/* ═══════════════════════════════════════════════════════════════════
   GLASSBOX — core stylesheet
   Structural layout, the 3D centerpiece, and every custom component.
   Utility-level styling (spacing / type scale / colors) lives in the
   markup as Tailwind classes; tokens are mirrored here as CSS vars so
   the canvas + 3D layers stay in sync with the Tailwind theme.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* Theme triplets — the light theme swaps these (see [data-theme]) */
  --c-bg-rgb: 11 12 16;
  --c-ice-rgb: 255 255 255;
  --c-data-rgb: 148 163 184;
  --c-smoke-rgb: 30 41 59;
  --c-edge-rgb: 255 255 255;   /* cube edge highlights */

  --c-nav-rgb: 203 213 225;    /* nav + secondary chrome text */
  --pill-bg: #171A21;          /* solid elevated surface for pills */
  --c-bg: rgb(var(--c-bg-rgb));
  --c-ice: rgb(var(--c-ice-rgb));
  --c-data: rgb(var(--c-data-rgb));
  --c-smoke: rgb(var(--c-smoke-rgb));
  --c-q1: #FF5722;        /* quantum orange — core          */
  --c-q2: #FF7043;        /* quantum orange — refraction    */
  /* Tracking for every extruded headline, hero line and emphasis span alike */
  --h3d-track: 0.025em;
  /* CTA fill only. White on the brand orange above measures 2.7–3.2:1, under
     the 4.5 AA floor, which is why button copy read as mush at 12–13px. These
     two are the same hue walked down until white clears AA (4.3 and 5.1), so
     the buttons get legible without moving the brand orange everywhere else. */
  --c-cta-1: #C93D0F;     /* CTA fill — core                */
  --c-cta-2: #DD4412;     /* CTA fill — refraction          */

  /* Extruded type. The side is a RAMP between two anchors — a single flat tone
     reads as a drop shadow because nothing about it says "surface receding
     from the light". Dark theme: white face, side steps down into near-black. */
  --h3d-face-hi: #FFFFFF;
  --h3d-face-mid: #EDF1F7;
  --h3d-face-lo: #A9B6C9;
  --h3d-near: #6E7789;
  --h3d-far: #1C212B;
  --h3d-contact: rgb(0 0 0 / 0.5);
  /* How far the extrusion leans RIGHT for every step it drops. At 1 the side
     ran as far sideways as down, so a word's depth landed in the space after
     it — invisible between two ink words, obvious where ink meets an
     emphasised one, which read as a tight gap around the highlight. Word
     spacing can't fix that: the face's space sits beside an inline-block and
     widens differently from the same space in the ::before clone, so the two
     copies drift apart. Leaning the depth downward instead keeps the gap
     clear and every copy in register. Lower = more frontal light. */
  --h3d-x: 0.7;
  /* Emphasis carries its own face and side, so a highlighted word is a
     differently-coloured solid rather than paint on a grey block. */
  --q3d-face-hi: #FFA579;
  --q3d-face-mid: #FF7043;
  --q3d-face-lo: #EF5316;
  --q3d-near: #C4400F;
  --q3d-far: #3D1204;
  /* Live values carry the same treatment in their own sign colour. Built on
     the same shape as the orange above — light tint, base, deeper base for the
     face; a dark side ramping to near-black — because that shape is what makes
     the highlight read as a solid. */
  --g3d-face-hi: #86EFAC;
  --g3d-face-mid: #4ADE80;
  --g3d-face-lo: #22C55E;
  --g3d-near: #15803D;
  --g3d-far: #052E16;
  --r3d-face-hi: #FCA5A5;
  --r3d-face-mid: #F87171;
  --r3d-face-lo: #EF4444;
  --r3d-near: #B91C1C;
  --r3d-far: #450A0A;
  /* The summit. Gold, and the only mark that gets a backdrop. */
  --y3d-face-hi: #FFF3C4;
  --y3d-face-mid: #FFD24D;
  --y3d-face-lo: #F5A623;
  --y3d-near: #B7770A;
  --y3d-far: #3D2503;
  /* Body copy takes the headline's colour rather than the muted chrome tone */
  --c-read: #E4EAF3;

  --cube: clamp(190px, 30vmin, 300px);
  --stage-cy: 33%; /* centerpiece rides above center, clear of the hero copy */

  /* Camera-driven knobs. js/camera.js interpolates these every frame. */
  --cube-o: 1;            /* whole-cube opacity              */
  --face-fill: 1;         /* smoked-glass panel fill         */
  --face-edge: 1;         /* ice-white refractive edge lines */
  --core-o: 1;            /* internal quantum core glow      */
  --stage-o: 1;           /* entire fixed stage              */
}

/* No CSS smooth-scroll: all programmatic movement goes through the
   rAF glide in main.js, and the two would fight each other. */
html, body {
  overflow-x: clip; /* clip (not hidden) — hidden would break position:sticky pinning */
  background: var(--c-bg);
}

/* Premium scrollbar — thin, dark, quiet */
html { scrollbar-width: thin; scrollbar-color: #1E293B #0B0C10; }
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: #0B0C10; }
::-webkit-scrollbar-thumb {
  background: #1E293B;
  border-radius: 999px;
  border: 2px solid #0B0C10;
}
::-webkit-scrollbar-thumb:hover { background: #34455C; }
::-webkit-scrollbar-thumb:active { background: rgba(255, 87, 34, 0.6); }

/* Explicit letter-spacing rules for the type system.
   Monospace is reserved for the terminal device — everything else
   speaks the refined sans so the page reads high-end, not retro. */
/* ── Extruded display type ─────────────────────────────────────────
   The FACE is the element: a gradient clipped to the glyphs. The SIDE is a
   ::before behind it carrying a stacked text-shadow. They have to be separate
   elements because a gradient face needs a transparent fill, and a transparent
   fill lets the element's own shadow show straight through the glyph.
   main.js generates the ::before's text into data-text so the copy stays
   single-source. No transform anywhere — the extrude runs straight down-right. */
/* ONE tracking value for every piece of extruded display type, set on the two
   roots that carry it — section headlines and the hero line. letter-spacing
   inherits, so the emphasis spans, the hero segments, the live ledger values
   and the milestone marks all take the same figure rather than each drifting
   to its own. If a component needs different air, change --h3d-track, not that
   component; a local override is what put the orange out of step before.
   Opened up from -0.005em: Archivo Black is drawn to set tight, but the
   extrusion throws down-RIGHT, so at negative tracking every glyph's side
   landed on the next glyph's face and the row fused into a smear. This is the
   point where each side finds background again; past ~0.04em it stops reading
   as an impact headline and starts reading as a tracked-out one. */
.h-section,
.hero-headline { letter-spacing: var(--h3d-track); }

.h-section {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  /* The variable width axis replaces Archivo Black's brute mass: condensed
     for section headlines, normal width for the hero (see .font-display). */
  font-stretch: 80%;
}

.h3d-line,
.h3d-q,
.h3d-seg,
.hero-live-value,
.hlc-marks em,
.hlc-arrow b {
  position: relative;
  background-image: linear-gradient(
    180deg,
    var(--h3d-face-hi) 0%,
    var(--h3d-face-mid) 46%,
    var(--h3d-face-lo) 100%
  );
  /* Tile the gradient per LINE, not per block: clipped to text, one gradient
     otherwise stretches over the whole element, so a headline wrapping to
     three lines gets the light top on line one and the dark bottom on line
     three and the lines stop matching. */
  background-size: 100% 1.08em;
  background-repeat: repeat-y;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.h3d-line { display: block; }
/* inline-block on the inline carriers: an absolutely-positioned ::before
   inside an INLINE box resolves top:0 against the font ascent rather than the
   content top, which left the clone a couple of px low and the layer beneath
   peeking out along the top-left edge. */
.h3d-q,
.h3d-seg,
.hero-live-value,
.hlc-arrow b { display: inline-block; }
/* An emphasised phrase sharing its line with plain text is atomic: the face
   can only break around it, so main.js pins the clone's spaces to NBSP to
   match. Without nowrap here the face would still break inside the phrase at
   narrow widths and drift off its own extrusion. A phrase that owns its whole
   line is left breakable — it and its clone wrap identically. */
.h3d-q.is-atomic { white-space: nowrap; }
.h3d-q:not(.is-atomic)::before { white-space: normal; }

/* The other half of that agreement, wrapped by h3d.js around any space-free
   run that mixes an atomic inline with text — an emphasised phrase and the
   comma behind it, a word and its trailing emoji. Both are one word to the
   clone; without this the face could break between them and the two wrapped
   to different line counts. */
.h3d-nb { white-space: nowrap; }

/* An emphasised word swaps the whole palette, face and side. It paints after
   the line's clone, so its orange side covers the neutral one underneath. */
/* Sign drives the palette. counter.js toggles is-pos / is-neg, and because
   the face is a clipped gradient the old `color` rules no longer do anything —
   these vars are what actually paint it now. */
.hero-live-value.is-pos {
  --h3d-face-hi: var(--g3d-face-hi);
  --h3d-face-mid: var(--g3d-face-mid);
  --h3d-face-lo: var(--g3d-face-lo);
  --h3d-near: var(--g3d-near);
  --h3d-far: var(--g3d-far);
}
.hero-live-value.is-neg {
  --h3d-face-hi: var(--r3d-face-hi);
  --h3d-face-mid: var(--r3d-face-mid);
  --h3d-face-lo: var(--r3d-face-lo);
  --h3d-near: var(--r3d-near);
  --h3d-far: var(--r3d-far);
}
/* Money put in is never negative, so this one's sign is known before any data
   loads. counter.js only adds .is-pos once ledger.json resolves, which left
   the headline's $0 slate on the first paint — and permanently slate if the
   fetch never lands (file://, offline). Green from the start instead. */
.hero-live-value--invested {
  --h3d-face-hi: var(--g3d-face-hi);
  --h3d-face-mid: var(--g3d-face-mid);
  --h3d-face-lo: var(--g3d-face-lo);
  --h3d-near: var(--g3d-near);
  --h3d-far: var(--g3d-far);
}

.h3d-q {
  --h3d-face-hi: var(--q3d-face-hi);
  --h3d-face-mid: var(--q3d-face-mid);
  --h3d-face-lo: var(--q3d-face-lo);
  --h3d-near: var(--q3d-near);
  --h3d-far: var(--q3d-far);
}

.h3d-line::before,
.h3d-q::before,
.h3d-seg::before,
.hero-live-value::before,
.hlc-marks em::before,
.hlc-arrow b::before {
  content: attr(data-text);
  position: absolute;
  top: 0;
  z-index: -1;
  color: var(--h3d-near);
  -webkit-text-fill-color: var(--h3d-near);
  /* 15 steps interpolated between two anchors rather than five flat tones —
     five banded visibly down the side. Offsets in em so the depth tracks the
     type size at every breakpoint. */
  text-shadow:
    calc(0.006em * var(--h3d-x)) 0.006em 0 color-mix(in oklab, var(--h3d-near) 100%, var(--h3d-far)),
    calc(0.012em * var(--h3d-x)) 0.012em 0 color-mix(in oklab, var(--h3d-near) 93%, var(--h3d-far)),
    calc(0.018em * var(--h3d-x)) 0.018em 0 color-mix(in oklab, var(--h3d-near) 86%, var(--h3d-far)),
    calc(0.024em * var(--h3d-x)) 0.024em 0 color-mix(in oklab, var(--h3d-near) 79%, var(--h3d-far)),
    calc(0.030em * var(--h3d-x)) 0.030em 0 color-mix(in oklab, var(--h3d-near) 71%, var(--h3d-far)),
    calc(0.036em * var(--h3d-x)) 0.036em 0 color-mix(in oklab, var(--h3d-near) 64%, var(--h3d-far)),
    calc(0.042em * var(--h3d-x)) 0.042em 0 color-mix(in oklab, var(--h3d-near) 57%, var(--h3d-far)),
    calc(0.048em * var(--h3d-x)) 0.048em 0 color-mix(in oklab, var(--h3d-near) 50%, var(--h3d-far)),
    calc(0.054em * var(--h3d-x)) 0.054em 0 color-mix(in oklab, var(--h3d-near) 43%, var(--h3d-far)),
    calc(0.060em * var(--h3d-x)) 0.060em 0 color-mix(in oklab, var(--h3d-near) 36%, var(--h3d-far)),
    calc(0.066em * var(--h3d-x)) 0.066em 0 color-mix(in oklab, var(--h3d-near) 29%, var(--h3d-far)),
    calc(0.072em * var(--h3d-x)) 0.072em 0 color-mix(in oklab, var(--h3d-near) 21%, var(--h3d-far)),
    calc(0.078em * var(--h3d-x)) 0.078em 0 color-mix(in oklab, var(--h3d-near) 14%, var(--h3d-far)),
    calc(0.084em * var(--h3d-x)) 0.084em 0 color-mix(in oklab, var(--h3d-near) 7%, var(--h3d-far)),
    calc(0.090em * var(--h3d-x)) 0.090em 0 color-mix(in oklab, var(--h3d-near) 0%, var(--h3d-far)),
    calc(0.115em * var(--h3d-x)) 0.115em 0.035em var(--h3d-contact),
    calc(0.165em * var(--h3d-x)) 0.165em 0.10em var(--h3d-contact);
}
.h3d-line::before { left: 0; right: 0; }
.h3d-q::before,
.h3d-seg::before,
.hero-live-value::before,
.hlc-marks em::before,
.hlc-arrow b::before { left: 0; white-space: pre; }

/* ── The ledger's labels: same depth, fewer facets ─────────────────
   These run at 0.36–0.42em of the headline — 17–20px. The shared ramp above
   puts 15 steps plus two BLURRED contact shadows inside 0.165em, which is
   under 3px at that size: every facet lands on less than a fifth of a pixel,
   they average into a soft grey wash, and the blur finishes it off. The result
   read as text with a smudge behind it while the headline beside it read as a
   solid — the same em values genuinely cannot look the same at a quarter of
   the size. Four hard steps and no blur, reaching about the same distance, so
   each facet gets most of a pixel to itself and the depth survives. */
.hlc-marks em::before,
.hlc-arrow b::before {
  text-shadow:
    0.035em 0.035em 0 color-mix(in oklab, var(--h3d-near) 100%, var(--h3d-far)),
    0.075em 0.075em 0 color-mix(in oklab, var(--h3d-near) 60%, var(--h3d-far)),
    0.115em 0.115em 0 color-mix(in oklab, var(--h3d-near) 25%, var(--h3d-far)),
    0.155em 0.155em 0 var(--h3d-far);
}

/* ── The rungs' ink: at this size the SIDE is what you actually see ──
   Those four facets land inside ~3px at 20px type, so the side covers the
   whole glyph and the background-clipped FACE contributes almost nothing.
   Measured by injection: forcing the face gradient to solid red repaints 79
   pixels, forcing --h3d-near repaints 9,762. So the rungs were reading as the
   near-black side while the headline beside them reads as its slate face, and
   the two never matched no matter what the face gradient said. Pointing the
   side at the face tones puts both on the same ink, and because --h3d-face-*
   already flips per theme this holds in light and dark without a second rule.
   The summit is excluded: $1M keeps its gold, and the $0 arrow is a separate
   carrier that keeps its green. */
.hlc-marks em:not(.hlc-end) {
  --h3d-near: var(--h3d-face-mid);
  --h3d-far: var(--h3d-face-lo);
}

/* Every carrier shares the one ramp above — same 15 steps, same 0.165em reach.
   A shorter side was tried on light-theme neutral type while the face was
   still near-black: it had no room for a side and a deep ramp just piled dark
   on dark. That is no longer true. The face now sits at a deep slate with the
   side wholly beneath it, so it can carry the full depth, and it has to — at
   0.058em against the emphasis's 0.165em the black sat visibly shallower than
   the orange beside it on the same line. */

/* ── Section descriptions ───────────────────────────────────────────
   Same ink as the headline, not the muted --c-data chrome tone (that one is
   tuned for nav and labels, not for paragraphs anyone actually reads).
   Size is bumped only on the 15px leads — the 11–12.5px small print shares
   the .text-data class and must not grow with them.
   Emphasis inside a description: <b> bold, <em> italic, <u> orange rule,
   .q orange text. They stack, so <b><u class="q"> is all three. */
main p.text-data {
  color: var(--c-read);
  font-weight: 500;
  /* 1.625 (leading-relaxed) was tight for the longer comedic beats on the
     near-black theme; 1.65 is the reading floor everywhere below. */
  line-height: 1.65;
}
main p.text-data.text-\[15px\] {
  font-size: 16px;
  line-height: 1.68;
}
/* The hero subheadline is text-ice, not text-data, so it needs naming here or
   the emphasis rules skip the one paragraph most likely to use them. */
.hero-sub {
  font-weight: 500;
  letter-spacing: 0.004em;
  /* Mobile ran 15px while desktop already sat at 17px — bring the base up to
     the same comfortable floor and cap the measure at ~62 characters. */
  font-size: 16.5px;
  line-height: 1.66;
  max-width: 62ch;
}
@media (min-width: 768px) {
  .hero-sub { font-size: 17px; line-height: 1.62; }
}

main p.text-data b,
main p.text-data strong,
.hero-sub b,
.hero-sub strong { font-weight: 700; }

main p.text-data em,
.hero-sub em { font-style: italic; }

main p.text-data u,
.hero-sub u {
  text-decoration-color: var(--c-q2);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

main p.text-data .q,
main p.text-data u.q,
.hero-sub .q,
.hero-sub u.q { color: var(--c-q1); }

/* ── The inline ledger, extruded ────────────────────────────────────
   The bar sits mid-sentence between extruded words, so it has to read as the
   same material. The track gets a box-shadow extrusion (a solid, not glyphs,
   so no clone is involved) and its labels take the text ramp — which is in em,
   so at their much smaller size the depth scales down to match automatically.
   No clone on the labels either: counter.js rewrites them, and a snapshot
   would go stale. They keep a solid fill, and a solid fill can carry the ramp
   directly. */
.hlc-track {
  /* Same 15-step ramp as the type, as box-shadow — it is a solid, not glyphs,
     so no clone is involved. Four chunky steps read as a stack of slabs next
     to the smoothly-ramped words either side of it. */
  box-shadow:
    0.006em 0.006em 0 color-mix(in oklab, var(--h3d-near) 100%, var(--h3d-far)),
    0.012em 0.012em 0 color-mix(in oklab, var(--h3d-near) 93%, var(--h3d-far)),
    0.018em 0.018em 0 color-mix(in oklab, var(--h3d-near) 86%, var(--h3d-far)),
    0.024em 0.024em 0 color-mix(in oklab, var(--h3d-near) 79%, var(--h3d-far)),
    0.030em 0.030em 0 color-mix(in oklab, var(--h3d-near) 71%, var(--h3d-far)),
    0.036em 0.036em 0 color-mix(in oklab, var(--h3d-near) 64%, var(--h3d-far)),
    0.042em 0.042em 0 color-mix(in oklab, var(--h3d-near) 57%, var(--h3d-far)),
    0.048em 0.048em 0 color-mix(in oklab, var(--h3d-near) 50%, var(--h3d-far)),
    0.054em 0.054em 0 color-mix(in oklab, var(--h3d-near) 43%, var(--h3d-far)),
    0.060em 0.060em 0 color-mix(in oklab, var(--h3d-near) 36%, var(--h3d-far)),
    0.066em 0.066em 0 color-mix(in oklab, var(--h3d-near) 29%, var(--h3d-far)),
    0.072em 0.072em 0 color-mix(in oklab, var(--h3d-near) 21%, var(--h3d-far)),
    0.078em 0.078em 0 color-mix(in oklab, var(--h3d-near) 14%, var(--h3d-far)),
    0.084em 0.084em 0 color-mix(in oklab, var(--h3d-near) 7%, var(--h3d-far)),
    0.090em 0.090em 0 color-mix(in oklab, var(--h3d-near) 0%, var(--h3d-far)),
    0.115em 0.115em 0.035em var(--h3d-contact);
}
/* The ledger's own labels sit inside the headline, so they get the headline's
   material — gradient face and the full ramp — rather than the flat colour and
   three-step stub they had. The net figure follows its sign, the same way the
   invested value does; counter.js keeps its clone in sync. */
.hlc-arrow.is-pos b {
  --h3d-face-hi: var(--g3d-face-hi);
  --h3d-face-mid: var(--g3d-face-mid);
  --h3d-face-lo: var(--g3d-face-lo);
  --h3d-near: var(--g3d-near);
  --h3d-far: var(--g3d-far);
}
.hlc-arrow.is-neg b {
  --h3d-face-hi: var(--r3d-face-hi);
  --h3d-face-mid: var(--r3d-face-mid);
  --h3d-face-lo: var(--r3d-face-lo);
  --h3d-near: var(--r3d-near);
  --h3d-far: var(--r3d-far);
}

/* Colour glyphs ignore the clip and would collect their own 15-layer stack,
   so h3d.js keeps them out of the ::before's copy of the text. That leaves the
   clone NARROWER than the face by exactly one emoji — invisible on a
   left-aligned headline, but a centred one centres the two at different points
   and the extrusion slides out from under the glyphs by half an emoji.
   Taking the glyph out of the width fixes it from the other side: the face now
   measures the same as the clone, both centre identically, and the emoji hangs
   past the last letter instead of pushing it. Decorative and always trailing,
   so nothing needs the space it would have taken. */
.h3d-emoji {
  -webkit-text-fill-color: initial;
  color: initial;
  text-shadow: 0.05em 0.06em 0.05em var(--h3d-contact);
  display: inline-block;
  width: 0;
  overflow: visible;
}

/* Scaled up to hold its own against the extruded headlines below it.
   Tracking comes in as the size goes up, or 0.3em at 12px runs absurdly wide.
   font-size here, not a utility, so it beats the text-[10px] in the markup. */
.kicker {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.nav-link  { letter-spacing: 0.13em; }

/* ── Fixed layers ─────────────────────────────────────────────── */

#flow-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  contain: strict;
  /* camera.js dims this during the channels handoff so the field's streaks
     stay a backdrop instead of competing with the copy on top of them */
  opacity: var(--field-o, 1);
}

#stage {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: var(--stage-o);
}

#grain {
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* Soft vignette for cinematic depth */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(120% 95% at 50% 20%, transparent 55%, rgba(0, 0, 0, 0.5) 100%);
}

/* ── Scenes & pins ────────────────────────────────────────────── */

/* Scenes float above the stage but must never swallow hovers meant
   for the graph nodes — interactivity is re-enabled per element. */
.scene { position: relative; z-index: 10; pointer-events: none; }

/* ── Scene lengths ─────────────────────────────────────────────────
   Defined here, NOT as Tailwind h-[Nvh] utilities. The committed
   tailwind.min.css is purged and only ever compiled the values that were in
   the markup when it was last built, so a new arbitrary height is a silent
   no-op: the scene collapses to the height of its own 100vh pin, the span
   goes to zero, and the entire scene choreography fires in one pixel. (There
   are no lg: height variants in the bundle at all.)
   The pin eats 100vh, so the scroll a scene actually gets is height - 100vh.
   Phones override these further down, in svh. */
#singularity { height: 128vh; }   /* 28vh of travel, faded across all of it */
#xray { height: 145vh; }          /* 45vh — the vault dive through 2A–2D */
/* Below lg the machine is unpinned and flows at its content height */
@media (min-width: 1024px) {
  /* The reserve is ADDED to the section rather than carved out of it: the 45vh
     of travel past the pin is what paces the whole scene (main.js derives its
     parallax span from `height - vh`), so spending it on the buffer would run
     the machine faster on exactly the short viewports that are already tight. */
  #engine {
    height: calc(145vh + var(--engine-reserve, 0px));
    padding-bottom: var(--engine-reserve, 0px);
  }

  /* Reserve the pin's own overflow inside the section.
     The pin is a hard 100svh box; the jobs column is not, and it does not fit
     at any common laptop height. Measured at 1920 wide:
       uncompressed (>950px tall)  column 1087 + the pin's 76+28 padding = 1191
       compressed  (701-950px)     column  805 + the same padding        =  909
       descriptions hidden (<=700) column  542 + the same padding        =  646
     Anything shorter than the figure for its tier and the surplus hangs out of
     the pin's bottom. There is nothing below it any more — #stack used to sit
     there and absorb it, and since it was removed the overflow lands straight
     on #kevin's top padding. Measured: at 1920x1080 the ticker left a 1px gap
     to the anti-guru kicker; at 1920x780 it finished 17px BELOW it.
     Each reserve is its tier's shortfall plus the 27px the left column can be
     parallaxed down by (--engine-left-y), so it falls to zero on viewports
     tall enough to have been fine already and never invents a gap.
     It must be padding on the SECTION: a sticky child is constrained by its
     containing block's content box, so this is a floor the pin cannot cross.
     A spacer element below the pin would not work — the pin would slide past
     it to the same place. */
  #engine { --engine-reserve: clamp(0px, calc(1220px - 100svh), 280px); }
}
@media (min-width: 1024px) and (max-height: 950px) {
  #engine { --engine-reserve: clamp(0px, calc(940px - 100svh), 240px); }
}
/* Under 700px the row descriptions are hidden, the column drops to 542 and the
   pin holds it again — reserving here would only invent dead space. */
@media (min-width: 1024px) and (max-height: 700px) {
  #engine { --engine-reserve: 0px; }
}

.pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Copy layers must not swallow hovers meant for the graph nodes below */
  pointer-events: none;
}
.pin a, .pin button, .pin input { pointer-events: auto; }
/* By the time the workforce grid is on screen the graph has dissolved,
   so the whole grid can take hover states back. */
