/* Hallmark · J0 — components. The system is in tokens.css; no raw colour, no raw
 * font-family here. check.py fails the build if that slips.
 */

/* ===========================================================================
   1 · Base
   =========================================================================== */

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

/* clip, never hidden: hidden makes a scroll container and kills position: sticky on
   every descendant, which is how a contents rail stops sticking for no findable reason. */
html, body { margin: 0; overflow-x: clip; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--color-paper);
  color: var(--color-ink-2);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Headings are monospace — the same family the evidence is in. On this site that is an
   argument rather than a mood: the hero is a diff, and a diff only reads if the two
   lines align character for character. */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-style: normal;
  letter-spacing: var(--tracking-display);
  line-height: var(--lh-tight);
  color: var(--color-ink);
  overflow-wrap: anywhere;
  min-width: 0;
}
h1 { font-size: var(--text-section); }
h2 { font-size: var(--text-section); }
h3 { font-size: var(--text-lg); letter-spacing: -0.03em; }

h4 { margin: 0; font-family: var(--font-body); font-weight: 600; font-size: var(--text-base); color: var(--color-ink); }

p { margin: 0 0 var(--space-md); max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-color: var(--color-rule-strong);
  text-underline-offset: 0.25em;
  transition: text-decoration-color var(--dur-short) var(--ease-out);
}
a:hover { text-decoration-color: var(--color-ink); }

/* Instantly. A ring that fades in leaves a keyboard user with no indicator for the
   first 200ms, which is the entire point of the ring. */
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }

code, kbd, samp { font-family: var(--font-mono); font-size: 0.92em; color: var(--color-ink); }
b, strong { font-weight: 600; color: var(--color-ink); }
em { font-style: italic; }       /* body copy only — never a heading */
img, svg { max-width: 100%; height: auto; display: block; }

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

.skip-link {
  position: absolute;
  inset-block-start: var(--space-xs);
  inset-inline-start: var(--space-xs);
  z-index: var(--z-toast);
  padding: var(--space-xs) var(--space-md);
  background: var(--color-ink);
  color: var(--color-paper);
  font-family: var(--font-mono);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-250%);
}
.skip-link:focus { transform: none; }

/* ===========================================================================
   2 · Shell and rhythm
   =========================================================================== */

.shell { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--gutter); }

section { padding-block: var(--space-2xl); }
section.tight { padding-block: var(--space-xl); }

/* The landing page divides with tape — a real exchange run as a rule. The inner pages
   have no tape to spend, so they divide with a hairline. */
section.ruled { border-block-start: var(--rule-hair) solid var(--color-rule); }

/* The hero owns its own vertical rhythm through .hero__in. */
.hero { padding-block: 0; }
@media (min-width: 60rem) {
  section { padding-block: var(--space-3xl); }
  section.tight { padding-block: var(--space-xl); }
}

.lead { font-size: var(--text-lead); line-height: var(--lh-snug); color: var(--color-ink-2); max-width: 50ch; }
.small { font-size: var(--text-sm); }
.muted { color: var(--color-muted); }
.tnum  { font-variant-numeric: tabular-nums; }
.measure { max-width: var(--measure); }
.mt-m { margin-block-start: var(--space-md); }
.mt-l { margin-block-start: var(--space-xl); }

.head { display: grid; gap: var(--space-md); margin-block-end: var(--space-xl); }
.head p { color: var(--color-ink-2); }

/* The tape: a real exchange, run as a rule between sections. It is the product's own
   output used as the page's divider, so the furniture carries information instead of
   decorating the gap. */
.tape {
  /* It is a <p>, so it inherited the reading measure and wrapped at 510px. A record is
     not prose and does not want one. */
  max-width: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-xl);
  padding-block: var(--space-sm);
  border-block: var(--rule-hair) solid var(--color-rule);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-faint);
}
.tape b { color: var(--color-muted); font-weight: 500; }
.tape .sig { color: var(--color-signal); }

/* ===========================================================================
   3 · Nav — a status bar, the shape the application's own chrome has
   =========================================================================== */

.bar {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-sticky);
  background: var(--color-paper);
  border-block-end: var(--rule-hair) solid var(--color-rule);
}
.bar__in { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); min-height: var(--nav-h); }

.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-xs);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-lg);
  letter-spacing: -0.04em;
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark:hover { color: var(--color-ink-2); }
.tag {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--text-2xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-faint);
}

