/* ============================================================================
   MOKI — styles.css  (W1-T2)
   Owns: design tokens (§2, verbatim), reset, base layout grid for every §5
   section, colour application, typography rules.

   Does NOT own motion. Every keyframe block, transition rule, scroll-timeline
   rule and prefers-reduced-motion override lives in fx-motion.css — nothing in
   this file animates anything, which is what makes the §11 grep-audit meaningful.
   Surface treatments (radius, textures, plate styles) live in fx-surfaces.css;
   type utilities (.eyebrow, numeral discipline, .text-*) live in fx-type.css.
   ========================================================================= */

/* ----------------------------------------------------------------------------
   1. DESIGN TOKENS — copied verbatim from SITE-BUILD-SPEC.md §2.
   These values were chosen against black fur, a white chest blaze and pale
   blue-grey eyes. Do not re-derive them.
--------------------------------------------------------------------------- */
:root {
  /* ---- color: light register (default, ~90% of the page) ---- */
  --moki-paper:      #F4EFE4; /* page background; also = text color inside #stand's dark planes */
  --moki-blaze:      #F2ECDC; /* card/plate surface, one step off paper, sampled off the chest blaze */
  --moki-ink:        #15130F; /* primary text + rules on paper, sampled off the cat's own fur */
  --moki-rule:       #C7BDA6; /* hairlines, dividers, muted captions on paper */

  /* ---- color: dark register (SCOPED to #stand only, never elsewhere) ---- */
  --moki-void:       #100F13; /* #stand background — deliberately lighter/cooler than the fur's
                                  true ~#0A0A0C so the cutout silhouette never dissolves into it */
  --moki-void-raised:#18171D; /* #stand panel surface (exhibit stamp plate) */
  --moki-line-void:  rgba(243,239,230,0.12); /* hairlines inside #stand only */

  /* ---- color: the two accents, both registers, both scoped, never adjacent ---- */
  --moki-witness:    #9FB9C2; /* the ONE cool accent — sampled off the iris. Rules, focus rings,
                                  the live-pulse dot, the active nav tick, the eye-glint. Never a
                                  flat fill, never body text on paper (fails contrast at that
                                  weight) — marks and lines only. */
  --moki-ember:      #B14A22; /* the ONE warm accent — CTA fills, hover states, the fierce mark.
                                  Used at most twice per screen so it keeps its authority. */
  --moki-alert:      #B8544A; /* negative price delta ONLY, inside #market only. Never decorative. */

  /* HARD RULE, enforced by review not by CSS: --moki-witness and --moki-ember never appear in the
     same component adjacent to each other. Cool+warm at small sizes muddies into a purple-ish
     read; keep them in separate components or separated by paper/ink space. */

  /* ---- colors banned near the fur (foreground/trait/overlay use) ----
     navy, charcoal/slate grey (other than --moki-void itself, which is background-only), dark
     forest green, dark brown, plum/eggplant. Any of these on a trait or overlay placed directly
     over the cutout reads as a smudge, not a shape. Any inherently dark trait (e.g. the Netherite
     Voxel Helm, §7) ships with a mandatory 1px light contour — see §7 for the exact color. */

  /* ---- type scale: fluid, clamp(), 16px root ---- */
  --text-xs:  clamp(0.75rem,  0.72rem + 0.15vw, 0.8125rem); /* micro-labels, mono footnotes */
  --text-sm:  clamp(0.875rem,0.83rem  + 0.2vw,  0.9375rem); /* small body, mono data cells */
  --text-base:clamp(1rem,    0.95rem  + 0.25vw, 1.125rem);  /* running prose */
  --text-md:  clamp(1.125rem,1.05rem  + 0.4vw,  1.375rem);  /* lede paragraphs */
  --text-lg:  clamp(1.5rem,  1.3rem   + 1vw,    2rem);      /* eyebrows set large, small h3 */
  --text-xl:  clamp(2rem,    1.6rem   + 2vw,    3rem);      /* h2 section headings */
  --text-2xl: clamp(2.75rem, 2rem     + 3.75vw, 4.5rem);    /* big stat numerals, exhibit titles */
  --text-3xl: clamp(3.5rem,  2.4rem   + 5.5vw,  7rem);      /* the wordmark, hero-scale marks */

  /* ---- spacing: fixed steps for component-internal gaps, one fluid token for section rhythm ---- */
  --space-1: 0.25rem;  --space-2: 0.5rem;   --space-3: 0.75rem; --space-4: 1rem;
  --space-5: 1.5rem;   --space-6: 2rem;     --space-7: 3rem;    --space-8: 4rem;
  --space-9: 6rem;
  --space-section: clamp(4rem, 3rem + 5vw, 9rem); /* vertical padding between page sections */

  /* ---- radii: exactly one scale, matching the piper precedent ---- */
  --radius-lg: 16px; --radius-md: 10px; --radius-sm: 6px; --radius-full: 999px;

  /* ---- durations + the one shared ease ---- */
  --duration-press:  60ms;   /* button :active release, linear, not eased */
  --duration-fast:   150ms;  /* micro state changes (focus ring, hover) */
  --duration-wipe:   640ms;  /* the print-wipe / plate-turn rule-draw */
  --duration-settle: 900ms;  /* the plate-turn photo opacity+scale settle */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); /* the ONE eased curve on the entire site */

  /* ---- z-index, named not guessed ---- */
  --z-nav: 40; --z-frame-pin: 10; --z-stamp: 50; --z-dialog: 100;
}

