/* ============================================================
   CASE STUDY SYSTEM
   Extracted from the DANA Wallet v3 redesign (dana-wallet-v3/wallet.css)
   so every case study shares one type scale, one rhythm and one set of
   components. DESIGN.md at the repo root holds the rules; this file is
   their implementation.

   Load order on a case-study page:
     nav.css  ->  case-study.css  ->  page.css (one-offs only)
              ->  footer.css  ->  page-transition.css
              ->  image-lightbox.css  ->  theme.css
   and body class="cs <page>-page".

   Colour is never declared here: every surface and ink reads theme.css
   (--bg, --bg-deep, --ink, --ink-muted, --ink-faint, --panel, --stroke)
   so the room light (day / night) keeps working. The only saturated
   colour on a case study belongs to the product, inside its screenshots.

   Everything here is visible with no JS and under reduced motion.
   Motion lives in case-study.js (rail, scrubbed video) and in each
   page's own signature, never in this file except the scrub layout.
   ============================================================ */

@font-face {
  font-family: "Tanker";
  src: url("assets/fonts/Tanker-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---- layout ---- */
  --cs-edge: min(1120px, 92vw);          /* the site's content width */
  --cs-rail: 158px;                      /* chapter rail column */
  --cs-rail-gap: 56px;
  --cs-measure: 33rem;                   /* ~71 characters of body copy */

  /* ---- rhythm ---- */
  --cs-chapter-gap: clamp(104px, 12vw, 176px);  /* above every chapter h2 */
  --cs-sub-gap: 96px;                           /* above a sub-head inside a chapter */
  --cs-block-gap: 56px;                         /* around a figure, ledger, grid */
  --cs-grid-gap: 20px;                          /* between frames in a row */
  --cs-climax-gap: clamp(150px, 16vw, 220px);   /* before the climax band */

  /* ---- type scale ---- */
  --cs-type-hero: clamp(56px, 5.4vw, 84px);
  --cs-type-h2: clamp(44px, 5.4vw, 76px);
  --cs-type-climax: clamp(60px, 8vw, 120px);
  --cs-type-metric: clamp(64px, 8.2vw, 120px);
  --cs-type-evidence: clamp(60px, 6.2vw, 88px);
  --cs-type-stage: 92px;
  --cs-type-pull: clamp(26px, 3vw, 38px);
  --cs-type-seq: clamp(48px, 4.6vw, 64px);
  --cs-type-metric-from: clamp(40px, 4.4vw, 64px);
  --cs-type-quote: clamp(20px, 2.1vw, 24px);
  --cs-type-sub: 24px;
  --cs-type-card: 22px;
  --cs-type-body: clamp(17px, 1.9vw, 18px);
  --cs-type-small: 16px;
  --cs-type-label: 15px;
  --cs-type-caption: 14px;

  /* ---- shape and depth ---- */
  --cs-radius: 22px;          /* every tonal container */
  --cs-radius-inner: 13px;    /* a screenshot inside a container */
  --cs-radius-control: 12px;  /* the CTA */
  --cs-surface: var(--panel);
  --cs-surface-deep: var(--bg-deep);
  --cs-shot-shadow: 0 1px 2px rgba(40, 30, 20, 0.16), 0 12px 18px -14px rgba(40, 30, 20, 0.4);
}

/* ---------- base ---------- */

.cs *, .cs *::before, .cs *::after { box-sizing: border-box; }
html:has(body.cs) { scroll-behavior: auto; }
/* a case study carries its own atmosphere; the site dot field is off */
html:has(body.cs)::before { display: none; }

body.cs {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.cs a { color: inherit; }
.cs img { max-width: 100%; }
.cs :focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------- display voice ----------
   Tanker carries claims and numbers only: the hero title, chapter
   heads, the climax head, evidence and outcome numbers, stage marks.
   Source text stays in normal case; the caps are CSS. */
.cs-display,
.cs-hero__title,
.cs-chapter > h2,
.cs-climax h2,
.cs-ledger__num,
.cs-stage__mark,
.cs-metric__value,
.cs-footnote__mark {
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.012em;
}

/* ============================================================
   HERO
   Owns the first viewport. The shipped product visual leads; the
   title, pitch, facts and one action sit beside it, never above it.
   The page supplies the visual inside .cs-hero__visual.
   ============================================================ */

.cs-hero {
  --cs-visual-h: clamp(460px, calc(100svh - 300px), 620px);
  position: relative;
  z-index: 1;
  width: var(--cs-edge);
  margin: 0 auto;
  min-height: calc(100svh - 112px);
  padding: 72px 0 40px;   /* clears the sticky nav and its blur */
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  grid-template-rows: 1fr auto auto 1fr;
  grid-template-areas:
    "visual ."
    "visual title"
    "visual copy"
    "visual .";
  column-gap: clamp(32px, 3.4vw, 52px);
  align-items: center;
}

.cs-hero__visual { grid-area: visual; margin: 0; min-height: var(--cs-visual-h); display: grid; align-items: center; }
.cs-hero__visual > figcaption,
.cs-hero__visual figcaption {
  margin-top: 18px;
  font-size: var(--cs-type-caption);
  line-height: 1.5;
  color: var(--ink-muted);
}

.cs-hero__title {
  grid-area: title;
  align-self: end;
  margin: 0 0 22px;
  font-size: var(--cs-type-hero);
  line-height: 0.86;
  color: var(--ink);
}
.cs-hero__title span { display: block; }   /* two lines, never three */

.cs-hero__copy { grid-area: copy; align-self: start; }
.cs-hero__pitch {
  margin: 0 0 18px;
  max-width: 25rem;
  font-size: 18px;
  line-height: 1.6;
  color: var(--ink-muted);
}

/* facts: category, year, platform; spaced by gap, never by glyphs */
.cs-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 22px;
  margin: 0 0 28px;
  font-size: var(--cs-type-label);
  font-weight: 600;
  color: var(--ink);
}

/* the one action */
.cs .cs-cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 15px 24px 15px 20px;
  border-radius: var(--cs-radius-control);
  background: var(--ink);
  color: var(--bg);
  font-size: 16px;
  font-weight: 700;
  text-decoration: none;
}
.cs-cta svg { width: 12px; height: 14px; fill: currentColor; }
.cs .cs-cta:hover { background: color-mix(in oklab, var(--ink) 84%, var(--bg)); }

