/* CS3 · layout and its pieces (docs/cs3-spec.md; geometry docs/cs3-figma-values.md). Needs tokens.css, shell.css,
   thread.css, story.css, band.css. Desktop rows at 1288 and above (CS3's own breakpoint, §0); 901–1287 stacks with
   desktop values; the shell's 900 and 600 for tablet and mobile. The "if it fits" switches (§0) are container queries.
   Stage A: everything at rest, no motion. */

.cs3 {
  --case: var(--color-case-cs3);
  --off: 80px; /* content column from the page margin: thread column + gap, 80 / 80 / 60 */
  /* Drawing colors inside the work (§7.2), local to CS3 */
  --martch-400: #c1583a;
  --martch-grey: #8a857d;
  --martch-ink: #141210;
  --martch-gallery-white: #faf8f5;
  container-type: inline-size;
}
.cs3 :where(p, h1, h2, figure) { margin: 0; }
.cs3 .sec { color: var(--color-text-secondary); }
.cs3 .pri { color: var(--color-text-primary); }

/* ---------- Fit: a box drawn at its natural size (--w × --h), scaled to its column below that (§0, cs3.js) ---------- */
.fit {
  position: relative;
  flex: none;
  width: calc(var(--w) * var(--fit, 1) * 1px);
  height: calc(var(--h) * var(--fit, 1) * 1px);
  overflow: hidden;
}
.fit__in {
  width: calc(var(--w) * 1px);
  height: calc(var(--h) * 1px);
  transform: scale(var(--fit, 1));
  transform-origin: 0 0;
}
.fit__in > svg { display: block; }

/* ---------- Drawings (§7): inline SVG, strokes keep their page weight ---------- */
.dr { display: block; flex: none; overflow: visible; fill: none; }
.dr * { vector-effect: non-scaling-stroke; }
.dr .x16 { stroke: var(--color-line-exact); stroke-width: 1.6px; }
.dr .x14 { stroke: var(--color-line-exact); stroke-width: 1.4px; }
.dr .x12 { stroke: var(--color-line-exact); stroke-width: 1.2px; }
.dr .h12 { stroke: var(--color-line-hand); stroke-width: 1.2px; }
.dr .hd { stroke: var(--color-line-hand); stroke-width: 1.6px; stroke-dasharray: 2 4; }
.dr .g16 { stroke: var(--color-line-guide); stroke-width: 1.6px; }
.dr .c14 { stroke: var(--case); stroke-width: 1.4px; stroke-linecap: round; stroke-linejoin: round; }
.dr .w16 { stroke: var(--color-bg-page); stroke-width: 1.6px; stroke-linecap: round; stroke-linejoin: round; }
.dr .dash { stroke-dasharray: 6 6; }
.dr .rc { stroke-linecap: round; }
.dr .fw { fill: var(--color-bg-page); }
.dr .fi { fill: var(--color-bg-ink); }
.dr .fg { fill: var(--color-line-guide); }
.dr .r2 { clip-path: inset(0 round 2px); }
/* Labels: Site/Label, centred on their Figma box (start-aligned where marked .st) */
.dr text {
  fill: var(--color-text-secondary);
  font-family: "Martian Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  dominant-baseline: central;
  text-anchor: middle;
}
.dr text.p { fill: var(--color-text-primary); }
.dr text.st { text-anchor: start; }
/* The Living room is drawn at ×0.9333 (600 → 560): its labels are 11 px on the page (§0) */
.lr text { font-size: 11.786px; }

/* Pawn · Art lover (§7.2): the story.css pawn ×3, its stroke 4.2 (a filled silhouette), the palette and four dots
   (three dots: the martch/success dot removed, Eden 11 Nov 2026) */