#engine-copy { pointer-events: auto; }

#hero-copy, #xray-copy, #engine-copy { will-change: opacity, transform; }
#xray-copy { position: absolute; inset: 0; }

/* The machine's two columns travel at slightly different scroll speeds.
   main.js only writes these variables on wide screens. */
/* min-width:0 — grid items default to min-content, which lets the wide
   dashboard table and the long ad filenames push the column past the
   viewport instead of scrolling/eliding inside it */
.engine-left,
.engine-right { min-width: 0; }
.engine-left,
.engine-right {
  will-change: transform;
}
.engine-left { transform: translate3d(0, var(--engine-left-y, 0px), 0); }
.engine-right { transform: translate3d(0, var(--engine-right-y, 0px), 0); }

/* Below lg the two-column grid stacks taller than one viewport, so the
   scene flows unpinned by default; pinning is re-applied at exactly
   Tailwind's lg query so no fractional-width gap can exist between them. */
.engine-pin {
  position: static;
  height: auto;
  min-height: 100svh;
  padding: 110px 0 72px;
}
@media (min-width: 1024px) {
  .engine-pin {
    position: sticky;
    height: 100vh;
    height: 100svh;
    min-height: 0;
    /* Clear the fixed header: the grid centres inside what's left, so the
       kicker and headline can never end up underneath it. */
    padding: 76px 0 28px;
  }
}
/* `safe` is load-bearing, and it belongs on .pin — that flex container is what
   centres the copy, not the grid inside it. A plain `center` overflows EQUALLY
   top and bottom once the column is taller than the pin, pushing the section's
   eyebrow up under the fixed header; it did exactly that on ~860-940px-tall
   laptops. `safe` keeps the centring while it fits and falls back to
   start-alignment the moment it doesn't. Plain `center` first for old engines. */
@media (min-width: 1024px) {
  .engine-pin {
    align-items: center;
    align-items: safe center;
  }
}

/* Short laptop viewports: compress the pinned engine scene so the
   headline and terminal never clip past the 100vh pin */
@media (min-width: 1024px) and (max-height: 950px) {
  /* 950px is derived, not taste: the uncompressed jobs column runs ~844px and
     the pin adds 76px + 28px of padding, so anything under ~948px tall cannot
     fit it. Compress from there rather than letting the last row fall off. */
  #engine-copy { gap: 32px; }
  /* Compression, but far gentler than before: this block used to drop the
     headline to 1.62rem and the body to 13.5px, which left the section reading
     smaller than everywhere else on the site while 314px of the pin sat unused
     at 1440x900. Trimmed to what the column actually needs. */
  #engine-copy .h-section { font-size: 2.15rem; margin-top: 8px; }
  #engine-copy > div > p.text-data { margin-top: 10px; font-size: 15px; }
  #engine-copy [aria-label="Some of the jobs it does"] { margin-top: 14px; }
  #engine-copy .swap-row { padding: 8px 10px; }
  #engine-copy .swap-new p { font-size: 12.5px; line-height: 1.45; margin-top: 2px; }
  #engine-copy .swap-stage { margin-bottom: 2px; }
  #engine-copy .font-semibold.uppercase { margin-top: 12px; }
  /* #engine-panel for specificity — the base .term-body rule sits later in
     this file and would otherwise win on source order. */
  #engine-panel .term-body { height: 296px; }
  .engine-honesty { font-size: 12px; }
}
@media (min-width: 1024px) and (max-height: 700px) {
  #engine-panel .term-body { height: 232px; }
  #engine-copy .swap-new p { display: none; }
}

.engine-pin::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, rgba(11, 12, 16, 0.78) 0%, rgba(11, 12, 16, 0.35) 55%, rgba(11, 12, 16, 0.65) 100%);
  opacity: 0;
  /* Shorter than the old 0.5s: the scrim now arms while the machine is still
     travelling in, so a half-second fade lagged visibly behind the copy. */
  transition: opacity 0.32s ease;
}
.engine-pin.is-lit::before { opacity: 1; }
.engine-pin > * { position: relative; }

/* ── Logo lockup — monochrome, the box inside the G ───────────── */

.logo-lockup { display: flex; align-items: center; }

/* A miniature of the hero centerpiece, built from the same glass:
   theme-aware translucent faces, ember core, slow perpetual spin. */
.logo-cube3d {
  width: 36px;
  height: 36px;
  display: block;
  position: relative;
}
.lc-spin {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 19px;
  height: 19px;
  margin: -9.5px 0 0 -9.5px;
  transform-style: preserve-3d;
  animation: lc-spin 16s linear infinite;
}
.lc-face {
  position: absolute;
  inset: 0;
  border: 1px solid rgb(var(--c-edge-rgb) / 0.42);
  background: linear-gradient(135deg,
    rgb(var(--c-edge-rgb) / 0.12),
    rgb(var(--c-edge-rgb) / 0.03) 40%,
    rgb(var(--c-bg-rgb) / 0.35));
}
.lc-f { transform: translateZ(9.5px); }
.lc-b { transform: rotateY(180deg) translateZ(9.5px); }
.lc-r { transform: rotateY(90deg) translateZ(9.5px); }
.lc-l { transform: rotateY(-90deg) translateZ(9.5px); }
.lc-t { transform: rotateX(90deg) translateZ(9.5px); }
.lc-u { transform: rotateX(-90deg) translateZ(9.5px); }
.lc-core {
  position: absolute;
  inset: 26%;
  border-radius: 50%;
  background: radial-gradient(circle, #FF7043 0%, rgba(255, 87, 34, 0.45) 55%, transparent 80%);
  filter: blur(1.5px);
  animation: lc-pulse 3.6s ease-in-out infinite;
}
.logo-lockup:hover .lc-core { filter: blur(1.5px) brightness(1.4); }
@keyframes lc-spin {
  from { transform: rotateX(-18deg) rotateY(0deg); }
  to   { transform: rotateX(-18deg) rotateY(360deg); }
}
@keyframes lc-pulse {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 1; }
}

/* ── Header ───────────────────────────────────────────────────── */

#site-header.is-scrolled {
  background: rgba(11, 12, 16, 0.72);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.nav-link {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: rgb(var(--c-nav-rgb));
  transition: color 0.25s ease;
  position: relative;
  padding: 4px 0;
}
.nav-link:hover { color: var(--c-ice); }
.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  height: 1px;
  width: 100%;
  background: var(--c-q1);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}
.nav-link.is-active { color: var(--c-ice); }
.nav-link.is-active::after { transform: scaleX(1); }

/* ── The centerpiece cube ─────────────────────────────────────── */

/* Giant faded wordmark floating behind the box (in front of the field).
   Centered by full-width text-align — the camera writes translateY onto
   this element every frame, so translate(-50%) centering would be wiped. */
#hero-watermark {
  position: absolute;
  left: 0;
  right: 0;
  /* Shares the cube's anchor so the wordmark centers behind the box */
  top: calc(var(--stage-cy) - 0.5em);
  text-align: center;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: clamp(3.2rem, 17vw, 20rem); /* low floor keeps it inside phone widths */
  line-height: 1;
  letter-spacing: 0.06em;
  padding-left: 0.06em; /* balance the trailing letter-space */
  white-space: nowrap;
  background: linear-gradient(180deg, rgb(var(--c-ice-rgb) / 0.12) 0%, rgb(var(--c-ice-rgb) / 0.015) 88%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  pointer-events: none;
  will-change: opacity;
}
/* Light theme: ink at the dark theme's alphas nearly vanishes on the
   paper background, so the wordmark takes a heavier top stop to match
   the pop it gets for free on near-black. The shorthand resets
   background-clip, so both clips are restated. */
[data-theme="light"] #hero-watermark {
  background: linear-gradient(180deg, rgb(15 23 42 / 0.2) 0%, rgb(15 23 42 / 0.03) 88%);
  -webkit-background-clip: text;
  background-clip: text;
}

#cube-halo {
  position: absolute;
  left: 50%;
  top: var(--stage-cy);
  width: calc(var(--cube) * 2.6);
  height: calc(var(--cube) * 2.6);
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255, 87, 34, 0.10) 0%, rgba(255, 255, 255, 0.03) 38%, transparent 68%);
  filter: blur(6px);
  opacity: calc(var(--core-o) * var(--cube-o));
}
/* Light theme: the white bloom is invisible on white, so the halo
   leans on saturated ember instead — the hero glow the dark theme
   gets from contrast alone */
[data-theme="light"] #cube-halo {
  background: radial-gradient(circle,
    rgba(255, 87, 34, 0.2) 0%,
    rgba(255, 112, 67, 0.09) 40%,
    transparent 68%);
  filter: blur(14px);
}

/* Reflective floor beneath the floating box */
#cube-floor {
  position: absolute;
  left: 50%;
  top: var(--stage-cy);
  width: calc(var(--cube) * 2.1);
  height: calc(var(--cube) * 0.5);
  transform: translate(-50%, calc(var(--cube) * 0.68));
  background: radial-gradient(ellipse at center,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(255, 87, 34, 0.035) 38%,
    transparent 68%);
  filter: blur(10px);
  opacity: calc(var(--cube-o) * var(--core-o));
}
/* Light theme: the floor reads as a grounded contact shadow with a
   little ember spill, not a light source */
[data-theme="light"] #cube-floor {
  background: radial-gradient(ellipse at center,
    rgb(15 23 42 / 0.13) 0%,
    rgba(255, 87, 34, 0.06) 40%,
    transparent 70%);
}

#cube-rig {
  position: absolute;
  left: 50%;
  top: var(--stage-cy);
  width: var(--cube);
  height: var(--cube);
  margin: calc(var(--cube) / -2) 0 0 calc(var(--cube) / -2);
  opacity: var(--cube-o);
  animation: rig-float 7s ease-in-out infinite;
  will-change: transform, opacity;
}

#cube {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* rotation + camera scale applied by js/camera.js */
}

.cube-face {
  position: absolute;
  inset: 0;
  border: 1px solid rgb(var(--c-edge-rgb) / calc(0.32 * var(--face-edge)));
  box-shadow:
    inset 0 0 34px rgb(var(--c-edge-rgb) / calc(0.05 * var(--face-fill))),
    inset 0 0 2px  rgb(var(--c-edge-rgb) / calc(0.30 * var(--face-edge)));
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: backdrop-filter 0.9s ease, -webkit-backdrop-filter 0.9s ease;
}
/* GLASSBOX, literally: while the box reads its subject the smoke
   clears, so the resolved still is actually visible through the glass.
   main.js mirrors the scan state onto #stage. */
#stage.subject-scanning .cube-face,
#stage.subject-analyzed .cube-face {
  backdrop-filter: blur(0px);
  -webkit-backdrop-filter: blur(0px);
}
/* blur(0px) is still a backdrop ROOT — the compositor keeps snapshotting and
   re-filtering the region behind all 18 faces for a zero-radius blur. Once the
   0.9s transition has landed there is nothing left to animate, so hand it the
   one value that actually releases the work. main.js adds .faces-clear when
   --face-fill has reached 0, i.e. when the glass is already invisible. */
#stage.faces-clear .cube-face {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: none;
}
#stage.subject-scanning .cube-face::before,
#stage.subject-analyzed .cube-face::before {
  opacity: calc(var(--face-fill) * 0.5);
}
/* Touch screens never had the blur (Android compositing hazard) —
   keep it that way in every scan state */
@media (pointer: coarse) {
  #stage.subject-scanning .cube-face,
  #stage.subject-analyzed .cube-face {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}
/* Smoked-glass panel fill — separated from the border so the camera can
   drop the panels to perfect transparency while edges linger a beat. */
.cube-face::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg,
    rgba(255, 255, 255, 0.10) 0%,
    rgba(255, 255, 255, 0.02) 38%,
    rgba(13, 15, 22, 0.42) 100%);
  opacity: var(--face-fill);
}
/* Sharp ice refraction glint along the top edge of each panel */
.cube-face::after {
  content: "";
  position: absolute;
  top: 0;
  left: 8%;
  width: 84%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.8), transparent);
  opacity: calc(0.6 * var(--face-edge));
}

.f-front  { transform: translateZ(calc(var(--cube) / 2)); }
.f-back   { transform: rotateY(180deg) translateZ(calc(var(--cube) / 2)); }
.f-right  { transform: rotateY(90deg)  translateZ(calc(var(--cube) / 2)); }
.f-left   { transform: rotateY(-90deg) translateZ(calc(var(--cube) / 2)); }
.f-top    { transform: rotateX(90deg)  translateZ(calc(var(--cube) / 2)); }
.f-bottom { transform: rotateX(-90deg) translateZ(calc(var(--cube) / 2)); }

/* Nested glass structure — scaled copies of the shell, edges only */
.cube-nest {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: scale3d(var(--nest), var(--nest), var(--nest));
}
.cube-nest .cube-face {
  border-color: rgb(var(--c-edge-rgb) / calc(0.18 * var(--face-edge)));
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.cube-nest .cube-face::before { content: none; }
.cube-nest .cube-face::after { opacity: calc(0.3 * var(--face-edge)); }

/* Touch devices: six stacked backdrop-filters are a known Android Chrome
   compositing hazard (layers render black or vanish, which killed the cube
   and the field behind it on phones). The blur is nearly invisible at
   phone sizes anyway; the borders and fills carry the look. */
@media (pointer: coarse) {
  .cube-face {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* Internal quantum core — the engine warming up */
.cube-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 52%;
  height: 52%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 112, 67, 0.95) 0%,
    rgba(255, 87, 34, 0.38) 42%,
    transparent 70%);
  filter: blur(13px);
  opacity: var(--core-o);
  animation: core-pulse 3.8s ease-in-out infinite;
}
.cube-core-dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: #FFD9CC;
  box-shadow: 0 0 18px 6px rgba(255, 87, 34, 0.9);
}

/* ── Kevin in the box: the coin-spin face at the cube's core ──── */

/* Hidden on purpose: the drifting portrait tile kept crossing the hero
   headline and sub, and a moving photo behind live copy is unreadable copy.
   The target-lock reticle goes with it — #face-hud sizes and positions itself
   from cubeMe.getBoundingClientRect() every frame, so leaving it on would peg
   it to a 0x0 rect in the top-left corner and print the dossier text there.
   Everything below is left intact so this is a two-line revert. The drift loop
   in main.js still runs against the hidden node; say the word and it comes out
   with the markup. */
#cube-me,
#face-hud { display: none; }

#cube-me {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--cube) * 0.36);
  aspect-ratio: 1 / 1;
  /* main.js appends the 3D drift to this centering transform each frame */
  transform: translate(-50%, -50%);
  transform-style: preserve-3d;
  perspective: 700px;
  /* Rides the core glow: fully there in the hero, dissolved by the time
     the vault graph owns the center of the screen */
  opacity: var(--core-o, 1);
  pointer-events: none;
  will-change: transform;
  z-index: 2;
  /* The growth on identify (scanning → analyzed) is NOT here: it folds into
     the per-frame transform main.js writes (see meScale in main.js). The
     standalone `scale` property is silently dropped on an element that already
     carries a `transform`, and a CSS transform: scale() would be clobbered by
     that same per-frame rewrite — so the scale rides inside it, which also
     grows the element's box so the target-lock reticle tracks it. */
}
/* Static pass-through wrappers — the card no longer spins; main.js
   billboards it flat to the viewer while it drifts */
.cm-spin,
.cm-tumble {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}
/* The surveillance still: a dark monitor tile in BOTH themes — the
   reference aesthetic is a wall of CCTV crops, and a dark tile is what
   pops on the light page anyway. Pre-scan the feed is defocused so the
   subject stays unidentifiable; the scan resolves the focus and draws
   the landmark mesh over the face. */
.cm-card {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  background: #0D1017;
  border: 1px solid rgb(255 255 255 / 0.55);
  box-shadow:
    0 14px 30px rgba(0, 0, 0, 0.4),
    0 0 20px rgba(255, 87, 34, 0.14);
}
.cm-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
  -webkit-user-drag: none;
  /* Unidentified: heavy defocus; scale hides the blur's soft edges */
  filter: blur(9px) saturate(0.6) brightness(0.92);
  transform: scale(1.08);
  transition: filter 1.1s ease 0.35s, transform 1.1s ease 0.35s;
}
#cube-me.is-scanning .cm-card img,
#cube-me.is-analyzed .cm-card img {
  filter: none;
  transform: scale(1);
}
/* On file: the feed keeps a low-grade archival glitch forever. The
   glitch windows are ~0.1% wide so linear interpolation reads as
   an abrupt signal fault, no steps() needed. */
#cube-me.is-analyzed .cm-card img {
  animation: cm-glitch 6.4s linear infinite;
}
@keyframes cm-glitch {
  0%, 40.9%, 43.5%, 75.9%, 77.1%, 100% { transform: scale(1); filter: none; }
  41% {
    transform: scale(1) translateX(1.5px);
    filter: drop-shadow(-2px 0 0 rgba(255, 45, 85, 0.55))
            drop-shadow(2px 0 0 rgba(0, 229, 255, 0.55));
  }
  42.4% { transform: scale(1) translateX(-1px); filter: hue-rotate(18deg); }
  76% { transform: scale(1.015) translateY(-1px); filter: saturate(1.5) contrast(1.08); }
}

/* CCTV texture: scanline stripes + a soft monitor vignette */
.cm-scanlines {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(130% 130% at 50% 8%, transparent 58%, rgba(0, 0, 0, 0.38) 100%),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 3px);
  opacity: 0.75;
}

/* Feed label, reference-style: M/xx in the tile corner */
.cm-id {
  position: absolute;
  left: 4%;
  top: 4%;
  padding: 1px 4px;
  font-family: "JetBrains Mono", monospace;
  font-size: 6.5px;
  font-weight: 500;
  letter-spacing: 0.12em;
  color: rgb(255 255 255 / 0.85);
  background: rgba(13, 16, 23, 0.55);
  border: 1px solid rgb(255 255 255 / 0.25);
}

/* Landmark mesh: hidden until the scan, then stroke-drawn in three
   passes (outline → features → triangulation) and kept on file with
   an occasional flicker */
.cm-mesh {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: rgb(255 255 255 / 0.95);
  opacity: 0;
  transition: opacity 0.6s ease;
}
#cube-me.is-scanning .cm-mesh { opacity: 1; transition: none; }
/* After the read the scaffolding lifts — the data stays, the mesh goes */
#cube-me.is-analyzed .cm-mesh { opacity: 0; transition-delay: 0.25s; }
.cm-mesh path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
#cube-me.is-scanning .cm-mesh path { animation: cm-draw 0.9s ease-out forwards; }
#cube-me.is-scanning .g-feat path { animation-delay: 0.3s; }
#cube-me.is-scanning .g-tri path { animation-delay: 0.55s; }
#cube-me.is-analyzed .cm-mesh path { stroke-dashoffset: 0; }
@keyframes cm-draw { to { stroke-dashoffset: 0; } }
.cm-dots {
  opacity: 0;
  transition: opacity 0.4s ease 0.8s;
}
#cube-me.is-scanning .cm-dots,
#cube-me.is-analyzed .cm-dots { opacity: 0.55; }
/* ── Target-lock HUD: the reticle that hunts the cutout ──────────
   Screen-space sibling of the 3D rig: main.js eases this layer onto
   #cube-me's projected rect every frame, so the reticle visibly
   chases the target. Cursor proximity (or the periodic sweep on
   touch screens) trips .is-locked; the mono type is diegetic — this
   is an instrument, same device family as the deploy terminal. */

