/* the wordmark's face — self-hosted, so the page still makes zero third-party requests.
   The one root-absolute path in the whole set: the font lives beside the page folder, not inside
   it (public/fonts/ → /fonts/), and stays at /fonts/ whether the pages are served from /comps/ or
   from the web root. Everything else resolves relative to the folder — see BASE in site.js. */
  @font-face {
    font-family: "Cal Sans";
    src: local("Cal Sans"), local("CalSans-Regular"), url("/fonts/CalSans-Regular.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
  }

  /* The same face again at 600, because the product lockup asks for it by weight.
     Cal Sans is drawn in one weight and ships under both filenames — the two woff2
     files are byte-identical, checked — but the lockup's fit was measured against
     the SemiBold file the rest of Foxora serves, so this sheet serves the same one
     under the same name. Declaring the face at 600 also keeps the browser from
     synthesising a bold out of the Regular, which would thicken the product name
     off the artwork. The 400 face above is untouched: it is what every other piece
     of brand type on this sheet still asks for. */
  /* IBM Plex Sans Light — the product name's face. SIL OFL, self-hosted like every
     other face here, so the sheet still makes no third-party request. */
  @font-face {
    font-family: "fx-plexsans";
    src: url("/fonts/plexsans-300.woff2") format("woff2");
    font-weight: 300; font-style: normal; font-display: swap;
  }
  @font-face {
    font-family: "Cal Sans";
    src: local("Cal Sans"), local("CalSans-SemiBold"), url("/fonts/CalSans-SemiBold.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
  }

  /* ==================================================== tokens & base */
  :root {
    --paper: #f4eee1;
    --paper-hi: #fbf7ec;
    --band-ink: #241c31;
    --band-ink2: #2c2240;
    --ink: #231c2b;
    --ink-soft: #5b5268;
    --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #4b3ba8; --v2: #5c36ac; --v3: #6e32a6; --v4: #84309f; --v5: #992e92;
    --deep: #533d7a;
    --rule: rgba(75, 59, 168, 0.24);
    --rule-soft: rgba(75, 59, 168, 0.14);
    --frame-rule: rgba(75, 59, 168, 0.46);
    --grid-minor: rgba(75, 59, 168, 0.03);
    --grid-major: color-mix(in srgb, var(--v1) 6%, transparent);
    /* theme hooks — every palette below is only these tokens */
    --pop: #533d7a; --pop-ink: #fbf7ec;          /* buttons + the result tile */
    --deep2: #5d4488; --tear: #57407e;           /* close-band gradient start, tear colour */
    --on-deep: #cdb9f2;                          /* small labels on deep surfaces */
    --band-label: #b9a7e6; --band-label-b: #d98fd0;
    --ghost: rgba(75, 59, 168, 0.12);
    --aur1: rgba(92, 54, 172, 0.13); --aur2: rgba(132, 48, 159, 0.16);
    /* THE SITE'S TYPE, chosen 2026-08-22 for every page: Playfair Display 700 (italic 400) for display,
       Source Serif 4 for copy, JetBrains Mono for labels — self-hosted full Latin files in /fonts, named
       FIRST so the sheet reads the same on every machine; Didot / Charter / Menlo stay behind as fallbacks. */
    --display: "fx-playfair", "Playfair Display", "Didot", "Bodoni 72", "Hoefler Text", Georgia, serif;
    --sub: "fx-sourceserif", "Source Serif 4", "Charter", "Iowan Old Style", Georgia, serif;
    --chip: "fx-jetbrains", "JetBrains Mono", "Menlo", "SF Mono", ui-monospace, monospace;
    --sans: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
    --serif: "fx-sourceserif", "Source Serif 4", "Charter", "Iowan Old Style", Georgia, serif;
    --brand: "Cal Sans", "Avenir Next", system-ui, sans-serif;
    --body: "fx-sourceserif", "Source Serif 4", "Charter", "Iowan Old Style", Georgia, serif;
    --mono: "fx-jetbrains", "JetBrains Mono", "Menlo", "SF Mono", ui-monospace, monospace;
    --v4-ink: color-mix(in srgb, var(--v4) 60%, var(--ink));   /* --v4 is a fill tone; this is the legible one */
    --thunk: cubic-bezier(.2, 1.4, .4, 1);
    --shadow-card: 0 16px 36px -26px color-mix(in srgb, var(--deep) 42%, transparent);
    --shadow-obj: 0 30px 60px -32px color-mix(in srgb, var(--deep) 52%, transparent);
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
  body {
    font-family: var(--body);
    background:
      linear-gradient(var(--grid-minor) 1px, transparent 1px),
      linear-gradient(90deg, var(--grid-minor) 1px, transparent 1px),
      linear-gradient(var(--grid-major) 1px, transparent 1px),
      linear-gradient(90deg, var(--grid-major) 1px, transparent 1px),
      radial-gradient(1000px 600px at 12% -6%, color-mix(in srgb, var(--v2) 7%, transparent), transparent 65%),
      radial-gradient(900px 560px at 96% 12%, color-mix(in srgb, var(--v5) 5%, transparent), transparent 60%),
      var(--paper);
    background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px, auto, auto, auto;
    background-attachment: scroll;
    color: var(--ink);
    line-height: 1.5;
    overflow-x: hidden;
  }
  ::selection { background: color-mix(in srgb, var(--v3) 22%, transparent); }
  a { color: inherit; text-decoration: none; }
  svg { display: block; }
  .mono { font-family: var(--mono); }
  .wrap { max-width: 1200px; margin: 0 auto; padding: 0 44px; }

  /* paper grain, page-wide, cheap (tiled data-uri) */
  .grain { position: fixed; inset: 0; z-index: 80; pointer-events: none; opacity: 0.028;
    /* No blend mode. At 2.8% opacity multiply is indistinguishable from normal,
       but it forces the compositor to re-blend the whole viewport on every frame —
       measured at roughly 17ms a frame, which is most of a frame budget for a
       texture nobody can see. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E"); }

  /* blueprint frame */
  .frame { position: fixed; inset: 0; pointer-events: none; z-index: 70; }
  /* the sheet's edges are a section cut: two dotted rules with the cut hatched between */
  .frame i { position: absolute; top: 0; bottom: 0; width: 26px;
    border-left: 1px dotted var(--frame-rule); border-right: 1px dotted var(--frame-rule);
    background-image: repeating-linear-gradient(45deg,
      color-mix(in srgb, var(--frame-rule) 38%, transparent) 0 1px, transparent 1px 11px); }
  .frame i:first-child { left: 18px; }
  .frame i:last-child { right: 18px; }
  @media (max-width: 900px) { .frame i { width: 13px; } }
  .frame::before, .frame::after { content: "+"; position: absolute; top: 4px; font-family: var(--mono); font-size: 14px; line-height: 1; color: var(--frame-rule); }
  .frame::before { left: 24px; }
  .frame::after { right: 24px; }

  /* scroll progress */
  .progress { position: fixed; top: 0; left: 0; right: 0; height: 2.5px; background: linear-gradient(90deg, var(--v1), var(--v5)); transform-origin: 0 50%; transform: scaleX(0); z-index: 90; }

  /* ==================================================== reveal system */
  .rv { opacity: 0; transform: translateY(22px); transition: opacity .7s ease, transform .7s cubic-bezier(.22,1,.36,1); transition-delay: var(--d, 0s); }
  .rv.on { opacity: 1; transform: none; }
  .rv-scale { opacity: 0; transform: scale(.94); transition: opacity .6s ease, transform .6s cubic-bezier(.22,1,.36,1); transition-delay: var(--d, 0s); }
  .rv-scale.on { opacity: 1; transform: none; }
  .thunk { opacity: 0; transform: scale(1.8) rotate(var(--rot, -8deg)); filter: blur(2px); transition: opacity .3s ease, filter .3s ease, transform .45s var(--thunk); transition-delay: var(--d, 0s); }
  .thunk.on { opacity: var(--o, 0.92); transform: scale(1) rotate(var(--rot, -8deg)); filter: none; }
  @media (prefers-reduced-motion: reduce) {
    .rv, .rv-scale, .thunk { opacity: 1 !important; transform: scale(1) rotate(var(--rot, 0deg)) !important; filter: none !important; transition: none !important; }
    html { scroll-behavior: auto; }
  }

  /* ==================================================== shared pieces */
  .btn {
    display: inline-flex; align-items: center; gap: 9px;
    font-family: var(--mono); font-size: 13.5px;
    background: var(--pop); color: var(--pop-ink);
    padding: 13px 21px; border-radius: 2px; border: 1px solid var(--pop);
    box-shadow: 0 1px 0 rgba(35,28,43,.35), inset 0 1px 0 rgba(255,255,255,.14);
    transition: background .2s, border-color .2s, transform .15s;
  }
  .btn:hover { background: var(--v3); border-color: var(--v3); transform: translateY(-1px); }
  .btn.hollow { background: transparent; color: var(--ink); border: 1px solid rgba(35,28,43,.45); box-shadow: none; }
  .btn.hollow:hover { border-color: var(--v3); color: var(--v3); background: transparent; }
  .btn svg { width: 15px; height: 15px; fill: currentColor; }
  .band .btn.hollow { color: #efe9f6; border-color: rgba(239,233,246,.5); }
  .band .btn.hollow:hover { color: #fff; border-color: #fff; }

  .chapter {
    display: flex; align-items: center; gap: 12px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.28em; text-transform: uppercase;
    color: var(--v3); margin-bottom: 20px;
  }
  .chapter b { color: var(--v3); font-weight: 400; }
  .chapter::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
  .band .chapter { color: var(--band-label); }
  .band .chapter b { color: var(--band-label-b); }
  .band .chapter::after { background: var(--band-label); opacity: .3; }

  h2 { font-family: var(--display); font-weight: 700; font-size: clamp(34px, 3.2vw, 44px); line-height: 1.06; letter-spacing: -0.004em; text-wrap: balance; margin-bottom: 18px; }
  .lede { font-size: 17.5px; line-height: 1.62; color: var(--ink-soft); max-width: 70ch; }
  .band h2 { color: #f2ecfa; }
  .band .lede { color: #b6abcf; }

  .stamp-el {
    display: inline-block; position: relative; text-align: center;
    border: 2.5px solid currentColor; border-radius: 7px;
    padding: 8px 14px; mix-blend-mode: multiply;
    font-family: var(--mono); text-transform: uppercase;
  }
  /* stamps carry real sentences. mix-blend-mode: multiply is what makes them read as ink;
     the extra 8% of transparency only cost contrast — 4.43:1 measured on the paper — so the
     stamp lands at full strength and the blend mode does the work. */
  .stamp-el.thunk.on { opacity: var(--o, 1); }
  .stamp-el::before { content: ""; position: absolute; inset: 3px; border: 1px solid currentColor; border-radius: 4px; }
  .stamp-el b { display: block; font-size: 15px; letter-spacing: 0.2em; font-weight: 700; }
  .stamp-el span { display: block; font-size: 8.5px; letter-spacing: 0.16em; margin-top: 2px; }

  .ghost-n {
    position: absolute; top: 18px; right: max(48px, calc((100vw - 1200px) / 2));
    font-family: var(--display); font-weight: 400; font-size: clamp(200px, 21vw, 320px); line-height: .9;
    color: transparent; -webkit-text-stroke: 1px var(--ghost);
    pointer-events: none; user-select: none; z-index: 0;
  }
  .band .ghost-n { -webkit-text-stroke-color: color-mix(in srgb, var(--band-label) 16%, transparent); }

  .fig-tab {
    position: absolute; top: -1px; left: -1px; z-index: 2;
    font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase;
    background: var(--ink); color: var(--paper-hi); padding: 5px 11px;
  }

  section { position: relative; overflow: hidden; }

  /* ============================================================ notice */
  /* ---- skip link: the first thing in the tab order, invisible until it is focused.
     Fixed, so it can never move the sheet a pixel; it lands on <main id="main">. */
  .skip { position: fixed; top: 0; left: 0; z-index: 200; transform: translateY(-140%);
    background: var(--pop); color: var(--pop-ink); border: 1px solid var(--ink); border-top: 0;
    font-family: var(--mono); font-size: 12px; letter-spacing: .06em; padding: 12px 18px; }
  .skip:focus { transform: none; }

  .notice { background: var(--deep); color: #efe9f6; text-align: center; position: relative; z-index: 41; }
  .notice a { display: block; padding: 8px 20px; font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em; }
  .notice i { font-style: normal; color: var(--on-deep); }
  .notice a:hover i { text-decoration: underline; }

  /* =============================================================== nav */
  nav {
    border-bottom: 1px solid var(--rule);
    background: color-mix(in srgb, var(--paper-hi) 94%, transparent);
    backdrop-filter: blur(8px);
    position: sticky; top: 0; z-index: 40;
  }
  nav .wrap { display: flex; align-items: center; justify-content: space-between; gap: 26px; height: 64px; }
  .brand { display: flex; align-items: center; }

  /* ---- the product lockup: the drawn Foxora artwork, then one product name set
     live beside it on the same baseline and at the same x-height. None of this is
     eyeballed. In the artwork's own coordinates (viewBox 3737×1170) the letters
     stand on a baseline at y=900 with their x-height topping out at y=432, so at a
     lockup height H the baseline falls 0.769231H below the top edge and the drawn
     x-height measures 0.4H. Cal Sans carries an x-height of 0.52em, so a name set
     at 0.4H / 0.52 = 0.769231H matches the drawn x-height exactly, and its capitals
     then land just under the f's ascender, which is where a cap belongs against one.

     The two baselines are joined by the line box itself rather than by arithmetic on
     font metrics: the name sits on the line's own baseline, and the artwork — an
     <img>, and so a replaced element whose baseline is its own bottom edge — is
     dropped the difference, H - 0.769231H, until its drawn baseline lands on that
     same line. Every measure below is a multiple of H, so the lockup holds at any
     size: set --fx-lk-h and nothing else moves.

     The name is set in the artwork's own ink, not the sheet's. --ink turns with the
     palette — #231c2b on the cream, #0b1f17 on the seafoam, #0f1030 on the indigo —
     and the drawn half cannot follow it, so the two halves drifted apart in colour:
     measured against the letters the artwork actually draws, the typeset half sat
     ΔE76 15 to 25 away, and the distance changed every time the palette did. One
     wordmark cannot be two colours. #111110 is the mark's own tile ink, a hair off
     the black the letters are drawn in (ΔE76 5.1) and neutral enough to read on all
     fifteen light papers. It would still vanish on a dark ground, which is why the
     footer, sitting on the deep violet, keeps its own light mark instead of this
     lockup — see .foot-brand — and why --fx-lk-ink is left as the way out. */
  .fx-lockup {
    /* The height, and the only figure to change. site.js reserves the artwork's box
       at this same number (LOCKUP_H) so the header does not jump while the file
       loads; move one and move the other. */
    --fx-lk-h: 26px;
    display: inline-block;
    /* The product name is set in IBM Plex Sans Light, not the brand face: Cal Sans
       has a single master — an identical stem at every weight — so a lighter word
       beside the heavy drawn letters is only reachable in another face. Its own
       metrics drive the fit: a 0.512em x-height puts the size at 0.4H / 0.512. */
    font-family: "fx-plexsans", "IBM Plex Sans", system-ui, sans-serif;
    font-weight: 300;
    font-size: calc(var(--fx-lk-h) * 0.78125);
    line-height: 1;
    white-space: nowrap;
    color: var(--fx-lk-ink, #000000);
  }
  .fx-lockup-art {
    /* The one declaration that is load-bearing rather than decorative: a reset that
       lays images out as blocks (Tailwind's preflight, normalize) takes the artwork
       out of the line, and the name drops to a second line under it. The join is
       made in an inline formatting context or it is not made at all. */
    display: inline-block;
    height: var(--fx-lk-h);
    width: auto;
    vertical-align: calc(var(--fx-lk-h) * -0.230769);
    /* One word space in this face: Cal Sans carries a 0.164em space and the
       artwork ships 29 units of trailing bearing, so the CSS supplies the rest.
       Plex Light's space is 0.236em, wider than Cal Sans's, so this moves with it. */
    margin-right: calc(var(--fx-lk-h) * 0.15959);
  }
  /* The name stays in Cal Sans as the type designer drew it — light against the
     heavy logo. The artwork's own lettering is stroke-expanded (at a matched
     x-height its stems measure 139 units against the face's 121), so the two
     halves differ in weight on purpose: the drawn word carries the brand, the
     set word names the product. Weight is the only axis that differs — baseline,
     x-height and word space are all the artwork's own. */
  /* The footer sits on the deep violet: the lockup swaps to the light inking of
     the same artwork, and the name follows it to the cream the drawing uses. */
  .fx-lockup--foot { --fx-lk-h: 22px; --fx-lk-ink: #F1EDE4; }
  /* The ink is stated here rather than inherited: the sheet colours prose by
     container, and the deep footer paints the spans it holds, which outranks
     .fx-lockup and would leave the set word a different colour from the drawn
     letters beside it. The class is doubled on purpose, to clear those rules
     rather than to chase each one. */
  .fx-lockup.fx-lockup .fx-lockup-name {
    font: inherit;
    letter-spacing: 0;
    color: var(--fx-lk-ink, #000000);
  }
  .links { display: flex; gap: 22px; font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); }
  .links a:hover { color: var(--v3); }
  .nav-right { display: flex; align-items: center; gap: 14px; }
  .seats-chip {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--v3); border: 1px solid var(--rule); border-radius: 999px; padding: 7px 13px;
  }
  .seats-chip i { width: 7px; height: 7px; border-radius: 50%; background: var(--v4); animation: pulse 2.2s ease-in-out infinite; }
  @keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--v4) 50%, transparent); } 55% { box-shadow: 0 0 0 6px transparent; } }
  .seats-chip:hover { border-color: var(--v3); }

  /* ============================================================== hero */
  .hero { position: relative; overflow: hidden; }
  .aurora { position: absolute; border-radius: 50%; filter: blur(90px); pointer-events: none; }
  .aurora.a1 { width: 640px; height: 520px; left: -180px; top: -140px; background: var(--aur1); animation: drift1 26s ease-in-out infinite alternate; }
  .aurora.a2 { width: 820px; height: 640px; right: -180px; top: 20px; background: var(--aur2); animation: drift2 32s ease-in-out infinite alternate, breathe 9s ease-in-out infinite; }
  @keyframes breathe { 0%, 100% { opacity: .85; } 50% { opacity: 1; } }
  @keyframes drift1 { from { transform: translate(0,0) scale(1); } to { transform: translate(70px, 40px) scale(1.12); } }
  @keyframes drift2 { from { transform: translate(0,0) scale(1.06); } to { transform: translate(-80px, -30px) scale(0.96); } }
  @media (prefers-reduced-motion: reduce) { .aurora, .seats-chip i { animation: none !important; } }

  .hero .wrap { display: grid; grid-template-columns: 1.04fr .96fr; gap: 84px; align-items: start; padding-top: 72px; padding-bottom: 76px; position: relative; z-index: 1; }
  .classline { display: flex; align-items: center; gap: 14px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .3em; text-transform: uppercase; color: var(--v3); margin-bottom: 26px; }
  .classline::before { content: ""; width: 34px; height: 1px; background: var(--rule); }
  .classline::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
  h1 { font-family: var(--display); font-weight: 700; font-size: clamp(42px, 4.6vw, 66px); line-height: 1.03; letter-spacing: -.005em; text-wrap: balance; margin-bottom: 16px; }
  h1 em { font-style: italic; font-weight: 400; }
  .dim { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; max-width: 520px; }
  .dim .tick { width: 1px; height: 11px; background: var(--v3); flex: none; }
  .dim .line { flex: 1; height: 1px; background: var(--v3); position: relative; }
  .dim .line.l::before { content: ""; position: absolute; left: 0; top: -3px; border: 3.5px solid transparent; border-right-color: var(--v3); transform: translateX(-2px); }
  .dim .line.r::before { content: ""; position: absolute; right: 0; top: -3px; border: 3.5px solid transparent; border-left-color: var(--v3); transform: translateX(2px); }
  .dim span { font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--v3); }
  .what {
    font-size: 18.5px; line-height: 1.62; color: var(--ink-soft); max-width: 52ch; margin-bottom: 14px;
  }
  .what b { color: var(--ink); font-weight: 700; }
  .sub { font-size: 16.5px; line-height: 1.6; color: var(--ink-soft); max-width: 52ch; margin-bottom: 30px; }
  .cta-row { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
  .cta-note { font-family: var(--mono); font-size: 10.5px; letter-spacing: .04em; color: var(--ink-faint); margin-bottom: 36px; }
  .cta-note i { font-style: normal; color: var(--v4-ink); padding: 0 3px; }

  /* the vision stat — small, sim-style: a rule, a number, one line */
  .gap-stat { display: inline-flex; align-items: baseline; gap: 12px; border-left: 2px solid var(--v1); padding: 2px 0 2px 14px; margin: 4px 0 22px; }
  .gap-stat b { font-family: var(--mono); font-size: 15px; letter-spacing: .02em; color: var(--v1); font-weight: 700; }
  .gap-stat span { font-family: var(--mono); font-size: 11px; letter-spacing: .04em; color: var(--ink-soft); white-space: nowrap; }
  @media (max-width: 720px) { .gap-stat span { white-space: normal; } }

  /* receipt (hero object) */
  .receipt-col { position: relative; display: flex; flex-direction: column; align-items: flex-end; }

  /* the printer: a job is typed, the box leaves, the slot rises, the paper feeds out
     line by line, the stamp lands, the receipt is torn off — then the next job. */
  .printer { position: relative; width: 100%; max-width: 424px; min-height: 596px; }
  .prompt {
    position: absolute; top: 0; left: 0; right: 0; z-index: 3; height: 158px;
    background: var(--paper-hi); border: 1px solid rgba(35,28,43,.28);
    box-shadow: var(--shadow-card);
    padding: 12px 16px 12px;
    opacity: 0; transform: translateY(12px);
    transition: opacity .45s ease, transform .6s cubic-bezier(.22,1,.36,1);
  }
  .prompt.in { opacity: 1; transform: none; }
  .prompt.out { opacity: 0; transform: translateY(-16px) scale(.985); transition: opacity .38s ease, transform .5s ease; }
  .pr-label { display: flex; justify-content: space-between; align-items: baseline; font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 8px; }
  .pr-role { font-style: normal; color: var(--v3); letter-spacing: .18em; }
  .pr-field { height: 74px; overflow: hidden; font-family: var(--body); font-size: 16.5px; line-height: 1.45; color: var(--ink); }
  .pr-caret { display: inline-block; width: 2px; height: 1.05em; background: var(--v3); vertical-align: -0.15em; margin-left: 2px; animation: blink 1.05s steps(1) infinite; }
  .prompt.out .pr-caret, .prompt.done .pr-caret { display: none; }
  .pr-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 8px; padding-top: 9px; border-top: 1px dashed var(--rule); }
  .pr-hint { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; color: var(--ink-faint); }
  .pr-run { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; padding: 6px 12px; background: var(--pop); color: var(--pop-ink); border-radius: 2px; transition: transform .12s ease, filter .12s ease; }
  .pr-run.pressed { transform: scale(.94); filter: brightness(.9); }
  /* the paper hums a little while it prints */
  .printer.humming .feed { animation: hum .09s linear infinite; }
  @keyframes hum { 0%,100% { transform: translateX(0); } 50% { transform: translateX(.6px); } }
  /* the feed window: clips only at the top edge — the paper emerges from an unseen slot; never clips sides or bottom */
  .feed { position: absolute; left: 0; right: 0; top: 163px; bottom: -40px; z-index: 1; clip-path: inset(0 -60px -400px -60px); transition: top .65s cubic-bezier(.22,1,.36,1); }
  .printer.fed .feed { top: 8px; }
  .feed .receipt { transform: translateY(-104%) rotate(.5deg); }
  .feed .receipt.printing { animation: feed-out 2.4s steps(46, end) forwards; }
  @keyframes feed-out { from { transform: translateY(-104%) rotate(.5deg); } to { transform: translateY(0) rotate(.5deg); } }
  .feed .receipt.printed { transform: translateY(0) rotate(.5deg); animation: none; }
  .feed .receipt.torn { transition: transform .5s cubic-bezier(.4,0,.8,.4), opacity .42s ease .08s; transform: translateY(54px) rotate(1.6deg); opacity: 0; }
  @media (prefers-reduced-motion: reduce) {
    .feed .receipt { transform: rotate(.5deg) !important; animation: none !important; }
    .prompt, .feed { transition: none !important; }
    .printer.humming .feed { animation: none; }
  }
  @media (max-width: 860px) { .printer { min-height: 700px; } }

  .receipt {
    position: relative; width: 100%; max-width: 424px;
    background: var(--paper-hi); transform: rotate(.5deg);
    box-shadow: var(--shadow-obj);
    padding: 34px 30px 24px;
    font-family: var(--mono); font-size: 12.5px; line-height: 1.75; color: var(--ink);
  }
  .receipt::before, .receipt::after { content: ""; position: absolute; left: 0; right: 0; height: 10px; background-repeat: repeat-x; background-size: 14px 10px; }
  .receipt::before { top: -9px; background-image: linear-gradient(45deg, transparent 7px, var(--paper-hi) 7px), linear-gradient(-45deg, transparent 7px, var(--paper-hi) 7px); }
  .receipt::after { bottom: -9px; background-image: linear-gradient(135deg, transparent 7px, var(--paper-hi) 7px), linear-gradient(-135deg, transparent 7px, var(--paper-hi) 7px); }
  .rc-head { text-align: center; margin-bottom: 12px; }
  .rc-head .rc-mark { width: 26px; height: 26px; margin: 0 auto 8px; opacity: .9; }
  .rc-head b { display: block; font-size: 14px; letter-spacing: .3em; }
  .rc-head span { display: block; font-size: 10px; letter-spacing: .24em; color: var(--ink-soft); margin-top: 3px; }
  .rc-rule { border: none; border-top: 1px dashed rgba(35,28,43,.35); margin: 12px 0; }
  .rc-row { display: flex; align-items: baseline; gap: 8px; }
  .rc-row .k { white-space: nowrap; color: var(--ink-soft); }
  .rc-row .lead { flex: 1; border-bottom: 2px dotted rgba(35,28,43,.3); transform: translateY(-4px); }
  .rc-row .val { white-space: nowrap; }
  .rc-row .val.strong { font-weight: 700; }
  .rc-stage { display: flex; gap: 10px; align-items: baseline; }
  .rc-stage .n { color: var(--v3); width: 20px; flex: none; }
  .rc-stage .s { width: 92px; flex: none; font-weight: 700; letter-spacing: .04em; }
  .rc-stage .d { color: var(--ink-soft); }
  .rc-refused { color: var(--v5); font-weight: 700; }
  .rc-refused-note { color: var(--ink-soft); font-size: 11px; padding-left: 14px; }
  .rc-barcode { height: 34px; margin: 14px 6px 6px; opacity: .85;
    background: repeating-linear-gradient(90deg, var(--ink) 0 2px, transparent 2px 5px, var(--ink) 5px 6px, transparent 6px 8px, var(--ink) 8px 12px, transparent 12px 14px, var(--ink) 14px 15px, transparent 15px 20px, var(--ink) 20px 23px, transparent 23px 25px); }
  .rc-serial { text-align: center; font-size: 10px; letter-spacing: .3em; color: var(--ink-soft); }
  .receipt .stamp-el.settled { position: absolute; right: -18px; top: 43%; color: var(--v4-ink); --rot: -8deg; }
  .receipt-caption { max-width: 424px; margin-top: 24px; font-size: 13px; font-style: italic; color: var(--ink-soft); text-align: center; line-height: 1.55; }

  /* ======================================================== trust band */
  .trust { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); background: color-mix(in srgb, var(--paper-hi) 62%, transparent); }
  .trust .wrap { display: grid; grid-template-columns: repeat(4, 1fr) 96px; }
  .t-cell { padding: 20px 24px; border-left: 1px solid var(--rule-soft); display: flex; align-items: baseline; gap: 12px; }
  .t-cell:first-child { border-left: none; }
  .t-cell b { font-family: var(--display); font-size: 38px; line-height: 1; }
  .t-cell span { font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); line-height: 1.6; }
  .t-cell .chk { color: var(--v3); }

  /* =========================================================== problem */
  .problem { background: linear-gradient(160deg, var(--band-ink) 0%, var(--band-ink2) 100%); }
  .problem .wrap { padding-top: 92px; padding-bottom: 96px; position: relative; z-index: 1; }
  .problem .ghost-n { top: 20px; }
  .slips { display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; margin-top: 52px; }
  .slip {
    position: relative; background: var(--paper-hi); color: var(--ink);
    padding: 20px 18px 24px;
    box-shadow: 0 22px 40px -22px rgba(0,0,0,.55);
  }
  .slip::after { content: ""; position: absolute; left: 0; right: 0; bottom: -8px; height: 8px; background-repeat: repeat-x; background-size: 12px 8px;
    background-image: linear-gradient(135deg, transparent 6px, var(--paper-hi) 6px), linear-gradient(-135deg, transparent 6px, var(--paper-hi) 6px); }
  .slip:nth-child(odd) { transform: rotate(-.7deg); }
  .slip:nth-child(even) { transform: rotate(.6deg); }
  .slip .s-n { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--v3); display: block; margin-bottom: 10px; }
  .slip h3 { font-family: var(--display); font-size: 19px; line-height: 1.15; margin-bottom: 7px; }
  .slip p { font-size: 13px; line-height: 1.5; color: var(--ink-soft); }
  .slip .s-state { display: inline-block; margin-top: 12px; font-family: var(--mono); font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--v5); border: 1px solid currentColor; padding: 3px 8px; border-radius: 999px; }
  .problem .turn { margin-top: 54px; font-family: var(--display); font-style: italic; font-size: 24px; color: #e8def5; text-align: center; }
  .problem .turn b { font-style: normal; color: #fff; }

  /* ======================================================= how it works */
  .how .wrap { padding-top: 92px; padding-bottom: 84px; }
  .steps { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; margin-top: 38px; }
  .step { position: relative; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.14); border-top: 2px solid var(--ink); padding: 20px 22px; box-shadow: var(--shadow-card); }
  .step .st-n { font-family: var(--mono); font-size: 11px; letter-spacing: 0.22em; color: var(--v3); }
  .step b { display: block; font-size: 17.5px; margin: 9px 0 7px; font-family: var(--body); font-weight: 700; }
  .step p { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); }
  .step .st-art { margin: 16px 0 12px; border: 1px dashed var(--rule); background: var(--paper); padding: 12px 14px; font-family: var(--mono); font-size: 11.5px; color: var(--ink); }
  .step .st-art .car { display: inline-block; width: 7px; height: 12px; background: var(--v3); vertical-align: middle; margin-right: 8px; animation: blink 1.1s steps(1) infinite; }
  @keyframes blink { 0%,55% { opacity: 1; } 56%,100% { opacity: .1; } }
  .step .st-chips { display: flex; gap: 8px; }
  .step .st-chips span { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; padding: 5px 10px; border-radius: 2px; border: 1px solid var(--rule); color: var(--v3); }
  .step .st-chips .wait { color: var(--ink); border-color: rgba(35,28,43,.4); }
  .step .st-receipt { display: grid; gap: 3px; }
  .step .st-receipt span { display: flex; justify-content: space-between; }
  .step .st-aside { font-size: 12.5px; font-style: italic; color: var(--ink-faint); }

  /* ========================================================= the spine */
  .spine { background: transparent; border-top: 3px double var(--rule); }
  .spine .wrap { padding-top: 92px; padding-bottom: 96px; }
  .spine .ghost-n { top: 30px; }
  .spine-grid { display: grid; grid-template-columns: 420px 1fr; gap: 70px; align-items: start; margin-top: 40px; }
  .sp-receipt-hold { position: sticky; top: 100px; }
  .sp-receipt { position: relative; background: var(--paper); box-shadow: var(--shadow-obj); padding: 30px 28px 22px; font-family: var(--mono); font-size: 12.5px; line-height: 1.8; }
  .sp-receipt::after { content: ""; position: absolute; left: 0; right: 0; bottom: -9px; height: 10px; background-repeat: repeat-x; background-size: 14px 10px;
    background-image: linear-gradient(135deg, transparent 7px, var(--paper) 7px), linear-gradient(-135deg, transparent 7px, var(--paper) 7px); }
  .sp-receipt .rc-head b { letter-spacing: .26em; }
  .sp-line { display: flex; gap: 10px; align-items: baseline; opacity: .12; transform: translateY(4px); transition: opacity .5s ease, transform .5s ease; }
  .sp-line.printed { opacity: 1; transform: none; }
  .sp-line .n { color: var(--v3); width: 22px; flex: none; }
  .sp-line .s { width: 96px; flex: none; font-weight: 700; }
  .sp-line .d { color: var(--ink-soft); }
  .sp-receipt .stamp-el.settled2 { position: absolute; right: -16px; top: 12px; color: var(--v4-ink); --rot: -7deg; }
  .sp-stages { display: grid; gap: 0; }
  .sp-stage { padding: 18px 0 20px; border-bottom: 1px solid var(--rule-soft); display: grid; grid-template-columns: 56px 1fr; gap: 20px; }
  .sp-stage:first-child { border-top: 1px solid var(--rule-soft); }
  .sp-stage .n { font-family: var(--display); font-size: 24px; color: var(--v3); padding-top: 2px; }
  .sp-stage h3 { font-family: var(--body); font-weight: 700; font-size: 18.5px; margin-bottom: 5px; }
  .sp-stage .plain { font-size: 15px; line-height: 1.55; color: var(--ink-soft); margin-bottom: 6px; }
  .sp-stage .tech { font-size: 13.5px; line-height: 1.5; color: var(--ink-faint); }
  .sp-stage code { font-family: var(--mono); font-size: 11px; color: var(--v3); border-bottom: 1px dotted var(--v3); padding-bottom: 1px; }

  /* ================================================================ l5 */
  .l5 .wrap { padding-top: 92px; padding-bottom: 90px; }
  .stair { position: relative; display: flex; align-items: flex-end; gap: 14px; margin: 58px 0 34px; padding-top: 26px; }
  .tread { flex: 1; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.16); border-top: 2px solid var(--ink); position: relative; padding: 13px 15px 15px; box-shadow: var(--shadow-card); }
  .tread .t-l { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; color: var(--v3); display: block; }
  .tread .t-b { font-family: var(--body); font-weight: 700; font-size: 15px; }
  .tread .t-p { font-size: 12px; color: var(--ink-soft); line-height: 1.45; margin-top: 4px; }
  .tread .t-flag { display: block; margin-top: 9px; font-family: var(--mono); font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--v3); }
  .tread.top { border-top: 3px solid var(--v1); }
  .ceiling { position: absolute; left: 0; right: 0; top: -14px; border-top: 2.5px dashed var(--v5); transform-origin: 0 50%; transform: scaleX(0); transition: transform 1s cubic-bezier(.22,1,.36,1) .5s; }
  .ceiling.on { transform: scaleX(1); }
  .ceiling span { position: absolute; right: 0; top: -26px; font-family: var(--mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--v5); }
  .l5-grid { display: grid; grid-template-columns: 300px 1fr; gap: 56px; align-items: start; margin-top: 44px; }
  .l5-note { background: var(--paper-hi); border: 1px solid rgba(35,28,43,.14); border-top: 2px solid var(--ink); padding: 20px 24px; box-shadow: var(--shadow-card); }
  .l5-grid .stair { margin: 0; }
  .l5-note b { font-family: var(--body); font-size: 17px; display: block; margin-bottom: 6px; }
  .l5-note p { font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); }

  /* ============================================================ install */
  .install { background: transparent; border-top: 3px double var(--rule); }
  .install .wrap { padding-top: 88px; padding-bottom: 66px; display: grid; grid-template-columns: 1fr 1fr; gap: 70px; align-items: center; }
  .term { position: relative; background: var(--paper); border: 1px solid rgba(35,28,43,.2); box-shadow: var(--shadow-obj); }
  .term-bar { display: flex; align-items: center; gap: 12px; padding: 11px 16px; border-bottom: 1px solid var(--rule); font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
  .term-bar .dots { display: flex; gap: 6px; }
  .term-bar .dots i { width: 10px; height: 10px; border-radius: 50%; }
  .term-bar .dots i:nth-child(1) { background: var(--v1); }
  .term-bar .dots i:nth-child(2) { background: var(--v3); }
  .term-bar .dots i:nth-child(3) { background: var(--v5); }
  .term-body { padding: 20px 22px 22px; font-family: var(--mono); font-size: 13px; line-height: 2.05; min-height: 250px; }
  .term-body .in i { font-style: normal; color: var(--v3); margin-right: 9px; }
  .term-body .out { color: var(--ink-soft); opacity: 0; transform: translateY(4px); transition: opacity .3s, transform .3s; }
  .term-body .out.show { opacity: 1; transform: none; }
  .term-body .out i { font-style: normal; margin-right: 9px; color: var(--ink-faint); }
  .term-body .out.ok { color: var(--ink); }
  .term-body .out.ok i { color: var(--v3); }
  .term-body .car { display: inline-block; width: 8px; height: 14px; background: var(--v3); vertical-align: middle; animation: blink 1.1s steps(1) infinite; }
  .marquee { border-top: 1px solid var(--rule); overflow: hidden; background: var(--paper-hi); }
  .marquee .track { display: flex; gap: 0; width: max-content; animation: lap 34s linear infinite; padding: 13px 0; }
  @keyframes lap { to { transform: translateX(-50%); } }
  @media (prefers-reduced-motion: reduce) { .marquee .track { animation: none; } }
  .marquee span { font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint); padding: 0 26px; white-space: nowrap; }
  .marquee span i { font-style: normal; color: var(--v3); margin-right: 10px; }

  /* ========================================================== ecosystem */
  .eco .wrap { padding-top: 92px; padding-bottom: 90px; }
  .eco .ghost-n { top: 30px; left: max(48px, calc((100vw - 1200px) / 2)); right: auto; }
  .eq { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 8px; margin: 48px auto 14px; max-width: 1040px; }
  .eterm { display: inline-block; font-family: var(--mono); font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink); border: 1.5px solid var(--ink); background: var(--paper-hi); padding: 9px 14px; box-shadow: 3px 3px 0 rgba(35,28,43,.16); }
  .eterm.hot { color: var(--paper-hi); background: var(--v3); border-color: var(--v3); }
  .eq .op { font-family: var(--display); font-size: 24px; color: var(--v3); padding: 0 4px; }
  .eq .res { font-family: var(--display); font-weight: 700; font-size: 26px; letter-spacing: .02em; color: var(--pop-ink); background: var(--pop); padding: 12px 24px; box-shadow: 4px 4px 0 rgba(35,28,43,.22); margin-left: 6px; }
  .eq-note { text-align: center; font-size: 14px; font-style: italic; color: var(--ink-faint); margin-bottom: 56px; }
  .layers { display: grid; gap: 20px; }
  .layer { display: grid; grid-template-columns: 92px 1.1fr 1fr; gap: 26px; align-items: center; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.13); border-left: 4px solid var(--hue); padding: 24px 28px; box-shadow: var(--shadow-card); position: relative; }
  .layer .l-n { font-family: var(--display); font-size: 44px; color: color-mix(in srgb, var(--hue) 80%, var(--ink)); }
  .layer .l-lin { display: block; font-family: var(--mono); font-size: 9px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
  .layer h3 { font-family: var(--body); font-weight: 700; font-size: 19px; margin-bottom: 6px; }
  .layer .l-body { font-size: 14px; line-height: 1.55; color: var(--ink-soft); }
  .layer ul { margin-top: 10px; display: grid; gap: 4px; }
  .layer li { list-style: none; font-size: 12.5px; color: var(--ink-soft); display: flex; gap: 8px; align-items: baseline; }
  .layer li::before { content: ""; width: 6px; height: 6px; background: var(--hue); transform: rotate(45deg); flex: none; }
  .scene { border: 1px dashed var(--rule); background: var(--paper); padding: 14px 16px; font-family: var(--mono); font-size: 11px; display: grid; gap: 8px; }
  .sc-card { background: var(--paper-hi); border: 1px solid rgba(35,28,43,.14); padding: 9px 12px; display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
  .sc-card b { font-weight: 700; }
  .sc-tag { font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--v3); border: 1px solid var(--rule); border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
  .sc-tag.warn { color: var(--v5); border-color: color-mix(in srgb, var(--v5) 40%, transparent); }
  .sc-note { font-size: 10px; color: var(--ink-faint); }
  .sc-fan { display: flex; gap: 8px; }
  .sc-fan span { flex: 1; text-align: center; border: 1px solid var(--rule); padding: 6px 4px; color: var(--v3); }
  .sc-steps { display: flex; gap: 6px; }
  .sc-steps span { flex: 1; text-align: center; border: 1px solid rgba(35,28,43,.14); background: var(--paper-hi); padding: 6px 4px; font-size: 10px; }
  .sc-steps .done { color: var(--v3); }
  .sc-steps .retry { color: var(--v5); border-color: color-mix(in srgb, var(--v5) 40%, transparent); }
  .sc-steps .queued { color: var(--ink-faint); }

  /* ============================================================ console */
  .console { background: transparent; border-top: 3px double var(--rule); }
  .console .wrap { padding-top: 90px; padding-bottom: 92px; }
  .board { border: 1.5px solid var(--ink); background: var(--paper); position: relative; margin-top: 46px; }
  .board .fig-tab { top: -13px; left: 18px; }
  .cols { display: grid; grid-template-columns: repeat(5, 1fr); }
  .colm { padding: 18px 14px 20px; min-height: 250px; border-left: 1px solid var(--rule-soft); }
  .colm:first-child { border-left: none; }
  .colm header { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; }
  .pip { width: 8px; height: 8px; border-radius: 50%; flex: none; }
  .pip.ready { border: 1.5px solid var(--v1); }
  .pip.run { background: var(--v1); }
  .pip.wait { background: var(--v3); box-shadow: 0 0 0 3px color-mix(in srgb, var(--v3) 15%, transparent); }
  .pip.done { background: var(--deep); }
  .pip.stop { background: var(--v5); }
  .colm .hint { font-size: 11.5px; font-style: italic; color: var(--ink-faint); line-height: 1.45; margin-bottom: 13px; }
  .cmt { background: var(--paper-hi); border: 1px solid rgba(35,28,43,.15); padding: 11px 12px; margin-bottom: 10px; }
  .cmt .fn { font-family: var(--body); font-weight: 700; font-size: 14.5px; margin-bottom: 4px; }
  .cmt .meta { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 10px; color: var(--ink-faint); }
  .cmt .note { margin-top: 6px; font-family: var(--mono); font-size: 10px; color: var(--v3); }
  .cmt .note.warn { color: var(--v5); font-weight: 700; }
  .cmt .decide { display: flex; gap: 7px; margin-top: 9px; }
  .cmt .decide span { font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; padding: 4px 9px; border: 1px solid rgba(35,28,43,.25); }
  .cmt .decide .go { background: var(--deep); border-color: var(--deep); color: var(--paper-hi); }
  #traveler { border-color: color-mix(in srgb, var(--v3) 60%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--v3) 12%, transparent), 0 10px 22px -14px rgba(0,0,0,.35); }
  .board-caption { margin-top: 22px; font-size: 13px; font-style: italic; color: var(--ink-soft); max-width: 84ch; }

  /* =========================================================== refusals */
  .refusals .wrap { padding-top: 92px; padding-bottom: 92px; }
  .refusals .ghost-n { top: 20px; -webkit-text-stroke-color: color-mix(in srgb, var(--v1) 20%, transparent); }
  .ref-grid { display: grid; grid-template-columns: 250px 1fr; gap: 58px; align-items: start; margin-top: 44px; }
  .rail { position: sticky; top: 96px; }
  .rail-stat { padding: 18px 0 20px; border-top: 2px solid var(--ink); }
  .rail-stat + .rail-stat { border-top: 1px solid var(--rule); }
  .rail-stat b { font-family: var(--display); font-size: 60px; line-height: 1; display: block; }
  .rail-stat span { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-soft); }
  .rail-note { border-top: 1px solid var(--rule); padding-top: 18px; font-size: 14px; line-height: 1.6; color: var(--ink-soft); }
  .rail-note code { font-family: var(--mono); font-size: 12px; color: var(--v3); border-bottom: 1px dotted var(--v3); }
  .rail .stamp-el { margin-top: 24px; color: var(--v5); --rot: -5deg; font-size: 10.5px; padding: 7px 12px; }
  .rail .stamp-el b { font-size: 10.5px; letter-spacing: .2em; font-weight: 400; }
  .schedule { border: 1.5px solid var(--ink); background: color-mix(in srgb, var(--paper-hi) 88%, transparent); position: relative; }
  .sch-tab { position: absolute; top: -13px; left: 18px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase; background: var(--ink); color: var(--paper-hi); padding: 5px 12px; }
  .sch-head, .sch-row { display: grid; grid-template-columns: 50px 1.06fr 1.14fr 1fr 196px; }
  .sch-head { font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft); background: color-mix(in srgb, var(--v1) 6%, transparent); border-bottom: 1px solid var(--ink); }
  .sch-head span { padding: 13px 12px 9px; border-left: 1px solid rgba(35,28,43,.12); }
  .sch-head span:first-child { border-left: none; }
  .sch-row { border-bottom: 1px solid rgba(35,28,43,.12); }
  .sch-row > * { padding: 12px; border-left: 1px solid rgba(35,28,43,.08); }
  .sch-row > *:first-child { border-left: none; }
  .sch-row .no { font-family: var(--mono); font-size: 11px; color: var(--v3); }
  .sch-row .name { font-family: var(--body); font-weight: 700; font-size: 15px; }
  .sch-row .mean, .sch-row .fix { font-size: 13px; line-height: 1.5; color: var(--ink-soft); }
  .sch-row .fix i { font-style: normal; color: var(--v3); margin-right: 5px; }
  .sch-row .id { font-family: var(--mono); font-size: 10px; display: flex; flex-direction: column; gap: 5px; align-items: flex-start; }
  .sch-row .id code { background: color-mix(in srgb, var(--v1) 7%, transparent); border: 1px solid color-mix(in srgb, var(--v1) 24%, transparent); padding: 3px 7px; }
  .sch-row.hot { background: color-mix(in srgb, var(--v5) 6%, transparent); position: relative; }
  .sch-row.hot .id code { background: color-mix(in srgb, var(--v5) 10%, transparent); border-color: var(--v5); color: var(--v5); font-weight: 700; }
  .sch-row.hot .id-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
  .sch-row.hot .refstamp { position: static; color: var(--v5); --rot: -6deg; --o: .9; padding: 3px 8px; border-width: 2px; border-radius: 5px; }
  .sch-row.hot .refstamp::before { inset: 2px; border-radius: 3px; }
  .sch-row.hot .refstamp b { font-size: 9.5px; letter-spacing: .18em; }
  .sch-void { height: 44px; display: flex; align-items: center; justify-content: center;
    background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--v1) 13%, transparent) 0 1px, transparent 1px 7px); }
  .sch-void span { font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); background: var(--paper-hi); padding: 3px 14px; border: 1px solid rgba(35,28,43,.14); }

  /* =============================================================== cost */
  .cost { background: transparent; border-top: 3px double var(--rule); }
  .cost .wrap { padding-top: 90px; padding-bottom: 88px; }
  .save-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; max-width: 860px; margin: 40px auto 0; border-top: 2px solid var(--ink); border-bottom: 1px solid var(--rule); }
  .save { padding: 22px 22px 20px; border-right: 1px solid var(--rule-soft); }
  .save:last-child { border-right: none; }
  .save b { display: block; font-family: var(--display); font-size: 52px; line-height: 1; color: var(--v1); margin-bottom: 8px; }
  .save span { font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); display: block; max-width: 22ch; }
  .meter { max-width: 860px; margin: 40px auto 40px; background: var(--paper); border: 1px solid rgba(35,28,43,.16); padding: 22px 26px; box-shadow: var(--shadow-card); position: relative; }
  .meter .fig-tab { top: -12px; }
  .meter-head { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 12px; }
  .meter-track { height: 14px; background: color-mix(in srgb, var(--v1) 8%, transparent); border: 1px solid color-mix(in srgb, var(--v1) 20%, transparent); position: relative; }
  .meter-fill { position: absolute; inset: 0 auto 0 0; width: 0; background: linear-gradient(90deg, var(--v1), var(--v4)); transition: width 1.2s cubic-bezier(.22,1,.36,1) .2s; }
  .meter.on .meter-fill { width: 78%; }
  .meter-cap { position: absolute; right: 0; top: -5px; bottom: -5px; width: 2.5px; background: var(--ink); }
  .meter-foot { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px 14px; margin-top: 14px; font-family: var(--mono); font-size: 11.5px; }
  .meter-foot .spent { color: var(--ink); font-weight: 700; }
  .meter-foot .refused-chip { color: var(--v5); border: 1.5px solid currentColor; border-radius: 5px; padding: 6px 11px; letter-spacing: .04em; --rot: -2deg; }
  .axes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; max-width: 860px; margin: 0 auto; }
  .axis { background: var(--paper); border: 1px solid rgba(35,28,43,.13); border-top: 2px solid var(--v1); padding: 14px 16px; }
  .axis b { display: block; font-family: var(--body); font-size: 15px; margin-bottom: 3px; }
  .axis span { font-size: 12.5px; color: var(--ink-soft); }
  .cost .caption { max-width: 860px; margin: 30px auto 0; font-size: 13px; font-style: italic; color: var(--ink-soft); }

  /* =========================================================== partners */
  .partners .wrap { padding-top: 92px; padding-bottom: 64px; }
  .ticket { max-width: 960px; margin: 48px auto 0; display: grid; grid-template-columns: 1fr 240px; background: var(--paper-hi); box-shadow: var(--shadow-obj); position: relative; }
  .ticket::before { content: ""; position: absolute; top: 10px; bottom: 10px; right: 240px; border-left: 2px dashed rgba(35,28,43,.25); }
  .ticket-main { padding: 40px 46px 38px; }
  .ticket-eyebrow { font-family: var(--mono); font-size: 10px; letter-spacing: .26em; text-transform: uppercase; color: var(--v3); display: block; margin-bottom: 12px; }
  .ticket-main h3 { font-family: var(--display); font-weight: 700; font-size: 30px; line-height: 1.1; margin-bottom: 16px; }
  .perks { display: grid; gap: 9px; margin-bottom: 26px; }
  .perks li { list-style: none; font-size: 14.5px; color: var(--ink-soft); display: flex; gap: 10px; align-items: baseline; }
  .perks li::before { content: ""; width: 7px; height: 7px; background: var(--v3); transform: rotate(45deg); flex: none; }
  .ticket-stub { padding: 34px 24px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; text-align: center;
    background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--v1) 5%, transparent) 0 1px, transparent 1px 8px), var(--paper-hi); }
  .ticket-stub .big { font-family: var(--display); font-weight: 700; font-size: 74px; line-height: 1; color: var(--v1); }
  .ticket-stub .lbl { font-family: var(--mono); font-size: 10px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-soft); }
  .seat-row { display: flex; gap: 8px; margin: 8px 0 4px; }
  .seat { width: 56px; padding: 8px 0 7px; border: 1.5px dashed var(--rule); text-align: center; position: relative; }
  .seat b { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); }
  .seat .open-stamp { position: absolute; inset: auto; left: 50%; top: 50%; transform: translate(-50%,-50%) rotate(var(--rot)); color: var(--v3); border: 1.5px solid currentColor; border-radius: 4px; font-family: var(--mono); font-size: 8px; letter-spacing: .14em; padding: 2px 6px; background: var(--paper-hi); }
  .seat .open-stamp.thunk.on { transform: translate(-50%,-50%) scale(1) rotate(var(--rot)); }
  .seat .open-stamp.thunk { transform: translate(-50%,-50%) scale(1.8) rotate(var(--rot)); }
  .stub-note { font-family: var(--mono); font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
  .fomo-line { text-align: center; margin-top: 26px; font-size: 14.5px; font-style: italic; color: var(--ink-soft); }
  .fomo-line b { font-style: normal; color: var(--v4-ink); }

  /* ============================================================== close */
  .close-band { background: linear-gradient(165deg, var(--deep2), var(--deep) 78%); color: #efe9f6; position: relative; overflow: hidden; }
  .close-band .close-mark { position: absolute; right: -50px; bottom: -70px; width: 340px; opacity: .06; }
  .close-band .wrap { padding-top: 88px; padding-bottom: 92px; text-align: center; position: relative; z-index: 1; }
  .close-band .k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .28em; text-transform: uppercase; color: var(--on-deep); display: block; margin-bottom: 18px; }
  .close-band h2 { color: #fdfbf5; font-size: clamp(36px, 4vw, 56px); margin-bottom: 14px; }
  .close-band .sub2 { font-size: 16px; color: rgba(239,233,246,.75); margin-bottom: 26px; }
  .close-band .eq2 { font-family: var(--mono); font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--on-deep); margin-bottom: 34px; }
  .close-band .cta-row { justify-content: center; }
  .close-band .btn { background: var(--paper-hi); color: var(--ink); border-color: var(--paper-hi); box-shadow: none; }
  .close-band .btn:hover { background: #fff; }
  .close-band .btn.hollow { background: transparent; color: #efe9f6; border: 1px solid rgba(239,233,246,.55); }
  .close-band .btn.hollow:hover { background: rgba(239,233,246,.1); color: #fff; border-color: #fff; }
  .close-note { margin-top: 26px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; color: rgba(239,233,246,.6); }
  .foot-tear { height: 12px; background-repeat: repeat-x; background-position: bottom; background-size: 16px 12px;
    background-image: linear-gradient(45deg, transparent 8px, var(--deep) 8px), linear-gradient(-45deg, transparent 8px, var(--deep) 8px); }
  footer { background: var(--deep); color: #efe9f6; border-top: 1px solid rgba(238, 230, 216, 0.16); position: relative; overflow: hidden; }
  footer .wrap { padding-top: 58px; padding-bottom: 26px; position: relative; }
  .foot-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 48px; align-items: start; position: relative; z-index: 1; }
  .foot-brand .fb-row { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
  .foot-brand svg { width: 22px; height: 22px; }
  .foot-brand b { font-family: var(--brand); font-weight: 400; font-size: 18px; letter-spacing: 0.005em; }
  .foot-brand p { font-size: 13.5px; line-height: 1.55; color: rgba(239, 233, 246, 0.72); max-width: 30ch; }
  .foot-col h2 { font-family: var(--mono); font-size: 9.5px; line-height: 1.4; letter-spacing: 0.24em; text-transform: uppercase; color: rgba(239, 233, 246, 0.72); margin-bottom: 13px; font-weight: 400; }
  .foot-col a { display: block; font-family: var(--mono); font-size: 12px; color: rgba(239, 233, 246, 0.82); padding: 4px 0; }
  .foot-col a:hover { color: #fff; }
  .foot-ghost {
    font-family: var(--brand); font-weight: 400; line-height: 0.78; letter-spacing: -0.02em;
    font-size: clamp(120px, 16vw, 230px); text-align: center;
    color: transparent; -webkit-text-stroke: 1px rgba(238, 230, 216, 0.15);
    margin-top: 44px; user-select: none;
  }
  .colophon { display: flex; justify-content: space-between; gap: 26px; font-family: var(--mono); font-size: 11px; letter-spacing: .05em; color: rgba(239,233,246,.72); border-top: 1px solid rgba(238, 230, 216, 0.14); padding-top: 20px; margin-top: 30px; position: relative; z-index: 1; }

  /* ------------------------------------------------- motion-ui layer */
  /* headlines rise a touch farther and slower than body reveals */
  h1.rv, h2.rv { transform: translateY(34px); transition-duration: .65s, .9s; }

  /* cards answer the cursor */
  .step, .layer, .axis, .slip, .cmt, .l5-note, .tread, .ticket, .meter {
    transition: transform .45s cubic-bezier(.22,1,.36,1), box-shadow .45s cubic-bezier(.22,1,.36,1), opacity .7s ease;
  }
  .step:hover, .layer:hover, .axis:hover, .l5-note:hover { transform: translateY(-4px); box-shadow: 0 26px 50px -30px color-mix(in srgb, var(--deep) 55%, transparent); }
  .slip:hover { transform: translateY(-4px) rotate(0deg) !important; }
  .cmt:hover { transform: translateY(-2px); }
  .btn { transition: transform .3s cubic-bezier(.22,1,.36,1), background .25s ease, border-color .25s ease; will-change: transform; }
  .btn:active { transform: scale(.97); }

  /* scroll-driven parallax — Chrome's native scroll timelines; static elsewhere */
  @supports (animation-timeline: view()) {
    .printer { animation: par-obj linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
    @keyframes par-obj { from { transform: translateY(22px); } to { transform: translateY(-26px); } }
    .ghost-n { animation: par-ghost linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
    @keyframes par-ghost { from { transform: translateY(54px); } to { transform: translateY(-54px); } }
    .foot-ghost { animation: par-rise linear both; animation-timeline: view(); animation-range: entry 0% cover 55%; }
    @keyframes par-rise { from { transform: translateY(46px); opacity: .3; } to { transform: none; opacity: 1; } }
    .sp-receipt { animation: par-soft linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
    @keyframes par-soft { from { transform: translateY(14px); } to { transform: translateY(-14px); } }
  }
  @media (prefers-reduced-motion: reduce) {
    .receipt, .ghost-n, .foot-ghost, .sp-receipt { animation: none !important; }
  }

  /* 01b · pillars — pure typography, no boxes: the one section that is only words */
  .pillars { background: transparent; border-bottom: 1px solid var(--rule); }
  .pillars .wrap { padding-top: 84px; padding-bottom: 84px; }
  .pillar-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; margin-top: 44px; border-top: 2px solid var(--ink); }
  .pillar { padding: 26px 26px 8px 0; border-right: 1px solid var(--rule-soft); }
  .pillar + .pillar { padding-left: 26px; }
  .pillar:last-child { border-right: none; }
  .p-n { display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em; color: var(--v3); margin-bottom: 14px; }
  .pillar h3 { font-family: var(--display); font-weight: 700; font-size: 34px; line-height: 1; letter-spacing: -.005em; margin-bottom: 12px; }
  .pillar p { font-size: 15px; line-height: 1.55; color: var(--ink-soft); }

  /* ============================================ document objects */
  /* 01 · incident report (dark band) */
  .incident { margin-top: 44px; background: var(--paper-hi); color: var(--ink); border: 1px solid rgba(35,28,43,.2); box-shadow: var(--shadow-obj); position: relative; }
  .incident::before { content: ""; position: absolute; left: 22px; top: 0; bottom: 0; width: 1px; background: color-mix(in srgb, var(--v5) 35%, transparent); }
  .inc-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; padding: 20px 28px 16px 44px; border-bottom: 2px solid var(--ink); }
  .inc-form { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .28em; text-transform: uppercase; color: var(--v3); margin-bottom: 6px; }
  .inc-title b { font-family: var(--display); font-size: 24px; letter-spacing: .01em; }
  .inc-meta { display: flex; gap: 22px; font-family: var(--mono); font-size: 10.5px; color: var(--ink-soft); }
  .inc-meta i { font-style: normal; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .16em; font-size: 9px; margin-right: 6px; }
  .inc-meta em { font-style: normal; color: var(--v5); font-weight: 700; }
  .inc-body { display: grid; grid-template-columns: 1.55fr 1fr; }
  .inc-findings { padding: 20px 28px 22px 44px; border-right: 1px dashed rgba(35,28,43,.25); }
  .inc-label { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .26em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 12px; }
  .inc-list { list-style: none; }
  .inc-list li { display: grid; grid-template-columns: 34px 1fr auto; gap: 14px; align-items: baseline; padding: 11px 0; border-bottom: 1px solid rgba(35,28,43,.1); }
  .inc-list li:last-child { border-bottom: none; }
  .inc-n { font-family: var(--mono); font-size: 11px; color: var(--v3); }
  .inc-list b { display: block; font-family: var(--display); font-size: 18px; line-height: 1.15; margin-bottom: 3px; }
  .inc-list p { font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
  .inc-code { font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; color: var(--v5); border: 1px solid currentColor; padding: 3px 7px; white-space: nowrap; }
  .inc-side { padding: 20px 26px 22px; position: relative; background: repeating-linear-gradient(-45deg, transparent 0 9px, color-mix(in srgb, var(--v1) 4%, transparent) 9px 10px); }
  .inc-cause { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); }
  .inc-cause b { color: var(--ink); }
  .inc-stamp { position: absolute; right: 18px; bottom: 16px; color: var(--v5); }
  .inc-stamp b { font-size: 13px; letter-spacing: .18em; }
  .inc-foot { display: flex; justify-content: space-between; padding: 10px 28px 10px 44px; border-top: 1px solid var(--ink); font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-faint); }

  /* 02 · the contract */
  .deed { margin-top: 44px; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.2); outline: 3px double var(--rule); outline-offset: 6px; padding: 44px 56px 40px; box-shadow: var(--shadow-obj); text-align: center; position: relative; }
  .deed-kicker { font-family: var(--mono); font-size: 10px; letter-spacing: .32em; text-transform: uppercase; color: var(--v3); margin-bottom: 12px; }
  .deed-title { font-family: var(--display); font-style: italic; font-weight: 400; font-size: 17px; color: var(--ink-soft); margin-bottom: 30px; }
  .articles { text-align: left; display: grid; gap: 22px; margin-bottom: 34px; }
  .article { display: grid; grid-template-columns: 128px 1fr; gap: 24px; align-items: start; }
  .article .a-no { font-family: var(--display); font-size: 13.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--v3); text-align: right; white-space: nowrap; border-right: 1px solid var(--rule-soft); padding: 4px 20px 0 0; }
  .article b { display: block; font-family: var(--display); font-size: 19px; margin-bottom: 5px; }
  .article p { font-size: 15px; line-height: 1.6; color: var(--ink-soft); }
  .a-art { display: inline-flex; align-items: center; gap: 8px; margin-top: 10px; border: 1px dashed var(--rule); background: var(--paper); padding: 8px 12px; font-family: var(--mono); font-size: 11.5px; color: var(--ink); }
  .a-art .car { display: inline-block; width: 7px; height: 12px; background: var(--v3); animation: blink 1.1s steps(1) infinite; }
  .a-chips span { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; padding: 4px 9px; border: 1px solid var(--rule); color: var(--v3); }
  .a-chips .wait { color: var(--ink); border-color: rgba(35,28,43,.4); }
  .a-receipt { display: grid; gap: 3px; }
  .a-receipt span { display: block; }
  .a-receipt i { font-style: normal; color: var(--v3); }
  .sigblock { display: grid; grid-template-columns: 1fr 1fr 150px; gap: 40px; align-items: end; text-align: left; border-top: 1px solid var(--rule-soft); padding-top: 30px; }
  .sig .sig-line { height: 1px; background: var(--ink); margin-bottom: 8px; position: relative; }
  .sig .sig-x { font-family: var(--display); font-style: italic; font-size: 22px; color: var(--ink-faint); position: absolute; left: 2px; top: -26px; }
  .sig .sig-digest { font-family: var(--mono); font-size: 11.5px; color: var(--v3); position: absolute; left: 0; top: -20px; }
  .sig b { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 3px; }
  .sig span { display: block; font-size: 12.5px; font-style: italic; color: var(--ink-faint); line-height: 1.5; }
  .seal { justify-self: end; }

  /* 04 · the licence */
  .l5-side { display: grid; gap: 18px; align-content: start; }
  .l5-fine { font-size: 13.5px; font-style: italic; line-height: 1.55; color: var(--ink-faint); }
  .l5-note b { display: block; font-family: var(--display); font-size: 19px; margin-bottom: 8px; }
  .licence { position: relative; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.22); border-radius: 10px; box-shadow: var(--shadow-obj); overflow: hidden; }
  .licence::before { content: ""; position: absolute; inset: 0; background: repeating-radial-gradient(circle at 92% -20%, color-mix(in srgb, var(--v1) 5%, transparent) 0 1px, transparent 1px 8px); pointer-events: none; }
  .lic-head { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding: 14px 20px; border-bottom: 1px solid var(--rule); background: color-mix(in srgb, var(--v1) 4%, transparent); position: relative; }
  .lic-brand { display: flex; align-items: center; gap: 12px; }
  .lic-brand svg { width: 30px; height: 30px; }
  .lic-brand b { display: block; font-family: var(--display); font-size: 17px; }
  .lic-brand span { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); margin-top: 2px; }
  .lic-no { font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; color: var(--deep); }
  .endorsements { list-style: none; padding: 6px 20px 0; position: relative; }
  .endorsements li { display: grid; grid-template-columns: 34px 168px 1fr auto; gap: 14px; align-items: baseline; padding: 12px 0; border-bottom: 1px dotted rgba(83,61,122,.35); }
  .e-lv { font-family: var(--mono); font-size: 11px; color: var(--v3); }
  .e-name { font-family: var(--display); font-size: 16.5px; }
  .e-desc { font-size: 13.5px; color: var(--ink-soft); }
  .e-mark { font-family: var(--mono); font-size: 11px; color: var(--v3); }
  .e-flag { font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--v5); border: 1px solid currentColor; padding: 2px 6px; }
  .e-cond { font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--v1); border: 1px solid currentColor; padding: 2px 6px; }
  .endorsements li.top { background: linear-gradient(90deg, color-mix(in srgb, var(--v1) 6%, transparent), transparent 70%); margin: 0 -20px; padding-left: 20px; padding-right: 20px; border-bottom: none; }
  .endorsements li.top .e-name { color: var(--v1); }
  .lic-cond { display: grid; grid-template-columns: 110px 1fr; gap: 16px; align-items: start; padding: 14px 20px 16px; border-top: 1px solid var(--rule); position: relative; }
  .lic-label { font-family: var(--mono); font-size: 9px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); padding-top: 3px; }
  .lic-cond p { font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
  .lic-cond p b { color: var(--ink); }
  .lic-stamp { position: absolute; right: 22px; bottom: 58px; color: var(--v1); }
  .lic-cond { padding-right: 250px; }
  .lic-stamp b { font-size: 12px; letter-spacing: .16em; }
  .lic-mrz { background: color-mix(in srgb, var(--paper-hi) 60%, #fff); border-top: 1px solid var(--rule); padding: 10px 20px; font-family: var(--mono); font-size: 12.5px; letter-spacing: 2.4px; color: var(--ink); white-space: nowrap; overflow: hidden; position: relative; }

  /* header · the lockup used structurally.

     The size lives on the brand box rather than on the lockup, because the hover
     rule below has to read it too; the lockup then takes it from here, and only
     needs the extra specificity to beat its own default. It shrinks on a narrow
     screen because it has to. The seats chip and the GitHub button beside it hold
     a hard 191.8px between them — measured, and they have no give left — and the
     sheet's gutters take another 88, so a 26px lockup puts the GitHub button's
     right edge at 429px and a 390px phone cuts the end off it. The old wordmark
     never showed this: it was live text, so it wrapped to two lines and squeezed
     itself to 107.7px. A lockup cannot wrap and must not, so it gets smaller
     instead, which costs nothing — every measure inside it is a multiple of H.

     The slope is the fit itself. The lockup measures 6.291×H wide (83.03 of
     artwork, 6.76 of gap and 73.78 of name at H=26), so H = (viewport - 282.3px) /
     6.291 keeps the button's right edge on the same gutter the old two-line
     wordmark left it. Rounded to 15.9vw - 44.9px, held between 17px and the full
     26px, which it reaches again at about 446px.

     The divisor is the name's own width, so it moves when the name does: this
     slope was 6.127 while the name read a lowercase "runtime", and the capital R
     the product actually carries is 4.28px wider at H=26. Set the name and reset
     the divisor, or the button starts creeping into the gutter. The floor bites
     just under a 390px phone: at exactly 390 the slope lands H on 17.11, a hair
     over it, and narrower than that the row stops shrinking and bleeds further
     into the nav's own 44px padding. Measured at 390 — a 107.6px lockup, the
     GitHub button's right edge at 373.5, 16.6px of sheet left beside it. Tight,
     but nothing clips and the page never scrolls sideways. */
  nav .brand { position: relative; padding-left: 4px; --fx-lk-h: clamp(17px, 15.9vw - 44.9px, 26px); }
  nav .brand .fx-lockup { --fx-lk-h: inherit; }
  /* The rule sweeps in 4.25px under the header's border, which is where the old
     mark-plus-wordmark brand box put it: that box measured 28.5px tall and landed
     the rule at 101.75px down the page. The lockup's box is exactly H tall, and it
     is centred in the 64px bar, so the drop back to that same line is
     37.25px - H/2 — which comes to the measured 24.25px at H=26 and holds as the
     lockup shrinks. */
  nav .brand::after { content: ""; position: absolute; left: 0; right: 0; bottom: calc(var(--fx-lk-h) / 2 - 37.25px); height: 2px; background: linear-gradient(90deg, var(--v1), var(--v5)); transform: scaleX(0); transform-origin: 0 50%; transition: transform .5s cubic-bezier(.22,1,.36,1); }
  nav .brand:hover::after { transform: scaleX(1); }
  .links a { position: relative; padding-bottom: 2px; }
  .links a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px; background: var(--v3); transform: scaleX(0); transform-origin: 0 50%; transition: transform .35s cubic-bezier(.22,1,.36,1); }
  .links a:hover::after { transform: scaleX(1); }

  /* footer · a closing sheet with the seal */
  .foot-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr 150px; }
  .foot-seal { justify-self: end; opacity: .9; }
  .foot-seal circle, .foot-seal text { stroke: rgba(238,230,216,.75); fill: none; }
  .foot-seal text { fill: rgba(238,230,216,.8); stroke: none; }
  .foot-seal .fs-fill { fill: rgba(238,230,216,.06); }

  /* ================================================== theme variants
     paper (default) · mono (ink on paper, no violet) · night (juicebox-deep
     aubergine, paper documents on a dark desk) · noir (dark monochrome).
     Documents stay paper on the dark themes: they re-declare the paper tokens. */
  /* -------- light gen-Z / AI palettes: bright fill for buttons, dark ink,
     text-level accents kept in the readable half of each hue ---------- */
  html[data-theme="lime"] {
    --paper: #f5f7ee; --paper-hi: #fbfcf4; --ink: #141a0c; --ink-soft: #4a553c; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #3f6212; --v2: #4d7c0f; --v3: #4d7c0f; --v4: #65a30d; --v5: #1a2e05;
    --deep: #1a220f; --deep2: #26321a; --tear: #26321a; --on-deep: #d9f99d;
    --pop: #c5f542; --pop-ink: #141a0c;
    --band-ink: #141a0c; --band-ink2: #1f2a12; --band-label: #bef264; --band-label-b: #d9f99d;
    --rule: rgba(77, 124, 15, 0.26); --rule-soft: rgba(77, 124, 15, 0.14); --frame-rule: rgba(77, 124, 15, 0.46); --grid-minor: rgba(77, 124, 15, 0.04);
    --ghost: rgba(77, 124, 15, 0.14); --aur1: rgba(163, 230, 53, 0.22); --aur2: rgba(132, 204, 22, 0.16);
  }
  html[data-theme="mint"] {
    --paper: #eff7f2; --paper-hi: #f7fcf9; --ink: #0d1f18; --ink-soft: #3d5a4d; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #0f5132; --v2: #14704a; --v3: #0f766e; --v4: #059669; --v5: #134e4a;
    --deep: #0c2e22; --deep2: #144736; --tear: #144736; --on-deep: #a7f3d0;
    --pop: #86efac; --pop-ink: #0d1f18;
    --band-ink: #0b2119; --band-ink2: #113126; --band-label: #6ee7b7; --band-label-b: #a7f3d0;
    --rule: rgba(5, 150, 105, 0.26); --rule-soft: rgba(5, 150, 105, 0.14); --frame-rule: rgba(5, 150, 105, 0.46); --grid-minor: rgba(5, 150, 105, 0.04);
    --ghost: rgba(5, 150, 105, 0.15); --aur1: rgba(110, 231, 183, 0.24); --aur2: rgba(45, 212, 191, 0.16);
  }
  html[data-theme="butter"] {
    --paper: #fbf7e8; --paper-hi: #fffcf0; --ink: #1f190c; --ink-soft: #5b5137; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #713f12; --v2: #854d0e; --v3: #a16207; --v4: #ca8a04; --v5: #422006;
    --deep: #26200a; --deep2: #3a3111; --tear: #3a3111; --on-deep: #fef08a;
    --pop: #fde047; --pop-ink: #1f190c;
    --band-ink: #201a09; --band-ink2: #302810; --band-label: #fde68a; --band-label-b: #fef3c7;
    --rule: rgba(161, 98, 7, 0.26); --rule-soft: rgba(161, 98, 7, 0.14); --frame-rule: rgba(161, 98, 7, 0.46); --grid-minor: rgba(161, 98, 7, 0.04);
    --ghost: rgba(161, 98, 7, 0.14); --aur1: rgba(253, 224, 71, 0.28); --aur2: rgba(250, 204, 21, 0.16);
  }
  html[data-theme="iris"] {
    --paper: #f0f1fb; --paper-hi: #f8f8ff; --ink: #0f1030; --ink-soft: #454873; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #3730a3; --v2: #4338ca; --v3: #4f46e5; --v4: #6366f1; --v5: #312e81;
    --deep: #1b1c4a; --deep2: #2a2b78; --tear: #2a2b78; --on-deep: #c7d2fe;
    --pop: #4f46e5; --pop-ink: #f8f8ff;
    --band-ink: #12133a; --band-ink2: #1c1d54; --band-label: #a5b4fc; --band-label-b: #c7d2fe;
    --rule: rgba(79, 70, 229, 0.24); --rule-soft: rgba(79, 70, 229, 0.13); --frame-rule: rgba(79, 70, 229, 0.46); --grid-minor: rgba(79, 70, 229, 0.04);
    --ghost: rgba(79, 70, 229, 0.13); --aur1: rgba(129, 140, 248, 0.24); --aur2: rgba(196, 181, 253, 0.2);
  }
  /* -------- the four added in tambo's spirit: seafoam (tambo-true), sage, lavender, glacier */
  html[data-theme="seafoam"] {
    --paper: #eef8f2; --paper-hi: #f6fcf8; --ink: #0b1f17; --ink-soft: #3b5b4c; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #0b6b4c; --v2: #0e7a57; --v3: var(--v2); --v4: #10a874; --v5: #0a4d38;
    --deep: #0a2a1f; --deep2: #0f4a37; --tear: #0f4a37; --on-deep: #a8f0d0;
    --pop: #8ff2c1; --pop-ink: #0b1f17;
    --band-ink: #08201a; --band-ink2: #0d3128; --band-label: #8ff2c1; --band-label-b: #c8fae3;
    --rule: rgba(14, 138, 99, 0.24); --rule-soft: rgba(14, 138, 99, 0.13); --frame-rule: rgba(14, 138, 99, 0.46); --grid-minor: rgba(14, 138, 99, 0.04);
    --ghost: rgba(14, 138, 99, 0.14); --aur1: rgba(143, 242, 193, 0.34); --aur2: rgba(94, 234, 212, 0.18);
    --soft: 1;
  }
  html[data-theme="sage"] {
    --paper: #f1f3ec; --paper-hi: #f8f9f4; --ink: #151a12; --ink-soft: #4b5545; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #3f5a3a; --v2: #4a6b45; --v3: var(--v2); --v4: #6b8f64; --v5: #2c3f29;
    --deep: #1d261b; --deep2: #2c3a29; --tear: #2c3a29; --on-deep: #cfe0c9;
    --pop: #b7d3ae; --pop-ink: #151a12;
    --band-ink: #171d15; --band-ink2: #222c20; --band-label: #b7d3ae; --band-label-b: #dcebd7;
    --rule: rgba(88, 122, 82, 0.28); --rule-soft: rgba(88, 122, 82, 0.15); --frame-rule: rgba(88, 122, 82, 0.32); --grid-minor: rgba(88, 122, 82, 0.045);
    --ghost: rgba(88, 122, 82, 0.15); --aur1: rgba(183, 211, 174, 0.34); --aur2: rgba(150, 190, 140, 0.18);
    --soft: 1;
  }
  html[data-theme="lavender"] {
    --paper: #f5f1fb; --paper-hi: #faf8fe; --ink: #1c1230; --ink-soft: #544565; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #6d28d9; --v2: #7c3aed; --v3: #7c3aed; --v4: #a78bfa; --v5: #4c1d95;
    --deep: #2a1748; --deep2: #3f2568; --tear: #3f2568; --on-deep: #ddd6fe;
    --pop: #c4b5fd; --pop-ink: #1c1230;
    --band-ink: #1e1436; --band-ink2: #2b1d4a; --band-label: #c4b5fd; --band-label-b: #ede9fe;
    --rule: rgba(124, 58, 237, 0.22); --rule-soft: rgba(124, 58, 237, 0.12); --frame-rule: rgba(124, 58, 237, 0.28); --grid-minor: rgba(124, 58, 237, 0.04);
    --ghost: rgba(124, 58, 237, 0.13); --aur1: rgba(196, 181, 253, 0.36); --aur2: rgba(232, 121, 249, 0.14);
    --soft: 1;
  }
  html[data-theme="glacier"] {
    --paper: #eef6f9; --paper-hi: #f6fbfd; --ink: #0b1a24; --ink-soft: #3d5563; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #0e5a72; --v2: #0e7490; --v3: var(--v2); --v4: #06b6d4; --v5: #164e63;
    --deep: #0b2a36; --deep2: #0f4254; --tear: #0f4254; --on-deep: #a5f3fc;
    --pop: #7ee9fa; --pop-ink: #0b1a24;
    --band-ink: #08202b; --band-ink2: #0d3140; --band-label: #67e8f9; --band-label-b: #cffafe;
    --rule: rgba(8, 145, 178, 0.24); --rule-soft: rgba(8, 145, 178, 0.13); --frame-rule: rgba(8, 145, 178, 0.46); --grid-minor: rgba(8, 145, 178, 0.04);
    --ghost: rgba(8, 145, 178, 0.14); --aur1: rgba(126, 233, 250, 0.32); --aur2: rgba(129, 140, 248, 0.14);
    --soft: 1;
  }
  html[data-theme="mint"], html[data-theme="lime"], html[data-theme="butter"], html[data-theme="iris"] { --soft: 1; }

  /* fresh palettes share tambo's manners: rounder controls, a soft glow on hover, dark-ink hover on bright fills */
  html[data-theme="mint"] .btn, html[data-theme="lime"] .btn, html[data-theme="butter"] .btn, html[data-theme="iris"] .btn,
  html[data-theme="seafoam"] .btn, html[data-theme="sage"] .btn, html[data-theme="lavender"] .btn, html[data-theme="glacier"] .btn,
  html[data-theme="mint"] .pr-run, html[data-theme="lime"] .pr-run, html[data-theme="butter"] .pr-run, html[data-theme="iris"] .pr-run,
  html[data-theme="seafoam"] .pr-run, html[data-theme="sage"] .pr-run, html[data-theme="lavender"] .pr-run, html[data-theme="glacier"] .pr-run { border-radius: 8px; box-shadow: none; }
  html[data-theme="mint"] .btn:hover, html[data-theme="lime"] .btn:hover, html[data-theme="butter"] .btn:hover,
  html[data-theme="seafoam"] .btn:hover, html[data-theme="sage"] .btn:hover, html[data-theme="lavender"] .btn:hover, html[data-theme="glacier"] .btn:hover { background: var(--ink); border-color: var(--ink); color: var(--paper-hi); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 38%, transparent); }
  html[data-theme="iris"] .btn:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 30%, transparent); }
  html[data-theme="mint"] .btn.hollow, html[data-theme="lime"] .btn.hollow, html[data-theme="butter"] .btn.hollow, html[data-theme="iris"] .btn.hollow,
  html[data-theme="seafoam"] .btn.hollow, html[data-theme="sage"] .btn.hollow, html[data-theme="lavender"] .btn.hollow, html[data-theme="glacier"] .btn.hollow { background: transparent; color: var(--ink); border-color: rgba(0,0,0,.4); }
  html[data-theme="mint"] .btn.hollow:hover, html[data-theme="lime"] .btn.hollow:hover, html[data-theme="butter"] .btn.hollow:hover, html[data-theme="iris"] .btn.hollow:hover,
  html[data-theme="seafoam"] .btn.hollow:hover, html[data-theme="sage"] .btn.hollow:hover, html[data-theme="lavender"] .btn.hollow:hover, html[data-theme="glacier"] .btn.hollow:hover { background: transparent; color: var(--ink); border-color: var(--ink); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 30%, transparent); }
  html[data-theme="mint"] .close-band .btn:not(.hollow), html[data-theme="lime"] .close-band .btn:not(.hollow), html[data-theme="butter"] .close-band .btn:not(.hollow), html[data-theme="iris"] .close-band .btn:not(.hollow),
  html[data-theme="seafoam"] .close-band .btn:not(.hollow), html[data-theme="sage"] .close-band .btn:not(.hollow), html[data-theme="lavender"] .close-band .btn:not(.hollow), html[data-theme="glacier"] .close-band .btn:not(.hollow) { background: var(--pop); color: var(--pop-ink); border-color: var(--pop); }
  html[data-theme="mint"] .eterm.hot, html[data-theme="lime"] .eterm.hot, html[data-theme="butter"] .eterm.hot,
  html[data-theme="seafoam"] .eterm.hot, html[data-theme="sage"] .eterm.hot, html[data-theme="lavender"] .eterm.hot, html[data-theme="glacier"] .eterm.hot { background: var(--pop); border-color: var(--ink); color: var(--pop-ink); }
  html[data-theme="mint"] .seats-chip i, html[data-theme="lime"] .seats-chip i, html[data-theme="butter"] .seats-chip i,
  html[data-theme="seafoam"] .seats-chip i, html[data-theme="sage"] .seats-chip i, html[data-theme="lavender"] .seats-chip i, html[data-theme="glacier"] .seats-chip i { background: var(--v3); }

  /* the close band keeps its own button colours whatever the palette says */
  html[data-theme] .close-band .btn.hollow { background: transparent; color: #efe9f6; border-color: rgba(239,233,246,.55); border-radius: 8px; }
  html[data-theme] .close-band .btn.hollow:hover { background: rgba(239,233,246,.1); color: #fff; border-color: #fff; box-shadow: none; }
  html[data-theme="paper"] .close-band .btn.hollow { border-radius: 2px; }

  /* -------- the family test rack: violet is foxora.ai's own sheet, ported token for
     token; rose · cobalt · sand · slate · orchid widen the hue coverage. Same manners
     as the tambo set: rounder controls, soft glow, dark ink on bright fills. */
  html[data-theme="violet"] {
    --paper: #f4eee1; --paper-hi: #fbf7ec; --ink: #231c2b; --ink-soft: #5b5268; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #4b3ba8; --v2: #5c36ac; --v3: #6e32a6; --v4: #84309f; --v5: #3b2f86;
    --deep: #2a2151; --deep2: #3a2d6d; --tear: #3a2d6d; --on-deep: #cdb9f2;
    --pop: #533d7a; --pop-ink: #fbf7ec;
    --band-ink: #241c31; --band-ink2: #2c2240; --band-label: #b9a7e6; --band-label-b: #d98fd0;
    --rule: rgba(75, 59, 168, 0.24); --rule-soft: rgba(75, 59, 168, 0.14); --frame-rule: rgba(75, 59, 168, 0.46); --grid-minor: rgba(75, 59, 168, 0.04);
    --ghost: rgba(75, 59, 168, 0.13); --aur1: rgba(92, 54, 172, 0.2); --aur2: rgba(132, 48, 159, 0.16);
    --soft: 1;
  }
  html[data-theme="rose"] {
    --paper: #fbf0f3; --paper-hi: #fef7f9; --ink: #2a0e18; --ink-soft: #6b4453; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #9f1239; --v2: #be123c; --v3: #be123c; --v4: #e11d48; --v5: #881337;
    --deep: #3a1020; --deep2: #55182f; --tear: #55182f; --on-deep: #fecdd3;
    --pop: #fda4af; --pop-ink: #2a0e18;
    --band-ink: #2c0d18; --band-ink2: #421424; --band-label: #fda4af; --band-label-b: #ffe4e6;
    --rule: rgba(225, 29, 72, 0.22); --rule-soft: rgba(225, 29, 72, 0.12); --frame-rule: rgba(225, 29, 72, 0.42); --grid-minor: rgba(225, 29, 72, 0.04);
    --ghost: rgba(225, 29, 72, 0.13); --aur1: rgba(253, 164, 175, 0.3); --aur2: rgba(244, 114, 182, 0.16);
    --soft: 1;
  }
  html[data-theme="cobalt"] {
    --paper: #eff3fc; --paper-hi: #f7f9fe; --ink: #0e1630; --ink-soft: #43507a; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #1d4ed8; --v2: #2563eb; --v3: #2563eb; --v4: #3b82f6; --v5: #1e3a8a;
    --deep: #16224a; --deep2: #1f3270; --tear: #1f3270; --on-deep: #bfdbfe;
    --pop: #93c5fd; --pop-ink: #0e1630;
    --band-ink: #101a3a; --band-ink2: #182652; --band-label: #93c5fd; --band-label-b: #dbeafe;
    --rule: rgba(37, 99, 235, 0.24); --rule-soft: rgba(37, 99, 235, 0.13); --frame-rule: rgba(37, 99, 235, 0.46); --grid-minor: rgba(37, 99, 235, 0.04);
    --ghost: rgba(37, 99, 235, 0.13); --aur1: rgba(147, 197, 253, 0.3); --aur2: rgba(129, 140, 248, 0.16);
    --soft: 1;
  }
  html[data-theme="sand"] {
    --paper: #f6f1e7; --paper-hi: #fbf8f1; --ink: #221b10; --ink-soft: #5e5340; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #6b5537; --v2: #7d6543; --v3: #7d6543; --v4: #a08256; --v5: #4a3a24;
    --deep: #272013; --deep2: #3a301d; --tear: #3a301d; --on-deep: #e7d9bd;
    --pop: #d9c39a; --pop-ink: #221b10;
    --band-ink: #241d11; --band-ink2: #362c1a; --band-label: #d9c39a; --band-label-b: #efe4cd;
    --rule: rgba(125, 101, 67, 0.28); --rule-soft: rgba(125, 101, 67, 0.15); --frame-rule: rgba(125, 101, 67, 0.4); --grid-minor: rgba(125, 101, 67, 0.045);
    --ghost: rgba(125, 101, 67, 0.15); --aur1: rgba(217, 195, 154, 0.3); --aur2: rgba(190, 160, 110, 0.16);
    --soft: 1;
  }
  html[data-theme="slate"] {
    --paper: #f0f2f5; --paper-hi: #f7f9fb; --ink: #10151c; --ink-soft: #4a5768; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #334155; --v2: #3f4f63; --v3: #3f4f63; --v4: #64748b; --v5: #1e293b;
    --deep: #161c26; --deep2: #232d3b; --tear: #232d3b; --on-deep: #cbd5e1;
    --pop: #aebfd3; --pop-ink: #10151c;
    --band-ink: #131922; --band-ink2: #1e2733; --band-label: #a9b8cc; --band-label-b: #d7dfe9;
    --rule: rgba(71, 85, 105, 0.28); --rule-soft: rgba(71, 85, 105, 0.15); --frame-rule: rgba(71, 85, 105, 0.4); --grid-minor: rgba(71, 85, 105, 0.045);
    --ghost: rgba(71, 85, 105, 0.15); --aur1: rgba(148, 163, 184, 0.26); --aur2: rgba(100, 116, 139, 0.14);
    --soft: 1;
  }
  html[data-theme="orchid"] {
    --paper: #f9f0f8; --paper-hi: #fdf7fc; --ink: #261023; --ink-soft: #644660; --ink-faint: color-mix(in srgb, var(--ink) 64%, var(--paper));
    --v1: #86198f; --v2: #a21caf; --v3: #a21caf; --v4: #c026d3; --v5: #701a75;
    --deep: #331030; --deep2: #4b1a47; --tear: #4b1a47; --on-deep: #f5d0fe;
    --pop: #f0abfc; --pop-ink: #261023;
    --band-ink: #2b0f28; --band-ink2: #40173c; --band-label: #f0abfc; --band-label-b: #fae8ff;
    --rule: rgba(162, 28, 175, 0.22); --rule-soft: rgba(162, 28, 175, 0.12); --frame-rule: rgba(162, 28, 175, 0.42); --grid-minor: rgba(162, 28, 175, 0.04);
    --ghost: rgba(162, 28, 175, 0.13); --aur1: rgba(240, 171, 252, 0.3); --aur2: rgba(217, 70, 239, 0.14);
    --soft: 1;
  }
  html[data-theme="violet"] .btn, html[data-theme="rose"] .btn, html[data-theme="cobalt"] .btn, html[data-theme="sand"] .btn, html[data-theme="slate"] .btn, html[data-theme="orchid"] .btn,
  html[data-theme="violet"] .pr-run, html[data-theme="rose"] .pr-run, html[data-theme="cobalt"] .pr-run, html[data-theme="sand"] .pr-run, html[data-theme="slate"] .pr-run, html[data-theme="orchid"] .pr-run { border-radius: 8px; box-shadow: none; }
  html[data-theme="rose"] .btn:hover, html[data-theme="cobalt"] .btn:hover, html[data-theme="sand"] .btn:hover,
  html[data-theme="slate"] .btn:hover, html[data-theme="orchid"] .btn:hover { background: var(--ink); border-color: var(--ink); color: var(--paper-hi); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 38%, transparent); }
  html[data-theme="violet"] .btn:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 30%, transparent); }
  html[data-theme="violet"] .btn.hollow, html[data-theme="rose"] .btn.hollow, html[data-theme="cobalt"] .btn.hollow,
  html[data-theme="sand"] .btn.hollow, html[data-theme="slate"] .btn.hollow, html[data-theme="orchid"] .btn.hollow { background: transparent; color: var(--ink); border-color: rgba(0,0,0,.4); }
  html[data-theme="violet"] .btn.hollow:hover, html[data-theme="rose"] .btn.hollow:hover, html[data-theme="cobalt"] .btn.hollow:hover,
  html[data-theme="sand"] .btn.hollow:hover, html[data-theme="slate"] .btn.hollow:hover, html[data-theme="orchid"] .btn.hollow:hover { background: transparent; color: var(--ink); border-color: var(--ink); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 30%, transparent); }
  html[data-theme="violet"] .close-band .btn:not(.hollow), html[data-theme="rose"] .close-band .btn:not(.hollow), html[data-theme="cobalt"] .close-band .btn:not(.hollow),
  html[data-theme="sand"] .close-band .btn:not(.hollow), html[data-theme="slate"] .close-band .btn:not(.hollow), html[data-theme="orchid"] .close-band .btn:not(.hollow) { background: var(--pop); color: var(--pop-ink); border-color: var(--pop); }
  html[data-theme="rose"] .eterm.hot, html[data-theme="cobalt"] .eterm.hot, html[data-theme="sand"] .eterm.hot,
  html[data-theme="slate"] .eterm.hot, html[data-theme="orchid"] .eterm.hot { background: var(--pop); border-color: var(--ink); color: var(--pop-ink); }
  html[data-theme="rose"] .seats-chip i, html[data-theme="cobalt"] .seats-chip i, html[data-theme="sand"] .seats-chip i,
  html[data-theme="slate"] .seats-chip i, html[data-theme="orchid"] .seats-chip i { background: var(--v3); }
  /* one mark, palette-aware everywhere: fold = accent, body = ink on paper; on deep surfaces fold = pop, body = light */
  .mk-fold { fill: var(--v4); }
  .mk-body { fill: var(--ink); }
  .foot-brand .mk-fold, .close-mark .mk-fold, .foot-seal .mk-fold { fill: var(--pop); }
  .foot-brand .mk-body { fill: #efe9f6; }
  .close-mark .mk-body { fill: var(--deep2); }
  .foot-seal .mk-body { fill: color-mix(in srgb, #efe9f6 70%, var(--deep)); }
  .seal .mk-fold { fill: var(--v4); }
  .seal .mk-body { fill: var(--ink-soft); }
  .rc-mark .mk-fold { fill: var(--v4); }
  .rc-mark .mk-body { fill: var(--ink); }
  /* seals follow the palette instead of carrying baked-in violet */
  .seal circle { stroke: var(--v3); }
  .seal circle:nth-of-type(3) { fill: color-mix(in srgb, var(--v3) 7%, transparent); }
  .seal text { fill: var(--v3); }

  /* alternate chapters carry a lighter wash; the grid shows through both */
  .how, .l5, .eco, .refusals, .partners { background: color-mix(in srgb, var(--paper-hi) 62%, transparent); border-top: 1px solid var(--rule); }
  .t-cell.void { padding: 0; background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--v1) 14%, transparent) 0 1px, transparent 1px 8px); }
  /* the sheet's title block — blueprint's strip under the nav */
  .titleblock { border-bottom: 1px solid var(--rule); background: transparent; }
  /* The strip takes whatever the sheet gives it: six cells on a product sheet,
     four on the company sheet. A fixed six-column track left the company page's
     four cells filling 741px of 1200 with two dead columns, and squeezed
     "Contains" into 1/6 until it wrapped. Auto columns cannot mismatch a count. */
  .titleblock .wrap { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
  /* The company sheet's four cells hold very unequal text — "1 : 1" against
     "Studio · Runtime · GRIP · Fennec" — so equal columns made the last one
     wrap and stood the strip 70px tall against every other page's 53. The
     tracks follow the content instead. */
  body.company .titleblock .wrap { grid-auto-flow: row; grid-template-columns: 1.05fr 0.8fr 0.55fr 1.6fr; }
  .titleblock span { display: block; padding: 9px 18px 10px; border-left: 1px solid var(--rule-soft); font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink); }
  .titleblock span:first-child { border-left: none; padding-left: 0; }
  .titleblock span i { display: block; font-style: normal; font-size: 9px; letter-spacing: .24em; color: var(--ink-faint); margin-bottom: 4px; }
  @media (max-width: 1080px) { .titleblock .wrap { grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); } .titleblock span { border-left: none; padding-left: 0; } }
  @media (max-width: 640px) { .titleblock { display: none; } }
  /* below 640 the chip is the first thing to go: it is a standing invitation, not a
     control, and the repository button beside it is the one that has to stay reachable. */
  @media (max-width: 640px) { .seats-chip { display: none; } }
  /* every chapter carries its bracket, hero and close included */
  .classline b, .close-band .k b { font-weight: 400; color: var(--v3); margin-right: 8px; }
  .close-band .k b { color: var(--on-deep); }
  /* ghost numerals default to the top-right corner of their chapter; sections must be positioned */
  .pillars, .how, .l5, .install, .console, .cost, .partners { position: relative; overflow: hidden; }
  .install .ghost-n { top: 20px; right: auto; left: max(48px, calc((100vw - 1200px) / 2)); }
  .cost .ghost-n { top: 24px; }

  /* the hero's ASCII field — a sparse, breathing grid of glyphs in the palette; a canvas, not an image */
  #ascii, #dots { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
  #ascii { opacity: .9; }
  html[data-bg="dots"] #ascii, html[data-bg="ascii"] #dots { display: none; }
  .hero { position: relative; }
  .hero .wrap { position: relative; z-index: 1; }

  /* the switcher — comp only, never ships */
  .themer { position: fixed; left: 18px; bottom: 18px; z-index: 90; display: flex; flex-wrap: wrap; max-width: calc(100vw - 36px); gap: 3px; padding: 5px; background: rgba(35,28,43,.9); border-radius: 22px; box-shadow: 0 10px 30px -10px rgba(0,0,0,.5); backdrop-filter: blur(8px); }
  .themer button { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: #cfc8d8; background: transparent; border: 0; padding: 7px 10px; border-radius: 999px; cursor: pointer; }
  .themer button:hover { color: #fff; }
  .themer button.on { background: #fbf7ec; color: #231c2b; }
  @media (max-width: 860px) { .themer { left: 10px; bottom: 10px; } .themer button { padding: 6px 9px; font-size: 9.5px; } }


  /* ========================================================= responsive */
  @media (max-width: 1240px) { .frame { display: none; } }
  @media (max-width: 1100px) {
    .hero .wrap, .install .wrap { grid-template-columns: 1fr; gap: 60px; }
    .receipt-col { align-items: center; }
    .slips { grid-template-columns: repeat(2, 1fr); }
    .steps { grid-template-columns: 1fr; }
    .spine-grid { grid-template-columns: 1fr; }
    .sp-receipt-hold { position: static; }
    .layer { grid-template-columns: 64px 1fr; }
    .layer .scene { grid-column: 1 / -1; }
    .cols { grid-template-columns: repeat(2, 1fr); }
    .colm { border-left: none; border-top: 1px solid var(--rule-soft); }
    .ref-grid { grid-template-columns: 1fr; }
    .rail { position: static; }
    .l5-grid { grid-template-columns: 1fr; gap: 36px; }
    .pillar-row { grid-template-columns: 1fr 1fr; }
    .pillar { padding: 22px 20px 12px 0; }
    .pillar + .pillar { padding-left: 20px; }
    .pillar:nth-child(2) { border-right: none; }
    .pillar:nth-child(n+3) { border-top: 1px solid var(--rule-soft); }
    .save-row { grid-template-columns: 1fr; }
    .save { border-right: none; border-bottom: 1px solid var(--rule-soft); }
    .inc-body { grid-template-columns: 1fr; }
    .inc-findings { border-right: none; border-bottom: 1px dashed rgba(35,28,43,.25); }
    .inc-head { flex-direction: column; align-items: flex-start; }
    .inc-meta { flex-wrap: wrap; gap: 10px 18px; }
    .article { grid-template-columns: 1fr; gap: 8px; }
    .article .a-no { text-align: left; border-right: none; padding: 0; }
    .sigblock { grid-template-columns: 1fr; gap: 40px; }
    .seal { justify-self: start; }
    .deed { padding: 32px 26px 30px; }
    .endorsements li { grid-template-columns: 30px 1fr; }
    .e-desc, .e-mark { grid-column: 2; }
    .lic-stamp { display: none; }
    .lic-cond { grid-template-columns: 1fr; gap: 6px; padding-right: 20px; }
    .foot-grid { grid-template-columns: 1fr 1fr; }
    .foot-seal { display: none; }
    .stair { flex-direction: column; align-items: stretch; padding-top: 0; }
    .tread { margin-bottom: 0 !important; }
    .ceiling { display: none; }
    .axes { grid-template-columns: repeat(2, 1fr); }
    .ticket { grid-template-columns: 1fr; }
    .ticket::before { display: none; }
    .ghost-n { display: none; }
    .trust .wrap { grid-template-columns: repeat(2, 1fr); }
    .t-cell.void { display: none; }
    .t-cell:nth-child(3) { border-left: none; }
  }
  @media (max-width: 860px) {
    /* The nav will not compress: brand, four links, the seats chip and the repository
       button do not fit one 390px line, and the answer used to be `display: none` — the
       four links simply left the site, with no menu and nothing in their place, so a
       phone could reach neither Install nor GRIP nor Contact from any page. A sheet that
       runs out of width does not delete a column, it takes a second line. The links get
       one: full width, ruled off, spread, and still in the tab order where they were. */
    /* A two-row bar is 129px, and 129px of a 844px phone pinned to the top for the
       whole page is worse than the problem it solves. The header scrolls away here,
       the way a phone header normally does; the footer carries the same links again
       at the other end, and every in-page anchor allows for the seam above it. */
    nav { position: static; backdrop-filter: none; }
    nav .wrap { flex-wrap: wrap; height: auto; padding-top: 9px; padding-bottom: 0; column-gap: 16px; }
    nav .brand { order: 1; }
    nav .nav-right { order: 2; }
    .links {
      order: 3; width: 100%; justify-content: space-between; gap: 4px;
      margin-top: 9px; border-top: 1px solid var(--rule-soft);
      font-size: 10.5px; letter-spacing: .12em;
    }
    .links a { padding: 14px 2px; }
    .links a::after { bottom: 9px; }
    .slips { grid-template-columns: 1fr; }
    .sch-head { display: none; }
    .sch-row { grid-template-columns: 44px 1fr; }
    .sch-row .mean, .sch-row .fix, .sch-row .id { grid-column: 2; border-left: none; padding-top: 0; }
    .sch-row.hot .refstamp { display: inline-block; }
    .cols { grid-template-columns: 1fr; }
    .eq .op { width: 100%; text-align: center; }
    .trust .wrap { grid-template-columns: 1fr; }
    .t-cell { border-left: none !important; }
    .axes { grid-template-columns: 1fr; }
  }

/* ============================================================ sub-pages */
.page-hero { position: relative; overflow: hidden; }
.page-hero .wrap { padding-top: 76px; padding-bottom: 64px; }
.page-hero .wrap.two { display: grid; grid-template-columns: 1.05fr .95fr; gap: 64px; align-items: center; }
.page-hero h1 { font-family: var(--display); font-weight: 700; font-size: clamp(38px, 4vw, 56px); line-height: 1.06; letter-spacing: -.004em; text-wrap: balance; margin-bottom: 20px; }
.page-hero h1 em { font-style: italic; font-weight: 400; }
.page-sec { position: relative; overflow: visible; border-top: 1px solid var(--rule); }   /* visible: an overflow:hidden ancestor kills position:sticky on the article rail */
.page-sec .wrap { padding-top: 72px; padding-bottom: 76px; }
.page-sec.wash { background: color-mix(in srgb, var(--paper-hi) 62%, transparent); }
.subpage nav a[aria-current="page"] { color: var(--v3); }
.subpage nav a[aria-current="page"]::after { transform: scaleX(1); }
/* install: the checklist sheet and the run sheet */
.steps-sheet, .runsheet { margin-top: 32px; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.2); box-shadow: var(--shadow-card); }
.ss-row { display: grid; grid-template-columns: 44px 1fr 220px; gap: 22px; align-items: start; padding: 20px 24px; border-bottom: 1px solid var(--rule-soft); }
.ss-row:last-child { border-bottom: none; }
.ss-n { font-family: var(--mono); font-size: 11px; color: var(--v3); padding-top: 4px; }
.ss-row b { display: block; font-family: var(--display); font-size: 19px; margin-bottom: 5px; }
.ss-row p { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); }
.ss-row code { font-family: var(--mono); font-size: 11.5px; color: var(--ink); background: color-mix(in srgb, var(--v1) 7%, transparent); border: 1px solid color-mix(in srgb, var(--v1) 24%, transparent); padding: 6px 10px; justify-self: end; white-space: nowrap; }
.rs-row { display: grid; grid-template-columns: 34px 300px 1fr; gap: 16px; align-items: baseline; padding: 15px 24px; border-bottom: 1px solid var(--rule-soft); }
.rs-row:last-child { border-bottom: none; }
.rs-row i { font-style: normal; font-family: var(--mono); font-size: 11px; color: var(--v3); }
.rs-row b { font-family: var(--body); font-weight: 700; font-size: 15.5px; }
.rs-row span { font-size: 14px; line-height: 1.55; color: var(--ink-soft); }
.rs-row code { font-family: var(--mono); font-size: 12px; color: var(--v3); }
/* contact: five doors */
.doors { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.door { display: block; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.16); border-top: 2px solid var(--ink); padding: 20px 22px 18px; box-shadow: var(--shadow-card); position: relative; transition: transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s; }
.door:hover { transform: translateY(-3px); box-shadow: 0 26px 50px -30px color-mix(in srgb, var(--deep) 55%, transparent); }
.door .d-n { font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em; color: var(--v3); display: block; margin-bottom: 10px; }
.door b { display: block; font-family: var(--display); font-size: 21px; line-height: 1.15; margin-bottom: 8px; }
.door p { font-size: 14.5px; line-height: 1.55; color: var(--ink-soft); margin-bottom: 12px; }
.door code { font-family: var(--mono); font-size: 11.5px; color: var(--v3); border-bottom: 1px dotted var(--v3); }
.door:last-child { grid-column: span 2; }
.page .caption { margin-top: 26px; font-size: 13px; font-style: italic; color: var(--ink-soft); }
.page .caption a { color: var(--v3); border-bottom: 1px dotted var(--v3); }
/* policies: a table of contents rail and the sheet */
.policy-grid { display: grid; grid-template-columns: 240px 1fr; gap: 56px; align-items: start; }
.policy-toc { position: sticky; top: 96px; align-self: start; display: grid; gap: 2px; }
.policy-toc .chapter { margin-bottom: 10px; }
.policy-toc a { font-family: var(--mono); font-size: 11.5px; color: var(--ink-soft); padding: 5px 0; border-bottom: 1px solid var(--rule-soft); }
.policy-toc a:hover { color: var(--v3); }
.policy-toc .draft { justify-self: start; margin-top: 22px; color: var(--v5); }
.policy-toc .draft b { font-size: 13px; letter-spacing: .2em; }
.policy { background: var(--paper-hi); border: 1px solid rgba(35,28,43,.2); outline: 3px double var(--rule); outline-offset: 6px; padding: 40px 48px 44px; box-shadow: var(--shadow-obj); }
.pol-kicker { font-family: var(--mono); font-size: 10px; letter-spacing: .24em; text-transform: uppercase; color: var(--v3); margin-bottom: 26px; padding-bottom: 14px; border-bottom: 1px solid var(--rule); }
.policy h3 { font-family: var(--display); font-weight: 700; font-size: 22px; margin: 30px 0 10px; scroll-margin-top: 90px; }
.policy h3 i { font-style: normal; font-family: var(--mono); font-size: 12px; color: var(--v3); margin-right: 12px; letter-spacing: .1em; }
.policy p { font-size: 15px; line-height: 1.65; color: var(--ink-soft); margin-bottom: 12px; }
.policy p b { color: var(--ink); }
.policy code { font-family: var(--mono); font-size: 12px; color: var(--v3); }
.policy a { color: var(--v3); border-bottom: 1px dotted var(--v3); }
.policy mark { background: color-mix(in srgb, var(--v5) 12%, transparent); color: var(--ink); padding: 0 4px; font-family: var(--mono); font-size: 12.5px; }
.pol-table { width: 100%; border-collapse: collapse; margin: 8px 0 14px; font-size: 13.5px; }
.pol-table th { text-align: left; font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); padding: 8px 10px 8px 0; border-bottom: 1px solid var(--ink); }
.pol-table td { vertical-align: top; padding: 10px 10px 10px 0; border-bottom: 1px solid var(--rule-soft); line-height: 1.5; color: var(--ink-soft); }
.pol-table td:first-child { color: var(--ink); font-weight: 700; }
/* Four columns of prose will not fit a phone. Rather than let the widest cell
   set the sheet's width — which pushed the whole page 59px sideways and dragged
   the fixed notice and grain out with it — the table keeps its columns and
   scrolls under the thumb, the same bargain the title block already makes. */
.pol-scroll { overflow-x: auto; scrollbar-width: thin; overscroll-behavior-x: contain; }
.pol-scroll::-webkit-scrollbar { height: 4px; }
.pol-scroll::-webkit-scrollbar-thumb { background: var(--rule); }
/* A grid item's automatic minimum is its own content, so every grid between the
   table and the sheet has to be told to let go — one `min-width: 0` short of the
   table and the whole column is dragged wide again. Both grids are named here:
   .policy-grid holds the rail and the deed, .article holds each numbered clause. */
.policy-grid > *,
.policy-deed .article,
.policy-deed .article > * { min-width: 0; }
@media (max-width: 720px) { .pol-scroll .pol-table { min-width: 460px; } }
/* the notice: no cookies here — a transparency notice, not a consent gate (nothing to consent to).
   If analytics are ever added, this MUST become a real gate: reject/accept with equal prominence, default off. */
.consent { position: fixed; right: 18px; bottom: 18px; z-index: 92; max-width: 380px; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.22); border-top: 2px solid var(--ink); box-shadow: var(--shadow-obj); padding: 16px 18px 14px; transform: translateY(20px); opacity: 0; transition: transform .5s cubic-bezier(.22,1,.36,1), opacity .4s; }
.consent.on { transform: none; opacity: 1; }
.consent b { display: block; font-family: var(--display); font-size: 17px; margin-bottom: 6px; }
.consent p { font-size: 13px; line-height: 1.55; color: var(--ink-soft); margin-bottom: 12px; }
.consent .row { display: flex; align-items: center; gap: 12px; }
.consent .btn { padding: 8px 14px; font-size: 12px; }
.consent a.more { font-family: var(--mono); font-size: 11px; color: var(--v3); border-bottom: 1px dotted var(--v3); }
@media (max-width: 1080px) { .page-hero .wrap.two { grid-template-columns: 1fr; gap: 40px; } .policy-grid { grid-template-columns: 1fr; gap: 28px; } .policy-toc { position: static; } .rs-row { grid-template-columns: 30px 1fr; } .rs-row span { grid-column: 2; } .ss-row { grid-template-columns: 40px 1fr; } .ss-row code { grid-column: 2; justify-self: start; } .doors { grid-template-columns: 1fr; } .door:last-child { grid-column: auto; } .policy { padding: 28px 22px; } }
/* the 64px lift was clearance for the comp-only theme switcher, which no longer
   ships; the notice sits on the edge it belongs on. */
@media (max-width: 860px) { .consent { left: 10px; right: 10px; bottom: 10px; max-width: none; } }
/* policies drawn up as deeds — the contract object, on the right of a table of articles */
.policy-deed { margin-top: 0; text-align: center; }
.deed-name { font-family: var(--display); font-weight: 700; font-size: 26px; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 6px; }
.policy-deed .article { grid-template-columns: 148px 1fr; gap: 22px; scroll-margin-top: 96px; }
.policy-deed .article p { margin-bottom: 8px; }
.policy-deed .article p:last-child { margin-bottom: 0; }
.policy-deed .article code { font-family: var(--mono); font-size: 12px; color: var(--v3); }
.policy-deed .article a { color: var(--v3); border-bottom: 1px dotted var(--v3); }
.policy-deed mark { background: color-mix(in srgb, var(--v5) 12%, transparent); color: var(--ink); padding: 0 4px; font-family: var(--mono); font-size: 12.5px; }
.policy-deed .pol-table { margin: 6px 0 4px; }
.witness { font-family: var(--display); font-style: italic; font-size: 15px; color: var(--ink-soft); border-top: 1px solid var(--rule-soft); padding-top: 24px; margin-bottom: 30px; }
.draft-stamp { position: absolute; top: 22px; right: 26px; color: var(--v5); }
.draft-stamp b { font-size: 14px; letter-spacing: .2em; }
@media (max-width: 1080px) { .policy-deed { padding: 32px 22px 30px; } .policy-deed .article { grid-template-columns: 1fr; gap: 6px; } .policy-deed .a-no { text-align: left; border-right: none; padding: 0; } .draft-stamp { position: static; display: inline-block; margin-bottom: 14px; } .policy-deed .sigblock { grid-template-columns: 1fr; gap: 36px; } .policy-deed .seal { justify-self: start; } }

/* ======================================================= 12 · approval
   the drawing's approval block — the sheet ends the way every sheet ends: drawn, checked, approved. */
.approval { position: relative; overflow: hidden; border-top: 3px double var(--rule); background: color-mix(in srgb, var(--paper-hi) 62%, transparent); }
.approval .wrap { padding-top: 88px; padding-bottom: 96px; }
.approval .ghost-n { top: 20px; }
.appr-head { display: grid; grid-template-columns: 1.1fr .9fr; gap: 48px; align-items: end; margin-bottom: 40px; }
.appr-head h2 { margin-bottom: 0; }
.appr-deck { font-size: 16.5px; line-height: 1.6; color: var(--ink-soft); max-width: 46ch; }
.appr-block { background: var(--paper-hi); border: 1.5px solid var(--ink); box-shadow: var(--shadow-obj); position: relative; }
.appr-row { display: grid; grid-template-columns: repeat(4, 1fr); border-bottom: 1.5px solid var(--ink); }
.appr-cell { padding: 16px 20px 18px; border-right: 1px solid var(--rule); min-width: 0; }
.appr-cell:last-child { border-right: none; }
.appr-cell i { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 8px; font-style: normal; }
.appr-cell b { display: block; font-family: var(--display); font-weight: 700; font-size: 24px; line-height: 1.05; margin-bottom: 8px; }
.appr-cell b.hand { font-weight: 400; font-style: italic; font-size: 26px; }
.appr-cell .ok { display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .02em; color: var(--ink-soft); line-height: 1.5; }
.appr-cell .ok em { font-style: normal; color: var(--v3); margin-right: 6px; }
.appr-cell .ok code { font-family: var(--mono); color: var(--v3); }
.appr-sign { display: grid; grid-template-columns: 1fr auto; gap: 40px; align-items: end; padding: 30px 28px 30px; }
.appr-line i { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); font-style: normal; }
.sig-big { position: relative; height: 1.5px; background: var(--ink); margin: 52px 0 12px; }
.sig-big.rv { opacity: 1; transform: scaleX(0); transform-origin: 0 50%; transition: transform 1.1s cubic-bezier(.22,1,.36,1); }
.sig-big.rv.on { transform: scaleX(1); }
.sig-big .x { position: absolute; left: 4px; top: -40px; font-family: var(--display); font-style: italic; font-size: 34px; color: var(--ink-faint); }
.appr-note { font-size: 14px; font-style: italic; color: var(--ink-soft); }
.appr-cta { display: flex; gap: 12px; align-items: center; padding-bottom: 22px; }
@media (max-width: 1080px) { .appr-head { grid-template-columns: 1fr; gap: 18px; } .appr-row { grid-template-columns: repeat(2, 1fr); } .appr-cell:nth-child(2) { border-right: none; } .appr-cell:nth-child(n+3) { border-top: 1px solid var(--rule); } .appr-sign { grid-template-columns: 1fr; gap: 22px; } .appr-cta { padding-bottom: 0; } }
@media (max-width: 640px) { .appr-row { grid-template-columns: 1fr; } .appr-cell { border-right: none; border-top: 1px solid var(--rule); } .appr-cell:first-child { border-top: none; } .appr-cta { flex-wrap: wrap; } }
/* IR-01 refiled: engineer's terms under each finding, the unsigned line, the clipped memo */
.inc-list li div small { display: block; margin-top: 5px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .04em; color: var(--ink-faint); line-height: 1.5; }
.inc-list li { grid-template-columns: 34px 1fr auto; padding: 12px 0; }
.inc-sign { display: grid; grid-template-columns: auto 1fr auto; gap: 16px; align-items: end; padding: 16px 28px 14px 44px; border-top: 1px dashed rgba(35,28,43,.28); }
.inc-sign .inc-label { font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--ink-faint); padding-bottom: 4px; }
.inc-sign .inc-blank { height: 1px; background: var(--ink); margin-bottom: 8px; position: relative; }
.inc-sign .inc-blank::before { content: "x"; position: absolute; left: 2px; top: -24px; font-family: var(--display); font-style: italic; font-size: 20px; color: var(--ink-faint); }
.inc-sign .inc-hint { font-size: 12.5px; font-style: italic; color: var(--ink-soft); padding-bottom: 4px; }
.inc-clip { position: absolute; right: 22px; top: 300px; width: 250px; background: var(--paper); border: 1px solid rgba(35,28,43,.22); box-shadow: var(--shadow-card); padding: 12px 14px 13px; transform: rotate(2.5deg); }
.inc-clip span { display: block; font-family: var(--mono); font-size: 9px; letter-spacing: .2em; text-transform: uppercase; color: var(--v3); margin-bottom: 6px; }
.inc-clip b { display: block; font-family: var(--body); font-weight: 400; font-size: 13px; line-height: 1.5; color: var(--ink); }
.inc-side { padding-bottom: 150px; }
@media (max-width: 1080px) { .inc-clip { position: static; transform: none; width: auto; margin: 16px 26px 0; } .inc-side { padding-bottom: 22px; } .inc-sign { grid-template-columns: 1fr; gap: 6px; } }

/* ============================================ 01 · the problem, six scenes
   Six moments where AI at real work comes apart, each with a small figure drawn on paper.
   Same sheet as the rest of the page: Didot for the claims, Charter for the sentences, mono for labels. */
.problem.problem-light { position: relative; overflow: visible; border-top: 3px double var(--rule); background: color-mix(in srgb, var(--paper-hi) 62%, transparent); }   /* visible: overflow:hidden would kill the sticky rail */
.problem-light .wrap { position: relative; z-index: 1; padding-top: 92px; padding-bottom: 96px; }
.problem-overview { display: grid; grid-template-columns: 1.1fr .9fr; gap: 56px; align-items: end; padding-bottom: 40px; border-bottom: 1.5px solid var(--ink); }
.problem-overview .chapter { grid-column: 1 / -1; margin-bottom: 4px; }
.problem-overview h2 { margin-bottom: 0; }
.problem-overview .lede { margin: 0; font-size: 16.5px; }
.problem-position { grid-column: 2; font-family: var(--body); font-style: italic; font-size: 15px; line-height: 1.55; color: var(--ink); border-left: 2px solid var(--v3); padding-left: 14px; }

.problem-scenes { list-style: none; counter-reset: fig; }
/* the stage: one sticky rail on the left that hands over from problem to problem; the drawings scroll on the right */
.problem-stage { display: grid; grid-template-columns: minmax(290px, .78fr) 1.36fr; gap: 44px; align-items: start; }
.problem-rail { position: sticky; top: 104px; padding-top: 44px; min-height: 420px; }
.rail-index { list-style: none; display: flex; gap: 6px; align-items: center; margin-bottom: 26px; }
.rail-index a { display: inline-flex; align-items: center; gap: 8px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em; color: var(--ink-faint); padding: 4px 2px; }
.rail-index a i { display: block; width: 26px; height: 2px; background: var(--rule); transition: background .4s ease, width .5s cubic-bezier(.22,1,.36,1); }
.rail-index a.is-active { color: var(--v3); }
.rail-index a.is-active i { background: var(--v3); width: 44px; }
.problem-rail .problem-scene__copy { position: absolute; left: 0; right: 0; top: 96px; opacity: 0; transform: translateY(22px); pointer-events: none; transition: opacity .45s ease, transform .6s cubic-bezier(.22,1,.36,1); }
.problem-rail .problem-scene__copy.is-active { position: relative; top: auto; opacity: 1; transform: none; pointer-events: auto; transition-delay: .08s; }
.problem-rail .problem-scene__copy.was-active { transform: translateY(-16px); }
.problem-scenes { list-style: none; counter-reset: fig; }
.problem-scene { counter-increment: fig; padding: 52px 0; }
.problem-scene + .problem-scene { border-top: 1px dashed var(--rule); }
.problem-scene__figures { display: grid; gap: 104px; }
.problem-scene__category { display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--v3); margin-bottom: 14px; }
.problem-scene h3 { font-family: var(--display); font-weight: 700; font-size: clamp(26px, 2.3vw, 32px); line-height: 1.1; letter-spacing: -.004em; margin-bottom: 12px; text-wrap: balance; }
.problem-scene__subtitle { font-family: var(--body); font-style: italic; font-size: 16.5px; color: var(--ink); margin-bottom: 10px; }
.problem-scene__body { font-size: 15px; line-height: 1.62; color: var(--ink-soft); }
/* the remedy: a receipt stub, torn off the ledger */
.problem-scene__answer { position: relative; margin-top: 22px; background: var(--paper-hi); border: 1px solid rgba(35,28,43,.16); border-top: 2px solid var(--ink); padding: 14px 18px 14px 28px; box-shadow: var(--shadow-card); }
.problem-scene__answer::before { content: ""; position: absolute; left: 10px; top: 8px; bottom: 8px; width: 5px; background-image: radial-gradient(circle at 50% 50%, var(--paper) 2.1px, transparent 2.6px); background-size: 5px 11px; background-repeat: repeat-y; }
.problem-scene__answer span { display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase; color: var(--v3); margin-bottom: 6px; }
.problem-scene__answer b { display: block; font-family: var(--display); font-size: 18px; line-height: 1.2; margin-bottom: 5px; }
.problem-scene__answer p { font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }

/* the figure: a small drawing on paper, with its Fig. tab */
.problem-figure { position: relative; background: none; border: 0; box-shadow: none; padding: 0; display: block; }
.problem-figure .bp { filter: drop-shadow(0 18px 28px color-mix(in srgb, var(--deep) 13%, transparent)); }
.problem-figure::before { content: none; }



.figure-heading { position: relative; z-index: 2; display: flex; flex-direction: row-reverse; justify-content: space-between; align-items: flex-end; gap: 22px; padding: 0 0 8px; margin: 0; border: 0; }
.problem-figure--fox .figure-heading span { color: var(--v3); }
.figure-heading span { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink);
    border: 1.8px solid currentColor; outline: 1px solid currentColor; outline-offset: 3.5px; padding: 6px 11px 5px;
    transform: rotate(-3.4deg); transform-origin: 100% 100%; margin: 0 62px 7px 0; opacity: .82; white-space: nowrap; flex: none; }
.figure-heading b { flex: 1; font-family: var(--display); font-weight: 700; font-size: 20px; line-height: 1.15; letter-spacing: -.004em; text-wrap: balance; }
.figure-foot { margin-top: auto; padding-top: 18px; text-align: center; font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); }
.figure-foot i { display: inline-block; width: 26px; height: 1px; background: var(--rule); vertical-align: middle; margin: 0 10px; }
.figure-foot--warning { color: var(--v5); }
/* every piece of a figure arrives in order once the scene is on screen */
.scene-step { opacity: 0; transform: translateY(8px); transition: opacity .5s ease var(--step, 0s), transform .6s cubic-bezier(.22,1,.36,1) var(--step, 0s); }
.problem-scene.rv.on .scene-step { opacity: 1; transform: none; }
@keyframes dashflow { to { background-position: -20px 0; } }
@keyframes dashflow-y { to { background-position: 0 -20px; } }


/* what it stands on */
.problem-foundation { margin-top: 64px; padding-top: 24px; border-top: 1.5px solid var(--ink); display: grid; grid-template-columns: 1fr 1.3fr; gap: 32px; align-items: start; }
.problem-foundation p { font-size: 15px; line-height: 1.6; color: var(--ink-soft); }
.problem-foundation p b { color: var(--ink); }
.problem-proof { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.problem-proof span { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; padding: 8px 12px; border: 1px solid var(--ink); background: var(--paper-hi); box-shadow: 2px 2px 0 rgba(35,28,43,.14); }

@media (max-width: 1080px) {
  .problem-overview { grid-template-columns: 1fr; gap: 18px; } .problem-position { grid-column: 1; }
  .problem-stage { grid-template-columns: 1fr; gap: 28px; } .problem-rail { position: static; padding-top: 0; min-height: 0; } .problem-rail .problem-scene__copy { position: relative; top: auto; opacity: 1; transform: none; pointer-events: auto; margin-bottom: 28px; } .rail-index { display: none; }
  .problem-foundation { grid-template-columns: 1fr; } .problem-proof { justify-content: flex-start; }
}
@media (max-width: 640px) {
  .model-load { grid-template-columns: 1fr; } .model-load__line { width: 1px; height: 40px; background: repeating-linear-gradient(180deg, var(--v3) 0 6px, transparent 6px 10px); margin: 0 auto; animation-name: dashflow-y; } .model-load__line i { display: none; } .model-load__line em { left: 16px; top: 50%; transform: translateY(-50%); }
  .crew-board { grid-template-columns: repeat(2, 1fr); }
  .job-check { grid-template-columns: 24px 1fr auto; } .job-check span { grid-column: 2 / -1; }
  .safety-flow { grid-template-columns: 1fr; gap: 20px; justify-items: center; } .safety-flow__path { width: 100%; }
}
/* ============================================ the blueprint drawings (svg.bp)
   Twelve sheets: frame, dogear, FIG strip, balloon — kept, but at paper weight (1px, 70% ink) so the
   drawing, not the drafting table, is the loudest thing. Inside: "soft panels, settled" — one focus
   surface per figure, tinted tiles, one stroke weight, three tones, four build beats and one slow ride.
   Everything in tokens; nothing typed as a hex. */
.bp { display: block; width: 100%; height: auto; overflow: visible; }
.bp text { font-family: var(--mono); font-size: 11px; letter-spacing: .08em; fill: var(--ink); text-anchor: middle; }
.bp rect, .bp line, .bp path, .bp circle, .bp ellipse { vector-effect: non-scaling-stroke; }
.bp use { stroke-width: 1; }
.bp .bp-paper { fill: var(--paper-hi); }
.bp .bp-frame { fill: none; stroke: color-mix(in srgb, var(--ink) 70%, transparent); stroke-width: 1; }
.bp .bp-ear { fill: var(--paper); stroke: color-mix(in srgb, var(--ink) 70%, transparent); stroke-width: 1; }
.bp .bp-earline { fill: none; stroke: var(--rule); stroke-width: 1; }
.bp .bp-strip line { stroke: color-mix(in srgb, var(--ink) 30%, transparent); stroke-width: 1; shape-rendering: crispEdges; }
.bp .bp-strip text { font-size: 10.5px; letter-spacing: .14em; fill: var(--ink-faint); text-anchor: start; }
.bp .bp-strip text.r { text-anchor: end; fill: color-mix(in srgb, var(--ink) 40%, transparent); }
.bp .ball { fill: var(--paper-hi); stroke: color-mix(in srgb, var(--ink) 70%, transparent); stroke-width: 1; }
.bp .ballt { font-size: 10px; font-weight: 400; letter-spacing: .04em; }
.problem-figure .bp { filter: drop-shadow(0 14px 22px color-mix(in srgb, var(--deep) 9%, transparent)); }
.bp .pop { opacity: 0; transition: opacity .5s ease var(--d, 0s); }
.problem-scene.rv.on .bp .pop { opacity: 1; }

/* the drawing language */
.bp .sc {
  --ln-focus: color-mix(in srgb, var(--v3) 45%, transparent);
  --ln-tile: color-mix(in srgb, var(--v3) 40%, transparent);
  --ln-acc: color-mix(in srgb, var(--v3) 35%, transparent);
  --ln-neutral: color-mix(in srgb, var(--ink) 18%, transparent);
  --ln-loose: color-mix(in srgb, var(--ink-faint) 60%, transparent);
  --ln-warn: color-mix(in srgb, var(--v5) 55%, transparent);
  --fl-focus: var(--paper-hi);
  --fl-tile: color-mix(in srgb, var(--v3) 8%, var(--paper-hi));
  --fl-tile-strong: color-mix(in srgb, var(--v3) 14%, var(--paper-hi));
  --fl-badge: color-mix(in srgb, var(--v3) 12%, var(--paper-hi));
  --fl-neutral: color-mix(in srgb, var(--ink) 4%, var(--paper-hi));
  --fl-warn: color-mix(in srgb, var(--v5) 9%, var(--paper-hi));
  --halo: color-mix(in srgb, var(--v3) 20%, transparent);
  --halo-warn: color-mix(in srgb, var(--v5) 14%, transparent);
  --ico: color-mix(in srgb, var(--ink) 60%, transparent);
  --tx: color-mix(in srgb, var(--ink) 62%, transparent);
  --tx-faint: color-mix(in srgb, var(--ink) 40%, transparent);
  --tx-acc: color-mix(in srgb, var(--v3) 85%, transparent);
  --tx-warn: color-mix(in srgb, var(--v5) 75%, transparent);
  --t0: 0s;
}
.problem-figure--fox .bp .sc { --t0: .25s; }
.bp .sc text { font-family: var(--mono); font-size: 9.5px; font-weight: 400; letter-spacing: .04em; text-transform: uppercase; fill: var(--tx); text-anchor: middle; stroke: none; }
.bp .sc .lb.l { text-anchor: start; } .bp .sc .lb.r { text-anchor: end; }
.bp .sc .lb.faint { fill: var(--tx-faint); } .bp .sc .lb.acc { fill: var(--tx-acc); } .bp .sc .lb.warn { fill: var(--tx-warn); }
.bp .sc .lb.small { font-size: 8.5px; } .bp .sc .lb.head { font-size: 8.5px; fill: color-mix(in srgb, var(--ink) 50%, transparent); }
.bp .sc .lb.count { font-size: 11px; letter-spacing: 0; font-variant-numeric: tabular-nums; fill: var(--tx-acc); }
.bp .sc .lb.letter { font-size: 12px; letter-spacing: 0; fill: var(--tx); }
.bp .sc .lb.q { font-size: 12px; letter-spacing: 0; fill: var(--tx-faint); } .bp .sc .lb.qw { font-size: 10px; letter-spacing: 0; fill: var(--tx-warn); }
.bp .sc .pillt { font-size: 9px; letter-spacing: .06em; fill: var(--tx-acc); }
.bp .sc .pillt.warn { fill: var(--tx-warn); } .bp .sc .pillt.neutral { font-size: 8.5px; fill: var(--tx); } .bp .sc .pillt.solid { fill: var(--paper-hi); }
.bp .sc .ico { color: var(--ico); } .bp .sc .ico.acc { color: var(--v3); } .bp .sc .ico.warn { color: var(--tx-warn); }
.bp .sc .panel { fill: var(--fl-focus); stroke: none; }
.bp .sc .inset { fill: none; stroke: var(--ln-focus); stroke-width: 1; stroke-dasharray: 6 5; stroke-linecap: round; }
.bp .sc .halo { fill: var(--halo); filter: blur(6px); } .bp .sc .halo.warn { fill: var(--halo-warn); }
.bp .sc .tile { fill: var(--fl-tile); stroke: var(--ln-tile); stroke-width: 1; }
.bp .sc .tile.neutral { fill: var(--fl-neutral); stroke: var(--ln-neutral); }
.bp .sc .tile.warn { fill: var(--fl-warn); stroke: var(--ln-warn); }
.bp .sc .tile.dashed { stroke-dasharray: 5 5; stroke: var(--ln-focus); }
.bp .sc .badge { fill: var(--fl-badge); stroke: var(--ln-tile); stroke-width: 1; }
.bp .sc .badge.neutral { fill: var(--fl-neutral); stroke: var(--ln-neutral); }
.bp .sc .card { fill: var(--fl-tile-strong); stroke: var(--ln-tile); stroke-width: 1; }
.bp .sc .hair { fill: none; stroke: var(--rule); stroke-width: 1; }
.bp .sc .bar { fill: var(--rule-soft); transform-origin: 0 50%; transform-box: fill-box; transform: scaleX(0); transition: transform .5s cubic-bezier(.22,1,.36,1) calc(var(--d, 0s) * .55 + var(--t0)); }
.problem-scene.rv.on .bp .sc .bar { transform: none; }
.bp .sc .pill { stroke: none; } .bp .sc .pill.acc { fill: var(--fl-badge); } .bp .sc .pill.warn { fill: var(--fl-warn); }
.bp .sc .pill.neutral { fill: var(--fl-neutral); } .bp .sc .pill.solid { fill: var(--v3); }
.bp .sc .thread { fill: none; stroke-width: 1; stroke-linecap: round; }
.bp .sc .thread.acc { stroke: var(--ln-acc); } .bp .sc .dot.acc { fill: color-mix(in srgb, var(--v3) 55%, transparent); }
.bp .sc .thread.loose { stroke: var(--ln-loose); stroke-dasharray: 2 4; } .bp .sc .dot.loose { fill: var(--ln-loose); }
.bp .sc .warndot { fill: var(--tx-warn); }
.bp .sc .okdot { fill: var(--v3); } .bp .sc .okp { fill: none; stroke: var(--paper-hi); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; }
.bp .sc .pulse { fill: none; stroke: var(--ln-focus); stroke-width: 1; opacity: 0; transform-box: fill-box; transform-origin: center; }
.bp .sc .ghost { opacity: .38; }

/* the four beats: ground → land → tie → say (delays are --d + the figure's --t0) */
.bp .sc .ground { opacity: 0; transition: opacity .5s ease calc(var(--d, 0s) * .55 + var(--t0)); }
.bp .sc .land, .bp .sc .sub { opacity: 0; transform: translateY(5px); transform-box: fill-box;
  transition: opacity .45s ease calc(var(--d, 0s) * .55 + var(--t0)), transform .55s cubic-bezier(.22,1,.36,1) calc(var(--d, 0s) * .55 + var(--t0)); }
.bp .sc .ground.land { transform: none; transition: opacity .5s ease calc(var(--d, 0s) * .55 + var(--t0)); }
.bp .sc .tie { opacity: 0; transition: opacity .45s ease calc(var(--d, 0s) * .55 + var(--t0)); }
.bp .sc .tie.wipe, .bp .sc .tie.wipe.down { clip-path: none; }
.bp .sc .say { opacity: 0; transition: opacity .35s ease calc(var(--d, 0s) * .55 + var(--t0)); }
.bp .sc .chk { opacity: 0; transform: scale(.9); transform-box: fill-box; transform-origin: center; transition: opacity .35s ease calc(var(--d, 0s) * .55 + var(--t0)), transform .35s cubic-bezier(.22,1,.36,1) calc(var(--d, 0s) * .55 + var(--t0)); }
.problem-scene.rv.on .bp .sc .ground, .problem-scene.rv.on .bp .sc .tie, .problem-scene.rv.on .bp .sc .say { opacity: 1; }
.problem-scene.rv.on .bp .sc .ghost { opacity: .38; }
.problem-scene.rv.on .bp .sc .land, .problem-scene.rv.on .bp .sc .sub, .problem-scene.rv.on .bp .sc .chk { opacity: 1; transform: none; }
.problem-scene.rv.on .bp .sc .land.ghost { opacity: .38; }

/* live: one slow, one-way ride per figure; reactions fire on the same clock */
.bp .sc .tok { opacity: 0; offset-rotate: 0deg; color: var(--v3); animation-timing-function: cubic-bezier(.45,0,.15,1); animation-iteration-count: infinite; animation-fill-mode: both; animation-play-state: paused; }
.bp .sc .tok-core { fill: color-mix(in srgb, currentColor 80%, transparent); }
.bp .sc .tok-card { fill: color-mix(in srgb, var(--v3) 28%, var(--paper-hi)); stroke: color-mix(in srgb, var(--v3) 55%, transparent); stroke-width: 1; }
.problem-scene.rv.on .bp .sc .tok { animation-play-state: running; }
@keyframes pb-ride { 0% { offset-distance: 0%; opacity: 0; } 6% { opacity: 1; } 50% { offset-distance: 100%; opacity: 1; } 57% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; } }
@keyframes pb-dwell { 0% { offset-distance: 0%; opacity: 0; } 6% { opacity: 1; } 26% { offset-distance: var(--rest); } 34% { offset-distance: var(--rest); } 56% { offset-distance: 100%; opacity: 1; } 63% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; } }
@keyframes pb-flip { 0% { offset-distance: 0%; opacity: 0; color: var(--v3); } 6% { opacity: 1; } 14% { color: var(--v3); } 18% { color: var(--v5); } 50% { offset-distance: 100%; opacity: 1; color: var(--v5); } 57% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; color: var(--v5); } }
@keyframes pb-stop { 0% { offset-distance: 0%; opacity: 0; color: var(--v3); } 6% { opacity: 1; } 16% { color: var(--v3); } 20% { color: var(--v5); } 44% { offset-distance: 100%; opacity: 1; } 84% { offset-distance: 100%; opacity: 1; } 90% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; color: var(--v5); } }
@keyframes pb-drift { 0% { offset-distance: 0%; opacity: 0; color: var(--v3); } 6% { opacity: 1; } 28% { color: var(--v3); } 34% { color: var(--v5); } 60% { opacity: 1; } 90% { offset-distance: 100%; opacity: 0; } 100% { offset-distance: 100%; opacity: 0; color: var(--v5); } }
@keyframes pb-carry { 0% { offset-distance: 0%; opacity: 0; } 6% { opacity: 1; } 40% { offset-distance: 50%; } 52% { offset-distance: 50%; } 86% { offset-distance: 100%; opacity: 1; } 92% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; } }
@keyframes pb-dip { 0% { offset-distance: 0%; opacity: 0; } 4% { opacity: 1; } 18% { opacity: 1; } 22% { opacity: 0; } 25% { offset-distance: 33.3%; } 29% { opacity: 1; } 43% { opacity: 1; } 47% { opacity: 0; } 50% { offset-distance: 66.7%; } 54% { opacity: 1; } 68% { opacity: 1; } 72% { opacity: 0; } 75% { offset-distance: 100%; } 79% { opacity: 1; } 93% { opacity: 1; } 97% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; } }
@keyframes pb-hop { 0% { offset-distance: 0%; opacity: 0; } 6% { opacity: 1; } 12% { offset-distance: 0%; } 22% { offset-distance: 33.33%; } 42% { offset-distance: 33.33%; } 52% { offset-distance: 66.67%; } 68% { offset-distance: 66.67%; } 78% { offset-distance: 100%; } 88% { opacity: 1; } 94% { opacity: 0; } 100% { offset-distance: 100%; opacity: 0; } }
/* the ride is NAMED only where motion is welcome — the token's class, never an inline
   style, so the reduced-motion rule below is the one that lands */
@media (prefers-reduced-motion: no-preference) {
  .bp .sc .tok.pb-ride  { animation-name: pb-ride; }
  .bp .sc .tok.pb-dwell { animation-name: pb-dwell; }
  .bp .sc .tok.pb-flip  { animation-name: pb-flip; }
  .bp .sc .tok.pb-stop  { animation-name: pb-stop; }
  .bp .sc .tok.pb-drift { animation-name: pb-drift; }
  .bp .sc .tok.pb-carry { animation-name: pb-carry; }
  .bp .sc .tok.pb-dip   { animation-name: pb-dip; }
  .bp .sc .tok.pb-hop   { animation-name: pb-hop; }
}


@media (max-width: 640px) { .bp .sc text { font-size: 12.5px; } .bp .sc .lb.small, .bp .sc .lb.head { font-size: 11px; } .bp .sc .lb.faint { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .bp .sc .ground, .bp .sc .land, .bp .sc .sub, .bp .sc .tie, .bp .sc .say, .bp .sc .bar, .bp .sc .chk, .bp .pop { transition: none; opacity: 1; transform: none; clip-path: none; }
  .bp .sc .ghost, .bp .sc .land.ghost { opacity: .38; }
  .bp .sc .tok { animation: none; opacity: 1; offset-distance: var(--rest, 50%); }
}

/* ============================================ rebuilt chapters (one layout each)
   Eleven chapters, one layout each, spliced from the per-section fragments. */

/* ============================================ shared drafting devices
   One vocabulary across the rebuilt chapters: whisper labels, title strips with
   dotted leaders, hairline sheet frames and dogears. Tokens only. */
.whisper { font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint); }
.strip { display: flex; justify-content: space-between; align-items: baseline; gap: 20px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint);
  border-top: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); padding-top: 9px; }
.strip .r { color: color-mix(in srgb, var(--ink) 40%, transparent); }
.leader { flex: 1; min-width: 24px; align-self: center; height: 1px; margin: 0 14px;
  background: radial-gradient(circle, var(--ink-faint) .8px, transparent 1px) 0 50%/6px 1px repeat-x;
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .6s cubic-bezier(.22,1,.36,1) var(--d, 0s); }
.rv.on .leader, .leader.on { transform: none; }
.sheet-frame { position: relative; border: 1px solid color-mix(in srgb, var(--ink) 70%, transparent); background: transparent; }
.dogear { position: absolute; right: -1px; top: -1px; width: 26px; height: 26px; z-index: 1;
  background: linear-gradient(225deg, var(--paper) 0 50%, transparent 50%); }
.dogear::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(225deg, transparent calc(50% - .5px), var(--rule) calc(50% - .5px) calc(50% + .5px), transparent calc(50% + .5px)); }
@media (prefers-reduced-motion: reduce) { .leader { transform: none !important; transition: none !important; } }

/* ---------------------------------------------- [problem] */
/* ============================================================ 01 · THE FOLD
   A mirrored spread. One 1px vertical fold runs down the chapter: left of it is always
   NOW, right of it is always WITH FOXORA. Declared once in the header, held for six
   leaves, and it governs the words and the drawings alike. Tokens only — no hex, no raw
   rgba, nothing heavier than 1px. */

/* The plate runs to the sheet's own edge — the full 1200 of .wrap, so the type keeps the
   44px margin and the drawings do not. Wider than this and the plate walks over the margin
   folio at 1440; this is the widest breakout the folio can live beside. */
.problem.problem-light { --plate-w: min(1200px, calc(100vw - 88px)); }

/* ---------------------------------------------------------- the first fold: the header
   The words all sit LEFT of the fold; the right half is deliberately empty, because that
   is where the chapter numeral lives. A watermark must never print over type — so instead
   of shrinking it or nudging it, the layout gives it a column of its own. */
.problem .problem-overview {
  display: grid; grid-template-columns: 1fr 1px 1fr; column-gap: 0; row-gap: 0;
  align-items: start; padding-bottom: 40px;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 70%, transparent);
}
.problem .problem-overview .chapter { grid-column: 1 / -1; grid-row: 1; margin-bottom: 30px; }
.problem .problem-overview h2 {
  grid-column: 1; grid-row: 2; margin: 0; padding-right: 52px;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(40px, 4vw, 56px); line-height: 1.04; letter-spacing: -.006em; text-wrap: balance;
}
.problem .problem-overview .fold-hd {
  grid-column: 2; grid-row: 2 / span 2; width: 1px; align-self: stretch; background: var(--rule-soft);
}
.problem .problem-overview .lede {
  grid-column: 1; grid-row: 3; margin: 22px 0 0; padding-right: 52px;
  font-size: 16.5px; line-height: 1.62; color: var(--ink-soft); max-width: 52ch;
}
/* the numeral drops to clear the kicker's leader and lands in the header's empty right
   half; its ±54px parallax stays inside that void at every scroll position */
.problem.problem-light .ghost-n { top: 56px; }

/* ---------------------------------------------------------- the margin folio */
.problem .problem-stage { position: relative; display: block; }
.problem .problem-folio { position: absolute; top: 0; bottom: 0; left: -104px; width: 44px; }
.problem .problem-folio .rail-index {
  position: sticky; top: 42vh; display: flex; flex-direction: column;
  align-items: flex-start; gap: 12px; margin: 0; list-style: none;
}
.problem .problem-folio .rail-index a {
  display: inline-flex; align-items: center; gap: 8px; padding: 0; white-space: nowrap;
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em; color: var(--ink-faint);
  transition: color .4s ease;
}
.problem .problem-folio .rail-index a i {
  display: block; width: 18px; height: 1px; background: var(--rule);
  transition: background .4s ease, width .5s cubic-bezier(.22,1,.36,1);
}
.problem .problem-folio .rail-index a.is-active { color: var(--v3); }
.problem .problem-folio .rail-index a.is-active i { width: 30px; background: var(--v3); }

/* ---------------------------------------------------------- the leaf: verso | fold | recto */
.problem .problem-scenes { list-style: none; margin: 0; }
.problem .problem-scene { position: relative; padding: 56px 0 64px; }
.problem .problem-scene + .problem-scene { border-top: 1px solid var(--rule-soft); }

/* Four shared rows — kicker · heading · aside · prose — run straight across the fold, so
   the problem and its answer are read off ONE set of baselines however the lines break.
   The recto has no aside, so it simply leaves row 3 empty and meets the verso again at
   row 4. Without subgrid the rows fall back to each half's own flow: the old behaviour. */
.problem .leaf-words {
  display: grid; grid-template-columns: 1fr 1px 1fr; column-gap: 0;
  grid-template-rows: auto auto auto auto; align-items: start;
}
.problem .leaf-verso, .problem .leaf-recto {
  display: grid; grid-template-rows: subgrid; grid-row: 1 / span 4;
}
.problem .leaf-verso { grid-column: 1; padding-right: 52px; }
.problem .leaf-recto { grid-column: 3; padding-left: 52px; }
.problem .problem-scene__category, .problem .leaf-recto > span { grid-row: 1; }
.problem .problem-scene h3, .problem .leaf-recto > b { grid-row: 2; }
.problem .problem-scene__subtitle { grid-row: 3; }
.problem .problem-scene__body, .problem .leaf-recto > p { grid-row: 4; }

/* the words' centre column and the plates' gutter fall on the same axis, so the fold is
   one unbroken line from the first word to the foot of the drawings */
.problem .leaf-fold {
  position: absolute; top: 56px; bottom: 64px; left: calc(50% - .5px);
  width: 1px; background: var(--rule); z-index: 1;
}

/* The two plates are one two-row grid, not two stacked blocks: the captions share row 1
   and the drawings share row 2, so a caption that wraps to two lines can never push one
   sheet below the other. */
.problem .leaf-plates {
  width: var(--plate-w); margin-inline: calc((100% - var(--plate-w)) / 2); margin-top: 36px;
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; column-gap: 40px;
}
.problem .problem-figure { display: contents; }
.problem .problem-figure--now .figure-heading { grid-column: 1; grid-row: 1; }
.problem .problem-figure--now .bp { grid-column: 1; grid-row: 2; }
.problem .problem-figure--fox .figure-heading { grid-column: 2; grid-row: 1; }
.problem .problem-figure--fox .bp { grid-column: 2; grid-row: 2; }

/* Alternating wash, so the run of six reads as a run at 20% zoom. paper-hi over this
   sheet is under two levels of 255 — invisible — so the band is the faintest possible
   breath of the accent instead, feathered at both ends so it never cuts a vertical seam. */
.problem .problem-scene--wash::before {
  content: ""; position: absolute; top: 0; bottom: 0; z-index: -1;
  left: calc((100% - var(--plate-w)) / 2); width: var(--plate-w);
  background: color-mix(in srgb, var(--v3) 2.2%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
}

/* ---------------------------------------------------------- verso type: the problem */
.problem .problem-scene__category {
  display: block; margin: 0; font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--v3);
}
.problem .problem-scene h3 {
  margin: 12px 0 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(30px, 2.6vw, 36px); line-height: 1.08; letter-spacing: -.004em; text-wrap: balance;
}
.problem .problem-scene__subtitle {
  margin: 10px 0 0; font-family: var(--body); font-style: italic; font-size: 16.5px;
  line-height: 1.45; color: var(--ink);
}
.problem .problem-scene__body { margin: 12px 0 0; font-size: 15px; line-height: 1.62; color: var(--ink-soft); }

/* ---------------------------------------------------------- recto type: the answer, unwrapped
   Same face, same size, facing its problem across the fold. That equality is the argument. */
.problem .leaf-recto > span {
  display: block; margin: 0; font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--v3);
}
.problem .leaf-recto > b {
  display: block; margin: 12px 0 0; font-family: var(--display); font-weight: 700; font-style: italic;
  font-size: clamp(30px, 2.6vw, 36px); line-height: 1.08; letter-spacing: -.004em; text-wrap: balance;
}
.problem .leaf-recto > p { margin: 12px 0 0; font-size: 15px; line-height: 1.62; color: var(--ink-soft); }

/* ---------------------------------------------------------- the figure caption, flattened */
.problem .figure-heading {
  display: flex; flex-direction: row; align-items: baseline; gap: 12px;
  border-top: 1px solid var(--rule-soft); border-bottom: 0; padding: 9px 0 0; margin: 0 0 14px;
}
.problem .figure-heading span {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-faint); flex: none; white-space: nowrap; opacity: 1;
  transform: none; border: 0; outline: 0; background: none; padding: 0; margin: 0;
}
.problem .problem-figure--fox .figure-heading span { color: var(--v3); }
.problem .figure-heading b {
  flex: 1; font-family: var(--body); font-style: italic; font-weight: 400;
  font-size: 13.5px; line-height: 1.4; color: var(--ink-soft); letter-spacing: 0; text-wrap: balance;
}

/* ---------------------------------------------------------- the caesura, after leaf 03 */
.problem .problem-caesura {
  list-style: none; display: flex; flex-direction: column; align-items: center; padding: 88px 0;
}
.problem .problem-caesura::before {
  content: ""; display: block; width: 60px; height: 1px; background: var(--rule); margin-bottom: 30px;
}
.problem .problem-caesura p {
  max-width: 46ch; text-align: center;
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: 24px; line-height: 1.4; color: var(--ink);
}

/* ---------------------------------------------------------- what it stands on
   The foundation closes the chapter, so it must not close it in boxes. The proofs are one
   quiet mono run on the sheet's own middot — the same separator the drawings use in their
   title strips — set from the statement's first baseline. No rules, no chips, no gaps. */
.problem .problem-foundation {
  margin-top: 64px; padding-top: 24px;
  border-top: 1px solid color-mix(in srgb, var(--ink) 70%, transparent);
  display: grid; grid-template-columns: 1fr 1.25fr; gap: 32px 56px; align-items: baseline;
}
.problem .problem-foundation p { max-width: 44ch; text-wrap: balance; }
.problem .problem-proof {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-start;
  column-gap: 0; row-gap: 11px;
}
.problem .problem-proof span {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink-faint); padding: 0; border: 0; background: none; box-shadow: none;
  white-space: nowrap;
}
.problem .problem-proof span:not(:last-child)::after {
  content: "·"; color: var(--rule); margin: 0 .95em 0 .8em; letter-spacing: 0;
}

/* ---------------------------------------------------------- motion: one beat, the fold drawing
   The leaf arrives and the fold draws downward — the page literally performing
   "now becomes with-Foxora". The twelve figures keep their own build untouched. */
.problem .leaf-fold {
  transform: scaleY(0); transform-origin: 50% 0;
  transition: transform .75s cubic-bezier(.22,1,.36,1) .06s;
}
.problem .problem-scene.rv.on .leaf-fold { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .problem .leaf-fold { transform: none !important; transition: none !important; }
}

/* ---------------------------------------------------------- responsive */
/* the folio needs its 104px of margin, clear of the page's own frame rule at 30px */
@media (max-width: 1420px) { .problem .problem-folio { display: none; } }

/* the plate stops breaking out once the breakout is smaller than the gutter */
@media (max-width: 1200px) {
  .problem .leaf-plates { width: 100%; margin-inline: 0; }
  .problem .problem-scene--wash::before { left: 0; width: 100%; }
}

/* one column: the fold turns horizontal and the plates fall in beside their own half */
@media (max-width: 1080px) {
  .problem .problem-overview { grid-template-columns: 1fr; row-gap: 0; }
  .problem .problem-overview .chapter { margin-bottom: 12px; }
  .problem .problem-overview h2 { grid-column: 1; grid-row: 2; padding-right: 0; }
  .problem .problem-overview .fold-hd { display: none; }
  .problem .problem-overview .lede { grid-column: 1; grid-row: 3; padding-right: 0; max-width: 62ch; }
  /* the numeral needs no rule here: the page already retires it below 1100, which is
     exactly where the header loses the empty column that was holding it */

  /* the leaf collapses to one column and the two halves interleave with their own plates:
     problem → its drawing → the fold, laid down flat → the answer → its drawing */
  .problem .problem-scene { display: grid; grid-template-columns: 100%; row-gap: 34px; padding: 44px 0 48px; }
  .problem .leaf-words, .problem .leaf-plates { display: contents; }
  .problem .leaf-verso, .problem .leaf-recto { display: block; }
  .problem .problem-figure { display: block; }
  .problem .leaf-verso, .problem .leaf-recto, .problem .problem-figure { grid-column: 1; grid-row: auto; }
  .problem .problem-scene__category, .problem .leaf-recto > span,
  .problem .problem-scene h3, .problem .leaf-recto > b,
  .problem .problem-scene__subtitle,
  .problem .problem-scene__body, .problem .leaf-recto > p { grid-row: auto; }
  .problem .leaf-verso { order: 1; padding-right: 0; }
  .problem .leaf-fold { display: none; }
  .problem .problem-figure--now { order: 2; }
  .problem .leaf-recto { order: 3; padding-left: 0; border-top: 1px solid var(--rule); padding-top: 11px; }
  .problem .problem-figure--fox { order: 4; }
  /* stacked, each plate already sits under its own side's kicker — the caption's
     own "Current systems / With foxora" would only stutter it */
  .problem .figure-heading span { display: none; }
  /* the drawings are drawn for a 580px sheet; let them fill a 1000px column and their
     own mono labels grow larger than the page's, which inverts the whole hierarchy */
  .problem .problem-figure .figure-heading, .problem .problem-figure .bp { max-width: 620px; }

  .problem .problem-caesura { padding: 56px 0; }
  .problem .problem-caesura p { font-size: 22px; }
  .problem .problem-foundation { grid-template-columns: 1fr; }
  .problem .problem-foundation p { max-width: 56ch; }
  .problem .problem-proof { justify-content: flex-start; }
}

@media (max-width: 640px) {
  .problem .problem-scene h3 { font-size: 26px; }
  .problem .leaf-recto > b { font-size: 22px; }
  .problem .problem-scene__subtitle { font-size: 15.5px; }
  .problem .figure-heading b { font-size: 13px; }
  .problem .problem-caesura p { font-size: 20px; }
  /* the title strip stays: at this size it is texture rather than text, and hiding it
     only leaves the sheet with an empty band where its foot should be */
  /* one term per line at this width anyway, so the middots would only hang off every
     line end — stack them instead and let the separator go */
  .problem .problem-proof { flex-direction: column; row-gap: 9px; }
  .problem .problem-proof span { white-space: normal; }
  .problem .problem-proof span:not(:last-child)::after { content: none; }
}

/* ---------------------------------------------- [pillars] */
/* ===================================================================
   01b · pillars — ruled ledger: the bill of materials.
   Four ruled lines, four display verbs, no boxes. The page's
   typographic breather between twelve drawings above and the
   folded sheet below. Replaces .pillar-row / .pillar entirely.
   =================================================================== */

.pillars { background: transparent; border-bottom: 1px solid var(--rule); }
.pillars .wrap { padding: 88px 44px 92px; }

/* --- shared drafting device (integrator: this is the page-wide .leader
       block, prefixed only so the fragment previews standalone. Drop it
       in favour of the shared copy and keep the .pillars .ln .leader
       overrides below.) */
.pillars .leader {
  flex: 1; min-width: 24px; align-self: center; height: 1px; margin: 0 14px;
  background: radial-gradient(circle, var(--ink-faint) .8px, transparent 1px) 0 50%/6px 1px repeat-x;
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .6s cubic-bezier(.22,1,.36,1) var(--d, 0s);
}
.pillars .rv.on .leader, .pillars .leader.on { transform: none; }

/* --- the title rule: head sits above it, the ledger hangs below it */
.pillars .bom {
  margin-top: 40px;
  border-top: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent);
}

/* --- one ruled line. Columns are word-driven, never equal cells. */
.pillars .ln {
  display: grid;
  grid-template-columns: 56px max-content 1fr 300px;
  align-items: baseline;
  padding: 34px 0 30px;
  border-bottom: 1px solid var(--rule-soft);
}
.pillars .ln:last-child {
  border-bottom: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent);
}

/* the one hand-tuned number: the numeral's cap sits on the verb's cap.
   Measured on the sheet — the verb's cap top is .088em below its own box top,
   the mono numeral's cap top is 1.2px below its content box. Scales with the
   verb so it holds at 68px (1600/1440) and at 5vw below that. */
.pillars .ln .p-n {
  grid-area: 1 / 1 / 2 / 2;
  align-self: start; margin: 0;
  padding-top: calc(clamp(44px, 5vw, 68px) * .088 - 1.2px);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em;
  line-height: 1; color: var(--v3);
  transition: color .35s ease;
}
.pillars .ln h3 {
  grid-area: 1 / 2 / 2 / 3;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(44px, 5vw, 68px); line-height: .95; letter-spacing: -.01em;
  color: var(--ink); padding-right: 24px; margin: 0;
  transition: transform .5s cubic-bezier(.22,1,.36,1);
}
.pillars .ln .leader {
  grid-area: 1 / 3 / 2 / 4;
  min-width: 80px; margin: 0 24px 0 0; align-self: baseline;
}
.pillars .ln p {
  grid-area: 1 / 4 / 2 / 5;
  width: 300px; font-size: 15.5px; line-height: 1.55; color: var(--ink-soft);
  transition: color .35s ease;
}
.pillars .ln .spec {
  grid-area: 2 / 4 / 3 / 5;
  display: block; margin-top: 10px; line-height: 1.5;
  font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-faint);
  text-wrap: balance;
}

/* --- hover: the ledger shifts, it never lifts */
.pillars .ln:hover h3 { transform: translateX(8px); }
.pillars .ln:hover .p-n { color: var(--v1); }
.pillars .ln:hover p { color: var(--ink); }

/* --- carried forward: the one stamp, on the clear zone under the foot rule */
.pillars .bom-carry { text-align: right; }
.pillars .bom-carry .stamp-el {
  margin-top: 26px; color: var(--v3);
  font-size: 10.5px; padding: 7px 13px;
}
.pillars .bom-carry .stamp-el b { font-size: 12.5px; letter-spacing: .22em; }
.pillars .bom-carry .stamp-el span { font-size: 8.5px; letter-spacing: .16em; }

/* --- responsive: the ledger folds to numeral + stack, leader retires */
@media (max-width: 900px) {
  .pillars .wrap { padding: 72px 44px 76px; }
  .pillars .ln { grid-template-columns: 44px 1fr; row-gap: 12px; padding: 30px 0 26px; }
  .pillars .ln .p-n { grid-area: 1 / 1 / 2 / 2; padding-top: calc(clamp(40px, 9vw, 52px) * .088 - 1.2px); }
  .pillars .ln h3 { grid-area: 1 / 2 / 2 / 3; font-size: clamp(40px, 9vw, 52px); padding-right: 0; }
  .pillars .ln .leader { display: none; }
  .pillars .ln p { grid-area: 2 / 2 / 3 / 3; width: auto; }
  .pillars .ln .spec { grid-area: 3 / 2 / 4 / 3; width: auto; margin-top: 0; }
  .pillars .bom-carry { text-align: left; }
  .pillars .bom-carry .stamp-el { position: static; }
}

@media (prefers-reduced-motion: reduce) {
  .pillars .leader { transform: none !important; transition: none !important; }
  .pillars .ln h3, .pillars .ln .p-n, .pillars .ln p { transition: none !important; }
}

/* ---------------------------------------------- [how] */
/* ==========================================================================
   [03] Using it — one job sheet at three moments, hung off a centre fold.
   Every selector is scoped to .how. Tokens + color-mix only, no hex.
   ========================================================================== */

  /* clip, not hidden: `overflow: hidden` makes the section a scroll container, which
     freezes every `animation-timeline: view()` inside it (the fold draw, and the page's
     own .ghost-n parallax). `overflow: clip` clips identically without that side effect,
     and falls back to the inherited `hidden` on engines that don't know it. */
  .how { overflow: clip; }
  .how .wrap { padding-top: 92px; padding-bottom: 88px; }
  .how .lede { max-width: 46ch; }

  /* ---------- shared drafting devices (page-level block; scoped copy so the
     fragment previews standalone — integrator may drop these three once the
     shared block lands in site.css) */
  .how .whisper { font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em;
    text-transform: uppercase; color: var(--ink-faint); }
  .how .leader { flex: 1; min-width: 24px; align-self: center; height: 1px; margin: 0 14px;
    background: radial-gradient(circle, var(--ink-faint) .8px, transparent 1px) 0 50%/6px 1px repeat-x;
    transform: scaleX(0); transform-origin: 0 50%;
    transition: transform .6s cubic-bezier(.22,1,.36,1) var(--d, 0s); }
  .how .rv.on .leader, .how .leader.on { transform: none; }
  .how .dogear { position: absolute; right: -1px; top: -1px; width: 26px; height: 26px; z-index: 1;
    background: linear-gradient(225deg, var(--paper) 0 50%, transparent 50%); }
  .how .dogear::after { content: ""; position: absolute; inset: 0; background:
    linear-gradient(225deg, transparent calc(50% - .5px), var(--rule) calc(50% - .5px) calc(50% + .5px), transparent calc(50% + .5px)); }

  /* ---------- the title line, centred on the fold's axis */
  .how .deed-head { margin-top: 48px; text-align: center; }
  .how .deed-kicker { font-family: var(--mono); font-size: 10px; letter-spacing: .32em;
    text-transform: uppercase; color: var(--v3); max-width: 46ch; margin: 0 auto 12px; }
  .how .deed-title { font-family: var(--display); font-style: italic; font-weight: 400;
    font-size: 17px; line-height: 1.38; color: var(--ink-soft); max-width: 46ch; margin: 0 auto 40px; }

  /* ---------- the fold: a plain dashed rule with a crosshair at its head */
  .how .zz { position: relative; padding-bottom: 140px; }
  .how .zz::before { content: ""; position: absolute; left: 50%; margin-left: -.5px; top: 0; bottom: 0; width: 1px;
    background: repeating-linear-gradient(180deg, var(--rule) 0 6px, transparent 6px 11px);
    transform-origin: 50% 0; }
  .how .zz::after { content: "+"; position: absolute; left: 50%; top: -9px; transform: translateX(-50%);
    font-family: var(--mono); font-size: 13px; line-height: 1; color: var(--rule); }

  /* ---------- the three beats */
  .how .beat { position: relative; display: grid; grid-template-columns: 1fr 1fr;
    column-gap: 96px; padding: 48px 0; align-items: start; }
  .how .beat > * { grid-row: 1; }
  .how .beat > .bt-prose { grid-column: 1; justify-self: end; }
  .how .beat > .sheet { grid-column: 2; justify-self: start; }
  .how .beat.b2 > .bt-prose { grid-column: 2; justify-self: start; }
  .how .beat.b2 > .sheet { grid-column: 1; justify-self: end; }

  /* the balloon rides the fold at each beat's head */
  .how .beat::before { content: attr(data-no); position: absolute; left: 50%; top: 38px;
    transform: translateX(-50%); width: 22px; height: 22px; border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--ink) 70%, transparent); background: var(--paper-hi);
    font-family: var(--mono); font-size: 10px; display: grid; place-items: center;
    color: var(--ink-soft); opacity: 0; transition: opacity .45s ease .2s; z-index: 1; }
  .how .beat.on::before { opacity: 1; }

  /* ---------- prose: always left-aligned, whichever side it sits on */
  .how .bt-prose { width: 100%; max-width: 372px; text-align: left; }
  .how .bt-prose .a-no { display: block; font-family: var(--mono); font-size: 10px;
    letter-spacing: .24em; text-transform: uppercase; color: var(--v3);
    border: 0; padding: 0; text-align: left; margin-bottom: 12px; }
  .how .bt-prose b { display: block; font-family: var(--display); font-weight: 700;
    font-size: 26px; line-height: 1.1; letter-spacing: -.004em; margin-bottom: 10px; }
  .how .bt-prose p { font-size: 16px; line-height: 1.6; color: var(--ink-soft); max-width: 44ch; }

  /* ---------- the mission sheet, seen three times */
  .how .sheet { width: 460px; background: var(--paper-hi); position: relative;
    border: 1px solid color-mix(in srgb, var(--ink) 70%, transparent);
    padding: 20px 22px; font-family: var(--mono); font-size: 12px; color: var(--ink);
    box-shadow: var(--shadow-card);
    transition: opacity .7s ease var(--d, 0s),
                transform .7s cubic-bezier(.22,1,.36,1) var(--d, 0s),
                box-shadow .35s ease; }
  .how .sheet.on { transition: opacity .7s ease,
                transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s ease; }
  .how .sheet:hover { transform: translateY(-2px); box-shadow: var(--shadow-obj); }
  .how .sheet .sh-h { display: block; margin-bottom: 13px; }
  .how .sheet .sh-rule { display: block; height: 1px; background: var(--rule-soft); margin: 14px 0; }

  /* rows inside the sheet reveal on a shorter throw than the page default */
  .how .sheet .rv { transform: translateY(9px); }
  .how .sheet .rv.on { transform: none; }

  /* the intent line — the one row every moment carries */
  .how .sheet .a-art { display: flex; align-items: flex-start; gap: 9px; margin: 0;
    border: 0; background: none; padding: 0;
    font-family: var(--mono); font-size: 12px; line-height: 1.58; color: var(--ink); }
  .how .sheet .a-art .car { display: inline-block; width: 6px; height: 11px; flex: none;
    margin-top: 4px; background: var(--v3); animation: none; }
  .how .beat.b1 .sheet .a-art .car { animation: blink 1.1s steps(1) infinite; }
  .how .sheet .a-line { flex: 1; }

  /* moment II — the state row */
  .how .sheet .a-chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .how .sheet .a-chips span { font-family: var(--mono); font-size: 10px; letter-spacing: .06em;
    padding: 4px 9px; border: 1px solid var(--rule-soft); color: var(--v3); }
  .how .sheet .a-chips .wait { color: var(--ink); border: 1px solid var(--ink); }

  /* moment III — the settled rows */
  .how .sheet .a-receipt { display: grid; gap: 7px; }
  .how .sheet .a-receipt .r { display: flex; align-items: baseline; width: 100%; }
  .how .sheet .a-receipt .k { color: var(--ink-soft); }
  .how .sheet .a-receipt .val { color: var(--ink); white-space: nowrap; }
  .how .sheet .a-receipt .val i { font-style: normal; color: var(--v3); }

  /* ---------- the close: two signatures either side of the fold */
  .how .sig-row { display: grid; grid-template-columns: 1fr 1fr; column-gap: 96px; margin-top: 44px; }
  .how .sig-row .sig { width: 100%; max-width: 44ch; }
  .how .sig-row .sig:first-child { justify-self: end; }
  .how .sig-row .sig:last-child { justify-self: start; }

  /* the seal terminates the rule */
  .how .zz .seal { position: absolute; left: 50%; margin-left: -66px; bottom: 0; justify-self: auto; }

  /* ---------- motion: the fold draws downward, just ahead of the reader */
  @supports (animation-timeline: view()) {
    .how .zz::before { animation: how-fold-draw linear both; animation-timeline: view();
      animation-range: entry 0% cover 45%; }
    @keyframes how-fold-draw { from { transform: scaleY(0); } to { transform: scaleY(1); } }
  }
  @media (prefers-reduced-motion: reduce) {
    .how .zz::before { animation: none !important; transform: none; }
    .how .leader { transform: none !important; transition: none !important; }
    .how .sheet .car { animation: none !important; }
  }

  /* ---------- responsive */
  @media (max-width: 1300px) {
    .how .sheet { width: 440px; }
  }
  @media (max-width: 1080px) {
    .how .zz { padding-bottom: 0; }
    .how .zz::before, .how .zz::after { left: 14px; }
    .how .beat { grid-template-columns: 1fr; padding: 40px 0 40px 44px; row-gap: 22px; }
    /* every one of these must match the desktop placement rules' specificity or beat it,
       or the sheet keeps grid-column: 2 and spills out of a one-column grid */
    .how .beat > .bt-prose, .how .beat > .sheet,
    .how .beat.b2 > .bt-prose, .how .beat.b2 > .sheet {
      grid-column: 1; grid-row: auto; justify-self: start; }
    .how .beat::before { left: 14px; top: 34px; }
    .how .bt-prose { max-width: 46ch; }
    .how .sheet { width: 100%; max-width: 460px; }
    .how .sig-row { grid-template-columns: 1fr; row-gap: 34px; padding-left: 44px; }
    .how .sig-row .sig, .how .sig-row .sig:first-child, .how .sig-row .sig:last-child {
      justify-self: start; max-width: 46ch; }
    .how .zz .seal { position: static; width: 92px; height: 92px; margin: 34px 0 0 -32px; }
  }
  @media (max-width: 640px) {
    .how .deed-head { margin-top: 40px; }
    .how .sheet { padding: 16px; }
    .how .sheet .a-line { white-space: normal; }
    .how .beat { padding: 34px 0 34px 34px; }
    .how .beat::before { left: 11px; }
    .how .zz::before, .how .zz::after { left: 11px; }
    .how .sig-row { padding-left: 34px; }
    .how .zz .seal { margin-left: -35px; }
  }

/* ---------------------------------------------- [spine] */
/* ================================================ 04 · under the hood — THE SIDENOTE SHEET
   The tape stays the only object. Everything under it is type: one measure with hanging
   folios, and the engineering exiled to a true sidenote margin on the head's own armature.
   overflow MUST stay visible (a hidden ancestor kills the sticky tape); therefore nothing
   in here may use negative-margin full-bleed. */

/* the strap is the tape's own title; at 14px it was falling into the tape's top rule —
   the only gap on the sheet under 24px. 24 keeps it a caption, not a collision. */
.spine .sp-head { padding-bottom: 24px; }

.spine .sp-body { padding: 76px 44px 96px; }

/* ------------------------------------------------------- the tape, corrected
   Three faults, one cause: the strip was built as six loose captions rather than
   one perforated register. (a) unprinted at .12 the whole object was illegible on
   arrival — a 112px grey smear at 1600, a near-blank screen at 390; (b) the block
   sat 16px under the top tear and 42px above the bottom one, so the band read
   bottom-heavy; (c) cell 03 wraps to two lines and nothing else did, so the strip
   had a ragged foot. Every cell now reserves the same two lines and the block is
   centred between the tears, so the six cells are one measured register. */
.spine .sp-line { opacity: .32; }
@media (min-width: 1081px) {
  .spine .sp-line { padding-top: 28px; }
  .spine .sp-line .d { min-height: 30px; }   /* 2 × (10.5px × 1.4) — one reserved measure */
  /* the tear lines must read as uninterrupted; the cell divider and the printhead
     both stop short of them instead of crossing */
  .spine .sp-line { border-left: 0; position: relative; }
  .spine .sp-line + .sp-line::before {
    content: ""; position: absolute; left: 0; top: 8px; bottom: 8px;
    width: 1px; background: var(--rule);
  }
  .spine .printhead > i { top: 8px; bottom: 8px; }
  .spine .printhead > i::before { top: -5px; }   /* nib meets its line, no 1px float */
}

/* ------------------------------------------------------- the measure */
.spine .sp-stages { display: block; margin-top: 0; }

/* identical armature to .sp-head: 7fr / 5fr, 64px gutter.
   At 1112px of content that is a 611px measure and a 437px note margin,
   and the note starts exactly where the lede starts. */
.spine .sp-stage {
  display: grid; grid-template-columns: minmax(0, 7fr) 5fr;
  column-gap: 64px; row-gap: 0;
  align-items: start;
  position: static; margin: 0; padding: 0 0 38px;
  border: 0; background: none;
}
.spine .sp-stage:first-child { border-top: 0; }
.spine .sp-stage::before { content: none; display: none; }

/* column 1 — the prose. The folio hangs out of flow, so all six paragraphs
   share ONE straight left edge; the hairline rules only the prose. */
.spine .sp-say {
  position: relative;
  padding-left: 74px; padding-top: 28px;
  border-top: 1px solid var(--rule-soft);
}
/* the hanging folio shares the heading's BASELINE, not its cap-line: at 34px against
   a 26px Didot, cap-aligning left the two 8px apart and the folio read as dropped. */
.spine .sp-stage .n {
  position: absolute; left: 0; top: 22px; width: auto; padding-top: 0;
  font-family: var(--display); font-weight: 400; font-size: 34px; line-height: 1;
  color: var(--ink-faint); transition: color .5s ease;
}
.spine .sp-stage h3 {
  font-family: var(--display); font-weight: 400; font-size: 26px; line-height: 1.15;
  color: var(--ink); text-indent: 0; margin: 0 0 10px;
}
.spine .sp-stage .plain {
  font-family: var(--body); font-size: 17.5px; line-height: 1.62;
  color: var(--ink); max-width: 46ch; margin: 0; text-wrap: pretty;
}

/* column 2 — the sidenote margin: subordinate, never grey filler in the measure */
/* the tick is a REGISTRATION mark: it lands exactly on the prose's hairline and
   carries it 14px into the margin. Floating 28px below the rule, it read as a
   stray dash. The note's first baseline then sits on the heading's baseline. */
.spine .sp-stage .tech {
  position: relative;
  padding-top: 36px; max-width: 320px; margin: 0;
  font-family: var(--body); font-size: 13px; line-height: 1.6;
  color: var(--ink-faint); overflow-wrap: anywhere;
}
.spine .sp-stage .tech::before {
  content: ""; position: absolute; top: 0; left: 0; width: 14px; height: 1px;
  background: var(--v3); opacity: .45; margin: 0;
  transition: opacity .5s ease;
}
.spine .sp-stage code {
  font-family: var(--mono); font-size: 11px; color: var(--v3);
  border-bottom: 1px dotted var(--v3); padding-bottom: 1px; overflow-wrap: anywhere;
}

/* ---------------------------------------------------------- the close */
/* the colophon takes the same armature; the seal lands in the note margin,
   at the end of the reading, at the moment it becomes true */
.spine .sp-foot {
  display: grid; grid-template-columns: minmax(0, 7fr) 5fr;
  gap: 0 64px; align-items: start; justify-content: initial;
  padding-top: 0;
}
.spine .sp-foot .rc-row {
  grid-row: 1; grid-column: 1; width: auto; flex: none;
  border-top: 1px solid var(--rule); padding-top: 22px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
}
.spine .sp-foot .rc-row .k { color: var(--ink-faint); text-transform: uppercase; letter-spacing: .18em; }
.spine .sp-foot .rc-row .val { color: var(--ink); }
/* the seal hangs from the status line's own rule and centres on the word it certifies —
   at 26px it floated 23px low and read as unattached to anything */
.spine .sp-foot .stamp-el.settled2 {
  grid-row: 1; grid-column: 2; justify-self: start; align-self: start;
  position: static; margin-top: 6px; color: var(--v4-ink); --rot: -7deg; flex: none;
}
/* softened seal — un-setting must be a fade, not a lurch */
.spine .sp-foot .stamp-el.settled2 { transform: scale(1.25) rotate(var(--rot, -7deg)); filter: none; }
.spine .sp-foot .stamp-el.settled2.on { transform: scale(1) rotate(var(--rot, -7deg)); }

.spine .sp-dim { max-width: none; margin: 52px 0 0; }

/* ---------------------------------------- tracked state (not animation)
   it moves only when the reader moves, and it walks back down on reverse scroll */
.spine .sp-stage.live .n { color: var(--v3); }
.spine .sp-stage.live .tech::before { opacity: 1; }

/* ------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .spine .sp-body { padding-bottom: 76px; }
  /* the tape is static here; the note tucks under the prose on the same edge
     and its 14px hair becomes the register divider */
  .spine .sp-stage { grid-template-columns: 1fr; }
  .spine .sp-stage .tech { padding-top: 0; margin-top: 14px; padding-left: 74px; max-width: 46ch; }
  /* one column: the hair goes back into flow as the register divider it is here */
  .spine .sp-stage .tech::before { position: static; margin-bottom: 13px; }
  /* the stamp first, the colophon under it. 24px put the seal's rotated corner 7px
     off the status rule — the seal needs its own air to read as a seal. */
  .spine .sp-foot { grid-template-columns: 1fr; row-gap: 44px; }
  .spine .sp-foot .stamp-el.settled2 { grid-row: 1; grid-column: 1; margin-top: 0; }
  .spine .sp-foot .rc-row { grid-row: 2; grid-column: 1; width: auto; }
}
@media (max-width: 700px) {
  .spine .sp-say { padding-left: 54px; padding-top: 24px; }
  .spine .sp-stage .n { font-size: 28px; top: 20px; }   /* same shared baseline, 28 vs 22 */
  .spine .sp-stage h3 { font-size: 22px; }
  .spine .sp-stage .plain { font-size: 16.5px; }
  .spine .sp-stage .tech { padding-left: 54px; }
  .spine .sp-stage { padding-bottom: 32px; }
  .spine .sp-foot .rc-row { width: auto; }
  .spine .sp-foot .stamp-el.settled2.thunk.on { transform: scale(.85) rotate(var(--rot, -7deg)); }
}
@media (max-width: 470px) {
  /* The nav's right-hand furniture used to be the reason this gutter was 18px: the
     seats chip and the repository button would not compress, and the sheet gave up
     its margins rather than push the header off the screen. The nav pays its own way
     now — the chip stands down below 640 and the links have their own second line —
     so the page gets its margins back. 26px is what a phone can actually spare. */
  .wrap { padding: 0 26px; }
  .spine .sp-stage .n { position: static; display: block; font-size: 26px; margin-bottom: 4px; }
  .spine .sp-say, .spine .sp-stage .tech { padding-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .spine .sp-stage .n, .spine .sp-stage .tech::before { transition: none; }
}

/* ---------------------------------------------- [l5] */
/* ================================================== [05] l5 — the licence, opened
   archetype: two-page-spread. One bound object; the thesis is folded in as the
   holder's declaration on the data page, the levels are endorsements on the facing page. */

  .l5 .wrap { padding: 92px 44px 90px; }
  .l5 h2 { max-width: 18ch; }
  .l5 .lede { max-width: 58ch; }

  /* the holder carries the reveal (transform: scale) so the booklet's own
     transform stays free for the scroll-linked drift, and `translate` stays
     free for the hover lift — three effects, no cascade fight. */
  .l5 .bk-hold { margin-top: 56px; }

  .l5 .booklet {
    width: min(1040px, 100%); margin: 0 auto; position: relative;
    display: grid; grid-template-columns: 1fr 1fr;
    background: var(--paper-hi);
    border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
    border-radius: 10px; box-shadow: var(--shadow-obj); overflow: hidden;
    transition: translate .35s cubic-bezier(.22,1,.36,1), box-shadow .35s ease;
  }
  .l5 .booklet:hover {
    translate: 0 -4px;
    box-shadow: 0 26px 50px -30px color-mix(in srgb, var(--deep) 55%, transparent);
  }
  /* guilloche */
  .l5 .booklet::before {
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
    background: repeating-radial-gradient(circle at 92% -20%, color-mix(in srgb, var(--v1) 5%, transparent) 0 1px, transparent 1px 9px);
    -webkit-mask-image: radial-gradient(62% 130% at 99% -8%, var(--ink), transparent 66%);
            mask-image: radial-gradient(62% 130% at 99% -8%, var(--ink), transparent 66%);
  }
  /* the gutter the two pages fold across */
  .l5 .booklet .fold {
    position: absolute; left: calc(50% - 28px); width: 56px; top: 0; bottom: 0;
    pointer-events: none; z-index: 3;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink) 5%, transparent) 50%, transparent);
  }
  .l5 .booklet .fold::after {
    content: ""; position: absolute; left: 28px; top: 0; bottom: 0; width: 1px; background: var(--rule);
  }
  .l5 .bk-alt { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

  /* ---------------------------------------------- left page · identity + declaration */
  .l5 .pg-id {
    position: relative; min-width: 0; z-index: 1;
    padding: 30px 36px 0;
    display: grid; grid-template-rows: auto 1fr auto;
  }
  .l5 .lic-head {
    display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
    background: none; border: 0; border-bottom: 1px solid var(--rule);
    padding: 0 0 18px;
  }
  .l5 .lic-brand { display: flex; align-items: center; gap: 13px; }
  .l5 .lic-brand svg { width: 34px; height: 34px; flex: none; }
  .l5 .lic-brand b { display: block; font-family: var(--display); font-weight: 700; font-size: 21px; line-height: 1.1; }
  .l5 .lic-brand span {
    display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--ink-faint); margin-top: 4px;
  }
  .l5 .lic-no {
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
    color: var(--deep); text-align: right; white-space: nowrap; padding-top: 9px;
  }

  /* the thesis, de-carded: it is the holder's declaration, not a note beside the object */
  .l5 .l5-note {
    align-self: start; max-width: 34ch; margin-top: 22px;
    background: none; border: 0; padding: 0; box-shadow: none;
    font-family: var(--body); font-size: 14.5px; line-height: 1.6; color: var(--ink-soft);
    transition: none;
  }
  .l5 .l5-note:hover { transform: none; box-shadow: none; }
  .l5 .l5-note b {
    display: block; font-family: var(--display); font-weight: 700;
    font-size: 20px; line-height: 1.25; color: var(--ink); margin-bottom: 10px;
    text-wrap: balance;
  }

  /* the section's one stamp — data page only, in the clear band the right page's height creates */
  .l5 .lic-stamp { position: absolute; left: 36px; bottom: 92px; right: auto; top: auto; color: var(--v1); --rot: -7deg; }
  .l5 .lic-stamp b { font-size: 12.5px; letter-spacing: .16em; }
  .l5 .lic-stamp span { font-size: 8px; letter-spacing: .16em; }

  /* the page's bottom strip */
  .l5 .lic-mrz {
    background: color-mix(in srgb, var(--paper-hi) 70%, transparent);
    border-top: 1px solid var(--rule); border-bottom: 0;
    margin: 0 -36px; padding: 10px 36px;
    font-family: var(--mono); font-size: 12px; letter-spacing: 2.2px; color: var(--ink);
    white-space: nowrap; overflow: hidden; position: relative;
  }

  /* --------------------------------------------- right page · the endorsements */
  .l5 .pg-end { position: relative; min-width: 0; z-index: 1; padding: 26px 36px; }
  .l5 .l5-fine { font-size: 13.5px; font-style: italic; line-height: 1.55; color: var(--ink-faint); }

  .l5 .endorsements { list-style: none; margin: 0; padding: 10px 0 0; position: relative; }
  .l5 .endorsements li {
    display: grid; grid-template-columns: 30px 1fr auto;
    grid-template-areas: "lv name mark" "lv desc mark";
    column-gap: 14px; row-gap: 3px; align-items: initial;
    padding: 12px 0;
    border-bottom: 1px dotted color-mix(in srgb, var(--deep) 35%, transparent);
  }
  .l5 .e-lv {
    grid-area: lv; align-self: start; padding-top: 4px;
    font-family: var(--mono); font-size: 11px; letter-spacing: .04em; color: var(--v3);
  }
  .l5 .e-name { grid-area: name; font-family: var(--display); font-weight: 700; font-size: 19px; line-height: 1.2; }
  .l5 .e-desc { grid-area: desc; font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
  .l5 .e-mark {
    grid-area: mark; align-self: center; justify-self: end;
    font-family: var(--mono); font-size: 11px; color: var(--v3);
  }
  .l5 .e-flag {
    font-family: var(--mono); font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
    color: var(--v5); background: none;
    border: 1px solid color-mix(in srgb, var(--v5) 45%, transparent); padding: 3px 8px;
  }
  .l5 .e-cond {
    font-family: var(--mono); font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
    color: var(--v1); background: none;
    border: 1px solid color-mix(in srgb, var(--v1) 45%, transparent); padding: 3px 8px;
  }
  /* the fifth is the only tinted row */
  .l5 .endorsements li.top {
    background: color-mix(in srgb, var(--v1) 6%, transparent);
    margin: 0 -36px; padding: 12px 36px; border-bottom: none;
  }
  .l5 .endorsements li.top .e-name { color: var(--v1); }

  .l5 .lic-cond {
    display: grid; grid-template-columns: 110px 1fr; gap: 16px; align-items: start;
    border-top: 1px solid var(--rule); padding: 14px 0 0; margin-top: 2px; position: relative;
  }
  .l5 .lic-label {
    font-family: var(--mono); font-size: 9px; letter-spacing: .24em; text-transform: uppercase;
    color: var(--ink-faint); padding-top: 3px;
  }
  .l5 .lic-cond p { font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
  .l5 .lic-cond p b { color: var(--ink); font-weight: 700; }

  /* ------------------------------------------------------------- motion */
  /* integrator: add `.booklet` to the shared par-soft selector (site.css ~608).
     It must sit on .booklet (transform) — the reveal lives on .bk-hold and the
     hover lift uses `translate`, so all three compose. */
  @supports (animation-timeline: view()) {
    .l5 .booklet { animation: par-soft linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
  }
  @media (prefers-reduced-motion: reduce) {
    .l5 .booklet { animation: none !important; transition: none !important; }
  }

  /* --------------------------------------------------------- responsive */
  @media (max-width: 900px) {
    .l5 .booklet { grid-template-columns: 1fr; }
    .l5 .booklet .fold { display: none; }
    .l5 .pg-end { border-top: 1px solid var(--rule); }
    .l5 .pg-id { grid-template-rows: auto auto auto auto; }
    .l5 .lic-stamp {
      position: static; justify-self: start; margin: 18px 0 26px; --rot: -4deg;
      display: inline-block;
    }
    .l5 .endorsements li { grid-template-columns: 30px 1fr; grid-template-areas: "lv name" "lv desc" "lv mark"; }
    .l5 .e-mark { justify-self: start; align-self: start; margin-top: 5px; }
    .l5 .lic-cond { grid-template-columns: 1fr; gap: 6px; }
  }
  @media (max-width: 620px) {
    .l5 .wrap { padding: 76px 24px 74px; }
    .l5 .pg-id { padding: 26px 22px 0; }
    .l5 .pg-end { padding: 22px; }
    .l5 .lic-mrz { margin: 0 -22px; padding: 10px 22px; font-size: 11px; letter-spacing: 1.6px; }
    .l5 .endorsements li.top { margin: 0 -22px; padding: 12px 22px; }
    .l5 .lic-head { flex-wrap: wrap; gap: 10px 16px; }
  }

/* ---------------------------------------------- [install] */
/* ---------------------------------------------- [install] */
/* ============================================ 06 · install — THE TRANSCRIPT
   One left edge, top to bottom, and one right edge held by the labels. Nothing
   but ruled type: a running head, one command at 64px, three leader rows closed
   by a foot rule, the buttons in open paper, and an imprint strip.
   No columns, no gutter, no object, no panel, no tint. Between the licence
   booklet and eco's weight, this section is the page's breath.
   Motion: one soft build beat. Zero continuously-moving elements — the
   marquee's lap and the caret's blink are both gone. */

/* clip, not hidden: `overflow: hidden` makes the section a scroll container,
   which freezes the page-wide .ghost-n view-timeline inside it. Clips the same. */
.install { overflow: clip; }
.install .wrap { padding: 92px 44px 64px; display: block; position: relative; z-index: 1; }

/* the head sits on the same left edge as everything below it */
.install .chapter { margin-bottom: 26px; }
.install h2 { max-width: 24ch; margin-bottom: 16px; }
.install .lede { max-width: 54ch; }

/* ------------------------------------------------------- the transcript */
.install .cmd-band {
  position: relative; margin: 62px 0 0; padding: 0;
  text-align: left; border: 0;
  /* the band no longer parallaxes: it holds a fixed distance to the head above
     and the closing rule below, so the vertical rhythm survives a scroll.
     (kills the old @supports par-soft rule the integrator DELETES.) */
  animation: none;
}
/* the wiping top rule is retired — .strip is the horizon now */
.install .cmd-band::before { content: none; }

/* the running head: a shared .strip, so the command hangs from a real rule.
   size pinned here so the preview matches the integrated page (the old block
   set 9.5px/.22em on .band-l and the integrator deletes it). */
.install .band-labs { margin: 0; gap: 0; }
.install .band-l {
  position: static; background: none; padding: 0; white-space: nowrap;
  font-size: 10px; letter-spacing: .18em; line-height: 1.4;
}

/* ---------------------------------------------------------- the command */
.install .in {
  margin-top: 34px;
  font-family: var(--mono); font-weight: 400;
  font-size: clamp(30px, 4.6vw, 64px); line-height: 1; letter-spacing: -.02em;
  color: var(--ink);
}
.install .in i {
  font-style: normal; margin-right: .34em;
  color: color-mix(in srgb, var(--v3) 58%, transparent);
}
.install #tcar {
  display: inline-block; width: 3px; height: .62em; background: var(--v3);
  vertical-align: baseline; animation: blink 1.1s steps(1) infinite;
}
/* the boot finishes, so the caret stops. A boot that never ends is also untrue. */
.install .cmd-band.done #tcar { animation: none; opacity: 0; }

/* --------------------------------- the boot: three ruled rows, not columns
   (selectors carry the `.boot` step so they also out-rank the three-column
   grid this replaces while both are on the page in preview) */
.install .boot { display: block; border-top: 0; margin: 36px 0 0; text-align: left; }
/* the row rule is ink-toned, not accent-toned: a 13%-green hairline vanishes
   into the drafting grid, and then the transcript has no rows at all. */
.install .boot .stn {
  display: flex; align-items: baseline;
  border-top: 1px solid color-mix(in srgb, var(--ink) 13%, transparent); border-left: 0;
  padding: 16px 0;
}
.install .boot .stn .out { flex: 0 1 auto; margin: 0; min-height: 0; }
.install .boot .stn .leader { flex: 1 0 24px; }
.install .out {
  display: block;
  font-family: var(--mono); font-size: 13.5px; line-height: 1.6; color: var(--ink-soft);
  opacity: 0; transform: translateY(4px); transition: opacity .4s, transform .5s;
}
.install .out.show { opacity: 1; transform: none; }
.install .out i { font-style: normal; display: inline-block; margin-right: 9px; color: var(--ink-faint); }
.install .out.ok { color: var(--ink); overflow-wrap: anywhere; }
.install .out.ok i { color: var(--v3); }

/* ------------------------------------------------------------ the terminus
   the payoff is the last line of the boot, at the largest size in it, and it
   is drawn, not tiled — no tint, no rounded corner, no card in miniature */
.install .boot .stn:last-child .out.ok {
  font-size: 16px; width: auto;
  background: none; border-radius: 0; margin: 0; padding: 0;
}
.install .url { position: relative; }
.install .url::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: radial-gradient(circle, var(--v3) .8px, transparent 1px) 0 50%/4px 1px repeat-x;
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}
.install .out.ok.show .url::after { transform: none; }

/* --------------------------------------------------------- closing the sheet
   It sits flush under the last row, at the weight of the running head above, so
   the transcript is a closed table — head rule, three light row rules, foot rule.
   Held off the buttons, it only fenced 700px of empty paper. */
.install .rule-close {
  display: block; height: 1px; margin: 0;
  background: color-mix(in srgb, var(--ink) 30%, transparent);
}

/* the buttons read as a consequence of the transcript, on its left edge —
   in open paper now, not inside a box drawn by two rules */
.install .cta-row { justify-content: flex-start; gap: 18px; margin: 40px 0 0; }

/* ------------------------------------- the platform names, as an imprint
   (this replaces the marquee: same six names, same "runs on", no treadmill)
   It is the running head again, upside down — label on the left edge, dotted
   leader, the six names flush to the right edge the transcript already keeps.
   Without that the sheet loses its right margin below the closing rule. */
.install .plats {
  margin: 48px 0 0; padding-top: 10px; gap: 0;
  border-top-color: var(--rule);
  font-size: 10px; letter-spacing: .18em;
}
.install .plats i { font-style: normal; color: var(--v3); flex: 0 0 auto; }
.install .plats .r {
  flex: 0 1 auto; text-align: right;
  color: var(--ink-faint); word-spacing: .24em;
}

/* ------------------------------------------------------------------ the stamp
   takes the air beside the head; the ghost numeral is on the left */
.install .wrap > .stamp-el { position: absolute; right: 44px; top: 150px; color: var(--v3); }

/* ------------------------------------------------------------------- motion */
@media (prefers-reduced-motion: reduce) {
  .install #tcar { animation: none !important; opacity: 0 !important; }
  .install .out { opacity: 1 !important; transform: none !important; }
  .install .url::after { transform: none !important; transition: none !important; }
}

/* --------------------------------------------------------------- responsive
   The stamp keeps the head's right margin for as long as that margin is really
   clear — the h2 is capped at 24ch and shrinks with the viewport, so it still
   is at 1080. Below 900 the head fills the sheet and the stamp goes.
   (the first query also neutralises the old ≤1200 hide the integrator DELETES.) */
@media (max-width: 1200px) { .install .wrap > .stamp-el { display: inline-block; } }
@media (max-width: 900px)  { .install .wrap > .stamp-el { display: none; } }

/* the row breaks: → on its line, ✓ under it, both hanging off one indent */
@media (max-width: 820px) {
  .install .boot .stn { flex-wrap: wrap; padding: 16px 0; }
  .install .boot .stn .leader { display: none; }
  .install .boot .stn .out {
    flex: 0 0 100%;
    padding-left: 1.55em; text-indent: -1.55em;
  }
  .install .boot .stn:last-child .out.ok { padding: 0 0 0 1.55em; }
  .install .boot .stn .out i { width: 1.55em; margin-right: 0; text-indent: 0; }
  .install .boot .stn .out + .out { margin-top: 5px; }
}

@media (max-width: 640px) {
  /* the page's mobile gutter is 22–24px, not the desktop 44 */
  .install .wrap { padding: 76px 24px 64px; }
  .install .cmd-band { margin-top: 58px; }
  .install .in { margin-top: 28px; }
  .install .boot { margin-top: 30px; }
  .install .out { font-size: 12.5px; }
  .install .boot .stn:last-child .out.ok { font-size: 13.5px; padding: 0 0 0 1.55em; }
  .install .cta-row { flex-wrap: wrap; }
  /* both strips stack under their rule — the labels no longer fit one line.
     (the `position: static` also neutralises the old ≤640 .band-labs block the
     integrator DELETES; harmless once it is gone.) */
  .install .band-labs, .install .plats {
    position: static; display: block; text-align: left; line-height: 1.9;
  }
  .install .band-labs .leader, .install .plats .leader { display: none; }
  .install .band-l { display: block; white-space: normal; line-height: 1.8; }
  .install .plats { margin-top: 46px; }
  .install .plats i { display: block; margin-bottom: 1px; }
  .install .plats .r { display: block; text-align: left; line-height: 1.8; }
}

/* ------------------------------------------------------------ PREVIEW ONLY
   wip-preview.py swaps only the <section>, so full.html's <div class="marquee">
   that follows it survives in this preview page. The integrator DELETES that
   node (and the .install + .marquee rules at ~1985–1988); this rule goes with it. */
.install + .marquee { display: none; }

/* ---------------------------------------------- [eco] */
/* ==================================================== 07 · the ecosystem
   THE SUM, THE SPREAD, THE SEAL — three bands of falling weight: an unframed
   display-paragraph sum closed by a total rule, four entries as running prose
   across one gutter hairline, and governance as the ONE framed paper object
   on the sheet. Every selector is #eco-scoped; tokens only, no hex, no radius. */

/* `clip`, not `hidden`: hidden makes the section a scroll container and freezes
   the page-wide .ghost-n view-timeline inside it */
#eco { overflow: clip; --fig: 58px; }   /* width of the hanging-figure margin */
#eco .wrap { padding: 92px 44px 90px; }
/* the head is a narrow left-hand set, so the ghost owns clear air on the right
   at every width it is drawn (it is display:none below 1100px). 56px, not 30:
   the page-wide ±54px view-timeline parallax would otherwise shave the numeral's
   top off against the section's own clip at the end of its travel. */
#eco .ghost-n { left: auto; right: max(48px, calc((100vw - 1200px) / 2)); top: 56px; }

/* ------------------------------------------------------------- head
   one column, set in the left third. Nothing sits under the ghost numeral. */
#eco .eco-head {
  display: block; grid-template-columns: none;
  max-width: 520px; margin-bottom: 58px;
}
#eco .eco-head h2 { max-width: 17ch; margin-bottom: 16px; }
#eco .eco-head .lede {
  align-self: auto; max-width: 54ch; font-size: 17px; line-height: 1.62; text-wrap: balance;
}

/* ============================================= BAND A · the sum
   fourteen names as two lines of running headline, closed by a total rule.
   Zero cell borders and zero frame — a sentence, then a sum. */
#eco .eq-band {
  border-top: 1px solid var(--rule); border-bottom: 0;
  padding: 36px 0 0; margin-top: 0;
}
#eco .eco-call {
  display: flex; align-items: center; padding: 0; margin: 0 0 26px;
  grid-column: auto; grid-row: auto;
}
#eco .eco-call .leader { margin: 0 0 0 14px; }

#eco .eq {
  display: block; grid-template-columns: none; grid-column: auto; grid-row: auto;
  border: 0; margin: 0; max-width: none; text-wrap: pretty;
  font-family: var(--display); font-size: clamp(24px, 2.6vw, 34px); line-height: 1.5;
}
/* the operator trails its own term, so no line can open on a "+" and the
   equation's left edge sits exactly on the section margin */
#eco .eq .part { display: inline; border: 0; padding: 0; white-space: nowrap; }
/* neutralise the retired cell grid at every breakpoint it was drawn in */
#eco .eq .part:nth-child(7n+1),
#eco .eq .part:nth-child(4n+1),
#eco .eq .part:nth-child(2n+1),
#eco .eq .part:nth-child(-n+7),
#eco .eq .part:nth-child(-n+12),
#eco .eq .part:nth-last-child(2),
#eco .eq .part:nth-last-child(3) { border: 0; padding: 0; }

#eco .eterm {
  display: inline; font-family: var(--display); font-weight: 400; font-size: inherit;
  letter-spacing: 0; text-transform: none; color: var(--ink);
  background: none; border: 0; box-shadow: none; padding: 0; white-space: nowrap;
}
#eco .eterm.hot {
  color: var(--v3); background: none; box-shadow: none; border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--v3) 45%, transparent); padding-bottom: 2px;
}
#eco .eq .op {
  display: inline; font-family: var(--mono); font-size: 11px; padding: 0 .34em;
  width: auto; flex: none; color: color-mix(in srgb, var(--v3) 40%, transparent);
}
#eco .eq .part:first-child .op { visibility: visible; }
#eco .eq .part:nth-of-type(14) .op { display: none; }

/* the total: a rule across the measure, then the sum, unframed */
#eco .eq .eq-res {
  display: flex; width: 100%; justify-content: flex-end; align-items: baseline;
  gap: 16px; margin-top: 30px; padding: 20px 0 0; border-top: 1px solid var(--rule);
}
#eco .eq .eq-res .op {
  font-size: 19px; padding: 0; color: color-mix(in srgb, var(--v3) 55%, transparent);
}
#eco .res {
  font-family: var(--display); font-weight: 700; font-size: 38px; line-height: 1.06;
  letter-spacing: -.004em; color: var(--ink);
  background: none; border: 0; border-radius: 0; box-shadow: none; margin: 0; padding: 0;
}

/* ============================================= BAND B · the four
   a book spread: one continuous hairline in the gutter and nothing else.
   No boxes, no backgrounds, no tints, no horizontal rules between entries. */
#eco .eco-four {
  position: relative;
  display: grid; grid-template-columns: 1fr 1fr;
  column-gap: 76px; row-gap: 54px; padding: 62px 0 0;
}
#eco .eco-four::before {
  content: ""; position: absolute; top: 62px; bottom: 0; left: 50%;
  width: 1px; background: var(--rule-soft);
}
/* flex, not block: it also disarms the base sheet's `.layer { display: contents }`
   and its 1100px grid re-flow without needing a second override */
#eco .eco-four .layer {
  display: flex; flex-direction: column; grid-template-columns: none;
  /* the sheet's generic .layer card sets align-items:center + gap:26px; both
     would shrink-wrap and re-centre the specimen inside its column */
  align-items: stretch; gap: 0;
  background: none; border: 0; padding: 0; box-shadow: none; position: relative;
}
#eco .eco-four .layer + .layer { margin-top: 0; }

/* ---- prose, shared by both bands (band C has no .layer wrapper) ----
   the figure hangs in its own margin and shares a baseline with the heading —
   grid + align-items:baseline, so no font-metric fudge can drift */
#eco .eco-four .layer > .note, #eco .eco-fifth > .note {
  display: grid; grid-template-columns: var(--fig) minmax(0, 1fr);
  column-gap: 0; align-items: baseline;
  padding: 0; grid-column: auto; grid-row: auto; margin-bottom: 30px;
}
#eco .eco-four .layer .l-n, #eco .eco-fifth .l-n {
  float: none; grid-column: 1; clear: none;
  font-family: var(--display); font-weight: 400; font-size: 40px; line-height: 1;
  color: color-mix(in srgb, var(--hue) 80%, var(--ink)); margin: 0;
}
#eco .eco-fifth .l-n { color: var(--v5); }
#eco .eco-four .layer h3, #eco .eco-fifth h3 {
  font-family: var(--display); font-weight: 700; font-size: 20px; line-height: 1.14;
  letter-spacing: -.004em; color: var(--ink); margin-bottom: 8px;
}
#eco .eco-four .layer .l-body, #eco .eco-fifth .l-body {
  clear: none; max-width: none; text-wrap: pretty;
  font-family: var(--body); font-size: 15px; line-height: 1.6; color: var(--ink-soft);
}
#eco .eco-four .layer ul, #eco .eco-fifth ul { margin-top: 12px; display: grid; gap: 5px; }
#eco .eco-four .layer li, #eco .eco-fifth li {
  list-style: none; display: grid; grid-template-columns: 15px 1fr; align-items: baseline;
  gap: 0; font-family: var(--body); font-size: 12.5px; line-height: 1.46; color: var(--ink-soft);
}
#eco .eco-four .layer li::before, #eco .eco-fifth li::before {
  content: "✓"; width: auto; height: auto; background: none; transform: none;
  font-family: var(--mono); font-size: 10.5px; color: var(--v3);
}

/* ---- the specimen: a footnote under the prose, smaller than the prose, and on
   the SAME left axis — only the figures hang in the margin.
   margin-top:auto floors every specimen in a row onto one shared rule. ---- */
#eco .eco-four .scene {
  display: block; margin: auto 0 0 var(--fig); padding: 16px 0 0;
  grid-column: auto; grid-row: auto;
  background: none; border: 0; border-radius: 0; border-top: 1px solid var(--rule-soft);
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-faint);
}
#eco .eco-four .l-lin { display: block; justify-self: start; margin: 0 0 8px; }
#eco .eco-four .sc-body { display: block; align-self: auto; gap: 0; }
/* card and fan/step run share one line box, so the two specimen shapes measure
   the same height and their rules land on one line across the spread */
#eco .sc-card {
  display: flex; justify-content: flex-start; align-items: baseline; gap: 0;
  background: none; border: 0; border-radius: 0; padding: 5px 0; line-height: 1.45;
}
#eco .sc-card b { font-weight: 700; color: var(--ink); }
#eco .eco-four .sc-card .leader { margin: 0 12px; }
#eco .sc-tag {
  background: none; border: 0; border-radius: 0; padding: 0; white-space: nowrap;
  font-family: var(--mono); font-size: 9px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--v3);
}
#eco .sc-tag.warn { color: var(--v5); background: none; border: 0; }
#eco .sc-fan, #eco .sc-steps {
  display: flex; flex-wrap: wrap; gap: 0; margin: 0; padding: 5px 0; line-height: 1.45;
}
#eco .sc-fan span, #eco .sc-steps span {
  flex: none; text-align: left; font-family: var(--mono); font-size: 10.5px;
  border: 0; border-right: 1px solid var(--rule-soft); border-radius: 0; background: none;
  padding: 0 12px 0 0; margin-right: 12px; color: var(--v3);
}
#eco .sc-fan span:last-child, #eco .sc-steps span:last-child {
  border-right: 0; padding-right: 0; margin-right: 0;
}
#eco .sc-steps .done { color: var(--v3); }
#eco .sc-steps .retry { color: var(--v5); background: none; border-color: var(--rule-soft); }
#eco .sc-steps .queued { color: var(--ink-faint); border-color: var(--rule-soft); }
#eco .eco-four .sc-note {
  display: block; justify-self: auto; text-align: left; margin: 10px 0 0;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-faint);
}

/* ============================================= BAND C · the fifth
   the one frame, the one shadow, the one dogear, the one warning tint.
   The object carries no title strip: "Only here" is said once, by the stamp. */
#eco .eco-fifth {
  display: grid; grid-template-columns: 380px minmax(0, 1fr);
  column-gap: 60px; align-items: start; padding-top: 76px;
}
#eco .eco-fifth > .note { margin-bottom: 0; }
#eco .eco-stamp {
  grid-column: 2; justify-self: start; display: inline-block; clear: none; margin-top: 28px;
  color: var(--v5); border-width: 2px; padding: 7px 12px;
  /* the thunk's pre-state is scale(1.8) — grow from the left edge so it never
     reaches past the margin */
  transform-origin: 0 50%;
}
#eco .eco-stamp b { font-size: 10.5px; letter-spacing: .2em; font-weight: 400; }

#eco .eco-fifth .scene {
  position: relative; display: block; padding: 0; margin: 0;
  grid-column: auto; grid-row: auto;
  background: color-mix(in srgb, var(--paper-hi) 94%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink) 70%, transparent); border-radius: 0;
  box-shadow: var(--shadow-obj);
  font-family: var(--mono); font-size: 11px; color: var(--ink-soft);
}
#eco .eco-fifth .scene.bedrock { padding-bottom: 0; }
#eco .scene.bedrock::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 10px;
  background: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--v1) 13%, transparent) 0 1px, transparent 1px 8px);
}

/* the two decisions, at full size — the object's whole content.
   The rows are full-bleed, so both the dotted rule and the warning tint run
   right to the frame instead of stopping short of it. */
#eco .eco-fifth .sc-body {
  display: block; align-self: auto; gap: 0; padding: 10px 0 8px;
  border-bottom: 1px solid var(--rule);
}
#eco .eco-fifth .sc-card {
  display: flex; align-items: baseline; padding: 24px 30px;
  background: none; border: 0; border-radius: 0;
  border-bottom: 1px dotted color-mix(in srgb, var(--ink) 16%, transparent);
}
#eco .eco-fifth .sc-card:last-child { border-bottom: 0; }
/* the fold is drawn at the frame's own weight, not the sheet's hairline */
#eco .eco-fifth .dogear::after {
  background: linear-gradient(225deg, transparent calc(50% - .5px),
    color-mix(in srgb, var(--ink) 50%, transparent) calc(50% - .5px) calc(50% + .5px),
    transparent calc(50% + .5px));
}
#eco .eco-fifth .sc-card b {
  font-family: var(--mono); font-weight: 700; font-size: 13px; color: var(--ink);
}
#eco .eco-fifth .sc-card .leader { margin: 0 18px; }
#eco .eco-fifth .sc-tag {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--v3); background: none; border: 0; border-radius: 0; padding: 0;
}
/* the page's one warning tint, bled to the object's inner edges */
#eco .eco-fifth .sc-card:last-child {
  background: color-mix(in srgb, var(--v5) 5%, transparent);
  margin-inline: 0; padding-inline: 30px;
}
#eco .eco-fifth .sc-tag.warn {
  color: var(--v5); background: none; border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--v5) 30%, transparent); padding-bottom: 2px;
}

/* foot — clear of the hatched bedrock strip by 22px */
#eco .eco-fifth .sc-note {
  display: block; justify-self: auto; margin: 0; padding: 16px 30px 32px; text-align: right;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-faint);
}

/* --------------------------------------------------- foot · title strip */
#eco .eq-foot {
  grid-column: auto; grid-row: auto;
  margin: 64px 0 0; padding: 9px 0 0; flex-wrap: wrap; gap: 6px 18px;
}
#eco .eq-foot .eq-note {
  flex: 1; min-width: 0; margin: 0; text-align: left;
  font-family: var(--body); font-style: italic; font-size: 12px; line-height: 1.45;
  letter-spacing: 0; text-transform: none; color: var(--ink-soft);
}
#eco .eq-foot .r { flex: none; white-space: nowrap; font-size: 10px; letter-spacing: .1em; }

/* ---------------------------------------------------------------- motion
   one build beat per band; nothing continuous, nothing scroll-linked. */

/* the base layer gives .layer a hover transition that would otherwise retime
   its reveal — put the entries back on the page's own .rv curve */
#eco .eco-four .layer {
  transition: opacity .7s ease, transform .7s cubic-bezier(.22, 1, .36, 1);
  transition-delay: var(--d, 0s);
}
/* band B arrives as four calm .rv beats — note + specimen as one gesture */
#eco .eco-four .scene > :not(.sc-body), #eco .eco-four .sc-body > * {
  opacity: 1; transform: none; transition: none;
}
/* band C prints once: row, row, note */
#eco .eco-fifth .scene > :not(.sc-body), #eco .eco-fifth .sc-body > * {
  opacity: 0; transform: translateY(7px);
  transition: opacity .5s ease var(--step, 0s), transform .6s cubic-bezier(.22,1,.36,1) var(--step, 0s);
}
#eco .eco-fifth .scene.on > :not(.sc-body), #eco .eco-fifth .scene.on .sc-body > * {
  opacity: 1; transform: none;
}
#eco .eco-fifth .scene > .dogear { opacity: 1; transform: none; transition: none; }

/* drawings never lift; hover does nothing in this chapter */
#eco .layer:hover, #eco .scene:hover { transform: none; box-shadow: none; }
#eco .eco-fifth .scene:hover { box-shadow: var(--shadow-obj); }
#eco .sc-card { transition: none; }
#eco .scene:hover .sc-card { border-color: color-mix(in srgb, var(--ink) 16%, transparent); }
#eco .eco-four .scene:hover .sc-card { border-color: transparent; }

@media (prefers-reduced-motion: reduce) {
  #eco .scene > *, #eco .sc-body > *,
  #eco .eco-fifth .scene > *, #eco .eco-fifth .sc-body > * {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
}

/* ------------------------------------------------------------ responsive */
@media (max-width: 1180px) {
  #eco .eco-four { column-gap: 56px; }
  #eco .eco-fifth { grid-template-columns: 330px minmax(0, 1fr); column-gap: 48px; }
}

@media (max-width: 1080px) {
  #eco .eco-head { max-width: none; margin-bottom: 48px; }
  #eco .eco-head h2 { max-width: 18ch; }
  #eco .eco-head .lede { max-width: 62ch; }
  #eco .eco-call { display: flex; }

  #eco .eco-four { grid-template-columns: 1fr; column-gap: 0; row-gap: 48px; padding-top: 54px; }
  #eco .eco-four::before { display: none; }

  /* one column is no reason to set prose 120 characters wide */
  #eco .eco-four .layer .l-body, #eco .eco-fifth .l-body { max-width: 58ch; }
  #eco .eco-four .layer li, #eco .eco-fifth li { max-width: 62ch; }

  #eco .eco-fifth { grid-template-columns: 1fr; row-gap: 40px; padding-top: 62px; }

  #eco .eq { grid-template-columns: none; }
  #eco .eq-foot { margin-top: 54px; }
}

@media (max-width: 640px) {
  #eco { --fig: 44px; }
  #eco .wrap { padding: 74px 22px 76px; }
  #eco .eq { font-size: clamp(19px, 5.4vw, 22px); line-height: 1.42; }
  #eco .eq .op { width: auto; text-align: left; }
  #eco .eq .eq-res { justify-content: flex-start; gap: 12px; margin-top: 24px; padding-top: 16px; }
  #eco .res { font-size: 26px; }

  #eco .eco-four .layer > .note, #eco .eco-fifth > .note { margin-bottom: 24px; }
  #eco .eco-four .layer .l-n, #eco .eco-fifth .l-n { font-size: 32px; }
  #eco .eco-four .layer h3, #eco .eco-fifth h3 { font-size: 19px; }
  /* the label takes the whole line so the tag drops below it at its OWN width —
     a full-width flex tag would stretch the warn tag's underline across the row */
  #eco .sc-card { flex-wrap: wrap; }
  #eco .sc-card b { flex: 1 0 100%; }
  #eco .sc-card .leader { display: none; }
  #eco .eco-four .sc-card { gap: 3px 0; }

  #eco .eco-fifth .scene { box-shadow: var(--shadow-card); }
  #eco .eco-fifth .sc-body { padding: 8px 0 6px; }
  #eco .eco-fifth .sc-card { padding: 16px 18px; }
  #eco .eco-fifth .sc-card .sc-tag { margin-top: 7px; }
  #eco .eco-fifth .sc-card:last-child { margin-inline: 0; padding-inline: 18px; }
  #eco .eco-fifth .sc-note { padding: 14px 18px 30px; text-align: left; letter-spacing: .12em; }

  #eco .eq-foot { display: block; }
  #eco .eq-foot .r { display: block; margin-top: 8px; }
}

/* ---------------------------------------------- [console] */
/* ================================================================ [08] console
   archetype: dimension-line — one commitment walks a full-bleed hairline.
   Every selector is scoped to .console so nothing leaks. Tokens only, no hex. */

/* ---------------------------------------------------------------- section */
.console { background: transparent; border-top: 3px double var(--rule); }
.console .wrap { padding-top: 90px; padding-bottom: 92px; }

/* ------------------------------------------------- HEAD · split headline row */
.console .wrap {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: 24px;
  row-gap: 0;
  align-content: start;
}
.console .chapter { grid-column: 1 / -1; grid-row: 1; }
.console h2 {
  grid-column: 1 / 8; grid-row: 2;
  max-width: 19ch; margin-bottom: 72px;
}
.console .lede {
  grid-column: 8 / -1; grid-row: 2; align-self: end;
  max-width: none; margin-bottom: 72px;
}

/* ------------------------------------------------------ HERO · the dimension line */
.console .board {
  grid-column: 1 / -1; grid-row: 3;
  position: relative; border: 0; background: transparent; margin-top: 0;
}

.console .cols {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin-inline: -16px;          /* station labels sit flush with the wrap's text edge */
}
/* the hairline: escapes the wrap to the sheet's two edges, clipped by section overflow:hidden */
.console .cols::before {
  content: ""; position: absolute;
  left: calc(50% - 50vw); width: 100vw;
  top: 150px; height: 1px;
  background: color-mix(in srgb, var(--ink) 38%, transparent);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .9s cubic-bezier(.22, 1, .36, 1) .18s;
}
.console .board.on .cols::before { transform: none; }

/* ------------------------------------------------------------------ stations */
.console .colm {
  position: relative;
  border: 0; min-height: 0;
  padding: 0 16px;
  display: grid;
  /* row 1 is the lane above the line; row 3 is floored so every ledger rule lands on one y */
  grid-template-rows: 150px auto minmax(40px, auto) auto;
  align-content: start;
}
/* the station ring, centred on the line */
.console .colm::before {
  content: ""; position: absolute; left: -3.5px; top: 146.5px;
  width: 7px; height: 7px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ink) 38%, transparent);
  background: var(--paper);
  transition: border-color .4s ease .18s, background-color .4s ease .18s;  /* lights as the card lands */
}
/* the walked trail — rings the card has already passed (and the one it stands on) stay lit */
.console .colm:has(~ .colm #traveler)::before,
.console .colm:has(#traveler)::before {
  border-color: var(--v3);
  background: color-mix(in srgb, var(--v3) 45%, transparent);
}

.console .colm header {
  grid-row: 2;
  display: flex; align-items: center; gap: 8px;
  padding-top: 18px; margin-bottom: 0;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink);
}
.console .colm .hint {
  grid-row: 3;
  font-size: 11.5px; font-style: italic; line-height: 1.45;
  color: var(--ink-faint); margin: 6px 0 0;
}
.console .colm > .cmt { grid-row: 4; }

/* the one tinted lane: the only station that is waiting on a person.
   the wash fades in down the lane so it has no arbitrary top edge floating in the air */
.console .colm[data-col="2"] {
  background: linear-gradient(to bottom,
    transparent 0,
    color-mix(in srgb, var(--v3) 6%, transparent) 150px);
}
.console .colm[data-col="2"] header { color: var(--v3); }
.console .colm[data-col="4"] header { color: var(--v5); }

/* ------------------------------------------- static stations = ledger entries, not cards */
.console .cmt {
  background: transparent; border: 0;
  border-top: 1px solid var(--rule-soft);
  padding: 10px 0 0; margin: 14px 0 0;
  display: grid; grid-template-columns: 1fr auto; column-gap: 10px; row-gap: 3px;
  transition: border-color .35s ease;
}
.console .cmt .fn {
  grid-column: 1 / -1;
  font-family: var(--body); font-weight: 400; font-size: 13px; line-height: 1.3;
  color: var(--ink); margin-bottom: 0;
  overflow-wrap: anywhere;
}
.console .cmt .meta {
  display: contents;
  font-family: var(--mono); font-size: 10px; color: var(--ink-faint);
}
.console .cmt .meta span { font-family: var(--mono); font-size: 10px; color: var(--ink-faint); }
.console .cmt .meta span:last-child { text-align: right; }
.console .cmt .note {
  grid-column: 1 / -1; margin-top: 0;
  font-family: var(--mono); font-size: 10px; letter-spacing: .01em; color: var(--v3);
}
.console .cmt .note.warn { color: var(--v5); font-weight: 700; }
/* ledgers shift colour, they never lift */
.console .cmt:not(#traveler):hover {
  transform: none;
  border-top-color: color-mix(in srgb, var(--v3) 42%, transparent);
}

/* ------------------------------------------------------- the traveller stays a card */
.console #traveler {
  grid-row: 1; align-self: end;
  background: var(--paper-hi);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-card);
  padding: 12px 14px; margin: 0 0 14px; width: 100%;
  display: block;
}
.console #traveler .fn {
  font-family: var(--body); font-weight: 700; font-size: 14px; line-height: 1.25;
  color: var(--ink); margin-bottom: 5px;
}
.console #traveler .meta {
  display: flex; justify-content: space-between; gap: 10px;
  font-family: var(--mono); font-size: 10px; color: var(--ink-faint);
}
.console #traveler .note { margin-top: 6px; }
.console #traveler .decide { display: flex; gap: 7px; margin-top: 9px; }
.console #traveler .decide span {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase;
  padding: 4px 9px; border: 1px solid var(--rule); color: var(--ink-soft);
}
.console #traveler .decide .go {
  background: var(--deep); border-color: var(--deep); color: var(--paper-hi);
}

/* ------------------------------------------------------------------ FOOT */
.console .board-foot {
  grid-column: 1 / -1; grid-row: 4;
  display: grid; grid-template-columns: 1fr auto;
  align-items: end; gap: 32px; margin-top: 34px;
}
.console .board-caption {
  margin: 0; font-size: 13px; font-style: italic; line-height: 1.55;
  color: var(--ink-soft); max-width: 64ch;
}
/* the black tab becomes a hairline title block; .fig-tab itself stays for the hero's "Fig. A" */
.console .board-foot .fig-tab {
  position: static; justify-self: end;
  background: transparent; color: var(--ink-faint);
  border: 1px solid var(--rule);
  padding: 9px 14px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  white-space: nowrap;
}

/* ------------------------------------------------------------ reduced motion */
@media (prefers-reduced-motion: reduce) {
  .console .cols::before { transform: none !important; transition: none !important; }
  .console .colm::before { transition: none !important; }
  .console .cmt { transition: none !important; }
}

/* ------------------------------------------------ RESPONSIVE · the line goes vertical */
@media (max-width: 1080px) {
  .console .wrap { display: block; padding-top: 74px; padding-bottom: 78px; }
  .console h2 { max-width: 24ch; margin-bottom: 16px; }
  .console .lede { max-width: 70ch; margin-bottom: 0; }
  .console .board { margin-top: 48px; }

  .console .cols {
    grid-template-columns: 1fr;
    margin-inline: 0;
    padding: 0 0 0 28px;
  }
  .console .cols::before {
    left: 0; top: 0; width: 1px; height: 100%;
    transform: none; transition: none;
  }
  .console .colm {
    display: block;
    padding: 0 0 26px 0;
    background: transparent;
  }
  .console .colm:last-child { padding-bottom: 0; }
  .console .colm::before { left: -31.5px; top: 6px; }
  .console .colm[data-col="2"] {
    background: color-mix(in srgb, var(--v3) 5%, transparent);
    padding: 0 14px 26px 0;
  }
  .console .colm header { padding-top: 0; }
  .console .colm .hint { margin-top: 5px; }
  .console .cmt { max-width: 34ch; }
  .console #traveler { margin: 14px 0 0; max-width: 34ch; }

  .console .board-foot { grid-template-columns: 1fr; gap: 22px; margin-top: 30px; }
  .console .board-foot .fig-tab {
    justify-self: start; white-space: normal;
    font-size: 9px; letter-spacing: .12em;
  }
}

/* ---------------------------------------------- [refusals] */
/* =========================================================== [09] refusals
   archetype: index-columns — an index of ten, set in two typographic columns.
   Devices: one dimension line, one hairline column rule, dotted leaders,
   one hatched void band. No boxes, no fills except the single v5 wash on 05. */

  .refusals .wrap { padding: 92px 44px 96px; }
  .refusals .ghost-n { top: 20px; -webkit-text-stroke-color: color-mix(in srgb, var(--v1) 20%, transparent); }
  .refusals .lede { max-width: 62ch; }

  /* ---------------------------------------------------- opening figure */
  .refusals .ref-open {
    margin-top: 46px; position: relative;
    display: grid; grid-template-columns: auto 1fr; column-gap: 40px; align-items: end;
  }
  .refusals .ref-open .rail-stat { border-top: 0; padding: 0; }
  .refusals .ref-open .rail-stat b {
    display: block; font-family: var(--display); font-weight: 400;
    font-size: 76px; line-height: .9; color: var(--ink); letter-spacing: -.01em;
  }
  .refusals .ref-open .rail-stat span {
    display: block; margin-top: 6px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em;
    text-transform: uppercase; color: var(--ink-soft);
  }
  .refusals .ref-open-r { min-width: 0; }
  /* the dimension line spans the rest of the width and draws itself left → right */
  .refusals .ref-open .dim {
    max-width: none; margin: 0 0 14px;
    clip-path: inset(-10px 100% -10px 0);
    transition: clip-path .9s cubic-bezier(.22,1,.36,1) .18s;
  }
  .refusals .ref-open.on .dim { clip-path: inset(-10px 0 -10px 0); }
  .refusals .ref-open .rail-note {
    border-top: 0; padding-top: 0; text-align: right;
    font-size: 13.5px; line-height: 1.6; color: var(--ink-soft);
  }
  .refusals .ref-open .rail-note code { font-family: var(--mono); font-size: 12px; color: var(--v3); border-bottom: 1px dotted var(--v3); }

  /* stamp 1 — lands in the clear band above the dimension line */
  .refusals .ref-open .stamp-el {
    position: absolute; right: 120px; top: -6px;
    color: var(--v5); --rot: -5deg; font-size: 10.5px; padding: 7px 12px;
  }
  .refusals .ref-open .stamp-el b { font-size: 10.5px; letter-spacing: .2em; font-weight: 400; }

  /* ------------------------------------------------------- the legend */
  .refusals .ix-legend {
    margin-top: 54px; padding-bottom: 8px;
    border-bottom: 1px solid var(--rule);
    font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em;
    text-transform: uppercase; color: var(--ink-faint);
  }

  /* -------------------------------------------------------- the index */
  .refusals .index { position: relative; display: grid; grid-template-columns: 1fr 1fr; column-gap: 72px; }
  .refusals .index::before {
    content: ""; position: absolute; left: calc(50% - .5px); top: 0; bottom: 0;
    width: 1px; background: var(--rule-soft);
  }
  .refusals .ix-col { min-width: 0; }

  .refusals .ix-entry {
    border-top: 1px solid var(--rule-soft); padding: 18px 0 20px;
    display: grid; grid-template-columns: 34px 1fr; column-gap: 14px; position: relative;
  }
  .refusals .ix-col > .ix-entry:first-child { border-top: 0; padding-top: 20px; }
  .refusals .ix-entry > * { grid-column: 2; min-width: 0; }
  .refusals .ix-entry .no {
    grid-column: 1; grid-row: 1;
    font-family: var(--mono); font-size: 11px; color: var(--v3);
    padding-top: 4px; transition: color .25s ease;
  }
  .refusals .ix-line { display: flex; align-items: baseline; }
  .refusals .ix-line .name { font-family: var(--body); font-weight: 700; font-size: 17px; line-height: 1.35; }
  .refusals .ix-line code {
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em;
    color: var(--ink); background: none; border: 0; padding: 0;
    overflow-wrap: anywhere; transition: color .25s ease;
  }
  .refusals .ix-entry .mean {
    display: block; margin-top: 8px; font-size: 13.5px; line-height: 1.55;
    color: var(--ink-soft); max-width: 44ch;
  }
  .refusals .ix-entry .fix { display: block; margin-top: 6px; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
  .refusals .ix-entry .fix i { font-style: normal; color: var(--v3); margin-right: 7px; }

  /* dotted leader — shared drafting device (integrator: dedupe with the global .leader) */
  .refusals .leader {
    flex: 1; min-width: 24px; align-self: center; height: 1px; margin: 0 14px;
    background: radial-gradient(circle, var(--ink-faint) .8px, transparent 1px) 0 50%/6px 1px repeat-x;
    transform: scaleX(0); transform-origin: 0 50%;
    transition: transform .6s cubic-bezier(.22,1,.36,1) var(--d, 0s);
  }
  .refusals .rv.on .leader, .refusals .leader.on { transform: none; }

  /* hover — paper, not an object: colour only, no lift */
  .refusals .ix-entry:hover .no,
  .refusals .ix-entry:hover .ix-line code { color: var(--v3); }
  .refusals .ix-entry.hot:hover .ix-line code { color: var(--v5); }

  /* ------------------------------------------- entry 05, the one warning */
  .refusals .ix-entry.hot {
    background: color-mix(in srgb, var(--v5) 6%, transparent);
    margin: 0 -18px; padding: 18px 18px 20px;
  }
  .refusals .ix-entry.hot .ix-line code { color: var(--v5); font-weight: 700; }
  .refusals .ix-note {
    display: block; margin-top: 5px; text-align: right;
    font-family: var(--mono); font-size: 9px; letter-spacing: .04em; line-height: 1.5; color: var(--v5);
  }
  /* stamp 2 — lands across entry 05's leader, the row's guaranteed clear air.
     anchored from the right so it stays on the leader as the column narrows. */
  .refusals .refstamp {
    position: absolute; right: 90px; top: 2px;
    color: var(--v5); --rot: -6deg; --o: .9;
    padding: 3px 8px; border-width: 2px; border-radius: 5px;
  }
  .refusals .refstamp::before { inset: 2px; border-radius: 3px; }
  .refusals .refstamp b { font-size: 9.5px; letter-spacing: .18em; }

  /* ---------------------------------------------------- closing figure */
  .refusals .ix-close {
    margin-top: 36px;
    display: grid; grid-template-columns: 1fr auto; column-gap: 40px; align-items: center;
  }
  .refusals .sch-void {
    height: 44px; display: flex; align-items: center; justify-content: center;
    background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--v1) 14%, transparent) 0 1px, transparent 1px 8px);
  }
  .refusals .sch-void span {
    font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase;
    color: var(--ink-faint); background: var(--paper-hi); padding: 3px 14px;
    border: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
  }
  .refusals .ix-close .rail-stat { border-top: 0; padding: 0; text-align: right; }
  .refusals .ix-close .rail-stat b {
    display: block; font-family: var(--display); font-weight: 400;
    font-size: 56px; line-height: .9; color: var(--ink);
  }
  .refusals .ix-close .rail-stat span {
    display: block; margin-top: 6px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em;
    text-transform: uppercase; color: var(--ink-soft);
  }

  /* ---------------------------------------------------------- responsive */
  @media (max-width: 1180px) {
    .refusals .ref-open .stamp-el { right: 40px; }
  }
  @media (max-width: 980px) {
    .refusals .index { grid-template-columns: 1fr; column-gap: 0; }
    .refusals .index::before { display: none; }
    .refusals .ix-col + .ix-col > .ix-entry:first-child { border-top: 1px solid var(--rule-soft); padding-top: 18px; }
    .refusals .ref-open { grid-template-columns: 1fr; row-gap: 22px; align-items: start; }
    .refusals .ref-open .rail-note { text-align: left; }
    .refusals .ref-open .stamp-el { position: static; justify-self: start; margin-top: 4px; }
  }
  @media (max-width: 640px) {
    .refusals .wrap { padding: 68px 44px 72px; }
    .refusals .leader { display: none; }
    /* the dimension line keeps its arrows; the label drops beneath it */
    .refusals .ref-open .dim { flex-wrap: wrap; gap: 0 10px; }
    .refusals .ref-open .dim span { order: 3; flex-basis: 100%; margin-top: 9px; line-height: 1.7; }
    .refusals .ix-line { display: contents; }
    .refusals .ix-line .name { grid-column: 2; grid-row: 1; }
    .refusals .ix-line code { grid-column: 2; grid-row: 4; display: block; margin-top: 10px; color: var(--v3); }
    .refusals .ix-entry .mean { grid-row: 2; max-width: none; }
    .refusals .ix-entry .fix { grid-row: 3; }
    .refusals .ix-note { grid-row: 5; margin-top: 4px; text-align: left; }
    .refusals .ix-entry.hot .ix-line code { color: var(--v5); }
    .refusals .ref-open .rail-stat b { font-size: 56px; }
    .refusals .ix-close { grid-template-columns: 1fr; row-gap: 20px; }
    .refusals .ix-close .rail-stat { text-align: left; }
    .refusals .ix-close .rail-stat b { font-size: 44px; }
    .refusals .refstamp { position: static; grid-column: 2; grid-row: 6; justify-self: start; margin-top: 14px; }
  }

  @media (prefers-reduced-motion: reduce) {
    .refusals .leader { transform: none !important; transition: none !important; }
    .refusals .ref-open .dim { clip-path: none !important; transition: none !important; }
  }

/* ---------------------------------------------- [cost] */
/* ================================================ 10 · cost — ledger-and-margin
   A frameless ruled sheet on the left; the carried totals in the margin on the right.
   Nothing here is a card: no box, no corner radius, no shadow. Only rules. */

  .cost { background: transparent; border-top: 3px double var(--rule); }
  .cost .wrap { padding: 92px 44px 88px; }
  .cost .ghost-n { top: 24px; }

  /* ---------------------------------------------------------- head: a spread */
  .cost .cost-head {
    display: grid; grid-template-columns: 1fr 1fr; column-gap: 56px; align-items: end;
    margin-bottom: 52px;
  }
  .cost .cost-head h2 { max-width: 13ch; margin-bottom: 0; }
  .cost .cost-ledes { display: grid; gap: 14px; }
  .cost .cost-ledes .lede { font-size: 16px; line-height: 1.6; max-width: 48ch; }

  /* ---------------------------------------------------------- body: sheet + margin */
  .cost .cost-body {
    display: grid; grid-template-columns: minmax(0, 1fr) 280px; column-gap: 56px;
    align-items: start;
  }

  /* ---------------------------------------------------------- the ledger sheet */
  .cost .meter {
    max-width: none; margin: 0; padding: 0; background: transparent; border: 0;
    box-shadow: none; position: relative;
    border-top: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent);
  }
  .cost .meter:hover { transform: none; box-shadow: none; }

  .cost .meter-head {
    display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
    color: var(--ink-soft); padding: 14px 0 0; margin-bottom: 0;
  }
  /* the ceiling label sits over the ceiling cap, not over the void past it */
  .cost .meter-head span:last-child { margin-right: 30px; }

  /* --- four ledger rows, one pitch, one ceiling */
  .cost .axes { display: block; max-width: none; margin: 18px 0 0; grid-template-columns: none; }
  .cost .axis {
    display: grid; grid-template-columns: 112px 220px minmax(0, 1fr); column-gap: 26px;
    align-items: center; padding: 18px 0; border: 0; background: none;
    border-top: 1px solid var(--rule-soft);
  }
  .cost .axis:hover { transform: none; box-shadow: none; }
  .cost .axis b { display: block; font-family: var(--body); font-size: 15px; font-weight: 700; color: var(--ink); margin-bottom: 0; }
  .cost .axis span { display: block; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }

  .cost .track { position: relative; height: 16px; display: block; }
  .cost .track::before {
    content: ""; position: absolute; left: 0; right: 30px; top: 50%;
    height: 1px; background: var(--rule);
    transform: scaleX(0); transform-origin: 0 50%;
    transition: transform .7s cubic-bezier(.22,1,.36,1) var(--d, 0s);
  }
  .cost .track::after {
    content: ""; position: absolute; right: 30px; top: 4px; bottom: 4px;
    width: 1px; background: var(--ink);                       /* the ceiling cap */
  }
  .cost .track i.void {
    position: absolute; right: 0; width: 30px; top: 3px; bottom: 3px; opacity: 0;
    background: repeating-linear-gradient(45deg,
      color-mix(in srgb, var(--v1) 13%, transparent) 0 1px, transparent 1px 7px);
    transition: opacity .5s ease 1.3s;                        /* nothing sits past the ceiling */
  }
  .cost .meter.on .track::before { transform: none; }
  .cost .meter.on .track i.void { opacity: 1; }

  /* --- the Money row is the live one: the existing meter, drawn to the same ceiling */
  .cost .track.live::before, .cost .track.live::after { display: none; }
  .cost .meter-track {
    position: absolute; left: 0; right: 30px; top: 50%; margin-top: -2px;
    height: 4px; background: color-mix(in srgb, var(--v1) 8%, transparent);
    border: 0; border-radius: 0;
  }
  .cost .meter-fill {
    position: absolute; inset: 0 auto 0 0; width: 0;
    background: linear-gradient(90deg, var(--v1), var(--v4));
    transition: width 1.2s cubic-bezier(.22,1,.36,1) .2s;
  }
  .cost .meter.on .meter-fill { width: 78%; }
  .cost .meter-cap { position: absolute; right: 0; top: -2px; bottom: -2px; width: 1px; background: var(--ink); }

  /* --- the sheet's foot: what is spent, and what was refused */
  .cost .meter-foot {
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px 20px;
    border-top: 1px solid var(--rule-soft); padding-top: 14px; margin-top: 6px;
    font-family: var(--mono); font-size: 11.5px;
  }
  .cost .meter-foot .spent { font-size: 11.5px; font-weight: 700; color: var(--ink); }
  .cost .meter-foot .refused-chip {
    color: var(--v5); border: 1px solid currentColor; border-radius: 5px;
    padding: 6px 11px; letter-spacing: .04em; line-height: 1.5;
  }

  /* --- the sheet's title strip */
  .cost .caption {
    display: flex; justify-content: space-between; align-items: baseline; gap: 28px;
    max-width: none; margin: 20px 0 0;
    border-top: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); padding-top: 10px;
    font-size: 13px; font-style: italic; line-height: 1.55; color: var(--ink-soft);
  }
  .cost .caption .c-txt { flex: 1 1 auto; text-wrap: pretty; }
  .cost .caption .c-fig {
    flex: 0 0 auto; font-family: var(--mono); font-style: normal; font-size: 9.5px;
    letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint);
    white-space: nowrap; padding-top: 3px;
  }

  /* ---------------------------------------------------------- the margin tally */
  .cost .save-row {
    display: grid; grid-template-columns: 1fr; gap: 0; max-width: none; margin: 0;
    border: 0;
  }
  .cost .save { padding: 20px 0 22px; border: 0; border-top: 1px solid var(--rule); }
  .cost .save:first-child { border-top: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent); }
  .cost .save b {
    display: block; font-family: var(--display); font-weight: 400; font-size: 56px;
    line-height: 1; color: var(--v1); margin-bottom: 8px;
  }
  .cost .save span {
    display: block; font-size: 13.5px; line-height: 1.5; color: var(--ink-soft);
    max-width: none; text-wrap: pretty;
  }

  /* ---------------------------------------------------------- motion safety */
  @media (prefers-reduced-motion: reduce) {
    .cost .track::before { transform: none !important; transition: none !important; }
    .cost .track i.void { opacity: 1 !important; transition: none !important; }
    .cost .meter-fill { transition: none !important; }
  }

  /* ---------------------------------------------------------- responsive */
  @media (max-width: 1080px) {
    .cost .cost-head { grid-template-columns: 1fr; row-gap: 20px; align-items: start; margin-bottom: 44px; }
    .cost .cost-head h2 { max-width: 20ch; }
    .cost .cost-body { grid-template-columns: 1fr; row-gap: 44px; }
    .cost .save-row {
      grid-template-columns: repeat(3, 1fr);
      border-top: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent);
    }
    .cost .save, .cost .save:first-child {
      border-top: 0; border-right: 1px solid var(--rule-soft); padding: 20px 22px 22px 0;
    }
    .cost .save + .save { padding-left: 22px; }
    .cost .save:last-child { border-right: 0; }
    .cost .axis { grid-template-columns: 100px minmax(0, 1fr); row-gap: 0; }
    .cost .axis .track { grid-column: 1 / -1; margin-top: 10px; }
  }
  @media (max-width: 640px) {
    .cost .axis { grid-template-columns: 1fr; }
    .cost .axis span { margin-top: 2px; }
    .cost .save-row { grid-template-columns: 1fr; border-top: 0; }
    .cost .save, .cost .save + .save {
      border-right: 0; padding: 18px 0 20px; border-top: 1px solid var(--rule);
    }
    .cost .save:first-child { border-top: 1.5px solid color-mix(in srgb, var(--ink) 70%, transparent); }
    .cost .save b { font-size: 44px; }
    .cost .meter-head { flex-direction: column; align-items: flex-start; gap: 5px; }
    .cost .meter-head span:last-child { margin-right: 0; }
    .cost .meter-foot { flex-direction: column; align-items: flex-start; gap: 12px; }
    .cost .caption { flex-direction: column; gap: 8px; }
  }

/* ---------------------------------------------- [partners] */
/* ============================================ 11 · partners — full-bleed-band
   The page's one symmetrical beat, and its one centred chapter head.
   A band lighter than the section's wash lifts one sheet off the paper:
   a seating plan in plan view — three ghost chairs, a table still being
   drawn, three open seats, one measure across them.
   Everything is scoped to .partners so nothing leaks. */

  /* ---------------------------------------------------------------- shell */
  .partners .wrap { padding-top: 0; padding-bottom: 0; }
  .partners .p-head  { padding: 92px 44px 0; }
  .partners .p-close { padding: 56px 44px 76px; }

  /* --------------------------------------------- head — the one centred one */
  .partners .chapter { justify-content: center; }
  .partners .chapter::before { content: ""; flex: 1; height: 1px; background: var(--rule); }
  .partners h2    { text-align: center; text-wrap: balance; max-width: 22ch; margin-inline: auto; }
  .partners .lede { text-align: center; max-width: 60ch; margin-inline: auto; }

  /* ---------------------------------------------------- shared drafting devices
     (integrator: identical text to the page-wide .whisper / .strip / .dogear
      block — dedupe against the shared copy and drop these three.) */
  .partners .whisper { font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em;
    text-transform: uppercase; color: var(--ink-faint); }
  .partners .strip { display: flex; justify-content: space-between; align-items: baseline; gap: 20px;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
    color: var(--ink-faint);
    border-top: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); padding-top: 9px; }
  .partners .strip .r { color: color-mix(in srgb, var(--ink) 40%, transparent); }
  .partners .dogear { position: absolute; right: -1px; top: -1px; width: 26px; height: 26px; z-index: 1;
    background: linear-gradient(225deg, var(--paper) 0 50%, transparent 50%); }
  .partners .dogear::after { content: ""; position: absolute; inset: 0; background:
    linear-gradient(225deg, transparent calc(50% - .5px), var(--rule) calc(50% - .5px) calc(50% + .5px), transparent calc(50% + .5px)); }

  /* ------------------------------------------------------------------ the band
     88% paper-hi: LIGHTER than the section's 62% wash, so the paper lifts
     instead of tinting. Never stronger, or the section reads as a card. */
  .partners .plan-band {
    width: 100%; margin-top: 52px; padding: 56px 0;
    background: color-mix(in srgb, var(--paper-hi) 88%, transparent);
    border-top: 1px solid var(--rule-soft); border-bottom: 1px solid var(--rule-soft);
  }

  /* ------------------------------------------------------- figure heading row */
  .partners .plan-head {
    max-width: 1112px; margin: 0 auto 24px;
    display: flex; align-items: center; justify-content: space-between; gap: 28px;
  }
  .partners .plan-head h3 {
    font-family: var(--display); font-weight: 700; font-size: 20px; line-height: 1.28;
    letter-spacing: .002em; max-width: 46ch;
  }
  .partners .plan-head .stamp-el { flex: none; color: var(--v3); padding: 7px 12px; }
  .partners .plan-head .stamp-el b { font-size: 11px; letter-spacing: .22em; font-weight: 400; }

  /* --------------------------------------------------------------- the sheet */
  .partners .plan {
    max-width: 1112px; margin: 0 auto; position: relative; background: var(--paper-hi);
    border: 1px solid color-mix(in srgb, var(--ink) 70%, transparent);
    box-shadow: var(--shadow-obj); padding: 38px 48px 0;
    transition: transform .35s cubic-bezier(.22,1,.36,1), translate .35s cubic-bezier(.22,1,.36,1), box-shadow .35s;
  }
  .partners .plan:hover { transform: translateY(-4px); }
  /* the sheet sits on the band, so its cut corner is the band's colour:
     88% paper-hi over the section's 62% wash resolves to ~95% paper-hi / 5% paper */
  .partners .plan .dogear { background: linear-gradient(225deg, color-mix(in srgb, var(--paper-hi) 95%, var(--paper)) 0 50%, transparent 50%); }

  /* the drawing area: the table runs the width of the sheet, the seating clusters
     sit on its centre line — a long table with only three seats drawn */
  .partners .plan-inner { max-width: none; margin: 0; }

  /* --- 1 · far side: three chairs that do not exist yet */
  .partners .far-side { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
  .partners .ghost-chairs { grid-column: 2; display: flex; gap: 18px; justify-content: center; }
  .partners .ghost-chairs i {
    width: 84px; height: 64px; display: block;
    border: 1px dashed color-mix(in srgb, var(--ink) 18%, transparent); border-radius: 6px;
    opacity: 0; transform: translateY(6px);
    transition: opacity .6s ease 1.05s, transform .6s cubic-bezier(.22,1,.36,1) 1.05s;
  }
  .partners .plan.on .ghost-chairs i { opacity: .38; transform: none; }
  .partners .far-side .stub-note {
    grid-column: 3; justify-self: stretch; display: flex; align-items: center; gap: 14px;
    font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase;
    color: var(--ink-faint); white-space: nowrap;
    opacity: 0; transition: opacity .6s ease 1.15s;
  }
  /* a leader off the last chair, so the note is annotated to it rather than floating */
  .partners .far-side .stub-note::before { content: ""; flex: 1; min-width: 22px; height: 1px; background: var(--rule-soft); }
  .partners .plan.on .far-side .stub-note { opacity: 1; }

  /* --- 2 · the table, plan view: a hatched void inside a dashed outline */
  .partners .table-plan {
    height: 120px; border-radius: 8px; margin: 26px 0;
    border: 1px dashed color-mix(in srgb, var(--v3) 45%, transparent);
    background: repeating-linear-gradient(45deg,
      color-mix(in srgb, var(--v1) 8%, transparent) 0 1px, transparent 1px 9px);
    display: grid; place-items: center;
    clip-path: inset(0 100% 0 0);
    transition: clip-path .7s cubic-bezier(.22,1,.36,1) .2s;
    animation: partners-crawl 3.8s linear infinite;   /* the one live thing: the dashes crawl */
  }
  .partners .plan.on .table-plan { clip-path: inset(0); }
  /* the label breaks the hatch, the way a drawing label breaks its own poché */
  .partners .table-plan .whisper { background: var(--paper-hi); padding: 3px 16px; }
  /* 25.456px = 2 × 9px hatch pitch along the 45° axis — a seamless loop */
  @keyframes partners-crawl { from { background-position: 0 0; } to { background-position: 25.456px 0; } }

  /* --- 3 · near side: the three seats that do exist */
  .partners .near-side { display: flex; gap: 18px; justify-content: center; }
  .partners .seat {
    width: 84px; height: 64px; padding: 0; position: relative; display: grid; place-items: center;
    background: color-mix(in srgb, var(--v3) 8%, var(--paper-hi));
    border: 1px solid color-mix(in srgb, var(--v3) 40%, transparent); border-radius: 6px;
    opacity: 0; transform: translateY(10px);
    transition: opacity .5s ease var(--d, 0s), transform .55s cubic-bezier(.22,1,.36,1) var(--d, 0s);
  }
  .partners .plan.on .seat { opacity: 1; transform: none; }
  .partners .seat b {
    position: absolute; left: 0; right: 0; bottom: 6px; text-align: center;
    font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; font-weight: 400;
    color: color-mix(in srgb, var(--v3) 62%, transparent);
  }
  .partners .seat .open-stamp {
    position: static; display: inline-block; border: 0; border-radius: 3px;
    background: color-mix(in srgb, var(--v3) 12%, transparent); color: var(--v3);
    font-family: var(--mono); font-size: 9px; letter-spacing: .14em; padding: 3px 8px;
    margin-bottom: 8px;
  }
  .partners .seat .open-stamp.thunk    { transform: scale(1.8) rotate(var(--rot, -8deg)); }
  .partners .seat .open-stamp.thunk.on { transform: scale(1) rotate(var(--rot, -8deg)); }

  /* --- 4 · the measure across the three tiles */
  .partners .plan-dim {
    max-width: none; width: 288px; margin: 22px auto 0; gap: 9px;
    transform: scaleX(0); transition: transform .7s cubic-bezier(.22,1,.36,1) .62s;
  }
  .partners .plan.on .plan-dim { transform: none; }
  .partners .plan-dim span { opacity: 0; transition: opacity .45s ease 1.2s; white-space: nowrap; }
  .partners .plan.on .plan-dim span { opacity: 1; }
  .partners .plan-dim i.long, .partners .plan-dim i.short { font-style: normal; }
  .partners .plan-dim i.short { display: none; }

  /* --- 5 · the bottom strip, edge to edge inside the sheet */
  .partners .plan .strip { margin: 34px -48px 0; padding: 9px 48px; }
  .partners .plan .strip i { font-style: normal; }
  .partners .plan .strip .ticket-eyebrow { display: inline; color: var(--ink-faint); font-size: inherit; letter-spacing: inherit; margin: 0; }
  .partners .plan .strip b { font-family: var(--mono); font-size: 10.5px; font-weight: 700; color: var(--v3); }
  .partners .plan .strip .lbl { font-family: inherit; font-size: inherit; letter-spacing: inherit; color: inherit; text-transform: inherit; }

  /* ------------------------------------------------- below the band: 12 cols */
  .partners .partner-close { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 40px; }

  .partners .perks {
    grid-column: 1 / span 6; display: block; margin: 0; counter-reset: perk;
    align-self: start;
  }
  .partners .perks li {
    list-style: none; counter-increment: perk;
    display: grid; grid-template-columns: 34px 1fr; column-gap: 14px; align-items: baseline;
    border-top: 1px solid var(--rule-soft); padding: 16px 0 14px;
    font-family: var(--body); font-size: 15px; line-height: 1.55; color: var(--ink-soft);
  }
  .partners .perks li:first-child { border-top: 1px solid var(--rule); }
  .partners .perks li::before {
    content: counter(perk, decimal-leading-zero);
    width: auto; height: auto; background: none; transform: none; flex: none;
    font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; color: var(--v3);
  }

  .partners .partner-ask { grid-column: 8 / span 5; align-self: start; }
  .partners .partner-ask .cta-row { margin-bottom: 0; flex-wrap: wrap; }
  .partners .fomo-line {
    text-align: left; margin-top: 22px; max-width: 44ch;
    font-size: 13.5px; line-height: 1.6; font-style: italic; color: var(--ink-soft);
  }
  .partners .fomo-line b { font-style: normal; color: var(--v4-ink); }

  /* ---------------------------------------------------------------- parallax
     (integrator: merge into the page-wide par-soft selector — .booklet, .plan) */
  @supports (animation-timeline: view()) {
    .partners .plan {
      animation: par-soft linear both; animation-timeline: view(); animation-range: entry 0% exit 100%;
    }
    .partners .plan:hover { transform: none; translate: 0 -4px; }
  }

  /* -------------------------------------------------------------- responsive */
  @media (max-width: 1024px) {
    .partners .partner-close { grid-template-columns: 1fr; gap: 34px; }
    .partners .perks, .partners .partner-ask { grid-column: 1; }
    .partners .fomo-line { max-width: 60ch; }
  }

  @media (max-width: 900px) {
    .partners .p-head  { padding-top: 74px; }
    .partners .p-close { padding-bottom: 64px; }
    .partners .plan-band { padding: 36px 0; margin-top: 40px; }
    .partners .plan-head { flex-direction: column; align-items: flex-start; gap: 14px; margin-bottom: 18px; }
    .partners .plan-head h3 { font-size: 18px; }
    .partners .plan { padding: 24px 18px 0; }
    .partners .plan .strip { margin: 26px -18px 0; padding: 9px 18px; flex-wrap: wrap; gap: 6px 16px; row-gap: 6px; }
    .partners .plan .strip .r { flex: none; }

    .partners .far-side { grid-template-columns: 1fr; justify-items: center; gap: 12px; }
    .partners .ghost-chairs { grid-column: 1; gap: 14px; }
    .partners .ghost-chairs i { width: 60px; height: 46px; }
    .partners .far-side .stub-note { grid-column: 1; justify-self: center; }
    .partners .far-side .stub-note::before { display: none; }   /* the leader has nothing to lead from */

    .partners .table-plan { height: 88px; margin: 20px 0; }

    .partners .near-side { gap: 14px; }
    .partners .seat { width: 60px; height: 46px; }
    .partners .seat .open-stamp { font-size: 7.5px; letter-spacing: .1em; padding: 2px 5px; margin-bottom: 7px; }
    .partners .seat b { font-size: 8px; bottom: 4px; }

    .partners .plan-dim { width: 208px; margin-top: 18px; gap: 7px; }
    .partners .plan-dim i.long  { display: none; }
    .partners .plan-dim i.short { display: inline; }
  }

  @media (max-width: 560px) {
    .partners .plan-head .stamp-el { display: none; }   /* its clear zone collapses */
    .partners .table-plan .whisper { font-size: 8.5px; letter-spacing: .16em; }
  }

  /* ---------------------------------------------------------- reduced motion
     everything at its final state — and the dashes stand still */
  @media (prefers-reduced-motion: reduce) {
    .partners .plan { animation: none !important; }
    .partners .table-plan { clip-path: none !important; animation: none !important; transition: none !important; }
    .partners .seat { opacity: 1 !important; transform: none !important; transition: none !important; }
    .partners .ghost-chairs i { opacity: .38 !important; transform: none !important; transition: none !important; }
    .partners .far-side .stub-note { opacity: 1 !important; transition: none !important; }
    .partners .plan-dim { transform: none !important; transition: none !important; }
    .partners .plan-dim span { opacity: 1 !important; transition: none !important; }
    .partners .seat .open-stamp.thunk { transform: rotate(var(--rot, -8deg)) !important; }
  }

/* ============================================ round three: colour, depth and proof
   Six leaf colours, a designed run, the installer, the difference, the proof sheet,
   and the depth layer last (it restates animation lists it must win). */

/* ------------------------------------------------ frag3-problem-six-colour */
/* ===================================================================
   01 · problem — THE SPECIMEN CARD
   Six leaves, six colours, one rule.

   The chapter already argued its case with a fold. What it could not do
   was say "there are six of these" before a word was read. It says it now
   in colour: a centred ±9° hue walk on the theme's own accent, six steps
   of 3.6°, generated by ONE relative-colour rule. L and C are held
   identical at every stop, so it is arithmetically impossible for one leaf
   to look more important than another — and the walk's midpoint IS the
   theme, so no theme leaves its own identity by leaf 06.

   The 0.92 on chroma is what makes that invariant TRUE rather than merely
   intended. Several themes park --v3 hard against the sRGB boundary, and a
   hue rotation walks it straight out: at full chroma seafoam's leaves 05
   and 06 resolve to color(srgb -0.077 …) and color(srgb -0.119 …), lime
   and glacier break at the other end, butter at +9. Chrome does not gamut-
   map those, it clips per channel — which pins saturation at 100% and
   crushes the last two steps together. Measured on seafoam before the
   scale: hue 147.0 → 153.6 → 158.9 → 164.0 → 166.4 → 168.3, i.e. steps of
   6.6, 5.3, 5.1, 2.4, 1.9 with saturation climbing 0.66 → 1.00. The walk
   died exactly where it was supposed to finish. 0.92 sits under the worst
   case across all nine themes (seafoam 0.938, lime 0.942, glacier 0.969,
   butter 0.983), so every stop lands inside sRGB, nothing is clipped, and
   the six steps are even. The cost is 8% chroma — invisible on its own,
   and it buys the equal-weight claim outright.

   --v5 is NEVER rotated. The warn hue is semantic (refused / wrong /
   danger), not a leaf identity; on the paper theme --v5 sits at hue 330.7
   and a rotation lands it in red, which is a veto breach.

   Degradation is honest, not clever: without relative colour every leaf is
   var(--v3) — the chapter exactly as it reads today. No lightness-step
   fallback; six lightness steps on a single-hue ramp read as an accident.
   =================================================================== */

/* ------------------------------------------------------- the one rule */
/* keyed off the IDs, never nth-of-type: .problem-caesura is also an <li>
   and would shift leaves 04–06 by one */
.problem #problem-01 { --hx: -9;   }
.problem #problem-02 { --hx: -5.4; }
.problem #problem-03 { --hx: -1.8; }
.problem #problem-04 { --hx:  1.8; }
.problem #problem-05 { --hx:  5.4; }
.problem #problem-06 { --hx:  9;   }

/* the folio is the same ruler, read down the margin */
.problem .problem-folio .rail-index li:nth-child(1) { --hx: -9;   }
.problem .problem-folio .rail-index li:nth-child(2) { --hx: -5.4; }
.problem .problem-folio .rail-index li:nth-child(3) { --hx: -1.8; }
.problem .problem-folio .rail-index li:nth-child(4) { --hx:  1.8; }
.problem .problem-folio .rail-index li:nth-child(5) { --hx:  5.4; }
.problem .problem-folio .rail-index li:nth-child(6) { --hx:  9;   }
/* the specimen row carries its own --hx inline, beside its stagger index */

/* base: all six identical — the calm, honest degradation */
.problem .problem-scene,
.problem .problem-specimen li,
.problem .problem-folio .rail-index li { --leaf: var(--v3); }

/* enhancement: one relative-colour rule generates all six.
   the unitless hue is mandatory — calc(h + 5.4deg) fails to parse and
   silently kills the colour. the 0.92 on c is the gamut guard, above. */
@supports (color: oklch(from red l c calc(h + 1))) {
  .problem .problem-scene,
  .problem .problem-specimen li,
  .problem .problem-folio .rail-index li {
    --leaf: oklch(from var(--v3) l calc(c * 0.92) calc(h + var(--hx, 0)));
  }
}

.problem .problem-scene {
  --leaf-rule:  color-mix(in srgb, var(--leaf) 34%, transparent);
  --leaf-hair:  color-mix(in srgb, var(--leaf) 16%, transparent);
  --leaf-ghost: color-mix(in srgb, var(--leaf) 55%, transparent);
}

/* ------------------------------------------------------- 1 · the chapter opening */
/* the header is the only place the chapter speaks in one voice; it should
   be the largest thing in it. Nothing else in the header moves — the
   fold-hd, the ghost 01 and its ±54px parallax stay exactly as they are. */
.problem .problem-overview h2 { font-size: clamp(44px, 4.6vw, 66px); line-height: 1.02; }

/* ------------------------------------------------------- 2 · the specimen row
   The chapter's contents page and its colour legend in one object. At 5.5%
   the wash on a leaf is invisible; the identity lives in the marks, and
   adjacency is the only place a 3.6° step reads. This row is where the six
   colours abut — six rules and six numerals on bare paper.
   No borders, no fills, no shadows, nothing joined by a line. This is the
   closest element in the chapter to a card grid and it must stay that way. */
/* the 34px foot is load-bearing, not padding. Leaf 01's folio numeral hangs
   14px into a 72px top padding, so a 6px foot left it 20px below this row and
   28px above its own kicker — it read as the tail of the specimen rather than
   the head of the leaf. Every other numeral sits 84px under the previous
   plate and 33px over its kicker; 34px here restores that ratio (48/28). */
.problem .problem-specimen {
  list-style: none; margin: 30px 0 34px;
  display: grid; grid-template-columns: repeat(6, 1fr); column-gap: 26px;
}
.problem .problem-specimen a { position: relative; display: block; }
.problem .problem-specimen i {
  display: block; height: 3px; background: var(--leaf);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .55s cubic-bezier(.22,1,.36,1) calc(var(--n) * .07s);
}
.problem .problem-specimen.rv.on i { transform: none; }
.problem .problem-specimen b {
  display: block; margin-top: 11px; font-family: var(--mono);
  font-weight: 400; font-size: 10.5px; letter-spacing: .22em; color: color-mix(in srgb, var(--leaf) 72%, var(--ink));
}
.problem .problem-specimen span {
  display: block; margin-top: 5px; font-family: var(--body);
  font-size: 13px; line-height: 1.35; color: var(--ink-soft); text-wrap: balance;
}
/* active state is layout-stable — a 1px underline, no height or weight
   change — so the row never jitters while the reader scrolls */
.problem .problem-specimen a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -9px;
  height: 1px; background: var(--leaf); transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .45s cubic-bezier(.22,1,.36,1);
}
.problem .problem-specimen a.is-active::after { transform: none; }

/* ------------------------------------------------------- 3 · the fold takes the colour
   The tallest graphic object on each leaf — a ~700px vertical line — is
   that leaf's colour. Its existing .75s downward draw is untouched and now
   draws in colour. This is the move. */
.problem .leaf-fold { background: var(--leaf-rule); top: 72px; }

/* ------------------------------------------------------- 4 · the per-leaf folio numeral
   A folio, not a headline. It hangs on the fold's head, centred, so it
   never collides with either kicker (verso ends at 50%−52px, recto starts
   at 50%+52px). It fades with its .rv parent only — no transform, no
   parallax, nothing that could fight the hinge. */
.problem .problem-scene { padding: 72px 0 64px; }
.problem .leaf-n {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  font-family: var(--display); font-weight: 700; font-size: 30px; line-height: 1; letter-spacing: .06em;
  color: transparent; -webkit-text-stroke: 1px var(--leaf-ghost); pointer-events: none;
}
@supports not (-webkit-text-stroke: 1px red) { .problem .leaf-n { color: var(--leaf-ghost); } }

/* ------------------------------------------------------- 5 · the wash, as a background
   NOT a ::before with z-index:-1 — .problem-scene carries a perspective in
   the depth layer, which makes it a stacking context and would trap a
   negative-z pseudo inside it. A background has no stacking behaviour and
   cannot break. Radial feathering also removes the mask entirely: no
   vertical seam at either end.
   5.5% is deliberate — 6% is a whisper, 11% starts to read as a card,
   16% is a coloured panel. The field stays under the threshold where it
   could shout. (Replaces .problem-scene--wash::before, deleted.) */
.problem .problem-scene {
  background: radial-gradient(118% 62% at 50% 46%,
    color-mix(in srgb, var(--leaf) 13%, transparent), transparent 78%)
    no-repeat 50% 0 / var(--plate-w) 100%;
}

/* ------------------------------------------------------- 6 · kickers, captions, rules
   Both sides of the fold take the colour — the fold's whole argument is
   that they are equals. The FIG title strips, balloons and frames stay
   ink: the drafting furniture never changes colour, only the drawing does. */
.problem .problem-scene__category,
.problem .leaf-recto > span,
.problem .problem-figure--fox .figure-heading span { color: color-mix(in srgb, var(--leaf) 72%, var(--ink)); }
.problem .figure-heading { border-top-color: var(--leaf-hair); }

/* ------------------------------------------------------- 7 · the folio as a six-colour ruler */
.problem .problem-folio .rail-index a i { background: color-mix(in srgb, var(--leaf) 40%, transparent); }
.problem .problem-folio .rail-index a.is-active { color: color-mix(in srgb, var(--leaf) 72%, var(--ink)); }
.problem .problem-folio .rail-index a.is-active i { width: 30px; background: var(--leaf); }

/* ------------------------------------------------------- 8 · the drawings
   The same token block, mechanically, with --leaf substituted for --v3 at
   identical percentages. Every --v5-derived token is left alone, so the
   warn language is the same on all six leaves. Both plates recolour
   together, so the fold's symmetry holds. */
.problem .problem-scene .bp .sc {
  --ln-focus:       color-mix(in srgb, var(--leaf) 45%, transparent);
  --ln-tile:        color-mix(in srgb, var(--leaf) 40%, transparent);
  --ln-acc:         color-mix(in srgb, var(--leaf) 35%, transparent);
  --fl-tile:        color-mix(in srgb, var(--leaf) 8%,  var(--paper-hi));
  --fl-tile-strong: color-mix(in srgb, var(--leaf) 14%, var(--paper-hi));
  --fl-badge:       color-mix(in srgb, var(--leaf) 12%, var(--paper-hi));
  --halo:           color-mix(in srgb, var(--leaf) 20%, transparent);
  --tx-acc:         color-mix(in srgb, var(--leaf) 85%, transparent);
}
.problem .problem-scene .bp .sc .ico.acc { color: var(--leaf); }
.problem .problem-scene .bp .sc .pill.solid { fill: var(--leaf); }
.problem .problem-scene .bp .sc .okdot { fill: var(--leaf); }
.problem .problem-scene .bp .sc .dot.acc { fill: color-mix(in srgb, var(--leaf) 55%, transparent); }
.problem .problem-scene .bp .sc .tok { color: var(--leaf); }
.problem .problem-scene .bp .sc .tok-card {
  fill: color-mix(in srgb, var(--leaf) 28%, var(--paper-hi));
  stroke: color-mix(in srgb, var(--leaf) 55%, transparent);
}

/* 9 · the caesura and the foundation stay colourless. The pause between 03
   and 04 is the one place the chapter stops being six things. Untouched. */

/* ------------------------------------------------------- motion: one new beat
   Six bars draw left-to-right, 70ms apart — 350ms of total stagger, then it
   is over. Nothing loops, nothing else is added. */
/* The six bars are decoration and sit drawn. The underline keeps its meaning
   and simply stops sliding — site.js runs its first activate(cards[0]) before
   the reduced-motion early return, so leaf 01 is marked and stays marked,
   exactly as the margin folio behaves. Lighting all six underlines instead
   would give the row six active states at once. */
@media (prefers-reduced-motion: reduce) {
  .problem .problem-specimen i { transform: none !important; transition: none !important; }
  .problem .problem-specimen a::after { transition: none !important; }
}

/* ------------------------------------------------------- responsive */
/* ≥1421 folio + 6-up specimen. 1081–1420 the folio hides (existing rule)
   and the specimen becomes the only index — 1112/6 = 185px a cell, still 6-up. */

@media (max-width: 1080px) {
  /* the leaf collapses to one column and .leaf-fold hides, so the colour
     spine goes with it — recover it in the numeral and the recto's rule */
  /* row-gap must clear the active underline, which hangs 9px below its cell
     and can land in the same column as the next row's bar: at 20px that left
     11px of real air and the underline read as the next cell's rule. 34px
     keeps 25px clear with the marker lit, which is the structural minimum. */
  .problem .problem-specimen { grid-template-columns: repeat(3, 1fr); row-gap: 34px; }
  .problem .problem-scene { padding: 44px 0 48px; }
  .problem .leaf-n {
    position: static; display: block; transform: none;
    font-size: 24px; margin-bottom: 10px; order: 0; grid-column: 1;
  }
  .problem .leaf-recto { border-top-color: var(--leaf-rule); }
}

@media (max-width: 640px) {
  .problem .problem-specimen { grid-template-columns: repeat(2, 1fr); }
  .problem .problem-overview h2 { font-size: clamp(34px, 4.6vw, 66px); }
  .problem .leaf-n { font-size: 20px; }
}

/* ------------------------------------------------ frag3-spine */
/* ---------------------------------------------- [spine] */
/* ================================================ 04 · under the hood — THE MEASURED RUN
   One drawing, twice: a dimension line across the top (the tape) and the same line
   rotated down the page (the descent). A dimension line is complete the instant it is
   drawn — datum, station ticks, terminators, names. Nothing here is ever "unfinished";
   there is only a distance not yet walked. What the reader's scroll moves is a 1px
   marker and an inked length, never the object's presence.
   Tokens + color-mix only. No hex. */

/* the section is its own drawing surface. overflow MUST stay visible:
   `section { overflow: hidden }` (site.css:149) makes the section a scrollport and
   silently kills the sticky tape, which drops the tracker onto its innerHeight branch. */
.spine { position: relative; overflow: visible; background: transparent; border-top: 3px double var(--rule); }
/* the ghost goes to the LEFT margin, behind the Didot — not to the right shoulder.
   This chapter's head is a spread and column 2 is the note margin, so the right
   shoulder is where the lede lives; a 320px outline behind 16px Charter is a
   collision, not a watermark. Behind a 60px heading it is a watermark, which is
   exactly how [06] install and [08] ecosystem already place theirs. */
.spine .ghost-n { top: 34px; right: auto; left: max(48px, calc((100vw - 1200px) / 2)); }

/* ------------------------------------------------------------ head armature
   7fr / 5fr with a 64px gutter — the armature the whole chapter is built on:
   the heading holds the measure, the lede sits in the note margin, and the strap
   is the tape's own title, ruled out to the right edge. */
.spine .sp-head {
  padding: 92px 44px 24px; position: relative; z-index: 1;   /* over the ghost numeral */
  display: grid; grid-template-columns: minmax(0, 7fr) 5fr;
  column-gap: 64px; align-items: end;
}
.spine .sp-head .chapter { grid-column: 1 / -1; margin-bottom: 22px; }
.spine .sp-head h2 { grid-column: 1; max-width: 16ch; margin-bottom: 0; }
.spine .sp-head .lede {
  grid-column: 2; align-self: end; max-width: 46ch;
  font-size: 16px; line-height: 1.6; padding-bottom: 5px; text-wrap: pretty;
}
.spine .sp-strap {
  grid-column: 1 / -1; margin: 54px 0 0;
  display: flex; align-items: center; gap: 12px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-faint);
}
.spine .sp-strap::after { content: ""; flex: 1; height: 1px; background: var(--rule-soft); }
.spine .sp-strap b { font-weight: 400; color: var(--ink-soft); }

/* ------------------------------------------------------------------ the tape
   A LINE, not a strip: no top border, no card, one hairline foot. It pins under the
   65px nav (64px bar + 1px rule) at a fixed 120px, which makes the tracker's read
   line the constant 65 + 120 + 200 = 385px. */
.spine .sp-tape {
  position: sticky; top: 65px; z-index: 5;
  width: 100%; height: 120px;
  background: color-mix(in srgb, var(--paper-hi) 92%, var(--paper));
  border-bottom: 1px solid var(--rule);
  box-shadow: var(--shadow-card);
}
.spine .tape-in {
  max-width: 1200px; margin: 0 auto; padding: 11px 44px; height: 100%;
  display: flex; flex-direction: column; gap: 8px; position: relative;
}
/* the caption is the dimension's own label: two terminators and the run between them.
   The words are the page's own — lifted from .sp-dim, which restates the same span as
   the chapter's closing dimension. A drawing may carry the same measure twice; the
   caption annotates the instrument, the closing dim states the whole. */
.spine .tape-cap {
  display: flex; align-items: center; gap: 10px; margin: 0;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-faint);
}
.spine .tape-cap .tick { width: 1px; height: 9px; background: var(--rule); flex: none; }
.spine .tape-cap .leader { margin: 0 4px; }   /* shared .leader; draws once on .rv.on */

/* ---------------------------------------------------------------- the chain
   Six equal intervals on one rule. Each station's tick opens its own interval and its
   name is written inside it, so the inked length is "interval walked", never "the next
   station is done". The run ends on a terminator at 100%, which is the DONE end. */
.spine .sp-chain {
  position: relative; flex: 1; min-height: 0;
  display: grid; grid-template-columns: repeat(6, 1fr); align-items: start;
}
.spine .sp-chain::before {
  content: ""; position: absolute; left: 0; right: 0; top: 26px; height: 1px;
  background: var(--rule);
}
.spine .sp-chain::after {
  content: ""; position: absolute; left: 0; top: 26px; height: 1px;
  width: calc(var(--i, 0) / 6 * 100%);
  background: var(--v3); opacity: .58;
  transition: width .55s cubic-bezier(.22, 1, .36, 1);
}

/* .sp-chain in the selector on purpose: it outranks the 2015-era .sp-line flex block at
   site.css:349–353 and the orphaned tape overrides at 1839–1860 even if either survives
   the pass. Both are on the delete list; this is the belt as well as the braces. */
.spine .sp-chain .sp-line {
  position: relative; display: grid;
  grid-template-columns: auto 1fr; grid-template-rows: auto 32px auto;
  gap: 0 8px;   /* row-gap 0 explicitly: the 2015-era .sp-line flex rule sets gap:10px */
  align-items: baseline; align-content: start;
  padding: 0 20px 0 0; margin: 0;
  opacity: 1; transform: none; border: 0;
}
.spine .sp-chain .sp-line::before {
  content: ""; position: absolute; left: 0; top: 22px; bottom: auto;
  width: 1px; height: 9px; background: var(--rule);
  transition: background .45s ease, height .45s ease;
}
.spine .sp-chain .sp-line.printed::before { background: var(--v3); height: 13px; }
/* the far terminator — the drawing closes on DONE, not on the sixth station */
.spine .sp-chain .sp-line:last-of-type::after {
  content: ""; position: absolute; right: 0; top: 22px;
  width: 1px; height: 9px; background: var(--rule);
  transition: background .45s ease, height .45s ease;
}
.spine .sp-chain .sp-line:last-of-type.printed::after { background: var(--v3); height: 13px; }

/* the names are part of the drawing and are legible before anything prints —
   that is the whole idea. Only the value is a measurement, so only it waits. */
.spine .sp-chain .sp-line .n {
  grid-column: 1; grid-row: 1; width: auto; flex: none;
  font-family: var(--mono); font-size: 10px; line-height: 1; letter-spacing: .16em;
  color: color-mix(in srgb, var(--v3) 50%, transparent);
  transition: color .45s ease;
}
.spine .sp-chain .sp-line .s {
  grid-column: 2; grid-row: 1; width: auto; flex: none;
  font-family: var(--mono); font-size: 11.5px; line-height: 1; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft);
  transition: color .45s ease;
}
.spine .sp-chain .sp-line .d {
  grid-column: 1 / -1; grid-row: 3; min-height: 30px;   /* 2 × (10.5 × 1.4) — one reserved measure */
  font-family: var(--mono); font-size: 10.5px; line-height: 1.4; color: var(--ink-faint);
  opacity: 0; transform: translateY(2px);
  transition: opacity .45s ease, transform .45s ease;
}
.spine .sp-chain .sp-line.printed .n { color: var(--v3); }
.spine .sp-chain .sp-line.printed .s { color: var(--ink); }
.spine .sp-chain .sp-line.printed .d { opacity: 1; transform: none; }

/* the chainage marker — a nib whose apex meets the rule, and a stem that runs down
   through the values row: the marker IS the boundary between what has printed and what
   has not. It is parked at DO THIS until the read moves it. It never enters the label
   row, so it can sit on a station's tick without touching that station's name. */
.spine .tape-in .printhead { position: absolute; left: 0; right: 0; top: 0; bottom: 0; pointer-events: none; }
.spine .tape-in .printhead > i {
  position: absolute; top: 26px; bottom: 10px; width: 1px; background: var(--v3);
  left: calc(var(--i, 0) / 6 * 100%);
  transition: left .55s cubic-bezier(.22, 1, .36, 1);
}
.spine .tape-in .printhead > i::before {
  content: ""; position: absolute; top: -5px; left: 50%; transform: translateX(-50%);
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--v3);
}

/* ============================================================== the descent
   the same chain, rotated: a datum rail down the gutter, one station tick per entry,
   the value the tape printed repeated as the entry's first line. */
/* the tape's sticky container holds the tape and the six stations and nothing else.
   Measured, not assumed: the container's bottom reaches the tape's pinned bottom (185)
   exactly as the close's own rule arrives at 185 + 54 = 239 — reading height. The tape
   lifts off the top edge on the same scroll beat the seal lands. (It is opaque and the
   close sits far below it on the way in; nothing is ever read THROUGH it.) */
.spine .sp-run { position: relative; }
.spine .sp-body { padding: 92px 44px 0; position: relative; z-index: 1; }
/* 54 + the last stage's own 38 = 92, the same open the register got at the top (the
   .sp-body padding). At 38 the closing rule fell on the station divider's own rhythm
   and read as a seventh entry; at 92 it is a different order of division, so it reads
   as the end of the chapter. It also puts the close at reading height on the same
   scroll beat the tape releases — see .sp-run above. */
.spine .sp-close { padding: 54px 44px 96px; position: relative; z-index: 1; }
.spine .sp-stages { display: block; position: relative; margin-top: 0; }

/* identical armature to .sp-head: 7fr / 5fr, 64px gutter.
   At 1112px of content that is a 611px measure and a 437px note margin,
   and the note starts exactly where the lede starts. */
.spine .sp-stage {
  display: grid; grid-template-columns: minmax(0, 7fr) 5fr;
  column-gap: 64px; row-gap: 0;
  align-items: start;
  position: relative; margin: 0; padding: 0 0 38px;
  border: 0; background: none;
}
.spine .sp-stage:first-child { border-top: 0; }

/* the rail is drawn interval by interval — from this station's tick to the next one's —
   so it can never overshoot the first or the last tick at any wrap. */
.spine .sp-stage::after {
  content: ""; position: absolute; left: 56px; top: 36px; height: 100%; width: 1px;
  background: var(--rule);   /* the same weight as the tape's rule — it is the same line */
}
.spine .sp-stage:last-child::after { display: none; }
/* the station tick: the tape's tick rotated a quarter turn — 9px, growing to 13px
   toward the entry it marks, and only when that entry is the live one. */
.spine .sp-stage::before {
  content: ""; display: block; position: absolute; left: 52px; top: 36px;
  width: 9px; height: 1px; background: var(--rule);
  transition: width .45s cubic-bezier(.22, 1, .36, 1), background .45s ease;
}

/* column 1 — the prose. The folio hangs out of flow in the same gutter as the rail,
   so all six paragraphs share ONE straight left edge. */
.spine .sp-say {
  position: relative;
  padding-left: 74px; padding-top: 28px;
  border-top: 1px solid var(--rule-soft);
}
/* the value the tape printed for this station, verbatim — the tape's line and the
   page's entry are one reading, not two. */
.spine .sp-say .val {
  display: block; font-family: var(--mono); font-size: 10.5px; line-height: 1.5;
  letter-spacing: .06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--v3) 60%, transparent);
  margin-bottom: 9px; transition: color .5s ease;
}
/* the hanging folio shares the heading's BASELINE, not its cap-line — measured, not
   guessed: at 34px Didot over a 26px Didot, 47.75px puts the two baselines on 75.75px. */
.spine .sp-stage .n {
  position: absolute; left: 0; top: 47.75px; width: auto; padding-top: 0;
  font-family: var(--display); font-weight: 400; font-size: 34px; line-height: 1;
  color: var(--ink-faint); transition: color .5s ease;
}
.spine .sp-stage h3 {
  font-family: var(--display); font-weight: 400; font-size: 26px; line-height: 1.15;
  color: var(--ink); text-indent: 0; margin: 0 0 10px;
}
.spine .sp-stage .plain {
  font-family: var(--body); font-size: 17.5px; line-height: 1.62;
  color: var(--ink); max-width: 46ch; margin: 0; text-wrap: pretty;
}

/* column 2 — the sidenote margin: subordinate, never grey filler in the measure.
   The 14px hair is a REGISTRATION mark: it lands exactly on the prose's hairline and
   carries it into the margin, so one datum crosses the whole spread. */
.spine .sp-stage .tech {
  position: relative;
  /* 25px puts the note's FIRST baseline on 40px — the same baseline as the entry's
     value line, so one datum crosses the spread: tick · value ——— hair · note */
  padding-top: 25px; max-width: 320px; margin: 0;
  font-family: var(--body); font-size: 13px; line-height: 1.6;
  color: var(--ink-faint); overflow-wrap: anywhere;
}
.spine .sp-stage .tech::before {
  content: ""; position: absolute; top: 0; left: 0; width: 14px; height: 1px;
  background: var(--v3); opacity: .45; margin: 0;
  transition: opacity .5s ease;
}
.spine .sp-stage code {
  font-family: var(--mono); font-size: 11px; color: var(--v3);
  border-bottom: 1px dotted var(--v3); padding-bottom: 1px; overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------ the close */
.spine .sp-foot {
  display: grid; grid-template-columns: minmax(0, 7fr) 5fr;
  gap: 0 64px; align-items: start; justify-content: initial;
  padding-top: 0;
}
.spine .sp-foot .rc-row {
  grid-row: 1; grid-column: 1; width: auto; flex: none;
  border-top: 1px solid var(--rule); padding-top: 22px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
}
.spine .sp-foot .rc-row .k { color: var(--ink-faint); text-transform: uppercase; letter-spacing: .18em; }
.spine .sp-foot .rc-row .val { color: var(--ink); }
.spine .sp-foot .stamp-el.settled2 {
  grid-row: 1; grid-column: 2; justify-self: start; align-self: start;
  position: static; margin-top: 6px; color: var(--v4-ink); --rot: -7deg; flex: none;
}
.spine .sp-foot .stamp-el.settled2 { transform: scale(1.25) rotate(var(--rot, -7deg)); filter: none; }
.spine .sp-foot .stamp-el.settled2.on { transform: scale(1) rotate(var(--rot, -7deg)); }

.spine .sp-dim { max-width: none; margin: 52px 0 0; }

/* ------------------------------------------ tracked state (not animation)
   it moves only when the reader moves, and it walks back down on reverse scroll */
.spine .sp-stage.live::before { width: 13px; background: var(--v3); }
.spine .sp-stage.live .n { color: var(--v3); }
.spine .sp-stage.live .val { color: var(--v3); }
.spine .sp-stage.live .tech::before { opacity: 1; }

/* -------------------------------------------------------------- responsive */
@media (max-width: 1360px) {
  .spine .sp-chain .sp-line .s { font-size: 11px; }
  .spine .sp-chain .sp-line .d { font-size: 10px; }
}
@media (max-width: 1080px) {
  /* the tape is static here — mandatory: the tracker reads its computed position and
     falls to its innerHeight * .62 branch when it is not sticky. A static register,
     not a chain: no rule, no ink, no marker, and every value on the sheet, because at
     this width the register is read once, above the descent, and never again. */
  .spine .sp-tape { position: static; height: auto; box-shadow: none; }
  .spine .tape-in { padding: 22px 44px 24px; gap: 0; }
  .spine .tape-cap { display: none; }
  .spine .sp-chain {
    grid-template-columns: repeat(2, 1fr); column-gap: 30px; row-gap: 18px;
  }
  .spine .sp-chain::before, .spine .sp-chain::after,
  .spine .tape-in .printhead { display: none; }
  .spine .sp-chain .sp-line {
    grid-template-rows: auto 7px auto; padding: 0 0 0 13px;
    border-left: 1px solid var(--rule-soft);
  }
  .spine .sp-chain .sp-line::before,
  .spine .sp-chain .sp-line:last-of-type::after { display: none; }
  .spine .sp-chain .sp-line .d { min-height: 0; opacity: 1; transform: none; }
}
/* the SPREAD holds to 940, not to 1080 — one breakpoint for the whole chapter, the
   same one the head folds on. At 1000px the 7fr column is still a 421px measure and
   the 5fr note margin is still 337px, so folding there only bought a full-measure
   hairline sitting over a half-measure paragraph with 500px of nothing beside it. */
@media (max-width: 940px) {
  .spine .sp-head { grid-template-columns: 1fr; }
  .spine .sp-head h2 { max-width: 22ch; margin-bottom: 18px; }
  .spine .sp-head .lede { grid-column: 1; max-width: 60ch; padding-bottom: 0; }
  .spine .sp-strap { margin-top: 38px; }

  .spine .sp-close { padding-bottom: 76px; }
  /* one column: the rail goes, the folio keeps its own gutter, and the note tucks
     under the prose on the same edge with its 14px hair as the register divider */
  .spine .sp-stage { grid-template-columns: 1fr; }
  .spine .sp-stage::before, .spine .sp-stage::after { display: none; }
  .spine .sp-stage .tech { padding-top: 0; margin-top: 14px; padding-left: 74px; max-width: 46ch; }
  .spine .sp-stage .tech::before { position: static; margin-bottom: 13px; }
  .spine .sp-foot { grid-template-columns: 1fr; row-gap: 44px; }
  .spine .sp-foot .stamp-el.settled2 { grid-row: 1; grid-column: 1; margin-top: 0; }
  .spine .sp-foot .rc-row { grid-row: 2; grid-column: 1; width: auto; }
}
@media (max-width: 700px) {
  .spine .sp-head { padding: 64px 24px 22px; }
  /* at 342px of measure the strap breaks inside both of its words — it has to come
     down a step so it stays one line with its rule */
  .spine .sp-strap { font-size: 9.5px; letter-spacing: .16em; gap: 8px; margin-top: 34px; }
  .spine .sp-body { padding: 64px 24px 0; }
  /* 32 + the last stage's 32 = 64, mirroring .sp-body's open at this width exactly as
     54 + 38 = 92 mirrors it above. The shorthand has to restate the top, or it zeroes
     the gap the close was given and the seal lands back on the last entry. */
  .spine .sp-close { padding: 32px 24px 76px; }
  .spine .tape-in { padding: 20px 24px 22px; }
  .spine .sp-say { padding-left: 54px; padding-top: 24px; }
  .spine .sp-stage .n { font-size: 28px; top: 45.75px; }   /* same shared baseline, 28 vs 22 */
  .spine .sp-stage h3 { font-size: 22px; }
  .spine .sp-stage .plain { font-size: 16.5px; }
  .spine .sp-stage .tech { padding-left: 54px; }
  .spine .sp-stage { padding-bottom: 32px; }
  .spine .sp-foot .rc-row { width: auto; }
  .spine .sp-foot .stamp-el.settled2.thunk.on { transform: scale(.85) rotate(var(--rot, -7deg)); }
}
@media (max-width: 560px) {
  /* two columns stop paying at 241px of measure — the register goes to one file */
  .spine .sp-chain { grid-template-columns: 1fr; row-gap: 14px; }
}
@media (max-width: 470px) {
  /* the folio is a direct child of the stage now, so the stage takes the rule and the
     folio sits under it, with its own entry — not stranded above the divider */
  .spine .sp-stage,
  .spine .sp-stage:first-child { border-top: 1px solid var(--rule-soft); padding-top: 22px; }
  .spine .sp-say { border-top: 0; padding-top: 0; padding-left: 0; }
  .spine .sp-stage .n { position: static; display: block; font-size: 26px; margin-bottom: 4px; }
  .spine .sp-stage .tech { padding-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .spine .sp-chain::after,
  .spine .tape-in .printhead > i,
  .spine .sp-chain .sp-line::before,
  .spine .sp-chain .sp-line:last-of-type::after,
  .spine .sp-chain .sp-line .n,
  .spine .sp-chain .sp-line .s,
  .spine .sp-chain .sp-line .d,
  .spine .sp-stage::before,
  .spine .sp-stage .n,
  .spine .sp-say .val,
  .spine .sp-stage .tech::before { transition: none; }
}

/* ------------------------------------------------ frag3-install */
/* ================================================== 06 · INSTALL
   TWO LEAVES, ONE INDENT.

   The chapter's largest object used to be `./foxora up` — step TWO of an
   install. The sheet showed the run and hid the install. So: two numbered
   leaves on one hanging indent. 01 is the one-liner, set at the largest size
   on the sheet and real selectable text from first paint. 02 is the boot,
   demoted, still typing, still ticking.

   Every device here already exists on the page — .strip head, .leader,
   dotted rule, hanging indent. Exactly one element is new: the copy control.
   Tokens only; no hex, no raw rgba, nothing heavier than 1px.
   Appended after site.css:2179+, so it out-ranks the old block on ties. */

.install { --gut: 46px; }

/* ------------------------------------------------------------- the leaves
   One indent governs both. The second leaf's running head is lighter than the
   first, so the sheet reads as one procedure with a subordinate step and not as
   a ladder of equal rules.

   The weight is 22%, not the 16% first drawn: measured off the render, ink 30%
   lands at luminance 174 on this paper, 16% at 203 and the boot rows' own 13%
   at 213 — so at 16% leaf 2's HEAD was only ten levels darker than the rows it
   governs, and the ladder flattened exactly where the spec warned it would.
   22% sits at ~188: clearly under leaf 1, clearly over its own rows. */
.install .leaf + .leaf { margin-top: 54px; }
.install .strip.sub-head { border-top-color: color-mix(in srgb, var(--ink) 22%, transparent); }

/* --------------------------------------------------------- the command line
   Three columns: the folio, the measure, the control. The control lives in
   its own `auto` track so it is beside the measure, never inside it. */
.install .cmdline {
  display: grid; grid-template-columns: var(--gut) 1fr auto;
  align-items: baseline; margin-top: 30px;
}
.install .ln {
  font-family: var(--mono); font-size: 11px; letter-spacing: .2em; line-height: 1;
  color: color-mix(in srgb, var(--v3) 62%, transparent);
}

/* step 01 — the gesture, at the top of the size ladder.
   MEASURED, not estimated. At 1600 the inner measure is 1112; the folio takes
   46 and the copy control takes 102 including its margin, so the line's own
   track is 964px — NOT the full 1112. The line costs 23.04em (38 chars at
   -.02em, plus the `$` and its .34em margin), so the ceiling is:
       44px → 1014px  wraps
       42px →  968px  fits by −4px — wraps
       40px →  922px  fits by 42px  ← this one
   The vw coefficient is 3.2, not the 3.4 first drawn: at 3.4 the line and its
   control were 4.3px apart at vw 975 (measured, not modelled), i.e. the sheet
   was one font-metric hair from breaking its own headline in two. 3.2 holds
   ≥42px of slack at EVERY width the three-column row is on (see the
   responsive block); the size at 1440 and above is unchanged at 40px. */
.install .in.one {
  margin: 0; font-family: var(--mono); font-weight: 400;
  font-size: clamp(16px, 3.2vw, 40px); line-height: 1.08; letter-spacing: -.02em;
  color: var(--ink);
  /* the hanging indent is inert at every width where the line does not wrap;
     at 390 it wraps once and breaks the way a shell user reads a pipeline */
  text-indent: -1.95ch; padding-left: 1.95ch;
}
.install .in.one i {
  font-style: normal; margin-right: .34em;
  color: color-mix(in srgb, var(--v3) 58%, transparent);
}
.install .in.one .cmd { overflow-wrap: break-word; }
/* the pipeline's tail is one token. Without this the only break opportunity the
   browser takes at 390 orphans the `|` at the end of line one; held together,
   the line breaks where a shell user reads it:
       $ curl -fsSL https://get.foxora.dev
           | sh                                                              */
.install .in.one .pipe { white-space: nowrap; }

/* step 02 — demoted. It is a consequence of 01, not a rival to it. */
.install .in { margin-top: 0; font-size: clamp(20px, 2.4vw, 31px); line-height: 1.08; }

/* ------------------------------------------------------- the placeholder mark
   The host does not exist yet (docs/BACKLOG.md Phase 1, E1-E2). The command is
   still printed in full and pasteable, because a command you cannot read is no
   use — so the domain carries THREE marks: a dagger, the page's own dotted rule
   under it, and the [not live yet] token in the note directly beneath. Remove
   any one of them and the page stops being true. */
.install .ph { position: relative; }
.install .ph::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.16em; height: 1px;
  background: radial-gradient(circle, color-mix(in srgb, var(--v4) 92%, transparent) .85px, transparent 1px) 0 50%/4.5px 1px repeat-x;
}
.install .ph::before {
  content: "\2020"; position: absolute; top: -.30em; right: -.66em; font-size: .32em;
  letter-spacing: 0; color: color-mix(in srgb, var(--v4) 92%, transparent);
}

/* ------------------------------------------------------------------ the note
   Hangs off the same indent as the measure, so it reads as a footnote to the
   line above it and not as a caption to the sheet. */
.install .foot-n {
  margin: 20px 0 0; padding-left: var(--gut); max-width: 64ch;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.8;
  letter-spacing: .02em; color: var(--ink-soft);
}
.install .foot-n b { color: color-mix(in srgb, var(--v4) 78%, transparent); margin-right: .7em; font-weight: 400; }
.install .foot-n .gate { color: color-mix(in srgb, var(--v4) 85%, transparent); margin-right: .5em; }
/* the requirements are a SECOND note, not the tail of the first: one is a
   launch gate, the other is what the command needs. Set solid they read as one
   five-line lump, and the faintness alone is too small a step to separate them
   — so they get half a line of air. */
.install .foot-n .req { display: block; margin-top: 9px; color: var(--ink-faint); }
/* the two paths are the load-bearing part of that sentence, so they step up one
   tone — to --ink-soft, not all the way to --ink, which punched a hole in a line
   that is deliberately faint */
.install .foot-n code { font-family: inherit; font-size: inherit; color: var(--ink-soft); background: none; padding: 0; }

/* ------------------------------------------------------------ the copy control
   The one new element on the sheet. Outlined, mono, the size of a marginal
   label — it must not compete with the line it serves. Its only motion is a
   180ms colour/label crossfade: no toast, no lift, no icon swap.

   THE WIDTH IS FIXED, and that is the load-bearing declaration here. The
   control sits in the command row's `auto` track, so its width is subtracted
   from the track the 40px line is set in. COPY measures 60.9px and COPIED
   77.3px; without the floor, clicking it stole 16.4px from the line and — at
   vw 975 — wrapped the headline command in two and dropped the whole sheet
   36px. A control that reflows the thing it serves is not a control. 7.8em of
   its own 10px = 78px, the wider label's measured box, so both labels centre
   in one box and the grid never moves. */
.install .cpy {
  align-self: start; margin: .3em 0 0 24px; cursor: pointer;
  min-width: 7.8em;
  font-family: var(--mono); font-size: 10px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-soft); background: transparent; border-radius: 2px;
  border: 1px solid color-mix(in srgb, var(--ink) 26%, transparent); padding: 8px 13px;
  white-space: nowrap;
  transition: color .18s, border-color .18s, background .18s;
}
.install .cpy:hover { color: var(--v3); border-color: color-mix(in srgb, var(--v3) 55%, transparent); }
.install .cpy:focus-visible { outline: 2px solid color-mix(in srgb, var(--v3) 55%, transparent); outline-offset: 2px; }
.install .cpy.done {
  color: var(--v3); border-color: color-mix(in srgb, var(--v3) 55%, transparent);
  background: color-mix(in srgb, var(--v3) 7%, transparent);
}

/* the existing ./foxora up button copies too. Its LABEL never changes — it is
   the command — so the confirmation is a token that fades in UNDER the row.

   It is taken out of flow deliberately. `.btn` is a flex box with `gap: 9px`,
   so a ::after that is a flex item costs 9px of gap even at zero width: the
   button sat 21px/30px lopsided at rest (measured 142.4px against a natural
   133.4px), and growing it on click shoved `Deploy to a platform` 45.7px to
   the right. Absolute, it is not a flex item: no gap, no growth, no shove.
   Anchored to .cta-row rather than the button so that when the row wraps on a
   phone the token still lands under the WHOLE row, on clear paper. */
.install .cta-row { position: relative; }
.install #copy-btn::after {
  content: "copied"; position: absolute; left: 1px; top: calc(100% + 11px);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-faint); white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity .18s;
}
.install #copy-btn.copied::after { opacity: 1; }

.install .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ------------------------------------------------------------------- motion
   Zero new transforms. Leaf 01 arrives on the .rv already on .cmd-band, its
   .leader sweeps at .26s, leaf 02's at .34s, and the existing observer then
   runs untouched: ./foxora up types at 62ms/char and the boot ticks in pairs.
   Reading order: install line → rule → prompt types → boot ticks. */
@media (prefers-reduced-motion: reduce) {
  .install .cpy, .install #copy-btn::after { transition: none !important; }
}

/* --------------------------------------------------------------- responsive
   Every breakpoint below is solved from the same inequality, not chosen: the
   line costs 0.73728·vw (23.04em at 3.2vw, capped at 921.6px once the clamp
   pins 40px) and must fit its own grid track. The control's reserve is now a
   fixed 102px (78 box + 24 gutter), so the reserve no longer moves under it.
     3 cols, gut 46 (vw ≥ 1250): 1112 − 46 − 102 = 964 vs 921.6 → 42px slack
     3 cols, gut 46 (1101-1200):  vw − 236                      → 53-79px
     3 cols, gut 34 (≤1100):      vw − 224   ⇒ holds to vw 853  → out at 1020
     2 cols, gut 34:              vw − 88 − 34 ⇒ holds to 465   → out at 820
     1 col:                       vw − 88 (−48 ≤640) ⇒ to 338   → wraps at 390
   The tightest point on the whole curve is 42px, and every step out of a
   column carries 40-90px, so a later tightening of the display line cannot
   silently walk the layout off a boundary. */

@media (max-width: 1100px) { .install { --gut: 34px; } }

/* the control steps out of the line's row while the line still has room —
   it is a marginal label, so it gives way first. 1020, not the 960 first
   drawn: with the control's width now pinned the three-column row runs out of
   measure at vw 853, and stepping out at 960 left only 28px of slack at the
   boundary. At 1020 the boundary carries 44px, the same order as the rest of
   the curve. */
@media (max-width: 1020px) {
  .install .cmdline { grid-template-columns: var(--gut) 1fr; }
  .install .cpy { grid-column: 2; grid-row: 2; justify-self: start; margin: 16px 0 0; }
}

/* the folio comes off the margin and stands over its own step */
@media (max-width: 820px) {
  .install .cmdline { grid-template-columns: 1fr; }
  .install .ln { grid-column: 1; grid-row: 1; margin-bottom: 10px; font-size: 10px; }
  .install .in.one, .install .in { grid-column: 1; grid-row: 2; }
  .install .cpy { grid-column: 1; grid-row: 3; margin: 18px 0 0; }
  .install .foot-n { padding-left: 0; }
}

/* the OS line is 57 characters of tracked mono; it stops fitting beside its own
   left label at ~711px. This covers the gap between there and the strip's own
   ≤640 stacking rule — and stops at 641 so it never fights that rule's flush-left
   setting on mobile. */
@media (max-width: 760px) and (min-width: 641px) {
  .install .l1 .band-l.r { white-space: normal; text-align: right; }
}

@media (max-width: 560px) {
  .install .leaf + .leaf { margin-top: 44px; }
}

/* ------------------------------------------------------------ PREVIEW ONLY
   wip-preview.py swaps only the <section>, so full.html's <div class="marquee">
   that follows it survives in this preview page. The integrator DELETES that
   node; this rule goes with it. (Already in site.css — restated so the preview
   is identical whichever file is edited first.) */
.install + .marquee { display: none; }

/* ------------------------------------------------ frag3-eco */
/* ============================================ [07] eco · round-3 additions
   Three new pieces of type, no new objects and no new lines between things:
   a dictionary line under the h2, a second sum that does not balance, and
   governance opened out as one running sentence beside a drafting change bar.
   Tokens only, no hex, no radius. Every selector is #eco-scoped. */

/* ------------------------------------------------------------ definition */
/* 26px below, not 18: the definition and the lede are two paragraphs of nearly the
   same measure, and at 18px they read as one lumpy block. 26 clears the sheet's
   24px floor between structural rows and lets the def stand as its own register. */
#eco .eco-def {
  margin: 22px 0 26px; max-width: 48ch;
  font-family: var(--body); font-size: 19px; line-height: 1.52;
  color: var(--ink); text-wrap: pretty;
}
#eco .eco-def b {
  font-family: var(--display); font-weight: 700; font-size: 21px; letter-spacing: -.004em;
}
/* nothing on the right, 7px on the left: after the span the markup already supplies a
   word space (~4.7px) and the .16em tracking leaves ~1.6px hanging off the stop, which
   together match the 7px on the left. A symmetric margin sets "n." visibly closer to
   the name than to the definition — the abbreviation then reads as an initial. */
#eco .eco-def .pos {
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 0 7px;
}

/* ================================================= BAND A · the short sum
   the same grammar one size down and one tone back, so the pair reads as
   thin-version / full-version at a squint — and one glyph carries the verdict. */
/* one step back from --ink-faint towards --ink: at 23px running display type
   bare --ink-faint measures 3.35:1 on seafoam paper, which is under AA for
   normal text. The mix is token-only, so every theme gets the same step. */
#eco .eq.eq-short {
  font-size: clamp(18px, 1.85vw, 23px); line-height: 1.5;
  color: color-mix(in srgb, var(--ink-faint) 78%, var(--ink));
  margin-bottom: 46px;
}
#eco .eq.eq-short .eterm { color: inherit; }
#eco .eq.eq-short .op { color: color-mix(in srgb, var(--ink) 20%, transparent); }
/* a hairline total, not the full rule the fourteen-part sum closes on */
#eco .eq.eq-short .eq-res {
  margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--rule-soft);
}
#eco .eq.eq-short .eq-res .res {
  font-family: var(--display); font-weight: 400; font-size: 24px; color: var(--ink-soft);
}
/* MONO, never --display: the display stack carries no ≠ and silently falls back
   to Times, which prints a foreign glyph beside Didot. */
#eco .eq.eq-short .eq-res .ne {
  font-family: var(--mono); font-size: 17px; color: var(--v5); padding: 0;
  opacity: 0; transition: opacity .45s ease .55s;
}
#eco .eq.eq-short.on .eq-res .ne { opacity: 1; }

/* the trailing operator, for BOTH sums.
   NOT `.part:last-of-type` — `:last-of-type` counts spans, and the last span in
   either equation is `.eq-res`, so `.part:last-of-type` matches nothing at all
   (verified on the live page). The last `.part` is the second-to-last span. */
#eco .eq .part:nth-last-of-type(2) .op { display: none; }

/* ------------------------------------------- the expansion · a change bar
   the bar sits ON the sheet's dominant left axis — the same axis as the h2, both
   sums, both kickers and the foot — and the prose is inset by the bar's gutter,
   which is what a change bar does. Indenting the whole block by --fig instead put
   the ONLY new vertical line on band B's prose axis and the running text on an
   axis nothing else uses, and it disagreed with itself below 1080. */
#eco .expand {
  margin: 36px 0 0; padding-left: 26px; max-width: 74ch;
  border-left: 1px solid color-mix(in srgb, var(--v3) 34%, transparent);
}
#eco .expand-h { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
#eco .expand-h .eterm.hot { font-size: 22px; }
#eco .organs-run {
  margin-top: 14px; font-family: var(--body); font-size: 15.5px; line-height: 1.72;
  color: var(--ink-soft); text-wrap: pretty;
}
#eco .organs-run b {
  font-family: var(--display); font-weight: 700; font-size: 16.5px; color: var(--ink);
}
#eco .organs-run .sep {
  font-family: var(--mono); font-style: normal; font-size: 11px;
  color: color-mix(in srgb, var(--v3) 45%, transparent); padding: 0 .55em;
}

/* ---------------------------------------------------------------- motion
   the fourteen-part sum now opens AFTER the short one, so the shortfall is
   read first. The per-term ladder is untouched — the whole ladder is offset
   by one beat. (`.eq#eq` is not itself an .rv element, so an inline --d on it
   would be inert; the offset has to be applied to its children.) */
#eco #eq > * { transition-delay: calc(var(--d, 0s) + .14s); }

@media (prefers-reduced-motion: reduce) {
  #eco .eq-short .ne { opacity: 1 !important; transition: none !important; }
}

/* ------------------------------------------------------------ responsive */
@media (max-width: 1080px) {
  #eco .eq.eq-short { font-size: clamp(17px, 2.4vw, 21px); margin-bottom: 40px; }
}

@media (max-width: 640px) {
  #eco .eco-def { font-size: 17.5px; max-width: none; }
  #eco .eco-def b { font-size: 19px; }
  /* neither kicker leaves room for a leader at this width — it would print as a
     four-dot stub floating at the right. Drop it to its own line and it draws as
     the full-measure rule the sheet uses everywhere else. */
  #eco .eco-call { flex-wrap: wrap; }
  #eco .eco-call .leader { flex: 1 0 100%; margin: 9px 0 0; }
  /* the ≤640 base rule `#eco .eq .eq-res { justify-content: flex-start; … }`
     carries onto the short sum through its own `.eq` class — only the size
     of the result needs restating */
  #eco .eq.eq-short { font-size: clamp(16px, 4.6vw, 19px); }
  #eco .eq.eq-short .eq-res .res { font-size: 19px; }
  #eco .expand { padding-left: 16px; max-width: none; }
  #eco .organs-run { font-size: 14.5px; line-height: 1.68; }
  #eco .organs-run b { font-size: 15.5px; }
}

/* ------------------------------------------------ frag3-proof */
/* ========================================================= 12 · PROOF
   A testimonial chapter with no testimonials: we print the FORM for a statement,
   blank, stamped UNSIGNED, counted as 0 statements on file. Open paper between two
   objects — the full-bleed partners band above, the filled approval plate below.
   Tokens only; every tint is a color-mix, so all nine themes hold. */

/* ---------------------------------------------------------------- ground
   NO wash: partners(wash) → proof(paper) → approval(wash) restores the alternation,
   and the chapter's whole subject is a blank sheet, which wants the plain sheet. */
.proof { border-top: 1px solid var(--rule); }
.proof .wrap { padding: 92px 44px 88px; }      /* 92 matches partners, 88 matches approval */
.proof .ghost-n { top: 22px; }

/* the headline holds its own column so it never runs under the numeral at 1600 */
.proof h2 { max-width: 26ch; }
.proof .lede { max-width: 62ch; }

/* ============================================ movement 1 · the statement form
   A form ON the sheet, not a loose object: the shared hairline .sheet-frame,
   transparent fill, and no shadow at all. */
.proof .pf-form {
  margin-top: 44px; max-width: 880px;
  padding: 26px 34px 0;
  box-shadow: none;
}
.proof .pf-formno { margin-bottom: 22px; }

/* -------------------------------------------------- the quotation, set large
   Three writing rules at a 44px pitch; the placeholder sits ON rule 1. The mark hangs
   into the measure, NOT into the frame: at the old clamp max of 88px with left:-.5em its
   box started at 236px — four pixels OUTSIDE an 880px frame whose border is at 244. The
   cap comes down and the placeholder is indented past it instead, so the two never meet. */
.proof .pf-quote {
  position: relative; height: 132px;
  background: repeating-linear-gradient(to bottom, transparent 0 43px,
    color-mix(in srgb, var(--ink) 12%, transparent) 43px 44px);
}
.proof .q-mark {
  position: absolute; left: -6px; top: .12em;
  font-family: var(--display); font-size: clamp(50px, 4.6vw, 74px); line-height: .7;
  color: color-mix(in srgb, var(--v3) 20%, transparent);
}
.proof .q-ph {
  display: inline-block; margin-left: clamp(30px, 2.9vw, 48px);
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: clamp(28px, 2.9vw, 40px); line-height: 44px;
  color: color-mix(in srgb, var(--ink) 38%, transparent);
}

/* ------------------------------------- the signature blank + the title block
   ONE rule across both halves, and both label rows hang from it at the same 12px.
   Before: .pf-attr carried its own border-top and the two columns were bottom-aligned,
   so SIGNED·THE PERSON QUOTED printed 9px above NAME/ROLE/COMPANY/DATE (measured 167 vs
   176 at 1600) beside a rule that covered only the right half of the form. Stretch +
   a shared border + margin-top:auto on the signature line fixes both at once.

   The left track's MAX is what the attribution block pays for: grid maximisation grows
   track 1 to its growth limit before the 1fr is sized, so a 420px cap left the four
   title-block cells at 88px each and [dd.mm.yyyy] wrapped. 300px is the widest cap the
   date cell survives at the spec'd 12.5px token. Measured, not guessed. */
.proof .pf-sign {
  margin-top: 30px;
  display: grid; grid-template-columns: minmax(240px, 300px) 1fr; gap: 32px;
  align-items: stretch;
  border-top: 1px solid var(--rule);
}
/* min-height keeps margin-top:auto working below 1080, where the grid is one column and
   the signature line has no taller sibling to be stretched against. */
.proof .pf-sign-line { min-width: 0; min-height: 66px; display: flex; flex-direction: column; padding-top: 12px; }
.proof .pf-sign-line > i {
  display: block; font-style: normal;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--ink-faint);
}
/* the approval grammar, now actually verbatim: site.css:670 .sig .sig-line is 1px, and
   .sig .sig-x is 22px at left:2px/top:-26px. At 1.5px this was the heaviest line on the
   sheet — heavier than the frame — for the one gesture that should match the deed. */
.proof .pf-rule { position: relative; height: 1px; background: var(--ink); margin: auto 0 12px; }
.proof .pf-rule.rv {
  opacity: 1; transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1.1s cubic-bezier(.22,1,.36,1) var(--d, 0s);
}
.proof .pf-rule.rv.on { transform: scaleX(1); }
.proof .pf-rule .x {
  position: absolute; left: 2px; top: -26px;
  font-family: var(--display); font-style: italic; font-size: 22px; color: var(--ink-faint);
}

/* four cells, sized to the fields they hold rather than exactly equal: [company] is nine
   characters and [dd.mm.yyyy] eleven, so equal quarters wrap both. The ratios keep every
   token on one line at 12.5px with room to spare. */
.proof .pf-attr {
  display: grid; grid-template-columns: 1fr 1fr 1.15fr 1.4fr;
  min-width: 0;
}
.proof .pf-cell { padding: 12px 12px; border-left: 1px solid var(--rule-soft); min-width: 0; }
.proof .pf-cell:first-child { border-left: none; padding-left: 0; }
.proof .pf-attr dt {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .24em;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: 8px;
}
/* flex, not the default block: an inline-block token sits on a line box whose strut leaves
   ~6px of descender space under it, so the field boxes floated 6px above the signature rule
   they are supposed to share a bottom edge with. As a flex item the token IS the cell's
   content box, and rule and boxes close on the same line. */
.proof .pf-attr dd { display: flex; align-items: flex-start; }

/* the bracket token — the one honest unit on this sheet, used in all three movements */
.proof .pf-ph {
  font-family: var(--mono); font-size: 12.5px; letter-spacing: .04em; color: var(--v3);
  border: 1px dashed color-mix(in srgb, var(--v3) 42%, transparent);
  background: color-mix(in srgb, var(--v3) 5%, transparent);
  padding: 2px 7px; display: inline-block; overflow-wrap: anywhere;
}

/* the stamp stays over the form's TRANSPARENT fill — .stamp-el is mix-blend-mode:multiply
   and goes muddy the moment it lands on a paper-hi slip. It lands across the blank writing
   rules, not on the title block: at bottom:96px it printed straight over [company]/[date]. */
.proof .pf-stamp {
  position: absolute; right: 38px; top: 126px;
  color: color-mix(in srgb, var(--v3) 78%, var(--ink));
}

/* the foot strip runs the full frame width, so it reads as part of the form */
.proof .pf-form .strip { margin: 0 -34px; padding: 9px 34px 14px; }
.proof .pf-form .strip i { font-style: italic; }
.proof .pf-form .strip b { font-weight: 400; color: var(--ink); }

/* ============================================ movement 1b · the register
   Structured exactly like .refusals .ix-entry so the two indexes read as one family. */
.proof .pf-reg-head { display: block; margin-top: 54px; }
.proof .pf-register { list-style: none; margin-top: 14px; }
.proof .pf-register li {
  display: grid; grid-template-columns: 34px 1fr; column-gap: 14px;
  border-top: 1px solid var(--rule-soft); padding: 16px 0 18px;
}
.proof .pf-register .no { font-family: var(--mono); font-size: 11px; color: var(--v3); padding-top: 3px; }
.proof .pf-line { display: flex; align-items: baseline; min-width: 0; }
.proof .pf-who {
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
  color: var(--ink-faint); flex: none;
}

/* ============================================ movement 2 · the cuttings
   Square corners, no avatar, no platform glyph, no bird. THREE slips on ONE wire, in one
   course — five in two courses left the second course's pins hanging from nothing, and read
   as a card grid, which is vetoed. Each slip hangs by a 1px thread the length of its --drop;
   the run of bare wire past the last slip is what "filed as they arrive" means. */
.proof .pf-cut-head { display: block; margin-top: 62px; }
/* flex-start, not the default stretch: stretch pulled every slip in a row down to the
   tallest one's bottom, which cancelled both the height difference and the --drop hang. */
.proof .pf-cuttings {
  position: relative; display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 30px 22px; padding-top: 26px;
}
/* the wire sits exactly where the flex line starts, so --drop IS the thread length.
   ink-30% is the .strip border weight: at var(--rule) it was indistinguishable from the
   drafting grid behind it and the slips appeared to hang from nothing. */
.proof .pf-wire {
  position: absolute; left: 0; right: 0; top: 26px; height: 1px;
  background: color-mix(in srgb, var(--ink) 30%, transparent);
}
.proof .pf-wire.rv {
  opacity: 1; transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .6s cubic-bezier(.22,1,.36,1);
}
.proof .pf-wire.rv.on { transform: scaleX(1); }

.proof .pf-cut {
  flex: 0 0 var(--w); margin-top: var(--drop); transform: rotate(var(--rot));
  border-radius: 0; border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--paper-hi) 88%, transparent);
  box-shadow: var(--shadow-card); padding: 14px 16px 20px; position: relative; min-width: 0;
}
/* the reveal must not eat the slip's resting rotation */
.proof .pf-cut.rv { transform: translateY(22px) rotate(var(--rot)); }
.proof .pf-cut.rv.on { transform: rotate(var(--rot)); }

/* the thread: 1px from the wire down to the slip's top edge, with a 7px crossbar resting ON
   the wire. It is counter-rotated about its own foot so it hangs vertical while the slip
   tilts — a thread that leans with the paper reads as a mistake. This replaces a "+" that
   floated in the gap, touching neither the wire above nor the slip below. */
.proof .pf-cut::before {
  content: ""; position: absolute; left: 30px; margin-left: -3px;
  top: calc(-1 * var(--drop)); height: var(--drop); width: 7px;
  transform: rotate(calc(-1 * var(--rot))); transform-origin: 50% 100%;
  background:
    linear-gradient(var(--rule), var(--rule)) 50% 0 / 1px 100% no-repeat,
    linear-gradient(color-mix(in srgb, var(--ink) 30%, transparent),
                    color-mix(in srgb, var(--ink) 30%, transparent)) 0 0 / 100% 1px no-repeat;
}

/* the body is the same bracket token as everywhere else, grown to fill the slip's measure.
   It replaces 1–2 empty writing rules: a 1px repeating gradient inside a rotated box
   antialiases into a scratchy broken dash that reads as a print defect, and it left each
   slip ~85% void. --rows still does the height variety, now with the blank drawn honestly. */
.proof .pf-cut-body { margin: 10px 0 12px; }
.proof .pf-cut .pf-ph {
  display: block; padding: 8px 10px 10px;
  min-height: calc(var(--rows, 1) * 22px + 20px);
}
.proof .pf-cut-meta {
  display: block;
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em; color: var(--ink-faint);
}

/* ============================================ movement 3 · the honest close
   Three rows, not five: `710 tests` and `Apache-2.0` already print in the approval
   block ~200px below. Every row here is checkable in the reader's own browser with no
   external address — see the LAUNCH GATE note in the fragment for what was verified. */
.proof .pf-check-h {
  margin-top: 68px; margin-bottom: 20px;
  font-family: var(--display); font-weight: 700; font-size: 26px; line-height: 1.15;
}
/* a closing rule, so the ledger stops instead of trailing off into the approval plate */
.proof .pf-check { list-style: none; border-bottom: 1px solid var(--rule-soft); }
/* 44px, not 96: the figures column was sized for a word, and now every entry is a single
   digit, which left a 112px void between the 0 and its claim */
.proof .pf-check li {
  display: grid; grid-template-columns: 44px 1fr auto; align-items: baseline; column-gap: 20px;
  border-top: 1px solid var(--rule-soft); padding: 14px 0;
}
.proof .pf-check li b {
  font-family: var(--display); font-weight: 700; font-size: 22px; line-height: 1.1;
}
.proof .pf-claim { display: flex; align-items: baseline; min-width: 0; font-size: 15px; color: var(--ink); }
.proof .pf-claim > span { flex: 0 1 auto; }
.proof .pf-method {
  font-style: normal; font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
  color: var(--ink-soft); overflow-wrap: anywhere;
}

/* ------------------------------------------------------------- motion, calm
   .rv / .thunk / .leader / [data-count] all ride the existing document-wide
   observers. Reduced motion is handled globally for those; only the two
   scaleX drawings need their own opt-out. */
@media (prefers-reduced-motion: reduce) {
  .proof .pf-rule, .proof .pf-wire { transform: none !important; transition: none !important; }
}

/* ------------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .proof .pf-sign { grid-template-columns: 1fr; gap: 26px; }
  /* one column: the shared rule now sits above the signature line only, so the title
     block takes its own back */
  .proof .pf-attr { border-top: 1px solid var(--rule); grid-template-columns: repeat(2, 1fr); }
  .proof .pf-cell:nth-child(3) { padding-left: 0; border-left: none; }
  .proof .pf-cell:nth-child(n+3) { border-top: 1px solid var(--rule-soft); }
  .proof .pf-stamp { position: static; margin: 28px 0 14px; display: inline-block; }
}

/* shrink, but never grow: with flex-grow:1 a short course stretches its slips into one
   enormous blank card. With grow at 0 the course keeps its own widths and the wire simply
   runs on past the last slip, which is the point. */
@media (max-width: 900px) {
  .proof .pf-cut { flex: 0 1 min(var(--w), 100%); }
}

@media (max-width: 640px) {
  .proof .wrap { padding: 64px 22px 66px; }
  .proof .pf-form { padding: 20px 20px 0; }
  .proof .pf-form .strip { margin: 0 -20px; padding-inline: 20px; }
  /* the mark stops hanging beside the line and sits above it — this is the one thing that
     pushes horizontal overflow at 390. Un-hung it needs its own air, so the form number
     gets 50px instead of 22px, and the placeholder drops its indent. */
  .proof .pf-formno { margin-bottom: 50px; }
  .proof .pf-quote {
    height: 102px;
    background: repeating-linear-gradient(to bottom, transparent 0 33px,
      color-mix(in srgb, var(--ink) 12%, transparent) 33px 34px);
  }
  .proof .q-mark { left: -2px; top: -40px; }
  .proof .q-ph { font-size: 26px; line-height: 34px; margin-left: 0; }
  /* !important is load-bearing: --rot / --drop are inline per slip, and an inline custom
     property beats a stylesheet one. Without it the slips stay tilted at 390. */
  .proof .pf-cut { flex: 1 1 100%; --rot: 0deg !important; --drop: 0px !important; }
  .proof .pf-wire, .proof .pf-cut::before { display: none; }
  .proof .pf-attr { grid-template-columns: 1fr; }
  .proof .pf-cell:nth-child(n+2) { padding-left: 0; border-left: none; border-top: 1px solid var(--rule-soft); }
  .proof .pf-check li { grid-template-columns: 1fr auto; column-gap: 14px; }
  .proof .pf-check li b { grid-column: 1 / -1; margin-bottom: 4px; }
  .proof .pf-check .leader { display: none; }
}

/* ------------------------------------------------ frag3-depth */
/* ═══════════════════════════════════════════════════ DEPTH · THE DRAFTING TABLE
   Append verbatim to the END of site.css. Nothing above it is edited.

   THE CAP — this is the constraint, and it is the whole design:
   EXACTLY TWO TILT RULES, TWO CHAPTERS, SEVEN ELEMENTS. Nothing else on the
   page rotates, ever. Everything else in this layer is a page-wide `scale` on a
   decorative numeral or a `box-shadow` ramp with no geometry at all.
   EVERY OBJECT ON THE PAGE THAT CARRIES A SENTENCE THE FOUNDER WROTE DOES NOT
   MOVE BY ONE PIXEL.

   Three strata, counted on the live page:
     1 · the table      — the ghost numeral is PRINTED on it, so it settles
                          (the rule reaches all 11 numerals; 6 of their chapters
                           are not scroll containers, so 6 actually move —
                           #problem #how #install #eco, and #l5 #partners below)
     2 · the sheets     — six problem spreads + one seating plan hinge up         (7 el)
     3 · the documents  — TWO real paper objects gain the shadow of having landed (2 el)

   SELECTORS TOUCHED — this is the complete list (eight selectors; the mobile
   --fx-landed line at max-width 640 restates the third-from-last one):
     .l5, .partners                     (overflow: clip — PREREQUISITE, see below)
     .ghost-n
     .problem .problem-scene            (perspective only)
     .problem .leaf-plates              (transform)
     .partners .plan-band .plan         (perspective only)
     .partners .plan-inner              (transform)
     #eco .eco-fifth .scene             (box-shadow ramp, + one mobile token line)
     .l5 .booklet                       (box-shadow ramp, restated list)

   STRATUM 3 IS TWO ELEMENTS, NOT FOUR — READ BEFORE ADDING A THIRD.
   The first cut of this file also ramped `.console .board` and `.cost .meter`.
   Both are DELIBERATELY NOT PAPER: site.css:2751 sets the board to
   `border: 0; background: transparent`, and site.css:3153-3157 sets the meter to
   `background: transparent; border: 0; box-shadow: none`, and says `none` again
   on :hover. An outer box-shadow on a transparent, borderless box still paints —
   it darkens everything outside the border box and clips the inside — so both
   chapters grew a phantom grey card with a hard vertical edge and no object
   casting it. Measured by screenshot diff against baseline at 1440: a soft dark
   band under the board's invisible bottom edge, and a visible rectangle corner at
   the meter's right edge. THE RULE IS: this ramp goes only on a box that already
   has a background, a border AND a --shadow-* of its own.

   HARD EXCLUSIONS — verified by grep on the comment-stripped file, zero matches:
     · the hero printer: .printer, #receipt, .feed, .prompt, .pr-*
     · .spine and everything inside it. NO `perspective` may ever be placed on an
       ancestor of .sp-tape — a perspective ancestor silently kills `position:
       sticky` and with it the spine's bidirectional printing.
     · #problem .rail-index is sticky. It lives in .problem-folio, a SIBLING of
       .problem-scenes, so it is not a descendant of .problem-scene. Keep it that way.

   PROPERTIES USED — perspective, perspective-origin, transform-origin, transform,
   scale, box-shadow, overflow, animation-*. No type size, no spacing, no layout
   property is set anywhere in this file. The only colour is --deep inside a
   color-mix, plus --shadow-obj / --shadow-card as-is. No hex. All nine themes
   untouched (overflow 0 and identical height verified on mint, butter, glacier,
   iris, paper).

   It degrades to ABSOLUTELY NOTHING where scroll-driven animations are
   unsupported, and to nothing at all under prefers-reduced-motion — measured:
   under reduce every one of these elements reports animation-name `none`,
   transform `none`, perspective `none`, and both sections keep site.css's
   own `overflow: hidden`. No separate reduced-motion block is needed or wanted.

   MEASURED against baseline full.html, three sizes, repeated runs:
     overflow 0 at 1600x1000, 1440x900, 390x844
     height 20799 (1600 and 1440) / 31642 (390) — byte-identical to baseline
     offender list byte-identical to baseline at every size
     overflow 0 and the same height on ?theme=mint and ?theme=iris
     under --force-prefers-reduced-motion: every element in this file reports
       animation-name none, transform none, perspective none, and both
       sections keep site.css's own overflow: hidden
     with the @supports condition forced false: the page's computed state is
       baseline exactly — .booklet back to par-soft alone, .ghost-n back to
       par-ghost alone, no perspective anywhere, no clip anywhere
   ══════════════════════════════════════════════════════════════════════════ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* ── PREREQUISITE · TWO sections must stop being scroll containers ──────
    The only rule in the file that is not itself motion. READ BEFORE DELETING.

    site.css:149 sets `section { overflow: hidden }`, and :863 repeats it for
    these two. `overflow: hidden` makes an element a SCROLL CONTAINER, and a
    scroll container is where `animation-timeline: view()` resolves against.
    #partners and #l5 never scroll, so every view() timeline inside them is
    frozen at its end state — the animation is applied, computes, reports its
    name and range, and does absolutely nothing. There is no symptom short of
    sampling the transform at two scroll depths.

    MEASURED before this rule: .plan-inner reports animation-name fx-lie and
    animation-range `entry 4% cover 26%`, and its transform is the identity
    matrix at every scroll position on the page, including with the element
    1100px BELOW the viewport. Dead before this line: .plan-inner and
    .l5 .booklet — two of this file's three non-numeral objects — plus two of
    the ghost numerals.

    `overflow: clip` clips identically and is NOT a scroll container. This page
    already discovered and fixed exactly this, twice, in the same words:
    site.css:1669 (.how) and site.css:2177 (.install). #eco:2363 is already clip
    and #problem:1073 is already visible — which is precisely why those two are
    the only chapters where the layer worked before this line existed.

    TWO SECTIONS, NOT FOUR — the first cut of this file also unfroze .console and
    .cost, for objects that have since been dropped from stratum 3 (see the head
    of this file). Nothing in those two chapters needs a live timeline now, so
    they are left exactly as they ship: `overflow: hidden`, numerals static.
    Do not widen this selector for a numeral. Every section listed here is a
    section whose motion this file is actually responsible for.
    Not .spine either — the spine needs `overflow: visible` for its sticky tape,
    and that is the spine builder's own prerequisite, not mine.

    Side effect, stated plainly, and it is a wanted one: two rules the page's own
    authors wrote and left frozen come back to life — `.l5 .booklet` par-soft
    (site.css:2137, whose comment asks the integrator to merge it into the
    page-wide selector) and `.partners .plan` par-soft (site.css:3475, same
    request). Their ±14px drift, and the page-wide .ghost-n ±54px parallax
    (site.css:604), now run in these two chapters as they already do in
    #problem, #how, #install and #eco. MEASURED that the numerals survive it:
    the worst box overshoot above the section's clip is -26.2px (#l5) and
    -24.1px (#partners), against -26.4px for #install, which ships today.

    It is inside both guards with everything else, so where scroll-driven
    animations are unsupported, or the reader asked for less motion, these two
    sections keep site.css's `overflow: hidden` untouched. */
    .l5, .partners { overflow: clip; }

    /* the three dials, and the only three numbers in the file */
    :root {
      --fx-tilt: 3.5deg;      /* 3deg = a whisper, 6deg = the ceiling. See RESIDUAL RISK. */
      --fx-eye: 1500px;       /* problem: viewing distance. Larger = flatter, calmer. */
      --fx-eye-wide: 1700px;  /* partners: one sheet, wider, so the eye stands back further */
    }

    /* ═══ STRATUM 1 · THE TABLE ══════ all 11 numerals, 6 of which can move
       The chapter numeral is printed ON the table, so it starts a hair further
       off and settles into the surface.

       TRAP 1 — use the independent `scale:` property, NEVER `transform:`.
       site.css:604 already animates .ghost-n's TRANSFORM via par-ghost; `scale:`
       composes with it instead of replacing it.

       TRAP 2 — `animation-name` is ONE declaration, not a merge. Naming only
       fx-print here silently DELETES par-ghost. The list must be restated in
       full. Verified live: getComputedStyle(.ghost-n) returns
       transform: matrix(1,0,0,1,0,54)  (par-ghost still running)  AND
       scale: 1.045                     (fx-print running)  simultaneously.
       INTEGRATOR: if par-ghost is ever renamed at site.css:604, rename it here too. */
    .ghost-n {
      animation-name: par-ghost, fx-print;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view(), view();
      animation-range: entry 0% exit 100%, entry 0% cover 40%;
    }
    @keyframes fx-print { from { scale: 1.045; } to { scale: 1; } }

    /* ═══ STRATUM 2 · THE HINGE ═══════════════════ 2 rules · 2 chapters · 7 el
       Perspective on the container, transform on the CHILD, hinge ALWAYS at the
       foot (transform-origin: 50% 100%).

       THAT ORIGIN IS THE ENTIRE OVERFLOW GUARANTEE. With the hinge on the bottom
       edge every point of the sheet moves AWAY from the eye, so the painted box
       only ever gets narrower. MEASURED at 1600px, full 3.5deg:
         .leaf-plates  untilted [left 200 → right 1400] · tilted [200 → 1400]
         .plan-inner   untilted [left 293 → right 1307] · tilted [293 → 1307]
       identical to the hundredth of a pixel, and page height is byte-identical
       to baseline (20799 at 1600, 31642 at 390).
       THIS GUARANTEE DIES THE MOMENT SOMEONE MOVES transform-origin OFF THE
       BOTTOM EDGE. Do not touch it.

       PERSPECTIVE ONLY REACHES DIRECT CHILDREN. Both perspective elements below
       are the immediate parent of the element that turns. An intermediate element
       with its own transform (and the default transform-style: flat) flattens the
       3D rotation into its own plane and the gesture silently becomes a 0.19%
       vertical squash. MEASURED: with perspective one level too high, the tilted
       .far-side box is [293 → 1307] — byte-identical to untilted, i.e. NOTHING
       HAPPENS. With it on the direct parent it is [297.91 → 1302.09], a real
       9.8px convergence. Never move a perspective up a level. */

    /* 01 · the problem — the SPREAD hinges, not each plate.
       One transform per leaf, not two: the mirrored pair tips up as one spread,
       which is the chapter's own idea. .problem-figure is display:contents, so
       .leaf-plates is also the simpler selector. The range resolves while the
       plates are still entering, so it never runs on top of the figures'
       existing build. */
    .problem .problem-scene {
      perspective: var(--fx-eye);
      perspective-origin: 50% 150%;
    }
    .problem .leaf-plates {
      transform-origin: 50% 100%;
      animation-name: fx-lie;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 2% cover 16%;
    }

    /* 11 · partners — only .plan-inner turns. The sheet, its frame, the .dogear
       and the Fig. 11 strip hold DEAD STILL, so the drawing lifts out of its own
       sheet rather than the sheet tipping.
       The perspective sits on .plan, the drawing's direct parent — NOT on
       .plan-band > .wrap. .plan already carries par-soft (site.css:3475), and a
       transformed intermediate flattens everything below it. See the measurement
       in the block comment above. */
    .partners .plan-band .plan {
      perspective: var(--fx-eye-wide);
      perspective-origin: 50% 140%;
    }
    .partners .plan-inner {
      transform-origin: 50% 100%;
      animation-name: fx-lie;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 4% cover 26%;
    }

    @keyframes fx-lie {
      from { transform: rotateX(var(--fx-tilt)); }
      to   { transform: rotateX(0deg); }
    }

    /* ═══ STRATUM 3 · THE DOCUMENTS ══════════════════ no geometry at all · 2 el
       The page's two framed paper objects gain only the shadow of having landed,
       so the type is pin-sharp at every frame. A 24% ramp with nothing moving
       reads as weight arriving, not as movement.

       ENTRY REQUIREMENT for this list, and there is no exception: the element
       must already have a background, a border AND a --shadow-* of its own.
       Both of these do (site.css:2003-2006 and :2559-2564); the ramp only
       changes WHEN their existing shadow arrives, never whether they have one.
       A transparent box put on this list paints a shadow with no object — see
       the note at the head of the file. */

    /* the landed value, held in a token so the mobile sheet weight survives:
       site.css:2710 gives the fifth scene the lighter --shadow-card below 640px,
       and an animation outranks it, so the ramp has to carry that value itself */
    .l5 .booklet, #eco .eco-fifth .scene { --fx-landed: var(--shadow-obj); }
    @media (max-width: 640px) { #eco .eco-fifth .scene { --fx-landed: var(--shadow-card); } }

    #eco .eco-fifth .scene {
      animation-name: fx-land;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 10% cover 34%;
    }
    /* .booklet already carries par-soft on the same element (site.css:2137) —
       same restated-list rule, same measured reason as .ghost-n above.
       INTEGRATOR: if par-soft is renamed, rename it here too. */
    .l5 .booklet {
      animation-name: par-soft, fx-land;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view(), view();
      animation-range: entry 0% exit 100%, entry 10% cover 34%;
    }
    @keyframes fx-land {
      from { box-shadow: 0 2px 6px -4px color-mix(in srgb, var(--deep) 30%, transparent); }
      to   { box-shadow: var(--fx-landed); }
    }

    /* ═══ RESPONSIVE ═══════════════════════════════════════════════════════════
       At 300px-wide plates the full gesture reads as a twitch, so the tilt
       shortens and the eye steps back. Nothing is switched off here.

       STATED PLAINLY, because it is easy to assume otherwise: below 1080px
       site.css:1512 sets `.problem .leaf-plates { display: contents }`. An
       element with display:contents generates no box, so it cannot be
       transformed — chapter 01's hinge is simply ABSENT under 1080px, at any
       --fx-tilt. That is the right answer rather than a gap to patch: below
       1080px the mirrored spread has already dissolved into one column, so
       "the spread tips up as one" no longer has anything to refer to.
       Chapter 11 is a real box at every width and hinges everywhere —
       measured at 390: .plan-inner [left 63 -> right 327], untilted and
       tilted alike. Do not "fix" chapter 01 by hinging .bp on mobile; that
       would break the cap of seven elements for a 2.5deg twitch. */
    @media (max-width: 860px) {
      :root { --fx-tilt: 2.5deg; --fx-eye: 1100px; --fx-eye-wide: 1200px; }
    }
  }
}

/* ═══════════════════════════════════════════════════════ NOTES FOR WHOEVER
   INHERITS THIS FILE — four things that will bite, in order of likelihood.

   1 · CROSS-BUILDER PIN — the six-colour wash.
       `perspective` on .problem-scene makes it a STACKING CONTEXT. Today's wash
       is `.problem .problem-scene--wash::before { z-index: -1 }` (site.css:1389).
       A negative-z-index child is trapped inside the new stacking context; it
       still paints (the scene has no background of its own to hide behind), but
       it is now one layer up from where its author put it. Chapter 01's rebuild
       is required to paint the six-colour wash as a `background` on
       .problem-scene instead — a background has no stacking behaviour and cannot
       break. If that rebuild lands as a pseudo-element after all, check it.

   2 · CROSS-BUILDER PIN — nothing else may transform these seven elements.
       This file owns the ONLY gesture on .leaf-plates / .problem-figure / .bp
       and on .plan-inner. A second `transform` or `animation` on any of them
       from chapter 01 or 11 replaces this one silently. Confirm on integration.

   3 · PINNED SELECTOR — `#eco .eco-fifth .scene`.
       Chapter 05's rebuild must keep `class="scene bedrock rv"` inside
       .eco-fifth. Check with:
         FX_EVAL='return !!document.querySelector("#eco .eco-fifth .scene")'
       -> true (verified true here).

   4 · KNOWN RESIDUAL RISK — hairlines at the angle, and where those frames land.
       A drawing at a partial angle DOES go soft on 1px strokes: measured on the
       seating plan at 1440, forcing the full 3.5deg and sampling edge contrast
       (99.9th-percentile luminance gradient) against the same crop at rest —
         the table's dashed outline   99 -> 65   (-34%)
         the three seats              101 -> 70  (-31%)
         the ghost chairs             17 -> 13   (-24%)
       That is a real loss, so it matters exactly where those frames are shown,
       and they are off-stage: the range starts at `entry 4%`, which for a 336px
       drawing is 13px of it above the fold, and the tilt is already down to
       ~0.8deg by the time 250px of the drawing is on screen. The reader sees
       maximum tilt only while the top edge is grazing the bottom of the window,
       and a pin-sharp drawing everywhere they can actually read it. Chapter 01's
       range (`entry 2% cover 16%`) is shorter and earlier still.
       KEEP IT THAT WAY. Do not push the end of either range later to make the
       gesture "more visible" — that walks the soft frames into the reading zone,
       which is the one thing this chapter cannot afford. If softness is ever
       reported on a low-DPI screen, drop --fx-tilt to 3deg; the dial exists for
       exactly this and touches nothing else.

   ONE SMALL, DELIBERATE SIDE EFFECT OF THE SHADOW RAMP, stated so nobody has to
   rediscover it:
     · An animation outranks every normal declaration, so `.l5 .booklet:hover`'s
       deeper shadow (site.css:2009) no longer applies. The values differ by
       4px of blur and 3% alpha; the hover `translate` lift is untouched. This is
       the ONLY hover the ramp costs — `#eco .eco-fifth .scene:hover` already
       restores --shadow-obj itself at site.css:2655, and the mobile
       --shadow-card at :2710 is carried through by --fx-landed above.
   ══════════════════════════════════════════════════════════════════════════ */

/* ------------------------------------------------ frag4-install (command blocks) */
/* ------------------------------------------------ frag4-install */
/* ================================================== 06 · INSTALL
   TWO COMMAND BLOCKS ON ONE HANGING INDENT.

   The previous sheet set `curl … | sh` at 40px as a bare line: it read as a
   headline and not as something you copy. A command is not a headline — it is
   a thing you take. So the two commands become BLOCKS: a tinted mono caption
   strip, a hairline box on --paper-hi, the command at reading size, and a copy
   control in its own gutter inside the box. The section's hero line is the H2
   again, which is what it always was.

   The block is built only from devices already on the page: .strip's rule
   weight, the dotted .leader, the hanging indent, the mono label. Tokens and
   color-mix only; no hex, nothing heavier than 1px.
   Appended after site.css, so it out-ranks the old blocks on ties. */

/* --gut  the hanging indent: folio track, note inset, boot inset — one measure.
   --cbw  THE COMMAND BLOCK'S MEASURE, and the number this sheet turns on.
          Measured, not guessed: at 1600 the longest command
          `$ curl -fsSL https://get.foxora.dev | sh` sets 357px of 15px Menlo;
          the scroller's own padding is 17+14 and the control gutter is a fixed
          94. That is 482px of obligation in a 1066px track — the block was
          twice the size of the thing it holds, and a box with 600px of blank
          paper in it does not read as a command, it reads as a form field.
          558px is 62 columns of the block's own face: 40 for the command, 3.4
          for its padding, 10.4 for the control, and 8.6 columns of air before
          the gutter. Both blocks take it, so they register with each other and
          with the note, and the full-width rules above and below them stay the
          only things that span the sheet. */
.install { --gut: 46px; --cbw: 558px; }

/* ---------------------------------------------------------------- the head
   The H2 stays at the sheet's chapter size. It is still the largest thing in
   this chapter — the commands are 15px instruments now, not headlines — and
   the earlier 52px made [06] the loudest of the twelve heads for no reason:
   every other chapter sets 44 and only [01] is allowed to open at 66. */
#install h2 { max-width: 21ch; margin-bottom: 18px; }
#install .lede { max-width: 56ch; }

/* -------------------------------------------------------------- the leaves */
.install .leaf + .leaf { margin-top: 50px; }
/* leaf 2's running head is lighter than leaf 1's: one procedure with a
   subordinate step, not a ladder of equal rules. 22% sits clearly under
   .strip's own 30% and clearly over the boot rows' 13%. */
.install .strip.sub-head { border-top-color: color-mix(in srgb, var(--ink) 22%, transparent); }

/* ----------------------------------------------------------------- the step
   The folio hangs in the margin the note and the boot rows also hang from, so
   one indent governs the whole sheet: 01 · block · note · 02 · block · boot. */
.install .cstep {
  display: grid; grid-template-columns: var(--gut) minmax(0, 1fr);
  align-items: start; margin-top: 24px;
}
.install .fol {
  padding-top: 10px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .2em; line-height: 1;
  color: color-mix(in srgb, var(--v3) 62%, transparent);
}

/* --------------------------------------------------------- the command block
   Paper, not a terminal: --paper-hi lifted a few percent toward --v1/--v3, one
   hairline in the accent rather than in ink, and a 3px corner — the same
   family as .btn's 2px, one step softer because the box is bigger.
   The mono metric is declared HERE so every `ch` below (the block's own cap,
   the code, the scroll test) is measured in the face the command is set in. */
.install .cb {
  position: relative; overflow: hidden;
  max-width: var(--cbw);
  font-family: var(--mono); font-size: 15px;
  border: 1px solid color-mix(in srgb, var(--v1) 33%, transparent);
  border-radius: 3px;
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--v1) 5%, transparent),
      color-mix(in srgb, var(--v3) 2%, transparent)),
    var(--paper-hi);
}

/* the caption strip — the block's own running head, one third the size of the
   command it labels, and it carries the page's dotted leader so the box reads
   as a sheet device and not as an imported code widget */
.install .cb-cap {
  display: flex; align-items: baseline; margin: 0;
  padding: 9px 14px 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--v1) 20%, transparent);
  background: color-mix(in srgb, var(--v1) 5%, transparent);
  font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-faint);
}
.install .cb-cap .cb-l { color: color-mix(in srgb, var(--v3) 80%, transparent); white-space: nowrap; }
.install .cb-cap .cb-r { color: var(--ink-faint); white-space: nowrap; }
.install .cb-cap .leader { flex: 1; min-width: 18px; margin: 0 12px; }

/* the body — measure and control in two tracks, so the control is INSIDE the
   block but never inside the line: the command can scroll under nothing. */
.install .cb-body { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: stretch; }

/* the measure. `pre` + overflow-x means a long command SCROLLS; it never wraps
   into a second line that a reader could paste half of. The <code> box itself
   stays inside the track — only its ink runs on — so a scrolling block never
   widens the page. */
/* The bar itself is retired. It is 50px of block height on the phone and a
   classic scrollbar would take 8-15 of them on any platform that reserves
   layout space for one, squeezing the descenders of the only line in the box.
   The ramp below is the cue instead, and Chrome/Firefox already make a
   scroller with no focusable content keyboard-reachable on its own, so the
   line stays operable without a rail drawn through the sheet. */
.install .cb-scroll {
  overflow-x: auto; overflow-y: hidden;
  overscroll-behavior-x: contain;
  padding: 15px 14px 16px 17px;
  scrollbar-width: none;
}
.install .cb-scroll::-webkit-scrollbar { display: none; }
.install .cb-code {
  display: block; white-space: pre;
  font-family: var(--mono); font-size: 15px; line-height: 1.65; letter-spacing: -.004em;
  color: var(--ink);
}
/* the prompt is furniture, not text: dim, unselectable, hidden from the
   reading order — drag across the line and you take the command alone. */
.install .cb-p {
  font-style: normal; margin-right: .8ch;
  color: color-mix(in srgb, var(--v3) 52%, transparent);
  -webkit-user-select: none; user-select: none;
}
.install .cb-code .pipe { white-space: pre; }

/* the control's own gutter: a hairline and a half-tone panel, so the button is
   held by the block instead of floating in it */
.install .cb-act {
  position: relative;
  display: flex; align-items: center; padding: 0 12px;
  border-left: 1px solid color-mix(in srgb, var(--v1) 22%, transparent);
  background: color-mix(in srgb, var(--v1) 6%, transparent);
}
/* the only cue that the measure scrolls — so it is only drawn when it does.
   It is hung on the CONTROL, not on the scroller, so it can never fade a
   command that already fits: the ramp lives in the 26px immediately left of the
   divider, in the block's own paper, and a long command visibly runs under the
   gutter instead of stopping dead mid-word. `.scrolls` is set by the observer
   in the fragment whenever scrollWidth outruns clientWidth, which after the
   --cbw cap is true only below ~646px — at 390 the curl line is 333px of Menlo
   in a 260px track. Above that the ramp would have been a permanent smudge
   promising a scroll that could not happen. */
.install .cb.scrolls .cb-act::before {
  content: ""; position: absolute; right: 100%; top: 0; bottom: 0; width: 26px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--v1) 4%, var(--paper-hi)));
}
/* THE WIDTH IS FIXED, and that is the load-bearing declaration here. COPY and
   COPIED are different strings: measured on the render, COPY's box is 66px and
   COPIED's 68px, so without a floor the block twitched 2px sideways under the
   cursor every time it was used. 7.3em of its own 9.5px is 69.35px — over the
   wider label — so both labels centre in one box and nothing moves. */
.install .cb-cpy {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 7.3em; padding: 7px 10px; cursor: pointer;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--paper-hi);
  border: 1px solid color-mix(in srgb, var(--v1) 34%, transparent);
  border-radius: 2px; white-space: nowrap;
  transition: color .18s, border-color .18s, background .18s;
}
.install .cb-cpy:hover {
  color: var(--v3);
  border-color: color-mix(in srgb, var(--v3) 55%, transparent);
  background: color-mix(in srgb, var(--v3) 6%, transparent);
}
.install .cb-cpy:focus-visible { outline: 2px solid color-mix(in srgb, var(--v3) 55%, transparent); outline-offset: 2px; }
.install .cb-cpy.done {
  color: var(--v3);
  border-color: color-mix(in srgb, var(--v3) 58%, transparent);
  background: color-mix(in srgb, var(--v3) 11%, transparent);
}

/* ------------------------------------------------------------------- step 02
   the caret is re-cut for the block's 15px: 2px wide, one line high, sitting
   on the baseline the typed text sits on. It still stops when the boot lands
   (.cmd-band.done #tcar) — a boot that never ends is also untrue. */
#install #tcar {
  display: inline-block; width: 2px; height: 1.02em; margin-left: 1px;
  vertical-align: -.16em;
  background: color-mix(in srgb, var(--v3) 88%, transparent);
}

/* ------------------------------------------------------- the placeholder mark
   The host does not exist yet (docs/BACKLOG.md Phase 1, E1-E2). The command is
   still printed in full and pasteable, because a command you cannot read is no
   use — so the domain carries THREE marks: a dagger, the page's own dotted rule
   under it, and the [not live yet] token in the note directly beneath. Remove
   any one of them and the page stops being true.
   Both marks are re-scaled for 15px: at the old .32em the dagger was 4.8px, a
   speck. .6em is 9px — a footnote mark you can actually see. */
.install .ph { position: relative; }
.install .ph::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.2em; height: 1px;
  background: radial-gradient(circle, color-mix(in srgb, var(--v4) 92%, transparent) .85px, transparent 1px) 0 50%/4px 1px repeat-x;
}
.install .ph::before {
  content: "\2020"; position: absolute; top: -.42em; right: -.6em;
  font-size: .6em; letter-spacing: 0;
  color: color-mix(in srgb, var(--v4) 92%, transparent);
}

/* ------------------------------------------------------------------ the note
   Hangs off the same indent as the block, so it reads as a footnote to the
   block above it and not as a caption to the sheet. */
/* border-box is global, so the cap has to carry the indent it hangs on or the
   note's right edge stops 46px short of the block's. +--gut, and the two agree
   to the pixel at every width. */
.install .foot-n {
  margin: 18px 0 0; padding-left: var(--gut); max-width: calc(var(--cbw) + var(--gut));
  font-family: var(--mono); font-size: 11.5px; line-height: 1.85;
  letter-spacing: .02em; color: var(--ink-soft);
}
.install .foot-n b { color: color-mix(in srgb, var(--v4) 78%, transparent); margin-right: .7em; font-weight: 400; }
/* the gate is a TOKEN, not tinted prose. Boxed in the same hairline-and-2px
   family as the copy control, so the one thing on this sheet that says a
   printed command does not resolve yet cannot be skimmed past as emphasis.
   Its box hangs on the line without opening it: padding and border are the
   only additions, and line-height 1.85 already carries them. */
.install .foot-n .gate {
  display: inline-block; margin-right: .55em; padding: 1px 6px 2px;
  line-height: 1.4;
  border: 1px solid color-mix(in srgb, var(--v4) 45%, transparent);
  border-radius: 2px;
  background: color-mix(in srgb, var(--v4) 8%, transparent);
  color: color-mix(in srgb, var(--v4) 92%, transparent);
  letter-spacing: .06em;
}
/* the requirements are a SECOND note, not the tail of the first: one is a
   launch gate, the other is what the command needs. */
.install .foot-n .req { display: block; margin-top: 9px; color: var(--ink-faint); }
.install .foot-n code { font-family: inherit; font-size: inherit; color: var(--ink-soft); background: none; padding: 0; }

/* ------------------------------------------------------------------ the boot
   now hangs from the same indent as the block above it, so the three ruled
   rows start where the command starts and still hold the sheet's right edge. */
.install .boot { margin: 26px 0 0; padding-left: var(--gut); }

/* --------------------------------------------------------- the ./foxora up CTA
   Its LABEL never changes — it is the command — so the confirmation is a token
   that fades in UNDER the row. Absolute, so it is not a flex item of .btn:
   no gap, no growth, no shove of `Deploy to a platform`. */
.install .cta-row { position: relative; }
.install #copy-btn::after {
  content: "copied"; position: absolute; left: 1px; top: calc(100% + 11px);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-faint); white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity .18s;
}
.install #copy-btn.copied::after { opacity: 1; }

.install .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ------------------------------------------------------------------- motion
   Zero new transforms. The blocks arrive on .cmd-band's existing .rv; their
   caption leaders sweep at .30s and .38s, between the two band strips'; the
   existing observer then types ./foxora up and ticks the boot in pairs.
   The copy control's only motion is a 180ms colour crossfade. */
@media (prefers-reduced-motion: reduce) {
  .install .cb-cpy, .install #copy-btn::after { transition: none !important; }
}

/* --------------------------------------------------------------- responsive
   The command is at reading size now, so the measure question stops being a
   headline problem and becomes an ordinary one. MEASURED off the render, not
   modelled — the scroller's own text track against the longest line:
     1600  track 431px  vs  357px   ←  74px spare, --cbw holds the block at 558
     1440  track 431px  vs  357px   ←  identical: the cap, not the column, is
                                        what sets the block at both widths
     1080  track 431px  vs  357px   ←  still the cap; the column is 992
      646  the column finally falls under 558 and the block goes fluid
      390  track 260px  vs  333px   ←  short by 73px, and it SCROLLS
   Only the phone runs short, and there the line scrolls inside its own box
   instead of wrapping — which is the whole point of the box, and the only
   width at which the ramp is drawn. Nothing on this curve can walk the layout
   off a boundary: the block is capped then fluid, and the two fixed reserves
   inside it (the folio track and the control gutter) are the only things
   subtracted from it. */

@media (max-width: 1100px) { .install { --gut: 34px; } }

/* the folio comes off the margin and stands over its own block; the note and
   the boot come back to the sheet's left edge with it */
@media (max-width: 820px) {
  .install .cstep { grid-template-columns: minmax(0, 1fr); }
  .install .fol { padding: 0 0 9px; font-size: 10px; }
  /* the indent is gone, so the cap loses the indent it was carrying — without
     this the note runs 34px past the block it is a footnote to. */
  .install .foot-n { padding-left: 0; max-width: var(--cbw); }
  .install .boot { padding-left: 0; }
}

@media (max-width: 640px) {
  .install .cb { font-size: 14px; }
  .install .cb-code { font-size: 14px; }
  .install .cb-cap { padding: 8px 12px 7px; letter-spacing: .18em; }
  .install .cb-scroll { padding: 13px 12px 14px 14px; }
  .install .cb-act { padding: 0 9px; }
  /* the floor is re-measured for the tighter box, not dropped: at min-width 0
     the label swap grew the control 46.2px → 60.3px and stole 14px from a
     261px measure mid-copy. 6.4em of 9.5px = 60.8px clears COPIED. */
  .install .cb-cpy { min-width: 6.4em; padding: 6px 8px; letter-spacing: .14em; }
  .install .foot-n { font-size: 11px; }
  .install .leaf + .leaf { margin-top: 42px; }
}

/* the OS line is 57 characters of tracked mono; it stops fitting beside its own
   left label at ~711px. This covers the gap between there and the strip's own
   ≤640 stacking rule — and stops at 641 so it never fights that rule's flush-left
   setting on mobile. */
@media (max-width: 760px) and (min-width: 641px) {
  .install .l1 .band-l.r { white-space: normal; text-align: right; }
}

/* ------------------------------------------------------------ PREVIEW ONLY
   wip-preview.py swaps only the <section>, so full.html's <div class="marquee">
   that follows it survives in this preview page. The integrator DELETES that
   node; this rule goes with it. */

/* ------------------------------------------------ hero-fluid.css (the current under the hero) */
/* ================================================ the hero's fluid field
     Append to site.css, after the `#ascii, #dots` rules near the end of the
     hero block. Four jobs: take the drafting grid off the hero *while the
     field is live*, hold the canvas, lay a token-built scrim between the field
     and the copy, and give the one transparent control in the hero a surface
     to sit on. Nothing here touches the frame, the auroras or the printer. */

  /* 1 · while the field is live the hero is a clean plate. The body still
     paints the 10px/50px drafting grid for the whole document; the hero draws
     its own paper over that one region, so the grid stops at the hero and
     resumes at the trust band's rule.

     Gated on .fx-fluid on purpose. With no WebGL, with reduced motion, or with
     ?fluid=0, the class is never set (or is removed again) and the hero is
     returned *exactly* as it was: grid, dots and all. #dots draws the major
     grid's own nodes — leaving it on a sheet whose grid had been erased left
     a lattice of orphaned marks with nothing to mark. */
  html.fx-fluid .hero { background: var(--paper); }

  /* 2 · the field's layer — under the auroras, under .wrap (z-index 1), and
     deaf to the pointer so every CTA keeps its clicks. It fades in once the
     first frame is on the canvas, so the hero opens on paper. */
  .fx-fluid-layer {
    position: absolute; inset: 0; z-index: 0;
    pointer-events: none; overflow: hidden;
    opacity: 0; transition: opacity 1.1s ease;
  }
  .fx-fluid-layer.is-on { opacity: 1; }
  .fx-fluid-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
  .fx-fluid-swatch { position: absolute; width: 0; height: 0; overflow: hidden; }

  /* 3 · the scrim: paper lifted back over every run of type, and a margin
     lifted back around the whole sheet. Percentages are measured off the live
     hero box (1600×820 and 1440×820 at the two desktop sizes): copy column
     y 8.8–89%, printer y 8.4–81%, receipt caption y 84.4–89.3%.

     Layer order is top-down, as CSS paints it:
       a. the copy column          d. the drawn margins, left and right
       b. the stat / CTA / note    e. head and foot
       c. the receipt caption      f. one even veil over the plate          */
  .fx-fluid-scrim {
    position: absolute; inset: 0; pointer-events: none;
    background:
      /* a · the headline and the lede — the long run of type on the field */
      radial-gradient(36% 44% at 30% 42%,
        color-mix(in srgb, var(--paper) 94%, transparent) 0%,
        color-mix(in srgb, var(--paper) 82%, transparent) 42%,
        color-mix(in srgb, var(--paper) 44%, transparent) 74%,
        transparent 100%),
      /* b · the stat rule, the two buttons and the note under them, which are
         small type low on the plate and were the least legible thing here */
      radial-gradient(32% 19% at 30% 80%,
        color-mix(in srgb, var(--paper) 90%, transparent) 0%,
        color-mix(in srgb, var(--paper) 72%, transparent) 46%,
        color-mix(in srgb, var(--paper) 30%, transparent) 78%,
        transparent 100%),
      /* c · the receipt's caption — the receipt is an opaque card and needs
         nothing, but the italic under it sits straight on the field */
      radial-gradient(23% 13% at 73% 88%,
        color-mix(in srgb, var(--paper) 88%, transparent) 0%,
        color-mix(in srgb, var(--paper) 60%, transparent) 52%,
        transparent 100%),
      /* d · the sheet's margins. A drawn plate has clean paper at its edges;
         this also keeps the field from running into the frame's dashed rules
         at 30px. Absolute, so the margin is a margin at every width. */
      linear-gradient(to right,
        var(--paper) 0,
        color-mix(in srgb, var(--paper) 52%, transparent) 34px,
        color-mix(in srgb, var(--paper) 16%, transparent) 78px,
        transparent 132px),
      linear-gradient(to left,
        var(--paper) 0,
        color-mix(in srgb, var(--paper) 52%, transparent) 34px,
        color-mix(in srgb, var(--paper) 16%, transparent) 78px,
        transparent 132px),
      /* e · head and foot, so the field never butts into the title block's
         rule above or the trust rule below, and the classline at 9% keeps
         clean paper behind it */
      linear-gradient(to bottom,
        var(--paper) 0%,
        color-mix(in srgb, var(--paper) 74%, transparent) 6%,
        color-mix(in srgb, var(--paper) 44%, transparent) 12%,
        color-mix(in srgb, var(--paper) 16%, transparent) 18%,
        transparent 26%,
        transparent 78%,
        color-mix(in srgb, var(--paper) 26%, transparent) 90%,
        color-mix(in srgb, var(--paper) 62%, transparent) 97%,
        var(--paper) 100%),
      /* f · and one even veil over the whole plate */
      color-mix(in srgb, var(--paper) 14%, transparent);
  }

  /* 4 · the hero's one transparent control. `.btn.hollow` is background:transparent,
     which was right on flat paper and wrong over a live field — the strokes ran
     through the button and it stopped reading as a surface. Paper, only here,
     only while the field is on. */
  html.fx-fluid .hero .btn.hollow { background: color-mix(in srgb, var(--paper) 88%, transparent); }
  html.fx-fluid .hero .btn.hollow:hover { background: color-mix(in srgb, var(--paper) 88%, transparent); }

  /* 5 · the two older hero backgrounds retire the moment the field is live.
     #dots drew the drafting grid's own nodes — with the grid gone from the
     hero its premise is gone, and its 50px lattice would fight the field's own
     lattice. #ascii is the comp-only alternative behind ?bg=ascii. Both are
     hidden before their loops can start, so neither is left running unseen;
     if the field ever fails to come up the class is removed and they return,
     along with the grid (rule 1). ?fluid=0 keeps the old pair for comparison. */
  html.fx-fluid #dots,
  html.fx-fluid #ascii { display: none !important; }

  /* narrow sheets: the columns stack, the copy runs the full measure and the
     printer takes the bottom half, so the scrim becomes one long column of
     paper with the plate left alive only where there is no type. Measured on
     the live boxes: 390×1800 — copy y 4–49%, printer 55–94%, caption 95–97%;
     1100×1389 — copy y 5–40%, printer 49–92%, caption 93–96%. */
  @media (max-width: 1100px) {
    .fx-fluid-scrim {
      background:
        radial-gradient(112% 30% at 50% 20%,
          color-mix(in srgb, var(--paper) 90%, transparent) 0%,
          color-mix(in srgb, var(--paper) 74%, transparent) 48%,
          color-mix(in srgb, var(--paper) 34%, transparent) 78%,
          transparent 100%),
        radial-gradient(104% 15% at 50% 45%,
          color-mix(in srgb, var(--paper) 84%, transparent) 0%,
          color-mix(in srgb, var(--paper) 50%, transparent) 56%,
          transparent 100%),
        radial-gradient(96% 9% at 50% 95%,
          color-mix(in srgb, var(--paper) 86%, transparent) 0%,
          transparent 100%),
        linear-gradient(to right,
          var(--paper) 0,
          color-mix(in srgb, var(--paper) 40%, transparent) 22px,
          transparent 60px),
        linear-gradient(to left,
          var(--paper) 0,
          color-mix(in srgb, var(--paper) 40%, transparent) 22px,
          transparent 60px),
        linear-gradient(to bottom,
          var(--paper) 0%,
          color-mix(in srgb, var(--paper) 56%, transparent) 5%,
          color-mix(in srgb, var(--paper) 20%, transparent) 12%,
          transparent 20%,
          transparent 74%,
          color-mix(in srgb, var(--paper) 30%, transparent) 90%,
          var(--paper) 100%),
        color-mix(in srgb, var(--paper) 16%, transparent);
    }
  }

/* ============================================ founder pass · 16 Aug, late
   Four hand edits: the six leaf colours become the product palettes, the
   chapter opening is cut down, the install blocks come to the middle, and
   the ecosystem's two sums stop being plain text. */

/* ---- 1 · six chapters, six colours — the product palettes' own accents.
   mint · lime · butter · iris · lavender · glacier (sage sits too close to
   mint and lime to read as its own chapter). These are deliberate constants,
   not theme tokens: the six must stay the same six on every palette. */
.problem {
  /* the six the founder picked, each a palette's own accent:
     lime · butter · paper · iris · sage · glacier */
  --leaf-1: #4d7c0f;   /* lime    */
  --leaf-2: #a16207;   /* butter  */
  --leaf-3: #6e32a6;   /* paper   */
  --leaf-4: #4f46e5;   /* iris    */
  --leaf-5: #4a6b45;   /* sage    */
  --leaf-6: #0e7490;   /* glacier */
}
.problem #problem-01, .problem .problem-specimen li:nth-child(1), .problem .problem-folio .rail-index li:nth-child(1) { --leaf: var(--leaf-1); }
.problem #problem-02, .problem .problem-specimen li:nth-child(2), .problem .problem-folio .rail-index li:nth-child(2) { --leaf: var(--leaf-2); }
.problem #problem-03, .problem .problem-specimen li:nth-child(3), .problem .problem-folio .rail-index li:nth-child(3) { --leaf: var(--leaf-3); }
.problem #problem-04, .problem .problem-specimen li:nth-child(4), .problem .problem-folio .rail-index li:nth-child(4) { --leaf: var(--leaf-4); }
.problem #problem-05, .problem .problem-specimen li:nth-child(5), .problem .problem-folio .rail-index li:nth-child(5) { --leaf: var(--leaf-5); }
.problem #problem-06, .problem .problem-specimen li:nth-child(6), .problem .problem-folio .rail-index li:nth-child(6) { --leaf: var(--leaf-6); }
/* the kicker and the leaf numeral carry the colour too, so a leaf is unmistakable */
.problem .problem-scene .problem-scene__category { color: color-mix(in srgb, var(--leaf) 72%, var(--ink)); }
.problem .problem-specimen i { height: 5px; background: color-mix(in srgb, var(--leaf) 42%, white); }
.problem .problem-specimen a:hover i, .problem .problem-specimen a.is-active i { background: var(--leaf); }

/* ---- 2 · the chapter opening: shorter, and the lede moves opposite the
   headline so the head is two columns deep instead of five lines tall */
.problem.problem-light .wrap { padding-top: 62px; }
.problem .problem-overview .chapter { margin-bottom: 16px; }
.problem .problem-overview h2 {
  font-size: clamp(38px, 3.5vw, 50px); line-height: 1.0; letter-spacing: -.014em; padding-right: 30px;
}
.problem .problem-overview { grid-template-columns: 1.32fr 1px .68fr; padding-bottom: 26px; }
.problem .problem-overview .lede { font-size: 15.5px; line-height: 1.58; padding-left: 40px; }
.problem .problem-overview .lede {
  grid-column: 3; grid-row: 2; margin: 9px 0 0; padding: 0 0 0 52px; max-width: 44ch;
}
.problem .problem-overview { padding-bottom: 30px; }
.problem .problem-specimen { margin: 22px 0 28px; }
@media (max-width: 1080px) {
  .problem .problem-overview .lede { grid-column: 1; grid-row: 3; padding-left: 0; margin-top: 18px; }
}

/* ---- 3 · install: one centred measure for the whole chapter, the two command
   blocks filling it. Everything in the section shares the same left edge, so
   the blocks read as the subject rather than as boxes adrift on the sheet. */
.install .wrap > * { max-width: 940px; margin-inline: auto; }
.install .cmd-band { max-width: 940px; }
.install .cstep { grid-template-columns: var(--gut) minmax(0, 1fr); }
.install { --cbw: 100%; }
.install .cb { width: 100%; border-color: color-mix(in srgb, var(--ink) 44%, transparent); box-shadow: var(--shadow-card); }
.install .cb-body { background: color-mix(in srgb, var(--v1) 7%, var(--paper-hi)); }
.install .cb-code { font-size: 16px; }
.install .cb-cap { padding-block: 9px 8px; }
@media (max-width: 1040px) {
  .install .wrap > *, .install .cmd-band { max-width: none; }
}

/* ---- 4 · the two sums stop reading as prose: the short one is set small and
   grey against a hairline, its verdict is loud, and the fourteen-part sum
   sits on its own tinted plate so the eye lands on the product, not the list */
#eco .eq.eq-short { font-size: clamp(17px, 1.6vw, 20px); color: color-mix(in srgb, var(--ink-faint) 88%, var(--ink)); }
#eco .eq.eq-short .eq-res .res { font-size: 30px; color: var(--ink); }
#eco .eq.eq-short .eq-res .ne { font-size: 21px; }
#eco .eq#eq {
  background: color-mix(in srgb, var(--v1) 9%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--ink) 34%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 34%, transparent);
  padding: 30px 30px 26px; margin-inline: -30px;
}
#eco .eq#eq .eterm { color: var(--ink); }

/* ---- 4b · governance stops being a paragraph: seven named parts, each on its
   own ruled line, the term in display type and the sentence hanging off a
   leader. A list of what the word contains — not boxes, not a table. */
#eco .organs { list-style: none; margin: 22px 0 0; padding: 0; border-top: 1px solid color-mix(in srgb, var(--ink) 34%, transparent); }
#eco .organ {
  display: grid; grid-template-columns: 42px minmax(140px, auto) minmax(24px, 1fr) minmax(0, 1.35fr);
  align-items: baseline; column-gap: 0; padding: 14px 0 13px;
  border-bottom: 1px solid var(--rule-soft);
}
#eco .organ:last-child { border-bottom: 1px solid color-mix(in srgb, var(--ink) 34%, transparent); }
#eco .organ .o-n { font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em; color: color-mix(in srgb, var(--v3) 85%, transparent); }
#eco .organ .o-t { font-family: var(--display); font-weight: 700; font-size: clamp(19px, 1.7vw, 24px); line-height: 1.1; color: var(--ink); }
#eco .organ .leader { margin: 0 16px; }
#eco .organ .o-d { font-family: var(--body); font-size: 15px; line-height: 1.5; color: var(--ink-soft); }
#eco .organ:hover .o-t { color: var(--v3); }
@media (max-width: 900px) {
  #eco .organ { grid-template-columns: 34px 1fr; row-gap: 4px; }
  #eco .organ .leader { display: none; }
  #eco .organ .o-d { grid-column: 2; }
}
/* the seven parts want the full measure — one line each, not two */
#eco .expand { max-width: none; }
#eco .organ { grid-template-columns: 46px minmax(150px, auto) minmax(40px, 1fr) minmax(0, 2fr); }

/* ============================================ one problem, one screen
   The founder's shape: each leaf fills the viewport, the whole sheet carries
   that problem's colour, and a scroll lands on the next problem rather than
   somewhere in the middle of it. The colour is set on the section by the
   scroll-spy (site.js) from the active leaf's own --leaf. */
.problem.problem-light {
  background: color-mix(in srgb, var(--sec-leaf, var(--v3)) 13%, white);
  transition: background 700ms cubic-bezier(.22, 1, .36, 1);
}
/* the per-leaf plate wash retires — the screen itself is the wash now */
.problem .problem-scene { background-image: none; }
.problem .problem-scene + .problem-scene { border-top: 0; }

.problem .problem-scene {
  min-height: calc(100vh - 66px);
  display: flex; flex-direction: column; justify-content: center;
  padding-top: 34px; padding-bottom: 40px;
  scroll-margin-top: 66px;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.problem .problem-caesura { scroll-snap-align: none; }
/* only the leaves carry snap points, so the rest of the page scrolls normally */
html { scroll-snap-type: y proximity; }

@media (max-height: 780px), (max-width: 1080px) {
  .problem .problem-scene { min-height: 0; padding-top: 56px; padding-bottom: 56px; }
  html { scroll-snap-type: none; }
}
@media (prefers-reduced-motion: reduce) {
  .problem.problem-light { transition: none; }
  /* a reader who asked for no motion does not want the scroll taken off them either:
     scroll-snap-stop: always seizes every leaf. The snap axis goes with the animation. */
  html { scroll-snap-type: none; }
}

/* ---- eco head: two columns instead of a tall left stack. The definition sets
   the noun on the left, the argument answers it on the right, and the chapter
   starts on its sums a screen earlier than it used to. */
#eco .eco-head {
  display: grid; grid-template-columns: minmax(0, 1.05fr) 1px minmax(0, .95fr);
  column-gap: 0; align-items: start; max-width: none; margin-bottom: 40px;
}
#eco .eco-head h2 { grid-column: 1; max-width: 15ch; margin-bottom: 20px; }
#eco .eco-head .eco-def { grid-column: 1; margin: 0; padding-right: 56px; }
#eco .eco-head .lede {
  grid-column: 3; grid-row: 1 / span 3; margin: 8px 0 0; padding-left: 56px;
  max-width: 46ch; border-left: 1px solid var(--rule-soft);
}
#eco .eq-band { margin-top: 8px; }
@media (max-width: 1080px) {
  #eco .eco-head { grid-template-columns: 1fr; }
  #eco .eco-head .lede { grid-column: 1; grid-row: auto; padding-left: 0; border-left: 0; margin-top: 20px; }
  #eco .eco-head .eco-def { padding-right: 0; }
}

/* ---- the fourteen parts as a manifest, not a wall of nouns. Each part is
   numbered, ruled and stamped with what it actually is today — which is the
   honest version of the sum and reads in one pass. */
#eco .bom { margin-top: 8px; padding: 26px 30px 22px;
  background: color-mix(in srgb, var(--v1) 7%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
#eco .bom-strip { margin: 0 0 14px; }
#eco .bom-list { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 64px; }
#eco .bom-list li { display: grid; grid-template-columns: 34px minmax(0, auto) minmax(24px, 1fr) auto;
  align-items: baseline; padding: 9px 0; border-bottom: 1px solid var(--rule-soft); }
#eco .bom-list .b-n { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; color: var(--ink-faint); }
#eco .bom-list .b-t { font-family: var(--display); font-weight: 700; font-size: 21px; line-height: 1.15; color: var(--ink); }
#eco .bom-list .leader { margin: 0 14px; }
#eco .bom-list .b-s { font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; }
#eco .bom-list .b-s.ok { color: var(--v3); }
#eco .bom-list .b-s.wip { color: var(--v5); }
#eco .bom-list li.hot .b-t { color: var(--v3); }
#eco .bom-list li.hot .b-t::after { content: "the one nobody else ships"; display: block;
  font-family: var(--mono); font-size: 9px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-faint); margin-top: 2px; }
#eco .bom-total { margin: 18px 0 0; text-align: right;
  font-family: var(--display); font-weight: 700; font-size: clamp(28px, 3vw, 42px); color: var(--ink); }
#eco .bom-total .b-eq { color: var(--v3); font-size: .6em; margin-right: 10px; }
@media (max-width: 860px) {
  #eco .bom { padding: 20px 16px 18px; }
  #eco .bom-list { grid-template-columns: 1fr; column-gap: 0; }
  #eco .bom-list .b-t { font-size: 18px; }
}

/* ============================================ one heading scale, every page
   Three pages were setting their own h1 (66 / 62 / 56px) with three different
   trackings, so the same voice changed size as you moved through the site.
   This is the scale; a page may only depart from it for a reason with a name. */
h1, .page-hero h1, .grip h1, .gr-open h1 {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(40px, 4.6vw, 64px); line-height: 1.02; letter-spacing: -.018em;
}
h2, .page-sec h2, .grip h2 {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(28px, 3.1vw, 46px); line-height: 1.06; letter-spacing: -.012em;
}
/* the two deliberate departures: policy clauses are numbered headings inside a deed,
   and the problem chapter's leaf headings are set to its own rhythm */
.policy-deed h2, .deed .art h2 { font-size: 26px; line-height: 1.06; letter-spacing: .22em; }
.problem .problem-scene h3 { letter-spacing: -.004em; }

/* ---- GRIP sits on the same sheet as install: same wrap, same left edge, the
   credential given room, and a hero that ends in something to do rather than air. */
.grip .gr-hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr); column-gap: 56px; align-items: start; }
.grip .gr-open { padding-top: 84px; padding-bottom: 64px; }
.grip .gr-say h1 { max-width: 15ch; }
.grip .gr-one { font-size: 17px; max-width: 46ch; }
.grip .gr-badge { margin-top: 24px; }
.grip .gr-cta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 26px; }
.grip .gr-cta .cta-note { width: 100%; margin-top: 2px; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
.grip .gr-cap { margin-top: 34px; padding-top: 18px;
  border-top: 1px solid color-mix(in srgb, var(--ink) 26%, transparent);
  font-family: var(--body); font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); max-width: 86ch; }
@media (max-width: 1080px) { .grip .gr-hero-grid { grid-template-columns: 1fr; row-gap: 36px; } }

/* ============================================ GRIP · the protocol sheet
   The page borrows a standard's FORM and never its credentials: a specimen credential
   with a real guilloché ground, a document-control register that says what does not
   exist, six subjects (never "clauses" — a clause is published text and there is none),
   the capsule's selection as a receipt, one labelled thesis, and a counted close. */
.grip .page-hero { padding-top: 84px; padding-bottom: 64px; }
.grip .page-sec { padding-top: 78px; padding-bottom: 78px; position: relative; }
.grip .page-sec.wash { background: color-mix(in srgb, var(--paper-hi) 62%, transparent); }
.grip .gr-hero-grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.06fr); column-gap: 56px; align-items: start; }
.grip .gr-say h1 { max-width: 15ch; }
.grip .gr-open .lede { font-size: 17px; max-width: 46ch; }
.grip .gr-strip { margin-top: 26px; }
.grip .gr-open .strip .r { color: var(--v5); }
.grip .cta-row { margin-top: 26px; }
.grip .cta-note { margin-top: 12px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }

/* the credential */
.grip .visa { position: relative; overflow: hidden; background: var(--paper-hi);
  border: 1px solid color-mix(in srgb, var(--ink) 58%, transparent);
  outline: 1px solid var(--rule); outline-offset: -5px; box-shadow: var(--shadow-card); }
.grip .visa-ground { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .10; color: var(--v1); pointer-events: none; }
.grip .visa > *:not(.visa-ground) { position: relative; }
.grip .visa-head { display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
  padding: 11px 18px; border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 9px; letter-spacing: .18em; text-transform: uppercase; }
.grip .visa-head span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grip .visa-head { gap: 18px; }
.grip .vh-l { color: var(--v3); } .grip .vh-r { color: var(--ink-faint); }
.grip .visa-body { display: grid; grid-template-columns: 104px minmax(0,1fr); gap: 20px; padding: 20px; }
.grip .plate { width: 104px; height: 122px; border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--paper) 40%, transparent);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px; }
.grip .plate .digest { width: 58px; height: 58px; }
.grip .plate .p-dig { font-family: var(--mono); font-size: 8.5px; color: var(--v3); }
.grip .plate .p-role { font-family: var(--mono); font-size: 8px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-faint); }
.grip .fields { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); column-gap: 18px; row-gap: 12px; }
.grip .field { min-width: 0; }
.grip .field b { display: block; font-family: var(--mono); font-size: 8.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint); font-weight: 400; }
.grip .field span { display: block; margin-top: 2px; font-family: var(--mono); font-size: 12px; color: var(--ink);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grip .field i { font-style: normal; font-family: var(--mono); font-size: 9px; color: var(--v3); }
.grip .field.blank span { color: var(--ink-faint); }
.grip .stamps { position: relative; height: 128px; margin: 0 18px 4px; }
.grip .cap-stamp { position: absolute; mix-blend-mode: multiply; }
.grip .cs-issue { left: 0; top: 6px; transform: rotate(-9deg); color: var(--v3); }
.grip .cs-sealed { left: 42%; top: 50px; transform: rotate(4deg); border: 2.5px solid var(--v3); color: var(--v3); padding: 7px 12px; text-align: center; }
.grip .cs-draft { right: 0; top: 0; transform: rotate(-4deg); border: 2.5px solid var(--v5); color: var(--v5); padding: 7px 12px; text-align: center; }
.grip .cs-sealed b, .grip .cs-draft b { display: block; font-family: var(--mono); font-size: 13px; letter-spacing: .18em; }
.grip .cs-sealed span, .grip .cs-draft span { display: block; font-family: var(--mono); font-size: 8px; letter-spacing: .1em; margin-top: 2px; }
.grip .mrz { border-top: 1px solid var(--rule); padding: 11px 18px 12px;
  background: color-mix(in srgb, var(--paper) 55%, var(--paper-hi));
  font-family: var(--mono); font-size: clamp(9px, .76vw, 12px); letter-spacing: 1.6px; white-space: nowrap; overflow: hidden; }
.grip .mrz p { margin: 0; line-height: 1.75; }

/* document control — the honesty gate, on screen one */
.grip .doc-control { list-style: none; margin: 26px 0 0; padding: 0; border-top: 1px solid color-mix(in srgb, var(--ink) 34%, transparent); }
.grip .doc-control li { display: flex; align-items: baseline; padding: 9px 0; border-bottom: 1px solid var(--rule-soft);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; }
.grip .doc-control .k { text-transform: uppercase; letter-spacing: .2em; color: var(--ink-faint); white-space: nowrap; }
.grip .doc-control .v { color: var(--ink); white-space: nowrap; }
.grip mark { background: color-mix(in srgb, var(--v5) 13%, transparent); color: var(--v5); font-family: var(--mono); padding: 1px 6px; }

/* [01] the pivot */
.grip .pivot { display: grid; grid-template-columns: 1fr 1px 1fr; margin-top: 30px; }
.grip .pv-fold { background: var(--rule); }
.grip .pv-half { padding: 0 46px; }
.grip .pv-half:first-child { padding-left: 0; } .grip .pv-half:last-child { padding-right: 0; }
.grip .pv-q { font-family: var(--display); font-weight: 700; font-size: clamp(21px, 2vw, 28px); line-height: 1.14; margin: 0 0 12px; color: var(--ink-soft); }
.grip .pv-half.hot .pv-q { color: var(--v3); }
.grip .pv-a { font-family: var(--body); font-size: 15.5px; line-height: 1.6; color: var(--ink-soft); }
.grip .pv-tag { margin-top: 14px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint); }
.grip .pv-close { margin: 32px 0 0; padding-top: 20px; border-top: 1px solid color-mix(in srgb, var(--ink) 34%, transparent);
  font-family: var(--body); font-size: 17px; line-height: 1.6; max-width: 78ch; }

/* [02] the six */
.grip .six { list-style: none; margin: 36px 0 0; padding: 0; border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .six li { display: grid; grid-template-columns: 60px minmax(140px, 210px) minmax(0, 1fr) minmax(0, 230px);
  align-items: baseline; gap: 0 22px; padding: 20px 0 18px; border-bottom: 1px solid var(--rule-soft); }
.grip .six .s-n { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--v3); }
.grip .six b { font-family: var(--display); font-weight: 700; font-size: 23px; line-height: 1.1; }
.grip .six .s-d { font-family: var(--body); font-size: 15px; line-height: 1.55; color: var(--ink-soft); }
.grip .six .s-c { font-family: var(--mono); font-size: 10px; letter-spacing: .06em; color: var(--v3); }
.grip .six .s-c i { font-style: normal; color: var(--ink-faint); }
.grip .six li:hover b { color: var(--v3); }
.grip .six-not { margin-top: 30px; padding-left: 22px; border-left: 2px solid var(--v5); max-width: 70ch;
  font-family: var(--body); font-size: 15px; line-height: 1.6; color: var(--ink-soft); }
.grip .six-not .whisper { display: block; margin-bottom: 6px; color: var(--v5); }

/* [03] the capsule receipt */
.grip .gr-fig-grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); column-gap: 56px; align-items: start; }
.grip .fig-body { font-family: var(--body); font-size: 16px; line-height: 1.62; color: var(--ink-soft); max-width: 52ch; margin-top: 16px; }
.grip .fig-cite { margin-top: 22px; font-family: var(--mono); font-size: 10px; letter-spacing: .08em; color: var(--v3); }
.grip .fig-cite span { color: var(--ink-faint); } .grip .fig-cite i { font-style: normal; color: var(--ink-faint); }
.grip .slip { background: var(--paper-hi); border: 1px solid color-mix(in srgb, var(--ink) 46%, transparent); box-shadow: var(--shadow-card); padding: 16px 20px 18px; }
.grip .slip-cap { display: flex; align-items: baseline; margin: 0 0 12px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); }
.grip .slip-cap .r { color: var(--v3); }
.grip .slip-rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.grip .slip-rows li { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 8px 0; border-bottom: 1px solid var(--rule-soft); font-family: var(--mono); font-size: 11.5px; }
.grip .slip-rows li span { color: var(--ink); }
.grip .slip-rows li b { font-weight: 400; font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; white-space: nowrap; }
.grip .slip-rows .in b { color: var(--v3); }
.grip .slip-rows .out span, .grip .slip-rows .out b { color: var(--ink-faint); }
.grip .slip-foot { margin-top: 12px; font-family: var(--mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
.grip .slip-foot span { color: var(--v3); }

/* [04] the thesis */
.grip .gr-th-grid { position: relative; }
.grip .th-flag { display: inline-block; margin: 10px 0 0; padding: 6px 12px; border: 1px solid var(--v5); color: var(--v5);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .22em; text-transform: uppercase; }
.grip .th-rows { margin-top: 30px; border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .th-row { display: grid; grid-template-columns: 70px minmax(0, 1fr); padding: 22px 0 20px; border-bottom: 1px solid var(--rule-soft); }
.grip .th-row .t-n { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--ink-faint); padding-top: 6px; }
.grip .th-row h3 { font-family: var(--display); font-weight: 700; font-size: 24px; line-height: 1.1; margin: 0 0 6px; }
.grip .th-row p { font-family: var(--body); font-size: 15.5px; line-height: 1.6; color: var(--ink-soft); max-width: 66ch; }
.grip .th-note { margin-top: 26px; font-family: var(--body); font-style: italic; font-size: 15px; line-height: 1.6; color: var(--ink-soft); max-width: 72ch; }

/* [05] where it stands */
.grip .st-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 56px; margin-top: 32px; align-items: start; }
.grip .st-true { list-style: none; margin: 0; padding: 0; border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .st-true li { display: grid; grid-template-columns: 110px minmax(0,1fr); align-items: baseline; padding: 16px 0; border-bottom: 1px solid var(--rule-soft); }
.grip .st-true b { font-family: var(--display); font-weight: 700; font-size: clamp(30px, 3vw, 42px); line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.grip .st-true span { font-family: var(--body); font-size: 15px; color: var(--ink-soft); }
.grip .st-true i { display: block; font-style: normal; font-family: var(--mono); font-size: 10px; color: var(--v3); margin-top: 2px; }
.grip .st-open { list-style: none; margin: 0; padding: 0; border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .st-open li { display: flex; align-items: baseline; padding: 16px 0; border-bottom: 1px solid var(--rule-soft); font-family: var(--mono); font-size: 11px; letter-spacing: .1em; }
.grip .st-open .o-k { text-transform: uppercase; letter-spacing: .2em; color: var(--ink-faint); white-space: nowrap; }
.grip .st-close { margin-top: 36px; display: grid; grid-template-columns: minmax(0, 1.2fr) auto; gap: 40px; align-items: center; }
.grip .st-close p { font-family: var(--body); font-size: 16px; line-height: 1.6; color: var(--ink-soft); max-width: 60ch; }
.grip .receipt .rc-rule { border-top-color: var(--rule); }

@media (max-width: 1080px) {
  .grip .gr-hero-grid, .grip .gr-fig-grid, .grip .st-grid { grid-template-columns: 1fr; row-gap: 36px; }
  .grip .pivot { grid-template-columns: 1fr; row-gap: 26px; }
  .grip .pv-fold { display: none; } .grip .pv-half { padding: 0; }
  .grip .six li { grid-template-columns: 44px minmax(0,1fr); row-gap: 6px; }
  .grip .six .s-d, .grip .six .s-c { grid-column: 2; }
  .grip .st-close { grid-template-columns: 1fr; gap: 20px; }
}
@media (max-width: 640px) { .grip .vh-r { display: none; } .grip .visa-body { grid-template-columns: 1fr; } .grip .plate { width: 100%; } .grip .fields { grid-template-columns: 1fr; } }

/* ---- the motion-lab studies, mounted on the protocol sheet */
.grip .gr-study { margin-top: 34px; }
.grip .gr-study section { padding: 0; margin: 0; }
/* the lab's own furniture comes off — the study keeps its drawing and its caption */
.grip .gr-study .fx-name, .grip .gr-study .fx-num, .grip .gr-study .fx-head,
.grip .gr-study .fx-idx, .grip .gr-study .fx-tag { display: none; }
.grip .gr-study .fx-note, .grip .gr-study .fx-cap, .grip .gr-study figcaption {
  font-family: var(--body); font-size: 14.5px; line-height: 1.55; color: var(--ink-soft);
  margin-top: 14px; max-width: 74ch; }
/* the lab stamps every study "PROPOSED STANDARD · NO SPECIFICATION WRITTEN YET" — true, and
   said once on this page already, so it is kept but set as the quiet gate it is */
.grip .gr-study .fx-gate, .grip .gr-study .fx-status {
  display: block; margin-top: 6px; font-family: var(--mono); font-size: 9px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--v5); }
.grip .gr-study--tall { margin-bottom: 26px; }
.grip .gr-fig-grid .gr-study { grid-column: 1 / -1; }

/* ============================================ recovered blocks
   Lost when the GRIP block was sliced out of this file — the proof ledger, the
   community close and the footer colophon were living inside the same region. */
/* ---- [11] what can be checked · real numbers, and two slots left blank on purpose */
.proof .pf-ledger { list-style: none; margin: 40px 0 0; padding: 0;
  border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.proof .pf-ledger li { display: grid; grid-template-columns: 40px minmax(120px, auto) minmax(150px, auto) minmax(24px, 1fr) minmax(0, 1.1fr);
  align-items: baseline; padding: 16px 0; border-bottom: 1px solid var(--rule-soft); }
.proof .pf-ledger .p-n { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; color: var(--ink-faint); }
.proof .pf-ledger .p-v { font-family: var(--display); font-weight: 700; font-size: clamp(30px, 3vw, 44px);
  line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.proof .pf-ledger .p-k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--v3); padding-left: 18px; }
.proof .pf-ledger .p-h { font-family: var(--body); font-size: 14.5px; line-height: 1.5; color: var(--ink-soft); }
.proof .pf-ledger .leader { margin: 0 16px; }
.proof .pf-ledger code { font-family: var(--mono); font-size: 12px; color: var(--v3); }
.proof .pf-slots { margin-top: 44px; padding-top: 26px; border-top: 1px solid var(--rule); }
.proof .pf-slots .whisper { display: block; margin-bottom: 18px; }
.proof .pf-slot { display: inline-block; width: min(46%, 460px); vertical-align: top; margin: 0 3% 22px 0;
  padding: 20px 22px; border: 1px dashed color-mix(in srgb, var(--ink) 26%, transparent); }
.proof .pf-q { font-family: var(--display); font-size: 21px; line-height: 1.25; color: var(--ink-faint); }
.proof .pf-by { margin-top: 12px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-faint); }
.proof mark { background: color-mix(in srgb, var(--v5) 13%, transparent); color: var(--v5);
  font-family: var(--mono); font-size: 12px; padding: 1px 6px; }
.proof .pf-note { margin-top: 6px; font-family: var(--body); font-style: italic; font-size: 14px; color: var(--ink-soft); }

/* ---- [13] the community close */
.close.community .cm-rows { list-style: none; margin: 36px 0 0; padding: 0;
  border-top: 1px solid color-mix(in srgb, var(--band-label, var(--ink)) 34%, transparent); }
.close.community .cm-rows li { display: grid; grid-template-columns: 44px minmax(0, auto) minmax(24px, 1fr) minmax(0, 1fr);
  align-items: baseline; padding: 15px 0; border-bottom: 1px solid color-mix(in srgb, var(--band-label, var(--ink)) 16%, transparent); }
.close.community .cm-rows .cm-n { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; opacity: .74; }
.close.community .cm-rows b { font-family: var(--display); font-weight: 700; font-size: 21px; }
.close.community .cm-rows span:last-child { font-family: var(--body); font-size: 15px; line-height: 1.5; opacity: .78; }
.close.community .cm-cta { margin-top: 34px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.close.community .cm-fine { font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; opacity: .74; margin-left: 6px; }

/* ---- the problem chapter: parallax between the words and the plates, and a
   smooth landing on anchors. The plates already tilt; this drifts them. */
html { scroll-behavior: smooth; }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 1081px) {
    .problem .leaf-words {
      animation: fx-drift-words linear both;
      animation-timeline: view();
      animation-range: entry 10% exit 90%;
    }
    .problem .figure-heading {
      animation: fx-drift-caps linear both;
      animation-timeline: view();
      animation-range: entry 10% exit 90%;
    }
  }
}
@keyframes fx-drift-words { from { transform: translateY(16px); } to { transform: translateY(-16px); } }
@keyframes fx-drift-caps  { from { transform: translateY(8px); }  to { transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ---- GRIP · the credential, the capsule and the thesis ------------------ */
.grip .gr-hero-grid { display: grid; grid-template-columns: minmax(0, .88fr) minmax(0, 1.12fr);
  gap: 56px; align-items: start; }
.grip .gr-say h1 { max-width: 15ch; }
.grip .gr-cap { margin: 34px auto 0; max-width: 1060px; padding-top: 20px;
  border-top: 1px solid var(--rule);
  font-family: var(--body); font-size: 15px; line-height: 1.6; color: var(--ink-soft); }

/* the credential — the passport object: guilloché ground, portrait, fields,
   three stamps at angles and a machine-readable band. Every value on it is a
   field of CognitiveCapsule; the DRAFT stamp is the honest one. */
.grip .visa { position: relative; border-radius: 10px; overflow: hidden;
  background: repeating-radial-gradient(circle at 88% -30%, color-mix(in srgb, var(--v1) 7%, transparent) 0 1px, transparent 1px 8px), var(--paper-hi);
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  box-shadow: 0 32px 64px -32px color-mix(in srgb, var(--deep) 42%, transparent); }
.grip .visa-head { display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 13px 20px; border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 9px; letter-spacing: .18em; text-transform: uppercase; white-space: nowrap; }
.grip .visa-head .vh-l { color: var(--v3); }
.grip .visa-head .vh-r { color: var(--ink-faint); }
.grip .visa-body { display: grid; grid-template-columns: 104px 1fr; gap: 20px; padding: 20px; }
.grip .portrait { width: 104px; height: 122px; border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--v1) 8%, transparent);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; }
.grip .portrait svg { width: 58px; height: 57px; opacity: .92; }
.grip .portrait .p-role { font-family: var(--mono); font-size: 7.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-faint); text-align: center; }
.grip .fields { display: grid; gap: 12px; align-content: start; }
.grip .field b { display: block; font-family: var(--mono); font-size: 8.5px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ink-faint); font-weight: 400; }
.grip .field span { display: block; margin-top: 2px; font-family: var(--mono); font-size: 12.5px; color: var(--ink); }
.grip .field i { font-style: normal; font-family: var(--mono); font-size: 9px; color: var(--v3); }
.grip .fields-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.grip .stamps { position: relative; height: 138px; margin: 0 18px 6px; }
.grip .st { position: absolute; mix-blend-mode: multiply; }
.grip .st-issue { left: 0; top: 6px; transform: rotate(-9deg); color: var(--v3); width: 104px; height: 104px; }
.grip .st-sealed { left: 42%; top: 52px; transform: rotate(4deg); border: 2.5px solid var(--v3);
  border-radius: 7px; color: var(--v3); padding: 7px 12px; text-align: center; }
.grip .st-draft { right: 0; top: 0; transform: rotate(-4deg); border: 2.5px solid var(--v5);
  border-radius: 7px; color: var(--v5); padding: 7px 12px; text-align: center; }
.grip .st-sealed::before, .grip .st-draft::before { content: ""; position: absolute; inset: 3px;
  border: 1px solid currentColor; border-radius: 4px; }
.grip .st-sealed b, .grip .st-draft b { display: block; font-family: var(--mono); font-size: 13px;
  letter-spacing: .18em; }
.grip .st-sealed span, .grip .st-draft span { display: block; font-family: var(--mono); font-size: 8px;
  letter-spacing: .1em; margin-top: 2px; }
.grip .mrz { border-top: 1px solid var(--rule); padding: 12px 20px 13px;
  background: color-mix(in srgb, var(--paper) 55%, var(--paper-hi));
  font-family: var(--mono); font-size: clamp(9.5px, .78vw, 12.5px); letter-spacing: 1.7px;
  color: var(--ink); white-space: nowrap; overflow: hidden; }
.grip .mrz p { line-height: 1.75; margin: 0; }

/* the capsule's five steps */
.grip .cap-steps { list-style: none; margin: 32px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0;
  border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .cap-steps li { padding: 18px 18px 16px; }
.grip .cap-steps li + li { border-left: 1px solid var(--rule); }
.grip .cap-steps .s-n { font-family: var(--mono); font-size: 10px; letter-spacing: .2em; color: var(--v3); }
.grip .cap-steps b { display: block; margin: 7px 0 7px; font-family: var(--display); font-weight: 700; font-size: 20px; }
.grip .cap-steps p { font-family: var(--body); font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }

/* the thesis */
.grip .th-flag { display: inline-block; margin: 6px 0 0; padding: 6px 12px;
  border: 1px solid color-mix(in srgb, var(--v5) 45%, transparent);
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--v5); }
.grip .gr-thesis h2 { margin-top: 16px; max-width: 22ch; }
.grip .th-rows { list-style: none; margin: 34px 0 0; padding: 0;
  border-top: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.grip .th-rows li { display: grid; grid-template-columns: 74px minmax(0, 1fr); align-items: start;
  padding: 22px 0 20px; border-bottom: 1px solid var(--rule-soft); }
.grip .th-rows .t-n { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--v3); padding-top: 6px; }
.grip .th-rows h3 { font-family: var(--display); font-weight: 700; font-size: 23px; line-height: 1.12; margin: 0 0 7px; }
.grip .th-rows p { font-family: var(--body); font-size: 15.5px; line-height: 1.6; color: var(--ink-soft); max-width: 72ch; }

@media (max-width: 1080px) {
  .grip .gr-hero-grid { grid-template-columns: 1fr; gap: 36px; }
  .grip .cred { transform: none; }
  .grip .cap-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grip .cap-steps li + li { border-left: 0; border-top: 1px solid var(--rule); }
  .grip .cap-steps li:nth-child(even) { border-left: 1px solid var(--rule); }
}
@media (max-width: 620px) {
  .grip .cred-body { grid-template-columns: 1fr; }
  .grip .cr-portrait { border-right: 0; border-bottom: 1px solid var(--rule); }
  .grip .cr-fields { grid-template-columns: 1fr; }
  .grip .cr-f:nth-child(odd) { border-right: 0; }
  .grip .cap-steps { grid-template-columns: 1fr; }
  .grip .cap-steps li:nth-child(even) { border-left: 0; }
  .grip .th-rows li { grid-template-columns: 44px minmax(0, 1fr); }
}

/* ============================================ reduced motion · the last loop
   Every caret on the site blinks forever. `blink` is the one infinite animation
   with no reduced-motion guard of its own, so it is stopped here, once, for all
   six places it is applied. The caret stays visible — it is the cursor, not the
   motion. (.install .cmd-band.done #tcar still wins with opacity: 0: the boot
   that has finished keeps no caret at all.) */
@media (prefers-reduced-motion: reduce) {
  .pr-caret,
  .step .st-art .car,
  .term-body .car,
  .a-art .car,
  .how .beat.b1 .sheet .a-art .car,
  .install #tcar { animation: none !important; opacity: 1; }
}

/* ============================================ the five type systems
   Self-hosted subsets, so the design is the same on every machine rather than
   Didot on a Mac and Georgia everywhere else. Switched with html[data-type];
   nothing here loads unless its system is selected — @font-face only fetches
   a file when a rule actually uses the family. */
@font-face { font-family: "fx-playfair";    src: url("fonts/playfair-700.woff2") format("woff2");        font-weight: 700; font-display: swap; }
@font-face { font-family: "fx-sourceserif"; src: url("fonts/sourceserif-400.woff2") format("woff2");     font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-sourceserif"; src: url("fonts/sourceserif-700.woff2") format("woff2");     font-weight: 700; font-display: swap; }
@font-face { font-family: "fx-plexsans";    src: url("fonts/plexsans-400.woff2") format("woff2");        font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-plexsans";    src: url("fonts/plexsans-600.woff2") format("woff2");        font-weight: 600; font-display: swap; }
@font-face { font-family: "fx-plexmono";    src: url("fonts/plexmono-400.woff2") format("woff2");        font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-bodoni";      src: url("fonts/bodonimoda-400.woff2") format("woff2");      font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-bodoni";      src: url("fonts/bodonimoda-700.woff2") format("woff2");      font-weight: 700; font-display: swap; }
@font-face { font-family: "fx-crimson";     src: url("fonts/crimsonpro-400.woff2") format("woff2");      font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-inter";       src: url("fonts/inter-400.woff2") format("woff2");           font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-inter";       src: url("fonts/inter-600.woff2") format("woff2");           font-weight: 600; font-display: swap; }
@font-face { font-family: "fx-jetbrains";   src: url("fonts/jetbrainsmono-400.woff2") format("woff2");   font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-jetbrains"; src: url("fonts/jetbrainsmono-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "fx-jetbrains"; src: url("fonts/jetbrainsmono-700.woff2") format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "fx-playfair"; src: url("fonts/playfair-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-sourceserif"; src: url("fonts/sourceserif-600.woff2") format("woff2"); font-weight: 600; font-display: swap; }
@font-face { font-family: "fx-caslond";     src: url("fonts/librecaslondisp-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-caslont";     src: url("fonts/librecaslontext-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-franklin";    src: url("fonts/librefranklin-400.woff2") format("woff2");   font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-franklin";    src: url("fonts/librefranklin-600.woff2") format("woff2");   font-weight: 600; font-display: swap; }
@font-face { font-family: "fx-dmmono";      src: url("fonts/dmmono-400.woff2") format("woff2");          font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-geist";       src: url("fonts/geist-400.woff2") format("woff2");           font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-geist";       src: url("fonts/geist-600.woff2") format("woff2");           font-weight: 600; font-display: swap; }
@font-face { font-family: "fx-geistmono";   src: url("fonts/geistmono-400.woff2") format("woff2");       font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-bricolage";   src: url("fonts/bricolage-700.woff2") format("woff2");       font-weight: 700; font-display: swap; }
@font-face { font-family: "fx-instsans";    src: url("fonts/instrumentsans-400.woff2") format("woff2");  font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-instserif";   src: url("fonts/instrumentserif-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-martian";     src: url("fonts/martianmono-400.woff2") format("woff2");     font-weight: 400; font-display: swap; }
@font-face { font-family: "fx-spacegro";    src: url("fonts/spacegrotesk-500.woff2") format("woff2");    font-weight: 500; font-display: swap; }
@font-face { font-family: "fx-spacemono";   src: url("fonts/spacemono-400.woff2") format("woff2");       font-weight: 400; font-display: swap; }

@font-face { font-family: "fx-playfair";    src: url("fonts/playfair-italic400.woff2") format("woff2");   font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "fx-bodoni";      src: url("fonts/bodoni-italic400.woff2") format("woff2");     font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "fx-instserif";   src: url("fonts/instrumentserif-italic.woff2") format("woff2"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "fx-crimson";     src: url("fonts/crimson-italic400.woff2") format("woff2");    font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "fx-sourceserif"; src: url("fonts/sourceserif-italic400.woff2") format("woff2"); font-weight: 400; font-style: italic; font-display: swap; }

/* The headline's thick/thin: the roman carries the weight, the italic answers it light.
   With real italics loaded the contrast is drawn rather than slanted by the browser. */
h1 em, h2 em, .gr-open h1 em { font-style: italic; font-weight: 400; }
html[data-type="geist"] h1 em, html[data-type="bricolage"] h1 em, html[data-type="space"] h1 em,
html[data-type="geist"] h2 em, html[data-type="bricolage"] h2 em, html[data-type="space"] h2 em {
  font-family: var(--serif); font-weight: 400; }

/* Each system sets the whole set — and each carries its OWN mono, because the mono
   is half this design's voice (every label, identifier, strip and stamp is set in it).
   --display headings · --sub sub-heads · --body paragraphs · --chip badges and stamps
   · --mono labels and code · --sans UI and buttons · --serif quotations */
html[data-type="broadsheet"] { --display:"fx-playfair",Georgia,serif;  --sub:"fx-plexsans",sans-serif;  --body:"fx-sourceserif",Georgia,serif; --chip:"fx-plexmono",monospace;  --mono:"fx-plexmono",Menlo,monospace;  --sans:"fx-plexsans",sans-serif;  --serif:"fx-sourceserif",Georgia,serif; }
html[data-type="didone"]     { --display:"fx-bodoni",Georgia,serif;    --sub:"fx-bodoni",Georgia,serif; --body:"fx-crimson",Georgia,serif;     --chip:"fx-jetbrains",monospace; --mono:"fx-jetbrains",Menlo,monospace; --sans:"fx-inter",sans-serif;    --serif:"fx-crimson",Georgia,serif; }
html[data-type="caslon"]     { --display:"fx-caslond",Georgia,serif;   --sub:"fx-franklin",sans-serif;  --body:"fx-caslont",Georgia,serif;     --chip:"fx-dmmono",monospace;    --mono:"fx-dmmono",Menlo,monospace;    --sans:"fx-franklin",sans-serif; --serif:"fx-caslont",Georgia,serif; }
/* the current-generation three */
html[data-type="geist"]      { --display:"fx-geist",sans-serif;        --sub:"fx-geist",sans-serif;     --body:"fx-geist",sans-serif;          --chip:"fx-geistmono",monospace; --mono:"fx-geistmono",Menlo,monospace; --sans:"fx-geist",sans-serif;    --serif:"fx-instserif",Georgia,serif; }
html[data-type="bricolage"]  { --display:"fx-bricolage",sans-serif;    --sub:"fx-instsans",sans-serif;  --body:"fx-instsans",sans-serif;       --chip:"fx-martian",monospace;   --mono:"fx-martian",Menlo,monospace;   --sans:"fx-instsans",sans-serif; --serif:"fx-instserif",Georgia,serif; }
html[data-type="space"]      { --display:"fx-spacegro",sans-serif;     --sub:"fx-spacegro",sans-serif;  --body:"fx-instsans",sans-serif;       --chip:"fx-spacemono",monospace; --mono:"fx-spacemono",Menlo,monospace; --sans:"fx-spacegro",sans-serif; --serif:"fx-instserif",Georgia,serif; }
/* the sans-led systems want tighter display tracking and a smaller mono, or the
   labels grow past their strips — Martian and Space Mono both run wide */
html[data-type="geist"] h1, html[data-type="bricolage"] h1, html[data-type="space"] h1,
html[data-type="geist"] h2, html[data-type="bricolage"] h2, html[data-type="space"] h2 { letter-spacing: -.03em; }
html[data-type="bricolage"] .chapter, html[data-type="space"] .chapter,
html[data-type="bricolage"] .whisper, html[data-type="space"] .whisper { font-size: 9px; letter-spacing: .12em; }

/* the set is honoured everywhere it has a job */
h3, .figure-heading b, .problem-scene__answer b, .sp-stage h3 { font-family: var(--sub, var(--body)); }
.stamp-el, .pill, .pillt, .b-s, .cm-fine, .pf-by, .gr-badge, .whisper { font-family: var(--chip, var(--mono)); }
.btn, .pr-run, .cb-cpy { font-family: var(--sans, var(--mono)); }

/* ============================================ the footer, as the sheet's colophon
   The zigzag was a sticker, not a drawn edge. The sheet now ends the way a sheet
   ends: a perforation line, a cut, air, and a title strip naming what follows. */
.foot-edge { position: relative; height: 46px; margin-top: 96px; background: var(--paper); }
.foot-edge .fe-perf { position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: radial-gradient(circle, color-mix(in srgb, var(--ink) 42%, transparent) 1px, transparent 1.6px) 0 50%/9px 1px repeat-x; }
.foot-edge .fe-cut { position: absolute; left: 0; right: 0; bottom: 0; height: 22px;
  background: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--deep) 26%, transparent) 0 1px, transparent 1px 9px);
  border-top: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-bottom: 1px solid var(--deep); }
footer { margin-top: 0; padding-top: 54px; }
.foot-title { display: flex; align-items: baseline; gap: 0; margin: 0 0 40px;
  padding-bottom: 12px; border-bottom: 1px solid color-mix(in srgb, var(--on-deep, #fff) 24%, transparent);
  font-family: var(--mono); font-size: 10px; letter-spacing: .24em; text-transform: uppercase;
  color: color-mix(in srgb, var(--on-deep, #fff) 62%, transparent); }
.foot-title i { flex: 1; height: 1px; margin: 0 16px;
  background: radial-gradient(circle, color-mix(in srgb, var(--on-deep, #fff) 34%, transparent) .8px, transparent 1px) 0 50%/7px 1px repeat-x; }
.foot-title span:first-child { color: var(--pop); }
/* the columns get rules, so the footer reads as ruled paper rather than a flat block */
.foot-grid > * + * { border-left: 1px solid color-mix(in srgb, var(--on-deep, #fff) 12%, transparent); padding-left: 28px; }
.foot-col h2 { padding-bottom: 8px; border-bottom: 1px solid color-mix(in srgb, var(--on-deep, #fff) 16%, transparent); }
@media (max-width: 900px) {
  .foot-edge { margin-top: 64px; height: 34px; }
  .foot-title { flex-wrap: wrap; gap: 6px 0; }
  .foot-title i { min-width: 24px; }
  .foot-grid > * + * { border-left: 0; padding-left: 0; }
}

/* ---- the platform marquee, back and drawn properly: a ruled band of names with
   line icons, scrolling slowly, paused when the reader asks for less motion. */
.plat-band { position: relative; overflow: hidden; width: 100%;
  border-top: 1px solid color-mix(in srgb, var(--ink) 26%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 26%, transparent);
  background: color-mix(in srgb, var(--paper-hi) 70%, transparent); }
.plat-band::before, .plat-band::after { content: ""; position: absolute; top: 0; bottom: 0; width: 120px; z-index: 2; pointer-events: none; }
.plat-band::before { left: 0; background: linear-gradient(90deg, var(--paper), transparent); }
.plat-band::after { right: 0; background: linear-gradient(270deg, var(--paper), transparent); }
.plat-run { display: flex; width: max-content; animation: plat-scroll 38s linear infinite; }
.plat-run > span { display: inline-flex; align-items: center; gap: 11px; padding: 15px 34px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft); white-space: nowrap; }
.plat-run svg { width: 17px; height: 17px; fill: none; stroke: var(--ink-faint);
  stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
@keyframes plat-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .plat-run { animation: none; } }

/* ---- draft statements: real words, on the page, unmistakably not yet approved.
   The dashed rule and the warn-tone label are the honesty; remove BOTH only when
   the person has confirmed, and move the counter off zero in the same edit. */
.proof .pf-slot.draft { position: relative; border-style: dashed; border-color: color-mix(in srgb, var(--v5) 40%, transparent); }
.proof .pf-draft { display: block; margin-bottom: 10px; font-family: var(--mono); font-size: 8.5px;
  letter-spacing: .22em; text-transform: uppercase; color: var(--v5); }
.proof .pf-slot.draft .pf-q { color: var(--ink); font-size: 19px; line-height: 1.34; }
.proof .pf-slot.draft .pf-by { color: var(--ink-soft); }
.proof .pf-note b { color: var(--ink); }


/* ═══════════════════════════════════════════════════════════════════════════
   THE PRODUCT CHROME — www.foxora.ai's header and footer, on this sheet.
   Scoped to body.product (runtime.html / grip.html / fennec.html opt in by
   declaring data-product); the company and Runtime sheets are untouched.
   Every value is chrome.css / v5.css on the Studio site, restated in this
   sheet's tokens. No hex below; nothing rounder than the button's 8px.
   ═══════════════════════════════════════════════════════════════════════ */
/* 1 · the notice strip: a drawing's revision note — key, dotted rule, the line */
body.product .notice { text-align: left; border-bottom: 1px solid color-mix(in srgb, var(--on-deep) 20%, transparent); }
body.product .notice .notice-row {
  display: flex; align-items: center; min-height: 26px; gap: 0;
  font-family: var(--mono); font-size: 10px; line-height: 1.4; letter-spacing: .2em; text-transform: uppercase;
  color: color-mix(in srgb, var(--on-deep) 74%, var(--deep));
}
body.product .notice .notice-key { flex: none; letter-spacing: .24em; color: var(--on-deep); }
body.product .notice .notice-rule {
  flex: 1; min-width: 18px; height: 1px; margin: 0 14px;
  background: radial-gradient(circle, color-mix(in srgb, var(--on-deep) 46%, transparent) .8px, transparent 1px) 0 50% / 7px 1px repeat-x;
}
body.product .notice a { flex: none; display: inline; padding: 0; font-size: inherit; letter-spacing: inherit; color: color-mix(in srgb, var(--on-deep) 82%, var(--deep)); transition: color 180ms ease; }
body.product .notice a i { color: var(--on-deep); }
body.product .notice a:hover { color: var(--on-deep); }
@media (max-width: 720px) {
  body.product .notice .notice-key, body.product .notice .notice-rule { display: none; }
  body.product .notice a { flex: 1; text-align: center; letter-spacing: .14em; }
}
/* 2 · the nav: the family, a rule, the one off-site link; Sign in and Download on the right */
body.product .links { align-items: center; gap: 20px; }
body.product .links .nav-sep { width: 1px; height: 16px; background: var(--rule); }
body.product .links a.offsite { display: inline-flex; align-items: center; gap: 3px; }
body.product .links a.offsite svg { width: 12px; height: 12px; opacity: .7; }
body.product .nav-right { gap: 8px; }
body.product .nav-right .btn {
  font-family: var(--sans); font-size: 12.5px; font-weight: 400; line-height: 1.5;
  padding: 8px 14px; gap: 8px; border-radius: 8px; box-shadow: none;
}
body.product .nav-right .btn svg { width: 13px; height: 13px; fill: currentColor; opacity: .85; flex: none; }
body.product .nav-right .btn.hollow { background: transparent; color: var(--ink); border-color: color-mix(in srgb, var(--ink) 40%, transparent); }
@media (max-width: 640px) { body.product .nav-right .btn.hollow { display: none; } }
@media (max-width: 720px) { body.product .links .nav-sep { display: none; } }
/* 3 · the footer: the colophon rail, the two off-site properties as ruled rows, four ruled columns */
body.product footer {
  --fp-hi: color-mix(in srgb, var(--paper-hi) 94%, var(--deep));
  --fp-ink: color-mix(in srgb, var(--paper-hi) 76%, var(--deep));
  --fp-soft: color-mix(in srgb, var(--paper-hi) 58%, var(--deep));
  --fp-rule: color-mix(in srgb, var(--on-deep) 20%, transparent);
  --fp-rule-soft: color-mix(in srgb, var(--on-deep) 12%, transparent);
  color: var(--fp-ink);
}
body.product .foot-title span:first-child { color: var(--on-deep); }
body.product .fp-offsite { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; }
body.product .fp-card {
  display: flex; flex-direction: column; color: var(--fp-ink);
  border-top: 1px solid var(--fp-rule); padding: 20px 28px 22px 0;
  transition: border-color 200ms ease;
}
body.product .fp-card:hover { border-top-color: var(--on-deep); }
body.product .fp-card + .fp-card { padding-left: 28px; border-left: 1px solid var(--fp-rule-soft); }
body.product .fp-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
body.product .fp-name { font-family: var(--display); font-weight: 400; font-size: 1.05rem; color: var(--fp-hi); }
body.product .fp-host { font-family: var(--mono); font-size: .68rem; letter-spacing: .06em; color: color-mix(in srgb, var(--on-deep) 70%, transparent); }
body.product .fp-blurb { margin-top: .55rem; font-family: var(--body); font-size: .88rem; line-height: 1.6; color: var(--fp-soft); flex: 1; max-width: 56ch; }
body.product .fp-cta {
  display: inline-flex; align-items: center; gap: .3rem; margin-top: 1rem;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--on-deep);
}
body.product .fp-cta svg { width: 14px; height: 14px; transition: transform 220ms cubic-bezier(.2,.7,.3,1); }
body.product .fp-card:hover .fp-cta svg { transform: translate(2px, -2px); }
body.product .foot-grid { margin-top: 52px; }
body.product .foot-grid > * + * { border-left: 1px solid var(--fp-rule-soft); padding-left: 28px; }
body.product .foot-brand p { color: var(--fp-soft); max-width: 32ch; }
body.product .fb-docs {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 18px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--on-deep);
}
body.product .fb-docs svg { width: 13px; height: 13px; }
body.product .foot-col h2 { font-size: 10px; color: var(--on-deep); }
body.product .foot-col a { color: color-mix(in srgb, var(--fp-ink) 92%, transparent); letter-spacing: .02em; }
body.product .foot-col a:hover { color: var(--on-deep); }
body.product .colophon { flex-wrap: wrap; gap: 10px 26px; border-top-color: var(--fp-rule); color: color-mix(in srgb, var(--on-deep) 66%, transparent); }
@media (max-width: 900px) { body.product .foot-grid > * + * { border-left: 0; padding-left: 0; } }
@media (max-width: 760px) { body.product .fp-offsite { grid-template-columns: 1fr; } body.product .fp-card + .fp-card { padding-left: 0; border-left: 0; } }

/* 4 · the button, as www.foxora.ai sets it — on every product sheet. 8px corner, the platform
   UI sans at 13.5px/400 on a 1.5 line, 13px 21px, no printed-edge shadow; the primary inks up on
   hover with a ring of the pop, the hollow keeps the paper and takes the same ring. */
body.product .btn {
  font-family: var(--sans); font-size: 13.5px; font-weight: 400; line-height: 1.5;
  padding: 13px 21px; gap: 9px; border-radius: 8px;
  background: var(--pop); color: var(--pop-ink); border: 1px solid var(--pop); box-shadow: none;
  transition: transform .3s cubic-bezier(.22,1,.36,1), background .25s ease, border-color .25s ease, color .25s ease, box-shadow .25s ease;
}
body.product .btn:hover { background: var(--ink); border-color: var(--ink); color: var(--paper-hi); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 38%, transparent); transform: translateY(-1px); }
body.product .btn:active { transform: scale(.97); }
body.product .btn:disabled { opacity: .6; transform: none; cursor: progress; }
body.product .btn.hollow { background: transparent; color: var(--ink); border-color: color-mix(in srgb, var(--ink) 40%, transparent); box-shadow: none; }
body.product .btn.hollow:hover { background: transparent; color: var(--ink); border-color: var(--ink); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pop) 30%, transparent); }
body.product .nav-right .btn { padding: 8px 14px; font-size: 12.5px; }
/* on the deep sheets — the community close band and the footer — the hollow button inks in cream */
body.product footer .btn.hollow { color: var(--paper-hi); border-color: color-mix(in srgb, var(--paper-hi) 50%, transparent); }
body.product footer .btn.hollow:hover { color: var(--paper-hi); border-color: var(--paper-hi); box-shadow: none; }

/* offsite arrows in every chrome: a glyph, not an illustration */
nav .links a svg, nav .links a.offsite svg, .nav-right a svg, header nav a svg { width: 12px; height: 12px; flex: none; vertical-align: -1px; margin-left: 4px; }

/* the top bar, the same on every chrome: deep band, one line, a link (and a second on standalone hosts) */
body.company .notice, body.runtime .notice, .notice { background: var(--deep); color: var(--on-deep); text-align: left; border-bottom: 1px solid color-mix(in srgb, var(--on-deep) 20%, transparent); }
body.company .notice .notice-row, .notice .notice-row { display: flex; align-items: center; gap: 14px; min-height: 30px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; }
body.company .notice .notice-key, .notice .notice-key { flex: none; letter-spacing: .24em; color: var(--on-deep); }
body.company .notice .notice-rule, .notice .notice-rule { flex: 1; height: 1px; background: color-mix(in srgb, var(--on-deep) 28%, transparent); }
body.company .notice a, .notice .notice-row a { flex: none; display: inline; padding: 0; font-size: inherit; letter-spacing: inherit; color: color-mix(in srgb, var(--on-deep) 82%, var(--deep)); text-decoration: none; }
body.company .notice a:hover, .notice .notice-row a:hover { color: var(--on-deep); text-decoration: underline; text-underline-offset: .25em; }
.notice .notice-2 { margin-left: 18px; }
@media (max-width: 720px) { .notice .notice-rule { display: none; } .notice .notice-row { min-height: 26px; font-size: 9.5px; } .notice .notice-2 { display: none; } }
