/* ══════════════════════════════════════════════════════════════════════
   §00  CASCADE ARCHITECTURE
   ──────────────────────────────────────────────────────────────────────
   Declaring the layer order up front means specificity stops being a
   negotiation. A component rule can never accidentally outrank a state
   rule, and print always wins, without a single !important.

   The order is deliberate:
     reset       — normalise, lowest priority of all
     tokens      — custom property definitions, no selectors of substance
     base        — element defaults, typography
     material    — the substrate: worklets, planes, glass, imagery
     layout      — page scaffolding, grids, sections
     components  — self-contained objects
     responsive  — viewport overrides. MUST outrank components: a media
                   query does not raise specificity, so a breakpoint rule
                   sitting in an earlier layer loses to the component
                   default it is trying to override, silently.
     motion      — animation and scroll-driven timelines
     states      — is-*, [open], :hover, gates
     a11y        — reduced motion, contrast, forced colours
     print       — last, because paper wins
   ══════════════════════════════════════════════════════════════════ */
@layer reset, tokens, base, material, layout, components, responsive,
       motion, states, a11y, print;


/* ══════════════════════════════════════════════════════════════════════
   §01  TYPED CUSTOM PROPERTIES
   ──────────────────────────────────────────────────────────────────────
   Registering a custom property gives it a type, which is what makes it
   animatable and interpolatable. Untyped custom properties are strings,
   so a transition on them snaps; these tween.

   This is what lets the rim light sweep round a panel edge, the glyphs
   draw themselves, and the counters run without JS touching textContent.
   ══════════════════════════════════════════════════════════════════ */

/* --- specular and rim geometry -------------------------------------
   inherits: true is load-bearing on every property below that a
   pseudo-element reads. A registered property with inherits: false is
   invisible to ::before and ::after, which resolve it to the initial
   value instead — so the specular highlight, the button sweep and the
   magnitude bar all silently stop tracking. Unregistered custom
   properties inherit by default, which is why this only becomes a
   hazard once they are typed. */
@property --mx {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 28%;
}
@property --my {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 0%;
}
@property --rim-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 152deg;
}

/* --- button magnetism and sweep ------------------------------------ */
@property --bx {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 50%;
}
@property --by {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 50%;
}
@property --sweep {
  syntax: '<percentage>';
  inherits: true;
  initial-value: -40%;
}

/* --- reveal cascade ----------------------------------------------- */
@property --rd {
  syntax: '<time>';
  inherits: false;
  initial-value: 0ms;
}

