/* ==========================================================================
   MIDNIGHT — design system v2  (binding spec: MIDNIGHT-VISUAL-PLAN.md)
   ==========================================================================
   Art direction: instrument panel. A measurement device, not a brochure.
   Every element carries information; anything decorative is deleted.

   Runtime: system font stack only. No webfont, no CDN, no remote asset —
   the microsite renders identically offline.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* --- neutral ramp (background) ---------------------------------------- */
  --ground:  #eceded;   /* overridden below; palette declared in one place */
  --ground:  #0a0c0d;   /* chassis */
  --face:    #101415;   /* panel face */
  --face-2:  #161b1c;   /* raised face */
  --face-3:  #1c2324;   /* selected face */

  --ink:   #e6ebeb;     /* measured value / primary readout */
  --ink-2: #9aa5a7;     /* engraved label */
  --ink-3: #838e90;     /* tick mark / tertiary — lightened to clear AA (was #6b7679) */

  --rule:   rgba(230, 235, 235, 0.10);
  --rule-2: rgba(230, 235, 235, 0.18);
  --rule-3: rgba(230, 235, 235, 0.30);

  /* --- colour roles ------------------------------------------------------
     ONE accent for interaction and focus. Everything else is neutral.
     Red and green are RESERVED status colours and only ever appear where the
     state genuinely is that: green = verified closed, red = refused/fault.
     Green never appears on an open gate. Amber marks state that is neither
     closed nor refused (open, pending, attention).
     --------------------------------------------------------------------- */
  --accent: #5ec8d8;
  --accent-wash: rgba(94, 200, 216, 0.12);
  --ok: #56b884;        /* reserved: genuinely closed */
  --ok-wash: rgba(86, 184, 132, 0.12);
  --warn: #cfa14a;      /* open / pending / attention */
  --warn-wash: rgba(207, 161, 74, 0.12);
  --fault: #dc7d68;     /* reserved: refused / fault — lightened for AA at 10.5px */
  --fault-wash: rgba(210, 112, 92, 0.12);

  /* --- type: at most two families. Mono carries everything measured. ----- */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --fs-micro: 10.5px;
  --fs-data: 12px;
  --fs-body: 13.5px;
  --fs-lead: 16px;
  --fs-h3: 19px;
  --fs-h2: 26px;

  /* --- grid and rhythm: 8px base, 12 columns, consistent vertical rhythm -- */
  --sheet: 1200px;
  --col: 72px;
  --gap: 24px;
  --u: 8px;

  /* --- motion: 120 / 240 / 400, ONE easing family ------------------------ */
  /* Layer 2 — one stroke hierarchy, used everywhere in the drawing. */
  --sw-fg: 2px;      /* the packet: the foreground object */
  --sw-struct: 1px;  /* plates, wall, envelope internals */
  --sw-tick: 0.5px;  /* engraved ticks and cell outlines */

  --t-1: 120ms;
  --t-2: 240ms;
  --t-3: 400ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

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

html { background: var(--ground); -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent); }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: 0; }
p { margin: 0; max-width: 72ch; }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
[hidden] { display: none !important; }

/* Instrument focus: a hard 1px accent outline, never a glow. */
:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }

/* ---------------------------------------------------------------- sheet ---- */

.sheet { max-width: var(--sheet); margin: 0 auto; padding: 0 var(--gap); }

/* Consistent vertical rhythm: every band opens on the same 8px multiple. */
.band { border-top: 1px solid var(--rule); padding: calc(var(--u) * 5) 0; }
.band:first-of-type { border-top: 0; }

/* A band header is a drawing-sheet row: index, title, note, rule. */
.band-head {
  display: grid;
  grid-template-columns: var(--col) minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--gap);
  align-items: baseline;
  margin-bottom: calc(var(--u) * 3);
}

.band-index { font-family: var(--mono); font-size: var(--fs-data); color: var(--accent); }
.band-head h2 { font-size: var(--fs-h2); }
.band-note { font-size: var(--fs-body); color: var(--ink-2); }

/* Every band states which artifact its numbers came from. */
.band-src {
  grid-column: 2 / -1;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-3);
  letter-spacing: 0.06em;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------- chassis ----- */

.chassis { border-bottom: 1px solid var(--rule); background: var(--face); }

.chassis-inner {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 2);
  min-height: calc(var(--u) * 7);
  padding: 0 var(--gap);
  max-width: var(--sheet);
  margin: 0 auto;
}