#face-hud {
  position: absolute;
  left: 0;
  top: 0;
  width: 130px;
  height: 130px;
  z-index: 3;
  color: rgb(var(--c-ice-rgb) / 0.5);
  opacity: calc(var(--core-o, 1) * 0.92);
  pointer-events: none;
  will-change: transform;
}
#face-hud.is-off { display: none; }
/* Scanning runs hot in quantum orange; once analyzed the chrome cools
   to clinical archival ice (theme-aware) while tag + cross keep the ember */
#face-hud.is-scanning { color: var(--c-q2); }
#face-hud.is-analyzed { color: rgb(var(--c-ice-rgb) / 0.8); }
#face-hud.is-analyzed .fh-tag,
#face-hud.is-analyzed .fh-cross { color: var(--c-q2); }
[data-theme="light"] #face-hud { color: rgb(15 23 42 / 0.55); }
[data-theme="light"] #face-hud.is-scanning { color: var(--c-q1); }
[data-theme="light"] #face-hud.is-analyzed .fh-tag,
[data-theme="light"] #face-hud.is-analyzed .fh-cross { color: var(--c-q1); }

.fh-frame {
  position: absolute;
  inset: 0;
  animation: fh-breathe 3.6s ease-in-out infinite;
}
/* The clamp: brackets bite in the instant the scan begins */
#face-hud.is-scanning .fh-frame,
#face-hud.is-analyzed .fh-frame {
  animation: none;
  transform: scale(0.94);
}
@keyframes fh-breathe {
  0%, 100% { transform: scale(1.02); }
  50% { transform: scale(1.09); }
}

.fh-corner {
  position: absolute;
  width: 17%;
  height: 17%;
  border: 0 solid currentColor;
}
.fh-tl { left: 0; top: 0; border-width: 1.5px 0 0 1.5px; }
.fh-tr { right: 0; top: 0; border-width: 1.5px 1.5px 0 0; }
.fh-bl { left: 0; bottom: 0; border-width: 0 0 1.5px 1.5px; }
.fh-br { right: 0; bottom: 0; border-width: 0 1.5px 1.5px 0; }

.fh-ring {
  position: absolute;
  inset: -9%;
  border: 1px dashed currentColor;
  border-radius: 50%;
  opacity: 0.5;
  animation: fh-orbit 16s linear infinite;
  transition: inset 0.5s ease, opacity 0.3s ease;
}
/* Duration change makes the orbit skip a beat on lock — reads as a
   glitchy re-sync, which is the point */
/* The orbit tightens onto the face once there's something to hold */
#face-hud.is-scanning .fh-ring { inset: 12%; opacity: 0.9; animation-duration: 2s; }
#face-hud.is-analyzed .fh-ring { inset: 12%; opacity: 0.7; animation-duration: 9s; }
@keyframes fh-orbit { to { transform: rotate(360deg); } }

.fh-cross {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.fh-cross::before, .fh-cross::after {
  content: '';
  position: absolute;
  background: currentColor;
}
.fh-cross::before { left: 50%; top: 0; width: 1.5px; height: 100%; margin-left: -0.75px; }
.fh-cross::after { top: 50%; left: 0; width: 100%; height: 1.5px; margin-top: -0.75px; }
#face-hud.is-scanning .fh-cross,
#face-hud.is-analyzed .fh-cross { opacity: 0.9; transform: scale(1); }

.fh-scan {
  position: absolute;
  left: 6%;
  right: 6%;
  top: 10%;
  height: 1.5px;
  background: linear-gradient(90deg, transparent, currentColor, transparent);
  opacity: 0;
}
/* The sweep loops for the whole analysis pass, then goes quiet */
#face-hud.is-scanning .fh-scan { animation: fh-scan 0.8s ease-in-out infinite; }
@keyframes fh-scan {
  0% { opacity: 0; top: 8%; }
  15% { opacity: 0.9; }
  85% { opacity: 0.9; }
  100% { opacity: 0; top: 90%; }
}

.fh-tag {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 13px;
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.26em;
  white-space: nowrap;
}
.fh-tag::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  animation: fh-blink 1.6s steps(2, jump-none) infinite;
}
.fh-tag b { font-weight: inherit; }
.fh-scanning, .fh-lock { display: none; }
#face-hud.is-scanning .fh-status,
#face-hud.is-analyzed .fh-status { display: none; }
#face-hud.is-scanning .fh-scanning {
  display: inline;
  animation: fh-flicker 0.6s steps(5, jump-none) infinite;
}
#face-hud.is-analyzed .fh-lock {
  display: inline;
  animation: fh-flicker 0.36s steps(5, jump-none) 1;
}
#face-hud.is-scanning .fh-tag::before,
#face-hud.is-analyzed .fh-tag::before { animation-duration: 0.5s; }
@keyframes fh-blink { 50% { opacity: 0.15; } }
@keyframes fh-flicker {
  0% { opacity: 0; }
  40% { opacity: 1; }
  60% { opacity: 0.2; }
  100% { opacity: 1; }
}

/* The dossier: live ledger + drift telemetry, revealed line by line */
.fh-data {
  position: absolute;
  left: 100%;
  top: 4%;
  margin-left: 17px;
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  line-height: 2.05;
  white-space: nowrap;
}
.fh-data em {
  display: block;
  font-style: normal;
  opacity: 0;
  transform: translateX(-7px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
#face-hud.is-analyzed .fh-data em { opacity: 0.92; transform: none; }
#face-hud.is-analyzed .fh-data em:nth-child(2) { transition-delay: 0.07s; }
#face-hud.is-analyzed .fh-data em:nth-child(3) { transition-delay: 0.14s; }
#face-hud.is-analyzed .fh-data em:nth-child(4) { transition-delay: 0.21s; }
#face-hud.is-analyzed .fh-data em:nth-child(5) { transition-delay: 0.28s; }

/* On file: the tile runs a touch hotter */
#cube-me.is-analyzed .cm-card {
  box-shadow:
    0 14px 30px rgba(0, 0, 0, 0.4),
    0 0 26px rgba(255, 87, 34, 0.3);
}

/* Phones: the face is ~50px wide — keep the frame + tag, shed the
   dossier column so it can never poke past the viewport edge */
@media (max-width: 767px) {
  .fh-data { display: none; }
  .fh-tag { margin-top: 10px; font-size: 8px; }
}

/* ── Graph node array ─────────────────────────────────────────── */

#graph-canvas, #graph-hubs { position: absolute; inset: 0; }
/* Canvas is a replaced element: inset alone won't stretch it */
/* pan-y keeps page scrolling alive on touch: vertical swipes scroll,
   horizontal drags rotate, two-finger pinch zooms the graph */
#graph-canvas { width: 100%; height: 100%; touch-action: pan-y; }
#graph-hubs { touch-action: pan-y; }

/* The whole layer reads as grabbable while the x-ray holds */
#stage.graph-live #graph-hubs { cursor: grab; }

/* The canvas becomes a drag/zoom surface while the x-ray holds */
#stage.graph-live #graph-canvas {
  pointer-events: auto;
  cursor: grab;
}
#stage.graph-live #graph-canvas.is-dragging { cursor: grabbing; }

/* Depth rail — the four layers as a clickable ladder */
#depth-rail {
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
#depth-rail button {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 9px 6px;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(148, 163, 184, 0.65);
  transition: color 0.25s ease;
}
#depth-rail button::after {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid rgba(148, 163, 184, 0.55);
  background: transparent;
  transition: all 0.25s ease;
  flex: none;
}
#depth-rail button:hover { color: var(--c-ice); }
#depth-rail button:hover::after { border-color: var(--c-ice); }
#depth-rail button.is-active { color: var(--c-ice); }
#depth-rail button.is-active::after {
  background: var(--c-q1);
  border-color: var(--c-q2);
  box-shadow: 0 0 10px rgba(255, 87, 34, 0.8);
}
#depth-rail button:focus-visible { outline: 1px solid var(--c-q1); outline-offset: 2px; border-radius: 6px; }
@media (max-width: 767px) {
  #depth-rail button span { display: none; } /* dots only on small screens */
}

/* X-ray interaction hints — quiet glass pills */
.hint-chips { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.hint-chips li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: rgb(var(--c-nav-rgb));
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.04);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 999px;
  padding: 7px 15px;
  width: fit-content;
}
.chip-ico { width: 11px; height: 11px; color: var(--c-q2); flex: none; }
.zoom-chip { padding-right: 8px; }
.zoom-chip button {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgb(255 87 34 / 0.35);
  background: rgb(255 87 34 / 0.08);
  color: var(--c-q2);
  border-radius: 50%;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: all 0.25s ease;
}
.zoom-chip button + button { margin-left: -4px; }
.zoom-chip button:hover {
  color: #FFFFFF;
  background: var(--c-q1);
  border-color: var(--c-q2);
}
[data-theme="light"] .zoom-chip button:hover { color: #FFFFFF; }

.hub-node {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 10px;
  background: none;
  border: 0;
  cursor: pointer;
  pointer-events: none; /* armed only during the x-ray phase via #stage.graph-live */
  will-change: transform, opacity;
}
#stage.graph-live .hub-node { pointer-events: auto; }
.hub-node:focus-visible { outline: 1px solid var(--c-q1); outline-offset: 4px; }

/* HUD reticle — hovering a node paints a targeting frame that snaps in
   and locks, so the graph reads as instrumentation rather than decoration.
   Drawn on the button so it never disturbs the chip's own layout. */
.hub-node::before,
.hub-node::after {
  content: "";
  position: absolute;
  top: 10px;
  left: 50%;
  width: 42px;
  height: 42px;
  margin-left: -21px;
  margin-top: -13.5px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}
.hub-node[data-core="true"]::before,
.hub-node[data-core="true"]::after { width: 50px; height: 50px; margin-left: -25px; margin-top: -15px; }
/* Outer frame: four corner brackets, drawn with corner-only gradients */
.hub-node::before {
  background:
    linear-gradient(var(--c-q2), var(--c-q2)) 0 0 / 11px 1.6px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 0 0 / 1.6px 11px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 100% 0 / 11px 1.6px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 100% 0 / 1.6px 11px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 0 100% / 11px 1.6px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 0 100% / 1.6px 11px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 100% 100% / 11px 1.6px no-repeat,
    linear-gradient(var(--c-q2), var(--c-q2)) 100% 100% / 1.6px 11px no-repeat;
  transform: scale(1.85) rotate(-12deg);
}
/* Inner ring: closes a beat later, the "lock" */
.hub-node::after {
  border: 1px solid rgb(255 87 34 / 0.5);
  border-radius: 50%;
  transform: scale(0.35);
}
.hub-node:hover::before,
.hub-node:focus-visible::before { opacity: 1; transform: scale(1) rotate(0deg); }
.hub-node:hover::after,
.hub-node:focus-visible::after {
  opacity: 1;
  transform: scale(1);
  transition-delay: 0.08s;
  animation: hud-lock 1.9s ease-in-out 0.42s infinite;
}
@keyframes hud-lock {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.14); opacity: 0.45; }
}

/* Node chips — square glass cubes in pure brand orange, the same
   gradient as the CTA and headline highlights (no off-hue shading) */
.hub-chip {
  width: 15px;
  height: 15px;
  border-radius: 3px;
  background:
    linear-gradient(160deg, rgb(255 255 255 / 0.3) 0%, transparent 40%),
    linear-gradient(135deg, var(--c-q2), var(--c-q1));
  box-shadow:
    0 0 14px rgba(255, 87, 34, 0.8),
    0 0 42px rgba(255, 87, 34, 0.35),
    inset 0 0 0 1px rgb(255 255 255 / 0.45);
  animation: chip-pulse 3.2s ease-in-out infinite;
}
.hub-node[data-core="true"] .hub-chip {
  width: 20px;
  height: 20px;
  animation-duration: 2.4s;
}
.hub-node:hover .hub-chip, .hub-node:focus-visible .hub-chip {
  box-shadow:
    0 0 22px rgba(255, 87, 34, 1),
    0 0 68px rgba(255, 87, 34, 0.5),
    inset 0 0 0 1px rgb(255 255 255 / 0.85);
}

.hub-tag {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 9.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--c-data);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9);
  transition: color 0.25s ease;
}
.hub-node:hover .hub-tag, .hub-node:focus-visible .hub-tag { color: var(--c-ice); }

/* ── Vault slideout — the node briefing rides in from the right ──
   Content-rich (points + shipped deliverables + CTA), so unlike the old
   hover modal it stays open until dismissed and is fully interactive. */
#node-panel {
  position: fixed;
  top: 76px;    /* clear of the header */
  right: 0;
  bottom: 72px; /* clear of the live scoreboard */
  width: min(430px, calc(100vw - 28px));
  z-index: 60;
  display: flex;
  flex-direction: column;
  padding: 30px 28px 26px;
  border: 0;
  border-left: 1px solid rgba(255, 87, 34, 0.4);
  border-radius: 24px 0 0 24px;
  background: rgb(var(--c-bg-rgb) / 0.86);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  pointer-events: none;
  opacity: 0;
  /* Delayed visibility flip keeps the slide animation intact while
     removing the closed panel's controls from the tab order and AT tree */
  visibility: hidden;
  transform: translateX(calc(100% + 48px));
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.32s ease, visibility 0s linear 0.42s;
  box-shadow:
    -28px 0 90px rgba(0, 0, 0, 0.6),
    0 0 44px rgba(255, 87, 34, 0.12);
}
#node-panel.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateX(0);
  pointer-events: auto;
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.32s ease, visibility 0s;
}

#panel-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.14);
  border-radius: 50%;
  background: rgb(var(--c-ice-rgb) / 0.05);
  color: var(--c-data);
  cursor: pointer;
  transition: all 0.25s ease;
}
#panel-close svg { width: 13px; height: 13px; }
#panel-close:hover { color: var(--c-ice); border-color: var(--c-q2); }

#panel-list li {
  display: flex;
  gap: 10px;
  color: var(--c-data);
  font-size: 13px;
  line-height: 1.6;
}
#panel-list li::before { content: "▸"; color: var(--c-q2); flex: none; }

/* The proof rack: what this node has shipped, linked to Proof of Work */
.panel-ship-head {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 9.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--c-q2);
}
.ship-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid rgb(var(--c-smoke-rgb) / 0.9);
  border-radius: 12px;
  background: rgb(var(--c-ice-rgb) / 0.03);
  transition: border-color 0.25s ease, background 0.25s ease;
}
a.ship-item:hover {
  border-color: rgba(255, 87, 34, 0.6);
  background: rgb(255 87 34 / 0.06);
}
.ship-type {
  font-family: "JetBrains Mono", monospace;
  font-weight: 500;
  font-size: 8.5px;
  letter-spacing: 0.14em;
  color: var(--c-q2);
  border: 1px solid rgb(255 87 34 / 0.4);
  border-radius: 999px;
  padding: 2px 8px;
  flex: none;
}
.ship-label {
  flex: 1;
  color: var(--c-ice);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
}
.ship-item i {
  font-style: normal;
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--c-q2);
  flex: none;
}
.ship-item.is-soon { opacity: 0.62; }
.ship-item.is-soon i { color: rgb(var(--c-data-rgb) / 0.8); font-size: 8.5px; }
.ship-empty {
  color: rgb(var(--c-data-rgb) / 0.85);
  font-size: 12px;
  line-height: 1.6;
  font-style: italic;
}
#node-panel .panel-cta {
  margin-top: auto;
  padding-top: 22px;
}

/* While the slideout is open the depth rail steps aside */
body.node-inspecting #depth-rail {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
#depth-rail { transition: opacity 0.25s ease; }

/* ── Layer 3 · workforce swap rows ────────────────────────────── */

.swap-row {
  /* tab-button reset */
  display: grid;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  grid-template-columns: minmax(128px, 158px) auto 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 16px 12px;
  border-bottom: 1px solid var(--c-smoke);
  border-left: 2px solid transparent;
  border-radius: 0 12px 12px 0;
  transition: background 0.3s ease, border-color 0.3s ease;
}
.swap-row:hover {
  background: rgba(255, 255, 255, 0.02);
  border-bottom-color: rgba(255, 87, 34, 0.55);
}
.swap-row:focus-visible { outline: 1px solid var(--c-q1); outline-offset: 2px; }
.swap-row.is-active {
  background: rgba(255, 255, 255, 0.03);
  border-left-color: var(--c-q1);
  border-bottom-color: rgba(255, 87, 34, 0.55);
}
.swap-row.is-active .swap-sys { color: var(--c-q2); }

.swap-old { display: flex; flex-direction: column; gap: 3px; }
/* Reads as body copy, not chrome: same ink and weight as every other
   description on the page. */
.swap-role {
  color: var(--c-read);
  font-size: 14px;
  font-weight: 500;
}
.swap-arrow {
  font-family: "JetBrains Mono", monospace;
  color: var(--c-q1);
  font-size: 13px;
}
/* Stage marker — ties each playbook row back to its layer in the
   section-02 vault graph (2A Research … 2D Scale) */
.swap-stage {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.2em;
  color: rgb(var(--c-data-rgb) / 0.85);
  margin-bottom: 4px;
}
.swap-row.is-active .swap-stage { color: var(--c-q2); }
.swap-sys {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--c-ice);
}
.swap-row:hover .swap-sys { color: var(--c-q2); }
.swap-new p {
  color: var(--c-read);
  font-weight: 500;
  font-size: 13.5px;
  line-height: 1.55;
  margin-top: 4px;
  max-width: 34ch;
}

/* ── Layer 3 · terminal array ─────────────────────────────────── */

/* macOS-style terminal window, themed for both modes */
:root {
  --term-bg: #0D0F14;
  --term-bar: #1A1D24;
  --term-border: #262B36;
  --term-cmd: #FFFFFF;
  --term-dim: rgba(148, 163, 184, 0.82);
  --term-accent: #FF7043;
  --term-ok: #7EE2A8;
  --term-user-bubble: #262B36;
  --term-row: rgba(148, 163, 184, 0.08);
  --term-shadow: 0 18px 44px rgb(0 0 0 / 0.4);
}
[data-theme="light"] {
  --term-bg: #FCFCFD;
  --term-bar: #E9EAEE;
  --term-border: #D5DAE2;
  --term-cmd: #0B0C10;
  --term-dim: #5B6779;
  --term-accent: #D84315;
  --term-ok: #1E9E4A;
  --term-user-bubble: #E9EAEE;
  --term-row: rgba(15, 23, 42, 0.05);
  --term-shadow: 0 14px 34px rgb(15 23 42 / 0.14);
}

.term-window {
  border: 1px solid var(--term-border);
  background: var(--term-bg);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--term-shadow);
}
.term-bar {
  position: relative;
  display: flex;
  align-items: center;
  padding: 11px 14px;
  background: var(--term-bar);
  border-bottom: 1px solid var(--term-border);
}
.term-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 8px;
  flex: none;
}
.term-dot-r { background: #FF5F57; }
.term-dot-y { background: #FEBC2E; }
.term-dot-g { background: #28C840; }
#term-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  color: var(--term-dim);
  white-space: nowrap;
}

.term-body {
  height: 424px;
  padding: 14px 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 12.5px;
  line-height: 1.5;
}

/* AI turns: mini glassbox avatar + plain text (Claude-style) */
.msg { display: flex; gap: 9px; align-items: flex-start; }
.msg p { margin: 0; }
.msg-ai p { color: var(--term-cmd); }
.msg-ai.is-final p { font-weight: 600; }
.chat-cube {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  margin-top: 2px;
  flex: none;
  background:
    linear-gradient(160deg, rgb(255 255 255 / 0.3) 0%, transparent 40%),
    linear-gradient(135deg, var(--c-q2), var(--c-q1));
  box-shadow: 0 0 8px rgba(255, 87, 34, 0.5);
}

/* The visitor's stand-in: a right-aligned bubble */
.msg-user { justify-content: flex-end; }
.msg-user p {
  background: var(--term-user-bubble);
  color: var(--term-cmd);
  border-radius: 12px 12px 3px 12px;
  padding: 7px 13px;
  max-width: 85%;
}

/* Thinking… with living dots */
.msg-think p { color: var(--term-dim); font-style: italic; }
.msg-think .dots::after {
  content: '';
  animation: think-dots 1.2s steps(1) infinite;
}
@keyframes think-dots {
  0%   { content: ''; }
  25%  { content: '.'; }
  50%  { content: '..'; }
  75%  { content: '...'; }
}

/* Option chips the AI offers — one gets picked for the visitor */
.chat-options { display: flex; flex-wrap: wrap; gap: 6px; padding-left: 23px; }
.chat-opt {
  border: 1px solid var(--term-border);
  color: var(--term-dim);
  border-radius: 999px;
  padding: 5px 13px;
  font-size: 11.5px;
  font-weight: 500;
  transition: all 0.3s ease;
}
.chat-opt.is-picked {
  background: linear-gradient(135deg, var(--c-q2), var(--c-q1));
  border-color: transparent;
  color: #FFFFFF;
}
.chat-options.is-spent .chat-opt:not(.is-picked) { opacity: 0.4; }

/* Task rows: spinner while running, check when done */
.chat-action {
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--term-row);
  border-radius: 9px;
  padding: 6px 11px;
  margin-left: 23px;
  color: var(--term-dim);
}
.chat-action.is-done { color: var(--term-cmd); }
.chat-action p { margin: 0; font-size: 12px; }
.chat-spin {
  width: 12px;
  height: 12px;
  flex: none;
  border-radius: 50%;
  border: 1.5px solid rgb(255 87 34 / 0.25);
  border-top-color: var(--term-accent);
  animation: chat-spin 0.9s linear infinite;
}
.chat-check {
  color: var(--term-ok);
  font-weight: 700;
  flex: none;
}
@keyframes chat-spin { to { transform: rotate(360deg); } }

/* ── Layer 3 · the deliverable, rendered inside the chat ──────────
   The run's output lands in the feed itself, small, as though it were
   just generated — rather than in a panel below that outgrows the pin. */

.chat-art {
  margin-left: 23px;
  border: 1px solid var(--term-border);
  border-radius: 10px;
  background: var(--term-row);
  padding: 8px 9px 9px;
  animation: art-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes art-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
.ca-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 7px;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--term-dim);
}
.ca-head span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ca-head b { flex: none; font-weight: 500; color: var(--term-accent); }