.bar__nav { display: flex; align-items: center; gap: var(--space-md); }
.bar__links { display: none; gap: var(--space-lg); list-style: none; margin: 0; padding: 0; }
.bar__links a,
.nav-menu__sheet a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--color-muted);
  text-decoration: none;
  white-space: nowrap;
}
.bar__links a:hover, .nav-menu__sheet a:hover { color: var(--color-ink); }
.bar__links a[aria-current="page"] { color: var(--color-ink); }
@media (min-width: 58rem) { .bar__links { display: flex; } }

.nav-menu { position: relative; }
.nav-menu > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center;
  min-height: 44px; padding-inline: var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--color-ink);
  border: var(--rule-hair) solid var(--color-rule-strong);
  white-space: nowrap;
}
.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu[open] > summary { border-color: var(--color-ink); color: var(--color-ink); }
.nav-menu__sheet {
  position: absolute;
  inset-block-start: calc(100% + var(--space-xs));
  inset-inline-end: 0;
  min-width: 12rem;
  display: grid;
  padding: var(--space-xs) var(--space-md);
  background: var(--color-paper-2);
  border: var(--rule-hair) solid var(--color-rule-strong);
  z-index: var(--z-dropdown);
}
@media (min-width: 58rem) { .nav-menu { display: none; } }

/* ===========================================================================
   4 · Controls
   =========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
  min-height: 46px; padding-inline: var(--space-lg);
  border: var(--rule-bar) solid transparent; border-radius: var(--radius);
  background: none;
  font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--color-ink); text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background-color var(--dur-short) var(--ease-out),
              border-color var(--dur-short) var(--ease-out),
              color var(--dur-short) var(--ease-out),
              transform var(--dur-micro) var(--ease-out);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--color-ink); border-color: var(--color-ink); color: var(--color-paper); }
.btn--primary:hover { background: var(--color-ink-2); border-color: var(--color-ink-2); color: var(--color-paper); }
.btn--secondary { border-color: var(--color-rule-strong); color: var(--color-ink); }
.btn--secondary:hover { border-color: var(--color-ink); }
.btn--sm { min-height: 40px; padding-inline: var(--space-md); font-size: var(--text-xs); }

.actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-block-start: var(--space-lg); }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.4em;
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--color-ink); text-decoration: none; white-space: nowrap;
  border-block-end: var(--rule-bar) solid var(--color-rule);
}
.link-arrow:hover { border-block-end-color: var(--color-ink); }

/* ===========================================================================
   5 · The hero — the page's one idea, and it is a diff
   =========================================================================== */

.hero__in { container-type: inline-size; padding-block: var(--space-2xl) var(--space-xl); }
@media (min-width: 60rem) { .hero__in { padding-block: var(--space-3xl) var(--space-2xl); } }

/* Sized from the string, which only a monospace allows. The two lines are 19 characters;
   Plex Mono advances 0.6em and the display tracking pulls back 0.045em, so each line is
   19 x 0.555 = 10.5em and 100/10.5 = 9.5cqi fills the column. 9.2 leaves a hair of slack
   for the trailing tracking. */
.diff {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.125rem, 9.2cqi, 6.5rem);
  letter-spacing: var(--tracking-display);
  line-height: 1.12;
  color: var(--color-ink);
  margin: 0;
}
.diff__line { display: block; white-space: pre; }

/* The request the two lines are about. Small, because it is the context rather than the
   claim — the claim is that the second line came back 200. */
.diff__req {
  display: block;
  margin-block-end: var(--space-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* The second line is the first line with one token replaced. Marking it is the whole
   argument: nothing else changed, and that is the bug.

   It is a rule under the phrase, not a highlight behind it. A filled block is fine over
   a word at body size and becomes a 630x130px slab at display size — which is the same
   "the signal must never fill a surface" rule this file states at the top, broken by
   scale rather than by intent. Ruled, it reads as a proofreader's mark and matches the
   way a verdict is marked. */
.diff__mark {
  color: var(--color-ink);
  /* No padding under it: padding on an inline box pushes the border outside the line
     box, and at this size that dropped an 8px rule straight through the line below. */
  border-block-end: 0.07em solid var(--color-signal);
  box-decoration-break: clone;
}
.diff__note {
  display: block;
  margin-block-start: var(--space-lg);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-signal);
}

/* The line under the one button. It says what you actually get, at the point where
   somebody is deciding whether to click — not two pages later. */
.cta-note {
  margin-block-start: var(--space-sm);
  max-width: 52ch;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 1.6;
  color: var(--color-muted);
}

.hero__sub { margin-block-start: var(--space-lg); max-width: 56ch; font-size: var(--text-lead); line-height: var(--lh-snug); color: var(--color-ink-2); }

.facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg);
  margin-block-start: var(--space-xl);
  padding-block-start: var(--space-lg);
  border-block-start: var(--rule-hair) solid var(--color-rule);
}
@media (min-width: 64rem) { .facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.facts div { display: grid; gap: var(--space-2xs); }
.facts b {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-xl);
  letter-spacing: -0.04em; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--color-ink);
}
.facts span { font-size: var(--text-xs); color: var(--color-muted); line-height: 1.45; }