.mark { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mark svg { display: block; flex: 0 0 auto; }

.mark-text {
  font-family: var(--mono);
  font-size: var(--fs-data);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.mark-spec {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.chassis-actions { margin-left: auto; display: flex; align-items: center; gap: calc(var(--u) * 1.5); }

.control {
  border: 1px solid var(--rule-2);
  padding: 6px 10px;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: border-color var(--t-1) var(--ease), color var(--t-1) var(--ease),
              background-color var(--t-1) var(--ease);
}

.control:hover { border-color: var(--rule-3); color: var(--ink); background: var(--face-2); }

/* ---------------------------------------------------------------- hero ----- */

.hero {
  padding: calc(var(--u) * 7) 0 calc(var(--u) * 4);
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: calc(var(--u) * 5);
  align-items: end;
}

.eyebrow {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: calc(var(--u) * 2);
}

h1 { font-size: clamp(32px, 5vw, 54px); line-height: 1.06; letter-spacing: -0.025em; }

.lede { font-size: var(--fs-lead); color: var(--ink-2); max-width: 46ch; }

/* V1 — hero motif. No text inside; the form carries the idea. */
.motif { display: block; width: 100%; max-width: 560px; height: auto; margin-top: calc(var(--u) * 3); }

.motif .in { stroke: var(--rule-3); stroke-width: var(--sw-struct); fill: none; }
.motif .ap { stroke: var(--rule-2); stroke-width: var(--sw-struct); fill: none; }
.motif .out { stroke: var(--accent); stroke-width: var(--sw-fg); fill: none; }
.motif .pt { fill: var(--accent); }

/* A motif fade-in is information-bearing: it shows direction of travel,
   input → commitment. Reduced motion jumps straight to the end state. */
/* One reveal for the whole motif: the direction of travel is the information,
   so a single grouped animation carries it instead of eight separate ones. */
.motif-reveal { animation: motif-in var(--t-3) var(--ease) both; }
@keyframes motif-in { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }

/* --------------------------------------------------------------- tags ------ */

.tags { display: flex; flex-wrap: wrap; gap: var(--u); margin-top: calc(var(--u) * 3); }

.tag {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--rule-2);
  border-left-width: 3px;
  padding: 5px 9px;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  max-width: 100%;
}

.tag-note {
  white-space: normal;
  text-transform: none;
  letter-spacing: 0.01em;
  font-size: var(--fs-data);
  line-height: 1.5;
  color: var(--ink);
}

/* Status tags: colour is chosen from the state, never for decoration. */
.tag-ok { border-left-color: var(--ok); color: var(--ok); }
.tag-warn { border-left-color: var(--warn); color: var(--warn); }
.tag-fault { border-left-color: var(--fault); color: var(--fault); }
.tag-accent { border-left-color: var(--accent); color: var(--accent); }
.tag:not([class*='tag-']) { border-left-color: var(--rule-3); }

/* ------------------------------------------------------------ schematic ---- */

.frame { border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 2.5) var(--gap) calc(var(--u) * 2); }

/* V2 — flow diagram. Dashed = private, solid = public. */
.frame svg { display: block; width: 100%; height: auto; }

.frame-cap {
  margin-top: calc(var(--u) * 1.5);
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.node-box {
  fill: var(--face-2);
  stroke: var(--rule-2);
  stroke-width: var(--sw-struct);
  transition: stroke var(--t-1) var(--ease), fill var(--t-1) var(--ease);
}

.node { cursor: pointer; }
.node:hover .node-box { stroke: var(--rule-3); }

/* Activation state is carried by an accent stroke plus the moving marker. */
.node[aria-current="true"] .node-box { stroke: var(--accent); fill: var(--face-3); }
.node:focus .node-box, .node:focus-visible .node-box { stroke: var(--ink); stroke-width: var(--sw-fg); }

.node-id { fill: var(--accent); font-family: var(--mono); font-size: 11px; }
.node-label { fill: var(--ink); font-family: var(--sans); font-size: 12.5px; font-weight: 600; }
.node-sub { fill: var(--ink-3); font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; }

/* Private leg: dashed. Public leg: solid. Truth carried by line style. */
.leg { fill: none; stroke-width: var(--sw-struct); }
.leg-private { stroke: var(--rule-2); stroke-dasharray: 3 4; }
.leg-public { stroke: var(--rule-3); }
.leg.is-active.leg-private { stroke: var(--ink-2); stroke-dasharray: 3 4; }
.leg.is-active.leg-public { stroke: var(--accent); }

/* The flow marker travels with transform only — layout is never animated. */
.marker { fill: var(--accent); opacity: 0; }
.leg.is-active + .marker { opacity: 1; animation: travel var(--t-3) linear infinite; }
@keyframes travel { from { transform: translateX(0); } to { transform: translateX(24px); } }

.plane { fill: none; stroke: var(--rule); stroke-width: var(--sw-struct); }
.plane-label { fill: var(--ink-3); font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em; }

.boundary { stroke: var(--warn); stroke-width: var(--sw-struct); stroke-dasharray: 3 4; }
.boundary-label { fill: var(--warn); font-family: var(--mono); font-size: 10px; letter-spacing: 0.14em; }

.reject-box { fill: var(--fault-wash); stroke: rgba(210, 112, 92, 0.5); stroke-width: var(--sw-struct); }
.reject-label { fill: var(--fault); font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em; }

/* ---------------------------------------------------------------- steps ---- */

.steps { list-style: none; margin: calc(var(--u) * 3) 0 0; padding: 0; }

.step {
  display: grid;
  grid-template-columns: var(--col) minmax(0, 1fr);
  gap: calc(var(--u) * 2.5);
  padding: calc(var(--u) * 2.5) 0;
  border-top: 1px solid var(--rule);
  scroll-margin-top: calc(var(--u) * 3);
}

.step[data-active="true"] { background: var(--face); }
.step-index { font-family: var(--mono); font-size: var(--fs-data); color: var(--accent); }
.step h3 { font-size: var(--fs-h3); margin-bottom: 6px; }
.step p { color: var(--ink-2); margin-bottom: calc(var(--u) * 1.5); }

.fields { display: flex; flex-wrap: wrap; gap: 6px; }

/* Per-step visuals (V5, V6, V7) sit under their step. */
.step-view { margin-top: calc(var(--u) * 2); }
/* Field ids like authority.revoked_credential_commitments have no break
   opportunity at a dot, so they must be allowed to break anywhere: otherwise a
   40-character id overflows a narrow column and widens the whole page. */
.step-src {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-3);
  margin-top: var(--u);
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- chips ---- */

.pair dd, .slot .value, .stage-box .value, .axis-name, .risk-id, .legend-value { overflow-wrap: anywhere; }

.field {
  display: inline-flex;
  align-items: center;
  gap: var(--u);
  min-height: 30px;
  border: 1px solid var(--rule-2);
  padding: 5px var(--u);
  background: var(--face);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
  overflow-wrap: anywhere;
  transition: border-color var(--t-1) var(--ease), color var(--t-1) var(--ease),
              background-color var(--t-1) var(--ease);
}

.field:hover { border-color: var(--rule-3); color: var(--ink); }
.field[aria-pressed="true"] { background: var(--accent-wash); border-color: var(--accent); color: var(--ink); }
.field .tick { width: 6px; height: 6px; flex: 0 0 auto; background: currentColor; opacity: 0.55; }

/* ------------------------------------------------- V3 — privacy ratio ------ */

.ratio { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 300px); gap: calc(var(--u) * 4); align-items: start; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18px, 1fr));
  gap: 4px;
  border: 1px solid var(--rule);
  padding: var(--u);
  background: var(--face);
}