/* Layout-only constants. Kept in a second :root block so the §2 token block
   above stays byte-for-byte verbatim. These are not design tokens — they are
   this file's own layout plumbing. */
:root {
  --page-max: 72rem;                          /* content column, ≈1152px at 16px root */
  --gutter: clamp(1.25rem, 4vw, 3rem);        /* page-edge inline padding */
  --nav-h: 3.5rem;                            /* sticky nav chrome height */

  /* The pinned cat's rendered height. One variable so the eye-band overlay
     (.stand__eyes) can scale/position itself off the same number — see the
     .stand__eyes math below. 70rem cap keeps the 1244px-tall source from ever
     being upscaled past ~1:1 on very tall screens. */
  --stand-cat-h: min(84vh, 70rem);
}
@supports (height: 1svh) {
  :root {
    /* svh, not vh: the pin holds through a long scroll on mobile, where the
       URL-bar collapse changes vh mid-scroll and would visibly resize the
       cat — svh is stable for the whole run. */
    --stand-cat-h: min(84svh, 70rem);
  }
}

/* ----------------------------------------------------------------------------
   2. FONTS — §3. Two families, four static instances, self-hosted, zero CDN.
--------------------------------------------------------------------------- */
@font-face {
  font-family: "Fraunces";
  font-weight: 900;
  font-style: normal;
  font-display: swap;
  src: url("/assets/fonts/Fraunces72pt-Black.woff2") format("woff2");
}
@font-face {
  font-family: "Fraunces";
  font-weight: 300;
  font-style: italic;
  font-display: swap;
  src: url("/assets/fonts/FrauncesLightItalic.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("/assets/fonts/PlexMono-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("/assets/fonts/PlexMono-Medium.woff2") format("woff2");
}

/* Metric-matched fallbacks (§3 step 4) so font-display:swap moves nothing.
   The percentages below are MEASURED, not guessed — computed with fontTools
   against the actual shipped woff2 files and the actual macOS system fonts:

     Fraunces72pt-Black : upm 2000, ascent 1956, descent 510, xAvgCharWidth 1126
     Georgia.ttf        : upm 2048, ascent 1878, descent 449, xAvgCharWidth  901
       size-adjust     = (1126/2000) / (901/2048)  = 127.97%
       ascent-override = (1956/2000) / 1.2797      =  76.42%
       descent-override= ( 510/2000) / 1.2797      =  19.93%

     PlexMono-Regular   : upm 1000, ascent 1025, descent 275, advance  600
     Menlo.ttc (Regular): upm 2048, ascent 1901, descent 483, advance 1233
       size-adjust     = (600/1000) / (1233/2048)  =  99.66%
       ascent-override = (1025/1000) / 0.9966      = 102.85%
       descent-override= ( 275/1000) / 0.9966      =  27.59%

   Fraunces Fallback is matched to the Black instance because that is the
   weight visible above the fold in #stand — the §11.4 wordmark-baseline
   check is the one this exists to pass. Tune size-adjust there if it fails;
   never remove swap. */
@font-face {
  font-family: "Fraunces Fallback";
  src: local("Georgia");
  size-adjust: 127.97%;
  ascent-override: 76.42%;
  descent-override: 19.93%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Plex Mono Fallback";
  src: local("Menlo");
  size-adjust: 99.66%;
  ascent-override: 102.85%;
  descent-override: 27.59%;
  line-gap-override: 0%;
}

/* ----------------------------------------------------------------------------
   3. RESET
--------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  /* overflow-x: clip, NOT hidden — measured piper finding (recon inventory):
     `hidden` on the root silently creates a scroll container and breaks
     position:sticky, which this page bets everything on (#stand pin, #nav,
     #archive stack). `clip` clips without creating a scroll container. */
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  background-color: var(--moki-paper);
  color: var(--moki-ink);
  font-family: Georgia, "Times New Roman", serif;
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, svg, canvas, video {
  display: block;
  max-width: 100%;
  height: auto; /* keeps the width/height-attribute aspect ratio when scaled down */
}

main { display: block; }

[hidden] { display: none; }

ol, ul {
  padding: 0;
}

a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-color: var(--moki-rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
a:hover { text-decoration-color: var(--moki-ember); }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* Focus is --moki-witness sitewide per the §2 token comment ("rules, focus
   rings ... marks and lines only"). Visible on both registers. */
:focus-visible {
  outline: 2px solid var(--moki-witness);
  outline-offset: 2px;
}

::selection {
  background-color: var(--moki-witness);
  color: var(--moki-ink);
}

/* ----------------------------------------------------------------------------
   4. BASE TYPOGRAPHY
   Running prose is intentionally the system serif stack: §3 ships exactly
   four font files and none of them is a prose instance (Fraunces Black and
   Light Italic are display-only, Plex Mono is for numbers/labels/captions/
   data cells only). Georgia is the permanent prose face, not a fallback.
--------------------------------------------------------------------------- */
h1, h2, h3 {
  font-family: "Fraunces", "Fraunces Fallback", Georgia, "Times New Roman", serif;
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-xl); margin-block-end: var(--space-5); }
h3 { font-size: var(--text-lg); margin-block-end: var(--space-4); }

p { max-width: 62ch; } /* prose measure guard; layout grids narrow it further */
p + p { margin-block-start: var(--space-4); }

/* Captions, labels and data cells are Plex Mono per §3. Numeral feature
   settings (tabular-nums, slashed zero) are fx-type.css's job — only the
   family assignment lives here. */
code, kbd, samp, figcaption, dt, time {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-sm);
}

strong { font-weight: 700; }

/* ----------------------------------------------------------------------------
   5. PAGE SHELL
   Paper-ground sections share one centered content column. #tape, #nav and
   #stand are full-bleed and are excluded on purpose. Selectors are the §5
   section ids — the one contract W1-T1's acceptance check guarantees.
--------------------------------------------------------------------------- */
#witness, #name, #generator, #toys, #market, #archive, #plates, #receipts, #verify {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-block: var(--space-section);
  padding-inline: var(--gutter);
}