/* ============================================================
   SHELL: sticky chapter rail + reading column
   ============================================================ */

.cs-shell {
  position: relative;
  z-index: 1;
  width: var(--cs-edge);
  margin: clamp(56px, 7vw, 104px) auto 0;
  display: grid;
  grid-template-columns: var(--cs-rail) minmax(0, 1fr);
  gap: var(--cs-rail-gap);
  align-items: start;
}
.cs-main { min-width: 0; }

/* sticks just under the nav's frosted veil (nav.css: header bottom 108px
   plus a 78px fade tail), so the rail never sits in the blur */
.cs-rail {
  position: sticky;
  top: 188px;
  padding: 2px 0 2px 20px;
}
.cs-rail__label {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-muted);
}
.cs-rail__list { list-style: none; margin: 0; padding: 0; }
.cs-rail__list a {
  display: block;
  padding: 7px 0;
  font-size: var(--cs-type-label);
  font-weight: 500;
  color: var(--ink-muted);
  text-decoration: none;
}
.cs-rail__list a:hover,
.cs-rail__list a.is-previewed { color: var(--ink); }
.cs-rail__list a[aria-current="true"] { color: var(--ink); font-weight: 700; }

/* progress: a rounded track whose fill is clipped, never scaled, so
   its caps stay round at every length. case-study.js sets --cs-progress. */
.cs-rail__track {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  border-radius: 3px;
  background: var(--stroke);
}
.cs-rail__fill {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  background: var(--ink);
  clip-path: inset(0 0 calc((1 - var(--cs-progress, 0)) * 100%) 0 round 3px);
}

/* cue scrubber (case-study.js adds .is-cued): the static track above is
   the no-JS fallback. One segment beside each chapter link, the current
   one in ink, and a handle riding the reading line with a ring of page
   ground to lift it off the dark segment. case-study.js sets the track's
   top and height to the list and writes positions straight from scroll,
   so nothing eases. */
.cs-rail.is-cued .cs-rail__track { display: none; }
.cs-cue {
  position: absolute;
  left: 0;
  width: 20px;
  cursor: pointer;
  touch-action: none;
}
.cs-rail.is-scrubbing .cs-cue { cursor: grabbing; }
.cs-cue__seg {
  position: absolute;
  left: 5px;
  width: 6px;
  border-radius: 2px;
  background: var(--stroke);
}
.cs-cue__seg.is-current { background: var(--ink); }
.cs-cue__handle {
  position: absolute;
  left: 0;
  top: -6px;
  width: 16px;
  height: 12px;
  border: 3px solid var(--bg);
  border-radius: 5px;
  background: var(--ink);
  pointer-events: none;
}
/* focus rings the handle, like a native slider thumb, so it never runs
   over the chapter numbers beside the track */
.cs-cue:focus-visible { outline: none; }
.cs-cue:focus-visible .cs-cue__handle { outline: 2px solid var(--ink); outline-offset: 2px; }
.cs-rail__num {
  display: inline-block;
  min-width: 1.75em;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}
