/* ===========================================================================
   /listing-kit — additions only.
   The page is the live site's chassis (site.css) with content swapped, so this
   file holds just the few things that page doesn't already have: the rollover
   line under the hero CTA, the stubbed-checkout notice, and the third voice
   specimen in Agent 01.
   =========================================================================== */

/* The rollover promise. Above the fold on purpose: the sharpest verified
   complaint in the research is a monthly fee tied to one listing that
   evaporates the moment it sells.

   Two flex items only, the accent square and one text span. An inline <b>
   left loose in here becomes a third flex item and the sentence splits into
   accidental columns, so the markup wraps its words in .lk-note__t. */
.lk-note {
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 11.5px; letter-spacing: 0.06em; line-height: 1.7;
  color: var(--on-ink-faint); margin: 26px 0 0; max-width: 46em;
}
.lk-note__t { min-width: 0; }
.lk-note b { color: var(--on-ink); font-weight: 500; }

/* Light sections need the ink-side colours instead. */
section:not(.dark) .lk-note { color: var(--faint); }
section:not(.dark) .lk-note b { color: var(--ink); }

/* The door is a centred composition in site.css (.door__frame is text-align:
   center, the title and sub are margin-auto). Stacking the button, the stub
   and the reassurance line here has to keep that axis — a centred headline
   over a left-aligned button is the one thing this section cannot do. */
.door__cta { display: flex; flex-direction: column; align-items: center; gap: 0; margin-top: 40px; }
.door__note { margin-top: 22px; justify-content: center; }

/* Checkout is deliberately stubbed: no Stripe product exists, and creating one
   is Peter's call. The notice replaces the silence a dead button would leave. */
.lk-stub {
  margin: 18px 0 0; padding: 15px 18px; max-width: 34em;
  border: 1px solid var(--dark-line-3); background: rgba(255,255,255,0.05);
  font-size: 11.5px; letter-spacing: 0.06em; line-height: 1.7; color: var(--on-ink-sub);
}
.lk-stub a { color: var(--accent); }
.lk-stub[hidden] { display: none; }

section:not(.dark) .lk-stub {
  border-color: var(--hair-strong); background: var(--wash); color: var(--ink-2);
}

/* .plan__tag is drawn for a two-word badge. Keep this page's tag near that
   length: a sentence in there renders as a wide flat accent bar directly above
   the flat accent CTA, which puts two accent fills in one card and breaks the
   brief's rule that the accent stays rare. No override needed while the words
   stay short. */

/* The brokerage card has no number. At the 32px the numeric tiers use, "Let's
   talk" becomes the loudest thing in the row and out-shouts the price it is
   deliberately withholding. Smaller keeps the three cards on one baseline. */
.plan__price--talk { font-size: 25px; font-style: italic; }

/* ---------------------------------------------------------------------------
   Agent 01 — three voice specimens instead of two.

   The claim is "written in a model of your voice", and one rewrite can only
   prove taste. Two named agents writing the same house in visibly different
   ways is what proves the model. So this page runs A / B / C where the site
   root still runs A / B.

   site.css draws .spec__tabs as a nowrap flex row at width:fit-content, which
   holds two labels and overflows the column with three between 700 and 1264px
   (the rail is still taking 280px up there). A three-up grid removes the guess:
   equal columns that always fit, stacking to full-width rows on phones where
   they double as bigger tap targets.
   --------------------------------------------------------------------------- */
.spec__tabs {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  width: 100%; max-width: 560px;
}
.spec__tab { text-align: center; }

/* Stacked, the divider has to move from the left edge to the top edge or the
   rows sit in one unbroken block. */
@media (max-width: 760px) {
  .spec__tabs { grid-template-columns: 1fr; max-width: none; }
  .spec__tab { text-align: left; }
  .spec__tab + .spec__tab { border-left: 0; border-top: 1px solid var(--hair); }
}

/* B and C carry a caption, a mono spec line and the read underneath, so the
   panel is taller here than the two-specimen version site.css was sized for.
   Holding a floor keeps the box from jumping as you toggle. */
.spec__panel { min-height: 300px; }

/* The specs line at the foot of a caption. Set in mono so "specs last" is
   legible as a shape before anyone reads a word of it — which is the whole
   job of this element, since the visitor is skimming. */
.spec__specs {
  display: block; margin-top: 16px;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.1em;
  color: var(--ink-2);
}

/* What we read off that agent, named so every claim can be checked against the
   caption directly above it. Same treatment as .audit-card__rec in SEC 02. */
.spec__tell {
  font-size: 10px; letter-spacing: 0.12em; line-height: 1.8;
  color: var(--faint); margin: 24px 0 0; padding-top: 12px;
  border-top: 1px solid var(--hair); max-width: 560px;
}
.spec__tell-off { color: var(--ink); }

.spec__hint { line-height: 1.9; }

@media (max-width: 700px) {
  .lk-note { font-size: 11px; margin-top: 22px; }
}

/* ===========================================================================
   SEC 03 — the clickable how-it-works.

   Scope note: this stylesheet is linked only from /listing-kit/index.html, so
   every selector below is already page-scoped. site.css is untouched and the
   home page keeps its .beat / .wf rendering exactly as it was.

   Layout. Buttons and panels sit in flat source order in one grid. Desktop
   places the three buttons in column 1 and drops all three panels into the
   same cell in column 2, where they overlap and only one is visible. Below
   981px the placement is dropped and source order does the rest — each panel
   lands directly under its own button, which is the accordion, with no
   duplicated markup and no JS moving nodes around.
   =========================================================================== */