/* ----------------------------------------------------------------------------
   5.1 #curtain — non-blocking corner stamp, fixed bottom-left.
   Mount/unmount and the wipe/fade are app.js + fx-motion.css. This file only
   places and colours it. Without JS the pre-paint script never runs, so the
   stamp would sit there forever — hide it entirely in that case (§11.2).
--------------------------------------------------------------------------- */
/* .visually-hidden was used in the markup from the first wave and DEFINED
   NOWHERE, in any of the five stylesheets. It only became obvious once
   live.js started writing real state into #market-status: the screen-reader
   announcement ("Live.", "Feed is stale.") was rendering as visible body copy
   under the market rail, which is both a layout bug and a small honesty
   problem, since a status meant for one audience was quietly addressing
   everyone. The clip-path recipe rather than display:none or visibility:
   hidden, because both of those remove the element from the accessibility
   tree, which would silence the live region this class exists to carry. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

html:not(.js) #curtain { display: none; }

#curtain {
  position: fixed;
  left: var(--space-5);
  bottom: var(--space-5);
  z-index: var(--z-stamp);
  pointer-events: none; /* never intercepts a tap; it is a stamp, not a control */
}
.curtain__stamp {
  display: inline-block;
  padding: var(--space-2) var(--space-3);
  background-color: var(--moki-paper);
  color: var(--moki-ink);
  border: 1px solid var(--moki-ember);
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: clamp(0.625rem, 0.58rem + 0.2vw, 0.75rem); /* §5.1: smaller than --text-xs on mobile */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ----------------------------------------------------------------------------
   5.2 #tape — case-file ticker. Track motion + edge mask are fx-motion.css;
   this is the static strip: one clipped row of mono facts.
--------------------------------------------------------------------------- */
#tape {
  overflow: hidden;
  border-block: 1px solid var(--moki-rule);
  padding-block: var(--space-2);
  background-color: var(--moki-paper);
}
.tape__track {
  display: flex;
  width: max-content; /* track sizes to content so a translateX marquee has room to run */
}
.tape__group {
  display: flex;
  gap: var(--space-7);
  padding-inline: calc(var(--space-7) / 2); /* half-gap each side = seamless join once app.js clones the group */
  white-space: nowrap;
}
.tape__group span {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--moki-ink);
}