/* ===========================================================================
   6 · The replay — three moves, each with the record it produced
   =========================================================================== */

.moves { display: grid; gap: var(--space-xl); margin: 0; padding: 0; list-style: none; counter-reset: move; }
@media (min-width: 64rem) { .moves { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); } }
.moves > li { counter-increment: move; display: grid; gap: var(--space-sm); align-content: start; padding-block-start: var(--space-md); border-block-start: var(--rule-bar) solid var(--color-rule-strong); }
.moves__n { font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-muted); }
.moves p { color: var(--color-ink-2); font-size: var(--text-sm); }

/* The gate, as two columns that disagree — the shape the rest of the page uses. */
.gate { display: grid; gap: var(--space-lg); margin: var(--space-lg) 0 0; padding: 0; list-style: none; }
@media (min-width: 48rem) { .gate { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xl); } }
.gate > li { display: grid; gap: var(--space-xs); align-content: start; padding-block-start: var(--space-sm); border-block-start: var(--rule-hair) solid var(--color-rule); }
.gate__k { font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-muted); }
.gate__k--no { color: var(--color-signal); }
.gate p { font-size: var(--text-sm); color: var(--color-ink-2); }

/* ===========================================================================
   7 · The refusals
   =========================================================================== */

.creed { list-style: none; margin: 0; padding: 0; counter-reset: creed; }
.creed > li {
  counter-increment: creed;
  display: grid; gap: var(--space-xs);
  padding-block: var(--space-lg);
  border-block-start: var(--rule-hair) solid var(--color-rule);
}
.creed > li:first-child { border-block-start: 0; }
.creed__n { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.1em; color: var(--color-faint); }
.creed h3 { color: var(--color-ink); }
.creed p { color: var(--color-ink-2); font-size: var(--text-sm); max-width: 60ch; }
@media (min-width: 58rem) {
  .creed > li { grid-template-columns: 3.5rem minmax(0, 1fr) minmax(0, 1.15fr); align-items: baseline; gap: var(--space-lg); padding-block: var(--space-xl); }
}

/* ===========================================================================
   8 · Evidence
   =========================================================================== */

.evidence {
  font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.75;
  font-variant-numeric: tabular-nums;
  color: var(--color-ink-2);
  background: var(--color-paper-2);
  border: var(--rule-hair) solid var(--color-rule);
  padding: var(--space-md);
  overflow-x: auto;
}
@media (min-width: 40rem) { .evidence { font-size: var(--text-sm); padding: var(--space-lg); } }
.evidence__head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-xs) var(--space-md);
  padding-block-end: var(--space-sm); margin-block-end: var(--space-sm);
  border-block-end: var(--rule-hair) solid var(--color-rule);
  color: var(--color-faint); font-size: var(--text-2xs);
  letter-spacing: 0.1em; text-transform: uppercase;
}
.evidence b { color: var(--color-ink); font-weight: 500; }
.evidence .dim { color: var(--color-faint); }
.evidence .key { color: var(--color-muted); }
.ev-line { display: block; white-space: pre; }
.ev-gap  { display: block; height: var(--space-sm); }

.ev-row { display: grid; gap: var(--space-2xs); padding-block: var(--space-sm); border-block-start: var(--rule-hair) solid var(--color-rule); }
.ev-row:first-of-type { border-block-start: 0; }
.ev-row__ep { color: var(--color-ink); word-break: break-all; }
.ev-row__as { color: var(--color-faint); font-size: var(--text-2xs); }
@media (min-width: 40rem) {
  .ev-row { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--space-sm) var(--space-md); }
  .ev-row__as { grid-column: 1; }
  .ev-row .verdict { grid-row: 1 / span 2; grid-column: 2; align-self: center; }
}