.cell {
  aspect-ratio: 1;
  border: 1px solid var(--rule-2);
  transition: transform var(--t-1) var(--ease), opacity var(--t-1) var(--ease);
}

.cell-private { background: var(--face-3); }
.cell-public { border-color: var(--accent); background: var(--accent-wash); }
.cell-conditional { border-color: var(--warn); background: var(--warn-wash); }

.legend { display: grid; gap: calc(var(--u) * 1.5); }

.legend-row {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: baseline;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 6px;
}

.legend-key { width: 12px; height: 12px; border: 1px solid var(--rule-2); }
.legend-label { font-size: var(--fs-data); color: var(--ink-2); }
.legend-value { font-family: var(--mono); font-size: var(--fs-body); color: var(--ink); }

/* --------------------------------------------------------- V4 explorer ----- */

.ledger { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.column { background: var(--face); padding: calc(var(--u) * 2); min-width: 0; }

.column-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--u) * 1.5);
  padding-bottom: var(--u);
  border-bottom: 1px solid var(--rule);
  margin-bottom: 6px;
}

.column-head h3 { font-size: var(--fs-h3); }
.column-count { font-family: var(--mono); font-size: var(--fs-data); color: var(--accent); }
.column-note { font-size: var(--fs-data); color: var(--ink-3); margin: 0 0 calc(var(--u) * 1.5); }
.column-list { display: flex; flex-direction: column; gap: 4px; }
.column-list .field { justify-content: space-between; width: 100%; }

.status { font-size: var(--fs-data); color: var(--ink-2); margin-bottom: calc(var(--u) * 2); }
.status.is-error { color: var(--fault); }

.readout {
  margin-top: calc(var(--u) * 2.5);
  border: 1px solid var(--rule-2);
  border-left: 3px solid var(--accent);
  background: var(--face);
  padding: calc(var(--u) * 2.5);
  min-width: 0;
  overflow-wrap: anywhere;
}