.dr .pa { fill: var(--color-bg-ink); stroke: var(--color-line-exact); stroke-width: 4.2px; stroke-linecap: round; }
.dr .pa-pal { fill: var(--martch-gallery-white); }
.dr .pa-d1 { fill: var(--martch-400); }
.dr .pa-d2 { fill: var(--martch-grey); }
.dr .pa-d3 { fill: var(--martch-ink); }

/* ---------- Question bubble: Figma counts its 1.6 outline inside the padding (hero wish text 198.8 = 250 − 48 − 3.2,
   stop bubbles 99.2 tall for 64 of text), so the CS3 bubbles add it; story.css stays as it is ---------- */
.cs3 .bubble { padding: calc(var(--in-m-y) + var(--stroke-exact)) calc(var(--in-m-x) + var(--stroke-exact)); }
/* Tail corner bottom-right (story.css has bottom-left) */
.bubble--br { border-radius: var(--radius-bubble) var(--radius-bubble) var(--radius-tail) var(--radius-bubble); }
.bubble--br::before {
  border-radius:
    calc(var(--radius-bubble) - var(--stroke-exact)) calc(var(--radius-bubble) - var(--stroke-exact))
    calc(var(--radius-tail) - var(--stroke-exact)) calc(var(--radius-bubble) - var(--stroke-exact));
}

/* ---------- The phone (§7.4): white, the screen fills it, a 6 / 5.14 ink outline inside, the notch ---------- */
.phone-fit { --w: 280; --h: 606; }
.phone {
  --pr: var(--radius-phone);
  --pb: 6px;
  position: relative;
  isolation: isolate;
  width: 280px;
  height: 606px;
  overflow: hidden;
  border-radius: var(--pr);
  background: var(--color-bg-page);
}
.phone picture { display: block; width: 100%; height: 100%; }
.phone img { display: block; width: 100%; height: 100%; object-fit: cover; }
.phone::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border: var(--pb) solid var(--color-bg-ink);
  border-radius: var(--pr);
  pointer-events: none;
}
.phone::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 8px;
  z-index: 2;
  width: 76px;
  height: 16px;
  margin-left: -38px;
  border-radius: var(--radius-m);
  background: var(--color-bg-ink);
}

/* ---------- Sections on the rail: thread column (the station) · content ---------- */
.ch1,
.stop,
.ending {
  position: relative;
  padding-left: calc(var(--in-page-x) + var(--off));
  padding-right: var(--in-page-x);
}
/* Station centred on --thread-x and on its label's centre (label top 99, line 17.6; §0) */
.st-pos {
  position: absolute;
  left: calc(var(--thread-x) - var(--st) / 2);
  top: calc(99px + 8.8px - var(--st) / 2);
}
/* The Sold station's Martch mark is a filled shape, no stroke (Eden, 11 Nov 2026) */
.station svg .st-mark { fill: var(--st-icon); stroke: none; }
/* The hero sweep ends 8 px into Chapter 1 (§4): the module lands 16 above this point */
.sec-start {
  position: absolute;
  left: var(--thread-x);
  top: 24px;
  width: 0;
  height: 0;
}

/* ---------- Hero (§3) · stacked by default (901–1287 with desktop values) ---------- */
.cs3-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-48);
  padding: var(--rh-section) var(--in-page-x) 101px; /* bottom 101: geometry exception (§3) */
  overflow-x: clip; /* the desktop floor line ends exactly at the page edge */
}
.hero-main {
  display: flex;
  flex-direction: column;
  gap: var(--rh-element);
  width: 100%;
}
/* A plain block (not flex), as on CS1 and CS2: the QA finds the headline's block and the lead below it (E1) */
.hero-text { max-width: var(--hero-col); }
.hero-tags { margin-bottom: 12px; }
.hero-lead {
  display: flex;
  flex-direction: column;
  gap: var(--rh-element);
  max-width: var(--hero-lead);
}
/* Four written lines on every size, never re-flowed */
.hero-title { white-space: nowrap; }
/* "the whole" and "picture." are two Figma nodes, 12 apart (8 on mobile), not a space; the space stays for reading */
.hero-gap { font-size: 0; }
/* "picture." carries the underline; the tracking given back as padding (shell spec §5). Its margin adds that
   tracking back to "the whole" as well, so the gap is Figma's */