.verdict {
  justify-self: start;
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap;
  padding-block-end: 0.1em;
  border: 0;
  border-block-end: var(--rule-bar) solid currentColor;
}
.verdict--through    { color: var(--color-signal); }
.verdict--held       { color: var(--color-held); }
.verdict--scoped     { color: var(--color-scoped); }
.verdict--unmeasured { color: var(--color-unmeasured); border-block-end-style: dashed; }
.hit { color: var(--color-signal); }
.ok  { color: var(--color-muted); }

/* ===========================================================================
   9 · Spec sheets
   =========================================================================== */

.spec { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: tabular-nums; text-align: start; }
.spec caption { text-align: start; color: var(--color-muted); font-size: var(--text-xs); padding-block-end: var(--space-sm); }
.spec th, .spec td { padding: var(--space-sm) var(--space-md) var(--space-sm) 0; border-block-start: var(--rule-hair) solid var(--color-rule); vertical-align: baseline; text-align: start; }
.spec thead th {
  border-block-start: 0; border-block-end: var(--rule-bar) solid var(--color-rule-strong);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-faint);
  padding-block-end: var(--space-xs);
}
.spec tbody th { font-family: var(--font-mono); font-weight: 600; color: var(--color-ink); white-space: nowrap; }
.spec td { color: var(--color-ink-2); }
.spec td:last-child, .spec th:last-child { padding-inline-end: 0; }
.spec .state { font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap; }
.spec .state--built   { color: var(--color-ink); }
.spec .state--partial { color: var(--color-scoped); }
.spec .state--no      { color: var(--color-unmeasured); }

@media (max-width: 47.999rem) {
  .spec, .spec tbody, .spec tr, .spec td, .spec th { display: block; }
  .spec thead { display: none; }
  .spec tr { padding-block: var(--space-md); border-block-start: var(--rule-hair) solid var(--color-rule); }
  .spec th, .spec td { border: 0; padding: 0 0 var(--space-2xs); }
  .spec td[data-label]::before {
    content: attr(data-label) " ";
    font-family: var(--font-mono); font-size: var(--text-2xs);
    letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-faint);
  }
}

/* ===========================================================================
   10 · Split, steps, definitions, screenshots
   =========================================================================== */

.split { display: grid; gap: var(--space-xl); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 64rem) {
  .split { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--space-2xl); }
  .split--flip > :first-child { order: 2; }
}
.split__say h2 { margin-block-end: var(--space-md); }
.split__say p { color: var(--color-ink-2); }

.steps { counter-reset: step; display: grid; gap: var(--space-lg); margin: 0; padding: 0; list-style: none; }
.steps > li { counter-increment: step; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-md); align-items: start; }
.steps > li::before { content: counter(step, decimal-leading-zero); font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--color-muted); }
.steps h3 { margin-block-end: var(--space-2xs); }

.cmd {
  display: block; font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.9;
  white-space: pre; overflow-x: auto;
  color: var(--color-ink-2); background: var(--color-paper-2);
  border: var(--rule-hair) solid var(--color-rule);
  padding: var(--space-md); margin-block: var(--space-sm) 0;
}
@media (min-width: 40rem) { .cmd { font-size: var(--text-sm); } }
.cmd .p { color: var(--color-faint); }
.cmd .c { color: var(--color-faint); }

.defs { display: grid; gap: var(--space-md); margin: var(--space-lg) 0 0; }
.defs > div { display: grid; gap: var(--space-2xs); padding-block-end: var(--space-md); border-block-end: var(--rule-hair) solid var(--color-rule); }
.defs > div:last-child { border-block-end: 0; padding-block-end: 0; }
.defs .term { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--color-ink); }
.defs .what { margin: 0; color: var(--color-ink-2); font-size: var(--text-sm); }
@media (min-width: 48rem) { .defs > div { grid-template-columns: minmax(0, 14rem) minmax(0, 1fr); gap: var(--space-lg); } }

/* Kept for when real captures land; there is no placeholder state any more. A dashed
   box printing its own filename is a note to self, and a visitor reads it as a site
   that is not finished — which is a worse impression than having no picture at all. */