.hiw {
  position: relative;
  margin-top: -40px; /* .h2 ships 88px of bottom margin; this block wants less */
}

/* Everything that hides a panel is gated behind .hiw--armed, which JS adds on
   init. With no JS the block degrades to one flowing column with all three
   steps and all three screens open — degraded, but whole. Same contract the
   .wf-armed choreography two sections down already runs on. */
@media (min-width: 981px) {
  .hiw--armed {
    display: grid;
    grid-template-columns: minmax(300px, 400px) minmax(0, 1fr);
    column-gap: 48px;
    align-items: start;
  }
  .hiw--armed .hiw__step[data-step="1"] { grid-area: 1 / 1; }
  .hiw--armed .hiw__step[data-step="2"] { grid-area: 2 / 1; }
  .hiw--armed .hiw__step[data-step="3"] { grid-area: 3 / 1; }
  /* Top-aligned, not stretched and not sticky. The whole block is ~800px in a
     900px viewport, so a
     sticky stage would barely travel and would leave a short screen floating
     over an empty column on arrival. Top-aligned, the screen and the ruled
     steps share a top edge and the three panels sit within ~150px of each
     other in height, so switching step changes the air below the screen and
     never the layout. Panels are deliberately NOT stretched: a bordered box
     with 200px of nothing in it reads as broken, where the same 200px of open
     canvas reads as the page breathing. */
  .hiw--armed .hiw__panel { grid-area: 1 / 2 / 4 / 3; align-self: start; }
}

/* ---- the rail and its bead -------------------------------------------------
   One 40px accent segment that travels to sit beside the active numeral. It is
   the only thing in the section that moves stage to stage, it is a transform
   on a 1px rule, and it is a diagram rather than chrome — the same vocabulary
   as .wf__spine two sections down, so the two arguments rhyme.
   Hidden below 981px, where the accordion's own expansion is the motion and
   measuring a moving target would be the whole bug surface. */
.hiw__rail {
  position: absolute; left: 0; top: 4px; bottom: 4px; width: 1px;
  background: var(--hair-strong);
}
.hiw__bead {
  position: absolute; left: 0; top: 0; width: 1px; height: 40px;
  background: var(--accent);
  transform: translateY(var(--bead, 0px));
  transition: transform 300ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ---- the step buttons ------------------------------------------------------
   Ruled blocks, not cards. Chrome holds still on purpose: 150ms on colour and
   border, nothing translates, nothing scales. The control surface must not
   wobble under the cursor — the motion budget is spent on the stage instead. */
.hiw__step {
  display: block; width: 100%; text-align: left;
  background: none; border: 0; border-top: 1px solid var(--hair-strong);
  padding: 26px 0 30px 28px; margin: 0; cursor: pointer;
  font-family: inherit; color: inherit;
  transition: border-color 150ms ease-out;
}
.hiw__step:last-of-type { border-bottom: 1px solid var(--hair-strong); }
.hiw__step.is-active { border-top-color: var(--ink); }
.hiw__step.is-active + .hiw__panel + .hiw__step { border-top-color: var(--ink); }
.hiw__step:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.hiw__no {
  display: block; font-size: 12px; letter-spacing: 0.2em;
  color: var(--faint); transition: color 150ms ease-out;
}
.hiw__step.is-active .hiw__no { color: var(--accent); }
.hiw__kicker {
  display: block; margin-top: 14px;
  font-size: 11px; letter-spacing: 0.22em; color: var(--ink-2);
}
.hiw__head {
  display: block; margin-top: 10px;
  font-size: 22px; font-weight: 600; line-height: 1.2; color: var(--ink);
}
.hiw__body {
  display: block; margin-top: 12px; max-width: 42em;
  font-size: 15.5px; line-height: 1.55; color: var(--ink-2);
  transition: color 150ms ease-out;
}
.hiw__step:not(.is-active) .hiw__body { color: var(--faint); }
.hiw__step:hover:not(.is-active) { border-top-color: var(--ink); }
.hiw__step:hover:not(.is-active) .hiw__no { color: var(--ink); }

/* ---- the field flip, which is the one owned gesture ------------------------
   Step 01 happens in the agent's own world, so its screen is on a light field.
   Steps 02 and 03 are ours, so the field is ink. It is the headline —
   "two of the three steps are ours" — made visible before a word is read, and
   it is the same argument the .wf block in SEC 04 makes in its own register.

   The changeover is a CUT, not a cross-fade: the outgoing panel clears in 90ms
   and the incoming one starts after it. Blending a paper panel through a dark
   one gives a muddy grey middle frame, and a cut reads as the lights going
   down, which is what the moment actually is. Each panel therefore carries its
   own field at every width; there is no shared backing plate to keep in sync. */
.hiw__field { display: none; }
.hiw__panel { border: 1px solid var(--dark-line); background: var(--ink); }
.hiw__panel--light { border-color: var(--hair-strong); background: var(--paper); }

/* ---- the stage -------------------------------------------------------------
   Where the motion budget goes. The panel does not slide in as a slab; its
   rows assemble, 220ms ease-out with a ~45ms stagger, so what you watch is the
   artifact building rather than a box arriving. Outgoing is a 90ms cut. */
.hiw__panel { position: relative; z-index: 1; min-width: 0; }

/* Desktop: all three panels stay in flow so the cell keeps the height of the
   tallest and nothing reflows when you switch. Inactive ones are hidden from
   the a11y tree by visibility, not by display. */
@media (min-width: 981px) {
  .hiw--armed .hiw__panel {
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity 90ms linear, visibility 0s linear 90ms;
  }
  .hiw--armed .hiw__panel.is-active {
    opacity: 1; visibility: visible; pointer-events: auto;
    transition: opacity 200ms ease-out 90ms, visibility 0s;
  }
}
/* Accordion: the closed panels genuinely leave the layout. */
@media (max-width: 980px) {
  .hiw--armed .hiw__panel { display: none; }
  .hiw--armed .hiw__panel.is-active { display: block; }
}

.hiw--armed .hiw__panel.is-active .scr__bar { animation: hiw-in 220ms cubic-bezier(0.2, 0.7, 0.2, 1) 90ms both; }
.hiw--armed .hiw__panel.is-active .scr__body > * { animation: hiw-in 220ms cubic-bezier(0.2, 0.7, 0.2, 1) var(--d, 135ms) both; }
.hiw--armed .hiw__panel.is-active .scr__body > *:nth-child(2) { --d: 180ms; }
.hiw--armed .hiw__panel.is-active .scr__body > *:nth-child(3) { --d: 225ms; }
.hiw--armed .hiw__panel.is-active .scr__body > *:nth-child(4) { --d: 270ms; }
.hiw--armed .hiw__panel.is-active .scr__foot { animation: hiw-in 220ms cubic-bezier(0.2, 0.7, 0.2, 1) 300ms both; }
@keyframes hiw-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* ---- the screen chassis, shared by all three panels ------------------------
   Every panel is a screen with a chrome bar, and the bar's address changes with
   the step: their tool, our intake, our delivery page. That progression is the
   thing that makes the stage read as product rather than illustration. */
.scr { display: flex; flex-direction: column; height: 100%; }
.scr__bar {
  display: flex; align-items: center; gap: 12px; flex: none;
  padding: 11px 14px; border-bottom: 1px solid var(--hair);
  font-size: 10.5px; letter-spacing: 0.08em; color: var(--faint);
  background: var(--wash);
}
.scr__key { border: 1px solid var(--hair-strong); padding: 2px 5px; font-size: 9.5px; letter-spacing: 0.1em; color: var(--ink-2); flex: none; }
.scr__dots { font-size: 7px; letter-spacing: 2px; color: var(--dark-line-3); flex: none; }
.scr__url { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-2); }
.scr__state { flex: none; font-size: 9.5px; letter-spacing: 0.14em; }
.scr__body { flex: 1 1 auto; padding: 22px; }
.scr__foot {
  flex: none; margin: 0; padding: 11px 14px; border-top: 1px solid var(--hair);
  font-size: 9.5px; letter-spacing: 0.13em; line-height: 1.7; color: var(--faint);
}