.readout h3 { font-family: var(--mono); font-size: 13px; font-weight: 500; margin: 10px 0 0; line-height: 1.5; }

.pairs { display: grid; gap: 10px; margin: calc(var(--u) * 2) 0 0; }

.pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: var(--u);
  align-items: baseline;
  border-top: 1px solid var(--rule);
  padding-top: var(--u);
}

.pair dt { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.pair dd { margin: 0; font-family: var(--mono); font-size: var(--fs-data); color: var(--ink); overflow-wrap: anywhere; }

/* --------------------------------------------- V5 — nullifier / replay ----- */

.stateway { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--u); align-items: center; }
.slot { border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 1.5); min-width: 0; }
.slot h4 { margin: 0 0 6px; font-size: var(--fs-data); font-family: var(--mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; }
.slot .value { font-family: var(--mono); font-size: var(--fs-data); color: var(--ink); overflow-wrap: anywhere; }
.slot[data-verdict="ok"] { border-left: 3px solid var(--ok); }
.slot[data-verdict="fault"] { border-left: 3px solid var(--fault); }
.slot[data-verdict="warn"] { border-left: 3px solid var(--warn); }
.arrow { font-family: var(--mono); color: var(--ink-3); }

/* ------------------------------------------------- V6 — status timeline ---- */
/* The axis is laid out in flow, not with absolutely-positioned labels: an
   absolute, nowrap label widened the page past a 320px viewport. Here every
   cell is a 1fr track, so a long role name wraps instead of pushing out. */
.timeline { border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 2.5); }

.axis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--rule-2);
  margin-top: calc(var(--u) * 3);
}

.axis-cell { position: relative; min-width: 0; padding: 0 var(--u) var(--u) 0; }

.axis-mark { position: absolute; top: -1px; left: 0; width: 1px; height: 9px; background: var(--rule-3); }

.axis-cell[data-role="revocation"] .axis-mark { background: var(--fault); }
.axis-cell[data-role="rotation"] .axis-mark { background: var(--accent); }
.axis-cell[data-role="recovery"] .axis-mark { background: var(--warn); }
.axis-cell[data-role="revision"] .axis-mark { background: var(--ink-3); }

.axis-name {
  display: block;
  padding-top: calc(var(--u) * 1.75);
  font-family: var(--mono);
  font-size: var(--fs-micro);
  color: var(--ink-2);
  overflow-wrap: anywhere;
}

.monotonic { border-top: 1px solid var(--rule); padding-top: var(--u); margin-top: calc(var(--u) * 3); font-family: var(--mono); font-size: var(--fs-micro); color: var(--ink-3); overflow-wrap: anywhere; }

/* ------------------------------------------------ V7 — fail-closed --------- */

.failclosed { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: calc(var(--u) * 2); }
.stage-box { border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 1.5); min-width: 0; }
.stage-box h4 { margin: 0 0 6px; font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; }
.stage-box .value { font-family: var(--mono); font-size: var(--fs-data); color: var(--ink); overflow-wrap: anywhere; }
.stage-box[data-verdict="fault"] { border-left: 3px solid var(--fault); }
.stage-box[data-verdict="ok"] { border-left: 3px solid var(--ok); }
.stage-box[data-verdict="warn"] { border-left: 3px solid var(--warn); }

/* Gauge for the fail-closed rejection: needle position is the state. */
.gauge { margin-top: calc(var(--u) * 2); border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 2); }
.gauge-track { position: relative; height: 2px; background: var(--rule-2); }
.gauge-needle { position: absolute; top: -6px; width: 2px; height: 14px; background: var(--fault); transition: transform var(--t-2) var(--ease); }
.gauge-scale { display: flex; justify-content: space-between; margin-top: var(--u); font-family: var(--mono); font-size: var(--fs-micro); color: var(--ink-3); }

/* ---------------------------------------------------- V8 — record --------- */

.facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--u) * 2.5); margin-top: calc(var(--u) * 3); }
.fact { border: 1px solid var(--rule-2); background: var(--face); padding: calc(var(--u) * 2.5); min-width: 0; }
.fact[data-fact="who"] { border-top: 3px solid var(--accent); }
.fact[data-fact="state"] { border-top: 3px solid var(--warn); }
.fact h3 { font-size: var(--fs-h3); margin-bottom: 4px; }
.fact-name { font-family: var(--mono); font-size: 20px; letter-spacing: 0.02em; margin-bottom: var(--u); overflow-wrap: anywhere; }
.fact .tags { margin: calc(var(--u) * 1.5) 0; }
.fact .pairs { margin-top: calc(var(--u) * 1.5); }