/* 2A — swipe-file rows */
.ca-voc { display: flex; flex-direction: column; gap: 5px; }
.ca-voc li { display: grid; grid-template-columns: 40px 1fr; gap: 7px; align-items: baseline; }
.ca-voc q {
  display: block;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--term-cmd);
  quotes: "\201C" "\201D";
}
.ca-voc q b { color: var(--term-accent); font-weight: 600; }
.voc-tag {
  font-family: "JetBrains Mono", monospace;
  font-size: 7px;
  font-style: normal;
  letter-spacing: 0.08em;
  text-align: center;
  border-radius: 3px;
  padding: 2px 0;
  background: rgb(var(--c-ice-rgb) / 0.08);
  color: var(--term-dim);
}
.voc-tag.t-pain, .voc-tag.t-fear { color: var(--term-accent); background: rgb(255 87 34 / 0.14); }

/* 2C — the generated ad set */
.ca-ads { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; }
/* On a phone the feed is too narrow for four: at ~73px a tile's hook drops
   under 7px and stops being readable. Two at full size still shows the
   system, and the card header keeps stating the real set size. */
@media (max-width: 640px) {
  .ca-ads { grid-template-columns: repeat(2, 1fr); gap: 6px; }
  .ca-ads .gen-tile:nth-child(n + 3) { display: none; }
}
.gen-tile { position: relative; }
/* Tiles resolve one at a time: shimmer first, then the render fades up */
.gen-tile .ad-canvas > * { transition: opacity 0.4s ease; }
.gen-tile.is-rendering .ad-canvas > * { opacity: 0; }
.gen-tile.is-rendering .ad-canvas::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(100deg,
    rgb(255 255 255 / 0.03) 30%, rgb(255 112 67 / 0.22) 50%, rgb(255 255 255 / 0.03) 70%);
  background-size: 260% 100%;
  animation: gen-shimmer 0.9s linear infinite;
}
@keyframes gen-shimmer {
  from { background-position: 130% 0; }
  to   { background-position: -130% 0; }
}

/* 2D — the triage table */
.ca-dash {
  width: 100%;
  border-collapse: collapse;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  letter-spacing: 0.02em;
}
.ca-dash th, .ca-dash td { padding: 3.5px 0; text-align: right; white-space: nowrap; }
.ca-dash th[scope="row"] { text-align: left; font-weight: 400; color: var(--term-cmd); }
.ca-dash td { color: var(--term-dim); }
.ca-dash tr + tr th, .ca-dash tr + tr td { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.5); }
.v-up, .v-hold, .v-cut { font-weight: 500; font-size: 8.5px; letter-spacing: 0.04em; }
.v-up { color: var(--term-ok); }
.v-hold { color: var(--term-dim); }
.v-cut { color: var(--term-accent); }

/* — 2B · the site it built, in a browser frame — */
.mini-browser {
  border: 1px solid var(--term-border);
  border-radius: 9px;
  overflow: hidden;
  background: var(--term-bg);
}
.mb-bar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 7px 10px;
  background: var(--term-bar);
  border-bottom: 1px solid var(--term-border);
}
.mb-bar > i { width: 7px; height: 7px; border-radius: 50%; background: rgb(var(--c-data-rgb) / 0.4); }
.mb-url {
  margin-left: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.1em;
  color: var(--term-dim);
}
/* A miniature of the page you're on — deliberately hand-drawn rather
   than a screenshot, so it stays crisp and follows the active theme. */
.mb-view {
  position: relative;
  height: 108px;
  background: radial-gradient(120% 90% at 50% 115%, rgb(255 87 34 / 0.16), transparent 60%), #0B0C10;
  overflow: hidden;
}
.mb-mark {
  position: absolute;
  inset-inline: 0;
  top: 16px;
  text-align: center;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 26px;
  letter-spacing: 0.12em;
  color: rgb(255 255 255 / 0.06);
}
.mb-cube {
  position: absolute;
  left: 50%;
  top: 30px;
  width: 46px;
  height: 46px;
  transform: translateX(-50%);
  filter: drop-shadow(0 0 9px rgb(255 87 34 / 0.55));
}
.mb-line {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  height: 5px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.5);
}
.mb-line.l1 { top: 88px; width: 108px; }
.mb-line.l2 { top: 98px; width: 76px; background: rgb(255 255 255 / 0.28); }
.mb-line.l3 { top: 108px; width: 90px; background: rgb(255 255 255 / 0.16); }
.mb-cta {
  position: absolute;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  width: 54px;
  height: 11px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--c-q2), var(--c-q1));
}
.mb-scoreboard {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 8px;
  padding: 4px 0;
  background: rgb(0 0 0 / 0.55);
  border-top: 1px solid rgb(255 255 255 / 0.09);
}
.mb-scoreboard i { width: 22px; height: 3px; border-radius: 999px; background: rgb(255 255 255 / 0.3); }
.mb-scoreboard i:first-child { background: rgb(255 112 67 / 0.8); }


/* — 2C · the static ad set — */
.ad-canvas {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: 8px;
  overflow: hidden;
  background: #0B0C10;
  /* The ad art is authored dark; it must not invert with the page */
  color-scheme: dark;
  /* Every element inside is sized in cqw, so the creative keeps its real
     proportions whether the column is 700px or a phone's 320px. */
  container-type: inline-size;
}
.ad-canvas > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Scrim so the burnt-in headline clears the photo underneath it */
.ad-canvas::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(0 0 0 / 0.66) 0%, rgb(0 0 0 / 0.12) 46%, rgb(0 0 0 / 0.72) 100%);
}
.ad-canvas > :not(img) { position: absolute; z-index: 1; }
/* Zone 1 · audience callout pill — mirrors the landing page's callout */
.ad-pill {
  top: 3cqw;
  left: 3cqw;
  right: 3cqw;
  /* Ad copy is persuasion, not machine output — sans, per the evidence-only
     mono diet (fix 4). */
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 2.5cqw;
  letter-spacing: 0.08em;
  color: #F1D9A8;
  border: 1px solid rgb(176 137 71 / 0.75);
  border-radius: 999px;
  padding: 1.2cqw 2.4cqw;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Zone 2 · the two-line hook */
.ad-hook {
  top: 12cqw;
  left: 4cqw;
  right: 4cqw;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 9.2cqw;
  line-height: 1.02;
  letter-spacing: -0.01em;
  color: #FFFFFF;
  text-shadow: 0 0.6cqw 3cqw rgb(0 0 0 / 0.65);
}
/* House signature: line one carries the accent, line two stays white */
.ad-hook i { font-style: normal; color: var(--c-q2); }
/* Zone 3 · the reframe — moves the blame off the reader */
.ad-reframe {
  bottom: 13cqw;
  left: 4cqw;
  right: 4cqw;
  font-size: 3.3cqw;
  line-height: 1.35;
  color: rgb(255 255 255 / 0.92);
  text-shadow: 0 0.3cqw 2cqw rgb(0 0 0 / 0.7);
}
/* Zone 6 · the CTA pill */
.ad-cta {
  bottom: 3.6cqw;
  left: 50%;
  transform: translateX(-50%);
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 2.9cqw;
  letter-spacing: 0.08em;
  color: #FFFFFF;
  background: linear-gradient(135deg, var(--c-q2), var(--c-q1));
  border-radius: 999px;
  padding: 1.8cqw 4cqw;
  white-space: nowrap;
}
@container (max-width: 170px) {
  .ad-pill, .ad-reframe, .ad-cta { display: none; }
  /* Sized so the longest hook line clears the tile without wrapping */
  .ad-hook { top: auto; bottom: 6cqw; font-size: 9.4cqw; line-height: 1.06; }
}

.v-up, .v-hold, .v-cut { font-weight: 500; font-size: 8.5px; letter-spacing: 0.06em; }
.v-up { color: var(--term-ok); }
.v-hold { color: rgb(var(--c-data-rgb) / 0.9); }
.v-cut { color: var(--term-accent); }
[data-theme="light"] .v-up { color: #157F3A; }

/* The transparency line under the whole panel — load-bearing for a
   site whose entire pitch is that the numbers are real. */
.engine-honesty {
  font-size: 12.5px;
  line-height: 1.6;
  font-weight: 500;
  color: var(--c-read);
  border-left: 2px solid rgb(255 87 34 / 0.5);
  padding-left: 11px;
}

/* ── The beach behind the machine ──────────────────────────────────
   Runs the full height of the pin down the terminal's flank, so he reads at
   size instead of being swallowed by the opaque panel sitting on him. The
   ::after paints the page colour back over every edge, which is why the
   feather follows the theme for free: --c-bg-rgb is already themed.
   The position override is load-bearing — `.engine-pin > *` forces every
   direct child to position: relative, which would drop this back into flow. */
.engine-pin > .beach-backdrop {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: min(54vw, 660px);
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.engine-pin > #engine-copy { z-index: 1; }
.beach-backdrop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The box and the source are both ~4:5, so cover crops barely 9% of the
     width and nothing vertically — the whole scene is on screen, and the
     y term here is inert. Biased left of centre to hold the water in frame. */
  object-position: 58% 50%;
  /* Muted well below the terminal's contrast — this is set dressing, and the
     chat feed on top of it still has to be the readable thing. */
  filter: saturate(0.86) contrast(0.95);
  opacity: 0.55;
  -webkit-user-drag: none;
}
.beach-backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Bite hard at the very edge and let go fast. An earlier, wider falloff on
     this side reached 44% in and quietly erased the water and the glass with
     it — the whole point of the shot. */
  background:
    linear-gradient(90deg, rgb(var(--c-bg-rgb)) 0%, rgb(var(--c-bg-rgb) / 0.5) 9%, rgb(var(--c-bg-rgb) / 0) 28%),
    linear-gradient(180deg, rgb(var(--c-bg-rgb)) 0%, rgb(var(--c-bg-rgb) / 0) 18%, rgb(var(--c-bg-rgb) / 0) 78%, rgb(var(--c-bg-rgb)) 100%);
}
/* On dark the photo is far brighter than the page, so the same opacity reads
   as a glowing rectangle. Drop it further and darken the source. */
:root[data-theme="dark"] .beach-backdrop img {
  opacity: 0.38;
  filter: saturate(0.7) contrast(0.9) brightness(0.78);
}
/* Stacked layout: the panel is full-width, so a flank crop has nowhere to go.
   Sit it behind the whole column instead, quieter, and let it bleed off-screen. */
@media (max-width: 1023px) {
  .engine-pin > .beach-backdrop {
    width: auto;
    left: 0;
    top: auto;
    height: 62svh;
    bottom: 0;
  }
  .beach-backdrop img { object-position: 62% 22%; opacity: 0.3; }
  .beach-backdrop::after {
    background:
      linear-gradient(180deg, rgb(var(--c-bg-rgb)) 0%, rgb(var(--c-bg-rgb) / 0) 34%),
      linear-gradient(90deg, rgb(var(--c-bg-rgb)) 0%, rgb(var(--c-bg-rgb) / 0) 26%, rgb(var(--c-bg-rgb) / 0) 74%, rgb(var(--c-bg-rgb)) 100%);
  }
  :root[data-theme="dark"] .beach-backdrop img { opacity: 0.22; }
}

/* ── Layer 4 · the stack ──────────────────────────────────────── */

.stack-card {
  border: 1px solid var(--c-smoke);
  /* Frosted: enough body to quiet the field behind the cards */
  background: rgb(var(--c-bg-rgb) / 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 18px;
  padding: 22px;
  transition: border-color 0.3s ease, background 0.3s ease, transform 0.3s ease;
}
.stack-card:hover {
  border-color: rgba(255, 87, 34, 0.5);
  background: rgb(var(--c-bg-rgb) / 0.82);
  transform: translateY(-3px);
}
.stack-logo {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(11, 12, 16, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}
.stack-logo svg { width: 20px; height: 20px; }
.stack-card h3 {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.03em;
  color: var(--c-ice);
  margin-top: 14px;
}
.stack-card > p {
  color: var(--c-data);
  font-size: 13px;
  line-height: 1.6;
  margin-top: 6px;
}
.stack-card .stack-role {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 112, 67, 0.85);
  margin-top: 12px;
}

/* ── Layer 5 · conversion ─────────────────────────────────────── */

/* Size and tracking are set here rather than left to the Tailwind text-[Npx]
   utilities in the markup: glassbox.css loads after the purged bundle, so at
   equal specificity these win, and the CTAs stay one readable size instead of
   five hand-tuned ones. 0.1em tracking was pulling the short all-lowercase
   labels apart at 12px — the words lost their shape. */
/* Type-preview change (fix 5): 16px minimum, tracking removed. Sentence-case
   CTA copy reads deadpan-confident at natural spacing; 0.045em at 15px was
   still pulling the short labels apart, and the click targets were small. */
.btn-quantum {
  background: linear-gradient(135deg, var(--c-cta-2), var(--c-cta-1));
  color: #FFFFFF;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0;
  border-radius: 999px;
  transition: box-shadow 0.3s ease, filter 0.3s ease, transform 0.15s ease;
}
/* The nav pill and the vault panel's CTA sit in tight chrome — they take the
   contrast and tracking fix, but stay compact. */
#site-header .btn-quantum,
#node-panel .btn-quantum { font-size: 14px; letter-spacing: 0; }
.btn-quantum:hover {
  box-shadow: 0 0 36px rgba(255, 87, 34, 0.55), 0 0 100px rgba(255, 87, 34, 0.22);
  filter: brightness(1.08);
}
.btn-quantum:active { transform: translateY(1px); }

/* Secondary CTA: quiet glass pill */
.btn-ghost {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.01em;
  color: rgb(var(--c-nav-rgb));
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.03);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 999px;
  padding: 13px 30px;
  transition: all 0.3s ease;
}
.btn-ghost:hover {
  color: var(--c-ice);
  border-color: rgba(255, 112, 67, 0.7);
  box-shadow: 0 0 22px rgba(255, 87, 34, 0.25);
}

/* Audience callout — solid elevated pill with the ember marker */
.eyebrow-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.14);
  background: var(--pill-bg);
  border-radius: 999px;
  padding: 9px 18px;
  box-shadow: 0 6px 18px rgb(0 0 0 / 0.25);
}
.eyebrow-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-q1);
  box-shadow: 0 0 8px rgba(255, 87, 34, 0.9);
  flex: none;
}

/* Highlight — a flat, solid quantum-orange rectangle. No skew,
   no glass, white text in both themes. */
.hl {
  position: relative;
  z-index: 0;
  white-space: nowrap;
  padding: 0.02em 0.16em;
  color: #FFFFFF;
}
.hl::before {
  content: "";
  position: absolute;
  inset: 0.09em -0.04em 0 -0.04em;
  background: linear-gradient(97deg, var(--c-q1) 0%, var(--c-q2) 100%);
  border-radius: 0.14em;
  z-index: -1;
}

/* Inverted monochrome highlight: ink pill in light mode, ice pill in dark.
   Tokens flip with the theme, so one rule serves both. */
.hl-ink {
  position: relative;
  z-index: 0;
  white-space: nowrap;
  padding: 0.02em 0.16em;
  color: var(--c-bg);
}
.hl-ink::before {
  content: "";
  position: absolute;
  inset: 0.09em -0.04em 0 -0.04em;
  background: var(--c-ice);
  border-radius: 0.14em;
  z-index: -1;
}

#cta-card { border-radius: 22px; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55); }

/* This headline sets inside the card's 478px column, not the page's, and at the
   section's 2.6rem "Watch me hit $1,000,000," misses that column by the width
   of its own comma — three lines, with "public" left alone on the last one.
   Same move as #engine-copy, for the same reason: a narrower column takes a
   narrower headline. 2.45rem clears the three-line break by 27px and still
   holds "or" down on the second line, where the sentence turns. */
@media (min-width: 768px) {
  #horizon .h-section { font-size: 2.45rem; }
}

/* Mini-course pricing card */
.price-card {
  position: relative;
  z-index: 2;
  text-align: center;
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: 22px;
  padding: 44px 32px 40px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45), 0 0 60px rgba(255, 87, 34, 0.07);
}

/* Pricing is the collection point for the ambient field. The canvas bends
   real particles into this reactor; these rings make the destination read
   even in a still frame. */
#pricing {
  isolation: isolate;
  --pricing-scale: 0.92;
  --pricing-vortex-opacity: 0.3;
}
#pricing > .max-w-2xl { position: relative; z-index: 2; }
.pricing-vortex {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 51%;
  width: min(1040px, 132vw);
  aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(var(--pricing-scale));
  opacity: var(--pricing-vortex-opacity);
  pointer-events: none;
  background:
    radial-gradient(circle at center, rgba(255, 112, 67, 0.22) 0 2%, rgba(255, 87, 34, 0.1) 9%, transparent 32%),
    repeating-conic-gradient(from 8deg, rgba(255, 112, 67, 0.11) 0 0.7deg, transparent 0.7deg 10deg);
  -webkit-mask-image: radial-gradient(circle, #000 0 47%, transparent 74%);
  mask-image: radial-gradient(circle, #000 0 47%, transparent 74%);
  transition: opacity 160ms linear, transform 160ms linear;
}
.pv-ring,
.pv-core,
.pv-beam {
  position: absolute;
  left: 50%;
  top: 50%;
}
.pv-ring {
  width: var(--ring-size);
  height: var(--ring-height);
  border: 1px solid rgba(255, 112, 67, 0.32);
  border-left-color: rgb(var(--c-ice-rgb) / 0.18);
  border-right-color: rgb(var(--c-ice-rgb) / 0.18);
  border-radius: 50%;
  transform: translate(-50%, -50%) rotate(var(--ring-tilt));
  box-shadow: inset 0 0 40px rgba(255, 87, 34, 0.08), 0 0 28px rgba(255, 87, 34, 0.08);
  animation: pricing-ring 9s linear infinite;
}
.pv-ring-1 { --ring-size: 32%; --ring-height: 13.5%; --ring-tilt: -8deg; animation-duration: 5s; }
.pv-ring-2 { --ring-size: 54%; --ring-height: 22.5%; --ring-tilt: 6deg; animation-duration: 8s; animation-direction: reverse; }
.pv-ring-3 { --ring-size: 78%; --ring-height: 33%; --ring-tilt: -3deg; animation-duration: 12s; }
.pv-core {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle at 42% 38%, #FFFFFF 0 4%, #FFD7C8 12%, #FF7043 34%, rgba(255, 87, 34, 0.12) 66%, transparent 72%);
  filter: blur(0.2px);
  box-shadow: 0 0 32px rgba(255, 87, 34, 0.75), 0 0 100px rgba(255, 87, 34, 0.38);
  animation: pricing-core 1.4s ease-in-out infinite;
}
.pv-beam {
  width: 70%;
  height: 1px;
  transform-origin: left center;
  background: linear-gradient(90deg, rgba(255, 112, 67, 0.72), transparent 68%);
  opacity: 0.35;
}
.pv-beam-a { transform: rotate(18deg) translateX(-4%); }
.pv-beam-b { transform: rotate(198deg) translateX(-4%); }
@keyframes pricing-ring {
  from { transform: translate(-50%, -50%) rotate(var(--ring-tilt)); }
  to { transform: translate(-50%, -50%) rotate(calc(var(--ring-tilt) + 360deg)); }
}
@keyframes pricing-core {
  0%, 100% { transform: translate(-50%, -50%) scale(0.88); opacity: 0.72; }
  50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
}
/* Course-overview table: lesson rows, value anchor, today price */
.price-table {
  text-align: left;
  border: 1px solid rgb(var(--c-smoke-rgb) / 0.8);
  border-radius: 16px;
  overflow: hidden;
}
.price-row {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 11px 18px;
}
.price-row + .price-row,
.price-total, .price-today { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.6); }
.price-num {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 11px;
  color: var(--c-q2);
}
.price-name {
  color: var(--c-ice);
  font-size: 13.5px;
  font-weight: 600;
  display: flex;
  flex-direction: column;
}
.price-name em {
  font-style: normal;
  font-weight: 400;
  font-size: 11.5px;
  color: rgb(var(--c-data-rgb) / 0.9);
  margin-top: 1px;
}
.price-val {
  color: rgb(var(--c-data-rgb) / 0.75);
  font-size: 12px;
  font-weight: 600;
}
.price-row.is-bonus { background: rgb(255 87 34 / 0.05); }
.price-row.is-bonus .price-name { color: var(--c-q2); }
.price-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px 18px;
  color: rgb(var(--c-data-rgb) / 0.9);
  font-size: 12.5px;
  font-weight: 600;
}
.price-strike { text-decoration: line-through; text-decoration-color: rgb(255 87 34 / 0.7); }
.price-today {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 13px 18px;
  background: rgb(255 87 34 / 0.08);
  color: var(--c-ice);
  font-size: 13px;
  font-weight: 700;
}
.price-amount {
  font-size: 34px;
  font-weight: 700;
  color: var(--c-ice);
  line-height: 1;
}

/* ── Scroll cue ───────────────────────────────────────────────── */

.cue-line {
  width: 1px;
  height: 44px;
  background: linear-gradient(180deg, var(--c-q1), transparent);
  overflow: hidden;
  position: relative;
}
.cue-line::after {
  content: "";
  position: absolute;
  left: 0;
  top: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(180deg, transparent, #fff);
  animation: cue-drop 2.2s ease-in-out infinite;
}

/* ── Keyframes ────────────────────────────────────────────────── */

@keyframes rig-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-13px); }
}
@keyframes core-pulse {
  0%, 100% { opacity: calc(var(--core-o) * 0.55); transform: translate(-50%, -50%) scale(0.92); }
  50%      { opacity: var(--core-o); transform: translate(-50%, -50%) scale(1.07); }
}
@keyframes chip-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.18); }
}
@keyframes cue-drop {
  0%   { top: -100%; }
  60%, 100% { top: 100%; }
}