.cs-rail__list a[aria-current="true"] .cs-rail__num,
.cs-rail__list a:hover .cs-rail__num,
.cs-rail__list a.is-previewed .cs-rail__num { color: var(--ink); }
.cs-rail__time {
  margin: 14px 0 0;
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

/* ============================================================
   CHAPTER
   One h2 per chapter, alone. Prose capped at the measure; figures
   and grids break out to the full column.
   ============================================================ */

.cs-chapter { padding-top: var(--cs-chapter-gap); }
.cs-chapter:first-child { padding-top: 0; }

.cs-chapter > h2 {
  margin: 0 0 36px;
  max-width: 12.5em;
  font-size: var(--cs-type-h2);
  line-height: 0.92;
  color: var(--ink);
}

.cs-chapter p,
.cs-chapter li {
  font-size: var(--cs-type-body);
  line-height: 1.75;
  color: var(--ink-muted);
}
.cs-chapter > p { max-width: var(--cs-measure); margin: 0 0 20px; }
.cs-chapter strong { color: var(--ink); }

.cs-subhead {
  margin: var(--cs-sub-gap) 0 14px;
  font-size: var(--cs-type-sub);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* the chapter's one sentence that matters most: type and space only,
   no card, no quote marks, no rule */
.cs-chapter > .cs-pull {
  max-width: 21em;
  margin: 56px 0 48px;
  font-size: var(--cs-type-pull);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* a stated takeaway at a step above body ("Opportunity:", a verdict) */
.cs-chapter > .cs-callout {
  margin: 28px 0;
  font-size: 20px;
  line-height: 1.6;
  color: var(--ink);
}

/* ============================================================
   FRAME: the one way a screenshot sits on the page
   ============================================================ */

.cs-frame {
  margin: 0;
  padding: 12px 12px 14px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
}
.cs-frame img,
.cs-frame video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--cs-radius-inner);
}
.cs-frame img[data-lightbox] { cursor: zoom-in; }
.cs-frame figcaption,
.cs-caption {
  margin-top: 12px;
  padding: 0 4px;
  font-size: var(--cs-type-caption);
  line-height: 1.5;
  color: var(--ink-muted);
}

/* a row of frames: equal heights, captions pinned to one baseline */
.cs-frames {
  display: grid;
  grid-template-columns: repeat(var(--cs-cols, 3), minmax(0, 1fr));
  gap: var(--cs-grid-gap);
  margin: var(--cs-block-gap) 0;
  align-items: stretch;
}
.cs-frames > .cs-frame { display: flex; flex-direction: column; }
.cs-frame__slot { flex: 1; display: flex; align-items: center; justify-content: center; }
/* a portrait screen inside a wider slot keeps its own width */
.cs-frame--screen img { width: auto; max-width: 100%; height: var(--cs-screen-h, 500px); margin: 0 auto; }

/* ============================================================
   EVIDENCE LEDGER: research sources at display size
   Rows, method beside count, so sources never read as the outcome
   tiles that belong to the climax.
   ============================================================ */

.cs-ledger { margin: 48px 0 64px; display: grid; gap: 14px; }
.cs-ledger__row {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1fr);
  gap: 32px;
  align-items: center;
  padding: 30px 34px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
}
.cs-ledger dt, .cs-ledger dd { margin: 0; }
.cs-ledger__num {
  display: block;
  font-size: var(--cs-type-evidence);
  line-height: 0.84;
  color: var(--ink);
}
.cs-ledger__unit {
  display: block;
  margin-top: 10px;
  font-size: var(--cs-type-label);
  font-weight: 600;
  color: var(--ink-muted);
}
.cs-ledger dd strong { display: block; margin-bottom: 6px; font-size: 17px; color: var(--ink); }
.cs-ledger dd span { display: block; font-size: var(--cs-type-small); line-height: 1.6; color: var(--ink-muted); }

/* ============================================================
   FINDINGS: a 2x2 of themes, each paired with its implication
   The implication sits on a deeper tonal stub joined to its theme.
   Subgrid keeps the stubs of a row level however long a theme runs.
   Rows: title, body, (optional) printed line, implication.
   ============================================================ */