.pic {
  --gap: 12px;
  position: relative;
  isolation: isolate;
  display: inline-block;
  margin-inline-start: calc(var(--gap) + 0.045em);
  padding-inline-end: 0.045em;
}
/* Mark · Underline: 2 beyond the word on each side, 2 below it, 8 tall (§3) */
.pic__line {
  position: absolute;
  z-index: -1;
  left: -2px;
  top: calc(100% + 2px);
  width: calc(100% + 4px);
  height: 8px;
  overflow: visible;
}

/* The hero room: a container, so the room picks its layout from the room it has (§0) */
.hero-room-row {
  container: hroom / inline-size;
  display: flex;
  justify-content: center;
  width: 100%;
}
/* Narrow (mobile, and tablet below 560): the wish bubble above a 290 close-up, lamp hidden */
.hero-room {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  width: min(290px, 100%);
}
.hero-room__wish {
  position: relative;
  z-index: 1;
  width: min(250px, 100%);
}
.hero-room__crop { --w: 290; --h: 325; }
.hero-room__crop svg { margin-left: -187px; }
.hero-room__crop .lr-lamp { display: none; }
.hero-room__floor { display: none; }

@media (min-width: 601px) {
  @container hroom (min-width: 560px) {
    .hero-room { display: block; width: 560px; }
    .hero-room__wish { position: absolute; left: 0; top: 46.8px; width: 250px; }
    .hero-room__crop { --w: 560; }
    .hero-room__crop svg { margin-left: 0; }
    .hero-room__crop .lr-lamp { display: inline; }
  }
}

/* ---------- Chapter 1 · The gap (§5) ---------- */
.ch1 {
  display: flex;
  flex-direction: column;
  gap: var(--space-48);
  padding-bottom: var(--space-96);
}
.ch1__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-40);
  padding-top: 99px;
}
.ch1__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
  max-width: 560px;
}
.ch1__title {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ch1__h > span { display: block; }
.ch1__h > span + span { margin-top: var(--space-4); }
.ch1-metric {
  display: flex;
  align-items: center;
  gap: var(--space-16);
}
.ch1-metric > .t-metric { flex: none; }
.ch1-metric__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.ch1__visual {
  container: doubts / inline-size;
  width: 100%;
}

/* The doubts scene · narrow: stacked bubbles (210, bubble 2 right-aligned), then the 286 close-up (§5) */
.doubts {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.doubts .bubble {
  position: relative;
  z-index: 1;
  width: min(210px, 100%);
}
.doubts__b2 { align-self: flex-end; }
.doubts__crop { --w: 286; --h: 325; margin-top: 18px; } /* Figma: 30 below bubble 3 */
.doubts__crop svg { margin-left: -166px; }

@media (min-width: 601px) {
  @container doubts (min-width: 600px) {
    .doubts { position: relative; display: block; width: 600px; height: 520px; }
    .doubts .bubble { position: absolute; width: 190px; }
    .doubts__b1 { left: 0; top: 120px; }
    .doubts__b2 { left: 247px; top: 20px; }
    .doubts__b3 { left: 410px; top: 120px; }
    .doubts__crop { --w: 560; position: absolute; left: 20px; top: 195px; margin: 0; }
    .doubts__crop svg { margin-left: 0; }
  }
}

/* ---------- Chapter 2 · the three stops (§6) · stacked by default (901–1287 with desktop values) ---------- */
.stop {
  display: flex;
  flex-direction: column;
  gap: var(--space-48);
  padding-bottom: var(--space-96);
}
.stop__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-40);
  padding-top: 99px;
}
.stop__asked,
.stop__call {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--rh-tight);
}
.stop__calltext {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
  align-self: stretch;
}
.stop__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}
.stop__title,
.stop__copy { max-width: 560px; }
.stop .bubble { width: 420px; }
.stop__illus {
  container: illus / inline-size;
  align-self: stretch;
}
.stop__phone {
  display: flex;
  justify-content: center;
}