.scr--ink { color: var(--on-ink); }
.scr--ink .scr__bar { background: rgba(255,255,255,0.03); border-bottom-color: var(--dark-line-2); color: var(--on-ink-faint); }
.scr--ink .scr__url { color: var(--on-ink-sub); }
.scr--ink .scr__foot { border-top-color: var(--dark-line-2); color: var(--on-ink-faint); }

/* ---- 01 · the resolve ------------------------------------------------------
   The listing photo grows with the frame; the readout holds its rhythm and
   pushes the rights line to the foot. Every value in the readout is legible in
   ../assets/zillow-before.webp — address, 3/2, 1,480 sq ft, $675,000, the 1/8
   photo counter, MLS 5540182. Nothing here was invented, and nothing here may
   drift from that image or from the carousel in SEC 02. */
.resolve { display: flex; flex-direction: column; }
.resolve__shot { flex: none; margin: 0 0 20px; border: 1px solid var(--hair-strong); background: var(--wash); overflow: hidden; }
/* The source is a full Zillow card; this window shows the photo band and the
   "For Sale" chip, not the sky above it. If the asset is ever re-cropped,
   re-check object-position rather than trusting it. */
.resolve__shot img { display: block; width: 100%; height: 258px; object-fit: cover; object-position: 50% 20%; filter: saturate(0.78); }
.resolve__shot figcaption { font-size: 9.5px; letter-spacing: 0.15em; color: var(--faint); padding: 8px 10px; border-top: 1px solid var(--hair); }
.resolve__head {
  flex: none; display: flex; justify-content: space-between; gap: 16px;
  font-size: 9.5px; letter-spacing: 0.18em; color: var(--faint);
  padding-bottom: 10px; border-bottom: 1px solid var(--hair-strong);
}
.resolve__dl { margin: 0; font-size: 12px; letter-spacing: 0.04em; flex: 1 1 auto; display: flex; flex-direction: column; }
.resolve__dl > div { display: flex; gap: 14px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--hair); }
.resolve__dl > div:last-child { border-bottom: 0; }
.resolve__dl dt { flex: 0 0 104px; font-size: 9.5px; letter-spacing: 0.15em; color: var(--faint); }
.resolve__dl dd { margin: 0; min-width: 0; color: var(--ink); }
.resolve__rights {
  flex: none; display: flex; gap: 10px; align-items: center; margin: 0;
  padding-top: 16px; border-top: 1px solid var(--hair-strong);
  font-size: 13.5px; line-height: 1.5; color: var(--ink-2);
}
.resolve__tick {
  flex: none; width: 16px; height: 16px; margin-top: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink); background: var(--ink); color: var(--paper); font-size: 10px;
}