.cs-findings {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
  margin: 40px 0 0;
}
.cs-finding {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 4;
  row-gap: 0;
}
.cs-finding > * { margin: 0; background: var(--cs-surface); }
.cs-finding h3 {
  padding: 26px 28px 0;
  border-radius: var(--cs-radius) var(--cs-radius) 0 0;
  font-size: var(--cs-type-card);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.cs-finding .cs-finding__body {
  padding: 12px 28px 14px;
  font-size: var(--cs-type-small);
  line-height: 1.65;
}
.cs-finding .cs-finding__line {
  padding: 0 28px 24px;
  font-size: var(--cs-type-label);
  font-weight: 700;
  line-height: 1.5;
  color: var(--ink);
}
.cs-finding__implication {
  padding: 22px 28px 26px;
  border-radius: 0 0 var(--cs-radius) var(--cs-radius);
  background: var(--cs-surface-deep) !important;
}
.cs-finding__implication strong {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}
.cs-finding__implication p {
  margin: 0;
  font-size: 16.5px;
  font-weight: 600;
  line-height: 1.55;
  color: var(--ink);
}

/* ============================================================
   COMPARE: versions or options side by side on one track
   Rows: mark, title, shot, description, worked, didn't.
   The current stage's mark is full ink; earlier marks are faint.
   ============================================================ */

.cs-compare {
  position: relative;
  list-style: none;
  margin: 96px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--cs-cols, 3), minmax(0, 1fr));
  column-gap: 28px;
}
.cs-compare::before {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  top: 40px;
  height: 4px;
  border-radius: 4px;
  background: var(--stroke);
}
.cs-stage {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 6;
  row-gap: 0;
  align-content: start;
}
.cs-stage > * { margin: 0; }
.cs-stage .cs-stage__mark {
  position: relative;
  justify-self: start;
  padding-right: 16px;
  background: var(--bg);      /* sits over the track */
  font-size: var(--cs-type-stage);
  line-height: 0.92;
  color: var(--ink-faint);
}
.cs-stage--now .cs-stage__mark { color: var(--ink); }
.cs-stage h3 {
  padding: 14px 0 18px;
  font-size: 21px;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.cs-stage__shot {
  align-self: stretch;
  padding: 14px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
}
.cs-stage__shot img {
  display: block;
  height: 440px;
  width: auto;
  max-width: 100%;
  margin: 0 auto;
  object-fit: contain;
  border-radius: var(--cs-radius-inner);
}
.cs-stage__shot figcaption { margin-top: 12px; padding: 0 4px; font-size: var(--cs-type-caption); line-height: 1.5; color: var(--ink-muted); }
.cs-stage .cs-stage__desc { padding-top: 22px; font-size: var(--cs-type-small); line-height: 1.65; }
.cs-stage h4 { margin: 22px 0 8px; font-size: 14px; font-weight: 700; color: var(--ink); }
.cs-stage ul { list-style: none; margin: 0; padding: 0; }
.cs-stage li { position: relative; padding-left: 22px; margin-bottom: 6px; font-size: 15.5px; line-height: 1.55; }
.cs-stage li::before { position: absolute; left: 2px; top: 0; font-weight: 700; color: var(--ink); }
.cs-stage__good li::before { content: "+"; }
.cs-stage__bad li::before { content: "\2212"; }
/* a stage with no lists in the source spans both list rows with its verdict */
.cs-stage .cs-stage__verdict {
  grid-row: span 2;
  align-self: start;
  margin-top: 22px;
  padding: 20px 22px;
  border-radius: 18px;
  background: var(--cs-surface-deep);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink);
}

/* ============================================================
   ANATOMY: one real screen taken apart, each part labelled
   The page sets each part's source slice with --top and --h
   (pixels in the source image) and the source width with --src-w.
   Seams never cross a mark or a word.
   ============================================================ */

.cs-anatomy {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 56px 48px;
  align-items: start;
  margin: var(--cs-block-gap) 0 0;
}
.cs-anatomy__figure { grid-column: 1 / -1; margin: 0; }
.cs-anatomy__figure > figcaption { margin-top: 12px; padding: 0 4px; font-size: var(--cs-type-caption); color: var(--ink-muted); }
.cs-anatomy__parts {
  --w: 420px;
  list-style: none;
  margin: 0;
  padding: 40px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
  display: grid;
  gap: 40px;
}
.cs-part {
  display: grid;
  grid-template-columns: var(--w) minmax(0, 1fr);
  align-items: center;
}
.cs-part__crop {
  display: block;
  width: var(--w);
  height: calc(var(--w) * var(--h) / var(--src-w, 375));
  overflow: hidden;
  border-radius: 12px;
  background: #fff;
  box-shadow: var(--cs-shot-shadow);
}
.cs-part__crop img {
  display: block;
  width: var(--w);
  max-width: none;
  height: auto;
  margin-top: calc(var(--w) * var(--top, 0) / var(--src-w, 375) * -1);
}
.cs-part__label {
  position: relative;
  padding-left: 64px;
  font-size: var(--cs-type-label);
  line-height: 1.45;
  color: var(--ink-muted);
}
.cs-part__label strong { display: block; font-size: 16px; color: var(--ink); }
/* leader from the part to its name, ending in a round dot on the part */
.cs-part__label::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 0.72em;
  width: 46px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink-faint);
}
.cs-part__label::after {
  content: "";
  position: absolute;
  left: 2px;
  top: calc(0.72em - 3px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ink);
}
.cs-anatomy__copy h3 { margin: 0 0 12px; font-size: var(--cs-type-sub); letter-spacing: -0.01em; color: var(--ink); }
.cs-anatomy__copy p { margin: 0 0 16px; }

/* ============================================================
   SCRUBBED PROTOTYPE VIDEO
   Static: a framed video with native controls. With JS
   (case-study.js adds html.has-scroll-video-js) the track becomes
   the scroll distance and the pin holds the stage under the nav
   while scroll owns the timeline.
   ============================================================ */