/* ----------------------------------------------------------------------------
   5.3 #nav — sticky dossier nav. The scroll fill rail is fx-motion.css's;
   the drawer swap is app.js + fx-motion.css. Chrome and layout live here.
--------------------------------------------------------------------------- */
#nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--nav-h);
  padding-inline: var(--gutter);
  /* §5.3: the one blur on the site — chrome over content, not a printed
     surface. Static, never animated. */
  background-color: color-mix(in srgb, var(--moki-paper) 88%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom: 1px solid var(--moki-rule);
}
@supports not (background-color: color-mix(in srgb, red 50%, transparent)) {
  #nav { background-color: var(--moki-paper); } /* solid fallback beats a transparent nav */
}

.nav__mark {
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* tap target */
  text-decoration: none;
}

.nav__rail {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  margin-inline-start: auto; /* rail sits right, mark sits left */
}
.nav__rail a {
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* §11.10 tap-target floor */
  padding-inline: var(--space-3);
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
}
.nav__rail a:hover { color: var(--moki-ember); }

.nav__toggle {
  display: none; /* mobile only, see media query at the bottom */
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-3);
  margin-inline-start: auto;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ----------------------------------------------------------------------------
   5.4 #stand — THE STANDING FRAME. The dark register lives here and ONLY
   here (§1 resolution); every other section stays on paper. The pin is
   layout (native position:sticky), so it lives in this file; the plane
   parallax, eye-glint step and exhibit-stamp wipe are all fx-motion.css.
--------------------------------------------------------------------------- */
#stand {
  position: relative;
  background-color: var(--moki-void);
  color: var(--moki-paper); /* the same cream is "the ink" on this side of the arc (§2) */
}

.stand__pin {
  position: sticky;
  top: 0;
  z-index: var(--z-frame-pin);
  height: 100vh;
  display: grid;
  place-items: center; /* centers the cat with zero transforms — nothing for the
                          reduced-motion fallback to inherit wrongly (§11.3) */
  overflow: clip;      /* planes overshoot the viewport during parallax; clip, not
                          hidden, for the same sticky-safety reason as the root */
}
@supports (height: 1svh) {
  .stand__pin { height: 100svh; }
}

/* Stacking inside the pin, back to front:
   far plane (1) → mid plane (2) → cat (3) → eye band (4) → near plane (5)
   → exhibit stamp (6). */