.shot { margin: 0; display: grid; gap: var(--space-sm); }
.shot img { width: 100%; border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-2); }
.shot figcaption { font-size: var(--text-sm); color: var(--color-muted); }
.shot figcaption b { color: var(--color-ink-2); }

/* ===========================================================================
   11 · Footer
   =========================================================================== */

.bottom { border-block-start: var(--rule-hair) solid var(--color-rule); padding-block: var(--space-2xl) var(--space-xl); padding-block-end: max(var(--space-xl), env(safe-area-inset-bottom)); }
.foot-stmt {
  margin: 0 0 var(--space-2xl); max-width: 26ch;
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.375rem, 3.4vw, 2.4rem);
  letter-spacing: -0.045em; line-height: 1.12; color: var(--color-ink);
}
.foot-stmt .q { border-block-end: 0.09em solid var(--color-signal); }
.foot-meta { display: grid; gap: var(--space-lg); padding-block-start: var(--space-lg); border-block-start: var(--rule-hair) solid var(--color-rule); }
@media (min-width: 48rem) { .foot-meta { grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: var(--space-2xl); } }
.foot-meta p { font-size: var(--text-sm); color: var(--color-muted); max-width: 46ch; }
.foot-links { display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg); list-style: none; margin: 0; padding: 0; }
.foot-links a { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: 0.04em; color: var(--color-muted); text-decoration: none; white-space: nowrap; }
.foot-links a:hover { color: var(--color-ink); }

/* ===========================================================================
   12 · Docs layout
   =========================================================================== */

.doc-grid { display: grid; gap: var(--space-xl); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 64rem) {
  .doc-grid { grid-template-columns: minmax(0, 13rem) minmax(0, 1fr); gap: var(--space-2xl); align-items: start; }
  .toc { position: sticky; inset-block-start: calc(var(--nav-h) + var(--space-lg)); }
}
.toc { font-size: var(--text-sm); }
.toc h2 { font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-faint); margin-block-end: var(--space-sm); }
.toc ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-xs); }
.toc a { display: block; padding-inline-start: var(--space-sm); border-inline-start: var(--rule-bar) solid var(--color-rule); color: var(--color-muted); text-decoration: none; transition: color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out); }
.toc a:hover { color: var(--color-ink); }
.toc a[aria-current="true"] { color: var(--color-ink); border-inline-start-color: var(--color-ink); }

.prose > section { padding-block: 0 var(--space-2xl); border: 0; }
.prose h2 { margin-block-end: var(--space-md); scroll-margin-block-start: calc(var(--nav-h) + var(--space-lg)); }
.prose h3 { margin-block: var(--space-xl) var(--space-sm); scroll-margin-block-start: calc(var(--nav-h) + var(--space-lg)); }
.prose p { color: var(--color-ink-2); }
.prose ul { color: var(--color-ink-2); max-width: var(--measure); padding-inline-start: var(--space-lg); }
.prose li { margin-block-end: var(--space-xs); }
.prose .evidence, .prose .cmd, .prose .spec { margin-block: var(--space-lg); }

.plain { padding-block: var(--space-2xl) var(--space-xl); }
.plain h1 { max-width: 28ch; }

/* ===========================================================================
   13 · The opening — the 0 you start with is the o you end with
   =========================================================================== */

.intro {
  position: fixed; inset: 0; z-index: var(--z-intro);
  display: grid; place-content: center; gap: var(--space-lg);
  background: var(--color-paper);
  animation: intro-leave var(--dur-long) var(--ease-in) 2500ms forwards;
}
.intro.is-done { animation: intro-leave 320ms var(--ease-in) forwards; }
body.intro-up { overflow: hidden; }

/* The whole trick rests on the face being monospace. "ZER" is exactly three characters,
   so the O's journey is exactly 3ch minus the three characters' worth of tracking — an
   exact distance rather than a number tuned by eye until it looked right. The letters
   are laid out at their final positions from the first frame and only transform and
   opacity move, so nothing reflows while it plays. */
.intro-word {
  --ls: -0.04em;
  --gap: calc(3ch + 3 * var(--ls));
  display: flex;
  align-items: baseline;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.75rem, 13vw, 7rem);
  letter-spacing: var(--ls);
  line-height: 1;
  color: var(--color-ink);
  animation: intro-in 620ms var(--ease-out) 150ms backwards,
             intro-close 900ms var(--ease-in-out) 800ms backwards;
}