/* ── Hamburger + compact-screen menu (below lg) ───────────────── */

#menu-toggle {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4.5px;
  width: 38px;
  height: 38px;
  border: 1px solid var(--c-smoke);
  border-radius: 10px;
  background: rgb(var(--c-bg-rgb) / 0.6);
  cursor: pointer;
}
#menu-toggle i {
  width: 16px;
  height: 2px;
  border-radius: 999px;
  background: var(--c-ice);
  transition: transform 0.25s ease, opacity 0.2s ease;
}
#menu-toggle.is-open i:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
#menu-toggle.is-open i:nth-child(2) { opacity: 0; }
#menu-toggle.is-open i:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }
@media (min-width: 1024px) { #menu-toggle { display: none; } }

.mobile-menu {
  position: fixed;
  top: 64px;
  left: 0;
  right: 0;
  z-index: 49;
  padding: 10px 20px 22px;
  background: rgb(var(--c-bg-rgb) / 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid rgb(var(--c-smoke-rgb) / 0.8);
  box-shadow: 0 24px 50px rgb(0 0 0 / 0.25);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s;
}
.mobile-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s;
}
.mobile-menu nav { display: flex; flex-direction: column; }
.mobile-menu nav > a {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgb(var(--c-nav-rgb));
  padding: 13px 2px;
  border-bottom: 1px solid rgb(var(--c-smoke-rgb) / 0.5);
  transition: color 0.2s ease;
}
.mobile-menu nav > a:hover { color: var(--c-ice); }
/* Theme control lives at the foot of the menu on compact screens; the
   header toggle is hidden below lg so the hamburger owns the top-right */
@media (max-width: 1023px) {
  header #theme-toggle { display: none; } /* header prefix beats #theme-toggle's display:flex */
}
.mm-theme {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.6);
}
.mm-theme-label {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--c-nav-rgb));
}
.mm-theme-toggle {
  display: flex;
  gap: 6px;
  border: 1px solid var(--c-smoke);
  border-radius: 999px;
  padding: 4px;
}
.mm-theme-toggle button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  border-radius: 999px;
  background: none;
  cursor: pointer;
  padding: 8px 16px;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: rgb(var(--c-data-rgb) / 0.85);
  transition: color 0.2s ease, background 0.2s ease;
}
.mm-theme-toggle button svg { width: 15px; height: 15px; }
.mm-theme-toggle button.is-active {
  color: var(--c-q2);
  background: rgb(var(--c-ice-rgb) / 0.08);
}
.mobile-menu .mm-cta {
  margin-top: 16px;
  border: 0;
  border-radius: 999px;
  text-align: center;
  color: #FFFFFF;
  padding: 13px 20px;
  /* Matches the other in-page CTAs. Set here rather than on .btn-quantum
     because this rule is later in the sheet and would otherwise win with the
     old 13px / wide-tracked values. */
  font-size: 16px;
  letter-spacing: 0;
}
@media (min-width: 1024px) { .mobile-menu { display: none; } }

/* ── Theme switcher ───────────────────────────────────────────── */

#theme-toggle {
  display: flex;
  align-items: center;
  gap: 2px;
  border: 1px solid var(--c-smoke);
  border-radius: 999px;
  padding: 3px;
}
#theme-toggle button {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  color: rgb(var(--c-data-rgb) / 0.8);
  transition: color 0.25s ease, background 0.25s ease;
}
#theme-toggle button:hover { color: var(--c-ice); }
#theme-toggle button.is-active {
  color: var(--c-q2);
  background: rgb(var(--c-ice-rgb) / 0.07);
}
#theme-toggle svg { width: 15px; height: 15px; }

/* ── Light theme ──────────────────────────────────────────────── */

[data-theme="light"] {
  --c-bg-rgb: 245 246 248;
  --c-ice-rgb: 11 12 16;
  --c-data-rgb: 51 65 85;     /* dark enough to survive /60 and /80 tints */
  --c-smoke-rgb: 203 211 222;
  --c-edge-rgb: 15 23 42;

  /* Light theme: a near-black FACE over a LIT GREY side. An earlier pass put a
     dark side under a dark face, which fused into one heavy mass and made the
     letterforms hard to pick out. Running the side light-to-dark instead gives
     the black glyph a clean edge to read against — the same way the thumbnail
     art handles black type — while the ramp still reads as a lit solid rather
     than the flat drop shadow a single tone would give. */
  /* Built to the same rule the orange follows: the side sits ENTIRELY DARKER
     than the face, so the two never share a tone and the glyph keeps a clean
     edge. That rule is why the orange reads as a solid, and why earlier
     near-black faces never could — at #0C1016 there is nothing left below to
     put a side into, so the ramp landed inside the face's own range and the
     row fused into a smear. Lifting the face to a deep slate buys back the
     room underneath. It reads black on a light page; it just isn't the
     maximum possible black. */
  --h3d-face-hi: #4A5568;
  --h3d-face-mid: #2E3744;
  --h3d-face-lo: #1A2029;
  --h3d-near: #10151C;
  --h3d-far: #05080C;
  --h3d-contact: rgb(15 23 42 / 0.26);
  --c-read: #0B0C10;
}
[data-theme="light"] { --c-nav-rgb: 51 65 85; --pill-bg: #FFFFFF; }
/* Section 3: the dark scrim becomes a light frost, and hover fills flip */
[data-theme="light"] .engine-pin.is-lit::before {
  background: linear-gradient(100deg,
    rgb(245 246 248 / 0.85) 0%,
    rgb(245 246 248 / 0.45) 55%,
    rgb(245 246 248 / 0.75) 100%);
}
[data-theme="light"] .swap-row:hover { background: rgb(15 23 42 / 0.04); }
[data-theme="light"] .swap-row.is-active { background: rgb(15 23 42 / 0.06); }
[data-theme="light"] body::before {
  background: radial-gradient(120% 95% at 50% 20%, transparent 55%, rgb(15 23 42 / 0.11) 100%);
}
[data-theme="light"] #grain { opacity: 0.04; mix-blend-mode: multiply; }
[data-theme="light"] #site-header.is-scrolled { background: rgb(245 246 248 / 0.75); }
[data-theme="light"] .cube-face::before {
  background: linear-gradient(135deg,
    rgb(255 255 255 / 0.6) 0%,
    rgb(255 255 255 / 0.2) 38%,
    rgb(148 163 184 / 0.3) 100%);
}
[data-theme="light"] #node-panel {
  background: rgb(255 255 255 / 0.86);
  border-color: rgb(15 23 42 / 0.12);
  box-shadow:
    0 0 0 1px rgba(255, 87, 34, 0.2),
    0 30px 80px rgb(15 23 42 / 0.18);
}
[data-theme="light"] #node-panel .border-t { border-color: rgb(15 23 42 / 0.1); }
[data-theme="light"] .hint-chips li {
  border-color: rgb(15 23 42 / 0.12);
  background: rgb(255 255 255 / 0.55);
}
[data-theme="light"] .btn-ghost {
  border-color: rgb(15 23 42 / 0.18);
  background: rgb(255 255 255 / 0.5);
}
[data-theme="light"] .hub-tag { text-shadow: 0 2px 10px rgb(245 246 248 / 0.9); }
[data-theme="light"] #email {
  background: rgb(255 255 255 / 0.7);
}
[data-theme="light"] ::-webkit-scrollbar-track { background: #F5F6F8; }
[data-theme="light"] ::-webkit-scrollbar-thumb {
  background: #C7D0DC;
  border-color: #F5F6F8;
}
[data-theme="light"] { scrollbar-color: #C7D0DC #F5F6F8; }

/* ── Small screens ────────────────────────────────────────────── */

@media (max-width: 480px) {
  .eyebrow-pill {
    letter-spacing: 0.15em;
    padding: 8px 14px;
    max-width: calc(100vw - 40px);
  }
  .swap-row {
    grid-template-columns: minmax(96px, 112px) auto 1fr;
    gap: 10px;
    padding: 14px 8px;
  }
  .swap-new p { max-width: none; }
  #depth-rail { right: 10px; }
  .term-body { height: 320px; }
}

/* ── Reduced motion ───────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  #cube-rig, .cube-core, .hub-chip, .cue-line::after, .lc-spin, .lc-core {
    animation: none !important;
  }
  .lc-spin { transform: rotateX(-18deg) rotateY(-30deg); }
  .chat-art { animation: none; }
  /* No staged reveal here, so the tiles must never sit in their
     pre-render state — that would leave the ad set blank. */
  .gen-tile.is-rendering .ad-canvas::before { display: none; }
  .gen-tile.is-rendering .ad-canvas > * { opacity: 1; }
}

/* ═══════════════════════════════════════════════════════════════════
   CHALLENGE COMPONENTS — scoreboard, typewriter, proof, anti-guru,
   channel carousel, and the Proof-of-Work article pages.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Live ledger scoreboard — the fixed bottom ticker ─────────── */

#scoreboard {
  position: fixed;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 9px 18px;
  border-radius: 999px;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.12);
  background: rgb(var(--c-bg-rgb) / 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.13em;
  color: rgb(var(--c-data-rgb) / 0.9);
  white-space: nowrap;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
/* Only the ledger half lights the pill — hovering a channel icon should not
   pretend the whole bar is one link any more. */
#scoreboard:has(.sb-ledger:hover) {
  border-color: rgba(255, 87, 34, 0.55);
  box-shadow: 0 0 26px rgba(255, 87, 34, 0.22), 0 10px 30px rgb(0 0 0 / 0.35);
}
/* The ledger carries the layout the pill itself used to have.
   align-self: stretch matters more than it looks — the whole pill used to BE
   this anchor, so it was tappable edge to edge. Once it became a child it
   shrank to the height of its own 9px text, which on a phone is a tap target
   you basically cannot hit. Stretching restores the full-height target. */
.sb-ledger {
  display: flex;
  align-items: center;
  align-self: stretch;
  gap: 13px;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}
.sb-links {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: none;
  padding-left: 11px;
  border-left: 1px solid rgb(var(--c-ice-rgb) / 0.14);
}
.sb-links a,
.sb-links span {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  color: var(--c-data);
  transition: color 0.2s ease, background 0.2s ease;
}
/* The icon reads small but the finger gets a full-height target: the pill is
   only ~37px tall, so the hit area is grown past the glyph instead of
   inflating the bar. */
.sb-links a::after {
  content: "";
  position: absolute;
  inset: -9px -2px;
}
.sb-links svg { width: 14px; height: 14px; }
.sb-links a:hover {
  color: var(--c-ice);
  background: rgb(var(--c-ice-rgb) / 0.1);
}
.sb-links .is-soon { opacity: 0.35; cursor: default; }
#scoreboard .sb-item b {
  color: var(--c-ice);
  font-weight: 500;
  margin-left: 3px;
  /* Live figures shouldn't jitter as digits change width (fix 2) */
  font-variant-numeric: tabular-nums;
}
/* One sign rule for every money figure: red below zero, green at or above */
#scoreboard .sb-item b.is-pos, .hero-live-value.is-pos { color: #7EE2A8; }
#scoreboard .sb-item b.is-neg, .hero-live-value.is-neg { color: #FF8A80; }
.sb-day {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-right: 13px;
  border-right: 1px solid rgb(var(--c-ice-rgb) / 0.12);
  color: var(--c-q2);
  font-weight: 500;
}
.sb-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #FF3B30;
  box-shadow: 0 0 8px rgba(255, 59, 48, 0.9);
  animation: sb-pulse 1.7s ease-in-out infinite;
  flex: none;
}

/* The current milestone leads the ticker; $1M rides as the faint summit */
.sb-mile {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 13px;
  border-right: 1px solid rgb(var(--c-ice-rgb) / 0.12);
}
.sb-mile b { color: var(--c-ice); font-weight: 500; }
#sb-mile-pct { color: var(--c-q2); }
.sb-bar {
  position: relative;
  width: 64px;
  height: 4px;
  border-radius: 999px;
  background: rgb(var(--c-ice-rgb) / 0.14);
  overflow: hidden;
  flex: none;
}
.sb-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--c-q1), var(--c-q2));
  box-shadow: 0 0 8px rgba(255, 87, 34, 0.6);
  transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.sb-summit {
  font-style: normal;
  color: rgb(var(--c-data-rgb) / 0.55);
  letter-spacing: 0.1em;
}
@keyframes sb-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* ── Hero: live CTA + typewriter ──────────────────────────────── */

.live-cta { display: inline-flex; align-items: center; gap: 9px; }
.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #22C55E;
  box-shadow: 0 0 9px rgba(34, 197, 94, 0.95);
  animation: sb-pulse 1.7s ease-in-out infinite;
  flex: none;
}

/* ── The climb, inside the headline: a segmented terminal bar.
   Four equal segments ($1K → $10K → $100K → $1M) with block teeth;
   the fill sweeps toward the $1M flag planted at the far end. ── */

.climb-line {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.14em;
  color: var(--c-ice);
}
.climb-line #climb-pct { color: var(--c-q2); }
.climb-bar {
  position: relative;
  width: min(230px, 40vw);
  height: 11px;
  border-radius: 3px;
  background: rgb(var(--c-ice-rgb) / 0.13);
  flex: none;
  margin-top: 2px;
}
.climb-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: linear-gradient(90deg, var(--c-q1), var(--c-q2));
  box-shadow: 0 0 14px rgba(255, 87, 34, 0.55);
  transition: width 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Block teeth carve the bar into ▓▓▓ cells */
.climb-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg, transparent 0 7px, rgb(var(--c-bg-rgb)) 7px 9px);
}
/* Milestone notches at the 1/4, 1/2, 3/4 marks */
.climb-bar::before {
  content: "";
  position: absolute;
  inset: -3px 0;
  background: repeating-linear-gradient(90deg, transparent 0 calc(25% - 1px), rgb(var(--c-data-rgb) / 0.9) calc(25% - 1px) 25%);
  z-index: 1;
}
/* The final boss, planted at the end of the bar */
.climb-summit {
  position: absolute;
  right: -6px;
  top: -17px;
  font-style: normal;
  font-family: "JetBrains Mono", monospace;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: 0.1em;
  color: rgb(var(--c-data-rgb) / 0.85);
}
.climb-summit::after {
  content: "";
  position: absolute;
  right: 9px;
  top: 11px;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid rgb(var(--c-data-rgb) / 0.85);
}

/* The live ledger shares the headline baseline: current rung, segmented
   climb, milestone ticks, and the live percentage in one typographic row. */
.hero-headline {
  width: min(1180px, calc(100vw - 40px));
  max-width: none;
}
/* Cap the desktop headline a hair below 3rem. The font scales with viewport
   HEIGHT (5.6vh), so a tall monitor pushes it to the 3rem/48px ceiling while a
   laptop sits at ~44.8px. At 48px the sentence wraps one step further and the
   inline ledger drops off the first line onto an interior one — where its
   marks and arrow, which sit ABOVE the bar by design, collide with the line
   above it. (Raising line-height would clear it but breaks the headline's
   symmetry, so that lever is out.) 2.8rem is exactly the size the laptop
   already renders at, 2 lines with the ledger on the first, so the wrap — and
   therefore the ledger's line — becomes viewport-height independent. Screens
   already under this cap are untouched.
   In glassbox.css, not the Tailwind text-[clamp(...)] class: that arbitrary
   value is purged from the compiled bundle, so editing it there ships nothing.
   min-width:768px mirrors Tailwind's md: breakpoint, the one it overrides. */
@media (min-width: 768px) {
  .hero-headline { font-size: clamp(2.1rem, 5.6vh, 2.8rem); }
}
.hero-climb-line {
  display: block;
}
.hero-live-value {
  /* No pill any more. The orange highlight it now has to match is bare
     extruded text, and a background would in any case be clipped to the
     glyphs by the face gradient rather than drawn behind them. */
  padding: 0;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  /* The money is the hook: values now set ~15% larger than the words around
     them, same family and extrusion, so they hit like a scoreboard instead of
     hiding inline at 0.94em. */
  font-size: 1.15em;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--h3d-track);  /* was -0.02em, out of step with the line */
  line-height: 1;
}
/* "1 day" reads as plain headline text: it inherits everything */
.hero-method {
  display: block;
  margin-top: 0.14em; /* the bar's underside is clean, lines sit tight */
}
.hero-camera {
  display: inline-block;
  margin-left: 0.16em;
  font-size: 0.78em;
  line-height: 1;
  vertical-align: 0.05em;
  filter: drop-shadow(0 0.08em 0.14em rgba(255, 87, 34, 0.3));
  animation: hero-camera-float 3.2s ease-in-out infinite;
}
@keyframes hero-camera-float {
  0%, 100% { transform: translateY(0) rotate(-7deg); }
  50% { transform: translateY(-0.08em) rotate(-3deg); }
}
/* The ledger rides INSIDE the sentence: I've turned $X into [bar] in N days.
   Red loss blocks left of the $0 tick, four revenue rungs to the right,
   and a live arrow over the current net position. */
.headline-ledger {
  position: relative;
  display: inline-block;
  width: clamp(6.2em, 16vw, 7.6em);
  /* Sized to the cap height of the headline beside it, so the bar reads as a
     word in the sentence rather than a hairline under it */
  height: 0.68em;
  margin: 0 0.12em;
  vertical-align: -0.02em;
  font-family: "JetBrains Mono", monospace;
  line-height: 1;
  white-space: normal;
}
.hlc-track {
  position: absolute;
  inset: 0;
  border-radius: 0.1em;
  overflow: hidden;
  background: rgb(var(--c-ice-rgb) / 0.13);
}
.hlc-track i {
  position: absolute;
  top: 0;
  bottom: 0;
  transition: left 0.6s cubic-bezier(0.22, 1, 0.36, 1), width 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
#hlc-fill {
  left: 14%;
  background: linear-gradient(90deg, var(--c-q1), var(--c-q2));
  box-shadow: 0 0 0.25em rgba(255, 87, 34, 0.36);
}
/* Sheen sweep — the bar reads as a number that is still moving */
.hlc-track i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgb(255 255 255 / 0.5) 50%, transparent 100%);
  background-size: 220% 100%;
  animation: hlc-sheen 2.6s linear infinite;
}
#hlc-fill-neg::after { animation-delay: 0.5s; }
@keyframes hlc-sheen {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}
/* The $0 tick breathes so the eye finds the origin */
.hlc-zero { animation: hlc-zero-pulse 3.4s ease-in-out infinite; }
@keyframes hlc-zero-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
#hlc-fill-neg {
  background: linear-gradient(90deg, #DC2626, #EF4444);
  box-shadow: 0 0 0.25em rgba(239, 68, 68, 0.4);
}
/* Chunky cells, fewer of them */
.hlc-track::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg, transparent 0 0.34em, rgb(var(--c-bg-rgb)) 0.34em 0.44em);
}
/* The $0 line between red and orange territory */
.hlc-zero {
  position: absolute;
  top: -0.1em;
  bottom: -0.1em;
  left: 14%;
  width: 2px;
  margin-left: -1px;
  background: rgb(var(--c-data-rgb) / 0.95);
  z-index: 2;
}
/* The live arrow rides above the bar with the ruler, pointing down at
   the net position; nothing hangs below the bar so the headline lines
   stay tight and symmetrical */