.cs-scrub { margin: var(--cs-block-gap) 0 0; }
.cs-scrub__pin {
  display: grid;
  justify-items: center;
  gap: 14px;
  padding: 14px 14px 16px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
}
.cs-scrub__media {
  display: block;
  width: 100%;
  max-height: min(72dvh, 720px);
  object-fit: contain;
  border-radius: 14px;
}
.cs-scrub figcaption { font-size: var(--cs-type-caption); color: var(--ink-muted); }
html.has-scroll-video-js .cs-scrub__track { height: 420vh; }
html.has-scroll-video-js .cs-scrub__pin {
  position: sticky;
  top: 0;
  height: 100dvh;
  align-content: center;
  padding: 120px 0 28px;      /* clears the sticky nav and its blur */
  border-radius: 0;
  background: transparent;
}
html.has-scroll-video-js .cs-scrub__media {
  width: auto;
  height: calc(100dvh - 200px);
  max-height: none;
  border-radius: 0;
}

/* ============================================================
   CLIMAX: the inverted results band
   --ink and --bg swap, so it is dark by day and light at night.
   A page may give it an edge silhouette from ITS OWN product
   (an inline <svg class="cs-climax__edge ..."> filled by this rule);
   the system ships none.
   ============================================================ */

.cs-climax {
  --cs-inv-muted: color-mix(in oklab, var(--bg) 76%, var(--ink));
  position: relative;
  z-index: 1;
  margin-top: var(--cs-climax-gap);
}
.cs-climax__band {
  position: relative;
  padding: clamp(84px, 9vw, 120px) 0 clamp(92px, 10vw, 132px);
  background: var(--ink);
  color: var(--bg);
}
.cs-climax__edge {
  position: absolute;
  left: 0;
  width: 100%;
  height: 56px;
  fill: var(--ink);
}
.cs-climax__edge--top { top: -55px; }
.cs-climax__edge--bottom { bottom: -55px; }

/* fallback when the page has no product silhouette to cut the edge with:
   an inset island, margin on every side, so no flat full-bleed seam */
.cs-climax--island .cs-climax__band {
  width: min(1240px, calc(100% - 32px));
  margin: 0 auto;
  border-radius: 36px;
}
.cs-climax--island .cs-climax__inner { width: min(1120px, calc(100% - 2 * clamp(24px, 5vw, 60px))); }

.cs-climax__inner {
  width: var(--cs-edge);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 56px;
  align-items: start;
}
.cs-climax__inner > h2,
.cs-climax__inner > .cs-climax__lead,
.cs-metrics { grid-column: 1 / -1; }

.cs-climax h2 {
  margin: 0 0 26px;
  font-size: var(--cs-type-climax);
  line-height: 0.88;
  color: var(--bg);
}
.cs-climax__lead,
.cs-climax__note {
  max-width: var(--cs-measure);
  margin: 0;
  font-size: 18px;
  line-height: 1.7;
  color: var(--cs-inv-muted);
}
.cs-climax__band strong { color: var(--bg); }

.cs-metrics {
  display: grid;
  grid-template-columns: repeat(var(--cs-cols, 3), minmax(0, 1fr));
  gap: 56px;
  margin: 72px 0 64px;
}
.cs-metric > * { margin: 0; }
.cs-metric__value {
  font-size: var(--cs-type-metric);
  line-height: 0.82;
  color: var(--bg);
  white-space: nowrap;
}
.cs-metric__value sup {
  margin-left: 6px;
  font-size: 0.3em;
  vertical-align: top;
  line-height: 1;
  color: var(--cs-inv-muted);
}
.cs-metric h3 { margin-top: 22px; font-size: 19px; font-weight: 700; color: var(--bg); }
.cs-metric__note { margin-top: 4px; font-size: var(--cs-type-label); color: var(--cs-inv-muted); }

/* the honest caveat, tied to its metrics by the same mark */
.cs-footnote {
  display: flex;
  gap: 12px;
  max-width: 30rem;
  margin: 0;
  font-size: var(--cs-type-label);
  line-height: 1.6;
  color: var(--cs-inv-muted);
}
.cs-footnote__mark { flex: none; font-size: 30px; line-height: 1; color: var(--bg); }

/* closing reflection, on the page ground, aligned to the reading column */
.cs-reflection {
  width: var(--cs-edge);
  margin: clamp(120px, 13vw, 176px) auto 0;
  padding-left: calc(var(--cs-rail) + var(--cs-rail-gap));
}
.cs-reflection p {
  max-width: 34rem;
  margin: 0 0 22px;
  font-size: clamp(18px, 2vw, 21px);
  line-height: 1.7;
  color: var(--ink);
}

/* ============================================================
   PROTOTYPE MODAL (appears without motion)
   ============================================================ */

