/*
Theme Name: ListHandled (child of optsus-base)
Template: optsus-base
Description: OptSus child theme for ListHandled, the Greenville NC home-repair block service. Concept B "The List" design language: warm paper ground, navy structure, clay accent, Bricolage Grotesque display over Inter body. Light theme only, by decision 2026-09-01.
Version: 0.5.0
Requires at least: 6.5
Requires PHP: 7.4
Author: OptSus
Text Domain: listhandled-child
*/

/* -------------------------------------------------------------------
   Scope of this file
   -------------------------------------------------------------------
   theme.json owns tokens: palette, type scale, spacing, element styles.
   This file carries only what theme.json cannot express - the composite
   components of Concept B (notepad list, step cards, scope table, the
   reserved booking slot) and the small ornaments that separate the brand
   from a generic block theme.

   No colour or spacing literal appears below without a matching preset
   variable. If a value has no preset, it is a deliberate one-off and
   carries a comment saying why.
   ------------------------------------------------------------------- */

:root {
  --lh-container: 1120px;
  --lh-pad: clamp(60px, 7vw, 108px);
  /* Concept B's rule colour at 42% - a hairline that reads on both paper
     and card without earning its own palette slug. */
  --lh-hairline: rgba(222, 214, 201, 0.62);
}

/* --- brand lockup ------------------------------------------------- */

.lh-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  flex: 0 0 auto;
}

/* The mark is a background image on a sized span, not an <img>, so the URL is
   resolved RELATIVE TO THIS STYLESHEET. An absolute /wp-content/... path breaks
   at review.optsus.com/listhandled/ (subpath) and would break again when the
   site moves to its own apex domain. Observed 404ing both marks on 2026-09-01.
   Explicit dimensions keep the header from shifting while the image loads. */
.lh-brand__mark {
  display: block;
  flex: 0 0 auto;
  width: 36px;
  height: 34px;
  background: url("assets/img/mark.png") center / contain no-repeat;
}

.lh-brand span {
  font-family: var(--wp--preset--font-family--heading);
  font-weight: 600;
  font-size: 23px;
  letter-spacing: -0.02em;
  color: var(--wp--preset--color--navy);
  white-space: nowrap;
}

/* Footer lockup sits on navy, so it takes the reverse mark and paper type.
   Rule of record: design-system/LOGO_USAGE_2026-09-01.md */
.lh-brand--reverse span {
  color: var(--wp--preset--color--background);
}

.lh-brand--reverse .lh-brand__mark {
  width: 44px;
  height: 42px;
  background-image: url("assets/img/mark-reverse.png");
}

/* --- the notepad list --------------------------------------------- */

.lh-notepad {
  position: relative;
  background: var(--wp--preset--color--card);
  border: 1px solid var(--wp--preset--color--rule);
  border-radius: 20px;
  padding: 38px 36px 30px;
  box-shadow: 0 18px 40px rgba(28, 42, 58, 0.07);
}

.lh-notepad::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 8px;
  border-radius: 20px 20px 0 0;
  background: var(--wp--preset--color--navy);
}

.lh-notepad ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.lh-notepad li {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 13px 0;
  border-bottom: 1px solid var(--lh-hairline);
  font-size: var(--wp--preset--font-size--md);
}

.lh-notepad li:last-child {
  border-bottom: 0;
}

/* Checkbox. Ticked items are done, unticked are not - the partial state is
   deliberate and carries the three-hour stop without a sentence about it.
   See design-system/COPY_RULES_2026-09-01.md R4. */
.lh-chk {
  flex: 0 0 22px;
  height: 22px;
  border-radius: 6px;
  border: 2px solid var(--wp--preset--color--navy);
  margin-top: 1px;
}

.lh-chk--done {
  background: var(--wp--preset--color--accent);
  border-color: var(--wp--preset--color--accent);
  position: relative;
}