.hlc-arrow {
  position: absolute;
  left: 14%;
  bottom: calc(100% + 0.06em);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.07em;
  pointer-events: none;
  z-index: 3;
  transition: left 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.hlc-arrow b {
  font-weight: 600;
  font-size: 0.52em;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--h3d-track);  /* was 0.02em */
  line-height: 1;
  white-space: nowrap;
}
.hlc-arrow i {
  width: 0;
  height: 0;
  border-left: 0.11em solid transparent;
  border-right: 0.11em solid transparent;
  border-top: 0.15em solid currentColor;
}
.hlc-arrow.is-neg { color: #DC2626; }
[data-theme="dark"] .hlc-arrow.is-neg { color: #F87171; }
.hlc-arrow.is-pos { color: #1E9E4A; }
[data-theme="dark"] .hlc-arrow.is-pos { color: #7EE2A8; }
.hlc-arrow.is-zero { color: rgb(var(--c-data-rgb) / 0.95); }
/* Milestone ruler ON TOP of the bar, ticks dipping down to it */
.hlc-marks {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: calc(100% + 0.08em);
  height: 0.66em;
  color: rgb(var(--c-data-rgb) / 0.9);
  pointer-events: none;
}
.hlc-marks em {
  position: absolute;
  left: var(--mark);
  top: 0;
  transform: translateX(-50%);
  font-style: normal;
  font-size: 0.46em;
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--h3d-track);  /* was 0.06em */
  white-space: nowrap;
}
 /* The tick lives on ::after. It used to sit on ::before, which is the slot
    the extruded clone needs (content: attr(data-text)) — and because this rule
    comes later in the sheet its content:"" won, so the marks were rendering a
    gradient face with no depth behind it. */
.hlc-marks em::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 1.18em;
  height: 0.7em;
  border-left: 1px solid rgb(var(--c-data-rgb) / 0.65);
}
.hlc-marks .hlc-end { transform: translateX(-62%); }

/* ── The summit mark ──────────────────────────────────────────────
   Gold face and side, a glow standing in for the backdrop, and a slow bob.
   The bob has to re-declare translateX(-62%): this mark is nudged left so it
   does not overhang the bar, and a keyframe that only sets translateY would
   drop that and shunt it sideways. */
.hlc-marks .hlc-end {
  /* The summit is the number the whole bar is pointing at, so it outsizes the
     rungs. Its nudge eases from -82% to -62% at the same time: at the old 0.36em
     old pull kept it clear of the bar end, but scaled up it walks the mark
     left into $100K, and there is only ~37px of runway between that label and
     the end of the bar for a 45px word. Sitting further right trades overhang
     — which the star already has — for the clearance. */
  font-size: 0.6em;
  transform: translateX(-62%);
  --h3d-face-hi: var(--y3d-face-hi);
  --h3d-face-mid: var(--y3d-face-mid);
  --h3d-face-lo: var(--y3d-face-lo);
  --h3d-near: var(--y3d-near);
  --h3d-far: var(--y3d-far);
  filter: drop-shadow(0 0 0.3em rgba(255, 196, 61, 0.6))
          drop-shadow(0 0 0.85em rgba(255, 160, 20, 0.28));
  animation: hlc-summit 2.4s ease-in-out infinite;
}
/* ::after is the tick for every other mark; the summit spends it on a star */
.hlc-marks .hlc-end::after {
  content: "✦";
  position: absolute;
  left: auto;
  right: -0.72em;
  top: -0.52em;
  height: auto;
  border: 0;
  /* Saturated, not pale: #FFDE6A vanished against the light page. This has to
     hold up on both themes, so it leans amber rather than pale gold and keeps
     a floor on the twinkle instead of fading to near-invisible. */
  /* Saturated, not pale: #FFDE6A vanished against the light page. Keep the
     glow TIGHT — the parent's drop-shadow filter applies to this pseudo too,
     and stacking a wide text-shadow on top of it smeared the star into an
     unreadable blob. One close shadow is enough to lift it off the page. */
  font-size: 1.15em;
  color: #E8940F;
  text-shadow: 0 0 0.12em rgba(255, 210, 90, 0.9);
  animation: hlc-twinkle 1.9s ease-in-out infinite;
}
@keyframes hlc-summit {
  0%, 100% { transform: translateX(-62%) translateY(0) scale(1); }
  50%      { transform: translateX(-62%) translateY(-0.16em) scale(1.07); }
}
@keyframes hlc-twinkle {
  0%, 100% { opacity: 0.8; transform: scale(0.9) rotate(0deg); }
  50%      { opacity: 1;   transform: scale(1.18) rotate(22deg); }
}
@media (prefers-reduced-motion: reduce) {
  .hlc-marks .hlc-end,
  .hlc-marks .hlc-end::after { animation: none; }
  .hlc-marks .hlc-end { transform: translateX(-62%); }
}

@media (max-width: 900px) {
  /* Narrow screens wrap the sentence across several lines, so an inline
     ledger's marks would print over the line above it. Give the bar its
     own centered row instead: sentence → ledger → sentence. */
  .headline-ledger {
    display: block;
    width: min(11em, 74vw);
    margin: 0.85em auto 0.3em;
  }
  /* One continuous sentence around the bar: no forced break after
     "in 1 day" — the text flows and wraps naturally */
  .hero-climb-line,
  .hero-method { display: inline; }
}

/* Typed caret on any active rotator */
.tw-on::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 0.9em;
  margin-left: 3px;
  vertical-align: -0.08em;
  background: currentColor;
  animation: caret-blink 1s steps(1) infinite;
}
@keyframes caret-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

/* Founding-price footnote under the hero CTA. Numbers come from the same
   ledger file as the scoreboard, so the two can never contradict. */
.price-note {
  margin-top: 12px;
  /* A sentence of pricing fine-print is prose, not a data readout — it joins
     the body sans so mono stays reserved for ledgers and logs (fix 4). */
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.9);
}
.price-note b { color: var(--c-q2); font-weight: 600; }
.price-note.is-gone { display: none; }
/* The note is a direct <p> of #hero-copy, and the responsive `#hero-copy > p`
   rules outrank a bare class — they were inflating it to full body size on
   phones, where uppercase mono with wide tracking then read LARGER than the
   sentence above it. Match their specificity so it stays a footnote. */
#hero-copy > p.price-note {
  margin-top: 12px;
  font-size: 10px;
  line-height: 1.5;
}

/* ── Vault section extras ─────────────────────────────────────── */

/* :not(.hidden) is load-bearing — this file loads after Tailwind, so a bare
   `.vault-link { display: inline-flex }` beat `.hidden` on source order and
   shipped the placeholder href="#" link even with no published vault. */
.vault-link:not(.hidden) {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: var(--c-q2);
  border-bottom: 1px solid rgb(255 87 34 / 0.4);
  padding-bottom: 2px;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.vault-link:hover { color: var(--c-ice); border-color: var(--c-ice); }
/* Breathing room between the vault link and the explore-hint chips below.
   Unconditional: the underline sat flush against the chips on narrow
   viewports, where the chips are also the tightest. */
.vault-link { margin-bottom: 14px; }
@media (min-width: 1024px) {
  .vault-link { margin-bottom: 18px; }
}

/* ── Proof of Work ────────────────────────────────────────────── */

.proof-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 18px;
  padding: 22px;
  transition: border-color 0.3s ease, background 0.3s ease, transform 0.3s ease;
}
.proof-card.is-live:hover {
  border-color: rgba(255, 87, 34, 0.5);
  background: rgb(var(--c-bg-rgb) / 0.82);
  transform: translateY(-3px);
}
.proof-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.proof-type {
  font-family: "JetBrains Mono", monospace;
  font-weight: 500;
  font-size: 8.5px;
  letter-spacing: 0.16em;
  color: var(--c-q2);
  border: 1px solid rgb(255 87 34 / 0.4);
  border-radius: 999px;
  padding: 3px 9px;
}
.proof-stat {
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.13em;
  color: rgb(var(--c-data-rgb) / 0.75);
}
.proof-card h3 {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.03em;
  color: var(--c-ice);
  margin-top: 14px;
}
.proof-card > p {
  color: var(--c-data);
  font-size: 13px;
  line-height: 1.6;
  margin-top: 6px;
  flex: 1;
}
.proof-link {
  /* Padding, not margin, on the top: an 18px line of text is a thin thing to
     hit with a thumb, and the padding grows the tap area without moving the
     link visually. */
  display: inline-block;
  margin-top: 6px;
  padding: 8px 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--c-q2);
  transition: color 0.25s ease;
  width: fit-content;
}
a.proof-link:hover { color: var(--c-ice); }
.proof-card.is-soon { opacity: 0.72; }
.proof-card.is-soon .proof-link {
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.8);
}

.proof-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  border: 1px solid rgba(255, 87, 34, 0.35);
  background:
    linear-gradient(150deg, rgba(255, 87, 34, 0.09), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 18px;
  padding: 20px 24px;
}

/* ── The anti-guru: rules card ────────────────────────────────── */

.rules-card {
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 18px;
  padding: 22px 24px;
  max-width: 34rem;
}
.rules-head {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 9.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--c-q2);
}
.rules-list {
  counter-reset: rule;
  margin-top: 8px;
  list-style: none;
  padding: 0;
}
.rules-list li {
  counter-increment: rule;
  position: relative;
  padding: 10px 0 10px 36px;
  color: var(--c-data);
  font-size: 13.5px;
  line-height: 1.6;
}
.rules-list li + li { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.5); }
.rules-list li::before {
  content: counter(rule, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 13px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--c-q2);
}
.rules-list b { color: var(--c-ice); font-weight: 600; }

/* ── Channel carousel — a 3D ring of feeds ────────────────────── */

.carousel-wrap { position: relative; }
.car-stage {
  position: relative;
  height: 272px;
  perspective: 1400px;
}
.car-ring {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}
.car-card {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 280px;
  /* Content-sized: the 16:9 thumb plus whatever the label needs, nothing
     more. Fixed heights left a slab of dead white under the title that grew
     with the card — worst on the wide arc variant. Centring moves to the
     standalone `translate` property so it composes with (rather than fights)
     the 3D transform carousel.js writes every frame. */
  height: auto;
  translate: -50% -50%;
  display: flex;
  flex-direction: column;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.14);
  background: rgb(var(--c-bg-rgb) / 0.92);
  box-shadow: 0 24px 60px rgb(0 0 0 / 0.45);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transition: border-color 0.3s ease;
}
.car-card:hover { border-color: rgba(255, 87, 34, 0.6); }
.car-card.is-front { border-color: rgba(255, 87, 34, 0.45); }
.car-card:focus-visible { outline: 1px solid var(--c-q1); outline-offset: 3px; }
.car-card.is-soon { cursor: default; }
.car-card.is-soon .car-thumb { filter: saturate(0.35); }

/* ── Channels carousel entrance ────────────────────────────────────
   Four cards converge from three points off the frame — one from the left,
   one from below, one from the right, the fourth reusing the left — as the
   section arrives. js/carousel.js adds .is-flown once the stage is in view.

   The offset has to fold into the SAME `translate` the centring above uses.
   It cannot go on `transform`, which carousel.js rewrites every frame to
   place each card on the ring, and it cannot simply replace `translate`
   either — that would drop the -50% -50% centring and the ring would come
   apart. Hence the calc() on both axes.

   Wide stage only: the narrow ring in section 07 sits in a much smaller
   column, where cards flown from half a viewport away read as a glitch. */
@media (prefers-reduced-motion: no-preference) {
  /* Each origin writes a whole `translate` rather than feeding offsets through
     custom properties — three static origins do not need the indirection, and
     the -50% centring has to be carried in every value anyway. */
  .car-stage-wide .car-card { transition: translate 900ms cubic-bezier(0.16, 1, 0.3, 1); }
  .car-stage-wide .car-card:nth-child(3n + 1) { translate: calc(-50% - 54vw) calc(-50% + 10vh); }
  .car-stage-wide .car-card:nth-child(3n + 2) { translate: -50% calc(-50% + 44vh); }
  .car-stage-wide .car-card:nth-child(3n + 3) { translate: calc(-50% + 54vw) calc(-50% + 10vh); }
  /* Staggered, or four cards land as one block and the move reads as a slide */
  .car-stage-wide .car-card:nth-child(2) { transition-delay: 90ms; }
  .car-stage-wide .car-card:nth-child(3) { transition-delay: 180ms; }
  .car-stage-wide .car-card:nth-child(4) { transition-delay: 270ms; }
  /* Four classes, so it outranks the three-class origins above */
  .car-stage-wide .car-ring.is-flown .car-card { translate: -50% -50%; }
}

/* The "video preview" — CSS-built thumbnail in brand monochrome */
.car-thumb {
  position: relative;
  display: block;
  /* The art is rendered 16:9. Deriving the height from the card width instead
     of pinning it per breakpoint keeps every channel thumbnail whole — the old
     fixed heights drifted a few px off the ratio and shaved the edges. */
  aspect-ratio: 16 / 9;
  flex: none;
  overflow: hidden;
  background:
    radial-gradient(130% 130% at 18% 0%, rgba(255, 87, 34, 0.26), transparent 55%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
.thumb-live {
  background:
    radial-gradient(130% 130% at 18% 0%, rgba(198, 40, 40, 0.32), transparent 55%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
.thumb-yt {
  background:
    radial-gradient(130% 130% at 82% 0%, rgba(255, 87, 34, 0.26), transparent 55%),
    linear-gradient(160deg, #14161C 0%, #08090C 100%);
}
.thumb-x {
  background:
    radial-gradient(130% 130% at 82% 100%, rgba(255, 255, 255, 0.1), transparent 55%),
    linear-gradient(160deg, #14161C 0%, #08090C 100%);
}
.thumb-discord {
  background:
    radial-gradient(130% 130% at 50% 110%, rgba(88, 101, 242, 0.28), transparent 60%),
    linear-gradient(160deg, #14161C 0%, #0B0C10 100%);
}
.thumb-glyph {
  position: absolute;
  right: -16px;
  bottom: -20px;
  width: 116px;
  height: 116px;
  color: rgb(255 255 255 / 0.08);
}
/* Real rendered thumbnail — fills the preview slot and sits under the
   badge and play puck, which stay readable over it via their own scrims */
.car-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
}
.thumb-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--c-q2), var(--c-q1));
  box-shadow: 0 0 26px rgba(255, 87, 34, 0.6);
}
.thumb-play::after {
  content: "";
  position: absolute;
  left: 55%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-left: 12px solid #FFFFFF;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
}
/* Livestream card: the center puck broadcasts instead of playing —
   YouTube's "Go live" mark on the brand-orange circle */
.thumb-play-live {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #FFFFFF;
}
.thumb-play-live::after { content: none; }
.thumb-play-live svg { width: 26px; height: 26px; }
.car-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.16em;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgb(255 255 255 / 0.18);
  background: rgb(0 0 0 / 0.55);
  color: #FFFFFF;
}
.badge-live {
  background: rgba(198, 40, 40, 0.92);
  border-color: rgba(255, 255, 255, 0.3);
}
.car-label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  flex: none; /* must not stretch — that stretch WAS the whitespace */
}
.car-name { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.car-name b {
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.car-name i {
  font-style: normal;
  color: var(--c-data);
  font-size: 11.5px;
  margin-top: 2px;
}
.car-arrow { color: var(--c-q2); font-size: 15px; flex: none; }

.car-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin-top: 8px;
}
.car-nav button {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.16);
  background: rgb(var(--c-bg-rgb) / 0.7);
  color: var(--c-data);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: all 0.25s ease;
}
.car-nav button:hover {
  color: var(--c-ice);
  border-color: var(--c-q2);
  box-shadow: 0 0 18px rgba(255, 87, 34, 0.3);
}
.car-caption {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.26em;
  color: rgb(var(--c-data-rgb) / 0.75);
  text-transform: uppercase;
}

/* ── Proof-of-Work article pages (proof/*.html) ───────────────── */

.ap-meta { display: flex; flex-wrap: wrap; gap: 10px; }
.ap-chip {
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 999px;
  padding: 7px 14px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.13em;
  color: var(--c-data);
}
.ap-chip b { color: var(--c-ice); font-weight: 500; }

.ap-section { margin-top: 56px; }
.ap-section h2 {
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 22px;
  letter-spacing: 0.03em;
  color: var(--c-ice);
}
.ap-section > p {
  color: var(--c-data);
  font-size: 15px;
  line-height: 1.75;
  margin-top: 12px;
}
.ap-list { margin-top: 14px; }
.ap-list li {
  display: flex;
  gap: 10px;
  color: var(--c-data);
  font-size: 14px;
  line-height: 1.7;
  padding: 4px 0;
}
.ap-list li::before { content: "▸"; color: var(--c-q2); flex: none; }
.ap-list b { color: var(--c-ice); font-weight: 600; }

.ap-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 4px;
  border: 1px solid rgb(var(--c-smoke-rgb) / 0.8);
  border-radius: 16px;
  overflow: hidden;
  margin-top: 18px;
}
.ap-stat {
  padding: 18px 16px;
  background: rgb(var(--c-bg-rgb) / 0.72);
  text-align: center;
}
.ap-stat b {
  display: block;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 22px;
  color: var(--c-ice);
}
.ap-stat span {
  display: block;
  margin-top: 5px;
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  letter-spacing: 0.18em;
  color: rgb(var(--c-data-rgb) / 0.8);
  text-transform: uppercase;
}

.prompt-block {
  border: 1px solid var(--term-border);
  background: var(--term-bg);
  border-radius: 14px;
  padding: 18px 20px;
  margin-top: 16px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  line-height: 1.75;
  color: var(--term-cmd);
  white-space: pre-wrap;
  word-break: break-word;
}
.prompt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  letter-spacing: 0.2em;
  color: var(--c-q2);
  margin-bottom: 10px;
}
.locked-row {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid rgb(var(--c-smoke-rgb) / 0.7);
  border-radius: 12px;
  padding: 13px 16px;
  margin-top: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: rgb(var(--c-data-rgb) / 0.85);
}
.locked-row svg { width: 12px; height: 12px; color: var(--c-q2); flex: none; }

.ap-cta {
  margin-top: 64px;
  text-align: center;
  border: 1px solid rgba(255, 87, 34, 0.35);
  background:
    linear-gradient(150deg, rgba(255, 87, 34, 0.09), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 22px;
  padding: 40px 28px;
}
.ap-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: var(--c-data);
  transition: color 0.25s ease;
}
.ap-back:hover { color: var(--c-ice); }

/* ── Light theme for challenge components ─────────────────────── */

[data-theme="light"] #scoreboard {
  background: rgb(255 255 255 / 0.85);
  border-color: rgb(15 23 42 / 0.14);
  box-shadow: 0 10px 30px rgb(15 23 42 / 0.12);
}
[data-theme="light"] .sb-day, [data-theme="light"] .sb-mile { border-color: rgb(15 23 42 / 0.14); }
[data-theme="light"] #scoreboard .sb-item b.is-pos,
[data-theme="light"] .hero-live-value.is-pos { color: #1E9E4A; }
[data-theme="light"] #scoreboard .sb-item b.is-neg,
[data-theme="light"] .hero-live-value.is-neg { color: #C62828; }
[data-theme="light"] .car-nav button { background: rgb(255 255 255 / 0.7); }
[data-theme="light"] .car-card {
  background: #FFFFFF;
  border-color: rgb(15 23 42 / 0.14);
  box-shadow: 0 24px 60px rgb(15 23 42 / 0.16);
}
[data-theme="light"] .ship-item { background: rgb(15 23 42 / 0.03); }

/* ── Small screens for challenge components ───────────────────── */

@media (max-width: 900px) {
  #site-header.is-scrolled,
  #scoreboard {
    background: rgb(var(--c-bg-rgb) / 0.95);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  #scoreboard {
    gap: 9px;
    padding: 8px 11px;
    font-size: 8.5px;
    letter-spacing: 0.09em;
    bottom: 10px;
    width: calc(100vw - 16px);
    max-width: 470px;
    border-radius: 16px;
  }
  /* The two-row money grid belongs to the ledger now, not the pill */
  #scoreboard .sb-ledger {
    flex: 1;
    display: grid;
    grid-template-columns: auto repeat(3, auto);
    gap: 5px 10px;
    justify-content: stretch;
  }
  .sb-links { padding-left: 9px; gap: 2px; }
  .sb-links a,
  .sb-links span { width: 24px; height: 24px; }
  .sb-day {
    justify-content: center;
    padding-right: 10px;
  }
  .sb-item { text-align: center; }
  .sb-key { font-size: 0; }
  .sb-key::after {
    content: attr(data-short);
    font-size: 8px;
  }
  /* The ladder owns row two. It keeps the full current-rung readout while
     the denser money row above switches to compact labels. */
  .sb-mile {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: auto minmax(62px, 1fr) auto auto;
    justify-content: stretch;
    border-right: 0;
    border-top: 1px solid rgb(var(--c-ice-rgb) / 0.1);
    padding-right: 0;
    padding-top: 5px;
    gap: 6px;
  }
  .sb-bar { width: 100%; }
  .sb-summit { display: inline; font-size: 7.5px; }
  /* Phones: the ledger keeps riding inline but grows relative to the
     smaller headline so the arrow label stays legible */
  .headline-ledger { width: min(8em, 50vw); height: 0.66em; }
  .hlc-arrow b { font-size: 0.54em; }
  .hlc-marks em { font-size: 0.48em; }
  .pricing-vortex { width: 175vw; }
  #node-panel {
    top: auto;
    right: 8px;
    left: 8px;
    bottom: 58px; /* clear of the scoreboard */
    width: auto;
    max-height: 66vh;
    border: 1px solid rgb(255 255 255 / 0.1);
    border-top-color: rgba(255, 87, 34, 0.4);
    border-radius: 18px;
    transform: translateY(calc(100% + 40px));
  }
  #node-panel.is-open { transform: translateY(0); }
  .car-stage { height: 244px; }
  .car-card { width: 236px; }
  .proof-strip { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 360px) {
  #scoreboard {
    gap: 4px;
    padding-inline: 7px;
    font-size: 7.5px;
    letter-spacing: 0.04em;
  }
  #scoreboard .sb-ledger { gap: 5px; }
  .sb-links a,
  .sb-links span { width: 19px; height: 19px; }
  .sb-links svg { width: 11px; height: 11px; }
  .sb-key::after { font-size: 7px; }
  .sb-day { padding-right: 6px; }
  .sb-mile { gap: 5px; }
}

/* ── Reduced motion for challenge components ──────────────────── */