.cs .prototype-modal {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  visibility: hidden;
}
.cs .prototype-modal.is-open { visibility: visible; }
.cs .prototype-modal__backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.7); cursor: pointer; }
.cs .prototype-modal__dialog {
  position: relative;
  z-index: 1;
  background: var(--panel);
  border-radius: 14px;
  overflow: hidden;
  width: min(480px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
}
.cs .prototype-modal__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 20px 16px; }
.cs .prototype-modal__eyebrow { margin: 0 0 4px; font-size: 13px; font-weight: 500; color: var(--ink-muted); }
.cs .prototype-modal__header h2 { margin: 0; font-size: 18px; font-weight: 700; color: var(--ink); }
.cs .prototype-modal__close {
  flex-shrink: 0;
  background: color-mix(in oklab, var(--ink) 8%, transparent);
  border: none;
  border-radius: 8px;
  color: var(--ink);
  font: 500 13px/1 "Plus Jakarta Sans", system-ui, sans-serif;
  padding: 8px 12px;
  cursor: pointer;
}
.cs .prototype-modal__close:hover { background: color-mix(in oklab, var(--ink) 15%, transparent); }
.cs .prototype-modal__video { display: block; width: 100%; max-height: calc(100dvh - 120px); object-fit: contain; background: #0d0b09; }
body.cs.prototype-modal-open { overflow: hidden; }

/* during the home -> case flight, nothing re-rasterises */
html:active-view-transition .cs-hero__visual img { filter: none; }
html:active-view-transition .case-header::before { backdrop-filter: none; -webkit-backdrop-filter: none; }

/* ============================================================
   HERO VARIANT: thesis-line headline
   The h1 is a thesis line, capped at Headline size so it holds two
   lines in the title column; the project name leads the facts line.
   ============================================================ */

.cs-hero--thesis .cs-hero__title { font-size: var(--cs-type-h2); line-height: 0.92; }
.cs-facts__project { color: var(--ink); font-weight: 700; }

/* ============================================================
   JOURNEY: numbered steps on one track
   Horizontal row, vertical below 760px. A step may carry one
   framed screenshot. .cs-journey--contrast holds two tracks.
   ============================================================ */

.cs-journey {
  --cs-steps: 5;
  position: relative;
  list-style: none;
  margin: var(--cs-block-gap) 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--cs-steps), minmax(0, 1fr));
  gap: 18px;
  align-items: start;
}
.cs-journey::before {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  top: 28px;
  height: 4px;
  border-radius: 4px;
  background: var(--stroke);
}
.cs-step { position: relative; min-width: 0; }
.cs-step__num {
  display: inline-block;
  margin: 0 0 14px;
  padding-right: 12px;
  background: var(--bg);      /* sits over the track */
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: var(--cs-type-seq);
  line-height: 0.9;
  letter-spacing: 0.012em;
  color: var(--ink);
}
.cs-journey .cs-step__title {
  margin: 0 0 6px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink);
}
.cs-chapter .cs-step p { margin: 0; font-size: var(--cs-type-small); line-height: 1.6; }
.cs-step .cs-frame { margin-top: 16px; }

/* contrast: the old way muted and long, the new way in ink and short */
.cs-journey--old .cs-step__num,
.cs-journey--old .cs-step__title { color: var(--ink-faint); }

/* ============================================================
   MOVE CHAPTER: number beside the h2, same baseline
   ============================================================ */

.cs-move__head {
  display: flex;
  align-items: baseline;
  gap: 22px;
  margin: 0 0 36px;
}
.cs-move__num {
  flex: none;
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: var(--cs-type-seq);
  line-height: 0.9;
  color: var(--ink-faint);
}
.cs-move__head h2 {
  margin: 0;
  max-width: 12.5em;
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.012em;
  font-size: var(--cs-type-h2);
  line-height: 0.92;
  color: var(--ink);
}
.cs-chapter .cs-move__num { font-size: var(--cs-type-seq); line-height: 0.9; }
.cs-move__why {
  margin: 40px 0 0;
  max-width: var(--cs-measure);
}
.cs-move__why strong { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.cs-chapter .cs-move__why p { margin: 0; font-size: 17px; line-height: 1.6; color: var(--ink); }

/* ============================================================
   METRIC PAIR: before -> after, inside the climax band
   ============================================================ */

.cs-pair > * { margin: 0; }
.cs-pair__values {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px 18px;
}
.cs-pair__from {
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: var(--cs-type-metric-from);
  line-height: 0.86;
  letter-spacing: 0.012em;
  color: var(--cs-inv-muted);
  white-space: nowrap;
}
.cs-pair__arrow {
  flex: none;
  width: 34px;
  height: 14px;
  align-self: center;
  fill: none;
  stroke: var(--cs-inv-muted);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.cs-pair__to {
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: var(--cs-type-metric);
  line-height: 0.82;
  letter-spacing: 0.012em;
  color: var(--bg);
  white-space: nowrap;
}
.cs-pair h3 { margin-top: 22px; font-size: 19px; font-weight: 700; color: var(--bg); }
.cs-pair__note { margin-top: 4px; font-size: var(--cs-type-label); color: var(--cs-inv-muted); }

/* proportional bars for a count pair: --v is the value / the larger value */
.cs-bars { display: grid; gap: 12px; margin: 26px 0 0; }
.cs-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
}
.cs-bar__fill {
  display: block;
  width: calc(var(--v) * 100%);
  min-width: 10px;
  height: 14px;
  border-radius: 7px;
  background: var(--bg);
}
.cs-bar--from .cs-bar__fill { background: var(--cs-inv-muted); }
.cs-bar__label { font-size: 14px; color: var(--cs-inv-muted); }

/* the pull-quote inside the band inverts with it */
.cs-climax .cs-pull {
  max-width: 21em;
  margin: 0;
  font-size: var(--cs-type-pull);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--bg);
}

