/* Mongla — a dive computer, not a document.
 *
 * THE PALETTE IS FOUND, NOT CHOSEN. Every colour below is sampled from the
 * vehicle's own CAD materials or it is the water. One rule carries the system:
 *
 *     RED is the machine, and it marks something MEASURED.
 *     OCEAN is what the machine perceives.
 *     Everything else is the dark it works in.
 *
 * Tokens are three layers — primitive (raw, named for where it came from),
 * semantic (what it means), component (what it dresses). Nothing outside the
 * :root block may use a raw hex.
 */

/* ── fonts: one superfamily, self-hosted, offline-capable ────────────
   Zed Mono and Zed Sans are custom Iosevka builds (SIL OFL). 18 MB of TTF
   subset to 129 KB of woff2 — smaller than the Google Fonts request they
   replace, and it works at a venue with no network. */
@font-face{font-family:"Zed Mono";src:url("fonts/zed-mono-extended.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Zed Mono";src:url("fonts/zed-mono-extendedbold.woff2") format("woff2");
  font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"Zed Sans";src:url("fonts/zed-sans-extended.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Zed Sans";src:url("fonts/zed-sans-extendedbold.woff2") format("woff2");
  font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"Zed Sans";src:url("fonts/zed-sans-extendeditalic.woff2") format("woff2");
  font-weight:400;font-style:italic;font-display:swap}

/* Manrope, variable, wght 200-800, latin only — 24 KB for every weight the page
   uses. It takes DISPLAY and headings. It does not take numbers: a measurement
   stays in Zed Mono or the columns stop aligning. (SIL OFL, self-hosted.) */
@font-face{font-family:"Manrope";src:url("fonts/manrope-latin.woff2") format("woff2");
  font-weight:200 800;font-style:normal;font-display:swap}

:root{
  /* ── layer 1: primitives, named for their source ─────────────── */
  --cad-red:#ff0000;        /* CAD material 4 — the fairings, exactly */
  --cad-amber:#f88701;      /* CAD material 0 — the accents */
  --cad-slate:#43484d;      /* CAD material 1 — the frame */
  --cad-glass:#c4e2f3;      /* CAD material 16 — the viewport */
  --sea:#004eff;            /* the medium */

  /* the descent: surfaces named by depth, because the page is one */
  --d0:#000000;
  --d1:#05070c;
  --d2:#0a0e16;
  --d3:#111726;
  --rule:#1a2030;
  --rule-lit:#2b3448;

  --ink:#e4e8ef;
  --ink-2:#98a2b4;
  --ink-3:#7b8598;          /* 5.4:1 on --d0 — these carry small mono labels */

  /* lifted tints: the saturated primitives are STRUCTURE and fail AA as text */
  --red-lit:#ff5747;
  --sea-lit:#5a8dff;

  /* ── layer 2: semantics ──────────────────────────────────────── */
  --signal:var(--cad-red);       /* something measured and live */
  --signal-text:var(--red-lit);
  --medium:var(--sea);           /* what the machine perceives */
  --medium-text:var(--sea-lit);
  --caution:var(--cad-amber);

  --state-water:#22d3c5;         /* proven in water   */
  --state-bench:var(--cad-amber);/* proven on a bench */
  --state-soft:#9a7bff;          /* software only     */
  --state-blocked:var(--cad-red);/* blocked           */

  /* ── layer 3: type ───────────────────────────────────────────── */
  --display:"Manrope",ui-sans-serif,system-ui,sans-serif;
  --mono-display:"Zed Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --data:"Zed Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --prose:"Zed Sans",ui-sans-serif,system-ui,sans-serif;

  /* ── type scale. Zed Sans is an EXTENDED face, so it reads roughly one
     size larger than its px value; the body is set accordingly, in Linear's
     15-17 px band, and everything inside a box steps down one rung. ─── */
  --fs-micro:9px;                                     /* silk legends */
  --fs-caption:12px;
  --fs-box:13.5px;                                    /* prose inside a surface */
  --fs-body:clamp(14px,.82rem + .1vw,15px);          /* one rung down, 2026-09-22 */
  --fs-lede:clamp(15px,.88rem + .18vw,16.5px);
  --fs-num:clamp(1rem,.92rem + .34vw,1.25rem);        /* a reading in a cell */
  --fs-num-hero:clamp(2.6rem,1.7rem + 2.8vw,4rem);
  --fs-h2:clamp(1.4rem,.95rem + 1.25vw,2.05rem);
  --fs-h1:clamp(2.1rem,.9rem + 4vw,4.4rem);

  --gutter:clamp(20px,3.4vw,72px);
  --measure:70ch;
  --wrap:min(1600px,100%);   /* was 1340 px: a 1920 screen left 290 px empty per side */
  --s1:8px; --s2:14px; --s3:22px; --s4:34px; --s5:52px; --s6:clamp(56px,7vw,96px);
  --t-fast:150ms; --t-mid:420ms; --t-slow:900ms;
  --ease:cubic-bezier(.16,1,.3,1);
  --ease-out-expo:cubic-bezier(.16,1,.3,1);   /* the surfacing letters */

  /* ── layer 2b: SURFACES, flat. Depth is shadow, never a gradient ──
     A gradient paints light without a source, so every panel invents its own
     sun and the page never agrees where the light is. A layered shadow is
     DERIVED from a height under one light, and that agreement is the whole
     effect. Fills below are flat; the ladder does the rest. */
  --s-sunk:#04060b;     /* below the field — wells, insets, screens */
  --s-flush:#080b12;    /* at the field                            */
  --s-raised:#0c1119;   /* one step up — panels                    */
  --s-key:#111725;      /* a pressable face                        */
  --edge-lit:rgba(255,255,255,.055);   /* the light catching a top edge  */
  --edge-dark:rgba(0,0,0,.55);         /* the shade under a bottom edge  */

  /* ── the ladder: contact + ambient + rim, never one blur ──────────
     The first three layers are Linear's surface recipe, read off linear.app
     with getComputedStyle: a faint white inner ring, a lit top rim, and a
     BLACK outer ring. The black ring is what separates a dark surface from a
     dark field -- a grey border does it by being lighter, which looks cheap. */
  --e0:none;
  --e1:inset 0 0 0 1px rgba(255,255,255,.03),
       inset 0 1px 0 var(--edge-lit),
       0 0 0 1px rgba(0,0,0,.6),
       0 1px 1px rgba(0,0,0,.55),
       0 4px 12px -6px rgba(0,0,0,.75);
  --e2:inset 0 0 0 1px rgba(255,255,255,.03),
       inset 0 1px 0 var(--edge-lit),
       0 0 0 1px rgba(0,0,0,.6),
       0 1px 2px rgba(0,0,0,.6),
       0 10px 28px -12px rgba(0,0,0,.82);
  --e3:inset 0 0 0 1px rgba(255,255,255,.03),
       inset 0 1px 0 var(--edge-lit),
       0 0 0 1px rgba(0,0,0,.6),
       0 2px 4px rgba(0,0,0,.6),
       0 20px 48px -20px rgba(0,0,0,.88);
  --e4:inset 0 0 0 1px rgba(255,255,255,.03),
       inset 0 1px 0 var(--edge-lit),
       0 0 0 1px rgba(0,0,0,.6),
       0 3px 6px rgba(0,0,0,.62),
       0 36px 80px -32px rgba(0,0,0,.92);
  /* pressed: the face drops INTO the ladder instead of sitting on it */
  --e-in:inset 0 2px 5px rgba(0,0,0,.8), inset 0 -1px 0 var(--edge-lit);
  /* a well is a CUT: its far rim catches the light (outer lip, below) and its
     near wall is in shade (inset, above). Without the lip it just vanishes
     into the field, which is what the first render showed. */
  --e-well:inset 0 2px 10px rgba(0,0,0,.9), inset 0 0 0 1px rgba(0,0,0,.7),
           0 0 0 1px rgba(255,255,255,.045), 0 1px 0 1px rgba(255,255,255,.06);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0; color:var(--ink);
  font-family:var(--prose); font-size:var(--fs-body);
  line-height:1.65; -webkit-font-smoothing:antialiased;
  /* NOT overflow-x:hidden -- that computes overflow-y to auto, which makes
     BODY the scroll container and silently breaks every position:sticky on the
     page. clip constrains the axis without creating a scroll box. */
  overflow-x:clip;
  /* FLAT. The void is one colour. Everything that used to be a gradient is
     now either a shadow (which implies a light) or grain (which implies a
     medium). Nothing here paints a highlight it cannot account for. */
  background:var(--d0);
}
/* The surface of the water, cast rather than painted: a fixed pane whose
   INSET shadow spills ocean over the top edge. It is the same mechanism as
   every other panel on the page, which is why it sits with them. */
body::before{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:1;
  box-shadow:inset 0 clamp(90px,16vh,190px) clamp(110px,20vh,240px)
             calc(-1 * clamp(70px,12vh,150px)) rgba(0,44,122,.42);
}
/* ── film grain ──────────────────────────────────────────────────────
   feTurbulence, rasterised by the browser into a tile. TWO layers at
   different scales and blend modes, because ONE tile at one scale repeats
   visibly at 1500 px and the eye finds the grid. The seed and baseFrequency
   of the top layer are rewritten from Math.random() on load (see index.html,
   ~6 lines) so no two visits carry the same grain -- that is the
   "randomization" this replaces the gradients with. The value below is the
   static fallback, so the page still has a surface with JS off. */
#grain{position:fixed;inset:0;pointer-events:none;z-index:3;
  opacity:.055;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch' seed='7'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:220px 220px}
#grain::after{content:"";position:absolute;inset:0;opacity:.5;
  mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='500' height='500'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.28' numOctaves='2' stitchTiles='stitch' seed='19'/%3E%3C/filter%3E%3Crect width='500' height='500' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size:500px 500px}
@media (prefers-reduced-motion:reduce){#grain{opacity:.04}}

::selection{background:var(--signal);color:#fff}

/* ── the title ────────────────────────────────────────────────────────
   The page is named after a port, and the vehicle it describes is a thing that
   goes under water, so the word does both: the letters surface one by one, a
   waterline sits across their feet with two slow swells, and a hull crosses it
   on a long patrol. Nothing here is decoration for its own sake -- the word
   behaves the way the subject behaves. All of it is transform/opacity, and all
   of it stops dead under prefers-reduced-motion. */
@font-face{font-family:"Mongla Bengali";src:url("fonts/noto-bengali-mongla.woff2") format("woff2");
  font-weight:500;font-display:swap}   /* Noto Sans Bengali, subset to the two words this site uses (OFL) */

/* ── the chart: the banner's sea, under the page ─────────────────────────
   The hero sits on the README banner's own chart -- contours, soundings, the
   dive track, the rose -- generated by tools/make_banner.py --site, so the
   banner and the page are one drawing. Behind every other section is the
   same seabed with only its contours, faint, instead of flat black. */
body::after{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:url("chart-page.svg") center/cover no-repeat;opacity:.5}
#surface{position:relative;isolation:isolate}
.surface__chart{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:right center;z-index:-1;pointer-events:none;
  /* the land is blank on a chart: the title's side fades the drawing out */
  -webkit-mask-image:linear-gradient(90deg,transparent 0 22%,#000 62%);
          mask-image:linear-gradient(90deg,transparent 0 22%,#000 62%);
  opacity:0;animation:chartin 1.6s var(--ease) .3s forwards}
@keyframes chartin{to{opacity:1}}
@media (max-width:900px){
  .surface__chart{opacity:.55;animation:none;
    -webkit-mask-image:linear-gradient(180deg,#000 0 30%,transparent 80%);
            mask-image:linear-gradient(180deg,#000 0 30%,transparent 80%)}
}

/* the patrol and the swells run past the edges on purpose; `clip` (not
   `hidden`) keeps them from widening the page without making a scroll box */
#surface{overflow-x:clip}
.title{position:relative;margin:0;line-height:.86;
  font-size:clamp(3.6rem,2rem + 12vw,11rem);letter-spacing:-.055em}
.title__word{display:inline-flex}
.title__word span{display:inline-block;transform:translateY(.42em);opacity:0;
  animation:surface 900ms var(--ease-out-expo) forwards}
.title__word span:nth-child(1){animation-delay:.05s}
.title__word span:nth-child(2){animation-delay:.12s}
.title__word span:nth-child(3){animation-delay:.19s}
.title__word span:nth-child(4){animation-delay:.26s}
.title__word span:nth-child(5){animation-delay:.33s}
.title__word span:nth-child(6){animation-delay:.40s}
@keyframes surface{to{transform:none;opacity:1}}

/* the waterline: two swells at different rates, which is what stops a wave
   from reading as a loop */
.title__sea{position:absolute;left:0;right:0;bottom:-.02em;width:100%;height:.30em;
  overflow:hidden;pointer-events:none;opacity:0;animation:tide 1.1s var(--ease) .5s forwards}
.title__sea path{fill:none;stroke:var(--signal);stroke-width:2.5;vector-effect:non-scaling-stroke}
.title__sea .s1{opacity:.85;animation:swell 9s linear infinite}
.title__sea .s2{stroke:var(--medium-text);opacity:.5;animation:swell 13s linear infinite reverse}
@keyframes tide{to{opacity:1}}
@keyframes swell{from{transform:translateX(0)}to{transform:translateX(300px)}}

/* the patrol: one hull, crossing under the word, every half minute */
/* the hull swims just UNDER the waterline, never over the type */
.title__sub{position:absolute;left:0;bottom:-.17em;width:clamp(62px,5vw,96px);height:auto;
  opacity:.5;pointer-events:none;animation:patrol 34s linear 1.6s infinite}
.title__sub .hull rect,.title__sub .hull path{fill:var(--ink-3)}
.title__sub .hull .fin{fill:var(--rule-lit)}
.title__sub .eye{fill:var(--signal)}
.title__sub .bubbles circle{fill:var(--rule-lit);animation:rise 2.4s var(--ease) infinite}
.title__sub .bubbles circle:nth-child(2){animation-delay:.5s}
.title__sub .bubbles circle:nth-child(3){animation-delay:1.1s}
@keyframes patrol{
  0%{transform:translateX(-14vw)}
  100%{transform:translateX(104vw)}
}
@keyframes rise{0%{opacity:0;transform:translate(0,4px)}
  30%{opacity:.9}100%{opacity:0;transform:translate(-6px,-14px)}}

.title__dot{color:var(--signal);display:inline-block;opacity:0;
  animation:surface 900ms var(--ease-out-expo) .47s forwards}
.title__bn{display:inline-block;margin-left:.22em;font-family:"Mongla Bengali","Noto Sans Bengali",sans-serif;
  font-weight:500;font-size:.34em;letter-spacing:0;color:var(--ink-3);vertical-align:baseline;
  opacity:0;animation:surface 1.1s var(--ease-out-expo) .6s forwards}
.title__origin{margin:clamp(18px,2.2vw,28px) 0 0;font-family:var(--data);font-size:11px;
  line-height:1.8;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);
  opacity:0;animation:surface 900ms var(--ease) .7s forwards}
.title__origin b{font-weight:400;color:var(--ink-2)}
.title__quote{margin:clamp(22px,3vw,38px) 0 0;max-width:30ch;
  font-family:var(--prose);font-style:italic;font-size:var(--fs-lede);line-height:1.35;
  color:var(--ink);padding-left:18px;border-left:2px solid var(--signal);
  opacity:0;animation:surface 900ms var(--ease) .62s forwards}

@media (prefers-reduced-motion:reduce){
  .title__word span,.title__sea,.title__quote,.title__dot,.title__bn,.title__origin,
  .surface__chart{animation:none;opacity:1;transform:none}
  .title__sea .s1,.title__sea .s2,.title__sub,.title__sub .bubbles circle{animation:none}
  .title__sub{display:none}
}

/* ── layout ──────────────────────────────────────────────────────── */
main{position:relative;z-index:2}
section{padding:clamp(72px,9.5vh,132px) var(--gutter);position:relative;
  border-top:1px solid var(--rule)}
section:first-of-type{border-top:0;min-height:96svh;display:flex;align-items:center;
  padding-top:clamp(86px,12vh,150px)}
section:first-of-type .wrap{width:100%}
.wrap{max-width:var(--wrap);margin:0 auto}
.wrap > h2, .wrap > .lede, .wrap > p, .wrap > h3{max-width:var(--measure)}
.wrap > .ledger, .wrap > figure, .wrap > .bento, .wrap > .years,
.wrap > ul.plain, .wrap > pre, .wrap > .bay, .wrap > .plate{max-width:none}
.col{max-width:var(--measure)}

/* corner brackets — the sheet knows it is a drawing sheet */
section::before,section::after{content:"";position:absolute;width:10px;height:10px;
  pointer-events:none;border:1px solid var(--rule-lit)}
section::before{left:var(--gutter);top:24px;border-right:0;border-bottom:0}
section::after{right:var(--gutter);top:24px;border-left:0;border-bottom:0}

/* ── glass: the one surface primitive ────────────────────────────── */
.glass{
  background:rgba(10,14,22,.66);
  border:1px solid var(--rule);
  border-top-color:var(--rule-lit);
  position:relative;
}
@supports (backdrop-filter:blur(8px)){
  .glass{backdrop-filter:blur(16px) saturate(1.15);background:rgba(10,14,22,.52)}
}
@supports (background:color-mix(in srgb,red 10%,transparent)){
  /* a faint red cast, as though the hull is just behind the panel */
  .glass{border-color:color-mix(in srgb,var(--signal) 9%,var(--rule))}
}

/* ── type ────────────────────────────────────────────────────────── */
h1,h2,h3{font-family:var(--display);font-weight:700;margin:0}
h2{font-weight:600}   /* a size step down wants a weight step down too: less shout, same hierarchy */
h1{font-size:var(--fs-h1);line-height:1.02;
  letter-spacing:-.035em;text-wrap:balance}
h2{font-size:var(--fs-h2);line-height:1.08;
  letter-spacing:-.03em;margin-bottom:16px;text-wrap:balance}
h3{font-size:1.0rem;letter-spacing:.02em;font-weight:700;color:#fff}

.mark{font-family:var(--data);font-size:clamp(10px,.6rem + .12vw,11px);
  letter-spacing:.22em;text-transform:uppercase;color:var(--ink-3);margin:0 0 26px}
.mark i{font-style:normal;color:var(--signal-text)}
.lede{font-size:var(--fs-lede);color:var(--ink-2);
  line-height:1.6;margin-top:var(--s3)}
.quiet{color:var(--ink-3)}
em{font-style:italic;color:var(--ink)}
strong{font-weight:700;color:#fff}

/* links: a dotted rule that closes up on hover. no underline-on-everything */
a{color:var(--medium-text);text-decoration:none;
  border-bottom:1px dotted color-mix(in srgb,var(--medium-text) 55%,transparent);
  transition:border-bottom-color var(--t-fast) var(--ease),color var(--t-fast) var(--ease)}
a:hover{color:#fff;border-bottom:1px solid var(--signal)}
a:focus-visible,canvas:focus-visible{outline:2px solid var(--signal-text);outline-offset:3px}
code,.n{font-family:var(--data);font-size:.87em;color:var(--medium-text)}
.nr{font-family:var(--data);color:var(--signal-text)}

/* ══ SKEUOMORPHIC PRIMITIVES ═════════════════════════════════════════
   Teenage Engineering's vocabulary, built entirely out of the shadow ladder:
   a face at a height, a lit top edge, a contact shadow, and travel when you
   press it. No gradient fills -- the only repeating-gradient here is KNURL,
   which is texture on a surface, not atmosphere behind one.
   ═══════════════════════════════════════════════════════════════════ */

/* a machined panel: flat anodised face, lit rim, sitting one step up */
.srf{background:var(--s-raised);border:1px solid var(--rule);
  border-top-color:var(--rule-lit);box-shadow:var(--e2);position:relative}
/* a recessed well: the same plate, pushed in */
.srf--sunk{background:var(--s-sunk);box-shadow:var(--e-well)}
/* silk-screened legend: printed ON the surface, so it is never full contrast */
.silk{font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--ink-3);display:block}
.silk--lit{color:var(--signal-text)}

/* a pressable face. it TRAVELS: on press it drops out of the ladder into it */
.key{appearance:none;font:inherit;cursor:pointer;
  font-family:var(--display);font-weight:800;font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-2);
  padding:10px 16px;border-radius:7px;
  background:var(--s-key);border:1px solid var(--rule-lit);
  box-shadow:var(--e2);
  transition:transform var(--t-fast) var(--ease),box-shadow var(--t-fast) var(--ease),
             color var(--t-fast) var(--ease)}
.key:hover{color:#fff;box-shadow:var(--e3);transform:translateY(-1px)}
.key:active{color:var(--signal-text);box-shadow:var(--e-in);transform:translateY(1px)}
.key[aria-pressed="true"]{color:var(--signal-text);box-shadow:var(--e-in)}
.key small{display:block;margin-top:5px;font-family:var(--data);font-weight:400;
  font-size:8px;letter-spacing:.1em;color:var(--ink-3);opacity:.8}
/* the hull's control deck: a row of keys sitting on the bay, TE-style.
   Always shown -- on a phone these are the ONLY way to take the explode. */
.deck{position:absolute;right:14px;top:clamp(46px,6vh,64px);z-index:2;display:flex;gap:6px;
  padding:6px;border-radius:11px;background:var(--s-flush);box-shadow:var(--e-well)}
.deck .key{min-width:44px;min-height:44px;padding:8px 10px 7px;font-size:9px}
@media (max-width:760px){.deck{left:10px;right:10px;justify-content:space-between;top:auto;
  bottom:46px}.deck .key{flex:1;min-width:0;padding:8px 4px 7px}}
/* knurling -- the milled grip on a real knob. A gradient used AS TEXTURE. */
.knurl{background-image:repeating-linear-gradient(90deg,
  rgba(255,255,255,.055) 0 1px, transparent 1px 3px)}

/* ══ THE BENTO ═══════════════════════════════════════════════════════
   The six headline numbers were six equal boxes in one line, which reads as
   a form, not as an instrument. Here the cells are DELIBERATELY UNEQUAL: the
   lead measurement takes a 2x2, the rest are 1x1 and 2x1, and each cell is a
   different KIND of object -- a rate, a latency, an angle, an error, a count,
   a refusal. Equal cells would just reproduce the row with rounder corners.
   ═══════════════════════════════════════════════════════════════════ */
.bento{display:grid;gap:10px;margin-top:clamp(36px,6vh,66px);
  grid-template-columns:repeat(4,1fr);
  grid-template-areas:
    "lead lead b    c"
    "lead lead d    c"
    "e    e    f    g";}
.bento > *{grid-area:var(--a);position:relative;padding:18px 18px 20px;
  border-radius:12px;background:var(--s-raised);border:0;
  box-shadow:var(--e1);overflow:hidden;
  transition:box-shadow var(--t-mid) var(--ease),transform var(--t-mid) var(--ease)}
.bento > *:hover{box-shadow:var(--e3);transform:translateY(-2px)}
.bento b{display:block;font-family:var(--data);font-weight:700;color:#fff;
  font-size:var(--fs-num);letter-spacing:-.035em;
  line-height:1}
.bento span{display:block;margin-top:8px;font-family:var(--prose);font-size:var(--fs-caption);
  line-height:1.45;color:var(--ink-3);max-width:34ch}

/* the lead cell: a recessed instrument screen with a real readout on it */
.bento .lead{--a:lead;background:var(--s-sunk);box-shadow:var(--e-well);
  padding:clamp(20px,2.4vw,30px);display:flex;flex-direction:column;
  justify-content:space-between;min-height:186px}
.bento .lead:hover{transform:none;box-shadow:var(--e-well)}
.bento .lead b{font-size:var(--fs-num-hero);letter-spacing:-.055em}
.bento .lead b u{text-decoration:none;color:var(--signal-text);
  font-size:.34em;letter-spacing:.02em;margin-left:.35em;vertical-align:.5em}
.bento .lead span{font-size:var(--fs-box);color:var(--ink-2);max-width:40ch}
/* the tick strip under the lead number: 500 marks, one per Hz, drawn as a
   repeating rule. It is the rate, shown, rather than the word "500 Hz". */
.bento .lead .ticks{height:26px;margin-top:14px;border-radius:4px;
  box-shadow:var(--e-in);
  background-image:repeating-linear-gradient(90deg,
    var(--signal) 0 1px, transparent 1px 5px);
  opacity:.52;
  -webkit-mask-image:linear-gradient(90deg,#000 0 62%,transparent);
          mask-image:linear-gradient(90deg,#000 0 62%,transparent)}
/* silk legends inside cells: re-asserted, because ".bento span" (a class plus
   an element) outranks ".silk" (one class) and silently turned them into prose */
.bento span.silk{font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.14em;
  color:var(--ink-3);margin:0 0 12px;max-width:none}
.bento span.silk.silk--lit{color:var(--signal-text)}
.bento .b{--a:b} .bento .c{--a:c} .bento .d{--a:d}
.bento .e{--a:e} .bento .f{--a:f} .bento .g{--a:g}
/* the error, shown: a 30 cm tape, one tick per cm, and the worst error as a
   sliver at its true width -- 1.09 / 30 = 3.63 % of the tape */
.bento .tape{position:relative;height:30px;margin:4px 0 16px;border-radius:4px;
  background-color:var(--s-sunk);box-shadow:var(--e-in);
  background-image:repeating-linear-gradient(90deg,var(--ink-3) 0 1px,transparent 1px calc(100% / 30));
  background-size:100% 9px;background-repeat:no-repeat;background-position:0 0}
.bento .tape i{position:absolute;top:0;bottom:0;right:0;width:3.63%;background:var(--signal)}
.bento .tape em{position:absolute;bottom:3px;font-style:normal;font-family:var(--data);
  font-size:9px;color:var(--ink-3);letter-spacing:.06em}
.bento .tape em:first-of-type{left:6px}
.bento .tape em:last-of-type{right:calc(3.63% + 6px)}
/* the angle, shown: two wedges from one apex. Water is the filled one. */
.bento .fov{width:100%;max-width:150px;height:auto;margin:6px 0 14px;display:block}
.bento .fov .water{fill:color-mix(in srgb,var(--medium) 34%,transparent);
  stroke:var(--medium-text);stroke-width:1}
.bento .fov .air{fill:none;stroke:var(--ink-3);stroke-width:1;stroke-dasharray:3 3}
/* the tall cell carries its number rotated down the side -- a grid break */
.bento .c{display:flex;flex-direction:column;justify-content:flex-end}
/* the refusal cell is the only one that is not a measurement, so it is the
   only one keyed to the blocked state */
.bento .warn{box-shadow:inset 0 1px 0 color-mix(in srgb,var(--caution) 55%,transparent),var(--e1)}
.bento .warn b{color:var(--caution)}
/* ── the instruments ledger: PAIRS carry a ratio, shown as length ─────
   A before/after number is a ratio, and a ratio is best read as two lengths
   on one scale. Each bar is the real proportion (--w), not a decoration. */
.bento--ledger{grid-template-columns:repeat(6,1fr);grid-template-areas:none;
  grid-auto-flow:row dense}
.bento--ledger > *{grid-area:auto;grid-column:span 1}
.bento--ledger > .pair{grid-column:span 3}
.bento--ledger > .wide{grid-column:span 4}
.pair .bar{position:relative;display:grid;grid-template-columns:auto 1fr;
  align-items:baseline;gap:4px 12px;margin-top:12px}
.pair .bar i{grid-column:1 / -1;display:block;height:8px;border-radius:999px;
  background:var(--s-sunk);box-shadow:var(--e-in);position:relative;overflow:hidden}
.pair .bar i::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w);
  border-radius:inherit;background:var(--signal);
  transform-origin:left;transform:scaleX(0);transition:transform var(--t-slow) var(--ease)}
.pair .bar.was i::after{background:var(--ink-3)}
.pair.in .bar i::after{transform:scaleX(1)}
.pair .bar b{font-size:var(--fs-num)}
.pair .bar.was b{color:var(--ink-2)}
.pair .bar em{font-style:normal;font-family:var(--data);font-size:10px;
  letter-spacing:.08em;color:var(--ink-3)}
.pair > span:last-child{margin-top:14px;max-width:44ch}
@media (prefers-reduced-motion:reduce){.pair .bar i::after{transform:none;transition:none}}
@media (max-width:1000px){
  .bento--ledger{grid-template-columns:repeat(2,1fr)}
  .bento--ledger > *{grid-column:span 1}
  .bento--ledger > .pair,.bento--ledger > .wide{grid-column:1 / -1}
}
@media (max-width:1000px){
  .bento:not(.bento--ledger){grid-template-columns:repeat(2,1fr);
    grid-template-areas:"lead lead" "b c" "d c" "e e" "f g"}
}
@media (max-width:560px){
  .bento--ledger > *{grid-column:1 / -1}
  .bento:not(.bento--ledger){grid-template-columns:1fr;
    grid-template-areas:"lead" "b" "c" "d" "e" "f" "g"}
  .bento .c{justify-content:flex-start}
}

/* ── ledger ──────────────────────────────────────────────────────── */
.ledger{width:100%;border-collapse:collapse;margin-top:38px;
  font-family:var(--data);font-size:12.5px}
.ledger th{text-align:left;font-weight:400;font-size:9.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-3);padding:0 14px 10px 0;
  border-bottom:1px solid var(--rule-lit)}
.ledger td{padding:12px 14px 12px 0;border-bottom:1px solid var(--rule);
  color:var(--ink-2);vertical-align:top}
.ledger td:first-child{color:#fff}
.ledger tr:hover td{background:var(--d1);color:var(--ink)}
.ledger td:last-child,.ledger th:last-child{padding-right:0}
.num{color:var(--medium-text)}
.numr{color:var(--signal-text)}

/* ── state: bracketed, not a rounded chip ────────────────────────── */
.st{font-family:var(--data);font-size:9px;letter-spacing:.16em;text-transform:uppercase;
  color:currentColor;white-space:nowrap;display:inline-block;padding:0}
.st::before{content:"[ ";opacity:.55}
.st::after{content:" ]";opacity:.55}
.st.water{color:var(--state-water)} .st.bench{color:var(--state-bench)}
.st.soft{color:var(--state-soft)}   .st.blocked{color:var(--state-blocked)}

/* ── the explode stage: the canvas is PINNED and the scroll drives it ──
   A viewer that scrolls out of frame halfway through its own animation is
   the animation not happening. The stage is tall; the bay sticks inside it. */
 /* 300vh -> 190 -> 115. Anything longer reads as the viewer holding the page
   hostage: the reader did not ask to be pinned, and a pinned section they did
   not ask for is the same complaint whether it is 3 screens or 2. 115vh is one
   screen of travel -- enough to read the explode as a motion, short enough that
   scrolling past it feels like scrolling. */
.stage{position:relative;margin-top:44px}
.stage .bay{margin-top:0}
.stage .bay canvas{height:min(62vh,560px)}

/* The explode is a control, not a scroll toll. Five stops on a machined fader:
   the reader takes it apart at their own pace, and the page never holds them.
   `explode(t)` already lerps toward its target, so a click IS the animation. */
.beats{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:1px;
  grid-template-columns:repeat(5,1fr);background:var(--rule);
  border:1px solid var(--rule);border-radius:3px;overflow:hidden}
.beats li{margin:0}
.beats button{display:block;width:100%;height:100%;text-align:left;cursor:pointer;
  padding:11px 13px 13px;border:0;background:var(--s-raised);color:inherit;
  font:inherit;position:relative;
  transition:background 160ms var(--ease),transform 160ms var(--ease)}
.beats button::before{content:'';position:absolute;inset:0 0 auto 0;height:2px;
  background:var(--signal);transform:scaleX(0);transform-origin:left;
  transition:transform 260ms var(--ease)}
.beats button:hover{background:var(--s-key)}
.beats button:active{transform:translateY(1px)}
.beats button:focus-visible{outline:2px solid var(--signal);outline-offset:-2px}
.beats li.on button{background:var(--s-key)}
.beats li.on button::before{transform:scaleX(1)}
.beats em{display:block;font-family:var(--data);font-size:9.5px;font-style:normal;
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin-bottom:6px}
.beats li.on em{color:var(--signal-text)}
.beats b{display:block;font-family:var(--display);font-weight:700;font-size:.92rem;
  color:#fff;letter-spacing:-.02em;line-height:1.25}
.beats span{display:block;margin-top:6px;font-family:var(--data);font-size:10.5px;
  line-height:1.62;color:var(--ink-3);letter-spacing:.02em}
/* the fader itself: a travel slot with a machined thumb */
.scrub{display:flex;align-items:center;gap:14px;margin-top:14px}
.scrub .silk{flex:none}
.scrub input{-webkit-appearance:none;appearance:none;flex:1;height:22px;
  background:transparent;cursor:ew-resize}
.scrub input:focus-visible{outline:2px solid var(--signal);outline-offset:4px}
.scrub input::-webkit-slider-runnable-track{height:4px;border-radius:2px;
  background:var(--s-key);box-shadow:inset 0 1px 2px rgba(0,0,0,.6)}
.scrub input::-moz-range-track{height:4px;border-radius:2px;background:var(--s-key);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.6)}
.scrub input::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:15px;height:22px;margin-top:-9px;border-radius:2px;background:#d8d5cf;
  border:1px solid #2a2724;box-shadow:0 1px 0 #fff inset,0 2px 5px rgba(0,0,0,.55)}
.scrub input::-moz-range-thumb{width:15px;height:22px;border-radius:2px;
  background:#d8d5cf;border:1px solid #2a2724;box-shadow:0 2px 5px rgba(0,0,0,.55)}
.scrub output{font-family:var(--data);font-size:11px;color:var(--signal-text);
  min-width:4.2em;text-align:right;font-variant-numeric:tabular-nums}
@media (max-width:760px){
  .beats{grid-template-columns:1fr}
  .beats span{font-size:11px}
}
}

/* ── the hull bay ────────────────────────────────────────────────── */
.bay{position:relative;margin-top:44px;border:1px solid var(--rule);overflow:hidden;
  /* a WELL: flat floor, and the shadow of its own rim falling in */
  background:var(--s-sunk);box-shadow:var(--e-well),var(--e2)}
.bay canvas{display:block;width:100%;height:clamp(300px,54vh,640px);cursor:grab;
  touch-action:pan-y}
.bay canvas:active{cursor:grabbing}
.bay .hud{position:absolute;inset:auto 0 0 0;display:flex;gap:24px;flex-wrap:wrap;
  padding:12px 16px;font-family:var(--data);font-size:9.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);border-top:1px solid var(--rule);
  background:var(--s-flush);box-shadow:0 -10px 26px -14px #000}
.bay .hud i{font-style:normal;color:var(--signal-text)}
.bay .keys{position:absolute;top:12px;right:16px;font-family:var(--data);
  font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
  opacity:.55;transition:opacity var(--t-fast) var(--ease);text-align:right;
  max-width:52%;line-height:1.9}
.bay .keys b{color:var(--signal-text);font-weight:400}
.bay:hover .keys{opacity:1}
@media (max-width:760px){.bay .keys{display:none}}
.bay .tagtop{position:absolute;top:12px;left:16px;font-family:var(--data);font-size:9.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--ink-3)}

/* ── figures ─────────────────────────────────────────────────────── */
.hero-render{margin-top:var(--s5);border:1px solid var(--rule);
  padding:clamp(14px,2vw,30px);
  background:var(--s-flush);box-shadow:var(--e2)}
.hero-render img{width:100%;height:auto;display:block}
.hero-render figcaption{margin-top:clamp(14px,1.8vw,22px);padding-top:13px;
  border-top:1px solid var(--rule)}

.plate{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;margin-top:var(--s5);
  background:var(--rule);border:1px solid var(--rule)}
/* the caption is a line of its own ABOVE the picture: pinned over the corner,
   it ran into the image and the two read as one muddle */
.plate figure{margin:0;position:relative;padding:clamp(12px,1.6vw,20px);
  background:var(--s-sunk);box-shadow:var(--e-well);
  display:flex;flex-direction:column;align-items:stretch;gap:10px;overflow:hidden}
.plate img{width:100%;height:auto;display:block;aspect-ratio:16/10;
  object-fit:contain;transition:transform var(--t-mid) var(--ease)}
.plate figure:hover img{transform:scale(1.035)}
.plate figcaption{order:-1;margin:0;font-family:var(--data);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-3)}
.plate figure::after{content:"";position:absolute;inset:auto auto 0 0;height:1px;width:0;
  background:var(--signal);transition:width var(--t-mid) var(--ease)}
.plate figure:hover::after{width:100%}
/* the HUD composites are 1700x1518 — nearly square. A 16/10 cell letterboxes
   them into black bars, so this variant matches the artefact instead. */
.plate--hud img{aspect-ratio:1700/1518}
@media (max-width:620px){.plate{grid-template-columns:1fr}}

figure{margin:var(--s6) 0 0}
figure img,figure svg{width:100%;height:auto;display:block}
figcaption{font-family:var(--prose);font-size:12.5px;color:var(--ink-3);
  margin-top:12px;max-width:66ch;line-height:1.5}
figure.panel{background:var(--s-raised);
  border:1px solid var(--rule);border-top-color:var(--rule-lit);
  padding:clamp(18px,2.6vw,38px);box-shadow:var(--e2)}
figure.panel figcaption{margin-top:clamp(16px,2vw,26px);padding-top:14px;
  border-top:1px solid var(--rule)}

/* ── a screenshot row: three windows, read as one exhibit ──────────────
   Each shot keeps its own caption, and the row's lede says when they were
   taken and against what -- a screenshot of a GCS with no vehicle attached is
   a screenshot of nothing, so the conditions are part of the figure. */
.shots{margin:var(--s5) 0 0}
.shots__lede{margin:0 0 14px;font-family:var(--data);font-size:var(--fs-caption);line-height:1.7;
  color:var(--ink-3);max-width:none}
.shots__lede .silk{display:block;margin-bottom:6px;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.shots__lede .silk i{font-style:normal;color:var(--signal)}
.shots__lede b{font-weight:400;color:var(--ink)}
.shots__row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.shots__row figure{margin:0;border-radius:13px;overflow:hidden;background:var(--s-sunk);
  box-shadow:var(--e2);display:flex;flex-direction:column}
.shots__row img{display:block;width:100%;height:auto;aspect-ratio:1500/778;object-fit:cover;
  object-position:top left;transition:transform 600ms var(--ease)}
.shots__row figure:hover img{transform:scale(1.02)}
.shots__row figcaption{padding:12px 14px 14px;font-family:var(--data);font-size:10.5px;
  line-height:1.65;color:var(--ink-3)}
.shots__row .silk{display:block;margin-bottom:5px;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--signal-text)}

/* ── further reading, as cards ─────────────────────────────────────────
   A three-column table of links reads as a spreadsheet and wastes the width on
   a phone. Each row is a card: what you want, why this one, and where to go. */
.reads{list-style:none;margin:var(--s5) 0 0;padding:0;display:grid;gap:10px;
  grid-template-columns:repeat(auto-fit,minmax(290px,1fr))}
.reads li{display:flex;flex-direction:column;gap:8px;padding:16px 18px;border-radius:13px;
  background:var(--s-raised);box-shadow:var(--e1);
  transition:transform 240ms var(--ease),box-shadow 240ms var(--ease)}
.reads li:hover{transform:translateY(-2px);box-shadow:var(--e2)}
.reads .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.13em;text-transform:uppercase;color:var(--signal-text)}
.reads .why{margin:0;font-family:var(--prose);font-size:var(--fs-box);line-height:1.55;
  color:var(--ink-2)}
.reads .go{margin:auto 0 0;padding-top:10px;box-shadow:0 -1px 0 var(--rule);
  font-family:var(--data);font-size:11px;color:var(--ink-3);word-break:break-word}
.reads .go a{color:var(--ink);border-bottom:1px solid var(--rule-lit)}
.reads .go a:hover{color:#fff;border-bottom-color:var(--signal)}

/* ── the chapter break carries the vehicle across it ───────────────────
   The breaks were a numeral, two lines and a great deal of nothing. Now the
   hull crosses each one under its own waterline: the same glyph as the title,
   so the page has one animal in it rather than a new one per section. */
.chapter{position:relative;overflow:hidden}
.chapter__sea{position:absolute;left:0;right:0;bottom:0;height:78px;pointer-events:none}
.chapter__wave{position:absolute;left:0;right:0;bottom:22px;width:100%;height:34px;overflow:visible}
.chapter__wave path{fill:none;stroke:var(--rule-lit);stroke-width:1.5;vector-effect:non-scaling-stroke;
  animation:swell 16s linear infinite}
.chapter__hull{position:absolute;bottom:10px;width:76px;height:auto;opacity:.45;
  animation:patrol 40s linear infinite}
.chapter__hull rect,.chapter__hull path{fill:var(--ink-3)}
.chapter__hull .fin{fill:var(--rule-lit)}
.chapter__hull .eye{fill:var(--signal)}
.chapter__hull .ping circle{fill:none;stroke:var(--signal);stroke-width:1.5;opacity:0;
  animation:pingout 4s var(--ease) infinite}
.chapter__hull .ping circle:nth-child(2){animation-delay:.45s}
@keyframes pingout{0%{opacity:.6;transform:scale(.25);transform-origin:96px 22px}
  70%,100%{opacity:0;transform:scale(1.6);transform-origin:96px 22px}}
@media (prefers-reduced-motion:reduce){
  .chapter__hull,.chapter__wave path,.chapter__hull .ping circle{animation:none}
  .chapter__hull{left:12%}
}

/* ── shoulders, as a dive ──────────────────────────────────────────────
   A list of influences is a bookshelf. Here each voice sits at a depth and
   points at the instrument in this vehicle it actually moved; the panel shows
   what that instrument reads today. Depth is ordering, not measurement. */
.dive{margin:var(--s5) 0 0;display:grid;gap:16px;grid-template-columns:minmax(230px,.34fr) minmax(0,1fr);
  align-items:stretch}   /* the panel matches the scale's height, or the row ends half empty */
.dive__scale{position:relative;padding:8px 0 8px 22px;display:grid;gap:4px}
.dive__scale::before{content:"";position:absolute;left:8px;top:0;bottom:0;width:1px;
  background:linear-gradient(180deg,var(--rule-lit),var(--signal))}
.dive__scale button{position:relative;display:grid;grid-template-columns:1fr auto;
  gap:2px 10px;padding:9px 12px;border:1px solid transparent;border-radius:10px;background:none;
  cursor:pointer;text-align:left;transition:background 200ms var(--ease),border-color 200ms var(--ease)}
.dive__scale button::before{content:"";position:absolute;left:-18px;top:50%;width:11px;height:1px;
  background:var(--rule-lit)}
.dive__scale button:hover{background:rgba(255,255,255,.04)}
.dive__scale button.on{border-color:var(--signal);background:rgba(255,42,20,.07)}
.dive__scale button.on::before{background:var(--signal);width:15px;left:-22px}
.dive__scale .w{font-family:var(--display);font-weight:700;font-size:12px;color:var(--ink-2)}
.dive__scale button.on .w{color:#fff}
.dive__scale .m{font-family:var(--data);font-size:9.5px;color:var(--ink-3)}
.dive__scale .i{grid-column:1/-1;font-family:var(--data);font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3)}
.dive__scale button.on .i{color:var(--signal-text)}

.dive__panel{display:grid;gap:14px;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  padding:clamp(16px,2vw,24px);border-radius:16px;background:var(--s-raised);box-shadow:var(--e2)}
.dive__instr{padding:14px;border-radius:12px;background:var(--s-sunk);box-shadow:var(--e-in);
  display:flex;flex-direction:column}
.dive__instr .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.dive__instr b{display:block;margin:6px 0 2px;font-family:var(--display);font-weight:800;
  font-size:var(--fs-num-hero);line-height:.9;letter-spacing:-.04em;color:#fff}
.dive__instr > span:nth-of-type(2){display:block;font-family:var(--data);font-size:10.5px;
  line-height:1.5;color:var(--ink-3)}
.dive__instr canvas{display:block;width:100%;height:auto;margin-top:auto;padding-top:14px}
.dive__say .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--signal-text)}
.dive__say h3{margin:8px 0 10px}
.dive__say p{margin:0 0 10px;font-size:var(--fs-box);color:var(--ink-2)}
.dive__say p b{color:#fff;font-weight:700}
.dive__say a{font-family:var(--data);font-size:10.5px;color:var(--signal-text);
  border-bottom:1px solid transparent}
.dive__say a:hover{border-bottom-color:var(--signal)}
.dive figcaption{grid-column:1/-1;margin-top:2px}
@media (max-width:980px){
  .dive{grid-template-columns:1fr}
  .dive__panel{grid-template-columns:1fr}
  .dive__scale{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
  .dive__scale::before,.dive__scale button::before{display:none}
  .dive__scale{padding-left:0}
}

/* ── inside its head: three panes, one clock ───────────────────────────
   The run is a toy integrator, and the figure says so; the rates, the gap
   distribution and the ladder are the measured ones. The narration strip is
   the vehicle speaking in fields it actually has. */
.brain{margin:var(--s5) 0 0}
.brain__screen{position:relative;border-radius:16px;overflow:hidden;background:var(--s-sunk);
  box-shadow:var(--e2)}
.brain__screen canvas{display:block;width:100%;height:auto}
.brain__say{padding:14px 18px;background:var(--s-key);box-shadow:0 -1px 0 var(--rule);
  font-family:var(--prose);font-style:italic;font-size:var(--fs-lede);line-height:1.5;
  color:var(--ink);min-height:3.4em}
.brain__rail{display:grid;gap:10px;grid-template-columns:minmax(0,1fr) auto;align-items:center;
  margin-top:12px}
.brain__rail ol{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:4px}
.brain__rail button{display:grid;grid-template-columns:auto auto;gap:7px;align-items:baseline;
  padding:8px 12px;border:1px solid var(--rule);border-radius:9px;background:none;cursor:pointer;
  transition:border-color 200ms var(--ease),background 200ms var(--ease)}
.brain__rail button:hover{border-color:var(--rule-lit);background:rgba(255,255,255,.04)}
.brain__rail .n{font-family:var(--data);font-size:9.5px;color:var(--ink-3)}
.brain__rail .t{font-family:var(--display);font-weight:700;font-size:11px;color:var(--ink-2)}
.brain__rail button.on{border-color:var(--signal);background:rgba(255,42,20,.08)}
.brain__rail button.on .t{color:#fff}
.brain__rail button.past .t{color:#3fd98a}
.brain__ctl{display:flex;align-items:center;gap:8px}
.brain__speed{display:flex;align-items:center;gap:7px}
.brain__speed .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
.brain__speed input{width:88px}
.brain__speed output{font-family:var(--data);font-size:10.5px;color:var(--ink);min-width:2.6ch}
.brain figcaption{margin-top:14px}
@media (max-width:900px){
  .brain__rail{grid-template-columns:1fr}
  .brain__say{font-size:var(--fs-body)}
}

/* ── the theatre: photon to thrust, one stage at a time ────────────────
   Replaces ten stacked cards that used a third of the width and explained the
   stages in prose. Here the measured cost is drawn to scale across the top, the
   stage plays big in the middle, the physics under it is cited beside it, and
   the ten stages are a rail you can scrub. Paced after Kurzgesagt, figured
   after MLU-Explain, and kept honest after Azeria Labs: the real structure, not
   a cartoon of it. */
.theatre{margin:var(--s5) 0 0;display:grid;gap:14px}
.theatre__budget{padding:14px 16px;border-radius:14px;background:var(--s-raised);box-shadow:var(--e2)}
.theatre .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.theatre .silk i{font-style:normal;color:var(--signal)}
.theatre__bar{display:flex;gap:2px;margin:10px 0 6px;height:34px}
.theatre__bar button{flex:1;min-width:0;border:0;border-radius:6px;cursor:pointer;
  background:rgba(255,255,255,.07);color:var(--ink-3);font-family:var(--data);font-size:10px;
  display:flex;align-items:center;justify-content:center;
  transition:background 200ms var(--ease),color 200ms var(--ease),transform 200ms var(--ease)}
.theatre__bar button:hover{background:rgba(255,255,255,.14);color:#fff}
.theatre__bar button.nom{background:repeating-linear-gradient(45deg,rgba(255,255,255,.05) 0 4px,transparent 4px 8px)}
.theatre__bar button.on{background:var(--signal);color:#fff;transform:translateY(-2px)}
.theatre__axis{display:flex;justify-content:space-between;font-family:var(--data);font-size:9.5px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}

.theatre__stage{display:grid;gap:14px;grid-template-columns:minmax(0,1.45fr) minmax(280px,.55fr);
  align-items:start}
.theatre__screen{position:relative;border-radius:14px;overflow:hidden;background:var(--s-sunk);
  box-shadow:var(--e2)}
.theatre__screen canvas{display:block;width:100%;height:auto;cursor:pointer}
/* a header strip, not an overlay: overlaid, it covered whatever each stage
   drew in its own top-left corner */
.theatre__hud{display:grid;grid-template-columns:auto auto 1fr;align-items:baseline;gap:6px 14px;
  padding:12px 16px 10px;background:var(--s-key);box-shadow:0 1px 0 var(--rule)}
.theatre__hud .silk{grid-row:1;grid-column:1}
.theatre__hud b{grid-row:1;grid-column:2;font-family:var(--display);font-weight:800;
  font-size:clamp(1.5rem,1rem + 1.4vw,2.1rem);line-height:1;letter-spacing:-.04em;color:#fff}
.theatre__hud b u{text-decoration:none;font-size:.42em;color:var(--signal-text);margin-left:3px}
.theatre__hud > span:last-child{grid-row:1;grid-column:3;font-family:var(--data);
  font-size:10.5px;color:var(--ink-3)}
.theatre__ctl{position:absolute;right:14px;bottom:14px;display:flex;gap:6px}
.theatre__text h3{margin:0 0 10px}
.theatre__text p{margin:0;color:var(--ink-2)}
.theatre__text b{color:#fff;font-weight:400;font-family:var(--data);font-size:.95em}
.theatre__theory{margin-top:16px;padding:14px;border-radius:12px;background:var(--s-sunk);
  box-shadow:var(--e-in)}
.theatre__theory p{margin:8px 0 10px;font-size:var(--fs-box);color:var(--ink-2)}
.theatre__theory a{font-family:var(--data);font-size:10.5px;letter-spacing:.04em;
  color:var(--signal-text);border-bottom:1px solid transparent}
.theatre__theory a:hover{border-bottom-color:var(--signal)}
.theatre__src{margin:14px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.theatre__src code{font-size:10.5px;color:var(--ink-3)}

.theatre__list{list-style:none;margin:0;padding:0;display:grid;gap:4px;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.theatre__list button{width:100%;display:grid;grid-template-columns:auto 1fr auto;gap:8px;
  align-items:baseline;padding:9px 11px;border:1px solid var(--rule);border-radius:10px;
  background:none;cursor:pointer;text-align:left;
  transition:border-color 200ms var(--ease),background 200ms var(--ease)}
.theatre__list button:hover{border-color:var(--rule-lit);background:rgba(255,255,255,.04)}
.theatre__list button.on{border-color:var(--signal);background:rgba(255,42,20,.07)}
.theatre__list .n{font-family:var(--data);font-size:9.5px;color:var(--ink-3)}
.theatre__list .t{font-family:var(--display);font-weight:700;font-size:11px;color:var(--ink-2)}
.theatre__list button.on .t{color:#fff}
.theatre__list .v{font-family:var(--data);font-size:11px;color:var(--ink)}
.theatre__list .v u{text-decoration:none;font-size:.72em;color:var(--ink-3);margin-left:2px}
@media (max-width:1000px){
  .theatre__stage{grid-template-columns:1fr}
  .theatre__hud{grid-template-columns:auto 1fr}
  .theatre__hud > span:last-child{grid-row:2;grid-column:1/-1}
}

/* ── the live board reading ────────────────────────────────────────────
   Generated by tools/board_panel.py from a snapshot taken over the cable. It
   is dated on its face because that is the only honest way to show a live
   reading in a static page: this is what the board said, then. */
.board-live{margin:var(--s5) 0 0;padding:clamp(16px,2vw,26px);border-radius:16px;
  background:var(--s-raised);box-shadow:var(--e2);position:relative;overflow:hidden}
.board-live::before{content:"";position:absolute;inset:0 0 auto 0;height:2px;
  background:linear-gradient(90deg,var(--signal),transparent 60%)}
.board-live header{display:flex;flex-wrap:wrap;justify-content:space-between;gap:10px;
  padding-bottom:14px;margin-bottom:16px;box-shadow:0 1px 0 var(--rule)}
.board-live .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.board-live .silk i{font-style:normal;color:var(--signal)}
.board-live__grid{display:grid;gap:14px;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) minmax(0,1fr)}
.board-live__wire,.board-live__streams,.board-live__checks{padding:14px;border-radius:12px;
  background:var(--s-sunk);box-shadow:var(--e-in);margin:0;list-style:none}
.board-live__wire b{display:block;margin:8px 0 10px;font-family:var(--display);font-weight:800;
  font-size:var(--fs-num-hero);line-height:.9;letter-spacing:-.04em;color:#fff}
.board-live__wire b u{text-decoration:none;font-size:.32em;color:var(--signal-text);margin-left:3px}
.board-live__bar{position:relative;height:9px;border-radius:5px;background:rgba(255,255,255,.07)}
.board-live__bar i{position:absolute;inset:0 auto 0 0;width:var(--w);border-radius:5px;
  background:var(--medium-text)}
.board-live__bar u{position:absolute;top:-4px;bottom:-4px;left:var(--x);width:2px;
  background:var(--signal)}      /* the 60 % bar this project ships against */
.board-live__wire p{margin:10px 0 0;font-family:var(--data);font-size:10.5px;line-height:1.6;
  color:var(--ink-3)}
.board-live__streams li{display:grid;grid-template-columns:1fr auto;align-items:center;
  gap:3px 8px;margin-bottom:9px}
.board-live__streams b{font-family:var(--data);font-size:10.5px;color:var(--ink);font-weight:400}
.board-live__streams i{grid-column:1/-1;order:3;height:3px;border-radius:2px;
  background:rgba(255,255,255,.07);position:relative}
.board-live__streams i::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w);
  border-radius:2px;background:var(--medium-text)}
.board-live__streams em{font-family:var(--data);font-style:normal;font-size:11px;color:#fff}
.board-live__streams em u{text-decoration:none;font-size:.7em;color:var(--ink-3);margin-left:2px}
.board-live__streams span{grid-column:1/-1;order:4;font-family:var(--data);font-size:9.5px;
  color:var(--ink-3)}
.board-live__checks li{display:grid;grid-template-columns:auto 1fr;gap:2px 10px;
  padding-bottom:9px;margin-bottom:9px;box-shadow:0 1px 0 var(--rule)}
.board-live__checks li:last-child{padding-bottom:0;margin-bottom:0;box-shadow:none}
.board-live__checks b{font-family:var(--display);font-weight:800;font-size:10px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.board-live__checks span{font-family:var(--data);font-size:11.5px;color:#fff;text-align:right}
.board-live__checks em{grid-column:1/-1;font-style:normal;font-family:var(--data);font-size:10px;
  color:var(--ink-3)}
.board-live__checks .ok span{color:#3fd98a} .board-live__checks .no span{color:var(--signal-text)}
.board-live__checks .warn span{color:#e0b341}
/* the board's own words, quoted as a terminal line */
.board-live__cfg{margin:14px 0 0;padding:14px;border-radius:12px;background:var(--s-sunk);
  box-shadow:var(--e-in)}
.board-live__cfg code{display:block;margin:8px 0;font-family:var(--data);font-size:13px;
  color:var(--signal-text);letter-spacing:.02em}
.board-live__cfg > span:last-child{display:block;font-family:var(--data);font-size:10.5px;
  line-height:1.9;color:var(--ink-3)}
/* the inline code inside that sentence must stay inline, or the sentence breaks
   into three lines with a word on each */
.board-live__cfg > span:last-child code{display:inline;margin:0;font-size:10.5px;
  color:var(--signal-text)}
.board-live__cfg b{color:#fff;font-weight:400}
.board-live figcaption{margin-top:14px}
@media (max-width:980px){ .board-live__grid{grid-template-columns:1fr} }

/* ── the safety chain ─────────────────────────────────────────────────
   Drawn as a chain because that is the argument: eight plain links, each held
   by a different owner, and the strength is in the order. A link that is OFF
   is drawn broken, and one that cannot tell two states apart is drawn thin --
   the figure shows the chain as configured, not as intended. */
.chain{margin:var(--s5) 0 0;padding:clamp(16px,2vw,26px);border-radius:16px;
  background:var(--s-raised);box-shadow:var(--e2)}
.chain__links{list-style:none;margin:0;padding:0;display:grid;gap:0;
  grid-template-columns:repeat(8,minmax(0,1fr));counter-reset:link}
.chain__links li{position:relative;padding:44px 10px 12px;text-align:center;counter-increment:link}
/* the link itself: an oval ring, and the bar that joins it to the next one */
.chain__links li::before{content:"";position:absolute;left:50%;top:6px;width:54px;height:26px;
  margin-left:-27px;border-radius:999px;border:3px solid var(--rule-lit);background:var(--s-sunk);
  transition:border-color 260ms var(--ease),background 260ms var(--ease),transform 260ms var(--ease)}
.chain__links li::after{content:"";position:absolute;top:18px;left:calc(50% + 27px);
  width:calc(100% - 54px);height:3px;background:var(--rule-lit);
  transition:background 260ms var(--ease)}
.chain__links li:last-child::after{display:none}
.chain__links b{display:block;font-family:var(--display);font-weight:800;font-size:12px;
  letter-spacing:.01em;color:#fff;line-height:1.25}
.chain__links span{display:block;margin-top:5px;font-family:var(--data);font-size:10.5px;
  line-height:1.4;color:var(--ink-3)}
.chain__links > li > em{display:inline-block;margin-top:7px;padding:2px 7px;border-radius:999px;
  font-style:normal;font-family:var(--data);font-size:9.5px;letter-spacing:.06em;
  color:var(--ink-2);background:var(--s-sunk)}
/* the states the figure can show */
.chain__links li.path::before{border-color:var(--medium-text)}
.chain__links li.path::after{background:var(--medium-text)}
.chain__links li.catch::before{border-color:#3fd98a;background:rgba(63,217,138,.16);transform:scale(1.12)}
.chain__links li.catch b{color:#3fd98a}
.chain__links li.miss::before{border-color:var(--signal);background:rgba(255,42,20,.14);transform:scale(1.12)}
.chain__links li.miss b{color:var(--signal-text)}
.chain__links li.broken::before{border-style:dashed;border-color:var(--signal)}
.chain__links li.broken::after{background:repeating-linear-gradient(90deg,var(--signal) 0 5px,transparent 5px 11px)}
.chain__links li.broken > em{color:var(--signal-text)}
.chain__links li.weak::before{border-width:1.5px;border-color:#e0b341}
.chain__links li.weak > em{color:#e0b341}

.chain__faults{display:flex;flex-wrap:wrap;gap:7px;margin-top:18px;padding-top:16px;
  box-shadow:0 -1px 0 var(--rule)}
.chain__faults .key.on{border-color:var(--signal);color:var(--signal-text)}
.chain__verdict{display:grid;gap:9px;margin-top:14px;grid-template-columns:1fr 1fr 2.4fr}
.chain__verdict > div{padding:12px 14px;border-radius:11px;background:var(--s-sunk);box-shadow:var(--e-in)}
.chain__verdict .silk{display:block;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
.chain__verdict b{display:block;margin-top:6px;font-family:var(--data);font-size:12.5px;
  font-weight:400;line-height:1.5;color:#fff}
.chain__verdict b.bad{color:var(--signal-text)}
.chain figcaption{margin-top:14px}
@media (max-width:1100px){
  .chain__links{grid-template-columns:repeat(4,minmax(0,1fr));row-gap:14px}
  .chain__links li:nth-child(4)::after{display:none}
  .chain__verdict{grid-template-columns:1fr 1fr}
  .chain__verdict .wide{grid-column:1/-1}
}
@media (max-width:560px){
  .chain__links{grid-template-columns:repeat(2,minmax(0,1fr))}
  .chain__links li:nth-child(2n)::after{display:none}
  .chain__links li:nth-child(4)::after{display:none}
}

/* ── the simulator gallery: one hull shot, four course shots ─────────── */
.simgal{display:grid;gap:10px;margin:var(--s5) 0;
  grid-template-columns:repeat(4,1fr);grid-template-areas:"h h a b" "h h c d"}
.simgal figure{margin:0;position:relative;border-radius:12px;overflow:hidden;background:#000;
  box-shadow:var(--e2)}
.simgal figure:nth-child(2){grid-area:a} .simgal figure:nth-child(3){grid-area:b}
.simgal figure:nth-child(4){grid-area:c} .simgal figure:nth-child(5){grid-area:d}
.simgal__hero{grid-area:h}
.simgal img{display:block;width:100%;height:100%;object-fit:cover;aspect-ratio:1600/789;
  transition:transform 600ms var(--ease)}
.simgal figure:hover img{transform:scale(1.03)}
.simgal figcaption{position:absolute;left:0;right:0;bottom:0;padding:22px 12px 10px;
  background:linear-gradient(0deg,rgba(0,0,0,.78),transparent);   /* a scrim, for legibility */
  font-family:var(--data);font-size:11px;color:var(--ink-2)}
.simgal .silk{display:block;font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.13em;text-transform:uppercase;color:#fff}
.simgal .silk i{font-style:normal;color:var(--signal)}
.simgal__hero figcaption{padding:48px 18px 16px;font-size:12px;max-width:none}
@media (max-width:860px){
  .simgal{grid-template-columns:1fr 1fr;grid-template-areas:"h h" "a b" "c d"}
  .simgal__hero figcaption{position:static;background:var(--s-raised)}
}

/* ── the section head: heading and its intro side by side ──────────────
   On a wide screen the intro used to sit under the heading at 70ch and leave
   the right half of every section empty. From 1200 px the heading takes the
   left column and the intro the right, the way an editorial page pairs a
   headline with its standfirst; everything after them spans both again. */
@media (min-width:1200px){
  section:not(:first-of-type) > .wrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:clamp(40px,5vw,96px);align-items:start}
  section:not(:first-of-type) > .wrap > *{grid-column:1/-1}
  section:not(:first-of-type) > .wrap > h2.col{grid-column:1;max-width:none}
  section:not(:first-of-type) > .wrap > h2.col + .lede{grid-column:2;max-width:62ch;margin-top:0}
}

/* ── display sizes ────────────────────────────────────────────────────
   Measured in Chrome at 1920 / 1280 / 390 px (2026-09-22). Before this, a pool
   photo rendered at 796 x 1061, each HUD still at 1538 x 1373, and the hull
   elevations at 1522 x 1393 -- a picture you have to scroll past is not a
   picture, it is a wall. Every photo now has a ceiling that is about the size
   the eye takes in at once. */
/* fill the row, but never fewer than four across on a wide screen: capping the
   TILE width left a third of the section empty, capping the COUNT does not */
.strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:9px}
@media (min-width:1100px){
  .strip{grid-template-columns:repeat(4,1fr)}
  /* two photos in a four-column grid left half the section empty */
  .strip:has(img:nth-child(2):last-child){grid-template-columns:repeat(2,1fr)}
  .strip:has(img:nth-child(3):last-child){grid-template-columns:repeat(3,1fr)}
}
.hud-pair{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  margin-top:var(--s5)}
.hud-pair .hero-render{margin-top:0}
.hero-render img{max-height:min(72vh,720px);object-fit:contain;background:#000}
.panel img{max-width:1180px;margin-inline:auto}
.panel img[src$="hull-elevations.svg"]{max-width:920px}
.plate{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
/* a four-item gallery in three columns leaves two dead cells; give it two */
.plate:has(> figure:nth-child(4):last-child){grid-template-columns:repeat(2,1fr)}
@media (min-width:1500px){
  .plate:not(:has(> figure:nth-child(4):last-child)){grid-template-columns:repeat(3,1fr)}
}

.strip img{aspect-ratio:1;object-fit:cover;max-height:clamp(240px,26vw,380px);filter:saturate(.55) contrast(1.1) brightness(.82);
  transition:filter var(--t-mid) var(--ease),transform var(--t-mid) var(--ease)}
.strip img:hover{filter:none;transform:translateY(-3px)}
.bleed{margin-left:calc(-1 * var(--gutter));margin-right:calc(-1 * var(--gutter))}
.bleed img{width:100%;max-height:76svh;object-fit:cover}

/* ── timeline ────────────────────────────────────────────────────── */
.years{margin-top:46px;border-top:1px solid var(--rule)}
.year{display:grid;grid-template-columns:104px 1fr;gap:clamp(14px,3vw,40px);
  padding:22px 0;border-bottom:1px solid var(--rule);align-items:baseline}
.year time{font-family:var(--data);font-size:11px;letter-spacing:.1em;color:var(--signal-text)}
.year p{margin:6px 0 0;color:var(--ink-2);font-size:var(--fs-box);max-width:62ch}

/* ── retractions ─────────────────────────────────────────────────── */
/* ── retractions: the belief, struck; the measurement, printed under it ──
   A bento, not a list. The two with the biggest swings take the wide cells.
   The claim is set as a sentence someone once believed, with a red rule
   through it; the measured value sits in a recessed readout underneath --
   the same well every measurement on this page lives in. */
.retracts{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-top:var(--s4)}
.retract{grid-column:span 2;position:relative;padding:20px 20px 22px;border-radius:12px;
  background:var(--s-raised);box-shadow:var(--e1);
  transition:box-shadow var(--t-mid) var(--ease),transform var(--t-mid) var(--ease)}
.retract:nth-child(-n+2){grid-column:span 3}
.retract:hover{box-shadow:var(--e3);transform:translateY(-2px)}
.retract b{display:block;font-family:var(--display);font-weight:700;font-size:.98rem;
  line-height:1.3;letter-spacing:-.01em;color:var(--ink-2);margin-bottom:12px;
  text-decoration:line-through;text-decoration-color:var(--signal);
  text-decoration-thickness:2px}
.retract p{margin:0;color:var(--ink-2);font-size:var(--fs-box);line-height:1.6}
.retract .was{display:inline-block;font-family:var(--data);font-size:var(--fs-caption);color:#fff;
  letter-spacing:.01em;padding:8px 12px;border-radius:8px;margin-bottom:12px;
  background:var(--s-sunk);box-shadow:var(--e-well);
  border-left:2px solid var(--signal)}
@media (max-width:1000px){
  .retracts{grid-template-columns:1fr 1fr}
  .retract,.retract:nth-child(-n+2){grid-column:span 1}
  .retract:first-child{grid-column:1 / -1}
}
@media (max-width:620px){.retracts{grid-template-columns:1fr}.retract{grid-column:1 / -1}}

/* ── code ────────────────────────────────────────────────────────── */
pre{font-family:var(--data);font-size:12.5px;line-height:1.72;background:var(--d1);
  border:1px solid var(--rule);border-left:2px solid var(--signal);
  padding:20px 22px;overflow-x:auto;margin:32px 0 0;color:var(--ink-2)}
pre .k{color:var(--signal-text)} pre .c{color:var(--ink-3);font-style:italic}
pre .s{color:var(--medium-text)}

/* ── plain list ──────────────────────────────────────────────────── */
ul.plain{list-style:none;padding:0;margin:30px 0 0;border-top:1px solid var(--rule)}
ul.plain li{display:flex;justify-content:space-between;gap:22px;flex-wrap:wrap;
  padding:14px 0;border-bottom:1px solid var(--rule);font-size:var(--fs-box);color:var(--ink)}
ul.plain li span{font-family:var(--data);font-size:10.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3);white-space:nowrap}

/* ── reveal: one orchestrated load, then scroll drives ───────────── */
.rise{opacity:0;transform:translateY(18px);
  transition:opacity 700ms var(--ease),transform 700ms var(--ease)}
.rise.in{opacity:1;transform:none}

/* scoped to the page's own footer: bare `footer` also matched every quote's
   attribution and gave each one 60 px of padding and a rule */
body > footer{padding:60px var(--gutter) 128px;border-top:1px solid var(--rule);
  font-family:var(--data);font-size:11px;
  color:var(--ink-3);letter-spacing:.04em;position:relative;z-index:2}
body > footer a{border:0;color:var(--ink-2)} body > footer a:hover{color:#fff;border:0}
body > footer p+p{opacity:.78;max-width:88ch;line-height:1.6}

@media (max-width:900px){
  main,footer{margin-left:0}
  section::before,section::after{display:none}
  .year{grid-template-columns:1fr;gap:4px}
  section:first-of-type{min-height:auto}
}

/* Below 720px a data table cannot stay a table and stay legible, so each row
   becomes a record with its column name carried in the cell. */
@media (max-width:720px){
  .ledger,.ledger tbody,.ledger tr,.ledger td{display:block;width:100%}
  .ledger thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .ledger tr{border-bottom:1px solid var(--rule-lit);padding:14px 0}
  .ledger td{border:0;padding:3px 0}
  .ledger td::before{content:attr(data-l);display:block;font-size:9px;letter-spacing:.16em;
    text-transform:uppercase;color:var(--ink-3);margin-bottom:3px}
  .ledger td:first-child{font-size:14px}
  ul.plain li{flex-direction:column;gap:4px}
  .strip{grid-template-columns:1fr 1fr;gap:7px}
  pre{font-size:11.5px;padding:16px 14px}
  figure.panel{padding:14px}
}
/* a drawing 820 units wide cannot shrink to a phone and stay a drawing */
@media (max-width:820px){
  figure.scrollable{overflow-x:auto;-webkit-overflow-scrolling:touch;
    overscroll-behavior-x:contain;position:relative}
  figure.scrollable svg,figure.scrollable img{min-width:680px}
  figure.scrollable figcaption{min-width:0;position:sticky;left:0}
  figure.scrollable::after{content:"drag the drawing sideways →";display:block;
    position:sticky;left:0;margin-top:10px;font-family:var(--data);font-size:9px;
    letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .rise{opacity:1;transform:none}
  body::before{display:none}
}

/* ═══════════════════════════════════════════════════════════════════
   THE DESCENT — structural language
   The page is a dive log, not a document. Three things carry that: a
   sounding line that reads live depth, chapter breaks that log the act,
   and a rhythm that alternates instrument / voice / evidence so no two
   sections feel the same.
   ═══════════════════════════════════════════════════════════════════ */

/* ── the sounding line ───────────────────────────────────────────── */
/* ── the descent dock ─────────────────────────────────────────────────
   Replaces the fixed left rail (2026-09-22). A vertical progress bar down the
   edge of a long page is the most borrowed device on the web, and this one also
   held 150 px of every screen hostage for the whole document. The dock costs a
   strip at the bottom, opens on hover/focus/tap/C, and -- the part a scrollbar
   cannot do -- draws each chapter as wide as its share of the page. */
.dock{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:70;
  font-family:var(--data);display:flex;flex-direction:column;align-items:stretch;
  gap:8px;width:min(860px,calc(100% - 32px))}
.dock__bar{display:grid;grid-template-columns:auto auto 1fr auto auto;align-items:center;gap:14px;
  width:100%;padding:6px 16px;border-radius:999px;border:1px solid var(--rule-lit);
  background:color-mix(in srgb,var(--s-key) 97%,transparent);
  box-shadow:var(--e3);color:var(--ink);text-align:left;
  transition:border-color 200ms var(--ease),transform 200ms var(--ease)}
.dock__bar:hover,.dock__bar:focus-visible{border-color:var(--signal);transform:translateY(-1px)}
.dock__idx b{font-size:13px;font-weight:700;color:#fff;letter-spacing:-.02em}
.dock__idx small{font-size:9px;color:var(--ink-3);margin-left:3px}
.dock__name{font-family:var(--display);font-weight:800;font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--signal-text);white-space:nowrap;
  max-width:16ch;overflow:hidden;text-overflow:ellipsis}
.dock__depth b{font-size:13px;font-weight:700;color:#fff}
.dock__depth small{font-size:9px;color:var(--ink-3);margin-left:2px}

/* the sonar floor: a canvas, drawn and flown by the dock script */
.dock__sea{position:relative;display:block;height:34px;min-width:0;cursor:ew-resize;
  touch-action:none}
.dock__sea canvas{display:block;width:100%;height:100%}
.dock--flying .dock__sea{cursor:grabbing}
.dock__tip{position:absolute;bottom:calc(100% + 10px);transform:translateX(-50%);
  white-space:nowrap;padding:4px 9px;border-radius:7px;background:#000;
  border:1px solid var(--rule-lit);font-family:var(--data);font-size:10px;letter-spacing:.06em;
  color:#fff;pointer-events:none}
.dock__idx{cursor:pointer;border-radius:7px;padding:3px 6px;margin:-3px -6px;border:0;
  background:none;color:inherit;font:inherit}
.dock__idx:hover,.dock__idx:focus-visible{background:rgba(255,255,255,.07)}

.dock__sheet{padding:16px 18px 14px;border-radius:16px;border:1px solid var(--rule-lit);
  background:color-mix(in srgb,var(--s-key) 94%,transparent);backdrop-filter:blur(18px);
  box-shadow:var(--e4,var(--e3));animation:dockin 220ms var(--ease) both}
@keyframes dockin{from{opacity:0;transform:translateY(8px) scale(.985)}to{opacity:1;transform:none}}
.dock__sheet .silk{display:block;margin-bottom:12px;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.dock__sheet .silk i{font-style:normal;color:var(--signal)}
.dock__rows{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:2px}
.dock__rows button{display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:baseline;
  padding:6px 8px 7px;border:0;border-radius:8px;background:none;cursor:pointer;text-align:left;
  transition:background 160ms var(--ease)}
.dock__rows button:hover,.dock__rows button:focus-visible{background:rgba(255,255,255,.06)}
.dock__rows .n{font-size:9px;color:var(--ink-3)}
.dock__rows .t{font-family:var(--display);font-weight:700;font-size:11px;letter-spacing:.02em;
  color:var(--ink-2)}
.dock__rows .on .t{color:#fff}
/* it lives IN the bar now. Hidden behind a hover, nobody could find it --
   which is the same as not shipping it. */
.dock__snd{display:flex;align-items:center;gap:6px;padding:5px 10px;border-radius:999px;
  border:1px solid var(--rule);background:rgba(255,255,255,.03);
  color:var(--ink-3);font-family:var(--data);font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;cursor:pointer;
  transition:color 200ms var(--ease),border-color 200ms var(--ease),background 200ms var(--ease)}
.dock__snd:hover,.dock__snd:focus-visible{color:var(--ink);border-color:var(--rule-lit);
  background:rgba(255,255,255,.07)}
.dock__snd .w1,.dock__snd .w2{opacity:0;transition:opacity 200ms var(--ease)}
.dock__snd.on{color:var(--signal-text);border-color:var(--signal)}
.dock__snd.on .w1{opacity:1;animation:sonar 2.6s var(--ease) infinite}
.dock__snd.on .w2{opacity:1;animation:sonar 2.6s var(--ease) .5s infinite}
@keyframes sonar{0%,100%{opacity:.25}45%{opacity:1}}

@media (max-width:640px){
  .dock{bottom:10px}
  .dock__bar{gap:9px;padding:7px 11px;grid-template-columns:auto 1fr auto auto}
  .dock__name{display:none}
  .dock__snd span{display:none}    /* the speaker alone, on a phone */
}
@media (prefers-reduced-motion:reduce){
  .dock__sheet{animation:none}
  .dock__snd.on .w1,.dock__snd.on .w2{animation:none;opacity:1}
}

/* ── chapter break: a log entry, full bleed ──────────────────────── */
/* 62svh of mostly nothing was a scroll tax between chapters; the break is a
   band now, with the numeral as the field it sits on rather than a shape
   floating beside the title */
/* a divider, not a chapter page: it marks a change of subject and gets out of
   the way. 62svh -> 38 -> 20, with the type stepped down to match. */
.chapter{min-height:0;display:flex;align-items:center;
  padding:clamp(34px,5vh,58px) var(--gutter) clamp(46px,6.5vh,74px);
  border-top:1px solid var(--rule);position:relative;overflow:hidden}
.chapter::before,.chapter::after{display:none}
.chapter .wrap{width:100%;position:relative;display:grid;grid-template-columns:auto 1fr;
  gap:clamp(20px,4vw,56px);align-items:center;max-width:var(--wrap)}
.chapter .no{font-family:var(--display);font-weight:700;
  font-size:clamp(2rem,1rem + 3.4vw,3.6rem);line-height:.78;letter-spacing:-.06em;
  color:transparent;-webkit-text-stroke:1px var(--rule-lit)}
/* and a second, huge copy behind everything: the chapter's own field mark */
.chapter .wrap::after{content:attr(data-no);position:absolute;right:0;top:50%;
  transform:translateY(-50%);font-family:var(--display);font-weight:800;
  font-size:clamp(5rem,3rem + 9vw,11rem);line-height:.72;letter-spacing:-.08em;
  color:rgba(255,255,255,.02);pointer-events:none;z-index:-1}
.chapter h2{margin:0;font-size:clamp(1.15rem,.9rem + .8vw,1.6rem)}
.chapter .sub{margin-top:14px;color:var(--ink-3);font-family:var(--data);
  font-size:11px;letter-spacing:.2em;text-transform:uppercase}
.chapter .hair{position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--signal);
  -webkit-mask-image:linear-gradient(90deg,#000,transparent 62%);
          mask-image:linear-gradient(90deg,#000,transparent 62%)}

/* ── split: text one side, evidence the other ────────────────────── */
.split{display:grid;grid-template-columns:minmax(0,var(--measure)) minmax(0,1fr);
  gap:clamp(28px,4.5vw,76px);align-items:start;margin-top:var(--s5)}
.split.flip{grid-template-columns:minmax(0,1fr) minmax(0,var(--measure))}
.split.flip > :first-child{order:2}
.split.flip > :last-child{order:1}
.split > *{min-width:0}
@media (max-width:1000px){
  .split,.split.flip{grid-template-columns:1fr}
  .split.flip > :first-child,.split.flip > :last-child{order:0}
}

/* ── glass, tinted by the hull ───────────────────────────────────── */
.pane{position:relative;padding:clamp(18px,2.4vw,32px);
  background:rgba(12,16,26,.55);border:1px solid var(--rule);
  border-top-color:color-mix(in srgb,var(--signal) 16%,var(--rule-lit))}
@supports (backdrop-filter:blur(8px)){
  .pane{backdrop-filter:blur(18px) saturate(1.2);background:rgba(12,16,26,.38)}
}
.pane{box-shadow:var(--e2)}
.pane::before{content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 1px 0 var(--edge-lit)}
.pane > *{position:relative}
.pane h3{margin-bottom:10px}
.pane p,.pane li{font-size:var(--fs-box);line-height:1.62}
.pane .k{font-family:var(--data);font-size:9.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--ink-3);display:block;margin-bottom:12px}

.panes{display:grid;grid-template-columns:repeat(auto-fit,minmax(248px,1fr));
  gap:1px;background:var(--rule);border:1px solid var(--rule);margin-top:var(--s5)}
.panes .pane{border:0}
.panes .pane:first-child{grid-column:1 / -1}
@media (max-width:760px){.panes .pane:first-child{grid-column:auto}}

.fig{font-family:var(--data);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--signal-text);display:block;margin-bottom:8px}

/* ── page-load orchestration: one moment, staggered ──────────────── */
@keyframes surface{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.boot > *{opacity:0;animation:surface 900ms var(--ease) forwards}
.boot > *:nth-child(1){animation-delay:60ms}
.boot > *:nth-child(2){animation-delay:180ms}
.boot > *:nth-child(3){animation-delay:300ms}
.boot > *:nth-child(4){animation-delay:420ms}
.boot > *:nth-child(5){animation-delay:540ms}
.boot .bento > *{opacity:0;animation:surface 700ms var(--ease) forwards}
.boot .bento > :nth-child(1){animation-delay:560ms}
.boot .bento > :nth-child(2){animation-delay:640ms}
.boot .bento > :nth-child(3){animation-delay:700ms}
.boot .bento > :nth-child(4){animation-delay:760ms}
.boot .bento > :nth-child(5){animation-delay:820ms}
.boot .bento > :nth-child(6){animation-delay:880ms}
.boot .bento > :nth-child(7){animation-delay:940ms}

@media (max-width:900px){
  .sound{display:none}
  .chapter .wrap{grid-template-columns:1fr;gap:14px}
  .chapter .no{font-size:3.4rem}
}
@media (prefers-reduced-motion:reduce){
  .boot > *,.boot .bento > *{opacity:1;animation:none}
}

/* ══ THE WIRE: a frame drawn as the bytes it is ══════════════════════
   The azeria-labs register convention: the structure IS the figure. Each
   byte is its own recessed cell holding its real hex; fields group bytes,
   carry their offset above and their decoded value below. Colour is role,
   and there are only three: RED is the part that means something (the verb
   and its tag), OCEAN is identity (who speaks, who listens), and everything
   else -- envelope and idle zeros -- stays in the dark it came from.
   44 bytes happen to split into two rows of 22 exactly on field boundaries,
   so the grid is 22 wide and no field is ever cut in half. */
.wire{margin-top:var(--s4);padding:clamp(16px,2.2vw,28px);border-radius:14px;
  background:var(--s-raised);box-shadow:var(--e2)}
.wire__cmd{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px 18px;
  padding-bottom:18px;margin-bottom:18px;box-shadow:0 1px 0 var(--rule)}
.wire__cmd code{font-size:14px;color:#fff;padding:6px 12px;border-radius:7px;
  background:var(--s-sunk);box-shadow:var(--e-in)}
.wire__cmd .silk:last-child{margin-left:auto}
.wire .silk{font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
.wire__bytes{display:grid;grid-template-columns:repeat(22,minmax(0,1fr));gap:12px 4px}
.fld{grid-column:span var(--n);display:flex;flex-direction:column;min-width:0;
  font-family:var(--data)}
.fld .off{font-size:9px;color:var(--ink-3);opacity:.7;padding:0 0 4px 2px}
.fld .hex{display:grid;grid-template-columns:repeat(var(--n),1fr);gap:2px;
  padding:3px;border-radius:6px;background:var(--s-sunk);box-shadow:var(--e-well)}
.fld .hex i{font-style:normal;text-align:center;font-size:clamp(10px,.55rem + .3vw,13px);
  line-height:1;padding:9px 0;border-radius:4px;color:var(--ink-3);
  background:var(--s-flush);box-shadow:inset 0 1px 0 var(--edge-lit)}
.fld b{margin-top:7px;padding-left:2px;font-family:var(--display);font-weight:800;
  font-size:8.5px;letter-spacing:.08em;line-height:1.25;text-transform:uppercase;
  color:var(--ink-3);overflow-wrap:anywhere}
.fld em{font-style:normal;font-size:12px;color:var(--ink-2);padding-left:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* roles */
.fld--verb .hex i,.fld--cmd .hex i{color:#fff;
  background:color-mix(in srgb,var(--signal) 24%,var(--s-flush));
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--signal) 45%,transparent)}
.fld--verb b,.fld--cmd b,.fld--verb em,.fld--cmd em{color:var(--signal-text)}
.fld--who .hex i{color:#fff;background:color-mix(in srgb,var(--medium) 26%,var(--s-flush));
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--medium) 50%,transparent)}
.fld--who b,.fld--who em{color:var(--medium-text)}
.fld--idle .hex i{opacity:.45}
.fld--idle em{color:var(--ink-3)}
/* the lookup table, azeria-style: name, value, what it means */
.wire__key{width:100%;margin-top:22px;border-collapse:separate;border-spacing:0 4px;
  font-size:12.5px}
.wire__key td{padding:9px 12px;background:var(--s-flush);vertical-align:baseline;
  color:var(--ink-2);font-family:var(--prose)}
.wire__key td:first-child{border-radius:7px 0 0 7px;width:1%;white-space:nowrap;
  box-shadow:inset 2px 0 0 var(--rule-lit)}
.wire__key td:last-child{border-radius:0 7px 7px 0}
.wire__key td b{font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3)}
.wire__key .v{font-family:var(--data);color:#fff;width:1%;white-space:nowrap}
.wire__key .fld--verb td:first-child,.wire__key .fld--cmd td:first-child{box-shadow:inset 2px 0 0 var(--signal)}
.wire__key .fld--who td:first-child{box-shadow:inset 2px 0 0 var(--medium-text)}
.wire figcaption{margin-top:16px}
/* narrow: the 22-byte rows no longer fit, so fields wrap as whole units */
@media (max-width:1000px){
  .wire__bytes{display:flex;flex-wrap:wrap;gap:12px 6px}
  .fld{flex:0 0 auto;width:calc(var(--n) * 32px + 8px)}
  .wire__cmd .silk:last-child{margin-left:0}
}

/* ══ THE CORE SAMPLE: the ledger, one column per entry ═══════════════
   Drawn like a drill core: a recessed tray, columns standing in the order
   they were laid down. Height is how many numbers an entry holds; colour is
   what the entry says about itself. Red is the only loud thing, and it is
   reserved for the entries that took something back. */
.core{margin-top:var(--s5);padding:clamp(16px,2.2vw,26px);border-radius:14px;
  background:var(--s-raised);box-shadow:var(--e2)}
.core__cols{list-style:none;margin:0;padding:10px 10px 0;display:flex;align-items:flex-end;
  gap:3px;height:clamp(150px,22vh,220px);border-radius:8px;
  background:var(--s-sunk);box-shadow:var(--e-well)}
.core__cols li{flex:1 1 0;min-width:2px;height:calc(var(--h) * 100%);
  border-radius:3px 3px 0 0;background:var(--rule-lit);
  transition:transform var(--t-fast) var(--ease),filter var(--t-fast) var(--ease);
  transform-origin:bottom}
.core__cols li:hover{transform:scaleY(1.04);filter:brightness(1.45)}
.core__cols li.core--back{background:var(--signal)}
.core__cols li.core--no{background:color-mix(in srgb,var(--caution) 78%,var(--s-sunk))}
.core__axis{display:flex;justify-content:space-between;margin-top:8px;
  font-family:var(--data);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3)}
.core figcaption{margin-top:14px;line-height:1.7}
.core__k{display:inline-flex;align-items:center;gap:7px;margin-right:18px;
  font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-2)}
.core__k::before{content:"";width:9px;height:9px;border-radius:2px;background:var(--rule-lit)}
.core__k.core--back::before{background:var(--signal)}
.core__k.core--no::before{background:var(--caution)}

/* ══ THE TALLY: a page that counts its own rows ══════════════════════
   Used on the capability map in place of a diagram. One bar, four states,
   each segment's width is its row count. Zero rows render as nothing, which
   is the honest picture of "nothing has been in water". */
.tally{margin:var(--s4) 0;padding:18px;border-radius:12px;background:var(--s-raised);
  box-shadow:var(--e2)}
.tally__bar{display:flex;gap:3px;height:14px;padding:3px;border-radius:999px;
  background:var(--s-sunk);box-shadow:var(--e-well)}
.tally__bar i{flex-basis:0;border-radius:999px}
.tally__bar i[style*="flex-grow:0"]{display:none}
.tally__key{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:14px;font-family:var(--display);
  font-weight:800;font-size:var(--fs-micro);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-3)}
.tally__key b{font-family:var(--data);font-size:14px;letter-spacing:0;color:#fff;margin-right:4px}
.tally figcaption{margin-top:10px}
/* colours follow the page's OWN emoji legend (🟣 bench, 🟡 built), not the
   front page's state tokens -- a bar that disagrees with the key printed
   three lines above it is worse than no bar */
.t--water{--c:var(--state-water)} .t--bench{--c:var(--state-soft)}
.t--built{--c:var(--cad-amber)} .t--blocked{--c:var(--state-blocked)}
.tally__bar i{background:var(--c)}
.tally__key span::before{content:"";display:inline-block;width:8px;height:8px;border-radius:2px;
  margin-right:7px;background:var(--c)}

/* ══ PHOTON TO THRUST: a sticky rail beside ten stops ════════════════
   Aceternity's Tracing Beam, ported: the spine's painted length is scroll
   progress through the list (stroke-dashoffset on a pathLength=1 line, a
   solid colour -- no moving gradient). Sticky Scroll Reveal, ported: the
   rail's readout swaps to the stop in view, so the left column is never
   empty while the prose runs on the right. */
.journey{display:grid;grid-template-columns:minmax(220px,300px) minmax(0,1fr);
  gap:clamp(24px,4vw,64px);margin-top:var(--s5);position:relative}
.journey__rail{position:sticky;top:clamp(70px,14vh,140px);align-self:start;
  height:calc(100svh - 2 * clamp(70px,14vh,140px));min-height:320px;display:flex;gap:18px}
.spine{width:24px;height:100%;flex:none;overflow:visible}
.spine__track{stroke:var(--rule-lit);stroke-width:1}
.spine__lit{stroke:var(--signal);stroke-width:2;stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset 120ms linear}
.journey__rail .readout{align-self:center;padding:22px 20px 24px;border-radius:14px;
  background:var(--s-sunk);box-shadow:var(--e-well);min-width:0;flex:1}
.journey__rail .readout b{display:block;margin:14px 0 10px;font-family:var(--data);font-weight:700;
  color:#fff;font-size:clamp(2.2rem,1.4rem + 2.2vw,3.4rem);letter-spacing:-.05em;line-height:1}
.journey__rail .readout b u{text-decoration:none;color:var(--signal-text);font-size:.32em;
  letter-spacing:.02em;margin-left:.3em;vertical-align:.55em}
.journey__rail .readout > span:last-child{display:block;font-size:var(--fs-caption);color:var(--ink-3);
  line-height:1.45}
.journey__rail .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--signal-text)}
.journey__stages{list-style:none;margin:0;padding:0;display:grid;gap:14px}
.stop{padding:22px 22px 18px;border-radius:14px;background:var(--s-raised);box-shadow:var(--e1);
  opacity:.55;transition:opacity var(--t-mid) var(--ease),box-shadow var(--t-mid) var(--ease)}
.stop.on{opacity:1;box-shadow:var(--e3)}
.stop .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);display:block;margin-bottom:10px}
.stop.on .silk{color:var(--signal-text)}
.stop > p{margin:0 0 12px;font-size:var(--fs-box);line-height:1.65;color:var(--ink-2);max-width:68ch}
.stop .src{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin:14px 0 0;
  padding-top:12px;box-shadow:0 -1px 0 var(--rule)}
.stop .src code{font-size:11px;color:var(--ink-3)}
.stop .pair{margin:4px 0 6px;max-width:460px}
/* mini table: requested vs delivered frame rate */
.mini{border-collapse:separate;border-spacing:3px;font-family:var(--data);font-size:12px;margin:2px 0 6px}
.mini th{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);text-align:left;padding-right:8px}
.mini td{padding:6px 10px;border-radius:6px;background:var(--s-sunk);box-shadow:var(--e-in);
  color:var(--ink-2);text-align:right}
.mini td.hi{color:#fff;box-shadow:var(--e-in),inset 0 -2px 0 var(--signal)}
/* stacked share bar */
.stack{display:flex;gap:2px;height:14px;padding:3px;border-radius:999px;max-width:460px;
  background:var(--s-sunk);box-shadow:var(--e-well)}
.stack i{flex:0 0 var(--w);min-width:3px;border-radius:999px;background:var(--rule-lit)}
.stack i.hi{background:var(--signal)}
.stack__k{display:flex;flex-wrap:wrap;gap:4px 16px;margin:8px 0 4px !important;
  font-family:var(--data);font-size:11px;color:var(--ink-3)}
.stack__k .hi{color:var(--signal-text)}
/* the lock ladder, as rungs */
.rungs{list-style:none;margin:2px 0 6px;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.rungs li{font-family:var(--data);font-size:11px;padding:7px 11px;border-radius:7px;
  background:var(--s-key);box-shadow:var(--e1);color:var(--ink-2)}
.rungs li.on{color:#fff}
.rungs li + li::before{content:"↓ ";color:var(--ink-3)}
.rungs li.x{color:var(--signal-text);background:var(--s-sunk);box-shadow:var(--e-in)}
@media (max-width:900px){
  .journey{grid-template-columns:1fr}
  .journey__rail{position:sticky;top:0;z-index:5;height:auto;min-height:0;
    background:var(--d0);padding:10px 0;margin:0 calc(-1 * var(--gutter));padding-inline:var(--gutter)}
  .spine{display:none}
  .journey__rail .readout{padding:12px 16px;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
  .journey__rail .readout b{margin:0;font-size:1.8rem}
  .stop{opacity:1}
}
@media (prefers-reduced-motion:reduce){.spine__lit{transition:none}.stop{transition:none}}

/* ── the two cores, as orbits (magicui Orbiting Circles, ported) ─────
   Period is the task's real period x 1000. Pure CSS: each ring rotates,
   each label counter-rotates to stay upright. */
.cores{margin:0;padding:clamp(18px,2.4vw,28px);border-radius:14px;background:var(--s-raised);
  box-shadow:var(--e2);overflow:hidden   /* the outer ring’s labels orbit past a phone’s edge */}
.orbits{position:relative;aspect-ratio:1;max-width:340px;margin:0 auto 18px;border-radius:50%;
  background:var(--s-sunk);box-shadow:var(--e-well)}
.orbit{position:absolute;border-radius:50%;box-shadow:inset 0 0 0 1px var(--rule-lit);
  animation:orbit var(--t) linear infinite}
.orbit--1{inset:30%;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--signal) 55%,transparent)}
.orbit--0a{inset:20%} .orbit--0b{inset:11%} .orbit--0c{inset:3%}
/* `translate`, not `transform:translate()`: the individual property composes
   BEFORE `rotate`, so the counter-rotation spins each label about its own
   centre. With transform it would swing every label off its ring. */
.orbit i{position:absolute;left:50%;top:0;translate:-50% -50%;font-style:normal;
  font-family:var(--data);font-size:9.5px;white-space:nowrap;padding:3px 7px;border-radius:999px;
  background:var(--s-key);box-shadow:var(--e1);color:var(--ink-2)}
.orbit--1 i{color:#fff;background:color-mix(in srgb,var(--signal) 30%,var(--s-key))}
.orbit--1 i:nth-child(2){top:75%;left:93%} .orbit--1 i:nth-child(3){top:75%;left:7%}
.orbit i{animation:counter var(--t) linear infinite}
.hub{position:absolute;inset:42%;display:grid;place-items:center;border-radius:50%;
  font-family:var(--display);font-weight:800;font-size:9px;letter-spacing:.12em;color:var(--ink-3);
  background:var(--s-key);box-shadow:var(--e2)}
@keyframes orbit{to{transform:rotate(360deg)}}
@keyframes counter{from{rotate:0deg}to{rotate:-360deg}}
@media (prefers-reduced-motion:reduce){.orbit,.orbit i{animation:none}}
.cores__k{width:100%}
.cores__k td:last-child{text-align:left;background:none;box-shadow:none;color:var(--ink-3)}
/* a spec plate, TE-style */
.spec{margin:0;padding:clamp(18px,2.4vw,28px);border-radius:14px;background:var(--s-raised);
  box-shadow:var(--e2)}
.spec .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);display:block;margin:0 0 12px}
.spec dl{display:grid;grid-template-columns:auto 1fr;gap:8px 16px;margin:0 0 24px;
  padding:14px 16px;border-radius:10px;background:var(--s-sunk);box-shadow:var(--e-well)}
.spec dt{font-family:var(--data);font-size:12px;color:#fff}
.spec dd{margin:0;font-size:var(--fs-caption);color:var(--ink-2);line-height:1.5}
.copies{list-style:none;margin:0 0 14px;padding:0;display:flex;flex-wrap:wrap;gap:6px}
.copies li{font-family:var(--data);font-size:11px;padding:7px 11px;border-radius:7px;
  background:var(--s-key);box-shadow:var(--e1);color:var(--ink-2)}
.spec p{margin:0;font-size:var(--fs-caption);color:var(--ink-3);line-height:1.55}
.split h3{margin-bottom:12px}

/* ══ THE STAGE ANIMATIONS ════════════════════════════════════════════
   One per stop: the frame ACTUALLY MOVING through that layer, not an
   illustration of it. Compositor-only properties (transform, opacity).
   They run only while their stop is the active one, so at most one
   animation is ever on screen; reduced motion freezes them at the pose
   that reads best as a still. */
/* ── colour loss: three channels per venue, measured ─────────────────
   The bar IS the measurement: width is the channel's mean level scaled to
   that venue's brightest channel, so the red bar's shortness is the point. */
.colour{margin:var(--s5) 0 0;padding:clamp(16px,2.2vw,26px);border-radius:14px;
  background:var(--s-raised);box-shadow:var(--e2)}
.colour__rows{list-style:none;margin:0;padding:0;display:grid;gap:18px;
  grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.colour__head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  margin-bottom:10px;padding-bottom:8px;box-shadow:0 1px 0 var(--rule)}
.colour__head b{font-family:var(--display);font-weight:800;font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:#fff}
.colour .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.chan{display:grid;grid-template-columns:14px 1fr auto;align-items:center;gap:10px;margin-top:7px}
.chan i{display:block;height:9px;border-radius:999px;background:var(--s-sunk);
  box-shadow:var(--e-in);position:relative}
.chan i::after{content:"";position:absolute;inset:1px auto 1px 1px;border-radius:999px;
  width:calc((100% - 2px) * var(--w) / 100%);background:var(--c)}
.chan b{font-family:var(--data);font-size:11px;color:var(--ink-2);min-width:3ch;text-align:right}
.chan--r{--c:var(--signal)} .chan--g{--c:#2fbf6a} .chan--b{--c:var(--medium-text)}
.chan--r .silk{color:var(--signal-text)}
.colour figcaption{margin-top:18px}

/* ── the record: two score cards, read from the official sheets ───────
   Each round's bar is scaled to the best round either year, so the two
   cards share one axis; the red tick is the finals wild card for THAT year,
   which is why it moves — the bar got longer and so did the bar to clear. */
.record{margin:var(--s5) 0 0}
.record__cards{display:grid;gap:14px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.score{padding:clamp(16px,2vw,24px);border-radius:14px;background:var(--s-raised);box-shadow:var(--e2)}
.score header{display:grid;grid-template-columns:auto 1fr;align-items:end;gap:0 14px;
  padding-bottom:12px;margin-bottom:14px;box-shadow:0 1px 0 var(--rule)}
.score time{grid-column:1/-1;font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.16em;color:var(--ink-3)}
.score .place{font-family:var(--display);font-weight:800;font-size:var(--fs-num-hero);
  line-height:.9;letter-spacing:-.04em;color:#fff}
.score .place sup{font-size:.34em;letter-spacing:0;color:var(--signal-text);margin-left:2px}
.score .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.score__rounds{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.score__rounds li{display:grid;grid-template-columns:96px 1fr 5ch 3ch;align-items:center;gap:10px}
.score__rounds i{display:block;height:10px;border-radius:999px;background:var(--s-sunk);
  box-shadow:var(--e-in);position:relative}
.score__rounds i::after{content:"";position:absolute;inset:1px auto 1px 1px;border-radius:999px;
  width:calc((100% - 2px) * var(--w) / 100%);background:var(--ink-2)}
.score__rounds i::before{content:"";position:absolute;top:-4px;bottom:-4px;left:var(--wc);
  width:2px;background:var(--signal);z-index:1}
.score__rounds b{font-family:var(--data);font-size:11px;color:var(--ink);text-align:right}
.score__rounds em{font-family:var(--data);font-style:normal;font-size:11px;color:var(--ink-3)}
.score__foot{margin:14px 0 0;font-family:var(--data);font-size:11px;color:var(--ink-3)}
.score__foot b{color:var(--signal-text);font-weight:400}
.record figcaption{margin-top:16px}

/* ── the blocker board: what is in the way, and whose move it is ─────
   Each row is keyed by who can actually clear it. Three owners, three
   colours, and no row where the owner is "us" — which is the point. */
.board{list-style:none;margin:var(--s4) 0 0;padding:0;display:grid;gap:8px}
.board li{display:grid;grid-template-columns:1fr auto;gap:4px 18px;align-items:baseline;
  padding:16px 18px;border-radius:11px;background:var(--s-raised);box-shadow:var(--e1);
  border-left:2px solid var(--c);transition:box-shadow var(--t-mid) var(--ease),
  transform var(--t-mid) var(--ease)}
.board li:hover{box-shadow:var(--e3);transform:translateX(2px)}
.board b{grid-column:1;justify-self:start;text-align:left;font-family:var(--display);
  font-weight:700;font-size:.98rem;color:#fff;line-height:1.3}
.board span{grid-column:1;justify-self:start;text-align:left;font-size:var(--fs-box);
  color:var(--ink-3);line-height:1.5}
.board em{grid-row:1 / span 2;font-style:normal;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--c);
  align-self:center;white-space:nowrap}
.board--water{--c:var(--state-water)} .board--fw{--c:var(--cad-amber)}
.board--hw{--c:var(--state-blocked)}
@media (max-width:620px){
  .board li{grid-template-columns:1fr}
  .board em{grid-row:auto;justify-self:start;margin-top:6px}
}

/* a pull quote: the one place on the page allowed to be personal */
/* a band, not a card. NOT a grid: the quote's text is a bare text node, and a
   bare text node inside a grid becomes an anonymous item that no selector can
   place -- which scattered the words and their attribution into separate
   cells. Block flow, with the attribution set to the right. */
.pull{margin:var(--s5) 0 0;padding:16px 0 16px 20px;border-radius:0;
  background:none;box-shadow:none;border-left:2px solid var(--signal);
  font-family:var(--display);font-weight:700;font-size:clamp(.98rem,.92rem + .3vw,1.16rem);
  line-height:1.45;letter-spacing:-.01em;color:#fff;max-width:72ch}
.pull em{font-style:normal;color:var(--signal-text)}
.pull footer{display:block;margin:10px 0 0;padding:0;border:0;
  font-family:var(--data);font-weight:400;font-size:var(--fs-micro);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);text-align:right}
.pull footer::before{content:"\2014\00a0"}
@media (max-width:760px){ .pull footer{text-align:left} }

/* ── the gate run ─────────────────────────────────────────────────────
   Seven steps and a hull that only advances when a step says yes. The path
   lights behind it; the red ticks under each step are the designed stops. */
.run{margin:var(--s4) 0 var(--s4);padding:clamp(14px,2vw,22px);border-radius:16px;
  background:var(--s-raised);box-shadow:var(--e2);overflow:hidden}
.run svg{display:block;width:100%;height:auto;overflow:visible}
.run__path{stroke:var(--rule-lit);stroke-width:2}
.run__lit{stroke:var(--signal);stroke-width:2;stroke-dasharray:790;stroke-dashoffset:790;
  animation:runlit 10s var(--ease) infinite}
.run__n circle{fill:var(--s-sunk);stroke:var(--rule-lit);stroke-width:2;
  animation:runnode 10s var(--ease) infinite;animation-delay:calc(var(--i) * 1.05s)}
.run__n text{text-anchor:middle;font-family:var(--data)}
.run__n .lab{font-family:var(--display);font-weight:800;font-size:13px;fill:#fff;letter-spacing:.02em}
.run__n .rate{font-size:10px;fill:var(--ink-3)}
.run__n .fail{stroke:var(--signal);stroke-width:1.5;stroke-dasharray:2 2;opacity:.7}
.run__n .why{font-size:9.5px;fill:var(--signal-text);opacity:.85}
.run__gate rect{fill:var(--ink-3)}
.run__sub rect{fill:var(--ink)} .run__sub circle{fill:var(--signal)}
.run__sub{animation:runsub 10s var(--ease) infinite}
@keyframes runlit{0%{stroke-dashoffset:790}75%,100%{stroke-dashoffset:0}}
@keyframes runnode{0%,4%{fill:var(--s-sunk);stroke:var(--rule-lit)}
  8%,100%{fill:var(--signal);stroke:var(--signal)}}
/* the hull hops step to step: it waits on each one, which is the point */
@keyframes runsub{
  0%{transform:translateX(70px)}   8%{transform:translateX(70px)}
  14%{transform:translateX(202px)} 19%{transform:translateX(202px)}
  25%{transform:translateX(333px)} 30%{transform:translateX(333px)}
  36%{transform:translateX(465px)} 41%{transform:translateX(465px)}
  47%{transform:translateX(597px)} 52%{transform:translateX(597px)}
  58%{transform:translateX(728px)} 63%{transform:translateX(728px)}
  69%{transform:translateX(860px)} 74%{transform:translateX(860px)}
  86%,100%{transform:translateX(950px);opacity:0}
}
@media (prefers-reduced-motion:reduce){
  .run__lit,.run__n circle,.run__sub{animation:none}
  .run__lit{stroke-dashoffset:0} .run__n circle{fill:var(--signal);stroke:var(--signal)}
  .run__sub{transform:translateX(860px)}
}

/* ── the width of now ─────────────────────────────────────────────────
   A live instrument, not a chart: the reader's own clock drives it, so the
   lanes drift apart in real time and the band between freshest and stalest is
   something you watch happen rather than something you are told. */
.nowfig{margin:var(--s5) 0 0;padding:clamp(14px,1.8vw,22px);border-radius:16px;
  background:var(--s-raised);box-shadow:var(--e2)}
.nowfig canvas{display:block;width:100%;height:auto;border-radius:11px;
  background:var(--s-sunk);box-shadow:var(--e-in)}
.nowfig__read{display:grid;gap:9px;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  margin-top:14px}
.nowfig__read > div{padding:11px 13px;border-radius:11px;background:var(--s-sunk);
  box-shadow:var(--e-in)}
.nowfig__read .silk{display:block;font-family:var(--display);font-weight:800;
  font-size:var(--fs-micro);letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
.nowfig__read b{display:block;margin-top:5px;font-family:var(--data);font-size:var(--fs-num);
  color:#fff;font-variant-numeric:tabular-nums}
.nowfig__ctl{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}
.nowfig__ctl .key.on{border-color:var(--signal);color:var(--signal-text)}
.nowfig figcaption{margin-top:14px}

/* ── the two long reads ───────────────────────────────────────────────
   Not link cards: each one carries a real figure out of the document it points
   at, generated by tools/site_pages.py, so the preview cannot advertise
   something the page no longer says. */
.pages{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));
  margin:var(--s5) 0 0}
.pages__card{display:flex;flex-direction:column;gap:12px;padding:clamp(20px,2.4vw,30px);
  border-radius:16px;background:var(--s-raised);box-shadow:var(--e2);border:0;
  color:inherit;text-decoration:none;
  transition:transform 260ms var(--ease),box-shadow 260ms var(--ease)}
.pages__card:hover,.pages__card:focus-visible{transform:translateY(-3px);box-shadow:var(--e3)}
.pages__card .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.pages__card .silk i{font-style:normal;color:var(--signal)}
.pages__card h3{margin:0;font-size:var(--fs-h2);letter-spacing:-.03em;color:#fff}
.pages__card p{margin:0;color:var(--ink-2)}
.pages__go{margin-top:auto;font-family:var(--data);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--signal-text)}
.pages__go i{font-style:normal;display:inline-block;transition:transform 220ms var(--ease)}
.pages__card:hover .pages__go i{transform:translateX(5px)}

.pages__cores{display:grid;gap:10px;grid-template-columns:1fr 1fr}
.pages__cores > div{padding:12px;border-radius:11px;background:var(--s-sunk);box-shadow:var(--e-in)}
.pages__cores ul{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:6px}
.pages__cores li{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  font-family:var(--data);font-size:11px;color:var(--ink-2)}
.pages__cores b{font-family:var(--display);font-weight:800;font-size:13px;color:#fff}
.pages__cores u{text-decoration:none;font-size:.62em;color:var(--ink-3);margin-left:2px}
/* core 1 is the one that may never be late, and it says so in ink */
.pages__cores > div:first-child b{color:var(--signal-text)}

.pages__tally{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.pages__tally li{display:grid;grid-template-columns:2.4ch auto 1fr;align-items:center;gap:9px}
.pages__tally b{font-family:var(--display);font-weight:800;font-size:15px;color:#fff;
  text-align:right}
.pages__tally .silk{font-size:var(--fs-micro)}
.pages__tally i{display:block;height:6px;border-radius:3px;background:var(--s-sunk);
  box-shadow:var(--e-in);position:relative}
.pages__tally i::after{content:"";position:absolute;inset:1px auto 1px 1px;border-radius:3px;
  width:calc((100% - 2px) * var(--w) / 100%);background:var(--c,var(--ink-3))}
.pages__tally em{grid-column:2/-1;font-style:normal;font-family:var(--data);font-size:10.5px;
  color:var(--ink-3);margin-top:-3px}
.pages__tally .t--water{--c:#2fbf6a} .pages__tally .t--bench{--c:#8b7cff}
.pages__tally .t--built{--c:#e0b341} .pages__tally .t--blocked{--c:var(--signal)}
/* a count of zero is the most important row on the card: it stays visible */
.pages__tally li:has(b:empty),.pages__tally .t--water b{color:var(--ink-3)}
@media (max-width:520px){ .pages__cores{grid-template-columns:1fr} }

/* ── the creed: one voice set above the rest of the shoulders list ───
   A plaque, not a card: deeper well, wider type, and the attribution in the
   data face so a date reads as a citation rather than a flourish. */
.creed{margin:40px 0 0;padding:clamp(26px,3.4vw,44px) clamp(22px,3.4vw,46px);border-radius:16px;
  background:var(--s-key);box-shadow:var(--e3),var(--e-in)}
.creed blockquote{margin:0;font-family:var(--display);font-weight:800;
  font-size:clamp(1.4rem,1rem + 2.1vw,2.6rem);line-height:1.15;letter-spacing:-.035em;color:#fff;
  text-wrap:balance}
.creed figcaption{margin-top:18px;padding-top:16px;box-shadow:0 -1px 0 var(--rule);
  font-family:var(--data);font-size:var(--fs-caption);line-height:1.6;color:var(--ink-2)}
.creed figcaption b{font-family:var(--display);font-weight:800;letter-spacing:.02em;color:#fff}
.creed figcaption em{display:block;margin-top:6px;font-style:normal;font-size:var(--fs-micro);
  letter-spacing:.06em;color:var(--ink-3)}
.creed p{margin:20px 0 0;max-width:68ch;color:var(--ink-2)}
.creed p strong{color:#fff}

/* ── what a vision verb hands back ──────────────────────────────────── */
.result{margin:0;padding:clamp(18px,2.4vw,26px);border-radius:14px;background:var(--s-raised);
  box-shadow:var(--e2)}
.result .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);display:block;margin-bottom:12px}
.result .frame{position:relative;aspect-ratio:21/9;border-radius:8px;background:var(--s-sunk);
  box-shadow:var(--e-well);overflow:hidden}
.result .frame i,.result .frame b,.result .frame u,.result .frame em{position:absolute;display:block}
.result .cx{left:50%;top:0;bottom:0;width:1px;background:var(--rule-lit)}
.result .cy{top:50%;left:0;right:0;height:1px;background:var(--rule-lit)}
.result .box{left:calc(50% + 62px - 34px);top:calc(50% - 30px);width:68px;height:52px;border-radius:4px;
  box-shadow:inset 0 0 0 1.5px var(--medium-text)}
.result .dx{left:50%;top:calc(50% + 34px);width:62px;height:2px;background:var(--signal)}
.result .dx::after{content:"";position:absolute;right:-1px;top:-3px;border:4px solid transparent;
  border-left:6px solid var(--signal);border-right:0}
.result .lab{left:calc(50% + 4px);top:calc(50% + 42px);font-style:normal;font-family:var(--data);
  font-size:11px;color:var(--signal-text)}
.result__k{margin:12px 0 14px;font-size:var(--fs-caption);color:var(--ink-3);line-height:1.55}
.codes{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:6px}
.codes li{padding:8px 10px;border-radius:7px;background:var(--s-sunk);box-shadow:var(--e-in);
  font-size:11px;color:var(--ink-3);line-height:1.35}
.codes b{display:block;font-family:var(--data);font-size:11.5px;color:#fff;margin-bottom:2px}
.codes .ok b{color:var(--state-water)} .codes .bad b{color:var(--signal-text)}

/* every horizontal scroller on the page gets the page's own scrollbar, not
   the browser's white default */
pre,.scrollable,.tw{scrollbar-width:thin;scrollbar-color:var(--rule-lit) transparent}
pre::-webkit-scrollbar,.scrollable::-webkit-scrollbar{height:6px}
pre::-webkit-scrollbar-thumb,.scrollable::-webkit-scrollbar-thumb{background:var(--rule-lit);border-radius:3px}
pre::-webkit-scrollbar-track,.scrollable::-webkit-scrollbar-track{background:transparent}
.split pre{font-size:11.5px}

/* ══ THE LAB: an explainer you can turn ══════════════════════════════
   mlu-explain's move: let the reader break it themselves. The canvas is the
   only thing on this page that shows a SIMULATION rather than a measurement,
   so it is labelled as one in the prose above it. */
.lab{display:grid;align-items:start;grid-template-columns:minmax(0,1.35fr) minmax(280px,.65fr);
  gap:clamp(16px,2.2vw,28px);margin-top:var(--s5);padding:clamp(16px,2.2vw,24px);
  border-radius:16px;background:var(--s-raised);box-shadow:var(--e2)}
.lab__stage{display:flex;flex-direction:column;gap:12px;min-width:0}
.lab canvas{width:100%;height:auto;border-radius:10px;background:var(--s-sunk);
  box-shadow:var(--e-well)}
.lab__read{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.lab__read > div{padding:10px 12px;border-radius:9px;background:var(--s-sunk);box-shadow:var(--e-in)}
.lab__read b{display:block;margin-top:5px;font-family:var(--data);font-size:15px;color:#fff}
.lab .silk{font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.lab__knobs{display:flex;flex-direction:column;gap:14px;min-width:0}
/* a <select> sizes itself to its LONGEST option and will not shrink below it,
   which pushed the whole page sideways on a phone. Bound it to its column. */
.lab__knobs select{width:100%;max-width:100%;min-width:0;text-overflow:ellipsis}
.lab__knobs .knob{min-width:0}
.knob{display:block}
.knob output{float:right;font-family:var(--data);font-size:12px;color:var(--signal-text)}
.knob em{display:block;margin-top:6px;font-style:normal;font-size:var(--fs-caption);
  line-height:1.5;color:var(--ink-3)}
.knob input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:26px;
  margin:8px 0 0;background:transparent;cursor:ew-resize}
.knob input[type=range]::-webkit-slider-runnable-track{height:8px;border-radius:999px;
  background:var(--s-sunk);box-shadow:var(--e-in)}
.knob input[type=range]::-moz-range-track{height:8px;border-radius:999px;
  background:var(--s-sunk);box-shadow:var(--e-in)}
/* a machined thumb: the same ladder as every other pressable thing here */
.knob input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:20px;height:20px;margin-top:-6px;border-radius:6px;background:var(--s-key);
  border:1px solid var(--rule-lit);box-shadow:var(--e2)}
.knob input[type=range]::-moz-range-thumb{width:20px;height:20px;border-radius:6px;
  background:var(--s-key);border:1px solid var(--rule-lit);box-shadow:var(--e2)}
.knob input[type=range]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--signal-text);
  outline-offset:2px}
.lab__presets{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
.lab__presets .key{padding:9px 12px;font-size:9px}
@media (max-width:980px){
  .lab{grid-template-columns:1fr}
  .lab__read{grid-template-columns:repeat(2,1fr)}
}

/* ── the lock ladder against the gap distribution ───────────────────
   Bar length is the share of 71 real gaps the rung covers. The rung that
   matters is marked: coast_s, sitting just above the p90. */
.rungs2{margin:var(--s5) 0 0;padding:clamp(16px,2.2vw,26px);border-radius:14px;
  background:var(--s-raised);box-shadow:var(--e2)}
.rungs2 > .silk{display:block;font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin-bottom:14px}
.rungs2 ol{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.rungs2 li{display:grid;grid-template-columns:minmax(120px,190px) 62px 1fr 56px;
  align-items:center;gap:12px}
.rungs2 b{font-family:var(--data);font-size:11.5px;color:var(--ink-2);font-weight:400;
  overflow:hidden;text-overflow:ellipsis}
.rungs2 em{font-style:normal;font-family:var(--data);font-size:12px;color:#fff;text-align:right}
.rungs2 i{display:block;height:10px;border-radius:999px;background:var(--s-sunk);
  box-shadow:var(--e-in);position:relative}
.rungs2 i::after{content:"";position:absolute;inset:2px auto 2px 2px;border-radius:999px;
  width:calc((100% - 4px) * var(--cov) / 100);background:var(--rule-lit)}
.rungs2 .key-rung i::after{background:var(--signal)}
.rungs2 .key-rung b,.rungs2 .key-rung u{color:var(--signal-text)}
.rungs2 u{text-decoration:none;font-family:var(--data);font-size:11px;color:var(--ink-3);
  text-align:right}
.rungs2__marks{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:14px;padding-top:12px;
  box-shadow:0 -1px 0 var(--rule);font-family:var(--data);font-size:10.5px;color:var(--ink-3)}
@media (max-width:760px){
  .rungs2 li{grid-template-columns:1fr 54px;grid-template-areas:"b e" "i u"}
  .rungs2 b{grid-area:b} .rungs2 em{grid-area:e} .rungs2 i{grid-area:i} .rungs2 u{grid-area:u}
}

/* ── fault injection: five paths, each a row that can go red ─────── */
.faults{margin:var(--s5) 0 0;padding:clamp(16px,2.2vw,26px);border-radius:14px;
  background:var(--s-raised);box-shadow:var(--e2)}
.faults > .silk{display:block;font-family:var(--display);font-weight:800;font-size:var(--fs-micro);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);margin-bottom:14px}
.faults ol{list-style:none;margin:0;padding:0;display:grid;gap:8px;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.faults li{position:relative;padding:14px 16px 14px 34px;border-radius:10px;
  background:var(--s-sunk);box-shadow:var(--e-in)}
.faults li::before{content:"";position:absolute;left:14px;top:18px;width:8px;height:8px;
  border-radius:50%;background:var(--caution)}
.faults b{display:block;font-family:var(--data);font-size:12.5px;color:#fff}
.faults span{display:block;margin-top:5px;font-size:var(--fs-caption);color:var(--ink-3);
  line-height:1.45}
.faults figcaption{margin-top:16px}

/* ── Diff (daisyUI), ported: one image clipped over another ─────────── */
.diff{position:relative;aspect-ratio:21/8;max-width:none;width:100%;border-radius:12px;overflow:hidden;
  box-shadow:var(--e2);background:var(--s-sunk)}
.diff img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.diff__top{clip-path:inset(0 calc(100% - var(--pos)) 0 0)}
.diff__line{position:absolute;top:0;bottom:0;left:var(--pos);width:2px;margin-left:-1px;
  background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.4);pointer-events:none}
.diff__line::after{content:"";position:absolute;top:50%;left:50%;width:30px;height:30px;
  margin:-15px 0 0 -15px;border-radius:50%;background:var(--s-key);box-shadow:var(--e2);
  border:1px solid var(--rule-lit)}
.diff__k{position:absolute;top:12px;font-family:var(--data);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:#fff;padding:4px 8px;border-radius:6px;background:rgba(0,0,0,.55)}
.diff__k--l{left:12px} .diff__k--r{right:12px}
.diff__range{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:ew-resize}
.diff__range:focus-visible + .diff__line,.diff:focus-within .diff__line{background:var(--signal-text)}
.diff-fig figcaption{max-width:var(--measure)}
@media (max-width:700px){ .diff{aspect-ratio:4/3} }

/* ── the colophon: who wrote what, and how to reach them ────────────
   Three columns that do not pretend to be equal -- the author's column
   leads, the other two support it. On a phone they stack in that order. */
.colophon{display:grid;gap:clamp(22px,3vw,44px);
  grid-template-columns:1.15fr 1fr 1fr;align-items:start;
  padding-bottom:26px;border-bottom:1px solid var(--rule)}
.colophon__who p{margin:8px 0 0;font-size:var(--fs-caption);line-height:1.68;
  color:var(--ink-2);max-width:42ch}
.colophon__who strong{color:var(--ink);font-weight:600}
.colophon__links{font-family:var(--data);font-size:11px;letter-spacing:.02em;
  color:var(--ink-3)}
.colophon__links a{color:var(--signal-text);text-decoration:none;
  border-bottom:1px solid transparent;transition:border-color 160ms var(--ease)}
.colophon__links a:hover{border-bottom-color:var(--signal-text)}
.colophon__note{margin-top:22px;font-family:var(--data);font-size:10.5px;
  line-height:1.7;color:var(--ink-3);max-width:74ch}
@media (max-width:900px){.colophon{grid-template-columns:1fr}}

/* the depth readout is pressable: it dives to the hull and opens it */
.dock__depth{border:0;font:inherit;color:inherit;cursor:pointer;
  transition:color 160ms var(--ease),transform 160ms var(--ease)}
.dock__depth:hover b{color:var(--signal-text)}
.dock__depth:active{transform:translateY(1px)}
.dock__depth:focus-visible{outline:2px solid var(--signal);outline-offset:3px}

/* Three readings of one drawing -- what it buys, what it costs, and what it
   cannot say. They were stacked in a single measure-width column under a
   full-width figure, which left the right half of the section empty for three
   screens. Side by side they are also easier to weigh against each other,
   which is the point of having all three. */
.verdict{display:grid;gap:clamp(24px,2.6vw,46px);grid-template-columns:repeat(3,1fr);
  margin-top:52px;padding-top:30px;border-top:1px solid var(--rule)}
.verdict__col h3{margin:0 0 10px}
.verdict__col p{margin:0;max-width:52ch}
.verdict__col .plain{margin-top:12px}
@media (max-width:1100px){.verdict{grid-template-columns:1fr 1fr}}
@media (max-width:760px){.verdict{grid-template-columns:1fr}}