/* Taste and Pay scenes: the Mobile variant (290) unless the column holds the Desktop one (480) above 600 (§0) */
.illus-d { display: none; }
.illus-m--taste { --w: 290; --h: 312; overflow: visible; } /* nothing overflows at rest; the Stage B ✓ badges sit 7 above */
.illus-m--pay { --w: 290; --h: 202; }
@media (min-width: 601px) {
  @container illus (min-width: 480px) {
    .illus-d { display: block; }
    .illus-m { display: none; }
  }
}
/* The Fit crop of the Living room: 290 at x −197 on mobile, 276 at x −176 above (appendix B4.3) */
.fitcrop { --w: 290; --h: 325; }
.fitcrop svg { margin-left: -197px; }
@media (min-width: 601px) {
  .fitcrop { --w: 276; }
  .fitcrop svg { margin-left: -176px; }
}

/* ---------- Ending · It’s a match (§8) · stacked by default ---------- */
.ending {
  --fw: 2.7px; /* the frame line around the painting (§0) */
  display: flex;
  flex-direction: column;
  gap: 120px; /* geometry exception (§8) */
  padding-top: 99px;
  padding-bottom: var(--rh-block);
}
.match {
  display: flex;
  flex-direction: column;
  gap: var(--space-32);
}
.match__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
  max-width: 560px;
}
.match__heading {
  display: flex;
  flex-direction: column;
  gap: var(--rh-tight);
}
.match__room {
  container: room / inline-size;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  width: min(720px, 100%);
}
/* CS3 · Room · State=Sold (§7.5): the photo, and the painting in its own window with its frame line outside it */
.room {
  position: relative;
  width: 100%;
  aspect-ratio: 980 / 671;
  overflow: hidden;
  border-radius: 0.5cqi; /* 3.6 / 3.33 / 1.45 (Figma scales it with the room) */
  background: var(--color-bg-surface);
}
.room picture { display: block; }
.room__photo {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The painting layer (Stage B moves it as one, §14.8): the black frame line, the window inside it at --fw */
.room__art {
  position: absolute;
  left: calc(43.764% - var(--fw));
  top: calc(29.476% - var(--fw));
  width: calc(16.553% + 2 * var(--fw));
  height: calc(25.335% + 2 * var(--fw));
  background: var(--color-bg-ink);
}
.room__win {
  position: absolute;
  inset: var(--fw);
  overflow: hidden;
  background: var(--color-bg-surface);
}
.room__win img {
  position: absolute;
  left: -8.22%;
  top: -5.23%;
  display: block;
  width: 116.44%;
  max-width: none;
  height: 111.11%;
}
.room-cap {
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.room-cap__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--case);
}

/* Beyond the buyer */
.beyond {
  display: flex;
  flex-direction: column;
  gap: var(--space-48);
}
.beyond__text {
  display: flex;
  flex-direction: column;
  gap: var(--rh-tight);
  max-width: 560px;
}
.beyond__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}
.beyond__pw {
  container: phones / inline-size;
  width: 100%;
}
/* Narrow: the two phones stacked, centred; a row where the column holds 600 above 600 (§0) */
.beyond__phones {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-48);
}
@media (min-width: 601px) {
  @container phones (min-width: 600px) {
    .beyond__phones { flex-direction: row; align-items: flex-start; gap: var(--space-40); }
  }
}
.bphone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--rh-tight);
  width: min(280px, 100%);
}
.bphone__label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}
.bphone__line {
  display: block;
  width: 55px;
  height: 6px;
  overflow: visible;
}
.bphone__line--wide { width: 68px; }
.bphone__cap {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  align-self: stretch;
}