/* ============================================================
   RESEARCH QUOTE: a real quote, plain type, attribution under it
   ============================================================ */

.cs-quotes { list-style: none; margin: var(--cs-block-gap) 0; padding: 0; display: grid; gap: 40px; }
.cs-quote { margin: 0; max-width: 30em; }
.cs-quote p {
  margin: 0;
  font-size: var(--cs-type-quote);
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.cs-chapter .cs-quote p { font-size: var(--cs-type-quote); line-height: 1.45; color: var(--ink); }
.cs-quote footer,
.cs-quote figcaption {
  margin-top: 10px;
  font-size: var(--cs-type-caption);
  font-weight: 600;
  color: var(--ink-muted);
}

/* ============================================================
   GROUPED PANEL: one set of related screens or assets
   ============================================================ */

.cs-group {
  margin: var(--cs-block-gap) 0;
  padding: 24px;
  border-radius: var(--cs-radius);
  background: var(--cs-surface);
}
.cs-group__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--cs-cols, 3), minmax(0, 1fr));
  gap: 16px;
  align-items: end;
}
.cs-group__items img { display: block; width: 100%; height: auto; border-radius: var(--cs-radius-inner); }
.cs-group__items span { display: block; margin-top: 8px; font-size: var(--cs-type-caption); font-weight: 600; color: var(--ink); }
.cs-group > figcaption { margin-top: 16px; font-size: var(--cs-type-caption); color: var(--ink-muted); }

/* ============================================================
   HERO VARIANT: a strip of shipped screens
   When the product visual is a sequence, the title and copy share one
   row and the strip runs the full content edge beneath, still inside
   the first viewport.
   ============================================================ */

.cs-hero--strip {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto auto;
  grid-template-areas:
    "title copy"
    "visual visual";
  align-items: end;
  row-gap: clamp(28px, 4vh, 48px);
}
.cs-hero--strip .cs-hero__title { margin: 0; }
.cs-hero--strip .cs-hero__copy { align-self: end; }
.cs-hero--strip .cs-hero__visual { min-height: 0; }

/* ============================================================
   TRIPTYCH: one v1 / v2 / Current comparison
   Three framed screens on one track, marks at Sequence size (earlier
   versions faint, Current in ink), then one verdict row: what the
   previous versions shared across two columns, the current rationale
   under Current.
   ============================================================ */