@media (prefers-reduced-motion: reduce) {
  .sb-dot, .live-dot, .ks-live { animation: none; }
  .fh-frame, .fh-ring, .fh-tag::before { animation: none; }
  #face-hud.is-scanning .fh-scan,
  #face-hud.is-scanning .fh-scanning,
  #face-hud.is-analyzed .fh-lock { animation: none; }
  #cube-me.is-analyzed .cm-card img { animation: none; }
  #cube-me.is-scanning .cm-mesh path { animation: none; stroke-dashoffset: 0; }
  .cm-card img { transition: none; }
  .mobile-menu { transition: opacity 0.2s ease, visibility 0s; transform: none; }
  .hero-camera { animation: none; transform: rotate(-5deg); }
  .sb-bar i, .climb-bar i, .hlc-track i { transition: none; }
  .hlc-track i::after { display: none; }
  .hlc-zero { animation: none; }
  .hlc-arrow { transition: none; }
  .pv-ring, .pv-core { animation: none; }
  .engine-left, .engine-right, .kevin-portrait, .kevin-story, .kevin-follow {
    transform: none !important;
  }
  .tw-on::after { animation: none; }
  #node-panel { transition: opacity 0.2s ease, visibility 0s linear 0.2s; transform: none; }
  #node-panel.is-open { transition: opacity 0.2s ease, visibility 0s; }
  .car-ring { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════
   ROUND 2 — hero character, proof toolbar + thumbnails, discord block,
   kevin socials, carousel drag affordances.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Kevin: shoulder-up portrait as a true background layer. The channel
   carousel is positioned above the portrait on desktop, while story,
   portrait and cards move at three restrained parallax speeds. ── */
#kevin {
  min-height: 1080px;
  isolation: isolate;
}
.kevin-portrait {
  position: absolute;
  top: -4%;
  right: 0;
  bottom: -4%;
  width: min(54vw, 820px);
  z-index: 0;
  pointer-events: none;
  transform: translate3d(0, var(--kevin-portrait-y, 0px), 0);
  will-change: transform;
}
.kevin-portrait img {
  position: absolute;
  top: 47%;
  right: 0;
  width: 100%;
  height: auto;
  transform: translateY(-50%);
  -webkit-user-drag: none;
}
.kevin-portrait::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgb(var(--c-bg-rgb)) 0%, rgb(var(--c-bg-rgb) / 0) 34%),
    linear-gradient(0deg, rgb(var(--c-bg-rgb)) 0 18%, rgb(var(--c-bg-rgb) / 0.94) 26%, rgb(var(--c-bg-rgb) / 0) 46%),
    linear-gradient(180deg, rgb(var(--c-bg-rgb) / 0.76) 0%, rgb(var(--c-bg-rgb) / 0) 16%);
}
.kp-light {
  filter: brightness(1.01) contrast(1.02) saturate(0.94);
  /* The source ends in a bright shirt. Fade the intrinsic image itself so
     its bottom edge can never read as a white horizontal shelf. */
  -webkit-mask-image: linear-gradient(180deg, #000 0 60%, rgba(0, 0, 0, 0.88) 70%, rgba(0, 0, 0, 0.32) 86%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0 60%, rgba(0, 0, 0, 0.88) 70%, rgba(0, 0, 0, 0.32) 86%, transparent 100%);
}
/* The dark portrait's own matte is near-black (1,1,1) while the page sits at
   #0B0C10 — the photo is DARKER than the page, so any surviving edge prints
   as a rectangle. The falloff therefore has to reach full transparency inside
   the box on every side, with a long ramp: a short one banded visibly at a
   delta this small. */
.kp-dark {
  display: none;
  --kp-fade: radial-gradient(58% 56% at 60% 46%,
    #000 0 26%,
    rgba(0, 0, 0, 0.92) 44%,
    rgba(0, 0, 0, 0.6) 60%,
    rgba(0, 0, 0, 0.25) 74%,
    rgba(0, 0, 0, 0.06) 86%,
    transparent 96%);
  -webkit-mask-image: var(--kp-fade);
  mask-image: var(--kp-fade);
}
[data-theme="dark"] .kp-light { display: none; }
[data-theme="dark"] .kp-dark {
  display: block;
  filter: brightness(1.05) contrast(1.03) saturate(1.05);
}
.kevin-story {
  position: relative;
  z-index: 2;
  max-width: 580px;
  transform: translate3d(0, var(--kevin-story-y, 0px), 0);
  will-change: transform;
}
.kevin-follow {
  position: absolute;
  z-index: 4;
  top: 50%;
  right: -6%;
  width: min(610px, 54vw);
  margin-top: 0 !important;
  transform: translate3d(0, var(--kevin-follow-y, 0px), 0);
  will-change: transform;
}
@media (max-width: 1023px) {
  #kevin { min-height: 0; }
  .kevin-portrait {
    top: 6%;
    bottom: 8%;
    width: 100%;
    opacity: 0.17;
  }
  .kevin-portrait img {
    top: 0;
    right: auto;
    left: 50%;
    width: min(100%, 820px);
    transform: translateX(-50%);
  }
  .kevin-portrait::after {
    background:
      linear-gradient(90deg, rgb(var(--c-bg-rgb) / 0.72) 0%, rgb(var(--c-bg-rgb) / 0) 48%),
      linear-gradient(0deg, rgb(var(--c-bg-rgb) / 0.9) 0%, transparent 30%);
  }
  .kevin-follow {
    position: relative;
    top: auto;
    right: auto;
    width: 100%;
    margin-top: 72px !important;
  }
}

/* ── Underline highlight used in the anti-guru copy ───────────── */

.hl-u {
  text-decoration: underline;
  text-decoration-color: var(--c-q1);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  color: var(--c-ice);
}

/* ── Proof toolbar: search + type chips ───────────────────────── */

.proof-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.proof-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 240px;
  max-width: 340px;
}
.proof-search svg {
  position: absolute;
  left: 15px;
  width: 13px;
  height: 13px;
  color: rgb(var(--c-data-rgb) / 0.8);
  pointer-events: none;
}
.proof-search input {
  width: 100%;
  background: rgb(var(--c-bg-rgb) / 0.72);
  border: 1px solid var(--c-smoke);
  border-radius: 999px;
  padding: 10px 18px 10px 38px;
  font-size: 13px;
  color: var(--c-ice);
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.proof-search input::placeholder { color: rgb(var(--c-data-rgb) / 0.7); }
.proof-search input:focus {
  outline: none;
  border-color: var(--c-q1);
  box-shadow: 0 0 0 1px var(--c-q1), 0 0 20px rgba(255, 87, 34, 0.2);
}
.proof-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.proof-chip {
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.6);
  color: var(--c-data);
  border-radius: 999px;
  padding: 7px 14px;
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  cursor: pointer;
  transition: all 0.25s ease;
}
.proof-chip:hover { color: var(--c-ice); border-color: rgba(255, 87, 34, 0.5); }
.proof-chip.is-active {
  background: linear-gradient(135deg, var(--c-q2), var(--c-q1));
  border-color: transparent;
  color: #FFFFFF;
}
.proof-none {
  grid-column: 1 / -1;
  color: rgb(var(--c-data-rgb) / 0.85);
  font-size: 13.5px;
  font-style: italic;
  padding: 26px 4px;
}

/* ── Proof card thumbnails ────────────────────────────────────── */

.proof-thumb {
  position: relative;
  aspect-ratio: 16 / 9;                /* rendered thumbnails are 16:9 */
  margin: -22px -22px 0;               /* bleed to the card edges */
  border-radius: 17px 17px 0 0;
  overflow: hidden;
  background:
    radial-gradient(130% 130% at 18% 0%, rgba(255, 87, 34, 0.22), transparent 55%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
/* The scenes are composed to fill the whole thumb, not sit in a corner */
.proof-thumb svg,
.proof-thumb .proof-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.proof-thumb .proof-img { object-fit: cover; display: block; user-select: none; }
.proof-card:hover .proof-thumb svg,
.proof-card:hover .proof-thumb .proof-img { transform: scale(1.03); }
.proof-thumb svg,
.proof-thumb .proof-img { transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); }
.proof-thumb::after {                   /* scanline sheen */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 40%, rgb(255 255 255 / 0.05) 50%, transparent 60%);
}
.proof-card { position: relative; }
.proof-card .proof-top { margin-top: 16px; }

/* Parallax lanes. main.js writes three offsets on #proof-grid and each card
   claims one by position, so the drift stays staggered however many drops
   the feed grows to. At three columns the lanes line up with the columns;
   narrower down to one, the same rule reads as a stagger down the list. */
#proof-grid > * {
  transform: translate3d(0, var(--pc-y, 0px), 0);
  will-change: transform;
}
#proof-grid > :nth-child(3n + 1) { --pc-y: var(--pcol-a, 0px); }
#proof-grid > :nth-child(3n + 2) { --pc-y: var(--pcol-b, 0px); }
#proof-grid > :nth-child(3n + 3) { --pc-y: var(--pcol-c, 0px); }

@media (prefers-reduced-motion: reduce) {
  #proof-grid > * { transform: none; will-change: auto; }
}
.t-system {
  background:
    radial-gradient(130% 130% at 82% 100%, rgba(255, 255, 255, 0.1), transparent 55%),
    linear-gradient(160deg, #14161C 0%, #08090C 100%);
}
.t-skill {
  background:
    radial-gradient(130% 130% at 50% 0%, rgba(255, 112, 67, 0.28), transparent 60%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
.t-brand {
  background:
    radial-gradient(130% 130% at 18% 100%, rgba(255, 255, 255, 0.08), transparent 55%),
    linear-gradient(160deg, #14161C 0%, #0B0C10 100%);
}
.t-community {
  background:
    radial-gradient(130% 130% at 50% 110%, rgba(88, 101, 242, 0.3), transparent 60%),
    linear-gradient(160deg, #14161C 0%, #0B0C10 100%);
}

/* The Discord block reads as its own thing: blurple edge, live CTA */
.proof-card.proof-discord { border-color: rgba(88, 101, 242, 0.45); }
.proof-card.proof-discord:hover {
  border-color: rgba(88, 101, 242, 0.8);
  background: rgb(var(--c-bg-rgb) / 0.82);
  transform: translateY(-3px);
}
.proof-card.proof-discord .proof-type {
  color: #A5B0FF;
  border-color: rgba(88, 101, 242, 0.55);
}
.proof-card.proof-discord .proof-link { color: #A5B0FF; }
.proof-card.proof-discord a.proof-link:hover { color: var(--c-ice); }

/* ── Kevin: the all-channels icon row ─────────────────────────── */

.social-row {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 18px;
}
.social-row a,
.social-row span {
  position: relative;
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.14);
  border-radius: 50%;
  background: rgb(var(--c-bg-rgb) / 0.7);
  color: var(--c-data);
  transition: all 0.25s ease;
}
.social-row svg { width: 21px; height: 21px; }
.social-row a:hover {
  color: var(--c-ice);
  border-color: var(--c-q2);
  box-shadow: 0 0 18px rgba(255, 87, 34, 0.3);
  transform: translateY(-2px);
}
.social-row span[aria-disabled] { opacity: 0.45; cursor: default; }
.ks-live {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22C55E;
  box-shadow: 0 0 8px rgba(34, 197, 94, 0.95);
  animation: sb-pulse 1.7s ease-in-out infinite;
}

/* ── Channels: where to find me ───────────────────────────────────
   Sits between the hero and the vault, inside the cinematic run. The
   ghosted cube behind it (camera.js handoff) is the box reference, so
   the section itself stays clean and centred. */

.channels-section {
  padding-block: clamp(44px, 6vh, 80px);
  text-align: center;
}
.channels-head h2 { margin-inline: auto; }
/* Spacing lives here, not on Tailwind utilities: the committed
   tailwind.min.css is purged and carries no mt-12 or md:mt-* variants, so
   those classes would silently do nothing in this markup. */
.carousel-wide { margin-top: 48px; }
@media (min-width: 768px) { .carousel-wide { margin-top: 56px; } }
.channels-ticker {
  margin-top: 34px;
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.24em;
  line-height: 1.9;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.6);
}
/* Phones: the three claims wrap to their own lines rather than breaking
   mid-phrase, and the section clears the fixed scoreboard bar */
@media (max-width: 640px) {
  /* Section headlines size to the column instead of a fixed 30px. At a fixed
     size a headline only had to land a pixel over to wrap to three lines with
     an ugly break, which meant re-tuning by hand every time the copy gained a
     word. Tuned for Archivo Black, which sets noticeably wider than Space
     Grotesk. Runs past the old 1.875rem cap now that a wrapped headline no
     longer slides off its own extrusion (see .h3d-q.is-atomic) — the ceiling
     here is the widest emphasised phrase, which must still fit its column on
     one line. Compound selectors because Tailwind's text-3xl matches
     .h-section's specificity. */
  #channels .h-section,
  #proof .h-section,
  #xray .h-section,
  #engine-copy .h-section,
  #kevin .h-section,
  #soon .h-section,
  #horizon .h-section {
    font-size: clamp(1.5rem, 8.4vw, 2.25rem);
  }

  /* Enough to clear the fixed scoreboard bar, no more */
  .channels-section { padding-bottom: clamp(64px, 9vh, 104px); }
  /* No max-width: the separators are nbsp-padded so the line can only break
     mid-phrase, and capping the width forced exactly that. At full width the
     three claims fit on one line. */
  .channels-ticker {
    font-size: 8px;
    letter-spacing: 0.1em;
  }
}

/* Full width earns a bigger ring than the one wedged beside the portrait */
@media (min-width: 1024px) {
  .car-stage-wide { height: 322px; perspective: 1700px; }
  .car-stage-wide .car-card { width: 360px; }
  .car-stage-wide .car-name b { font-size: 15.5px; }
  .car-stage-wide .car-name i { font-size: 12px; }
}

/* ── The program: not for sale yet ────────────────────────────────
   A rail of what has to happen before there is anything to buy. The
   pricing block it replaced is kept in this sheet on purpose — the
   program is shelved "for now", not cancelled. */

.soon-track {
  position: relative;
  max-width: 30rem;
  margin: 48px auto 0;
  text-align: left;
  display: grid;
  gap: 22px;
}
.soon-step {
  position: relative;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  align-items: start;
}
.soon-step::before {                    /* the rail between the dots */
  content: "";
  position: absolute;
  left: 8px;
  top: 21px;
  bottom: -22px;
  width: 1px;
  background: rgb(var(--c-ice-rgb) / 0.14);
}
.soon-step:last-child::before { display: none; }
.soon-dot {
  width: 17px;
  height: 17px;
  margin-top: 2px;
  border-radius: 50%;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.3);
  background: rgb(var(--c-bg-rgb) / 0.9);
}
.soon-step.is-done .soon-dot {
  border-color: var(--c-q2);
  background: var(--c-q2);
  box-shadow: 0 0 14px rgba(255, 87, 34, 0.45);
}
.soon-step.is-now .soon-dot {
  border-color: var(--c-q2);
  box-shadow: 0 0 0 3px rgba(255, 87, 34, 0.16);
  animation: sb-pulse 1.9s ease-in-out infinite;
}
.soon-body b {
  display: block;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 14.5px;
  color: var(--c-ice);
}
.soon-body em {
  display: block;
  margin-top: 4px;
  font-style: normal;
  font-size: 13px;
  line-height: 1.6;
  color: var(--c-data);
}
/* Steps still ahead read quieter than the two that are live */
.soon-step:not(.is-done):not(.is-now) .soon-body { opacity: 0.6; }
.soon-cta { margin-top: 48px; }

@media (prefers-reduced-motion: reduce) {
  .soon-step.is-now .soon-dot { animation: none; }
}

/* ── Carousel drag affordance ─────────────────────────────────── */

.car-stage { touch-action: pan-y; cursor: grab; }
.car-stage:active { cursor: grabbing; }
.car-card { user-select: none; -webkit-user-drag: none; }
.car-card img, .car-card svg { pointer-events: none; }

/* ── Light theme, round 2 ─────────────────────────────────────── */

[data-theme="light"] .proof-search input { background: rgb(255 255 255 / 0.7); }
/* :not(.is-active) — a plain override here would repaint the active chip's
   orange fill white and render its white label invisible */
[data-theme="light"] .proof-chip:not(.is-active) { background: rgb(255 255 255 / 0.6); }
[data-theme="light"] .social-row a,
[data-theme="light"] .social-row span { background: rgb(255 255 255 / 0.7); }

/* ── Legal pages ─────────────────────────────────────────────────────── */

.legal-body {
  min-height: 100vh;
  background:
    radial-gradient(900px 500px at 82% -8%, rgba(255, 87, 34, 0.12), transparent 70%),
    var(--c-bg);
}
.legal-header {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid rgb(var(--c-smoke-rgb) / 0.65);
  background: rgb(var(--c-bg-rgb) / 0.82);
  backdrop-filter: blur(16px);
}
.legal-header-inner {
  width: min(1180px, calc(100% - 40px));
  height: 64px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.legal-nav {
  display: flex;
  align-items: center;
  gap: 22px;
  margin-left: auto;
}
.legal-nav a {
  color: rgb(var(--c-data-rgb) / 0.92);
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  transition: color 0.2s ease;
}
.legal-nav a:hover,
.legal-nav a[aria-current="page"] { color: var(--c-q2); }
.legal-shell {
  position: relative;
  z-index: 1;
  width: min(1180px, calc(100% - 40px));
  margin: 0 auto;
  padding: 72px 0 110px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: clamp(48px, 7vw, 92px);
  align-items: start;
}
.legal-article { min-width: 0; max-width: 780px; }
.legal-eyebrow {
  color: var(--c-q2);
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.legal-title {
  margin-top: 14px;
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-size: clamp(2.35rem, 7vw, 4.6rem);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 0.98;
}
.legal-intro {
  max-width: 680px;
  margin-top: 24px;
  color: var(--c-data);
  font-size: 16px;
  line-height: 1.8;
}
.legal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  margin-top: 28px;
  padding: 15px 0;
  border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.75);
  border-bottom: 1px solid rgb(var(--c-smoke-rgb) / 0.75);
  color: rgb(var(--c-data-rgb) / 0.88);
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.legal-meta b { color: var(--c-ice); font-weight: 500; }
.legal-summary {
  margin-top: 34px;
  padding: 20px 22px;
  border: 1px solid rgba(255, 87, 34, 0.34);
  border-radius: 16px;
  background:
    linear-gradient(145deg, rgba(255, 87, 34, 0.08), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.7);
}
.legal-summary strong {
  display: block;
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-size: 14px;
  letter-spacing: 0.04em;
}
.legal-summary p { margin-top: 7px; color: var(--c-data); font-size: 13.5px; line-height: 1.7; }
.legal-section {
  margin-top: 54px;
  scroll-margin-top: 92px;
}
.legal-section h2 {
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.legal-section h2 .legal-num {
  display: inline-block;
  min-width: 2.5em;
  color: var(--c-q2);
  font-family: "JetBrains Mono", monospace;
  font-size: 0.42em;
  font-weight: 500;
  letter-spacing: 0.08em;
  vertical-align: 0.38em;
}
.legal-section h3 {
  margin-top: 26px;
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-size: 16px;
  font-weight: 700;
}
.legal-section p,
.legal-section li {
  color: var(--c-data);
  font-size: 14.5px;
  line-height: 1.82;
}
.legal-section p { margin-top: 14px; }
.legal-section ul,
.legal-section ol { margin: 14px 0 0 20px; }
.legal-section ul { list-style: disc; }
.legal-section ol { list-style: decimal; }
.legal-section li + li { margin-top: 8px; }
.legal-section strong { color: var(--c-ice); font-weight: 600; }
.legal-section a,
.legal-contact a { color: var(--c-q2); text-decoration: underline; text-underline-offset: 3px; }
.legal-section a:hover,
.legal-contact a:hover { color: var(--c-ice); }
.legal-table-wrap {
  margin-top: 20px;
  overflow-x: auto;
  border: 1px solid var(--c-smoke);
  border-radius: 14px;
}
.legal-table {
  width: 100%;
  min-width: 620px;
  border-collapse: collapse;
  text-align: left;
}
.legal-table th {
  padding: 12px 14px;
  background: rgb(var(--c-ice-rgb) / 0.045);
  color: var(--c-ice);
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.legal-table td {
  padding: 13px 14px;
  border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.65);
  color: var(--c-data);
  font-size: 12.5px;
  line-height: 1.6;
  vertical-align: top;
}
.legal-rail {
  position: sticky;
  top: 92px;
  border: 1px solid var(--c-smoke);
  border-radius: 16px;
  padding: 18px 20px;
  background: rgb(var(--c-bg-rgb) / 0.74);
}
.legal-rail p {
  color: var(--c-ice);
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.legal-rail ol { margin-top: 10px; }
.legal-rail a {
  display: block;
  padding: 5px 0;
  color: rgb(var(--c-data-rgb) / 0.92);
  font-size: 12px;
  line-height: 1.45;
  transition: color 0.2s ease;
}
.legal-rail a:hover { color: var(--c-q2); }
.legal-contact {
  margin-top: 56px;
  padding: 24px;
  border: 1px solid var(--c-smoke);
  border-radius: 18px;
  background: rgb(var(--c-bg-rgb) / 0.72);
}
.legal-contact h2 {
  color: var(--c-ice);
  font-family: "Instrument Sans", sans-serif;
  font-size: 20px;
  font-weight: 700;
}
.legal-contact p,
.legal-contact address { margin-top: 10px; color: var(--c-data); font-size: 13.5px; font-style: normal; line-height: 1.75; }
.legal-footer { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.65); }
.legal-footer-inner {
  width: min(1180px, calc(100% - 40px));
  margin: 0 auto;
  padding: 22px 0 30px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  color: rgb(var(--c-data-rgb) / 0.8);
  font-size: 10.5px;
  letter-spacing: 0.05em;
}
.legal-footer-links { display: flex; gap: 20px; }
.legal-footer a { color: inherit; transition: color 0.2s ease; }
.legal-footer a:hover { color: var(--c-ice); }

@media (max-width: 860px) {
  .legal-shell { grid-template-columns: 1fr; padding-top: 52px; }
  .legal-rail { display: none; }
  .legal-article { max-width: none; }
}
@media (max-width: 640px) {
  .legal-header-inner,
  .legal-shell,
  .legal-footer-inner { width: min(100% - 32px, 1180px); }
  .legal-header-inner { gap: 14px; }
  .legal-nav { gap: 12px; }
  .legal-nav a { font-size: 8.5px; letter-spacing: 0.11em; }
  .legal-nav a:first-child { display: none; }
  .legal-shell { padding: 42px 0 80px; }
  .legal-title { font-size: clamp(2.35rem, 16vw, 3.5rem); }
  .legal-intro { font-size: 15px; }
  .legal-section { margin-top: 44px; }
  .legal-section h2 .legal-num { display: block; min-width: 0; margin-bottom: 7px; vertical-align: baseline; }
}
@media (max-width: 360px) {
  .legal-header-inner { gap: 10px; }
  .legal-header .logo-lockup > span:last-child { display: none; }
  .legal-nav { gap: 10px; }
  .legal-nav a { font-size: 8px; }
}

/* ── Small screens, round 2 ───────────────────────────────────── */

@media (max-width: 640px) {
  .proof-search { max-width: none; }
  /* No height override here. The thumbs are rendered 16:9 and .proof-thumb
     already carries that aspect-ratio; pinning a height defeated it and left
     object-fit: cover to crop away nearly half of every image. */
}

/* ── Proof articles: editorial structure ──────────────────────── */

.ap-crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.8);
}
.ap-crumb a { color: inherit; transition: color 0.2s ease; }
.ap-crumb a:hover { color: var(--c-ice); }
.ap-crumb i { font-style: normal; color: var(--c-q2); }

.ap-dek { color: var(--c-data); font-size: 18px; line-height: 1.7; margin-top: 14px; }
.ap-inline-link { color: var(--c-q2); border-bottom: 1px solid rgb(255 87 34 / 0.4); }
.ap-inline-link:hover { color: var(--c-ice); border-color: var(--c-ice); }

/* ── Coming-soon page ─────────────────────────────────────────── */

/* The page opens like a hero: eyebrow, headline and dek centred and scaled
   up, so the honest "not built yet" promise lands before the status board. */
.soon-hero {
  text-align: center;
  margin-top: 44px;
}
.soon-hero .kicker {
  font-size: 11.5px;
  letter-spacing: 0.30em;
}
.soon-hero h1 {
  font-size: clamp(2.1rem, 6.4vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin-top: 18px;
  text-wrap: balance;
}
.soon-hero .ap-dek {
  font-size: clamp(16.5px, 1.9vw, 20px);
  line-height: 1.65;
  max-width: 46ch;
  margin: 20px auto 0;
  text-wrap: pretty;
}
@media (max-width: 640px) {
  .soon-hero { margin-top: 30px; }
}

/* An honest status board: what is live, what is being built, what is not
   buyable yet. Reads top-down like a build log rather than a sales list. */
.soon-status {
  margin-top: 34px;
  border: 1px solid var(--c-smoke);
  border-radius: 16px;
  background: rgb(var(--c-bg-rgb) / 0.55);
  overflow: hidden;
}
.soon-row {
  display: grid;
  grid-template-columns: 78px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 13px 16px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--c-data);
}
.soon-row + .soon-row { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.6); }
.soon-state {
  font-family: "JetBrains Mono", monospace;
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-align: center;
  border-radius: 999px;
  padding: 4px 0;
  border: 1px solid currentColor;
}
.soon-state.is-live { color: #1E9E4A; }
[data-theme="dark"] .soon-state.is-live { color: #7EE2A8; }
.soon-state.is-wip { color: var(--c-q2); }
.soon-state.is-soon { color: rgb(var(--c-data-rgb) / 0.75); }

.soon-price {
  margin-top: 40px;
  padding: 24px 26px 26px;
  border: 1px solid rgba(255, 87, 34, 0.4);
  border-radius: 18px;
  background:
    linear-gradient(150deg, rgba(255, 87, 34, 0.09), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.6);
}
.soon-amount { margin-top: 10px; color: var(--c-ice); }
.soon-amount span { font-size: 40px; font-weight: 700; letter-spacing: -0.02em; }
.soon-amount em {
  font-style: normal;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--c-data);
  margin-left: 6px;
}
.soon-price b { color: var(--c-q2); font-weight: 600; }

/* The main page's field sits on a dark card; here the card follows the theme */
.soon-input { background: rgb(var(--c-ice-rgb) / 0.06); }
[data-theme="dark"] .soon-input { background: rgb(0 0 0 / 0.45); }

.soon-cta {
  margin-top: 52px;
  padding: 30px 28px 32px;
  border: 1px solid var(--c-smoke);
  border-radius: 20px;
  background: rgb(var(--c-bg-rgb) / 0.7);
  scroll-margin-top: 88px;
}

@media (max-width: 640px) {
  .soon-row { grid-template-columns: 66px 1fr; gap: 10px; font-size: 13px; padding: 11px 13px; }
  .soon-price, .soon-cta { padding-inline: 18px; }
  .soon-amount span { font-size: 34px; }
}

.ap-byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.7);
  border-bottom: 1px solid rgb(var(--c-smoke-rgb) / 0.7);
  padding: 14px 0;
  margin-top: 26px;
}
.ap-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid rgb(var(--c-ice-rgb) / 0.16);
  background: radial-gradient(120% 120% at 30% 0%, rgba(255, 87, 34, 0.3), #171A21 72%);
  flex: none;
}
.ap-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 8%; }
.ap-byline-who { display: flex; flex-direction: column; }
.ap-byline-who b { color: var(--c-ice); font-size: 13px; font-weight: 600; }
.ap-byline-who span { color: rgb(var(--c-data-rgb) / 0.9); font-size: 11.5px; margin-top: 1px; }
.ap-byline-meta {
  margin-left: auto;
  text-align: right;
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.8);
  line-height: 1.9;
}