.stand__plane {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.stand__plane--far  { z-index: 1; }
.stand__plane--mid  { z-index: 2; color: var(--moki-line-void); } /* mid-plane SVG line art
                          inherits currentColor (§5.4); per-exhibit recolour is fx-motion's */
.stand__plane--near { z-index: 5; }

.stand__cat {
  z-index: 3;
  height: var(--stand-cat-h);
  width: auto;    /* source is 658x1244; height drives, width follows the ratio */
  max-width: none; /* opt out of the global img max-width; the pin clips overflow */
}

/* The eye band overlays the cat's own eyes exactly. It is positioned in the
   cat's coordinate space: --f converts source px (moki-full.png, 658x1244)
   to rendered px. The origin (168, 248) is MEASURED, not derived: an exact
   template match of assets/moki-eyes.png against assets/moki-full.png
   (mean abs diff 0.0 at that offset, PIL/numpy sweep, 2026-08-10). Note the
   §5.5 eye-line estimate of y≈165 is wrong about this asset — the real band
   sits at y 248-308. If W0-T3 ever regenerates the crop, re-run the match
   and update these two source-px numbers, nowhere else. */
.stand__eyes {
  --f: calc(var(--stand-cat-h) / 1244);
  position: absolute;
  z-index: 4;
  width: calc(272 * var(--f));
  height: calc(60 * var(--f));
  top: calc(50% - (var(--stand-cat-h) / 2) + (248 * var(--f)));
  left: calc(50% - (658 * var(--f) / 2) + (168 * var(--f)));
  max-width: none;
  pointer-events: none;
}

.stand__stamp {
  position: absolute;
  z-index: 6;
  left: var(--space-6);
  bottom: var(--space-6);
  max-width: none;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--moki-paper);
  background-color: var(--moki-void-raised);
  border: 1px solid var(--moki-line-void);
  padding: var(--space-2) var(--space-4);
}

/* Five spacer blocks drive the scroll distance: 5 x 84vh = 420vh desktop
   (§5.4). The pin itself contributes the first viewport-height of travel. */
.stand__scroller > * { height: 84vh; }

/* ----------------------------------------------------------------------------
   5.5 #witness — the eyes. Deep negative space: the crop takes ~40% width
   and overlaps the copy column's edge via a shared grid track — never a
   centered two-up block (§5.5). minmax(0,1fr) everywhere: a grid item's
   default min-width:auto refuses to shrink below content width (measured
   piper bug).
--------------------------------------------------------------------------- */
#witness {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--space-5);
  align-items: center;
}
.witness__crop {
  grid-column: 1 / 7;  /* ends at line 7... */
  grid-row: 1;
}
.witness__crop img { width: 100%; }
.witness__copy {
  grid-column: 6 / 13; /* ...starts at line 6 — column 6 is the overlap zone */
  grid-row: 1;
  /* Text clears the overlapping photo edge: column 6 is 1/7 of this box's
     width, plus one column gap of breathing room. */
  padding-inline-start: calc(100% / 7 + var(--space-5));
}

/* ----------------------------------------------------------------------------
   5.6 #name — honest etymology. Same negative-space discipline: the glyph
   pair is its own left-hand mass, disclosure copy sits right, unequal
   columns (§5.6). Glyphs render at full ink weight immediately — the
   kinetic weight treatment was killed in §1 and must not come back.
--------------------------------------------------------------------------- */
#name {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: var(--space-7);
  align-items: start;
}
#name .eyebrow { grid-column: 1 / -1; } /* layout placement only; its type
                          treatment belongs to fx-type.css */
#name h2 {
  grid-column: 1;
  /* Row span is a placement hack with a reason: the disclosure paragraph
     count is W5-T1's call (spec names at least two), so the heading claims
     enough rows for any sane count and every following <p> auto-places into
     column 2 beside it. */
  grid-row: 2 / span 8;
  font-size: var(--text-3xl);
  margin-block-end: 0;
}
#name p:not(.eyebrow) {
  grid-column: 2;
}