.lh-chk--done::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9.6 16.6 5 12l1.4-1.4 3.2 3.2 8-8L19 7.2z'/%3E%3C/svg%3E") center / 16px no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='white' d='M9.6 16.6 5 12l1.4-1.4 3.2 3.2 8-8L19 7.2z'/%3E%3C/svg%3E") center / 16px no-repeat;
}

.lh-notepad__foot {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 2px solid var(--wp--preset--color--navy);
}

.lh-notepad__foot b {
  font-family: var(--wp--preset--font-family--heading);
  font-size: 34px;
  font-weight: 800;
  color: var(--wp--preset--color--navy);
  letter-spacing: -0.02em;
  /* Without this the price breaks mid-number at 390px and renders as "$30 / 0".
     Observed in the 2026-09-01 mobile fidelity capture. */
  white-space: nowrap;
}

/* Stack the price above its caption on narrow screens rather than letting the
   flex row squeeze both. */
@media (max-width: 480px) {
  .lh-notepad__foot {
    flex-direction: column;
    gap: 4px;
  }
}

/* --- the booking slot --------------------------------------------- */

/* Height is reserved so the Cal.com iframe cannot shift the page when it loads.
   Measured, not guessed: the live embed reports 571px in the month view, and it
   grows downward when a date is picked and the slots panel opens. Growth below
   the fold causes no shift above it, so the reserve only needs to cover the
   initial view plus a margin. 720px left ~150px of dead card. */
.lh-booking {
  min-height: 620px;
  border-radius: 20px;
  overflow: hidden;
  background: var(--wp--preset--color--card);
  border: 1px solid var(--wp--preset--color--rule);
}

@media (max-width: 900px) {
  .lh-booking {
    min-height: 560px;
  }
}

/* --- scope table --------------------------------------------------- */

.lh-scope {
  border: 2px solid var(--wp--preset--color--navy);
  border-radius: 18px;
  overflow: hidden;
  background: var(--wp--preset--color--card);
}

.lh-scope__head {
  background: var(--wp--preset--color--navy);
  color: var(--wp--preset--color--background);
  font-size: var(--wp--preset--font-size--sm);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Two columns on desktop, stacked on mobile. This lived as an inline
   grid-template-columns in the pattern markup, which cannot carry a media query
   and left the table in two cramped columns at 390px. */
/* Source order is heading, list, heading, list - so the stacked mobile layout
   reads correctly without any placement rules. Desktop then places the pairs
   into two columns explicitly. Doing it the other way round (both headings
   first) put "We do not" directly under "We do this" when stacked, with both
   lists below. Observed in the 2026-09-01 mobile capture. */
.lh-scope__grid {
  display: grid;
  grid-template-columns: 1fr;
}

.lh-scope__grid > .lh-scope__head {
  padding: 15px 24px;
  margin: 0;
}

.lh-scope__grid > ul {
  padding: 10px 24px 20px;
  margin: 0;
}

@media (min-width: 721px) {
  .lh-scope__grid {
    grid-template-columns: 1fr 1fr;
  }
  .lh-scope__grid > *:nth-child(1) { grid-column: 1; grid-row: 1; }
  .lh-scope__grid > *:nth-child(2) { grid-column: 1; grid-row: 2; }
  .lh-scope__grid > *:nth-child(3) { grid-column: 2; grid-row: 1; }
  .lh-scope__grid > *:nth-child(4) { grid-column: 2; grid-row: 2; }
}

.lh-scope li {
  list-style: none;
  padding: 11px 0;
  border-bottom: 1px solid var(--lh-hairline);
}

.lh-scope li:last-child {
  border-bottom: 0;
}

.lh-scope li::before {
  font-weight: 700;
  margin-right: 10px;
  color: var(--wp--preset--color--accent);
  content: "+";
}

.lh-scope .lh-scope__no li::before {
  content: "-";
  color: var(--wp--preset--color--muted);
}

/* --- eyebrow ornament ---------------------------------------------- */

.lh-eyebrow {
  font-size: var(--wp--preset--font-size--sm);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wp--preset--color--accent);
}