/* ---- 02 · confirm the read -------------------------------------------------
   The controls are a picture of controls, so they are aria-hidden and given no
   hover state. A non-functional thing that invites a click is a dark pattern,
   and the .scr__foot names the panel as a mock-up. */
.read { display: flex; flex-direction: column; }
.read__head {
  flex: none; display: flex; justify-content: space-between; gap: 16px;
  font-size: 9.5px; letter-spacing: 0.18em; color: var(--on-ink-faint);
  padding-bottom: 10px; border-bottom: 1px solid var(--dark-line-2);
}
.read__list { list-style: none; margin: 0; padding: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.read__list li {
  display: grid; grid-template-columns: 108px minmax(0, 1fr) auto;
  gap: 16px; align-items: center;
  padding: 19px 0; border-bottom: 1px solid var(--dark-line);
}
.read__list li:last-child { border-bottom: 0; }
.read__k { font-size: 9.5px; letter-spacing: 0.15em; color: var(--on-ink-faint); }
.read__v { font-size: 15.5px; line-height: 1.45; color: var(--on-ink); }
.read__ctl { font-size: 9.5px; letter-spacing: 0.14em; color: var(--on-ink-faint); border: 1px solid var(--dark-line-3); padding: 5px 9px; white-space: nowrap; }

/* ---- 03 · the delivery page ------------------------------------------------
   Counted, per category, and the counts add to the total: 2 + 5 + 3 = 10, taken
   straight from LISTING-KIT-PRD §4's output list. If the kit changes, this
   number changes here and everywhere else on the same day. */
.ship { display: flex; flex-direction: column; }
.ship__head { flex: none; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 10px 20px; }
.ship__addr { margin: 0; font-size: 10px; letter-spacing: 0.18em; color: var(--on-ink-faint); }
.ship__title { margin: 0; font-family: var(--serif); font-style: italic; font-size: 26px; line-height: 1.1; color: var(--on-ink); }
.ship__count {
  flex: none; margin: 18px 0 0; padding: 10px 12px;
  border: 1px solid var(--dark-line-3); background: rgba(255,255,255,0.03);
  font-size: 10px; letter-spacing: 0.16em; color: var(--on-ink);
}
.ship__list { list-style: none; margin: 6px 0 0; padding: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.ship__list li {
  display: grid; grid-template-columns: 92px 74px minmax(0, 1fr) auto;
  gap: 16px; align-items: center;
  padding: 18px 0; border-bottom: 1px solid var(--dark-line);
}
.ship__list img { width: 92px; height: 62px; object-fit: cover; border: 1px solid var(--dark-line-2); display: block; }
.ship__slug {
  width: 92px; height: 62px; overflow: hidden; position: relative;
  border: 1px solid var(--dark-line-2); background: rgba(255,255,255,0.02);
  padding: 6px 7px 0; font-size: 6.5px; line-height: 1.5; color: var(--on-ink-sub);
}
.ship__slug::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 24px;
  background: linear-gradient(to top, var(--ink), rgba(20, 21, 26, 0));
}
.ship__k { font-size: 9.5px; letter-spacing: 0.16em; color: var(--on-ink-faint); }
.ship__v { font-size: 14px; line-height: 1.4; color: var(--on-ink); }
.ship__n { font-size: 13px; color: var(--on-ink-sub); }
.ship__foot { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; margin-top: 18px; }
.ship__btn { border: 1px solid var(--on-ink-faint); color: var(--on-ink); padding: 10px 16px; font-size: 10.5px; letter-spacing: 0.16em; }
.ship__legal { flex: 1 1 220px; font-size: 9.5px; letter-spacing: 0.12em; line-height: 1.6; color: var(--on-ink-faint); }

.hiw__legal {
  margin: 26px 0 0; font-size: 9.5px; letter-spacing: 0.14em;
  line-height: 1.7; color: var(--faint);
}

/* ---- the accordion (<= 980px) ---------------------------------------------
   Source order already interleaves button and panel, so the only work here is
   dropping the grid placement and giving each panel its own field. */
@media (max-width: 980px) {
  .hiw { margin-top: -24px; }
  .hiw__rail { display: none; }
  .hiw__step { padding-left: 0; padding-bottom: 22px; border-left: 2px solid transparent; }
  .hiw__step.is-active { padding-left: 16px; border-left-color: var(--accent); }
  .hiw__panel { margin: 0 0 30px; }
  .hiw__step[data-step="3"] + .hiw__panel { margin-bottom: 0; }
  .hiw__step:last-of-type { border-bottom: 1px solid var(--hair-strong); }
  .resolve { grid-template-columns: minmax(0, 1fr); }
  .resolve__shot img { height: 190px; }
  .scr__body { padding: 18px; }
  .read__list li { grid-template-columns: minmax(0, 1fr) auto; }
  .read__k { grid-column: 1 / -1; }
  .ship__list li { grid-template-columns: 58px minmax(0, 1fr) auto; gap: 12px; }
  .ship__k { grid-column: 2; font-size: 9px; }
  .ship__v { grid-column: 2; }
  .ship__list img { width: 58px; height: 44px; grid-row: span 2; }
  .ship__slug { width: 58px; height: 44px; grid-row: span 2; font-size: 5px; padding: 4px 5px 0; }
  .ship__slug::after { height: 16px; }
  .ship__n { grid-row: span 2; }
}

@media (max-width: 560px) {
  .hiw__head { font-size: 19px; }
  .hiw__body { font-size: 14.5px; }
  .scr__body { padding: 15px; }
  .ship__title { font-size: 21px; }
  .read__v { font-size: 13.5px; }
  .scr__url { font-size: 9.5px; }
  /* Two mono labels either side of a 300px screen wrap into two ragged
     columns. The right-hand one is an annotation, so it goes. */
  .resolve__head > span + span,
  .read__head > span + span { display: none; }
  .resolve__dl > div { flex-direction: column; align-items: flex-start; gap: 3px; }
  .resolve__dl dt { flex: none; }
  .resolve__shot img { height: 190px; }
}

/* Reduced motion: the bead jumps, the field cuts, the panel swaps. Every one of
   those states is reachable by click and none of them was ever carried by the
   animation, so the section reads identically without any of it.

   Specificity has to match the rules being cancelled — a media query adds none
   of its own, and .hiw--armed .hiw__panel.is-active .scr__bar out-weighs a bare
   .hiw__panel.is-active .scr__bar written in here. Checked in the browser under
   an emulated reduce, not read off the source. */
@media (prefers-reduced-motion: reduce) {
  .hiw__bead { transition: none; }
  .hiw__step { transition: none; }
  .hiw--armed .hiw__panel,
  .hiw--armed .hiw__panel.is-active { transition: none; }
  .hiw--armed .hiw__panel.is-active .scr__bar,
  .hiw--armed .hiw__panel.is-active .scr__body > *,
  .hiw--armed .hiw__panel.is-active .scr__foot { animation: none; }
}

/* ===========================================================================
   SEC 04 / block 03 — the workflow, restyled for this page only.

   Scope note, again, because it matters here: site/index.html carries the same
   .wf markup and reads only css/site.css. This stylesheet is linked from
   /listing-kit/ alone, so every override below is invisible to the home page.
   Nothing in site.css was touched.

   The complaint being answered: the transformation did not read. The grey
   daytime listing card and the twilight film sat on one dark ground, so a
   visitor scrolling past saw a wall of tiles rather than a before and an
   after. And the column heights were 527 / 564 / 1162, which left two-thirds
   of the composition empty for most of a screen of scrolling.
   =========================================================================== */

/* ---- 1. the field split ----------------------------------------------------
   WHAT YOU SEND lifts onto paper; everything else stays on ink. Reading it as
   emphasis would be backwards — the light side is the fluorescent world the
   agent already works in, and its contents are deliberately drab, while the
   ink side holds all the warmth because the light is in the pictures. Same
   argument the relight handle above makes, in a different register. */
.wf__pane {
  background: var(--paper); border: 1px solid var(--hair-strong);
  padding: 18px; color: var(--ink);
}
.wf__pane .wf__label { color: var(--faint); }
.wf__pane .wf__cap { color: var(--faint); margin-bottom: 0; }
.wf__pane .wf__url { border-color: var(--hair-strong); color: var(--ink-2); background: var(--wash); }
.wf__pane .wf__url-key { border-color: var(--hair-strong); color: var(--ink-2); }
.wf__pane .wf__listing { border-color: var(--hair-strong); }
.wf__pane .wf__phones img { border-color: var(--hair-strong); }

/* Desaturating the card made sense against ink. On paper it reads as a fault
   in the image rather than a fault in the listing, so it comes most of the way
   back — the point is that this is ordinary, not that it is broken. */
.wf__pane .wf__listing img { filter: saturate(0.85) contrast(0.97); }
.wf__pane .wf__phones img { filter: saturate(0.7) brightness(0.97); }

/* BEFORE / AFTER, in the same tag vocabulary as the relight handle above. */
.wf__label { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.wf__tag {
  flex: none; font-size: 9px; letter-spacing: 0.2em;
  border: 1px solid var(--hair-strong); color: var(--ink); padding: 3px 7px;
}
.wf__tag--after { border-color: var(--dark-line-3); color: var(--on-ink); }

/* ---- 2. the fit ------------------------------------------------------------
   The two short columns pin while the tall one packs, so the before is beside
   the after for the whole assembly instead of scrolling away from it. Sticky
   goes on the inner wrapper: the column stretches, the panel does not, which
   is what keeps the lit rectangle the height of its own contents rather than
   the height of the folder. */
.wf { align-items: stretch; }
.wf__stick { position: sticky; top: 88px; }
.wf__machine .wf__stick { padding-top: 2px; }

/* The folder ran 1,079px on its own. Shorter stills and a three-up grid at
   full width bring it inside the height of the pinned columns' travel. */
@media (min-width: 1081px) {
  .wf { grid-template-columns: 0.95fr 0.8fr 2.05fr; }
  /* Seven tiles and a full-width film is 3 + 6 = three clean rows of three.
     Anything else leaves a hole in the last row. */
  .wf__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Shorter stills, and the still fills whatever height its row ends up, or a
     card in a tall row shows a band of bare paper under the photo. */
  .wf__card > img { height: auto; min-height: 118px; flex: 1 1 auto; }
}

/* ---- 3. the playhead -------------------------------------------------------
   The spine already drew as you scrolled and the nodes already lit one at a
   time, and it still read as static, because nothing was ever in motion at the
   instant you looked. A marker riding the end of the fill fixes that: it is
   always somewhere, so the diagram is always running.

   The node at the playhead is the only one holding the accent. Passed nodes
   stay lit and go quiet. Selecting it takes no JS — ":is-on with no later
   sibling that is also is-on" is the leading edge by definition — and it
   spends less accent than the old rule, which lit every dot at once. */
.wf__spine-wrap { position: relative; }
.wf__play {
  position: absolute; left: 1px; top: 8px; z-index: 2;
  width: 9px; height: 9px; margin-top: -4px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 4px rgba(229, 72, 42, 0.22);
  opacity: 0;
  /* A percentage in translateY() resolves against the element's own height, so
     it has to ride on `top`, which resolves against the wrapper. Nine pixels
     of travel is not the intent. */
  top: calc(8px + var(--wf-p, 1) * (100% - 16px));
}
.workflow.wf-armed .wf__play { opacity: 1; }

.workflow.wf-armed .wf__node.is-on .wf__dot {
  background: var(--dark-line-3); border-color: var(--dark-line-3); box-shadow: none;
}
.workflow.wf-armed .wf__node.is-on:not(:has(~ .wf__node.is-on)) .wf__dot {
  background: var(--on-ink-faint); border-color: var(--on-ink-faint); box-shadow: none;
}
.workflow.wf-armed .wf__node--accent .wf__node-name { color: var(--on-ink); }
.workflow.wf-armed .wf__node.is-on:not(:has(~ .wf__node.is-on)) .wf__node-name { color: var(--accent); }

/* Below the three-column layout the pinning is pointless — the columns stack,
   so there is nothing to pin them beside. */
@media (max-width: 1080px) {
  .wf__stick { position: static; }
  .wf__play { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .wf__play { display: none; }
}

/* The kit-page tile is a browser mock with a fixed-height body, so in a row
   sized by a taller neighbour it showed a band of bare paper under the chrome.
   Let the mock own the whole card. */
.wf__card--site { justify-content: stretch; }
.wf__card--site .wf__browser { flex: 1 1 auto; display: flex; flex-direction: column; }
.wf__card--site .wf__browser-body { flex: 1 1 auto; }
.wf__card--site .wf__browser-body img { height: 100%; min-height: 118px; }

/* A latent overflow this page inherited, which the light pane's padding turned
   from invisible to obvious. .wf__url-text is a nowrap flex item, so the URL
   bar's min-content is ~323px, and an `auto`-minimum grid track refuses to go
   below it — the single-column layout at 375px has 274px to give. The document
   was already 9px wider than the viewport before this rebuild and would have
   been 38px after. minmax(0, 1fr) lets the track be the width it actually has
   and hands the problem to the ellipsis, which is what it is for. */
.wf__url-text { min-width: 0; }
@media (max-width: 1080px) { .wf { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 820px) { .wf { grid-template-columns: minmax(0, 1fr); } }

/* ===========================================================================
   THE TWO TABLES.

   Scope note, third time, because it is the rule this file exists under: this
   stylesheet is linked from /listing-kit/index.html alone. site.css is shared
   with the live home page and is not touched by anything below.

   Both tables are real <table> elements with real <th scope> — this is tabular
   data, a grid of divs would be a lie to a screen reader, and the semantics
   are what make the sticky row-header in the comparison worth having.
   =========================================================================== */

/* One accessible name per table, off-screen. Not display:none, which would
   take it out of the accessibility tree and defeat the point. */
.tbl-cap {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   SEC 01 — the comparison.

   Ruled, on canvas, no card. The only column with a field of its own is ours,
   and it earns that by being the column the reader is deciding about, not by
   being the one we are selling. Everything else is hairlines and type weight.
   --------------------------------------------------------------------------- */
.vs { margin-top: 88px; border-top: 2px solid var(--ink); padding-top: 34px; }
.vs__eyebrow { font-size: 11px; letter-spacing: 0.2em; color: var(--faint); margin: 0 0 18px; }
.vs__title {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(28px, 3.4vw, 40px); line-height: 1.08; letter-spacing: -0.015em;
  margin: 0 0 18px; max-width: 16em;
}
.vs__lede { font-size: 17px; line-height: 1.55; color: var(--ink-2); margin: 0 0 34px; max-width: 620px; }

/* The overflow container. The page body must never scroll sideways, so the
   table is given a floor it will not go below and this box takes the overflow.
   Focusable, because a scroll region a mouse can reach and a keyboard cannot
   is a bug that ships constantly. */
.vs__scroll { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.vs__scroll:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

.vs__table {
  width: 100%; min-width: 820px; border-collapse: collapse;
  font-size: 15px; line-height: 1.45;
}
.vs__table th, .vs__table td {
  text-align: left; vertical-align: top; padding: 16px 20px;
  border-top: 1px solid var(--hair); color: var(--ink-2); font-weight: 400;
}
/* The win mark is weight and value, never hue — the same treatment wherever it
   lands, which is the only way the concessions read as concessions. <strong>
   carries it into the accessibility tree; .vs__legend says it in words. */
.vs__table strong { font-weight: 600; color: var(--ink); }

/* Column heads. The corner cell is a <td> on purpose: an empty <th> in the
   corner of a two-axis table claims a heading that is not there. */
.vs__table thead th {
  border-top: 0; border-bottom: 1px solid var(--ink);
  padding-top: 0; padding-bottom: 14px;
  font-size: 10px; letter-spacing: 0.18em; line-height: 1.6; color: var(--ink);
  vertical-align: bottom;
}
/* Row labels stay put while the columns travel. Solid canvas behind them, or
   the cells they scroll over show through.

   The corner cell has to pin with them. Left loose it scrolls away, the next
   column head slides into the space the sticky labels occupy, and every header
   ends up one column out of register with the body it names — which is worse
   than no sticky column at all. */
.vs__table tbody th[scope="row"],
.vs__table thead .vs__corner {
  position: sticky; left: 0;
  width: 210px; padding-left: 0;
  background: var(--canvas);
  border-right: 1px solid var(--hair-strong);
}
.vs__table tbody th[scope="row"] { z-index: 1; color: var(--ink); font-weight: 500; }
.vs__table thead .vs__corner {
  z-index: 2; padding: 0;
  border-top: 0; border-bottom: 1px solid var(--ink);
}

/* Ours: a lit column on paper with its own edges. No accent, no tick glyphs,
   no green — the head band is ink, which is a token, not a highlight. */
.vs__table thead th.vs__ours {
  background: var(--ink); color: var(--on-ink);
  padding: 14px 20px; border-bottom-color: var(--ink);
}
.vs__table td.vs__ours {
  background: var(--paper); color: var(--ink-2);
  border-left: 1px solid var(--hair-strong); border-right: 1px solid var(--hair-strong);
}
.vs__table tbody tr:last-child td.vs__ours { border-bottom: 1px solid var(--hair-strong); }

.vs__hint { display: none; font-size: 10px; letter-spacing: 0.18em; color: var(--faint); margin: 12px 0 0; }
.vs__legend {
  font-size: 10px; letter-spacing: 0.14em; line-height: 1.8; color: var(--faint);
  margin: 20px 0 0; padding-top: 14px; border-top: 1px solid var(--hair); max-width: 60em;
}

/* 820px of table + 64px of shell padding + 80px of frame padding = it starts
   overflowing at 964px. The hint appears one pixel before that and not before,
   so nobody is told to drag a table that fits. */
@media (max-width: 963px) { .vs__hint { display: block; } }

@media (max-width: 700px) {
  .vs { margin-top: 64px; }
  .vs__table { min-width: 700px; font-size: 14px; }
  .vs__table th, .vs__table td { padding: 13px 14px; }
  .vs__table tbody th[scope="row"],
  .vs__table thead .vs__corner { width: 132px; }
  .vs__table tbody th[scope="row"] { font-size: 13px; }
  .vs__table thead th { font-size: 9px; letter-spacing: 0.14em; }
  .vs__table thead th.vs__ours { padding: 12px 14px; }
}

/* ---------------------------------------------------------------------------
   SEC 05 — what a kit includes.

   Asymmetric split, hairline between, same device the two problem columns in
   SEC 01 already use. Three columns fit at every width down to 560px, where
   the table restacks into rows instead of scrolling — a 3-column table is not
   wide enough to earn a scroller, and stacking keeps the KITS value beside its
   own row rather than off-screen.
   --------------------------------------------------------------------------- */
/* Stretched, not top-aligned: the intro runs about 400px shorter than the
   table, and a divider that stops in mid-air over 600px of empty column reads
   as unfinished where a full-height one reads as a spread. */
.buys {
  display: grid; grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
  gap: 0 56px; align-items: stretch;
  border-top: 2px solid var(--ink); padding-top: 34px; margin-bottom: 52px;
}
.buys__intro { border-right: 1px solid var(--hair); padding-right: 56px; }
.buys__eyebrow { font-size: 10.5px; letter-spacing: 0.2em; color: var(--faint); margin: 0 0 18px; line-height: 1.7; }
.buys__title {
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(28px, 3.2vw, 38px); line-height: 1.06; letter-spacing: -0.015em;
  margin: 0 0 18px;
}
.buys__lede { font-size: 16px; line-height: 1.6; color: var(--ink-2); margin: 0; }

.buys__panel { min-width: 0; }

/* ---------------------------------------------------------------------------
   The kit manifest. Three counted groups across the wide column, then the four
   things a kit carries that are not files.

   The count sits in the heading rather than beside each line because the eye
   reads 2 · 5 · 3 across the row before it reads a word, and that sum is the
   claim. Groups are equal columns so the numbers land on one baseline; they
   stack in source order below 700px, where a three-up of two-item lists is
   narrower than its own words.
   No accent: SEC 05 already spends it on the featured plan's tag and CTA.
   --------------------------------------------------------------------------- */
.kitman {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 32px; margin-bottom: 26px;
}
.kitman__grp + .kitman__grp { border-left: 1px solid var(--hair); padding-left: 32px; }
.kitman__h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: 10.5px; letter-spacing: 0.2em; color: var(--ink-2);
  margin: 0 0 12px; padding-bottom: 10px; border-bottom: 1px solid var(--hair-strong);
}
.kitman__n { font-family: var(--serif); font-size: 25px; letter-spacing: 0; color: var(--ink); line-height: 1; }
.kitman__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.kitman__list li { font-size: 14.5px; line-height: 1.45; color: var(--ink-2); }

/* The non-file promises. Mono and ruled so they read as terms, not as more
   deliverables — a person's approval is not a file and should not look like one. */
.kitman__also {
  list-style: none; margin: 0 0 30px; padding: 16px 0 0;
  border-top: 1px solid var(--hair-strong);
  display: grid; gap: 9px;
  font-size: 11px; letter-spacing: 0.08em; line-height: 1.6; color: var(--ink-2);
  text-transform: uppercase;
}
.kitman__also li { padding-left: 18px; position: relative; }
.kitman__also li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 7px; height: 1px; background: var(--ink-2);
}

@media (max-width: 700px) {
  .kitman { grid-template-columns: 1fr; gap: 22px; }
  .kitman__grp + .kitman__grp { border-left: 0; padding-left: 0; }
}
/* Fixed layout, because auto layout treats the gauge column's width as a
   suggestion and hands it a third of the table — which puts the numeral and
   the word "Free" adrift in the middle of an empty column instead of on a
   right edge they share. */
.buys__table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.buys__table thead th:first-child { width: 32%; }
.buys__table thead th.buys__k { width: 110px; }
.buys__table th, .buys__table td {
  text-align: left; vertical-align: top; padding: 15px 20px 15px 0;
  border-top: 1px solid var(--hair); font-weight: 400;
}
.buys__table thead th {
  border-top: 0; border-bottom: 1px solid var(--ink); padding-top: 0; padding-bottom: 12px;
  font-size: 9.5px; letter-spacing: 0.18em; color: var(--faint);
}
.buys__table tbody th[scope="row"] {
  width: 34%; font-size: 15.5px; line-height: 1.4; color: var(--ink); font-weight: 500;
}
.buys__table tbody td { font-size: 14.5px; line-height: 1.55; color: var(--ink-2); }

/* The gauge. A left hairline turns the last column into an instrument face
   rather than a third column of prose, and every value in it is right-aligned
   so the shape of the column reads before any of it does. */
/* Two classes, because `.buys__table td` is one class plus a type selector and
   would otherwise win the text-align. */
.buys__table .buys__k {
  padding-right: 0; padding-left: 20px;
  border-left: 1px solid var(--hair); text-align: right; white-space: nowrap;
}
.buys__table thead th.buys__k { border-left-color: transparent; }

/* One row carries a number, and it is the only thing in the block set at price
   scale. The band under it is --ghost against --canvas: barely there on
   purpose, because the numeral is doing the work and a filled row would read
   as the recommended option in a section full of plan cards. */
.buys__row--spend > * { background: var(--ghost); }
.buys__num { font-family: var(--serif); font-size: 34px; line-height: 0.9; color: var(--ink); display: inline-block; }
.buys__zero { font-size: 15px; letter-spacing: 0.06em; color: var(--faint); }
.buys__free { font-size: 12px; letter-spacing: 0.14em; color: var(--ink); }

.buys__foot {
  font-size: 15px; line-height: 1.6; color: var(--ink-2);
  margin: 22px 0 0; padding-top: 18px; border-top: 1px solid var(--hair-strong);
}
.buys__foot b { color: var(--ink); font-weight: 600; }
.buys__foot a {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.16em;
  color: var(--ink); text-decoration: none;
  border-bottom: 1px solid var(--hair-strong); padding-bottom: 2px;
  white-space: nowrap; margin-left: 4px;
}
.buys__foot a:hover { border-bottom-color: var(--ink); }
.buys__foot a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

@media (max-width: 980px) {
  .buys { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .buys__intro { border-right: 0; padding-right: 0; padding-bottom: 30px; border-bottom: 1px solid var(--hair); margin-bottom: 30px; }
  .buys__lede { max-width: 620px; }
}

/* Restacked: the head row goes, each row becomes a block, and the KITS value
   moves to the top-right of its own row where it stays next to the thing it
   is counting. */
@media (max-width: 560px) {
  .buys { margin-bottom: 40px; }
  .buys__table, .buys__table tbody, .buys__table tr, .buys__table th, .buys__table td { display: block; }
  .buys__table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .buys__table tr { border-top: 1px solid var(--hair); padding: 16px 0; position: relative; }
  .buys__table tr:first-child { border-top: 1px solid var(--ink); }
  .buys__table th, .buys__table td { border-top: 0; padding: 0; }
  .buys__table tbody th[scope="row"] { width: auto; padding-right: 96px; font-size: 16px; }
  .buys__table tbody td:not(.buys__k) { margin-top: 8px; }
  /* Two classes again — `.buys__table .buys__k` set the gauge rule and would
     otherwise keep it. It stays, deliberately: pulled in beside the value it
     is the one thing separating a number from the label it belongs to now
     that the column is gone. */
  .buys__table .buys__k {
    position: absolute; top: 14px; right: 0; width: auto;
    padding-left: 14px; height: 34px; display: flex;
    align-items: flex-start; justify-content: flex-end;
  }
  .buys__row--spend > * { background: none; }
  /* `.buys__table tr` is a class plus a type selector, so the row's own
     padding has to be written at matching weight or the negative margin
     travels without the padding that cancels it and the band eats its text. */
  .buys__table tr.buys__row--spend {
    background: var(--ghost);
    padding: 16px 14px; margin: 0 -14px;
  }
  .buys__table .buys__row--spend .buys__k { right: 14px; }
  .buys__num { font-size: 30px; }
}

@media (prefers-reduced-motion: reduce) {
  .vs__scroll { scroll-behavior: auto; }
}