.cs-triptych { margin: var(--cs-block-gap) 0; }
.cs-triptych__stages {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--cs-grid-gap);
}
.cs-triptych__stages::before {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  top: 26px;
  height: 4px;
  border-radius: 4px;
  background: var(--stroke);
}
.cs-triptych__stage { min-width: 0; display: grid; align-content: start; }
.cs-triptych .cs-triptych__mark {
  position: relative;
  justify-self: start;
  margin: 0 0 16px;
  padding-right: 14px;
  background: var(--bg);
  font-family: "Tanker", "Plus Jakarta Sans", system-ui, sans-serif;
  font-size: var(--cs-type-seq);
  line-height: 0.9;
  letter-spacing: 0.012em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cs-triptych__stage--now .cs-triptych__mark { color: var(--ink); }
.cs-triptych .cs-frame img {
  width: auto;
  max-width: 100%;
  height: var(--cs-triptych-h, 440px);
  margin: 0 auto;
  object-fit: contain;
}
.cs-triptych__verdicts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--cs-grid-gap);
  margin-top: 14px;
}
.cs-triptych__prev,
.cs-triptych__now {
  padding: 20px 22px 22px;
  border-radius: 18px;
  background: var(--cs-surface-deep);
}
.cs-triptych__prev { grid-column: 1 / 3; }
.cs-triptych__prev strong,
.cs-triptych__now strong { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.cs-chapter .cs-triptych__prev p,
.cs-chapter .cs-triptych__now p { margin: 0; font-size: var(--cs-type-small); line-height: 1.6; }
.cs-chapter .cs-triptych__now p { font-weight: 600; color: var(--ink); }

/* ============================================================
   VERDICT LINE: one sentence that closes a chapter or a block
   ============================================================ */

.cs-chapter .cs-verdict,
.cs-verdict {
  max-width: 30em;
  margin: 28px 0 0;
  font-size: var(--cs-type-card);
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* ============================================================
   EMPTY SLOT: a named visual the repo does not have
   ============================================================ */

.cs-slot {
  margin: 0;
  display: grid;
  align-content: center;
  justify-items: start;
  gap: 6px;
  min-height: var(--cs-slot-h, 240px);
  padding: 28px;
  border: 2px dashed var(--stroke);
  border-radius: var(--cs-radius);
  background: var(--cs-surface-deep);
}
.cs-slot strong { font-size: var(--cs-type-label); font-weight: 700; color: var(--ink); }
.cs-slot code,
.cs-slot span { font-size: var(--cs-type-caption); color: var(--ink-muted); font-family: inherit; }

/* ============================================================
   RESPONSIVE
   1180: tighten. 1023: hero stacks, rail hides, two-up grids go one-up.
   760: phone layouts. Every h2 holds two lines at 390.
   ============================================================ */

@media (max-width: 1180px) {
  .cs-compare { column-gap: 20px; }
  .cs-stage__shot img { height: 380px; }
  .cs-anatomy__parts { --w: 340px; }
}

@media (max-width: 1023px) {
  .cs-hero--strip { grid-template-areas: "title" "visual" "copy"; }
  .cs-hero {
    --cs-visual-h: clamp(330px, calc(42vw + 160px), 560px);
    min-height: 0;
    padding-top: 68px;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    grid-template-areas: "title" "visual" "copy";
    align-items: start;
  }
  .cs-hero__title { margin: 0 0 28px; font-size: clamp(54px, 13vw, 96px); }
  .cs-hero__copy { margin-top: 32px; }

  .cs-shell { display: block; }
  .cs-rail { display: none; }

  .cs-anatomy { grid-template-columns: 1fr; gap: 40px; }
  .cs-climax__inner { grid-template-columns: 1fr; row-gap: 32px; }
  .cs-reflection { padding-left: 0; }
}

@media (max-width: 760px) {
  .cs-chapter > h2 { font-size: clamp(32px, 8.9vw, 44px); }

  .cs-frames { gap: 10px; }
  .cs-frame { padding: 8px 8px 10px; border-radius: 16px; }
  .cs-frame img, .cs-frame video { border-radius: 10px; }
  .cs-frame figcaption { font-size: 13px; margin-top: 8px; }
  .cs-frame--screen img { height: var(--cs-screen-h-sm, 320px); }

  .cs-ledger__row { grid-template-columns: 1fr; gap: 14px; padding: 24px; }

  .cs-findings { grid-template-columns: 1fr; }
  .cs-finding { grid-row: auto; display: block; }
  .cs-finding > * { display: block; }

  .cs-compare { grid-template-columns: 1fr; row-gap: 72px; margin-top: 72px; }
  .cs-compare::before { display: none; }
  .cs-stage { display: block; }
  .cs-stage .cs-stage__mark { font-size: 76px; }
  .cs-stage__shot img { height: 400px; }
  .cs-stage .cs-stage__verdict { margin-top: 20px; }

  .cs-anatomy__parts { --w: min(200px, 52vw); padding: 22px 16px; gap: 26px; }
  .cs-part__label { padding-left: 34px; font-size: 13px; }
  .cs-part__label::before { width: 22px; }

  .cs-metrics { grid-template-columns: 1fr; gap: 40px; }
  .cs-triptych { --cs-triptych-h: 240px; }
  .cs-triptych__stages { gap: 8px; }
  .cs-triptych .cs-triptych__mark { font-size: 24px; margin-bottom: 10px; padding-right: 8px; }
  .cs-triptych__stages::before { top: 13px; }
  .cs-triptych__verdicts { grid-template-columns: 1fr; }
  .cs-triptych__prev { grid-column: auto; }
  .cs-climax h2 { font-size: clamp(36px, 10vw, 60px); }

  .cs-journey { grid-template-columns: 1fr; gap: 28px; padding-left: 0; }
  .cs-journey::before { left: 14px; right: auto; top: 8px; bottom: 8px; width: 4px; height: auto; }
  .cs-step { display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: 14px; }
  .cs-step__num { grid-row: span 3; margin: 0; padding: 4px 0 6px; text-align: left; font-size: 44px; }
  .cs-step .cs-frame { grid-column: 2; max-width: 240px; }

  .cs-move__head { gap: 14px; }
  .cs-move__head h2 { font-size: clamp(32px, 8.9vw, 44px); }
  .cs-group__items { grid-template-columns: repeat(var(--cs-cols-sm, 2), minmax(0, 1fr)); }
  .cs-climax__edge { height: 32px; }
  .cs-climax__edge--top { top: -31px; }
  .cs-climax__edge--bottom { bottom: -31px; }

  html.has-scroll-video-js .cs-scrub__track { height: 380svh; }
  html.has-scroll-video-js .cs-scrub__pin { height: 100svh; padding-top: 96px; }
  html.has-scroll-video-js .cs-scrub__media { height: calc(100svh - 170px); max-width: 100%; }
}