.ap-cover {
  position: relative;
  aspect-ratio: 16 / 9;               /* matches the rendered cover art */
  border-radius: 18px;
  overflow: hidden;
  margin-top: 28px;
  border: 1px solid rgb(var(--c-smoke-rgb) / 0.8);
  background:
    radial-gradient(130% 130% at 18% 0%, rgba(255, 87, 34, 0.24), transparent 55%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
/* Real cover art: fills the frame, retires the decorative glyph, and earns a
   bottom scrim so the exhibit label stays readable over bright artwork */
.ap-cover-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ap-cover:has(.ap-cover-img) svg { display: none; }
.ap-cover:has(.ap-cover-img)::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 52%;
  z-index: 1;
  background: linear-gradient(180deg, transparent, rgb(11 12 16 / 0.85));
}
.ap-cover b { z-index: 2; }
/* The label rides the dark scrim, so it stays bone-white in BOTH themes —
   --c-ice inverts to ink under [data-theme="light"] and would vanish here */
.ap-cover:has(.ap-cover-img) b {
  color: #FFFFFF;
  text-shadow: 0 1px 12px rgb(11 12 16 / 0.5);
}
.ap-cover svg {
  position: absolute;
  right: 3%;
  bottom: -16%;
  width: 210px;
  height: 210px;
  color: rgb(255 255 255 / 0.09);
}
.ap-cover b {
  position: absolute;
  left: 24px;
  bottom: 18px;
  font-family: "Instrument Sans", sans-serif;
  font-weight: 700;
  font-size: 21px;
  letter-spacing: 0.05em;
  color: var(--c-ice);
}
.ap-cover-cap {
  font-family: "JetBrains Mono", monospace;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(var(--c-data-rgb) / 0.7);
  margin-top: 10px;
}

.ap-toc {
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 16px;
  padding: 18px 22px;
  margin-top: 34px;
}
.ap-toc a {
  display: flex;
  gap: 9px;
  color: var(--c-data);
  font-size: 13.5px;
  padding: 4px 0;
  transition: color 0.2s ease;
}
.ap-toc a::before { content: "▸"; color: var(--c-q2); }
.ap-toc a:hover { color: var(--c-ice); }

.ap-takeaways {
  border: 1px solid rgba(255, 87, 34, 0.35);
  background:
    linear-gradient(150deg, rgba(255, 87, 34, 0.08), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 16px;
  padding: 18px 22px;
  margin-top: 18px;
}
.ap-section h2 { scroll-margin-top: 90px; }

.ap-authorbox {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 18px;
  padding: 20px 22px;
  margin-top: 56px;
}
.ap-authorbox .ap-avatar { width: 56px; height: 56px; }
.ap-authorbox b { color: var(--c-ice); font-size: 14.5px; display: block; }
.ap-authorbox p { color: var(--c-data); font-size: 13px; line-height: 1.65; margin-top: 5px; }
.ap-authorbox .ap-socials { display: flex; gap: 12px; margin-top: 10px; }
.ap-authorbox .ap-socials a {
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--c-q2);
  transition: color 0.2s ease;
}
.ap-authorbox .ap-socials a:hover { color: var(--c-ice); }

/* ── Article sidebar (lg+): sticky rail with more proof + the offer ── */

.ap-side {
  position: sticky;
  top: 92px;
  align-self: start;
  flex-direction: column;
  gap: 16px;
}
.ap-side-card {
  border: 1px solid var(--c-smoke);
  background: rgb(var(--c-bg-rgb) / 0.72);
  border-radius: 16px;
  padding: 18px 20px;
}
.side-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  color: var(--c-data);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  transition: color 0.2s ease;
}
.side-item + .side-item { border-top: 1px solid rgb(var(--c-smoke-rgb) / 0.5); }
a.side-item:hover { color: var(--c-ice); }
.side-item.is-soon { opacity: 0.6; }
.side-thumb {
  position: relative;
  width: 46px;
  height: 34px;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  background:
    radial-gradient(130% 130% at 18% 0%, rgba(255, 87, 34, 0.22), transparent 55%),
    linear-gradient(160deg, #171A21 0%, #0B0C10 100%);
}
.side-thumb svg { width: 16px; height: 16px; color: rgb(255 255 255 / 0.5); }
.side-thumb .side-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ap-side-cta {
  border-color: rgba(255, 87, 34, 0.35);
  background:
    linear-gradient(150deg, rgba(255, 87, 34, 0.09), transparent 70%),
    rgb(var(--c-bg-rgb) / 0.72);
}

/* === Responsive hardening =================================================
   These rules cover fixed chrome, dense challenge widgets, editorial pages,
   and short phone viewports without changing the desktop composition. */

img,
video {
  max-width: 100%;
  height: auto;
}

.price-name,
.swap-old,
.swap-new,
.ap-byline-who,
.site-footer-links {
  min-width: 0;
}

@media (max-width: 900px) {
  #scoreboard {
    bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }

  #hero-copy {
    bottom: calc(86px + env(safe-area-inset-bottom, 0px));
  }

  #node-panel {
    bottom: calc(82px + env(safe-area-inset-bottom, 0px));
    max-height: min(66dvh, 620px);
  }

  .engine-pin {
    padding-bottom: calc(104px + env(safe-area-inset-bottom, 0px));
  }

  .proof-toolbar {
    align-items: stretch;
  }

  .proof-search {
    flex-basis: 100%;
    max-width: none;
  }

  /* Chips wrap to tidy rows; a sideways-scrolling row reads as a
     cut-off chip with no affordance */
  .proof-filters { flex-wrap: wrap; }
  .proof-chip { flex: 0 0 auto; min-height: 40px; }
}

@media (max-width: 640px) {
  :root { --cube: clamp(145px, 42vw, 172px); }

  /* Small cube, smaller passenger */
  #cube-me { width: calc(var(--cube) * 0.28); }

  /* Section 2 on phones: the copy becomes a solid glass card, so the
     graph, cube wireframe, and satellites can NEVER mix into the text.
     The constellation itself settles into the lower half (camera + radius
     handle that); this card guarantees the separation visually. */
  #xray-copy > div {
    top: 74px;
    left: 14px;
    right: 14px;
    max-width: none;
    padding: 16px 18px 18px;
    border-radius: 16px;
    border: 1px solid rgb(var(--c-smoke-rgb) / 0.7);
    background: rgb(var(--c-bg-rgb) / 0.92);
    box-shadow: 0 12px 30px rgb(0 0 0 / 0.14);
  }

  /* Phones get a slim financial ticker. The milestone ladder already lives
     in the headline, so duplicating it here only steals CTA space. */
  #scoreboard {
    width: min(calc(100vw - 20px), 372px);
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    gap: 6px;
    padding: 7px 8px;
    border-radius: 999px;
    font-size: 8.5px;
    line-height: 1;
    letter-spacing: 0.03em;
  }
  #scoreboard .sb-ledger {
    flex: 1;
    display: grid;
    grid-template-columns: auto repeat(3, minmax(0, 1fr));
    gap: 6px;
  }
  /* Icons stay rather than disappear — the bar is the one CTA that follows you
     the whole way down the page — but not so small they can't be hit. */
  .sb-links { padding-left: 7px; gap: 1px; }
  .sb-links a,
  .sb-links span { width: 29px; height: 29px; }
  .sb-links svg { width: 13px; height: 13px; }

  #scoreboard .sb-mile { display: none; }
  #scoreboard .sb-day {
    justify-content: flex-start;
    gap: 4px;
    padding-right: 6px;
  }
  #scoreboard .sb-dot { width: 4px; height: 4px; }
  #scoreboard .sb-item {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 0;
  }
  #scoreboard .sb-item b { margin-left: 0; letter-spacing: -0.02em; }
  #scoreboard .sb-key::after { font-size: 7px; }

  body > header:not(.legal-header) > div,
  #site-header > div {
    height: 60px;
    padding-inline: 16px;
    gap: 10px;
  }

  body > header:not(.legal-header) .logo-lockup > span:last-child,
  #site-header .logo-lockup > span:last-child {
    font-size: 15px;
    margin-left: 0.42rem;
  }

  body > header:not(.legal-header) > div > div,
  #site-header > div > div {
    gap: 8px;
    flex: none;
  }

  #menu-toggle {
    width: 44px;
    height: 44px;
  }

  #theme-toggle { padding: 2px; }
  #theme-toggle button { width: 34px; height: 34px; }

  .mobile-menu {
    top: 60px;
    max-height: calc(100dvh - 60px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 8px 16px calc(18px + env(safe-area-inset-bottom, 0px));
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .mobile-menu nav > a {
    min-height: 44px;
    display: flex;
    align-items: center;
    padding-block: 10px;
  }

  .mobile-menu .mm-cta { justify-content: center; }

  /* Phones set their own scene lengths (svh, so the URL bar can't stretch
     them). These override the h-[Nvh] classes in the markup — change both
     or the desktop edit does nothing here. The pin eats 100svh, so the
     scroll each scene really gets is the remainder: 35svh and 55svh.
     The vault keeps the larger share; it has two beats to play. */
  #singularity { height: 128svh; }
  #xray { height: 155svh; }

  #hero-copy {
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-inline: 16px;
  }

  #node-panel {
    bottom: calc(48px + env(safe-area-inset-bottom, 0px));
    max-height: min(72dvh, 620px);
  }

  .hero-headline {
    width: 100%;
    /* Sized so the opening line — "R*tard is speedrunning" — holds together on
       one line at 375px (~28px is the largest the wide display face fits all
       three words in the column; measured at 360/375/414). The ledger widget
       threaded through this line is sized in em, so it scales with the type;
       .headline-ledger below keeps it inside the column. Larger phones grow it
       back up toward the 2.2rem cap. */
    font-size: clamp(1.5rem, 7.5vw, 2.2rem);
    line-height: 1.16;
  }

  .hero-method { margin-top: 0.34em; }
  /* The bar reads as its own row on phones (see the 900px block), so it gets to
     be chunkier here and the milestone marks step up to a legible size — they
     carry the headline's exact extruded material, which only reads as such once
     the glyphs are big enough to show the ramp. The summit stays a step above
     the rungs. */
  .headline-ledger { width: min(13em, 76vw); height: 0.9em; }
  .hlc-arrow b { font-size: 0.54em; }
  /* No letter-spacing here — the marks inherit --h3d-track like every other
     piece of extruded type. They used to carry their own 0.035em. */
  .hlc-marks em { font-size: 0.58em; }
  .hlc-marks .hlc-end { font-size: 0.68em; }
  /* The enlarged summit would otherwise sit its sparkle past the column edge;
     tuck the star in so the whole mark stays on-screen. */
  .hlc-marks .hlc-end::after { right: -0.5em; }

  #hero-copy > p {
    margin-top: 14px;
    font-size: 14px;
    line-height: 1.55;
  }

  .hero-actions {
    width: min(100%, 320px);
    margin-top: 20px;
    gap: 10px;
  }

  .hero-actions > a {
    width: 100%;
    min-height: 46px;
    justify-content: center;
    text-align: center;
  }

  /* Full-width card: the copy owns the top of the screen outright,
     the graph settles into the lower half beneath it */
  #xray-copy > div:first-child {
    top: 74px;
    left: 14px;
    right: 14px;
    max-width: none;
  }

  #xray-copy .hint-chips { margin-top: 16px; }
  .hint-chips li { max-width: 100%; font-size: 10px; }
  #depth-rail { right: 5px; }
  #depth-rail button { min-width: 36px; min-height: 40px; padding-inline: 8px; }

  .engine-pin { padding-top: 88px; }
  #engine-copy { gap: 32px; padding-inline: 16px; }
  /* Same clamp as every other section headline. Its own was larger, which
     left the machine title bigger than the rest on phones. This rule sits
     later in the sheet than the shared one, so it has to match rather than
     just be deleted from the shared list. */
  #engine-copy .h-section { font-size: clamp(1.5rem, 8.4vw, 2.25rem); }
  #engine-copy > div > p.text-data { font-size: 14px; }
  #engine-copy [aria-label="Some of the jobs it does"] { margin-top: 26px; }

  .swap-row {
    grid-template-columns: minmax(0, 0.9fr) auto minmax(0, 1.15fr);
    gap: 8px;
    padding: 13px 6px;
  }

  .swap-role,
  .swap-sys { overflow-wrap: anywhere; }
  .swap-new p { font-size: 11px; line-height: 1.35; }
  .term-body { height: 330px; padding: 14px; font-size: 10.5px; }
  .term-bar { padding-inline: 14px; }
  .term-bar #term-title { font-size: 8.5px; letter-spacing: 0.1em; }
  .chat-art { margin-left: 0; }
  .ca-voc li { grid-template-columns: 34px 1fr; gap: 6px; }

  #proof,
  #kevin { padding-block: 84px; }
  #pricing { padding-block: 72px; }

  .proof-card,
  .rules-card { padding: 18px; }
  .proof-strip { padding: 18px; }
  .proof-chip { min-height: 44px; padding: 9px 13px; }

  .kevin-portrait {
    top: 2%;
    bottom: auto;
    height: min(72svh, 680px);
    opacity: 0.14;
  }

  .kevin-portrait img {
    width: min(112%, 720px);
    max-width: none;
    object-position: 58% 8%;
  }

  .kevin-follow { margin-top: 56px !important; }
  .carousel-wrap { width: 100%; }
  .car-stage { height: 232px; }
  .car-card { width: 224px; }
  .car-nav { gap: 10px; }
  .car-nav button { width: 44px; height: 44px; flex: none; }
  .car-caption { min-width: 0; font-size: 8px; letter-spacing: 0.12em; line-height: 1.35; text-align: center; }
  .social-row { gap: 8px; }
  .social-row a,
  .social-row span { width: 48px; height: 48px; }

  .price-card {
    padding: 30px 14px 28px;
    border-radius: 18px;
  }

  .price-row {
    grid-template-columns: 24px minmax(0, 1fr) auto;
    gap: 8px;
    padding: 10px;
  }

  .price-name { font-size: 13px; overflow-wrap: anywhere; }
  .price-name em { font-size: 10.5px; line-height: 1.35; }
  .price-total,
  .price-today { padding-inline: 12px; }
  .price-card > .btn-quantum { display: inline-flex; width: min(100%, 320px); justify-content: center; padding-inline: 18px; }
  .price-card > p { overflow-wrap: anywhere; }

  #horizon > .flex-1 {
    padding: 92px 16px calc(118px + env(safe-area-inset-bottom, 0px));
  }

  #cta-card { padding: 24px; border-radius: 18px; }
  #access-form input,
  #access-form button { min-height: 48px; }

  #horizon footer > div {
    padding-inline: 16px;
    padding-bottom: calc(54px + env(safe-area-inset-bottom, 0px));
    text-align: center;
  }

  .site-footer-links {
    flex-wrap: wrap;
    justify-content: center;
    gap: 2px 8px;
  }
  /* 11px text is a 17px-tall tap target. Padding gives the thumb something to
     land on without changing how the row reads; the gap shrinks to absorb it. */
  .site-footer-links > a,
  .site-footer-links > span {
    padding: 9px 10px;
    display: inline-block;
  }

  body > main.grid {
    padding: 34px 16px calc(118px + env(safe-area-inset-bottom, 0px));
    gap: 40px;
  }

  .ap-dek { font-size: 16px; line-height: 1.62; }
  .ap-byline-meta { width: 100%; margin-left: 54px; text-align: left; }
  /* .ap-cover keeps its 16/9 aspect-ratio — a fixed height cropped the art */
  .ap-cover b { left: 18px; right: 18px; bottom: 16px; font-size: 18px; }
  .ap-section { margin-top: 44px; }
  .ap-section h2 { font-size: 20px; }
  .ap-section > p { font-size: 14px; line-height: 1.7; }
  .ap-toc,
  .ap-takeaways,
  .prompt-block { padding: 16px; }
  .locked-row { align-items: flex-start; padding: 12px; letter-spacing: 0.08em; overflow-wrap: anywhere; }
  .ap-cta { margin-top: 48px; padding: 30px 18px; }
  .ap-authorbox { padding: 18px; }

  .legal-summary,
  .legal-contact { padding: 18px; }
  .legal-table-wrap { max-width: 100%; overscroll-behavior-inline: contain; -webkit-overflow-scrolling: touch; }
  .legal-footer-links { flex-wrap: wrap; gap: 10px 16px; }
}

@media (max-width: 380px) {
  .hero-actions { width: 100%; }
  .car-stage { height: 214px; }
  .car-card { width: 204px; }
  .price-card { padding-inline: 10px; }
  .price-row { grid-template-columns: 20px minmax(0, 1fr) auto; gap: 6px; padding-inline: 8px; }
  .ap-byline-meta { margin-left: 0; }
  .ap-authorbox { flex-direction: column; }
}

@media (max-height: 560px) and (pointer: coarse) {
  :root { --cube: 138px; }
  #hero-copy { bottom: calc(48px + env(safe-area-inset-bottom, 0px)); }
  .hero-headline { font-size: clamp(1.15rem, 4.2vw, 1.35rem); line-height: 1.12; }
  .hero-method { margin-top: 0.2em; }
  #hero-copy > p { margin-top: 8px; font-size: 12px; line-height: 1.35; max-width: 34rem; }
  .hero-actions { margin-top: 10px; flex-direction: row; width: auto; max-width: none; }
  .hero-actions > a { width: auto; min-height: 40px; padding-block: 9px; }
  #xray-copy > div:first-child { top: 66px; max-width: min(310px, 44vw); }
  #xray-copy .hint-chips { display: none; }
  .mobile-menu nav > a { min-height: 38px; padding-block: 7px; }
}


/* ═══════════════════════════════════════════════════════════════════
   TYPE SYSTEM OVERRIDES — appended last so they win on source order
   against both this sheet and the purged Tailwind bundle (equal
   specificity, later file).
   ═══════════════════════════════════════════════════════════════════ */

/* One display voice. The hero headline and section h2s carry the compiled
   .font-display utility (Space Grotesk in tailwind.min.css until the next
   build — tailwind.config.cjs now maps display to Instrument Sans). One
   variable grotesk covers both: normal width here, the condensed 80% cut
   comes from .h-section above. */
.font-display { font-family: "Instrument Sans", sans-serif; }

/* Section titles get the true black cut. Instrument Sans maxes at 700, so
   every h2.h-section steps up to Archivo 900 — still condensed via the
   font-stretch: 80% set on .h-section above (Archivo's wdth axis covers it).
   Must sit after .font-display: the markup stacks both classes on the same
   h2, and this rule has to win the family. */
.h-section {
  font-family: "Archivo", "Instrument Sans", sans-serif;
  font-weight: 900;
}

/* The inline ledger owns its own line. With the longer hero sentence, the
   bar was wrapping onto an interior line on desktop, where its marks and
   arrow (which sit ABOVE the bar) collided with the text line above — the
   failure the 2.8rem cap was tuned to prevent. As a centered block row it
   gets clean air at every width; mobile already wrapped it this way. Wider
   than the old inline clamp so it reads as the climb visual, not a word. */
.hero-headline .headline-ledger {
  display: block;
  width: clamp(11em, 80vw, 15em);
  /* The 0.85em top margin is load-bearing: the marks ruler (~0.74em) and the
     arrow are absolutely positioned ABOVE the bar's box, so without reserved
     flow space they paint over the text line above. As an inline-block the
     line box donated that space; as a block it has to be explicit. */
  margin: 0.85em auto 0.04em;
}