/* --- the causal chain: a single number drives the whole diagram ---- */
@property --chain-progress {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* --- glyph line drawing ------------------------------------------- */
@property --draw {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}

/* --- instrument dials --------------------------------------------- */
@property --bar {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 0%;
}

/* --- substrate drift ---------------------------------------------- */
@property --drift-x {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}
@property --drift-y {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

/* --- houdini worklet inputs ---------------------------------------- */
@property --metal-seed {
  syntax: '<number>';
  inherits: false;
  initial-value: 11;
}
@property --metal-density {
  syntax: '<number>';
  inherits: false;
  initial-value: 0.72;
}
@property --metal-contrast {
  syntax: '<number>';
  inherits: false;
  initial-value: 0.55;
}
@property --lattice-gap {
  syntax: '<length>';
  inherits: false;
  initial-value: 34px;
}
@property --lattice-bay {
  syntax: '<length>';
  inherits: false;
  initial-value: 112px;
}


/* ══════════════════════════════════════════════════════════════════════
   §02  TOKENS
   ──────────────────────────────────────────────────────────────────────
   The palette is authored in oklch, which is perceptually uniform: a
   lightness step of 0.04 looks like the same size step everywhere on the
   ramp, which hex simply cannot promise. Every mid-tone below is derived
   from two anchors with color-mix rather than hand-picked, so the ramp
   cannot drift out of tune when one value changes.

   The @supports block underneath restates all of it in hex. Anything
   that cannot parse oklch gets the exact v3 palette, unchanged.
   ══════════════════════════════════════════════════════════════════ */
@layer tokens {

  :root {
    /* ── faces ───────────────────────────────────────────────────── */
    --display: "Archivo", "Archivo Narrow", "Arial Narrow", Impact, sans-serif;
    --body:    "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
    --mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Consolas, monospace;

    /* ── one easing language ─────────────────────────────────────── */
    --ease:      cubic-bezier(.22, .61, .36, 1);
    --ease-io:   cubic-bezier(.65, .02, .28, 1);
    --ease-out:  cubic-bezier(.16, 1, .3, 1);
    --ease-spring: cubic-bezier(.34, 1.56, .64, 1);

    /* ── metrics ─────────────────────────────────────────────────── */
    --pad:   clamp(20px, 4vw, 56px);
    --maxw:  1240px;
    --nav-h: 70px;
    --hair:  1px;

    /* ── depth scale, so shadows come from one system ────────────── */
    --z-substrate: 0;
    --z-vignette:  1;
    --z-shell:     2;
    --z-rail:      40;
    --z-nav:       50;
    --z-progress:  60;
    --z-grain:     70;
    --z-skip:      100;
  }

  /* ── the palette, in oklch ─────────────────────────────────────── */
  @supports (color: oklch(50% 0.1 250)) {
    :root {
      /* Two anchors, used for the washes that genuinely want to be
         derived. The structural and substrate values below are set
         directly: they were tuned against v3's hex ramp and mixing them
         out of the anchors put the hairlines half a stop too light and
         the mesh two stops too dark. Deriving everything would be a
         tidier story than the one the page actually needs. */
      --anchor-deep:  oklch(14.5% 0.018 250);
      --anchor-light: oklch(92.0% 0.012 240);

      /* substrate ramp */
      --void:    oklch(10.5% 0.014 250);
      --ink:     oklch(15.0% 0.017 250);
      --steel-1: oklch(19.5% 0.019 248);
      --steel-2: oklch(24.0% 0.021 246);
      --steel-3: oklch(29.0% 0.023 245);

      /* structure */
      --line:      oklch(23.5% 0.020 248);
      --line-soft: oklch(18.0% 0.018 251);

      /* the atmospheric mesh. Lighter and more chromatic than the steel
         ramp on purpose: these are lights in the room, not surfaces. */
      --mesh-hi:  oklch(44.0% 0.055 252);
      --mesh-mid: oklch(25.5% 0.038 251);
      --mesh-lo:  oklch(29.0% 0.030 250);
      --mesh-dn:  oklch(32.0% 0.036 252);

      /* type ramp */
      --text:    oklch(92.5% 0.010 240);
      --dim:     oklch(79.5% 0.016 240);
      --mute:    oklch(70.0% 0.018 238);
      --panel-p: oklch(82.0% 0.014 240);

      /* the only accents on the page */
      --amber:      oklch(76.5% 0.135 72);
      --amber-hi:   oklch(85.5% 0.098 78);
      --amber-deep: oklch(62.0% 0.130 66);
      --oxide:      oklch(52.5% 0.115 32);
      --oxide-text: oklch(68.0% 0.128 33);

      /* derived washes, so alpha values stop being magic numbers */
      --amber-wash:  color-mix(in oklch, var(--amber) 12%, transparent);
      --amber-edge:  color-mix(in oklch, var(--amber) 28%, transparent);
      --glass-tint:  color-mix(in oklch, var(--steel-2) 94%, var(--anchor-light));
      --rim-hot:     color-mix(in oklch, var(--anchor-light) 90%, var(--amber));
    }
  }

  /* ── the palette, in hex — the v3 values, exactly ──────────────── */
  @supports not (color: oklch(50% 0.1 250)) {
    :root {
      --void:    #070A0E;
      --ink:     #0C1116;
      --steel-1: #131B23;
      --steel-2: #1A242E;
      --steel-3: #222E3A;

      --line:      #26313D;
      --line-soft: #1A222C;

      --mesh-hi:  #406084;
      --mesh-mid: #1C2E42;
      --mesh-lo:  #263648;
      --mesh-dn:  #2A3E54;

      --text:    #E4EBF2;
      --dim:     #B3C1CC;
      --mute:    #96A5B1;
      --panel-p: #B8C4CE;

      --amber:      #E8A33D;
      --amber-hi:   #F5C87F;
      --amber-deep: #C4801F;
      --oxide:      #B4523A;
      --oxide-text: #E07A57;

      --amber-wash: rgba(232, 163, 61, .12);
      --amber-edge: rgba(232, 163, 61, .28);
      --glass-tint: #1A242E;
      --rim-hot:    #EDF4FC;
    }
  }

  /* ── quality tiers ─────────────────────────────────────────────────
     The script measures the device and writes one of these onto <html>.
     Everything expensive keys off them, so there is exactly one place
     that decides how hard this page is allowed to work.               */
  :root {
    --tier-blur-deep:    18px;
    --tier-blur-shallow:  9px;
    --tier-grain:        .05;
  }
  html.tier-mid {
    --tier-blur-deep:    10px;
    --tier-blur-shallow:  5px;
    --tier-grain:        .035;
  }
  html.tier-low {
    --tier-blur-deep:     0px;
    --tier-blur-shallow:  0px;
    --tier-grain:           0;
  }
  /* the two costliest planes come off entirely on a low-tier device;
     the mesh and the rack lattice carry the substrate on their own */
  html.tier-low .plane--metal,
  html.tier-low .plane--streak { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════
   §03  RESET
   ══════════════════════════════════════════════════════════════════ */
@layer reset {

  *, *::before, *::after { box-sizing: border-box; }

  html {
    background: var(--ink);
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-padding-top: calc(var(--nav-h) + 16px);
  }

  body {
    margin: 0;
    min-height: 100svh;                 /* small viewport unit: no jump
                                           when mobile chrome retracts  */
    background: var(--ink);
    color: var(--text);
    overflow-x: clip;                   /* clip beats hidden here: it does
                                           not create a scroll container,
                                           so sticky still works         */
  }

  /* overflow: clip is newer than sticky-safety concerns; keep a fallback */
  @supports not (overflow: clip) {
    body { overflow-x: hidden; }
  }

  h1, h2, h3, h4, h5, h6, p, dl, dd, figure, blockquote { margin: 0; }
  ul, ol { margin: 0; padding: 0; }
  li { list-style: none; }

  img, svg, canvas, picture, video {
    display: block;
    max-width: 100%;
  }

  button, input, select, textarea {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    margin: 0;
  }

  /* the modern way to opt a whole subtree out of tab order is inert;
     nothing here needs it yet, but decorative canvases do */
  [inert] { pointer-events: none; }
}


/* ══════════════════════════════════════════════════════════════════════
   §04  BASE
   ══════════════════════════════════════════════════════════════════ */
@layer base {

  body {
    font-family: var(--body);
    font-size: 18px;
    line-height: 1.62;
    font-synthesis: none;               /* never fake a weight or slant */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  /* Optical sizing and kerning on, and pretty wrapping where supported.
     text-wrap: pretty fixes the last-line orphan that balance cannot. */
  p, li, dd, figcaption {
    text-wrap: pretty;
    hanging-punctuation: first allow-end;
  }

  h1, h2, h3, h4 {
    font-family: var(--display);
    font-weight: 700;
    font-stretch: 74%;
    text-transform: uppercase;
    letter-spacing: .004em;
    text-wrap: balance;
    font-optical-sizing: auto;
  }

  p { margin-bottom: 1.05em; }
  p:last-child { margin-bottom: 0; }

  a {
    color: var(--amber);
    text-decoration: none;
    transition: color .2s var(--ease);
  }
  a:hover { color: var(--amber-hi); }

  /* Underlines belong on links inside running prose, where they carry
     meaning, and nowhere else. Scoping this by ancestor rather than by
     :not([class]) is the difference between styling prose links and
     accidentally styling every unclassed anchor on the page, which is
     what the nav is made of. */
  :is(.prose, .lede, .sec__p, .step__b, .q__inner, .aside, .xnote,
      .close p, .eng__p, .inst__foot, .res__note, .pop__body) a {
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--amber) 40%, transparent);
    text-decoration-thickness: 1px;
    text-underline-offset: .22em;
    transition: text-decoration-color .25s var(--ease), color .2s var(--ease);
  }
  a:not([class]):hover { text-decoration-color: var(--amber-hi); }

  ::selection {
    background: color-mix(in srgb, var(--amber) 26%, transparent);
    color: #fff;
  }

  :focus-visible {
    outline: 2px solid var(--amber);
    outline-offset: 3px;
    border-radius: 2px;
  }

  /* the scrollbar, styled both ways */
  html { scrollbar-color: var(--steel-3) var(--void); scrollbar-width: thin; }
  ::-webkit-scrollbar { width: 11px; height: 9px; }
  ::-webkit-scrollbar-track { background: var(--void); }
  ::-webkit-scrollbar-thumb {
    background: var(--steel-3);
    border-radius: 6px;
    border: 2px solid var(--void);
  }
  ::-webkit-scrollbar-thumb:hover { background: #3A4856; }

  .sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §05  MATERIAL — the substrate
   ──────────────────────────────────────────────────────────────────────
   Three ways to paint the brushed metal, in descending order of quality,
   selected by @supports:

     1. A Houdini paint worklet. Real per-pixel procedural generation on
        the compositor, driven by typed custom properties, so the seed and
        density can be animated. Chromium only, for now.
     2. An inline SVG feTurbulence data URI. What v3 used. Works
        everywhere, but it is a fixed raster that cannot be animated.
     3. A plain gradient, for anything that supports neither.

   The WebGL field sits above all of them and replaces none of them: if
   the context fails to acquire, the generated planes are still the whole
   substrate and nothing looks broken.
   ══════════════════════════════════════════════════════════════════ */
@layer material {

  .substrate {
    position: fixed;
    inset: 0;
    z-index: var(--z-substrate);
    pointer-events: none;
    contain: strict;
  }

  .plane {
    position: absolute;
    inset: -14%;
    will-change: transform;
  }

  /* ── the gradient mesh: atmosphere ───────────────────────────────── */
  .plane--mesh {
    background:
      radial-gradient(820px 600px at 78% -8%,  color-mix(in srgb, var(--mesh-hi)  50%, transparent), transparent 66%),
      radial-gradient(700px 540px at  4% 22%,  color-mix(in srgb, var(--mesh-mid) 62%, transparent), transparent 70%),
      radial-gradient(560px 420px at 92% 54%,  color-mix(in srgb, var(--mesh-lo)  34%, transparent), transparent 70%),
      radial-gradient(1000px 760px at 46% 106%,color-mix(in srgb, var(--mesh-dn)  40%, transparent), transparent 72%),
      linear-gradient(178deg, var(--steel-1) 0%, var(--void) 54%, var(--ink) 100%);
    translate: var(--drift-x) var(--drift-y);
    scale: 1.06;
    animation: mesh-drift 42s var(--ease-io) infinite alternate;
  }

  @supports not (color: oklch(50% 0.1 250)) {
    .plane--mesh {
      background:
        radial-gradient(820px 600px at 78% -8%,  rgba(64, 96,132,.50), transparent 66%),
        radial-gradient(700px 540px at  4% 22%,  rgba(28, 46, 66,.62), transparent 70%),
        radial-gradient(560px 420px at 92% 54%,  rgba(38, 54, 72,.34), transparent 70%),
        radial-gradient(1000px 760px at 46% 106%,rgba(42, 62, 84,.40), transparent 72%),
        linear-gradient(178deg, #0F161D 0%, #0A0E13 54%, #0C1116 100%);
    }
  }

  @keyframes mesh-drift {
    from { --drift-x:  0%;    --drift-y: 0%;    scale: 1.02; }
    to   { --drift-x: -1.6%;  --drift-y: 1.2%;  scale: 1.08; }
  }

  /* ── brushed metal: tier 1, the paint worklet ───────────────────── */
  .plane--metal {
    opacity: .30;
    mix-blend-mode: soft-light;
    --metal-seed: 11;
    --metal-density: .72;
    --metal-contrast: .55;
    /* fallback first, so the cascade lands on the worklet only if the
       worklet actually registered */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='700' height='420'><filter id='m' x='0' y='0'><feTurbulence type='fractalNoise' baseFrequency='0.006 0.72' numOctaves='4' seed='11' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/><feComponentTransfer><feFuncA type='linear' slope='.55'/></feComponentTransfer></filter><rect width='700' height='420' filter='url(%23m)'/></svg>");
    background-size: 700px 420px;
  }

  /* only browsers that both support paint() and have loaded the worklet
     get this: the html.has-worklet class is set after addModule resolves */
  @supports (background-image: paint(brushed-metal)) {
    html.has-worklet .plane--metal {
      background-image: paint(brushed-metal);
      background-size: auto;
    }
  }

  /* ── rack elevation lattice ──────────────────────────────────────
     The proportion carries the information: uprights wide apart, beam
     levels close together. This is a rack face, not a decorative grid. */
  .plane--rack {
    opacity: .5;
    --lattice-bay: 112px;
    --lattice-gap: 34px;
    background-image:
      linear-gradient(90deg,  color-mix(in srgb, #96B4D2 6%, transparent) 1px, transparent 1px),
      linear-gradient(180deg, color-mix(in srgb, #96B4D2 3%, transparent) 1px, transparent 1px);
    background-size: var(--lattice-bay) 100%, 100% var(--lattice-gap);
    mask-image: radial-gradient(1300px 900px at 50% 2%, #000 0%, rgba(0,0,0,.5) 46%, transparent 78%);
    -webkit-mask-image: radial-gradient(1300px 900px at 50% 2%, #000 0%, rgba(0,0,0,.5) 46%, transparent 78%);
  }

  @supports (background-image: paint(rack-lattice)) {
    html.has-worklet .plane--rack {
      background-image: paint(rack-lattice);
      background-size: auto;
    }
  }

  /* ── long-exposure specular streaks ──────────────────────────────── */
  .plane--streak {
    opacity: .6;
    background:
      linear-gradient(103deg, transparent 22.6%, rgba(196,220,244,.055) 23%,   transparent 23.4%),
      linear-gradient(103deg, transparent 37.7%, rgba(232,163, 61,.050) 38%,   transparent 38.3%),
      linear-gradient(103deg, transparent 58.7%, rgba(196,220,244,.032) 59%,   transparent 59.3%),
      linear-gradient(103deg, transparent 71.6%, rgba(196,220,244,.042) 72%,   transparent 72.4%),
      linear-gradient(103deg, transparent 86.8%, rgba(196,220,244,.028) 87%,   transparent 87.3%);
    mask-image: linear-gradient(180deg, #000, transparent 58%);
    -webkit-mask-image: linear-gradient(180deg, #000, transparent 58%);
  }

  /* ── the WebGL field ─────────────────────────────────────────────
     Sits between the generated planes and the content. It is decorative
     and inert: aria-hidden, inert, pointer-events none, and it is only
     ever inserted by script, so a no-JS reader never sees an empty box
     where a canvas should be.                                         */
  .field {
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.2s var(--ease-out);
    contain: strict;
  }
  html.field-live .field { opacity: 1; }
  .field canvas { width: 100%; height: 100%; display: block; }

  /* ── corner falloff, so the sheet has edges ─────────────────────── */
  .vignette {
    position: fixed;
    inset: 0;
    z-index: var(--z-vignette);
    pointer-events: none;
    background: radial-gradient(140% 110% at 50% 40%, transparent 52%, rgba(4,6,9,.62) 100%);
  }

  /* ── film grain ──────────────────────────────────────────────────
     The one thing that stops glass reading as plastic. The texture is
     generated in a worker into an OffscreenCanvas where available, so
     the main thread never pays for it; the SVG turbulence below is the
     fallback and is what v3 shipped.                                  */
  .grain {
    position: fixed;
    inset: -140px;
    z-index: var(--z-grain);
    pointer-events: none;
    opacity: var(--tier-grain);
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' seed='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='200' height='200' filter='url(%23n)'/></svg>");
    animation: grain-shift 5s steps(4) infinite;
  }
  html.has-grain-bitmap .grain {
    background-image: var(--grain-src);
    background-size: 256px 256px;
  }

  @keyframes grain-shift {
    0%   { translate:  0     0; }
    25%  { translate: -2%    1%; }
    50%  { translate:  1%   -2%; }
    75%  { translate: -1%   -1%; }
    100% { translate:  0     0; }
  }

  .shell { position: relative; z-index: var(--z-shell); }
}


/* ══════════════════════════════════════════════════════════════════════
   §07  MATERIAL — the glass system
   ──────────────────────────────────────────────────────────────────────
   Built as a 1px gradient-filled padding wrapper, not a border colour.
   The wrapper's ::after paints a radial highlight that is visible only in
   that 1px frame, so the rim light travels around the edge with the
   cursor. --rim-angle is a registered <angle>, so the gradient itself can
   be tweened rather than swapped.

   The interior carries a top inner highlight and a bottom occlusion, so a
   panel reads as having thickness rather than being cut from paper. Left
   and right edges separate cool and warm, suggesting refraction, held
   near the threshold of perception.
   ══════════════════════════════════════════════════════════════════ */
@layer material {

  .glass {
    position: relative;
    border-radius: 5px;
    padding: var(--hair);
    background:
      linear-gradient(var(--rim-angle),
        color-mix(in srgb, var(--rim-hot) 40%, transparent)      0%,
        rgba(150, 180, 210, .11)                                24%,
        rgba(110, 140, 170, .045)                               56%,
        var(--amber-wash)                                       87%,
        rgba(196, 220, 244, .17)                                100%);
    box-shadow:
      /* grounding: long, soft, heavily offset. Cheap glass floats. */
      0 44px 88px -32px rgba(0, 0, 0, .86),
      0 14px 30px -14px rgba(0, 0, 0, .52),
      /* chromatic edge */
      -1px 0 0 rgba(118, 168, 220, .055),
       1px 0 0 rgba(232, 163,  61, .045);
  }

  .glass::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: radial-gradient(340px 220px at var(--mx) var(--my),
                color-mix(in srgb, var(--rim-hot) 55%, transparent), transparent 62%);
  }

  .glass__body {
    position: relative;
    z-index: 1;
    border-radius: 4px;
    overflow: hidden;
    background: linear-gradient(180deg,
                color-mix(in srgb, var(--glass-tint) 95%, transparent),
                color-mix(in srgb, var(--ink) 97%, transparent));
    backdrop-filter: blur(var(--tier-blur-deep)) saturate(1.12);
    -webkit-backdrop-filter: blur(var(--tier-blur-deep)) saturate(1.12);
    box-shadow:
      inset 0  1px  0    rgba(220, 238, 255, .15),   /* thickness, top    */
      inset 0 -20px 28px -24px rgba(0, 0, 0, .96);   /* occlusion, bottom */
  }

  /* specular response — position is lerped in script so it trails the
     pointer rather than snapping to it */
  .glass__body::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background: radial-gradient(460px 320px at var(--mx) var(--my),
                rgba(220, 238, 255, .085), transparent 60%);
  }

  /* a shallower plane: less blur, shorter shadow, dimmer rim */
  .glass--recessed {
    background: linear-gradient(var(--rim-angle),
      rgba(206, 228, 250, .23),
      rgba(130, 160, 190, .06) 42%,
      rgba(232, 163,  61, .06) 100%);
    box-shadow:
      0 26px 50px -26px rgba(0, 0, 0, .70),
      0  4px 12px  -6px rgba(0, 0, 0, .40);
  }
  .glass--recessed::after {
    background: radial-gradient(280px 180px at var(--mx) var(--my),
                rgba(232, 244, 255, .30), transparent 62%);
  }
  .glass--recessed .glass__body {
    backdrop-filter: blur(var(--tier-blur-shallow)) saturate(1.06);
    -webkit-backdrop-filter: blur(var(--tier-blur-shallow)) saturate(1.06);
    background: linear-gradient(180deg, rgba(24, 33, 43, .88), rgba(12, 17, 23, .94));
  }

  .parallax { position: relative; z-index: 1; }
}


/* ══════════════════════════════════════════════════════════════════════
   §08  LAYOUT
   ══════════════════════════════════════════════════════════════════ */
@layer layout {

  .wrap {
    position: relative;
    z-index: 1;
    max-width: var(--maxw);
    margin-inline: auto;
    padding-inline: var(--pad);
  }

  .sec {
    position: relative;
    overflow: clip;
    padding-block: clamp(58px, 7vw, 104px);
    border-top: var(--hair) solid var(--line-soft);
    /* container queries need a container. Naming it means a component can
       ask about this specific ancestor rather than the nearest one. */
    container-type: inline-size;
    container-name: section;
    /* skip rendering work for sections far off screen, but supply an
       intrinsic size so the scrollbar does not jitter */
    content-visibility: auto;
    contain-intrinsic-size: auto 900px;
  }
  @supports not (overflow: clip) {
    .sec { overflow: hidden; }
  }

  /* the first and last sections stay always-rendered: the hero because it
     is the first paint, the closer because content-visibility interacts
     badly with a page-bottom scroll anchor */
  .hero, .close { content-visibility: visible; }

  .sec__h {
    font-size: clamp(34px, 4.8vw, 58px);
    line-height: .95;
    font-stretch: 72%;
    color: #fff;
    max-width: 21ch;
  }
  .sec__p {
    font-size: 18px;
    color: var(--dim);
    max-width: 60ch;
  }

  .duo {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: clamp(24px, 4vw, 64px);
    align-items: end;
  }

  .prose { max-width: 70ch; font-size: 18.5px; line-height: 1.68; color: var(--dim); }
  .prose b, .prose strong { color: #fff; font-weight: 500; }

  .lead-p {
    margin-bottom: clamp(26px, 3.2vw, 40px);
    max-width: 66ch;
    font-size: 20px;
    line-height: 1.62;
    color: var(--dim);
  }
  .lead-p b { color: #fff; font-weight: 500; }
}


/* ══════════════════════════════════════════════════════════════════════
   §09  COMPONENTS — structural devices
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .eyebrow {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: clamp(20px, 3vw, 34px);
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .17em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .eyebrow__i { color: var(--amber); flex: none; }
  .eyebrow__t { flex: none; }

  .dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    flex: none;
    background: var(--amber);
    box-shadow: 0 0 12px color-mix(in srgb, var(--amber) 85%, transparent);
  }

  .rule {
    flex: 1;
    height: var(--hair);
    min-width: 24px;
    background: linear-gradient(90deg, var(--line), transparent);
    transform-origin: left center;
  }

  /* the three fixed facts, as discrete stops with hairline separators
     instead of punctuation */
  .stops {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 clamp(14px, 2vw, 26px);
    margin-bottom: clamp(24px, 3.4vw, 38px);
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .stops li { position: relative; padding-block: 2px; }
  .stops li + li { padding-left: clamp(14px, 2vw, 26px); }
  .stops li + li::before {
    content: "";
    position: absolute;
    left: 0; top: 50%;
    width: 1px; height: 11px;
    margin-top: -5.5px;
    background: var(--line);
  }
  .stops .lead { color: var(--amber); }

  /* an aside that qualifies what has just been claimed */
  .aside {
    margin-top: clamp(30px, 3.8vw, 48px);
    padding: 2px 0 2px clamp(18px, 2.4vw, 30px);
    border-left: 2px solid var(--amber);
    max-width: 74ch;
  }
  .aside h3 {
    font-size: 20px;
    font-stretch: 80%;
    line-height: 1.1;
    color: #fff;
    margin-bottom: 10px;
  }
  .aside p { margin-bottom: .8em; font-size: 17.5px; line-height: 1.62; color: var(--dim); }
  .aside p:last-child { margin-bottom: 0; }

  /* engineering dimension callout: extension lines, end ticks, label */
  .dim {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .dim__span { position: relative; flex: 1; height: 7px; min-width: 36px; }
  .dim__span::before {
    content: "";
    position: absolute;
    inset: 3px 0 auto 0;
    height: 1px;
    background: var(--line);
  }
  .dim__span::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 7px;
    border-left: 1px solid var(--line);
    border-right: 1px solid var(--line);
  }
  .dim__v { color: var(--amber); flex: none; }

  /* ── sheet-zone rail ───────────────────────────────────────────────
     An indicator, not navigation, so it is inert and never takes a tab
     stop. Wide viewports only.                                        */
  .rail {
    position: fixed;
    z-index: var(--z-rail);
    top: 50%;
    translate: 0 -50%;
    left: max(14px, calc((100vw - var(--maxw)) / 2 - 46px));
    display: none;
    flex-direction: column;
    gap: 14px;
    pointer-events: none;
  }
  .rail__i { display: flex; align-items: center; gap: 8px; }
  .rail__t {
    width: 14px; height: 1px;
    background: var(--line);
    transition: width .4s var(--ease), background .4s var(--ease);
  }
  .rail__n {
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .12em;
    color: #7E8E9B;
    transition: color .4s var(--ease);
  }
  .rail__i.is-on .rail__t { width: 22px; background: var(--amber); }
  .rail__i.is-on .rail__n { color: var(--amber); }

  /* ── scroll progress ──────────────────────────────────────────────
     Where scroll-driven animations exist this is pure CSS on the
     compositor and the script never touches it. See §16.             */
  .progress {
    position: fixed;
    inset: 0 0 auto 0;
    height: 2px;
    z-index: var(--z-progress);
    pointer-events: none;
    background: linear-gradient(90deg, var(--amber), var(--amber-hi));
    scale: 0 1;
    transform-origin: left center;
    box-shadow: 0 0 10px color-mix(in srgb, var(--amber) 60%, transparent);
  }

  .skip {
    position: fixed;
    top: 8px; left: 8px;
    z-index: var(--z-skip);
    translate: 0 -160%;
    padding: 12px 18px;
    border-radius: 3px;
    background: var(--amber);
    color: #14100A;
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    transition: translate .2s var(--ease);
  }
  .skip:focus { translate: 0 0; color: #14100A; }
  /* the skip target takes focus programmatically; it is a landmark, not
     a control, so it should not paint a ring when it receives it */
  main:focus { outline: none; }
}


/* ══════════════════════════════════════════════════════════════════════
   §10  COMPONENTS — navigation
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .nav {
    position: sticky;
    top: 0;
    z-index: var(--z-nav);
    background: color-mix(in srgb, var(--void) 72%, transparent);
    backdrop-filter: blur(14px) saturate(1.1);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    border-bottom: var(--hair) solid var(--line-soft);
    box-shadow: inset 0 1px 0 rgba(220, 238, 255, .06);
    transition: background .4s var(--ease), border-color .4s var(--ease);
  }
  .nav .wrap {
    display: flex;
    align-items: center;
    gap: clamp(14px, 3vw, 40px);
    height: var(--nav-h);
  }

  .brand { display: flex; align-items: center; gap: 11px; white-space: nowrap; color: #fff; }
  .brand:hover { color: #fff; }
  .brand__mark { width: 20px; height: 20px; flex: none; overflow: visible; }
  .brand__mark rect { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; }
  .brand__mark .r-book  { stroke: var(--mute);  transition: translate .5s var(--ease); }
  .brand__mark .r-floor { stroke: var(--amber); transition: translate .5s var(--ease); }
  .brand:hover .r-book  { translate: -1px -1px; }
  .brand:hover .r-floor { translate:  1px  1px; }
  .brand__w {
    font-family: var(--display);
    font-size: 23px;
    font-weight: 700;
    font-stretch: 82%;
    letter-spacing: .05em;
    text-transform: uppercase;
    line-height: 1;
  }
  .brand__w em { font-style: normal; color: var(--amber); }

  .nav__readout {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: #95A3AF;
  }
  .nav__readout .rule { max-width: 100px; }
  .nav__readout b {
    font-weight: 500;
    color: var(--mute);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .nav__links {
    display: flex;
    align-items: center;
    gap: clamp(12px, 1.6vw, 22px);
    white-space: nowrap;
    margin-left: auto;
  }
  .nav__links a:not(.btn) {
    position: relative;
    padding-block: 4px;
    font-family: var(--mono);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--dim);
  }
  .nav__links a:not(.btn)::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 1px;
    background: var(--amber);
    scale: 0 1;
    transform-origin: left center;
    transition: scale .3s var(--ease);
  }
  .nav__links a:not(.btn):hover { color: #fff; }
  .nav__links a:not(.btn):hover::after { scale: 1 1; }
}


/* ══════════════════════════════════════════════════════════════════════
   §11  COMPONENTS — controls
   ──────────────────────────────────────────────────────────────────────
   The sweep uses a registered <percentage>, so the highlight travelling
   across the face is a real interpolation rather than a background swap.
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 15px 24px;
    border-radius: 3px;
    overflow: hidden;
    text-align: center;
    cursor: pointer;
    font-family: var(--mono);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: .09em;
    text-transform: uppercase;
    transition:
      background .25s var(--ease),
      border-color .25s var(--ease),
      color .25s var(--ease),
      --sweep .55s var(--ease-out);
  }
  .btn::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(130px 90px at var(--bx) var(--by),
                rgba(255, 255, 255, .26), transparent 62%);
    opacity: 0;
    transition: opacity .3s var(--ease);
  }
  .btn:hover::after { opacity: 1; }

  /* a second, slower sheen that crosses the whole face once on hover */
  .btn::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(100deg,
      transparent calc(var(--sweep) - 18%),
      rgba(255, 255, 255, .16) var(--sweep),
      transparent calc(var(--sweep) + 18%));
  }
  .btn:hover { --sweep: 140%; }

  .btn__arw {
    width: 8px; height: 8px;
    flex: none;
    border-top: 1.5px solid currentColor;
    border-right: 1.5px solid currentColor;
    rotate: 45deg;
    transition: translate .3s var(--ease);
  }
  .btn:hover .btn__arw { translate: 2px -2px; }

  .btn--primary {
    background: var(--amber);
    color: #14100A;
    box-shadow:
      0 14px 30px -12px color-mix(in srgb, var(--amber) 48%, transparent),
      inset 0 1px 0 rgba(255, 255, 255, .42);
  }
  .btn--primary:hover { background: var(--amber-hi); color: #14100A; }

  .btn--ghost {
    border: 1px solid var(--line);
    color: var(--text);
    background: rgba(160, 190, 215, .045);
    box-shadow: inset 0 1px 0 rgba(220, 238, 255, .05);
  }
  .btn--ghost:hover { border-color: #3F5162; color: #fff; background: rgba(160, 190, 215, .075); }

  .btn--sm { padding: 11px 18px; font-size: 12.5px; }
  .btn--lg { padding: 17px 32px; font-size: 14.5px; }
}


/* ══════════════════════════════════════════════════════════════════════
   §13  COMPONENTS — stepped document rows
   ──────────────────────────────────────────────────────────────────────
   A narrow mono key column against a wide prose column. Used by both
   method sections, so the two read as parts of one specification rather
   than as two different designs.

   The breakpoint is a container query, not a media query: these rows
   collapse when their own column gets narrow, which is the thing that
   actually matters, and it means the component behaves correctly if it is
   ever dropped into a sidebar.
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .steps { margin-top: clamp(30px, 4vw, 52px); }

  .step {
    display: grid;
    grid-template-columns: 196px 1fr;
    gap: clamp(18px, 4vw, 56px);
    padding-block: clamp(26px, 3.2vw, 42px);
    border-top: var(--hair) solid var(--line-soft);
  }
  .step:last-child { border-bottom: var(--hair) solid var(--line-soft); }

  @container section (max-width: 720px) {
    .step { grid-template-columns: 1fr; gap: 14px; }
  }

  .step__k { position: relative; }
  .step__n {
    display: block;
    margin-bottom: 9px;
    font-family: var(--mono);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--amber);
  }
  .step__t {
    font-size: clamp(25px, 2.6vw, 32px);
    line-height: 1.02;
    font-stretch: 76%;
    color: #fff;
  }
  .step__b { max-width: 66ch; }
  .step__b p { margin-bottom: .95em; font-size: 17.5px; line-height: 1.66; color: var(--dim); }
  .step__b p:last-child { margin-bottom: 0; }
  .step__b b, .step__b strong { color: #fff; font-weight: 500; }

  /* a mono list of concrete checks, so a claim is followed by specifics */
  .checks {
    margin-top: 18px;
    border-top: var(--hair) solid var(--line-soft);
  }
  .checks li {
    position: relative;
    padding: 9px 0 9px 20px;
    border-bottom: var(--hair) solid var(--line-soft);
    font-family: var(--mono);
    font-size: 13.5px;
    line-height: 1.55;
    letter-spacing: .005em;
    color: #B4C2CE;
  }
  .checks li:last-child { border-bottom: none; }
  .checks li::before {
    content: "";
    position: absolute;
    left: 1px; top: 16px;
    width: 7px; height: 1px;
    background: var(--amber);
    /* scaleX is driven by --draw so the ticks can draw themselves in */
    transform-origin: left center;
    scale: var(--draw) 1;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §18  COMPONENTS — questions
   ──────────────────────────────────────────────────────────────────────
   Three implementations, best first.

     1. interpolate-size: allow-keywords plus ::details-content. The
        browser animates height to and from the keyword auto natively, and
        ::details-content gives us the generated box that wraps a closed
        details' children. No script at all: open state, keyboard, and the
        screen-reader expanded announcement are entirely the browser's.
     2. The v3 script path, which measures and tweens the height.
     3. Plain <details>, which snaps. Still perfectly usable.

   Where 1 is available the script leaves the FAQ completely alone, which
   is the whole argument for these features: less of our code in the way
   of something the platform now does better.
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .faq {
    border-top: var(--hair) solid var(--line);
    max-width: 980px;
    margin-top: clamp(26px, 4vw, 44px);
  }

  .q { position: relative; border-bottom: var(--hair) solid var(--line); }
  .q::before {
    content: "";
    position: absolute;
    left: -1px; top: 0; bottom: 0;
    width: 1px;
    background: var(--amber);
    scale: 1 0;
    transform-origin: top center;
    transition: scale .4s var(--ease);
  }
  .q[open]::before { scale: 1 1; }

  .q > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: flex-start;
    gap: clamp(14px, 2vw, 24px);
    padding: 21px 2px 21px 0;
  }
  .q > summary::-webkit-details-marker { display: none; }
  .q > summary::marker { content: ""; }

  .q__n {
    flex: none;
    padding-top: 6px;
    font-family: var(--mono);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .14em;
    color: var(--mute);
    transition: color .3s var(--ease);
  }
  .q__t {
    flex: 1;
    font-family: var(--display);
    font-weight: 700;
    font-stretch: 78%;
    font-size: clamp(21px, 2.2vw, 26px);
    line-height: 1.1;
    text-transform: uppercase;
    color: #fff;
    transition: color .25s var(--ease);
  }
  .q > summary:hover .q__t { color: var(--amber-hi); }
  .q > summary:hover .q__n { color: var(--amber); }
  .q[open] .q__n { color: var(--amber); }

  .q__pm { position: relative; width: 13px; height: 13px; flex: none; margin-top: 9px; }
  .q__pm::before,
  .q__pm::after {
    content: "";
    position: absolute;
    background: var(--amber);
    transition: rotate .32s var(--ease), opacity .32s var(--ease);
  }
  .q__pm::before { inset: 6px 0 auto 0; height: 1px; }
  .q__pm::after  { inset: 0 auto 0 6px; width: 1px; }
  .q[open] .q__pm::before { rotate: 90deg; }
  .q[open] .q__pm::after  { rotate: 90deg; opacity: 0; }

  .q__a { overflow: hidden; }
  .q__inner {
    padding: 0 0 26px clamp(28px, 4.4vw, 50px);
    max-width: 76ch;
  }
  .q__a p { margin-bottom: .9em; font-size: 17.5px; line-height: 1.68; color: var(--dim); }
  .q__a p:last-child { margin-bottom: 0; }

  /* ── tier 1: the platform does it ──────────────────────────────── */
  @supports (interpolate-size: allow-keywords) and selector(::details-content) {

    /* opting the page in is what makes height: auto interpolable */
    :root { interpolate-size: allow-keywords; }

    /* the script reads this class and stands down */
    html.native-details .q { }

    html.native-details .q::details-content {
      block-size: 0;
      overflow: hidden;
      opacity: 0;
      /* allow-discrete lets content-visibility flip at the right end of
         the transition instead of instantly */
      transition:
        block-size .44s var(--ease-out),
        opacity .34s var(--ease),
        content-visibility .44s allow-discrete;
    }
    html.native-details .q[open]::details-content {
      block-size: auto;
      opacity: 1;
    }
    /* with the native path live, the wrapper div stops doing any work */
    html.native-details .q__a { overflow: visible; }
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §19  COMPONENTS — the variance exception panel
   ──────────────────────────────────────────────────────────────────────
   The strongest glass object on the page, and the first thing below the
   hero copy. The buyer reads a report shaped exactly like this every
   week, so it establishes domain fluency before a word of prose gets
   read — which is the whole reason it sits this high.

   It is a real <table>. The columns carry a header relationship, the
   numbers are tabular, and the whole thing is legible with scripting
   off: the animation only ever removes a gate that CSS applied.

   Overflow on narrow screens is handled with the local-attachment
   background technique rather than a scroll listener — the covers move
   with the content while the shadows stay fixed, so the affordance
   appears and disappears at exactly the right moments with no script at
   all. That matters here: a scroll cue that needs JS to exist is a cue
   that is missing in the one situation it is needed most.
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .report { margin-top: clamp(40px, 5vw, 76px); }

  /* the deepest plane in the glass system: most blur, strongest rim,
     longest throw */
  .glass--deep {
    box-shadow:
      0 60px 116px -34px rgba(0, 0, 0, .90),
      0 18px  40px -16px rgba(0, 0, 0, .62),
      -1px 0 0 rgba(118, 168, 220, .07),
       1px 0 0 rgba(232, 163,  61, .05);
  }
  .glass--deep .glass__body {
    backdrop-filter: blur(calc(var(--tier-blur-deep) * 1.22)) saturate(1.16);
    -webkit-backdrop-filter: blur(calc(var(--tier-blur-deep) * 1.22)) saturate(1.16);
  }

  .vp__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 14px 18px;
    border-bottom: var(--hair) solid var(--line);
    background: linear-gradient(180deg, rgba(220, 238, 255, .07), transparent);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
  }
  .vp__title { display: flex; align-items: center; gap: 9px; color: #B7C5D2; }
  .vp__title .dot { width: 5px; height: 5px; }
  .vp__meta { color: var(--mute); }

  .vp__viewport { position: relative; }

  /* Two pairs of layers. The solid "covers" are attached local, so they
     scroll away with the content; the shadows are attached scroll, so
     they stay put. Where a cover sits over a shadow, the shadow is
     hidden — which is exactly the end of the scroll range. */
  .vp__scroll {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    background:
      linear-gradient(90deg,  var(--vp-bg) 34%, transparent) 0    0 / 44px 100% no-repeat local,
      linear-gradient(270deg, var(--vp-bg) 34%, transparent) 100% 0 / 44px 100% no-repeat local,
      radial-gradient(farthest-side at 0    50%, rgba(0,0,0,.55), transparent) 0    0 / 22px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.55), transparent) 100% 0 / 22px 100% no-repeat scroll,
      var(--vp-bg);
    --vp-bg: #0A0E13;
  }
  @supports (color: oklch(50% 0.1 250)) {
    .vp__scroll { --vp-bg: oklch(13% 0.015 250); }
  }

  .vp {
    width: 100%;
    min-width: 720px;
    border-collapse: collapse;
    font-family: var(--mono);
    font-size: 14px;
    font-variant-numeric: tabular-nums;
  }
  /* Scoped to thead deliberately. The item cell is a <th scope="row">
     for the header relationship it gives assistive tech, but it is data
     and has to look like data — styling bare `th` would hand it the
     column-header background, border weight and colour, and would also
     out-specify .vp__item. */
  .vp thead th {
    padding: 12px 16px;
    text-align: left;
    font-weight: 500;
    font-size: 12px;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--mute);
    white-space: nowrap;
    border-bottom: var(--hair) solid var(--line);
    background: rgba(220, 238, 255, .022);
  }
  .vp td,
  .vp tbody th {
    padding: 13px 16px;
    border-bottom: var(--hair) solid var(--line-soft);
    white-space: nowrap;
    vertical-align: top;
    font-weight: 400;
    background: none;
  }
  .vp tbody th { text-align: left; }
  .vp tbody tr:last-child :is(td, th) { border-bottom: none; }

  .vp__num  { text-align: right; }
  .vp__item { color: #fff; font-weight: 500; }
  .vp__vend { color: #C4D0DB; }
  .vp__book,
  .vp__floor { color: #C4D0DB; }

  /* the numbers pull the eye first; the cause is the payload but reads
     one step quieter */
  .vp__cause {
    white-space: normal;
    min-width: 250px;
    font-size: 13.5px;
    color: var(--dim);
  }

  .vp__delta { font-weight: 500; letter-spacing: .02em; }
  .vp__delta--up { color: var(--amber); }
  .vp__delta--dn { color: var(--oxide-text); }

  /* one faint pulse as the row lands, then never again */
  .vp__delta { transition: text-shadow .34s var(--ease); }
  .vp__row.is-pulse .vp__delta { text-shadow: 0 0 16px currentColor; }

  .vp__row {
    transition:
      background .22s var(--ease),
      box-shadow .22s var(--ease),
      translate  .22s var(--ease);
  }
  .vp__row:hover {
    background: rgba(220, 238, 255, .05);
    box-shadow:
      inset 0  1px 0 rgba(220, 238, 255, .10),
      inset 0 -1px 0 rgba(220, 238, 255, .05);
    translate: 0 -1px;
  }

  .vp__note {
    padding: 13px 18px;
    border-top: var(--hair) solid var(--line);
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.6;
    letter-spacing: .04em;
    color: var(--mute);
    background: linear-gradient(0deg, rgba(220, 238, 255, .035), transparent);
  }

  .vp__hint {
    display: none;
    align-items: center;
    gap: 9px;
    margin-top: 12px;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .vp__hint::before {
    content: "";
    width: 7px; height: 7px;
    flex: none;
    border-top: 1px solid var(--amber);
    border-right: 1px solid var(--amber);
    rotate: 45deg;
  }
  /* the cue is only true when the table actually cannot fit */
  @container hero (max-width: 760px) { .vp__hint { display: flex; } }
  @media (max-width: 760px) { .vp__hint { display: flex; } }
}


/* ══════════════════════════════════════════════════════════════════════
   §22  COMPONENTS — closing, colophon, self-audit
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  .close { text-align: center; padding-block: clamp(66px, 8vw, 116px); }
  .close__bar {
    width: 52px; height: 2px;
    margin: 0 auto clamp(24px, 3.5vw, 38px);
    transform-origin: center;
    background: var(--amber);
    box-shadow: 0 0 18px color-mix(in srgb, var(--amber) 60%, transparent);
  }
  .close h2 {
    font-size: clamp(38px, 6.2vw, 80px);
    line-height: .92;
    font-stretch: 70%;
    color: #fff;
    max-width: 22ch;
    margin: 0 auto clamp(16px, 2.5vw, 24px);
  }
  .close p { margin: 0 auto clamp(26px, 3.5vw, 34px); max-width: 56ch; font-size: 19px; color: var(--dim); }
  .close__addr {
    margin-top: clamp(22px, 3vw, 30px);
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--mute);
  }

  footer { border-top: var(--hair) solid var(--line-soft); background: color-mix(in srgb, var(--void) 74%, transparent); }
  footer .wrap {
    padding-block: 28px;
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: .08em;
    color: var(--mute);
  }
  .foot__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
  }
  footer a { color: var(--dim); }
  footer a:hover { color: var(--amber); }
  .colophon { display: flex; align-items: center; gap: 11px; }

  /* ── the self-audit ────────────────────────────────────────────────
     A page about data integrity, reporting on its own runtime. It is the
     only place on the site where a number is generated rather than
     stated, and it is honest because it is measured live in front of the
     reader. It is also the fastest way to see which of the tiers above
     this browser actually got.                                         */
  .audit {
    margin-top: 26px;
    padding-top: 22px;
    border-top: var(--hair) solid var(--line-soft);
  }
  .audit__h {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    font-size: 12px;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: #95A3AF;
  }
  .audit__grid {
    display: grid;
    /* the longest label and its value have to fit side by side inside
       one track, or the row pushes the grid open */
    grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
    gap: 1px 0;
  }
  .audit__row {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 6px 14px 6px 0;
    font-size: 12px;
    letter-spacing: .07em;
  }
  .audit__k { color: #95A3AF; white-space: nowrap; }
  .audit__d {
    flex: 1;
    height: 1px;
    min-width: 8px;
    background: repeating-linear-gradient(90deg, var(--line-soft) 0 2px, transparent 2px 5px);
    align-self: center;
  }
  .audit__v {
    flex: none;
    min-width: 0;
    text-align: right;
    color: var(--mute);
    text-transform: uppercase;
    overflow-wrap: anywhere;
  }
  .audit__v[data-state="on"]   { color: var(--amber); }
  .audit__v[data-state="off"]  { color: #7E8E9B; }
  .audit__v[data-state="info"] { color: var(--dim); }
}


/* ══════════════════════════════════════════════════════════════════════
   §23  MOTION
   ──────────────────────────────────────────────────────────────────────
   Where scroll-driven animations exist, the entire reveal system, the
   progress bar, the causal chain and the glyph drawing are pure CSS
   running on the compositor. No scroll listener, no observer, no main
   thread work, and nothing for a stalled ticker to strand.

   animation-timeline: view() ties an animation to an element's own
   progress through the viewport; scroll() ties it to a scroll container.
   Both are declarative, so the browser can run them off the main thread.

   The script only builds the observer fallback when this whole block has
   been declined. That check lives in one place: see the CAP.scrollTL
   capability in the script.
   ══════════════════════════════════════════════════════════════════ */
@layer motion {

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

      /* ── reveals ──────────────────────────────────────────────── */
      html.css-scroll [data-a="lift"] {
        animation: reveal-lift linear both;
        animation-timeline: view();
        animation-range: entry 2% cover 20%;
      }
      html.css-scroll [data-a="fade"] {
        animation: reveal-fade linear both;
        animation-timeline: view();
        animation-range: entry 2% cover 18%;
      }
      html.css-scroll [data-a="line"] {
        animation: reveal-line linear both;
        animation-timeline: view();
        animation-range: entry 0% cover 16%;
      }

      @keyframes reveal-lift {
        from { opacity: 0; translate: 0 20px; }
        to   { opacity: 1; translate: 0 0; }
      }
      @keyframes reveal-fade {
        from { opacity: 0; }
        to   { opacity: 1; }
      }
      @keyframes reveal-line {
        from { scale: 0 1; }
        to   { scale: 1 1; }
      }

      /* ── scroll progress, straight off the root scroller ─────────── */
      html.css-scroll .progress {
        animation: bar-grow linear both;
        animation-timeline: scroll(root block);
      }
      @keyframes bar-grow {
        from { scale: 0 1; }
        to   { scale: 1 1; }
      }

      /* ── the causal chain: one number, whole diagram ─────────────── */
      html.css-scroll .chain {
        animation: chain-draw linear both;
        animation-timeline: view();
        animation-range: entry 24% cover 62%;
      }
      @keyframes chain-draw {
        from { --chain-progress: 0; }
        to   { --chain-progress: 1; }
      }

      /* ── glyphs draw themselves as their cell arrives ────────────── */
      html.css-scroll .cell {
        animation: glyph-draw linear both;
        animation-timeline: view();
        animation-range: entry 6% cover 30%;
      }
      @keyframes glyph-draw {
        from { --draw: 0; }
        to   { --draw: 1; }
      }

      /* ── the substrate planes drift on scroll, no JS parallax ────── */
      html.css-scroll .plane--metal  { animation: plane-drift-1 linear both; animation-timeline: scroll(root block); }
      html.css-scroll .plane--rack   { animation: plane-drift-2 linear both; animation-timeline: scroll(root block); }
      html.css-scroll .plane--streak { animation: plane-drift-3 linear both; animation-timeline: scroll(root block); }
      @keyframes plane-drift-1 { to { translate: 0 -2.4%; } }
      @keyframes plane-drift-2 { to { translate: 0 -5.6%; } }
      @keyframes plane-drift-3 { to { translate: 0 -8.8%; } }

      /* ── photographic layers, slowest of all ─────────────────────── */
      html.css-scroll .atmos {
        animation: atmos-drift linear both;
        animation-timeline: view();
        animation-range: cover 0% cover 100%;
      }
      @keyframes atmos-drift {
        from { translate: 0 1.4%; }
        to   { translate: 0 -1.4%; }
      }

      /* ── the spec panel rides a shallower plane than its column ──── */
      html.css-scroll .parallax {
        animation: panel-drift linear both;
        animation-timeline: view();
        animation-range: cover 0% cover 100%;
      }
      @keyframes panel-drift {
        from { translate: 0 13px; }
        to   { translate: 0 -13px; }
      }
    }
  }

  /* ── the observer fallback ─────────────────────────────────────────
     Applied only when the block above was declined. Identical end state,
     driven by a class the observer adds.                              */
  html.js-reveal [data-a] {
    transition: opacity .72s var(--ease), translate .72s var(--ease), scale .72s var(--ease);
    transition-delay: var(--rd);
  }
  html.js-reveal [data-a="fade"]:not(.is-in) { opacity: 0; }
  html.js-reveal [data-a="lift"]:not(.is-in) { opacity: 0; translate: 0 20px; }
  html.js-reveal [data-a="line"]:not(.is-in) { scale: 0 1; }

  /* the chain and glyphs, driven by the observer instead */
  html.js-reveal .chain { transition: --chain-progress 1.6s var(--ease-out); }
  html.js-reveal .chain.is-in { --chain-progress: 1; }
  html.js-reveal .cell { transition: --draw 1s var(--ease-out) .15s; }
  html.js-reveal .cell:not(.is-in) { --draw: 0; }
}


/* ══════════════════════════════════════════════════════════════════════
   §24  STATES
   ══════════════════════════════════════════════════════════════════ */
@layer states {

  .nav.is-stuck {
    background: color-mix(in srgb, var(--void) 90%, transparent);
    border-bottom-color: var(--line);
  }

  /* ── the causal chain, lit ─────────────────────────────────────────
     Node lighting is derived from --chain-progress with a plain
     comparison, so the nodes cannot fall out of step with the line that
     is supposed to be reaching them. Each node declares the point on the
     track where it sits, and lights when the fill passes it.

     style() container queries let a rule test a custom property value.
     Where they are missing, the script adds .is-lit instead.           */
  @supports (container-type: normal) and (width: 1cqw) {
    @container style(--chain-progress > 0.12) { .node:nth-child(1) { --lit: 1; } }
    @container style(--chain-progress > 0.32) { .node:nth-child(2) { --lit: 1; } }
    @container style(--chain-progress > 0.52) { .node:nth-child(3) { --lit: 1; } }
    @container style(--chain-progress > 0.72) { .node:nth-child(4) { --lit: 1; } }
    @container style(--chain-progress > 0.90) { .node:nth-child(5) { --lit: 1; } }
  }

  .node.is-lit,
  .node:where([style*="--lit"]) {
    border-color: var(--amber-edge);
    background: linear-gradient(180deg, rgba(33, 45, 58, .76), rgba(14, 20, 26, .64));
    box-shadow:
      inset 0 1px 0 rgba(220, 238, 255, .07),
      0 18px 40px -26px rgba(0, 0, 0, .7);
  }
  .node.is-lit .node__n     { color: var(--amber); }
  .node.is-lit .node__ghost { color: color-mix(in srgb, var(--amber) 8%, transparent); }

  /* the last consequence is the one that costs money */
  .node--terminal.is-lit             { border-color: color-mix(in srgb, var(--oxide) 34%, transparent); }
  .node--terminal.is-lit .node__n    { color: var(--oxide-text); }
  .node--terminal.is-lit .node__ghost{ color: color-mix(in srgb, var(--oxide) 9%, transparent); }

  .chain__mk.is-lit::before { border-color: var(--amber); background: var(--amber); scale: 1.15; }
  .chain__mk--terminal.is-lit::before { border-color: var(--oxide); background: var(--oxide); }

  /* ── the load gate ─────────────────────────────────────────────────
     Applied by an inline head script before first paint, removed by the
     load sequence or by a 2.6s failsafe. Once the script has written
     these values as inline styles they outrank this class, so removing it
     is no longer enough to recover the page: showEverything() is what
     does that. Everything gated here is marked data-intro.             */
  html.js-anim [data-intro="fade"]  { opacity: 0; }
  html.js-anim [data-intro="lift"]  { opacity: 0; translate: 0 20px; }
  html.js-anim [data-intro="line"]  { scale: 0 1; }
  html.js-anim [data-intro="panel"] { opacity: 0; translate: 0 44px; scale: .988; }
  html.js-anim .hd__l > span        { translate: 0 104%; }
  html.js-anim .nav                 { translate: 0 -100%; }
  /* the rows print in; the table itself is never hidden */
  html.js-anim .vp__row             { opacity: 0; }

  /* ── the pure-CSS no-JS gate ───────────────────────────────────────
     @media (scripting: none) is a real media query, so the page can now
     answer the question "is script running?" in CSS, before any script
     has had a chance to run. Nothing here is strictly required — every
     one of these elements is already inert without script — but it lets
     the page stop reserving room for things that will never arrive.    */
  @media (scripting: none) {
    .field { display: none; }
    .inst  { display: none; }   /* an instrument with no arithmetic is furniture */
    .pop-open { display: none; }
    .audit { display: none; }
  }
  /* initial-only covers the printed and pre-render cases */
  @media (scripting: initial-only) {
    .field { display: none; }
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §25  RESPONSIVE
   ──────────────────────────────────────────────────────────────────────
   Most component breakpoints are container queries, declared next to the
   component they govern. What is left here is genuinely viewport-scoped:
   chrome, the rail, and the decisions about how hard a small device
   should be asked to work.

   This lives in its own layer, ordered after components, because a media
   query adds no specificity. A breakpoint rule in an earlier layer loses
   to the component default it is meant to override — and loses quietly,
   which is the worst way to lose.
   ══════════════════════════════════════════════════════════════════ */
@layer responsive {

  @media (min-width: 1460px) {
    .rail { display: flex; }
  }
  @media (max-width: 1240px) {
    .nav__readout { display: none; }
  }

  @media (max-width: 1000px) {
    .duo { grid-template-columns: 1fr; align-items: start; gap: 20px; }
    .hero__grid { grid-template-columns: 1fr; }
    /* the chain becomes a vertical run and the track moves to its side,
       so the sequence still reads as a sequence */
    .chain { padding-left: 26px; }
    .chain__track { display: none; }
    .chain__vtrack { display: block; }
    .chain__steps { grid-template-columns: 1fr; gap: 14px; }
    .node__ghost { bottom: -10px; font-size: 62px; }
  }

  @media (max-width: 760px) {
    .nav__links a:not(.btn) { display: none; }
    /* On a phone the depth layers crowd the copy and cost bandwidth for
       an effect nobody sees at that size. Keep the two that frame the
       page and drop the rest. Because they are display:none they are
       never intersected, so lazy loading skips them and the bytes are
       never fetched. */
    .atmos--receiving,
    .atmos--flow,
    .atmos--coords { display: none; }
    .atmos--hero { width: 66vw; height: 100%; opacity: .26; }
    .atmos--aisle { opacity: .20; }
  }

  @media (max-width: 620px) {
    body { font-size: 17px; }
    :root { --nav-h: 62px; }
    .hd { font-size: clamp(42px, 12vw, 64px); }
    .lede { font-size: 18.5px; }
    .prose, .lead-p { font-size: 17.5px; }
    .hero__cta { max-width: none; }
    .spec { padding: 22px 20px 24px; }
    .checks li { font-size: 13px; }
    /* mobile GPUs choke on stacked backdrop filters */
    .glass__body,
    .glass--recessed .glass__body {
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      background: linear-gradient(180deg, rgba(23, 31, 41, .975), rgba(11, 16, 21, .99));
    }
    .nav { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(9, 13, 18, .97); }
    .plane--streak, .plane--metal, .grain { display: none; }
    .glass::after, .glass__body::before { display: none; }
    .node__ghost { font-size: 54px; }
  }

  /* a device that reports a coarse pointer gets bigger hit targets
     regardless of how wide its screen is */
  @media (pointer: coarse) {
    .btn { padding-block: 17px; }
    .q > summary { padding-block: 24px; }
    .fld input { padding-block: 14px; }
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §26  ACCESSIBILITY
   ══════════════════════════════════════════════════════════════════ */
@layer a11y {

  /* ── reduced motion ────────────────────────────────────────────────
     Everything that would animate into place is shown finished. The
     script returns before building any of it, and the WebGL field is
     never initialised at all.                                         */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: .001ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: .001ms !important;
      animation-timeline: auto !important;
    }
    html { scroll-behavior: auto; }
    .field { display: none; }

    /* finished state for the chain and the glyphs */
    :root { --chain-progress: 1; --draw: 1; }
    .node {
      border-color: var(--amber-edge);
      background: linear-gradient(180deg, rgba(33, 45, 58, .76), rgba(14, 20, 26, .64));
    }
    .node .node__n { color: var(--amber); }
    .node .node__ghost { color: color-mix(in srgb, var(--amber) 8%, transparent); }
    .node--terminal .node__n { color: var(--oxide-text); }
    .chain__mk::before { border-color: var(--amber); background: var(--amber); }
    .chain__mk--terminal::before { border-color: var(--oxide); background: var(--oxide); }
    .chain__pulse { display: none; }
  }

  /* ── reduced transparency ──────────────────────────────────────────
     A reader who has asked the OS to cut transparency gets opaque
     panels. The glass reads as metal instead of glass, which is a
     legitimate second look rather than a degraded one.                */
  @media (prefers-reduced-transparency: reduce) {
    .glass__body,
    .glass--recessed .glass__body,
    .nav,
    .pop {
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      background: var(--steel-1);
    }
    .atmos { opacity: .08 !important; }
    .grain { display: none; }
    .field { display: none; }
  }

  /* ── more contrast ─────────────────────────────────────────────── */
  @media (prefers-contrast: more) {
    :root {
      --dim:        #E2EAF1;
      --mute:       #BFCBD5;
      --panel-p:    #D8E2EA;
      --line:       #3C4A58;
      --line-soft:  #2C3742;
      --oxide-text: #E4795A;
    }
    .glass__body { background: linear-gradient(180deg, rgba(20, 28, 37, .99), rgba(8, 12, 16, 1)); }
    .cell { background: linear-gradient(180deg, rgba(20, 28, 37, .97), rgba(9, 13, 18, .99)); }
    .node { background: linear-gradient(180deg, rgba(22, 31, 40, .95), rgba(10, 15, 20, .95)); }
    .atmos { opacity: .07 !important; }
    .plane--metal, .plane--streak, .grain, .field { display: none; }
    .cell p, .node p, .spec__s { color: #C6D2DC; }
    .checks li, .req dd, .res__v { color: #B6C4D0; }
  }

  /* ── forced colours ────────────────────────────────────────────────
     This audience is largely on managed Windows desktops, where High
     Contrast is common enough to design for rather than hope about.
     Forced colours strips every background, border colour and shadow
     this page is built out of, so the structure has to be restated in
     system colours and anything decorative has to get out of the way.  */
  @media (forced-colors: active) {
    .substrate, .vignette, .grain, .field, .atmos, .progress, .rail,
    .chain__fill, .chain__vfill, .chain__pulse, .node__ghost { display: none !important; }

    .glass { padding: 0; background: none; box-shadow: none; border: 1px solid CanvasText; }
    .glass::after, .glass__body::before { display: none; }
    .glass__body {
      background: Canvas;
      box-shadow: none;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
    }
    .grid8, .cell, .node, .deliv li, .q, .faq, .sec, .step,
    .checks li, .req > div, .res, .inst__out { border-color: CanvasText; }
    .cell, .node { border: 1px solid CanvasText; }
    .aside { border-left-color: CanvasText; }
    .checks li::before { background: CanvasText; }
    .dot, .close__bar { background: CanvasText; }
    .btn--primary, .skip, .pop, .pop-open { border: 1px solid CanvasText; }
    .res__bar::after { background: CanvasText; forced-color-adjust: none; }
    .audit__v[data-state="on"]  { color: Highlight; }
    .audit__v[data-state="off"] { color: GrayText; }
  }
}


/* ══════════════════════════════════════════════════════════════════════
   §27  PRINT
   ──────────────────────────────────────────────────────────────────────
   This page gets forwarded and printed. It should come out as a clean
   document, not a screenshot of a dark website.
   ══════════════════════════════════════════════════════════════════ */
@layer print {

  @media print {
    @page { margin: 16mm 14mm; }

    .substrate, .vignette, .grain, .field, .progress, .rail,
    .nav, .atmos, .skip, .pop, .pop-open, .audit { display: none !important; }

    html, body { background: #fff; color: #111; }

    .glass { background: none; box-shadow: none; padding: 0; border: 1px solid #bbb; }
    .glass__body {
      background: none;
      box-shadow: none;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
    }
    .glass::after, .glass__body::before { display: none; }

    h1, h2, h3, h4, .q__t, .spec__v, .brand__w, .step__t, .res__big { color: #000; }
    .lede, .sec__p, .eng__p, .close p, .q__a p, .node p, .cell p,
    .spec__s, .prose, .lead-p, .step__b p, .aside p, .xcol > p { color: #222; }
    .checks li, .req dd, .req dt, .xnote, .res__k, .res__v { color: #333; }

    .node__ghost, .res__bar { display: none; }
    .q > .q__a { display: block !important; height: auto !important; opacity: 1 !important; }
    .q::details-content { block-size: auto !important; opacity: 1 !important; }

    .sec { border-top: 1px solid #ccc; padding-block: 22px; break-inside: avoid; content-visibility: visible; }
    .step, .cell, .node { break-inside: avoid; }
    .node, .cell { background: none; border: 1px solid #ddd; }

    a { color: #111; text-decoration: underline; }
    a[href^="mailto:"]::after { content: " (" attr(href) ")"; font-size: .85em; }
  }
}

/* ══════════════════════════════════════════════════════════════════════
   §40  COMPONENTS — the article sheet
   ──────────────────────────────────────────────────────────────────────
   Everything above this line is lifted verbatim from the homepage so the
   two surfaces cannot drift apart. What follows is the only new CSS on a
   guide page, and it is built entirely from the tokens in §02 — no new
   colours, no new faces, no new easing.

   A guide is a document, not a landing page, so the measure is tighter
   than the homepage's and the heading ramp is one step quieter.
   ══════════════════════════════════════════════════════════════════ */
@layer components {

  /* ── breadcrumb ──────────────────────────────────────────────────── */
  .crumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 10px;
    margin-bottom: clamp(22px, 3vw, 32px);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .crumb li { display: flex; align-items: center; gap: 10px; }
  .crumb li + li::before {
    content: "";
    width: 5px; height: 5px;
    flex: none;
    border-top: 1px solid var(--line);
    border-right: 1px solid var(--line);
    rotate: 45deg;
  }
  .crumb a { color: var(--dim); }
  .crumb a:hover { color: var(--amber); }
  .crumb [aria-current="page"] { color: var(--mute); }

  /* ── article masthead ────────────────────────────────────────────── */
  .art { padding-block: clamp(30px, 4vw, 46px) clamp(58px, 7vw, 96px); }

  .art__h1 {
    font-size: clamp(34px, 5vw, 62px);
    line-height: .95;
    font-stretch: 70%;
    color: #fff;
    max-width: 20ch;
  }
  .art__dek {
    margin-top: clamp(18px, 2.4vw, 26px);
    max-width: 64ch;
    font-size: 20px;
    line-height: 1.6;
    color: var(--dim);
  }
  .art__dek b { color: #fff; font-weight: 500; }

  .art__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 clamp(14px, 2vw, 24px);
    margin-top: clamp(24px, 3vw, 34px);
    padding-top: 16px;
    border-top: var(--hair) solid var(--line-soft);
    font-family: var(--mono);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .art__meta li { position: relative; padding-block: 2px; }
  .art__meta li + li { padding-left: clamp(14px, 2vw, 24px); }
  .art__meta li + li::before {
    content: "";
    position: absolute;
    left: 0; top: 50%;
    width: 1px; height: 11px;
    margin-top: -5.5px;
    background: var(--line);
  }
  .art__meta time { color: var(--dim); }

  /* ── the answer block ────────────────────────────────────────────
     The first thing a reader, a snippet or an answer engine meets. It
     is deliberately the only recessed-glass object above the fold, so
     it reads as the extract rather than as decoration.               */
  .answer { margin-top: clamp(34px, 4.4vw, 52px); max-width: 74ch; }
  .answer .glass__body { padding: clamp(22px, 3vw, 30px) clamp(22px, 3vw, 32px); }
  .answer__k {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: #95A3AF;
  }
  .answer__p {
    font-size: 19px;
    line-height: 1.58;
    color: var(--text);
  }

  /* ── contents ────────────────────────────────────────────────────── */
  .toc {
    margin-top: clamp(34px, 4.4vw, 52px);
    padding-top: 20px;
    border-top: var(--hair) solid var(--line-soft);
  }
  .toc__k {
    margin-bottom: 14px;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: #95A3AF;
  }
  .toc__l {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
    gap: 1px clamp(16px, 3vw, 40px);
  }
  .toc__l li { border-top: var(--hair) solid var(--line-soft); }
  .toc__l a {
    display: flex;
    gap: 12px;
    padding: 9px 0;
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: .04em;
    color: #B4C2CE;
  }
  .toc__l a:hover { color: var(--amber); }
  .toc__l a span { color: var(--amber); flex: none; }

  /* ── body sections ───────────────────────────────────────────────── */
  .g { border-top: var(--hair) solid var(--line-soft); padding-block: clamp(42px, 5.2vw, 72px); }
  .g__h {
    font-size: clamp(27px, 3.2vw, 40px);
    line-height: 1.0;
    font-stretch: 74%;
    color: #fff;
    max-width: 24ch;
    margin-bottom: clamp(20px, 2.6vw, 28px);
  }
  .g__sh {
    margin: clamp(28px, 3.2vw, 38px) 0 12px;
    font-size: 19px;
    font-stretch: 80%;
    line-height: 1.15;
    color: #fff;
  }
  .g .prose { max-width: 72ch; }
  .g .prose + .g__sh { margin-top: clamp(30px, 3.4vw, 40px); }

  /* a definition run: term in mono amber, meaning in prose */
  .defs { margin-top: clamp(22px, 2.8vw, 30px); max-width: 76ch; }
  .defs > div {
    padding-block: clamp(16px, 2vw, 22px);
    border-top: var(--hair) solid var(--line-soft);
  }
  .defs > div:last-child { border-bottom: var(--hair) solid var(--line-soft); }
  .defs dt {
    margin-bottom: 7px;
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--amber);
  }
  .defs dd { font-size: 17.5px; line-height: 1.64; color: var(--dim); }
  .defs dd b, .defs dd strong { color: #fff; font-weight: 500; }
  .defs dd + dd { margin-top: .7em; }

  /* a plain signal list — symptoms, fields, anything enumerable */
  .sig { margin-top: clamp(20px, 2.6vw, 28px); max-width: 76ch; border-top: var(--hair) solid var(--line-soft); }
  .sig li {
    position: relative;
    padding: 11px 0 11px 22px;
    border-bottom: var(--hair) solid var(--line-soft);
    font-size: 17px;
    line-height: 1.6;
    color: var(--dim);
  }
  .sig li::before {
    content: "";
    position: absolute;
    left: 1px; top: 21px;
    width: 8px; height: 1px;
    background: var(--amber);
  }
  .sig li b, .sig li strong { color: #fff; font-weight: 500; }
  .sig code, .prose code, .defs code, .step__b code, .vp code {
    font-family: var(--mono);
    font-size: .88em;
    letter-spacing: .01em;
    color: #C8D5E1;
    background: rgba(160, 190, 215, .07);
    border: 1px solid var(--line-soft);
    border-radius: 3px;
    padding: .08em .36em;
    white-space: nowrap;
  }

  /* the worked arithmetic, so a claim is followed by its working */
  .calc { margin-top: clamp(22px, 2.8vw, 30px); }
  .calc .glass__body { padding: 0; }
  .calc__h {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 13px 18px;
    border-bottom: var(--hair) solid var(--line);
    background: linear-gradient(180deg, rgba(220, 238, 255, .07), transparent);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
  }
  .calc__h span:first-child { display: flex; align-items: center; gap: 9px; color: #B7C5D2; }
  .calc__h span:first-child .dot { width: 5px; height: 5px; }
  .calc__h span + span { color: var(--mute); }
  .calc .vp { min-width: 560px; }
  .calc .vp__cause { min-width: 210px; }

  /* the closing figure of a worked example */
  .calc__out {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px 16px;
    padding: 15px 18px;
    border-top: var(--hair) solid var(--line);
    background: linear-gradient(0deg, rgba(232, 163, 61, .05), transparent);
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .calc__out b { color: var(--amber); font-weight: 500; font-size: 15px; letter-spacing: .02em; }

  /* ── the audit CTA ───────────────────────────────────────────────── */
  .cta { margin-top: clamp(44px, 5.4vw, 72px); }
  .cta .glass__body {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: clamp(20px, 3vw, 40px);
    padding: clamp(26px, 3.2vw, 36px) clamp(24px, 3.2vw, 38px);
  }
  .cta__b { max-width: 58ch; }
  .cta__h { font-size: clamp(22px, 2.4vw, 28px); font-stretch: 78%; line-height: 1.08; color: #fff; margin-bottom: 10px; }
  .cta__p { font-size: 17px; line-height: 1.6; color: var(--dim); }
  .cta__p b { color: #fff; font-weight: 500; }

  /* ── related guides ──────────────────────────────────────────────── */
  .rel { border-top: var(--hair) solid var(--line-soft); padding-block: clamp(42px, 5.2vw, 66px); }
  .rel__h {
    margin-bottom: clamp(22px, 2.8vw, 30px);
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: .17em;
    text-transform: uppercase;
    color: var(--mute);
  }
  .rel__l { display: grid; grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); gap: 1px clamp(20px, 3vw, 44px); }
  .rel__l li { border-top: var(--hair) solid var(--line-soft); }
  .rel__l a { display: block; padding: clamp(16px, 2vw, 22px) 0; color: var(--text); }
  .rel__t {
    display: block;
    margin-bottom: 6px;
    font-family: var(--display);
    font-size: 19px;
    font-weight: 700;
    font-stretch: 78%;
    text-transform: uppercase;
    letter-spacing: .004em;
    line-height: 1.08;
    color: #fff;
    transition: color .2s var(--ease);
  }
  .rel__l a:hover .rel__t { color: var(--amber); }
  .rel__d { display: block; font-size: 15.5px; line-height: 1.55; color: var(--mute); }

  /* ── the guide index in the footer, on every page ─────────────────── */
  .foot__nav {
    display: flex;
    flex-wrap: wrap;
    gap: 10px clamp(16px, 2.4vw, 28px);
    margin-top: 20px;
    padding-top: 18px;
    border-top: var(--hair) solid var(--line-soft);
    font-size: 12.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
  }
}

@layer responsive {
  @media (max-width: 620px) {
    .art__dek { font-size: 18.5px; }
    .answer__p { font-size: 17.5px; }
    .sig li, .defs dd { font-size: 16.5px; }
    .calc .vp { min-width: 520px; }
  }
}