/* ----------------------------------------------------------------------------
   5.7 #generator + 5.8 #toys — in-flow sections. Their internals belong to
   pfp.js/game.js markup plus the fx layers; this file provides the shells
   (content column above) and nothing speculative.
--------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------------
   5.9 #market — the gate. Closed state is plain words, zero digits, zero
   skeletons (§5.9/§8). live.js flips data-state; state styling that needs
   colour lives here only when live.js ships markup for it.
--------------------------------------------------------------------------- */
.market__note { max-width: 58ch; }

/* ----------------------------------------------------------------------------
   5.10 #archive — sticky-stack dossier. Cards share one top offset so they
   deal on top of each other; --i (set inline by W1-T1) is consumed by
   fx-motion.css for the fan/recede. Card surface texture is fx-surfaces.css;
   the opaque background lives here because the deal mechanic is unreadable
   through a transparent card.
--------------------------------------------------------------------------- */
.archive__stack {
  display: grid;
  gap: var(--space-6);
}
.archive__card {
  position: sticky;
  top: calc(var(--nav-h) + var(--space-6));
  min-height: 55vh;
  padding: var(--space-6);
  background-color: var(--moki-blaze);
  border: 1px solid var(--moki-rule);
}

/* ----------------------------------------------------------------------------
   5.11 #receipts — honesty ledger. A ruled <dl>: mono terms, prose answers,
   one hairline per row.
--------------------------------------------------------------------------- */
.receipts__list > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: var(--space-5);
  padding-block: var(--space-4);
  border-top: 1px solid var(--moki-rule);
}
.receipts__list > div:last-child { border-bottom: 1px solid var(--moki-rule); }
.receipts__list dt {
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.receipts__list dd { margin: 0; }

/* ----------------------------------------------------------------------------
   5.12 #verify — ruled reference list, never a card grid (piper pattern).
   Markup detail is W1-T1's; these element rules keep it honest either way:
   list entries ruled, "what this does NOT tell you" sub-lines muted via
   --moki-rule, never an alarm colour. Gated links render disabled with no
   href — style the disabled look off the attribute state, not a class.
--------------------------------------------------------------------------- */
#verify ul, #verify ol { list-style: none; }
#verify li {
  padding-block: var(--space-4);
  border-top: 1px solid var(--moki-rule);
}
#verify li:last-child { border-bottom: 1px solid var(--moki-rule); }
#verify small {
  display: block;
  margin-block-start: var(--space-1);
  color: color-mix(in srgb, var(--moki-ink) 55%, var(--moki-paper));
  font-size: var(--text-sm);
}
#verify a:not([href]) {
  text-decoration-line: none;
  color: color-mix(in srgb, var(--moki-ink) 45%, var(--moki-paper));
  cursor: not-allowed;
}

/* ----------------------------------------------------------------------------
   6. RESPONSIVE
   One breakpoint does the structural work; §11.10 sweeps the rest.
   Reduced-motion restructuring (pin collapse etc.) is fx-motion.css's per
   the §4 ownership table — zero prefers-reduced-motion blocks here.
--------------------------------------------------------------------------- */
@media (max-width: 767px) {
  /* nav: rail collapses behind the drawer toggle (drawer itself is
     app.js/fx territory) */
  .nav__rail { display: none; }
  .nav__toggle { display: inline-flex; }

  /* stand: 5 x 56vh = 280vh scroll distance (§5.4 mobile), and the mid
     plane drops so only two planes paint on small GPUs (§11.10 checks
     exactly this) */
  .stand__scroller > * { height: 56vh; }
  .stand__plane--mid { display: none; }

  /* witness: crop stacks above copy, overlap released */
  .witness__crop { grid-column: 1 / -1; grid-row: 1; }
  .witness__copy {
    grid-column: 1 / -1;
    grid-row: 2;
    padding-inline-start: 0;
    padding-block-start: var(--space-5);
  }

  /* name: glyph mass stacks above disclosure */
  #name { grid-template-columns: minmax(0, 1fr); }
  #name h2 { grid-row: auto; margin-block-end: var(--space-5); }
  #name p:not(.eyebrow) { grid-column: 1; }

  /* receipts: term above answer */
  .receipts__list > div {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-1);
  }

  /* archive cards read shorter on small screens (§5.10) */
  .archive__card { min-height: 45vh; padding: var(--space-5); }
}