.table { border-top: 1px solid var(--rule); margin-top: calc(var(--u) * 3); }

.row {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.7fr) auto;
  gap: calc(var(--u) * 2.5);
  align-items: center;
  padding: calc(var(--u) * 1.5) 0;
  border-bottom: 1px solid var(--rule);
  min-width: 0;
}

.row > * { min-width: 0; }
.row .lane { font-size: var(--fs-body); font-weight: 600; overflow-wrap: anywhere; }
.row .data { font-family: var(--mono); font-size: var(--fs-data); color: var(--ink-2); overflow-wrap: anywhere; }
.row.is-open { border-left: 3px solid var(--warn); padding-left: calc(var(--u) * 1.75); }

.pill {
  display: inline-flex;
  border: 1px solid currentColor;
  padding: 3px var(--u);
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Reserved status colours. Chosen from the state, never for decoration. */
.pill-ok { color: var(--ok); }
.pill-warn { color: var(--warn); }
.pill-fault { color: var(--fault); }
.pill-accent { color: var(--accent); }

/* --------------------------------------------------------------- lists ----- */

.columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--u) * 5); }
.columns > * { min-width: 0; }
.columns h3 { font-size: var(--fs-h3); padding-bottom: var(--u); border-bottom: 1px solid var(--rule); margin-bottom: 4px; }
.list { list-style: none; margin: 0; padding: 0; }
.list li { border-bottom: 1px solid var(--rule); padding: 11px 0; font-size: var(--fs-data); color: var(--ink-2); overflow-wrap: anywhere; }

.risks { display: grid; gap: 0; }

.risk {
  border-bottom: 1px solid var(--rule);
  padding: 11px 0;
  display: grid;
  grid-template-columns: var(--col) minmax(0, 1fr);
  gap: calc(var(--u) * 1.75);
  align-items: baseline;
  min-width: 0;
}

.risk > * { min-width: 0; }
.risk-id { font-family: var(--mono); font-size: var(--fs-data); color: var(--warn); }
.risk p { font-size: var(--fs-data); color: var(--ink-2); }
.risk small { display: block; margin-top: 4px; font-size: var(--fs-micro); color: var(--ink-3); }

.sources { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 calc(var(--u) * 4); border-top: 1px solid var(--rule); margin-top: calc(var(--u) * 2.5); }

.source {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--u);
  align-items: baseline;
  border-bottom: 1px solid var(--rule);
  padding: var(--u) 0;
  min-width: 0;
}

.source code { font-family: var(--mono); font-size: 11px; color: var(--ink-2); overflow-wrap: anywhere; }
.source span { font-family: var(--mono); font-size: var(--fs-micro); color: var(--ink-3); overflow-wrap: anywhere; }
.quote { font-size: var(--fs-data); color: var(--ink-3); margin: calc(var(--u) * 1.25) 0 0; }

/* --------------------------------------------------------------- closing --- */

.closing {
  border-top: 1px solid var(--rule-2);
  padding: calc(var(--u) * 4.5) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--u) * 4);
}

.closing h2 { font-size: var(--fs-h2); max-width: 32ch; }
.closing p { margin-top: var(--u); color: var(--ink-2); }

.action {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--accent);
  color: var(--accent);
  padding: 10px calc(var(--u) * 2);
  font-family: var(--mono);
  font-size: var(--fs-data);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color var(--t-1) var(--ease);
}

.action:hover { background: var(--accent-wash); }

.colophon {
  border-top: 1px solid var(--rule);
  padding: calc(var(--u) * 2.5) 0 calc(var(--u) * 5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--u) calc(var(--u) * 3);
  align-items: baseline;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Skip link: parked off-screen with `left` only, so it stays focusable. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  padding: 10px 14px;
  background: var(--face-2);
  border: 1px solid var(--accent);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--fs-data);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.skip:focus { left: var(--gap); top: 10px; }

/* ------------------------------------------------------------ responsive --- */

@media (max-width: 1000px) {
  .hero { grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 3); align-items: start; }
  .band-head { grid-template-columns: 48px minmax(0, 1fr); }
  .band-head .band-note { grid-column: 2; }
  .band-src { grid-column: 2; }
  .ledger { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ratio { grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 3); }
}

@media (max-width: 760px) {
  :root { --gap: 18px; --col: 36px; }
  .band { padding: calc(var(--u) * 4) 0; }
  .hero { padding: calc(var(--u) * 5) 0 calc(var(--u) * 3); }
  .chassis-inner { min-height: 52px; gap: var(--u); }
  .mark-spec { display: none; }
  .ledger, .facts, .columns, .sources, .failclosed, .stateway { grid-template-columns: minmax(0, 1fr); }
  .arrow { display: none; }
  .step { grid-template-columns: var(--col) minmax(0, 1fr); gap: calc(var(--u) * 1.75); }
  .row { display: block; }
  .row > * { margin-bottom: var(--u); }
  .closing { display: block; }
  .closing .action { margin-top: calc(var(--u) * 2.5); }
}