/* ZER is not faded in — it is pulled out behind the travelling O. Each letter sits in
   its own one-character box with overflow hidden and starts shifted a full box to the
   left, so it emerges from under the O exactly as the O clears that slot. Fading them
   in instead let the O cross letters that were already drawn, and the collision looked
   like a bug. This is transform only, like everything else here. */
.iw-mid { display: inline-flex; }
.iw-let { display: inline-block; overflow: hidden; }
.iw-let > span { display: inline-block; transform: translateX(-100%); animation: let-in 380ms var(--ease-out) forwards; }
.iw-let:nth-child(1) > span { animation-delay: 1040ms; }
.iw-let:nth-child(2) > span { animation-delay: 1340ms; }
.iw-let:nth-child(3) > span { animation-delay: 1640ms; }

/* The O is one character wide and holds both glyphs; it slides right into place, and
   only at the end does the digit become the letter — in the same cell, so the shape
   settles rather than swaps. */
.iw-o { position: relative; display: inline-block; animation: o-travel 900ms var(--ease-in-out) 800ms backwards; }
.iw-o > span { display: inline-block; }
.iw-0 { position: absolute; inset-block-start: 0; inset-inline-start: 0; animation: fade-out 320ms var(--ease-in-out) 1760ms forwards; }
.iw-O { opacity: 0; animation: fade-in 320ms var(--ease-in-out) 1800ms forwards; }

.intro-rule {
  display: block; justify-self: center;
  width: clamp(4rem, 18vw, 10rem); height: var(--rule-bar);
  background: var(--color-ink);
  transform: scaleX(0);
  animation: bar-in 600ms var(--ease-out) 1820ms forwards;
}

.intro-skip {
  position: fixed; inset-block-end: var(--space-xl); inset-inline-end: var(--space-xl);
  min-height: 44px; padding-inline: var(--space-md);
  background: none; border: var(--rule-hair) solid var(--color-rule-strong); border-radius: var(--radius);
  color: var(--color-muted);
  font-family: var(--font-mono); font-size: var(--text-xs);
  letter-spacing: 0.1em; text-transform: uppercase; cursor: pointer;
}
.intro-skip:hover { color: var(--color-ink); border-color: var(--color-ink-2); }

@keyframes intro-in    { from { opacity: 0; transform: translate3d(calc(var(--gap) / 2), 10px, 0); }
                         to   { opacity: 1; transform: translate3d(calc(var(--gap) / 2), 0, 0); } }
@keyframes intro-close { from { transform: translate3d(calc(var(--gap) / 2), 0, 0); }
                         to   { transform: translate3d(0, 0, 0); } }
@keyframes o-travel    { from { transform: translate3d(calc(var(--gap) * -1), 0, 0); }
                         to   { transform: translate3d(0, 0, 0); } }
@keyframes let-in      { to { transform: translateX(0); } }
@keyframes bar-in      { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes intro-leave { to { opacity: 0; visibility: hidden; } }
@keyframes fade-out    { to { opacity: 0; } }
@keyframes fade-in     { to { opacity: 1; } }

/* ===========================================================================
   14 · Motion
   =========================================================================== */

.rise { animation: rise var(--dur-long) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 70ms); }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* .reveal starts invisible, so the class that hides it is only added by site.js — if
   the script never runs, every section is simply there. */
.js .reveal { opacity: 0; transform: translateY(12px); }
.js .reveal.seen { animation: rise var(--dur-long) var(--ease-out) forwards; animation-delay: calc(var(--i, 0) * 60ms); }

.d1 { --i: 1; } .d2 { --i: 2; } .d3 { --i: 3; } .d4 { --i: 4; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 150ms !important; animation-delay: 0ms !important; transition-duration: 150ms !important; }
  .rise, .js .reveal.seen, .intro-word { animation-name: fade-only; }
  .iw-let > span { animation: none; transform: none; }
  .iw-o { animation: fade-only 150ms linear forwards; }
  .intro { animation: intro-leave 150ms linear 900ms forwards; }
  .intro-rule { animation: fade-only 150ms linear forwards; transform: none; }
  .iw-0 { animation: fade-out 150ms linear 400ms forwards; }
  .iw-O { animation: fade-in 150ms linear 440ms forwards; }
  @keyframes fade-only { from { opacity: 0; } to { opacity: 1; transform: none; } }
}

@media (pointer: coarse) { .btn { min-height: 48px; } }