/* How I worked */
.how {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}
.how__note {
  display: flex;
  flex-direction: column;
  gap: var(--rh-tight);
  max-width: 560px;
}
.how__detail { max-width: 560px; }

/* ---------- Desktop ≥ 1288: the side-by-side layouts (§10) ---------- */
@media (min-width: 1288px) {
  .cs3-hero {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
  .hero-main { flex: 0 1 680px; min-width: 0; }
  .hero-room-row { flex: none; width: 560px; }
  /* The floor continues from the room's right edge to the page edge, at the room's floor (§0) */
  .hero-room__floor {
    display: block;
    position: absolute;
    left: 100%;
    top: calc(336px * 560 / 600 - 0.8px);
    width: var(--in-page-x);
    height: 1.6px;
    background: var(--color-line-guide);
  }

  /* Chapter 1: header (480–560) · gap 120 → 48 · the scene (600) */
  .ch1 {
    flex-direction: row;
    align-items: flex-start;
    column-gap: clamp(48px, 100% - 1160px, 120px);
    padding-bottom: 61px;
  }
  .ch1__head { flex: 1 1 560px; min-width: 480px; max-width: 560px; }
  .ch1__visual { flex: none; width: 600px; padding-top: 79px; }

  /* The stop: text column 536 (480 + 56) · gap 24 · the phone column */
  .stop {
    display: grid;
    grid-template-columns: 536px minmax(0, 1fr);
    column-gap: var(--space-24);
    align-items: start;
    padding-bottom: 0;
  }
  .stop__text { padding: 99px 56px 61px 0; }
  .stop__title,
  .stop__copy { max-width: none; }
  .stop__phone { padding: 99px 0 61px; }

  /* Ending rows */
  .match { flex-direction: row; align-items: flex-start; gap: 80px; }
  .match__head { flex: none; width: 480px; max-width: none; }
  .match__room { flex: 1 1 0; width: auto; max-width: 720px; }
  .room-cap { align-self: flex-end; }

  .beyond {
    flex-direction: row;
    align-items: center;
    column-gap: clamp(48px, 100% - 1160px, 120px);
  }
  .beyond__text { flex: 1 1 560px; min-width: 480px; max-width: 560px; }
  .beyond__pw { flex: none; width: 600px; }
  .beyond__phones { justify-content: flex-end; }

  .how {
    flex-direction: row;
    align-items: flex-start;
    column-gap: clamp(48px, 100% - 1040px, 120px);
  }
  .how__note { flex: none; width: 560px; max-width: none; }
  .how__detail { flex: none; width: 480px; max-width: none; padding-top: 30px; }
}

/* 901–1287 (Eden, 11 Nov 2026, stop point 2): the room starts at the margin under the text, not centred, so the
   line's run down at x 776 passes beside it instead of through it */
@media (min-width: 901px) and (max-width: 1287px) {
  .hero-room-row { justify-content: flex-start; }
}

/* 1288–1423: the text column is the content minus the room and the gap; the headline shrinks in the Figma
   proportion so "the whole picture." fits (84 at 1424) */
@media (min-width: 1288px) and (max-width: 1423px) {
  .hero-title { font-size: min(84px, (100cqi - 688px - 12px) / 7.6); }
}

/* ---------- Tablet · 601–900 ---------- */
@media (max-width: 900px) {
  .cs3 .station { --st: 32px; --st-r: var(--radius-m); }
  .cs3-hero { padding-top: var(--space-64); padding-bottom: var(--space-96); }
  .stop .bubble { width: 380px; }
  .ending { --fw: 2.5px; gap: var(--space-96); }
}

/* ---------- Mobile · up to 600 ---------- */
@media (max-width: 600px) {
  .cs3 { --off: 60px; }
  .cs3-hero { gap: var(--space-32); padding-top: var(--space-48); padding-bottom: var(--space-40); }
  /* Headline to lead 24 on mobile (Figma 16; Eden, 11 Nov 2026, stop point 2), so the line's start keeps E1's 16 px
     from the lead at 320–600 */
  .hero-main { gap: var(--space-24); }
  .pic { --gap: 8px; }

  .ch1 { gap: var(--space-40); padding-bottom: 80px; }

  .stop { gap: var(--space-40); padding-bottom: 80px; }
  .stop__text { gap: var(--space-32); }
  .stop__asked .speaker { align-self: stretch; }
  .stop .speaker .bubble { flex: 1; width: auto; }
  .phone-fit { --w: 240; --h: 519.43; }
  .phone {
    --pr: 29.14px;
    --pb: 5.14px;
    width: 240px;
    height: 519.43px;
  }
  .phone::before { top: 7.7px; width: 73px; height: 15.4px; margin-left: -36.5px; }

  .ending { --fw: 1.6px; gap: 72px; }
  .match { gap: var(--space-24); }
  .beyond { gap: var(--space-40); }
  .bphone { width: min(240px, 100%); }
}

/* 320–389: the headline shrinks so "the whole picture." fits the column (34 at 390) */
@media (max-width: 389px) {
  .hero-title { font-size: min(34px, (100cqi - 64px - 8px) / 7.6); }
}

/* =====================================================================================================
   Stage B · motion (docs/cs3-spec.md §14). Every start state sits under html.cs3-motion, set before the first paint
   by js/cs3-early.js and kept in sync by cs3.js (reduced motion, also switched live). Without it: the Stage A page.
   The scenes are played by cs3.js (Web Animations, fill both); data-m on a scene: none (waiting, its lines not yet
   measured) → "play" → "done" (the rest, = Stage A). Only opacity, transform, clip-path and SVG presentation values
   move (plus filter on the ending photo and painting, §14.1).
   ===================================================================================================== */
.cs3 { --e: cubic-bezier(0.2, 0.7, 0.2, 1); }
.match__w { display: inline-block; } /* "It’s a" / "match.": the line break stays by width (§14.8) */

/* Pieces that exist only for the motion: hidden at rest */
.dr .m-glow { opacity: 0; }
.dr .ts-badge__disc { fill: var(--case); }
.dr .py-coin { fill: var(--case); }
/* Pops and moves turn from their own box (§14.2) */
.dr :is(.m-pop, .ts-badge, .py-lock, .py-coin) { transform-box: fill-box; transform-origin: center; }
.dr .hr-art { transform-box: view-box; transform-origin: 288px 66px; }
.dr .fc-art { transform-box: view-box; transform-origin: 342px 48px; }

/* ---------- Load (§14.2): the site rhythm ---------- */
@keyframes cs3-rise {
  from { transform: translateY(0.25em); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes cs3-draw {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
@keyframes cs3-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
.cs3-motion .cs3-hero:not([data-m="done"]) .hero-title { animation: cs3-rise 0.6s ease 0.2s both; }
.cs3-motion .cs3-hero:not([data-m="done"]) .pic__line { animation: cs3-draw 0.7s cubic-bezier(0.5, 0, 0.2, 1) 0.65s both; }
.cs3-motion .cs3-hero:not([data-m="done"]) .hero-lead { animation: cs3-fade 0.8s ease 1.45s both; }

/* ---------- Start states of the scenes (until data-m="done") ---------- */
/* Lines that draw: unseen until cs3.js has measured them (it then hides them with their dash) */
.cs3-motion :is(.cs3-hero, .stop__illus):not([data-m]) .m-draw { stroke-opacity: 0; }
.cs3-motion .cs3-hero:not([data-m="done"]) :is(.m-pop, .hr-art, .hero-room__wish) { opacity: 0; }
.cs3-motion .cs3-hero:not([data-m="done"]) .hero-room__floor { clip-path: inset(0 100% 0 0); }
.cs3-motion .stop__illus:not([data-m="done"]) :is(.ts-pick, .ts-chip, .ts-trait) { opacity: 0; }
.cs3-motion .stop__illus:not([data-m="done"]) :is(.fc-art, .fc-lab, .fc-chip) { opacity: 0; }
.cs3-motion .stop__illus:not([data-m="done"]) :is(.py-chip, .py-arrive) { opacity: 0; } /* the lock is there from the start */

/* Chapter 1 · the doubt bubbles: dashed outline and secondary text until they turn solid (§14.5).
   The solid outline is the bubble's own ink ring; a page-coloured cover hides it until then. */
.cs3-motion .doubts:not([data-m="done"]) .bubble { color: var(--color-text-secondary); }
.doubts__cover,
.doubts__dash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.doubts__cover { inset: -0.5px; border-radius: inherit; background: var(--color-bg-page); }
.doubts__dash { width: 100%; height: 100%; overflow: visible; }
.doubts__dash path {
  fill: none;
  stroke: var(--color-line-hand);
  stroke-width: 1.6px;
  stroke-dasharray: 6 6;
}
html:not(.cs3-motion) :is(.doubts__cover, .doubts__dash),
.doubts[data-m="done"] :is(.doubts__cover, .doubts__dash) { display: none; }

/* ---------- Text openings (§14.4, §14.7): once, when the line reaches the station ---------- */
.cs3-motion .ch1:not(.is-open) :is(.ch1__title > .t-label, .ch1__h > span, .ch1__intro > .t-sub, .ch1-metric),
.cs3-motion .stop:not(.is-open) :is(.stop__asked > .t-label, .speaker, .stop__call > .t-label, .stop__title, .stop__copy),
.cs3-motion .ending:not(.is-open) .match__heading > .t-label,
.cs3-motion .beyond__text:not(.is-open) :is(.beyond__text > .t-label, .beyond__intro > *) {
  opacity: 0;
  transform: translateY(12px);
}
.cs3-motion .ch1.is-open :is(.ch1__title > .t-label, .ch1__h > span, .ch1__intro > .t-sub, .ch1-metric),
.cs3-motion .stop.is-open :is(.stop__asked > .t-label, .speaker, .stop__call > .t-label, .stop__title, .stop__copy),
.cs3-motion .ending.is-open .match__heading > .t-label,
.cs3-motion .beyond__text.is-open :is(.beyond__text > .t-label, .beyond__intro > *) {
  transition: opacity 0.55s ease var(--od, 0s), transform 0.55s var(--e) var(--od, 0s);
}
.cs3-motion .ch1__h > span:first-child,
.cs3-motion .stop .speaker,
.cs3-motion .beyond__intro > h2 { --od: 0.08s; }
.cs3-motion .ch1__h > span + span,
.cs3-motion .stop :is(.stop__call > .t-label, .stop__title),
.cs3-motion .beyond__intro > p { --od: 0.16s; }
.cs3-motion .ch1__intro > .t-sub,
.cs3-motion .stop .stop__copy { --od: 0.24s; }
.cs3-motion .ch1-metric { --od: 0.32s; }

/* The stop's phone column rises with the text (≥ 1288) or when it enters the view (stacked) */
.cs3-motion .stop:not(.is-up) .stop__phone { opacity: 0; transform: translateY(18px); }
.cs3-motion .stop.is-up .stop__phone { transition: opacity 0.7s var(--e) var(--od, 0s), transform 0.7s var(--e) var(--od, 0s); }
@media (min-width: 1288px) {
  .cs3-motion .stop .stop__phone { --od: 0.16s; }
}
/* Beyond the buyer: the two phone columns (the second 0.18 s later in a row, set by cs3.js) */
.cs3-motion .bphone:not(.is-up) { opacity: 0; transform: translateY(30px); }
.cs3-motion .bphone.is-up { transition: opacity 0.8s var(--e) var(--od, 0s), transform 0.8s var(--e) var(--od, 0s); }

/* At once: a station already reached when the page builds, motion switched back on, the QA's drawAll */
.cs3-motion .is-instant,
.cs3-motion .is-instant *,
.cs3-motion [data-thread-static] :is(.ch1, .stop, .ending, .beyond__text, .bphone),
.cs3-motion [data-thread-static] :is(.ch1, .stop, .ending, .beyond__text) * { transition: none !important; }

/* ---------- The painting on the thread (§14.3): rides the tip; above the content, below the sticky nav ---------- */
[data-thread-root] > .cs3-ride {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  width: 52px;
  height: 70px;
  opacity: 0;
  pointer-events: none;
  transform-origin: 26px 4px;
}
/* It fades in over 0.4 s and hides at once, so it never shows over a station (Update 11 Nov 2026, Eden) */
[data-thread-root] > .cs3-ride.is-on { opacity: 1; transition: opacity 0.4s ease; }
[data-thread-root] > .cs3-ride svg { display: block; overflow: visible; fill: none; }
.cs3-ride svg * { vector-effect: non-scaling-stroke; }
.cs3-ride__wire { stroke: var(--color-line-exact); stroke-width: 1.2px; stroke-linecap: round; stroke-linejoin: round; }
.cs3-ride__frame { stroke: var(--color-bg-ink); stroke-width: 1.6px; }
.cs3-ride__nail { fill: var(--color-bg-ink); }
html:not(.cs3-motion) [data-thread-root] > .cs3-ride { display: none; }

/* ---------- The phones (§14.6): screen layers, tap rings and overlays, in the 280 × 606 screen ---------- */
.ph-fx {
  --k: 1;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  width: 280px;
  height: 606px;
  transform: scale(var(--k));
  transform-origin: 0 0;
  pointer-events: none;
}
@media (max-width: 600px) {
  .ph-fx { --k: calc(240 / 280); }
}
.ph-fx > * { position: absolute; }
.ph-fx__screen {
  left: 0;
  top: 0;
  display: block;
  width: 280px;
  height: 606px;
  max-width: none;
  object-fit: cover;
}
.ph-fx__ring { overflow: visible; }
.ph-fx__ring circle { fill: rgba(193, 88, 58, 0.12); stroke: var(--case); stroke-width: 1.6px; }
.ph-fx__ring--pulse circle { fill: none; }
.ph-fx__corners { overflow: visible; fill: none; }
.ph-fx__corners path { stroke: var(--color-bg-page); stroke-width: 1.6px; stroke-linecap: square; }
.ph-fx__pill {
  top: 115px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--color-bg-ink);
  color: var(--color-bg-page);
  font-family: "Funnel Sans", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 400;
  line-height: normal;
  white-space: nowrap;
}
.ph-fx__bar { left: 32px; top: 214.4px; width: 151.5px; height: 1.6px; background: var(--case); transform-origin: 0 50%; }
.ph-fx__cover { background: var(--color-bg-page); }
html:not(.cs3-motion) .ph-fx { display: none; }

/* ---------- Ending · It’s a match (§14.8) ---------- */
.room__sketch {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--color-bg-page);
  pointer-events: none;
}
.room__sketch * { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.room__sketch .sk-x { stroke: var(--color-line-exact); }
.room__sketch .sk-h { stroke: var(--color-line-hand); }
.room__sketch .sk-g { stroke: var(--color-line-guide); }
.room__sketch .sk-i { stroke: var(--color-bg-ink); }
html:not(.cs3-motion) .room__sketch,
.match[data-m="done"] .room__sketch { display: none; }
.cs3-motion .match:not([data-m="done"]) .room__photo { opacity: 0; }
.cs3-motion .match:not([data-m="done"]) .room__art { clip-path: inset(100% 0 0 0); }
.cs3-motion .match:not([data-m="done"]) :is(.match__w, .match__head > .t-sub, .room-cap) { opacity: 0; }