@media (max-width: 380px) {
  .pair, .risk, .source { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* Reduced motion: jump straight to the finished state, no travel. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  .marker { display: none; }
  .leg.is-active.leg-public { stroke: var(--accent); }
  .leg.is-active.leg-private { stroke: var(--ink-2); }
}

/* ==========================================================================
   V2 — animated explainer, and V1 ambient
   ==========================================================================
   Instrument display, not a motion graphic. Movement is transform/opacity
   only: nothing here animates layout, so the compositor does the work and the
   page keeps its 60fps budget.
   ========================================================================== */

/* V1 ambient: one slow, low-amplitude breath on the terminal marker only. It
   is deliberately far slower and smaller than the flow so the two never
   compete. Reduced motion drops it to the end state (opacity 1). */
.motif .pt { animation: motif-breathe 7s ease-in-out infinite; }

@keyframes motif-breathe {
  0%, 100% { opacity: 0.66; }
  50% { opacity: 1; }
}

/* C3 — visual order is set with `order` so the DOM (and therefore the tab
   order) can be controls → cells → sentences while the drawing still reads
   first on screen. */
.explainer {
  margin-top: calc(var(--u) * 3.5);
  border: 1px solid var(--rule-2);
  background: var(--face);
  display: flex;
  flex-direction: column;
}

.explainer-head { order: 1; }
.explainer-display { order: 2; }
.explainer-modes { order: 3; }
.explainer-controls { order: 4; }
.scrub { order: 5; }
.stage-list { order: 6; }
.resolution { order: 7; }

/* --- C2: the timeline scrubber --- */
.scrub {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: calc(var(--u) * 1.5);
  align-items: center;
  padding: calc(var(--u) * 2) calc(var(--u) * 2.5) 0;
}

.scrub-label, .scrub-pos { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); }
.scrub-pos { color: var(--accent); }

.scrub-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 2px;
  background: var(--rule-2);
  border: 0;
  cursor: pointer;
}

.scrub-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 18px;
  background: var(--accent);
  border: 0;
  border-radius: 2px;
}

.scrub-range:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }

/* --- C1: cells are interactive in technical mode only --- */
.explainer[data-mode="technical"] .exp-cell { cursor: pointer; }
.explainer[data-mode="technical"] .exp-cell:hover { fill: var(--ink); }
.explainer[data-mode="technical"] .exp-cell:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }

.exp-detail { border-top: 1px solid var(--rule); padding: calc(var(--u) * 2.5); min-width: 0; overflow-wrap: anywhere; }
.exp-detail[hidden] { display: none; }
.exp-detail h3 { font-family: var(--mono); font-size: 13px; font-weight: 500; margin: var(--u) 0 0; }

.explainer-head { padding: calc(var(--u) * 2.5); border-bottom: 1px solid var(--rule); }
.explainer-head h3 { font-size: var(--fs-h3); margin: var(--u) 0; }

/* The honesty label is part of the UI, not a footnote. */
.honesty {
  border-left: 3px solid var(--warn);
  background: var(--warn-wash);
  padding: calc(var(--u) * 1.25) calc(var(--u) * 1.75);
  font-size: var(--fs-data);
  color: var(--ink);
  max-width: 72ch;
}

.explainer-display { padding: calc(var(--u) * 2.5) calc(var(--u) * 2.5) calc(var(--u) * 1.5); }

.explainer-display svg { display: block; width: 100%; height: auto; }

/* --- the drawing: three deliberate depths, one accent, consistent weights --- */
/* Every stroke in the drawing carries the hierarchy AND is non-scaling, so the
   engraving stays legible when the drawing shrinks to a phone. */
.exp-ground, .exp-plate, .exp-plate-slot, .exp-wall, .exp-envelope, .exp-flap,
.exp-token, .exp-seal, .exp-gate-post, .exp-gate-bar { vector-effect: non-scaling-stroke; }
/* The 66 cells are deliberately NOT non-scaling: they communicate by FILL, which
   scales correctly anyway, and device-space stroke recomputation on 66 elements
   was a measurable cost. The engraving that must stay crisp is structural. */

.exp-ground { fill: var(--face); stroke: var(--rule); stroke-width: var(--sw-struct); }
.exp-plate { fill: var(--face-2); stroke: var(--rule-2); stroke-width: var(--sw-struct); transition: stroke var(--t-2) var(--ease), fill var(--t-2) var(--ease); }
.exp-plate[data-active="true"] { fill: var(--face-3); stroke: var(--accent); stroke-width: var(--sw-fg); }
.exp-plate-num { fill: var(--ink-3); font-family: var(--mono); font-size: 11px; }
.exp-plate[data-active="true"] .exp-plate-num { fill: var(--accent); }
.exp-plate-name { fill: var(--ink-3); font-family: var(--sans); font-size: 11px; font-weight: 600; }
.exp-plate[data-active="true"] .exp-plate-name { fill: var(--ink); }
.exp-plate-slot { fill: none; stroke: var(--rule-2); stroke-width: var(--sw-tick); stroke-dasharray: 2 3; }

.exp-wall { stroke: var(--ink-2); stroke-width: var(--sw-struct); }
.exp-wall-label { fill: var(--ink-2); font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em; }

/* the packet is the foreground object: heaviest stroke in the drawing */
.exp-packet { transition: transform var(--t-3) var(--ease); }
.exp-envelope { fill: var(--face-3); stroke: var(--ink); stroke-width: var(--sw-fg); }
.exp-flap { stroke: var(--ink-3); stroke-width: var(--sw-tick); }

.exp-seal { fill: none; stroke: var(--ok); stroke-width: var(--sw-fg); opacity: 0; transition: opacity var(--t-2) var(--ease); }
.exp-packet[data-sealed="true"] .exp-seal { opacity: 1; }

.exp-scan { fill: var(--accent); opacity: 0; transition: opacity var(--t-1) var(--ease); }
.explainer[data-beat="check"] .exp-scan { opacity: 0.85; animation: exp-scan var(--t-3) linear infinite; }
.explainer[data-beat="check"] .exp-envelope { stroke: var(--accent); }
@keyframes exp-scan { from { transform: translateX(-46px); } to { transform: translateX(46px); } }

/* the packet's contents: one cell per inventoried field, in class bands */
/* No stroke: the cells are separated by layout gaps, so a dark hairline added
   nothing and measured 1.05:1 against the ground — below the 3:1 graphical
   threshold. The fill is the signal (5.51:1 private, 9.47:1 public). */
.exp-cell { stroke: none; }

/* The dissolve is two group fades instead of sixty-six element transitions. */
.exp-group { transition: opacity var(--t-3) var(--ease); will-change: opacity; }
.exp-group[data-state="visible"] { opacity: 1; }
.exp-group[data-state="redacting"] { opacity: 0.5; }
.exp-group[data-state="sealing"] { opacity: 0.75; }
.exp-group[data-state="gone"] { opacity: 0; }
.exp-cell[data-class="PRIVATE"] { fill: var(--ink-3); }
.exp-cell[data-class="CONDITIONAL_PUBLIC"] { fill: var(--warn); }
.exp-cell[data-class="PUBLIC"] { fill: var(--accent); }

/* At the crossing the hidden cells are visibly redacted, then gone; the public
   ones converge into the token. Nothing is described as deleted. */
.exp-cell[data-redacted="true"] { fill: var(--fault); }
.exp-cell[data-continuing="true"] { fill: var(--accent); }

/* the sealed token: small, opaque, clearly not the original contents */
.exp-token {
  fill: var(--face); stroke: var(--accent); stroke-width: var(--sw-fg); opacity: 0;
  transform-box: fill-box; transform-origin: center; transform: scale(0.5);
  transition: opacity var(--t-3) var(--ease), transform var(--t-3) var(--ease);
}
.exp-token[data-visible="true"] { opacity: 1; transform: scale(1); }

/* the gate at the refusal station */
.exp-gate-bar { stroke: var(--ink); stroke-width: var(--sw-fg); fill: var(--ink-2); transition: transform var(--t-2) var(--ease), fill var(--t-2) var(--ease); }
.exp-gate-post { fill: var(--ink-3); stroke: var(--rule-2); stroke-width: var(--sw-struct); }
.exp-gate[data-state="shut"] .exp-gate-bar { transform: translateY(0); fill: var(--fault); }
.exp-gate[data-state="open"] .exp-gate-bar { transform: translateY(-96px); }
.exp-packet[data-blocked="true"] { opacity: 0.55; }
.exp-packet[data-blocked="true"] .exp-envelope { stroke: var(--fault); }

/* --- narration lives with the drawing, in the same frame --- */
.narration {
  padding: calc(var(--u) * 1.5) 0 0;
  font-size: 22px;
  line-height: 1.45;
  color: var(--ink);
  max-width: 62ch;
}

.explainer[data-mode="technical"] .narration {
  font-family: var(--mono);
  font-size: var(--fs-data);
  color: var(--ink-2);
  line-height: 1.6;
}

.transform {
  padding: calc(var(--u) * 1.25) 0 0;
  font-size: 15px;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}

.explainer[data-mode="technical"] .transform { font-family: var(--mono); font-size: var(--fs-data); }

.explainer-modes { display: flex; flex-wrap: wrap; gap: var(--u); padding: calc(var(--u) * 2) calc(var(--u) * 2.5); border-top: 1px solid var(--rule); }

.explainer-controls { display: flex; flex-wrap: wrap; gap: var(--u); padding: 0 calc(var(--u) * 2.5) calc(var(--u) * 2); }

.stage-plain { font-size: 15px; }
.explainer[data-mode="technical"] .stage-plain { font-size: var(--fs-body); }

.stage {
  display: grid;
  grid-template-columns: var(--col) minmax(0, 1fr);
  gap: calc(var(--u) * 2);
  padding: calc(var(--u) * 1.75) calc(var(--u) * 2.5);
  border-bottom: 1px solid var(--rule);
  min-width: 0;
}

.stage > * { min-width: 0; }
.stage[data-active="true"] { background: var(--face-2); }
.stage-index { font-family: var(--mono); font-size: var(--fs-data); color: var(--accent); }
.stage h4 { margin: 0 0 calc(var(--u) * 0.5); font-size: var(--fs-body); }
.stage p { font-size: var(--fs-data); color: var(--ink-2); margin: 0; overflow-wrap: anywhere; }
.stage .stage-src { font-family: var(--mono); font-size: var(--fs-micro); color: var(--ink-3); margin-top: calc(var(--u) * 0.5); }

@media (max-width: 760px) {
  .stage { grid-template-columns: 32px minmax(0, 1fr); gap: var(--u); }
}

/* ---- Layer 1 — the opening promise and the chapter line ------------------ */
.opening {
  margin: calc(var(--u) * 1.5) 0 0;
  border-left: 3px solid var(--accent);
  padding-left: calc(var(--u) * 1.75);
  font-size: 24px;
  line-height: 1.35;
  color: var(--ink);
  max-width: 44ch;
}

.chapter {
  padding: calc(var(--u) * 2) 0 0;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ---- Layer 1 — linked highlighting, both directions ---------------------- */
.stage { cursor: pointer; transition: background-color var(--t-1) var(--ease); }
.stage[data-linked="true"], .stage:hover, .stage:focus-visible { background: var(--face-3); }
.exp-plate[data-linked="true"] { stroke: var(--accent); stroke-width: var(--sw-fg); }

/* ---- Layer 2 — the packet renders its own state -------------------------- */
.exp-packet[data-pstate="opened"] .exp-flap { opacity: 0; }
.exp-packet[data-pstate="opened"] .exp-envelope { stroke: var(--accent); }
.exp-packet[data-pstate="spent"] .exp-token { stroke: var(--ink-2); }
.explainer[data-stage="nullifier"] .exp-token { stroke-dasharray: 2 2; }
.exp-packet[data-pstate="blocked"] .exp-envelope { stroke: var(--fault); }

/* ---- Layer 5 — what this does NOT prove --------------------------------- */
.callout {
  margin-top: calc(var(--u) * 3);
  border: 1px solid var(--warn);
  background: var(--warn-wash);
  padding: calc(var(--u) * 2.5);
}

.callout h3 {
  font-family: var(--mono);
  font-size: var(--fs-data);
  letter-spacing: 0.14em;
  color: var(--warn);
  margin: 0 0 calc(var(--u) * 1.5);
}

.callout-list { list-style: none; margin: 0; padding: 0; }

.callout-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--u) calc(var(--u) * 2);
  align-items: baseline;
  border-top: 1px solid rgba(207, 161, 74, 0.35);
  padding: calc(var(--u) * 1.25) 0;
  font-size: var(--fs-data);
  color: var(--ink);
}

.callout-key { color: var(--ink-2); }
.callout-val { font-family: var(--mono); color: var(--warn); overflow-wrap: anywhere; }

@media (max-width: 760px) {
  .opening { font-size: 20px; }
  .callout-list li { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* ---- E — the resolution beat: the journey closes instead of stopping ------ */
.resolution {
  margin: calc(var(--u) * 2.5) 0 0;
  border-top: 1px solid var(--rule-2);
  padding-top: calc(var(--u) * 2);
  font-size: 19px;
  line-height: 1.45;
  color: var(--ink);
  max-width: 60ch;
  opacity: 0;
  transition: opacity var(--t-3) var(--ease);
}

.resolution[data-shown="true"] { opacity: 1; }

.explainer[data-phase="resolution"] .exp-token { stroke: var(--accent); }
