/* ─────────────────────────────────────────────────────────────────────────
   THE VEALTH WORKFIELD — production object grammar (issue #883, Wave 2).

   Wave 1 proved this language in an isolated prototype
   (apps/web/public/prototypes/workfield/). This is its FIRST PRODUCTION USE.
   The authority for every stage name, state word, line style, control-to-node
   mapping and named projection is apps/web/public/vealth/data/workfield-v0.json;
   this sheet only dresses it.

   THREE RULES GOVERN EVERY DECLARATION BELOW.

   1. OBJECT BEFORE CARD. There is no `.card` in this file and no
      `border-radius: 999px`. Each object owns a silhouette that reads before
      its label does: a place has no box, a need is an unclosed bracket, a
      packet is the only object with a clipped corner, a receipt the only one
      allowed a terminal double rule, a port is welded to the node it affects.

   2. LINE IS GRAMMAR. Hairline = a relationship exists. Solid = this actually
      happened and is recorded. Dashed = proposed, pending or unknown. Return =
      rejected and still open. Closure = a receipt closed it. The same five
      styles govern the connectors between nodes and the borders of objects, so
      the topology and its contents speak one language. Downstream connectors
      are DASHED until the packet's own server-owned evidence strength says the
      transition happened, so an open packet never draws a path it did not take.

   3. COLOUR IS THE SECOND SIGNAL. Every state carries a word first, a shape
      second and a hue third. Nothing here is distinguishable by hue alone.

   TOKENS: ground, ink, rule, panel and type all come from the HOUSE sheet
   (vealth-next.css). This file introduces NO second theme system — it declares
   only the six semantic role hues plus the line/axis metrics, and it declares
   every one of them again under [data-theme="dark"] so check:theme-parity
   holds. House law is followed exactly: dark is OPT-IN, so there is no
   prefers-color-scheme block here either.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* The six semantic roles. Each is ALWAYS paired with a word. Values are the
     house palette, DEEPENED where the house hue failed WCAG 2.2 AA at small
     text against the page's own parchment ground. That is a real measurement,
     not a preference: the house comment scores --gold-text at 5.2:1 against a
     cream panel, but the front door's darkest --page stop is rgb(225,203,165),
     where #7c590c measures 4.05:1. scripts/workfield-home-audit.ts scores every
     painted pair against the WORST ground the page can paint and fails the run
     on a single miss, in both themes.

     DEEPENED AGAIN IN WAVE 5, for the same reason one zoom further out. The
     lenses print role-coloured text on top of --pre-bg (a code face, a copy
     control, a machine-twin call), which composites to rgb(215,193,156) over
     that same darkest stop. The Wave 2 hues measured 4.31 / 4.44 / 4.48 / 4.51
     there — every one of them under AA for small text on the surface the
     reference pages actually paint. These five clear 4.5 on BOTH the bare
     ground and that composited face, measured by
     scripts/workfield-lens-audit.ts across all nine surfaces in both themes.
     Deepening can only raise the ratio on a light ground, so the surfaces
     Waves 2-4 already cleared stay cleared. The dark values are untouched:
     they were measured against the dark ground and still pass there. */
  --wf-value: #654706;      /* gold: value + economically consequential state */
  --wf-living: #1f5434;     /* botanical green: available / accepted / tended */
  --wf-evidence: #22506a;   /* hydrological aqua: evidence + machine linkage */
  --wf-attention: #7d3348;  /* blush: human attention, the judgment queue */
  --wf-stop: #832b0e;       /* safety stop, rejection, destructive ONLY */
  --wf-unknown: rgba(40, 29, 24, 0.80); /* "we do not know" is information */

  /* Structure. --wf-line carries meaning and clears 3:1 as a UI boundary;
     --wf-line-soft separates and never carries meaning. --wf-soft is the
     smallest readable label ink, and --wf-on-ink is the only text colour ever
     painted on a filled --ink surface. */
  --wf-line: #7d5f3d;
  --wf-line-soft: rgba(120, 80, 45, 0.26);
  --wf-soft: rgba(40, 29, 24, 0.78);
  --wf-face: rgba(250, 242, 224, 0.62);
  --wf-face-2: rgba(250, 241, 222, 0.90);
  --wf-on-ink: #faf3e2;

  --wf-axis: 8px;  /* the connector segment between two stages */
}

:root[data-theme="dark"] {
  --wf-value: #d9b876;
  --wf-living: #94c69b;
  --wf-evidence: #8badb4;
  --wf-attention: #c9a8a4;
  --wf-stop: #e2795a;
  --wf-unknown: rgba(236, 228, 208, 0.74);
  --wf-line: #8d7a4e;
  --wf-line-soft: rgba(224, 203, 150, 0.18);
  --wf-soft: rgba(236, 228, 208, 0.66);
  --wf-face: rgba(224, 203, 150, 0.05);
  --wf-face-2: rgba(224, 203, 150, 0.10);
  --wf-on-ink: #0d1109;
}

/* ═══════════════════════════════════════════════════════════════════════
   THE FIELD — three bands, one direction
   Upstream runs left to right along the top, the packet is the dominant band
   across the middle, and the evidence channel runs left to right along the
   bottom. That is #883's bird's-eye model laid down so the WHOLE machine fits
   one desktop viewport, which is Wave 2's gate: fourteen stages stacked in one
   column measured 2,338px at 1440x900 and could never satisfy it.

   The <ol> is the truth; the grid is only presentation. Strip every stylesheet
   and the DOM still narrates intake, place, need, demand, pledge, funding,
   PACKET, proof, judgment, receipt, settlement, earned credit, record, next
   work — in that order, which is also the reading order at every width.

   42 tracks, because 42 is the least common multiple of the six upstream
   stations and the seven downstream ones: each upstream station spans 7 and
   each downstream station spans 6, so both bands divide the field exactly and
   neither needs a hand-placed column.
   ═══════════════════════════════════════════════════════════════════════ */
.wf-field {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(42, minmax(0, 1fr));
  /* Two rows. The upstream band runs across the top; the packet and the
     downstream channel share the second. Downstream splits at the receipt:
     the EVIDENCE run (proof, judgment, receipt) beside the packet, then the
     OUTCOME run (settlement, earned credit, record, next work). Read the near
     run down, then the far one, and that is exactly the DOM order — the two
     runs are nested lists so neither column's height is hostage to the
     other's rows. */
  grid-template-rows: auto auto;
  column-gap: 0;
  row-gap: var(--wf-axis);
  align-items: start;
}
.wf-node { position: relative; min-width: 0; }
/* Each upstream station gets the width its content needs, not an equal share:
   the two control ports carry a live figure and its projection, a place
   carries a name, a pledge carries one sentence. The spans total 42. */
.wf-node--up { grid-row: 1; padding: 0 14px 0 15px; }
.wf-node--up:nth-child(1) { grid-column: span 6; }
.wf-node--up:nth-child(2) { grid-column: span 6; }
.wf-node--up:nth-child(3) { grid-column: span 7; }
.wf-node--up:nth-child(4) { grid-column: span 8; }
.wf-node--up:nth-child(5) { grid-column: span 5; }
.wf-node--up:nth-child(6) { grid-column: span 10; }
.wf-node--axis { grid-row: 2; grid-column: 1 / 20; padding: 0 clamp(14px, 1.6vw, 24px) 0 0; }
.wf-node--channel {
  grid-row: 2;
  grid-column: 20 / -1;
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  column-gap: 0;
  align-items: start;
}
.wf-chan {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--wf-axis);
}
.wf-node--down { padding: 0 12px 0 16px; }

/* A station's LEFT EDGE is its connector: the incoming edge of the chain,
   drawn in the grammar `data-line` names. The JS moves a downstream edge to
   solid only where a server-owned projection says the transition happened. */
.wf-node--up[data-line]::before,
.wf-node--down[data-line]::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 0;
  border-left: 2px solid var(--wf-line);
}
.wf-node--up[data-line="dashed"]::before,
.wf-node--down[data-line="dashed"]::before { border-left-style: dashed; }
.wf-node--up[data-line="hairline"]::before,
.wf-node--down[data-line="hairline"]::before { border-left-width: 1px; opacity: 0.8; }
.wf-node--up[data-line="return"]::before,
.wf-node--down[data-line="return"]::before { border-left-style: dotted; }
.wf-node--up[data-line="closure"]::before,
.wf-node--down[data-line="closure"]::before { border-left-width: 3px; }
.wf-node--up[data-line="none"]::before,
.wf-node--down[data-line="none"]::before { border-left-color: transparent; }

/* The two band-to-band joins: upstream feeds the packet on a solid run,
   because the packet demonstrably exists; the packet feeds the evidence
   channel on a run the JS only solidifies once proof has actually arrived. */
.wf-node--axis::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(-1 * var(--wf-axis));
  height: var(--wf-axis);
  width: 0;
  border-left: 2px solid var(--wf-line);
}
/* The packet feeds the evidence channel sideways, on a run the JS solidifies
   only once the packet's own evidence strength says proof actually arrived. */
.wf-node--enter::after {
  content: "";
  position: absolute;
  left: -14px;
  top: 8px;
  width: 14px;
  height: 0;
  border-top: 2px solid var(--wf-line);
}
.wf-node--enter[data-line="dashed"]::after { border-top-style: dashed; }

/* The stage name is mono and small; the CONTENT carries the display face. A
   stage label never competes with the object underneath it. */
.wf-stage {
  font: 600 10px/1.3 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--wf-soft);
  margin: 0 0 4px;
}
.wf-stage b { color: var(--ink); font-weight: 700; }

/* A live count sits BESIDE the node it describes, never in a KPI belt. */
.wf-count { margin: 4px 0 0; font: 400 12px/1.4 "Inter", system-ui, sans-serif; color: var(--muted); }
.wf-count b {
  font: 600 17px/1 "Fraunces", Georgia, serif;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin-right: 5px;
}
.wf-src {
  display: block;
  font: 500 10px/1.42 var(--mono, ui-monospace, monospace);
  color: var(--wf-evidence);
  letter-spacing: 0.01em;
  margin-top: 2px;
  word-break: break-word;
}

/* ── OBJECT 1 · PLACE ANCHOR ───────────────────────────────────────────────
   An open label over a coordinate rule. No enclosing box: a place is not a
   container, it is the ground everything else is measured from. */
.wf-place { padding: 0 0 5px; border-bottom: 2px solid var(--wf-line); }
.wf-place-name { margin: 0; font: 600 clamp(16px, 1.5vw, 19px)/1.2 "Fraunces", Georgia, serif; color: var(--ink); }
.wf-place-coord { margin: 3px 0 0; font: 500 10.5px/1.4 var(--mono, ui-monospace, monospace); color: var(--wf-soft); }

/* ── OBJECT 2 · NEED SIGNAL ────────────────────────────────────────────────
   An unclosed bracket: three sides drawn, the fourth deliberately absent. A
   need has no state, no price and no proof rule, and it looks unresolved. */
.wf-need {
  border: 1px solid var(--wf-line);
  border-right: 0;
  border-left-width: 3px;
  padding: 6px 10px 6px 9px;
  background: linear-gradient(90deg, var(--wf-face), transparent 88%);
}
.wf-need p { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--ink); }
.wf-need .wf-src { margin-top: 4px; }

/* ── CONTROL PORTS · VOTE / FUND / DO ──────────────────────────────────────
   A port is WELDED to the node it affects: it shares that node's edge and
   carries a stem into it. It is not a destination and never a card. The three
   of them sit at lotus-radial spacing around the packet: VOTE and FUND on the
   tributaries feeding it, DO on the plate itself. */
.wf-port {
  position: relative;
  border: 2px solid var(--wf-line);
  background: var(--wf-face);
  padding: 6px 10px 7px;
}
.wf-port-word {
  display: block;
  font: 600 clamp(19px, 1.9vw, 24px)/1 "Fraunces", Georgia, serif;
  letter-spacing: 0.02em;
  margin: 0 0 2px;
  color: var(--ink);
}
.wf-port-role {
  display: block;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wf-value);
  margin: 0 0 7px;
}
.wf-port p { margin: 0; font-size: 12px; line-height: 1.4; color: var(--muted); }
.wf-port .wf-count { margin-top: 4px; }
.wf-port--free .wf-port-role { color: var(--wf-living); }
/* the stem that welds the port to the axis it feeds */
.wf-port::after {
  content: "";
  position: absolute;
  top: -2px;
  bottom: -2px;
  right: -4px;
  width: 4px;
  background: var(--wf-line);
}

/* THE PORT IS THE CONTROL. The whole port head is the link, so a control is
   never a separate button sitting beside the node it belongs to, and it costs
   a mobile spine no extra height while still clearing a 44px thumb. */
.wf-portlink {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  min-height: 44px;
  align-content: center;
  text-decoration: none;
  color: inherit;
}
.wf-portlink:hover .wf-port-word { color: var(--wf-value); }

/* The state's SHAPE, which is what "open" and "closed" look like with every
   colour removed: dashed is pending, solid happened, dotted returned for
   revision, and only a closed thing draws the double rule. */
.wf-shape { display: inline-block; width: 26px; height: 0; border-top: 2px solid currentColor; flex: none; }
.wf-shape[data-shape="dashed"] { border-top-style: dashed; }
.wf-shape[data-shape="return"] { border-top-style: dotted; }
.wf-shape[data-shape="double"] { border-top: 4px double currentColor; height: 4px; }

/* The one action shape. Square, contained, never a pill. */
.wf-act {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 15px;
  border: 2px solid var(--ink);
  background: var(--ink);
  color: var(--wf-on-ink);
  font: 700 12px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
}
.wf-act:hover { background: transparent; color: var(--ink); }
.wf-act--quiet {
  background: transparent;
  color: var(--ink);
  border-color: var(--wf-line);
  font-weight: 600;
}
.wf-act--quiet:hover { border-color: var(--ink); background: transparent; color: var(--ink); }

/* ── OBJECT 3 · WORK PACKET (the dominant object) ──────────────────────────
   A squared work-order plate with a clipped top-right corner. The clip is the
   silhouette: at any zoom, blurred, with every label removed, the packet is
   the one object in the field with a cut corner. */
.wf-plate {
  position: relative;
  border: 2px solid var(--ink);
  background: var(--wf-face-2);
  --clip: 20px;
  clip-path: polygon(0 0, calc(100% - var(--clip)) 0, 100% var(--clip), 100% 100%, 0 100%);
}
.wf-plate::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: var(--clip);
  height: var(--clip);
  background: linear-gradient(to bottom left, transparent 49.4%, var(--ink) 49.4%, var(--ink) 52%, transparent 52%);
}
/* The identity band: what this packet IS, what state it is in, and the one
   thing to do about it — in one strip, at every width. */
.wf-plate-head {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: center;
  padding: 6px 16px;
  padding-right: 34px;
  border-bottom: 2px solid var(--ink);
}
.wf-plate-k {
  margin: 0;
  font: 700 10px/1.3 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}
.wf-plate-id {
  margin: 0 0 0 auto;
  font: 500 11px/1.35 var(--mono, ui-monospace, monospace);
  color: var(--wf-soft);
  word-break: break-all;
}
.wf-plate-task {
  margin: 0;
  padding: 6px 16px 3px;
  font: 600 clamp(16.5px, 1.35vw, 20px)/1.14 "Fraunces", Georgia, serif;
  color: var(--ink);
}

/* The fixed field anatomy. This ORDER is the canonical one every later surface
   must repeat: place, task, proof required, pay, then the state foot, then the
   one next action, then the id and the machine twin. */
.wf-fields { margin: 0; padding: 0 16px 2px; }
.wf-fields > div {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 2px 14px;
  padding: 5px 0;
  border-top: 1px solid var(--wf-line-soft);
}
.wf-fields dt {
  font: 700 10px/1.6 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-fields dd { margin: 0; font-size: 13px; line-height: 1.4; color: var(--ink); }
.wf-fields dd .wf-src { margin-top: 3px; }
/* `.wf-money` deleted (issue #883 Wave 6): the only elements carrying it are
   in apps/web/public/prototypes/workfield/, which ships its own workfield.css
   and never loads this sheet. */

/* The state: the WORD first, the shape second, the colour third. */
.wf-plate-sub {
  margin: 0;
  padding: 5px 16px 6px;
  border-bottom: 1px solid var(--wf-line-soft);
  font-size: 12px;
  line-height: 1.38;
  color: var(--muted);
}
.wf-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 700 11.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
.wf-state svg { flex: none; }
.wf-state--open, .wf-state--claimed { color: var(--wf-living); }
.wf-state--submitted { color: var(--wf-evidence); }
.wf-state--approved { color: var(--wf-attention); }
.wf-state--rejected { color: var(--wf-stop); }
.wf-state--settled { color: var(--wf-value); }
.wf-state--expired, .wf-state--unknown { color: var(--wf-unknown); }

/* The DO port lives ON the plate, in its identity band, never beside it. */
.wf-plate .wf-doport {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
}
.wf-doport .wf-port-word { font-size: 18px; margin: 0; flex: none; }
.wf-doport .wf-act { flex: none; }

.wf-twin {
  margin: 0;
  padding: 5px 16px 7px;
  border-top: 1px solid var(--wf-line-soft);
  font: 500 10.5px/1.5 var(--mono, ui-monospace, monospace);
  color: var(--wf-evidence);
  word-break: break-word;
}
.wf-twin a { color: inherit; }

/* The explicit absence state. Not a specimen, not an empty card: the plate
   keeps its silhouette and says, in the board's own words, that nothing is
   live. It is the same object, in its honest empty condition. */
.wf-plate[data-state="absent"] .wf-plate-task,
.wf-plate[data-state="pending"] .wf-plate-task { color: var(--muted); }

/* ── OBJECT 4 · PROOF BUNDLE ───────────────────────────────────────────────
   An evidence strip: a manifest of rows, hairline-ruled, no enclosing box.
   Evidence is a list of commitments, not a piece of content. */
.wf-evidence { border-top: 2px solid var(--wf-evidence); border-bottom: 2px solid var(--wf-evidence); }
.wf-evidence ol { list-style: none; margin: 0; padding: 0; }
.wf-evidence li { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; padding: 5px 2px; }
.wf-evidence li + li { border-top: 1px solid var(--wf-line-soft); }
.wf-evidence .k {
  font: 700 9.5px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-evidence);
}
.wf-evidence .v { font-size: 12px; line-height: 1.38; color: var(--ink); }

/* ── OBJECT 5 · JUDGMENT GATE ──────────────────────────────────────────────
   A narrow boundary drawn ACROSS the evidence channel. Both branches are
   always present. Physical work is never shown as deterministic, and
   deterministic work is never shown as waiting on a person. */
.wf-gate { border-top: 3px solid var(--wf-attention); border-bottom: 3px solid var(--wf-attention); padding: 6px 0 1px; }
.wf-gate-rule { margin: 0 0 9px; font: 600 12.5px/1.45 "Inter", system-ui, sans-serif; color: var(--ink); }
.wf-branch { padding: 4px 0 5px 10px; border-left: 2px solid var(--wf-line); }
.wf-branch + .wf-branch { margin-top: 6px; border-left-style: dashed; }
.wf-branch-k {
  margin: 0 0 3px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-living);
}
.wf-branch + .wf-branch .wf-branch-k { color: var(--wf-evidence); }
.wf-branch p { margin: 0; font-size: 12px; line-height: 1.38; color: var(--muted); }

/* ── OBJECT 6 · RECEIPT ────────────────────────────────────────────────────
   A ledger document. The ONLY object permitted a terminal double rule at its
   foot, and that rule is what "closed" looks like when every colour is
   removed. An open receipt never draws it. */
.wf-receipt { border: 1px solid var(--wf-line); border-top: 4px double var(--ink); background: var(--wf-face); }
.wf-receipt-head { padding: 6px 12px 5px; border-bottom: 1px solid var(--wf-line); }
.wf-receipt-k {
  margin: 0 0 3px;
  font: 700 9.5px/1.3 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--wf-value);
}
.wf-receipt-id { margin: 0; font: 500 11px/1.45 var(--mono, ui-monospace, monospace); color: var(--wf-soft); }
.wf-receipt-body { padding: 5px 12px 6px; font-size: 12px; line-height: 1.4; color: var(--muted); }
.wf-receipt-body p { margin: 0; }
.wf-receipt-body p + p { margin-top: 7px; }
.wf-receipt-foot {
  border-top: 4px double var(--ink);
  padding: 6px 12px;
  font: 700 10px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wf-value);
}

/* ── OBJECT 7 · RECORD ─────────────────────────────────────────────────────
   A chronological trace. Settled receipts sit on the spine at full weight;
   declarations and testimony are indented, lighter and separately headed, so
   the two can never be confused by silhouette. */
.wf-record { border-top: 2px solid var(--wf-line); padding-top: 6px; }
.wf-record-k {
  margin: 0 0 5px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-record ul { list-style: none; margin: 0; padding: 0; }
.wf-record li { padding: 5px 0 5px 10px; font-size: 12px; line-height: 1.38; color: var(--ink); border-left: 3px solid var(--wf-value); }
.wf-record--weak { margin: 7px 0 0 12px; }
.wf-record--weak li { color: var(--wf-soft); border-left: 1px dashed var(--wf-line); }

/* the return arc: it closes only where a receipt exists */
.wf-return { display: flex; align-items: flex-start; gap: 10px; }
.wf-return svg { flex: none; color: var(--wf-line); margin-top: 2px; }
.wf-return p { margin: 0; font-size: 12px; line-height: 1.38; color: var(--muted); }

/* ── The legend ────────────────────────────────────────────────────────────
   Every line style in the field, named. Below the topology, never inside it. */
.wf-legend { margin: 20px 0 0; border-top: 1px solid var(--wf-line-soft); padding-top: 13px; }
.wf-legend h2 { font: 600 14px/1.2 "Fraunces", Georgia, serif; margin: 0 0 9px; color: var(--ink); }
.wf-legend dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); gap: 9px 22px; margin: 0; }
.wf-legend div { display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 9px; align-items: center; }
.wf-legend dt { display: flex; align-items: center; }
.wf-legend dd { margin: 0; font-size: 11.5px; line-height: 1.4; color: var(--muted); }
.wf-legend dd b {
  display: block;
  color: var(--ink);
  font: 700 10px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.wf-swatch { display: block; width: 46px; height: 0; border-top: 2px solid var(--wf-line); }
.wf-swatch--hair { border-top-width: 1px; opacity: 0.8; }
.wf-swatch--dashed { border-top-style: dashed; }
.wf-swatch--return { border-top-style: dotted; }
.wf-swatch--closure { border-top: 4px double var(--ink); }

/* ═══ MOBILE — one vertical causal spine, never stacked cards ══════════════
   The DOM order IS the visual order. The spine moves to the left edge, every
   tributary hangs off it, and no grid nests inside another. */
@media (max-width: 900px) {
  :root { --wf-axis: 4px; }
  .wf-field { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-auto-flow: row; row-gap: var(--wf-axis); }
  .wf-node--up,
  .wf-node--up:nth-child(1), .wf-node--up:nth-child(2), .wf-node--up:nth-child(3),
  .wf-node--up:nth-child(4), .wf-node--up:nth-child(5), .wf-node--up:nth-child(6),
  .wf-node--axis,
  .wf-node--channel { grid-column: 1; grid-row: auto; align-self: stretch; }
  .wf-node--up { padding: 0 0 0 18px; }
  .wf-node--channel { display: block; }
  .wf-chan { gap: var(--wf-axis); }
  .wf-chan + .wf-chan { margin-top: var(--wf-axis); }
  .wf-node--down { padding: 0 0 0 18px; }
  /* The plate's identity band packs onto two rows at 390: what this is and
     what state it is in, then the one thing to do about it. */
  .wf-plate-head { gap: 1px 9px; padding: 3px 14px 4px; }
  .wf-plate-id { margin-left: 0; flex-basis: auto; }
  .wf-plate .wf-doport { flex-basis: 100%; }
  /* Every node hangs off ONE spine at the left edge, and the connector runs
     the height of the node it belongs to, so the causal chain is continuous. */
  .wf-node--up[data-line]::before,
  .wf-node--down[data-line]::before { top: 0; bottom: calc(-1 * var(--wf-axis)); }
  .wf-node--axis::before { left: 8px; }
  .wf-node--enter::after { display: none; }

  /* The upstream tributaries become LABELLED LEDGER ROWS, not blocks: the
     stage name sits in a fixed left column and its object beside it, exactly
     as #883's mobile law asks ("data becomes labelled ledger rows"). Nothing
     is hidden and nothing moves out of causal order; the six tributaries just
     stop spending a whole line each on their own name. That is what puts the
     packet's identity, its state and its one next action inside the first
     844px viewport. */
  .wf-node--up {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr);
    gap: 0 8px;
    align-items: start;
  }
  .wf-node--up .wf-stage { margin: 0; padding-top: 3px; }
  /* A provenance line that hangs off the node itself, not off its object,
     still belongs in the object column: otherwise auto-placement drops it
     under the stage name and it reads as a second label. */
  .wf-node--up > .wf-count { grid-column: 2; }
  .wf-node--up .wf-port { padding: 2px 8px 2px; }
  .wf-node--up .wf-portlink { min-height: 44px; }
  .wf-node--up .wf-port-word { font-size: 15px; }
  .wf-node--up .wf-port-role { font-size: 8.5px; letter-spacing: 0.08em; }
  .wf-node--up .wf-port p { font-size: 11px; line-height: 1.3; }
  .wf-node--up .wf-port::after { display: none; }
  .wf-node--up .wf-count { margin-top: 1px; font-size: 11px; }
  .wf-node--up .wf-count b { font-size: 14px; }
  .wf-node--up .wf-src,
  .wf-node--down .wf-src { font-size: 8.5px; line-height: 1.3; }
  .wf-node--up .wf-portlink { min-height: 44px; gap: 0 8px; align-content: center; }
  .wf-node--up .wf-port .wf-count { margin-top: 3px; }
  .wf-node--up .wf-place { padding-bottom: 3px; }
  .wf-need { padding: 2px 8px 3px 7px; }
  .wf-need p { font-size: 11.5px; line-height: 1.32; }
  .wf-place { padding-bottom: 2px; }
  .wf-place-name { font-size: 14.5px; }
  .wf-place-coord { margin-top: 1px; font-size: 9.5px; }
  .wf-stage { font-size: 8px; letter-spacing: 0.09em; margin-bottom: 2px; line-height: 1.32; }

  .wf-fields > div { grid-template-columns: 84px minmax(0, 1fr); gap: 1px 10px; padding: 4px 0; }
  .wf-fields dt { letter-spacing: 0.1em; }
  .wf-fields dd { font-size: 13px; }
  .wf-plate-task { padding: 10px 14px 6px; }
  .wf-plate-head { padding: 9px 14px 8px; padding-right: 34px; }
  .wf-fields { padding: 0 14px 2px; }
  .wf-plate-sub { padding: 5px 14px 6px; font-size: 11.5px; }
  .wf-plate .wf-doport { margin-left: 0; }
  .wf-doport .wf-act { flex: 1 1 auto; }
  .wf-twin { padding: 8px 14px 10px; }
  .wf-legend div { grid-template-columns: 38px minmax(0, 1fr); }
  .wf-swatch { width: 38px; }
}

/* ═══ MOTION — causality only, and none of it at rest ══════════════════════
   The single animation in the Workfield is a dash resolving into a value that
   actually arrived. It runs once and nothing loops. */
@keyframes wf-resolve {
  from { opacity: 0.4; }
  to { opacity: 1; }
}
.wf-resolved { animation: wf-resolve 200ms ease-out 1; }

@media (prefers-reduced-motion: reduce) {
  .wf-resolved { animation: none; }
}

/* Forced colours: the line grammar must survive when the palette does not. */
@media (forced-colors: active) {
  .wf-plate, .wf-port, .wf-need, .wf-receipt { border-color: CanvasText; }
  .wf-node[data-line]::before,
  .wf-node--up::after,
  .wf-node--down::after { border-color: CanvasText; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   WAVE 3 — THE BOARD, POST AND FUND ZOOMS (issue #883, §11 Wave 3)

   Wave 2 put the Workfield on the front door at its OBSERVATORY zoom: the
   whole machine at once. These three surfaces are the same field seen closer,
   and the rules do not change with the zoom:

     BOARD  — the live work layer. Place, demand, funding and the selected
              packet are the spine; the raw ledger of every other open job
              runs beneath it; craft and reference recede to the foot.
     POST   — the upstream tributary. A place and a need visibly BECOME the
              draft packet, which wears the same plate it will wear on the
              board, and the publish gate is the last thing on the page.
     FUND   — the funding node, drilled into. One packet, its real gap, its
              terms, the obligations we hold the rails to, and only then the
              doors that can take money.

   NOTHING BELOW INTRODUCES A SECOND THEME. Every colour is one of the six
   --wf-* semantic roles already declared above in BOTH themes; this section
   declares no token of its own, so check:theme-parity has nothing new to
   check and no page can drift into a private palette.

   NO GENERIC CARD, NO CAPSULE. There is still no `.card` and no
   `border-radius: 999px` in this file. A door is a bounded object with a
   stem, a ledger row is a ruled row, and reference material is visibly
   lighter than the work it explains.
   ═════════════════════════════════════════════════════════════════════════ */

/* THE PAGE GROUND, ON A REAL ANCESTOR.
   body.simple paints the ground on a fixed ::before pseudo-element, which
   composites correctly and is INVISIBLE to any contrast reader walking the
   ancestor chain: axe scores a dark-theme page's light ink against white and
   reports thirty phantom failures per surface. index.html already declares the
   same token on <html> for exactly this reason (Wave 2). Same token, same
   value, no new colour, and the ground is now painted before the glow layer
   composites over it. */
html { background: var(--page); }

/* The page frame the three zooms share. One measure, one rhythm, and the
   dominant object is always the packet. */
.wf-page { max-width: 1120px; }
.wf-head { margin: 0 0 clamp(10px, 1.4vw, 16px); }
.wf-head h1 {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.02em;
  font-size: clamp(25px, 2.3vw, 33px);
  line-height: 1.06;
  margin: 0 0 6px;
  max-width: 22ch;
  padding-left: 0;
}
.wf-head h1::before, .wf-head h1::after { display: none; }
.wf-head .wf-lede {
  font-family: "Fraunces", Georgia, serif;
  font-size: clamp(13px, 1vw, 15.5px);
  line-height: 1.38;
  color: var(--ink);
  max-width: 78ch;
  margin: 0;
}
.wf-eyebrow {
  font: 700 10.5px/1.3 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--wf-value);
  margin: 0 0 3px;
}

/* WCAG 2.2 AA 2.5.8, the inline half. A link inside a sentence is exempt from
   the house 44px rule and is NEVER exempt from its own 24x24 floor. Padding on
   the block axis rather than display:inline-block, so a long link still wraps
   inside its line and cannot push a 390px page sideways. Home declares the
   same floor on its own inline links (Wave 2); this is that rule for the three
   zooms. */
.wf-page p a,
.wf-page li a,
.wf-page dd a,
.wf-page dt a { padding: 6px 1px; }

/* A section heading inside a zoom. Not a scene, not a card: a rule and a
   name, so the causal spine keeps running through it. */
.wf-sec { margin: clamp(20px, 2.4vw, 34px) 0 0; }
.wf-sec > h2 {
  font: 600 clamp(17px, 1.5vw, 21px)/1.15 "Fraunces", Georgia, serif;
  color: var(--ink);
  margin: 0 0 6px;
  padding-left: 0;
}
.wf-sec > h2::before, .wf-sec > h2::after { display: none; }
.wf-sec > .wf-lede { font-size: 13.5px; line-height: 1.5; color: var(--muted); max-width: 74ch; margin: 0 0 10px; }
.wf-boundary {
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  font-size: 12px;
  line-height: 1.6;
  color: var(--wf-soft);
  max-width: 84ch;
}
/* A link in a sentence takes the value hue; the ONE filled action does not.
   `.wf-sec a` outranks `.wf-act` on specificity, and before the :not() below it
   repainted every action's ink gold on near-black (measured 2.23:1 on eight
   surfaces by scripts/workfield-lens-audit.ts). An action carries its own ink
   because its own ground is the ink. */
.wf-boundary a:not(.wf-act),
.wf-sec a:not(.wf-act),
.wf-ledger a:not(.wf-act),
.wf-defs a:not(.wf-act),
.wf-rails a:not(.wf-act),
.wf-head a:not(.wf-act),
.wf-lens a:not(.wf-act),
.wf-reference a:not(.wf-act),
.wf-invariant a:not(.wf-act),
.wf-standing a:not(.wf-act),
.wf-twin-side a:not(.wf-act) { color: var(--wf-value); }

/* EVERY link inside a Workfield object needs an answer, in both themes. When
   Wave 5 took the generic `.card` off the protocol boxes it also took away the
   only rule in the house sheet that coloured the links inside them, and those
   anchors fell back to the USER-AGENT default: #0000EE, which measures 1.98:1
   on the dark ground. A component that owns a surface owns the links on it. */

/* A link that is the WHOLE of its own row is a standalone control, not a link
   inside a sentence, so it takes the house 44px floor rather than 2.5.8's
   inline 24x24 exemption. Grown by hit area, never by type size. */
.wf-rail-v > a:only-child,
.wf-ledger-v > a:only-child,
/* A line whose whole content is one safety link is that same standalone
   control, not a link inside a sentence. Measured at 24px on fund.html at 1440
   and 1024 by scripts/workfield-ratchet-audit.ts (issue #883 Wave 6); it only
   cleared the floor at 768 and below, where the sentence happened to wrap onto
   a second line. Grown by hit area, never by type size. */
.wf-checkline > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1px;
}

/* ── THE SPINE LAYOUT ──────────────────────────────────────────────────────
   A zoom has fewer stations than the observatory, so it does not need the
   observatory's 42-track band. Three tributaries across the top, the packet
   dominant and full width beneath them, and at 900px or less the base sheet's
   mobile rules already collapse it to one vertical causal spine. */
@media (min-width: 901px) {
  .wf-field--spine { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: auto auto; }
  .wf-field--spine > .wf-node--up,
  .wf-field--spine > .wf-node--up:nth-child(1),
  .wf-field--spine > .wf-node--up:nth-child(2),
  .wf-field--spine > .wf-node--up:nth-child(3),
  .wf-field--spine > .wf-node--up:nth-child(4),
  .wf-field--spine > .wf-node--up:nth-child(5),
  .wf-field--spine > .wf-node--up:nth-child(6) { grid-row: 1; grid-column: span 1; }
  .wf-field--spine > .wf-node--axis { grid-row: 2; grid-column: 1 / -1; padding: 0; }
  .wf-field--spine > .wf-node--axis::before { left: 16.6%; }
}

/* ── EDITABLE FIELDS ───────────────────────────────────────────────────────
   Post is the one zoom where the packet's fields are still the person's to
   write. They stay in the SAME rows, in the same order, so the draft and the
   published packet are visibly one object at two moments — not a form that
   later turns into something else. */
.wf-edit {
  width: 100%;
  font: inherit;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
  background: var(--wf-face);
  border: 1px solid var(--wf-line);
  border-radius: 0;
  padding: 7px 9px;
  min-height: 44px;
}
textarea.wf-edit { min-height: 66px; resize: vertical; }
.wf-edit:focus { outline: 2px solid var(--wf-value); outline-offset: 1px; }
.wf-fields dd .wf-note {
  display: block;
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.42;
  color: var(--wf-soft);
}

/* ── LEDGER ROWS ───────────────────────────────────────────────────────────
   #883's mobile law made general: "data becomes labelled ledger rows". Every
   list on these three zooms that used to be a grid of equal-weight cards is
   this instead — a ruled row carrying its own state word. */
.wf-ledger { list-style: none; margin: 8px 0 0; padding: 0; border-top: 1px solid var(--wf-line); }
.wf-ledger > li {
  display: grid;
  grid-template-columns: minmax(150px, 210px) minmax(0, 1fr);
  gap: 3px 18px;
  padding: 9px 0 10px;
  border-bottom: 1px solid var(--wf-line-soft);
  align-items: start;
}
.wf-ledger-k {
  margin: 0;
  font: 700 10.5px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink);
}
.wf-ledger-v { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.wf-ledger-v + .wf-ledger-v { margin-top: 6px; }
.wf-ledger-v b { color: var(--ink); }
/* The one place a compact capsule is right: a state chip on a ledger row.
   It always carries its word, so nothing is readable by shape or hue alone. */
.wf-ledger-state {
  display: inline-block;
  margin-right: 8px;
  padding: 2px 8px;
  border: 1px solid currentColor;
  font: 700 9.5px/1.6 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.wf-ledger-state--done { color: var(--wf-living); }
.wf-ledger-state--partial { color: var(--wf-value); }
.wf-ledger-state--open { color: var(--wf-stop); }
@media (max-width: 620px) {
  .wf-ledger > li { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* ── DOORS ─────────────────────────────────────────────────────────────────
   A money door is an OBJECT with a stem into the funding node, the same
   shape a control port has, never a marketing card. Its live state line is
   part of the object, so the door can never claim to be open while the state
   beneath it says it is closed. */
.wf-doors { display: grid; grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); gap: 14px; margin-top: 12px; }
.wf-door { position: relative; border: 2px solid var(--wf-line); background: var(--wf-face); padding: 10px 14px 13px; }
.wf-door::after { content: ""; position: absolute; top: -2px; bottom: -2px; left: -4px; width: 4px; background: var(--wf-line); }
.wf-door-k {
  margin: 0 0 3px;
  font: 600 clamp(16px, 1.5vw, 19px)/1.15 "Fraunces", Georgia, serif;
  color: var(--ink);
}
.wf-door-role {
  display: block;
  margin: 0 0 7px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-value);
}
.wf-door p { margin: 0 0 7px; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.wf-door p:last-child { margin-bottom: 0; }
.wf-door .wf-state-line { font: 600 12px/1.45 var(--mono, ui-monospace, monospace); color: var(--wf-evidence); }
.wf-door pre {
  margin: 9px 0 0;
  padding: 9px 10px;
  border: 1px solid var(--wf-line-soft);
  background: var(--wf-face-2);
  font: 500 11px/1.5 var(--mono, ui-monospace, monospace);
  color: var(--ink);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 17em;
  overflow: auto;
}
.wf-door label { font: 600 12px/1.5 "Inter", system-ui, sans-serif; color: var(--ink); }
.wf-door input[type="number"], .wf-door input[type="text"] {
  font: inherit; font-size: 13px; color: var(--ink); background: var(--wf-face-2);
  border: 1px solid var(--wf-line); border-radius: 0; padding: 8px 9px; min-height: 44px; width: 110px;
}
button.wf-act { cursor: pointer; }
button.wf-act[disabled] { opacity: 0.55; cursor: not-allowed; }
.wf-acts { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 0; }

/* ── THE REFERENCE BAND ────────────────────────────────────────────────────
   Craft curriculum, standards, comparisons: true, worth keeping, and NOT
   what a board is for. It keeps every word and every anchor, and it is
   visibly subordinate — one rule above it, smaller type, folded by default,
   and never a full screen of its own. */
.wf-reference { margin: clamp(28px, 3.4vw, 46px) 0 0; padding-top: 14px; border-top: 4px double var(--wf-line); }
.wf-reference > h2 {
  font: 600 clamp(15px, 1.2vw, 17px)/1.2 "Fraunces", Georgia, serif;
  color: var(--wf-soft);
  margin: 0 0 4px;
  padding-left: 0;
}
.wf-reference > h2::before, .wf-reference > h2::after { display: none; }
.wf-reference > .wf-lede { font-size: 12.5px; line-height: 1.5; color: var(--wf-soft); max-width: 74ch; margin: 0 0 10px; }

/* ── THE RAW LEDGER OF EVERY OTHER JOB ─────────────────────────────────────
   The board's own rows keep their own component (work-board.css) untouched:
   the claim, vote and fund flows on them are live money paths and this wave
   changes how the field reads, never what a row does. All this does is seat
   that component inside the spine. */
.wf-board-slot { margin-top: 10px; }
.wf-board-slot .work-board { border-top: 0; margin-top: 0; padding-top: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   WAVE 4 — VERIFY, THE RECEIPT DOCUMENT AND ME (issue #883, §11 Wave 4)

   Wave 3 gave the PACKET one silhouette everywhere. Downstream of it nothing
   was shared: a live record rendered into a generic card on Verify, another
   card per pending proof, a bespoke certificate face plus a dot timeline on
   receipt.html, a hand-written narrative on packet 14, and four stat tiles on
   Me with testimony sitting at the same weight as an onchain settlement.

   Wave 4's gate: A PERSON CAN TELL PENDING PROOF, ACCEPTED PROOF, SETTLEMENT,
   TESTIMONY AND SELF-DECLARATION APART WITHOUT READING A PARAGRAPH.

   THE BOTTOM EDGE IS THE STATE. #883 §5 forbids carrying that distinction by
   colour, so every closure below differs in KIND at the foot of the document:

     data-close="open"      no foot rule at all, and a dotted stub trailing
                            downward: the document is visibly unfinished
     data-close="rejected"  a dotted RETURN rule with the path back to proof
     data-close="approved"  one plain solid rule: a line, not a seal
     data-close="receipt"   one solid rule, under a double header rule
     data-close="settled"   the terminal DOUBLE rule — the seal
     data-close="earned"    the terminal DOUBLE rule, with the disposition
                            rail below showing money did NOT move

   Settled and earned record are both closed and are NOT the same closure: the
   two-lane disposition rail draws exactly one lane solid and leaves the other
   dashed and dimmed with its own words. That is #883's "cash settlement and
   other settlement forms remain distinct", drawn rather than asserted.

   NO NEW TOKEN SYSTEM. Every colour below is one of the six --wf-* semantic
   roles already declared at the top of this sheet in BOTH themes.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The two state words Wave 4 adds to the ladder. Word first, shape second,
   hue third, exactly as the seven before them. */
.wf-state--receipt { color: var(--wf-evidence); }
.wf-state--earned { color: var(--wf-living); }
.wf-state--open { color: var(--wf-attention); }

/* ── THE RECEIPT DOCUMENT ──────────────────────────────────────────────────
   A ledger document with the eight parts of #883 §5 in stable positions. The
   immutable header rule is the 4px double at the top; what changes with the
   state is the FOOT. */
.wf-doc { margin: 0; }
.wf-receipt .wf-receipt-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  padding: 9px 16px 8px;
}
.wf-receipt-title {
  margin: 0;
  flex-basis: 100%;
  font: 600 clamp(17px, 1.5vw, 22px)/1.16 "Fraunces", Georgia, serif;
  color: var(--ink);
}
.wf-receipt .wf-receipt-id { margin: 0; }
.wf-receipt .wf-state { margin-left: auto; }
.wf-receipt-sub {
  margin: 0;
  padding: 6px 16px 7px;
  border-bottom: 1px solid var(--wf-line-soft);
  font-size: 12px;
  line-height: 1.4;
  color: var(--muted);
}

/* The four labelled rows. Same grid rhythm as the packet's own fields, so a
   receipt and a packet read as two objects in one system. */
.wf-rec { margin: 0; padding: 0 16px 2px; }
.wf-rec > div {
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr);
  gap: 2px 14px;
  padding: 7px 0;
  border-top: 1px solid var(--wf-line-soft);
}
.wf-rec dt {
  font: 700 10px/1.6 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-rec dd { margin: 0; font-size: 13px; line-height: 1.45; color: var(--ink); }
.wf-rec dd .wf-src { margin-top: 3px; }

/* A part heading inside the document: a rule and a name, never a nested box. */
.wf-part { padding: 9px 16px 2px; }
.wf-part > h3 {
  margin: 0 0 5px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-part > h3::before, .wf-part > h3::after { display: none; }

/* THE NON-CLAIMS BLOCK. Structural, not a footnote: a dashed boundary, which
   is the same grammar the field uses for "not established". */
.wf-notclaims {
  margin: 4px 16px 10px;
  padding: 9px 12px;
  border: 1px dashed var(--wf-line);
}
.wf-notclaims > p {
  margin: 0 0 5px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-stop);
}
.wf-notclaims ul { margin: 0; padding-left: 17px; font-size: 12px; line-height: 1.45; color: var(--muted); }
.wf-notclaims li + li { margin-top: 4px; }

/* `.wf-claims`, the mirror of the non-claims block, is deleted (issue #883
   Wave 6): Wave 4 drew the accepted claim inside the receipt head instead, and
   no element in the repo has ever carried the class. `.wf-notclaims` above is
   the live one — three surfaces render it. */

/* ── THE EVENT SPINE ───────────────────────────────────────────────────────
   Chronology as a ruled ledger, never as cards. The last event carries the
   larger marker, so where the chain currently ends is visible at a glance. */
.wf-spine { list-style: none; margin: 0 0 8px; padding: 0 16px 0 26px; }
.wf-spine li {
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr);
  gap: 2px 14px;
  padding: 6px 0 6px 12px;
  border-left: 2px solid var(--wf-line);
  position: relative;
}
.wf-spine li::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 12px;
  width: 8px;
  height: 8px;
  background: var(--wf-line);
}
.wf-spine li:last-child::before { width: 10px; height: 10px; left: -6px; background: var(--ink); }
.wf-spine .k {
  font: 700 10px/1.6 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}
.wf-spine .v { font: 500 11.5px/1.5 var(--mono, ui-monospace, monospace); color: var(--wf-soft); word-break: break-word; }
.wf-spine .v a { color: var(--wf-value); }

/* ── THE DISPOSITION RAIL ──────────────────────────────────────────────────
   Two lanes: SETTLEMENT and EARNED RECORD. Exactly one may be taken, and the
   lane that was not taken stays drawn and says why. Never collapsed into "the
   receipt", never recoloured into agreement. */
.wf-disposition {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin: 4px 16px 8px;
}
.wf-lane { padding: 7px 0 8px 11px; border-left: 3px solid var(--wf-line); }
.wf-lane + .wf-lane { margin-left: 14px; }
.wf-lane[data-taken="no"] { border-left-style: dashed; opacity: 0.66; }
.wf-lane-k {
  margin: 0 0 3px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-lane[data-taken="yes"] .wf-lane-k { color: var(--ink); }
.wf-lane p { margin: 0; font-size: 12px; line-height: 1.42; color: var(--muted); }
.wf-lane-mark {
  display: block;
  margin-top: 6px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-lane[data-taken="yes"] .wf-lane-mark { color: var(--wf-value); }
@media (max-width: 620px) {
  .wf-disposition { grid-template-columns: minmax(0, 1fr); }
  .wf-lane + .wf-lane { margin: 8px 0 0; }
}

/* ── THE CLOSURE EDGES. The whole state grammar, with no colour in it. ───── */
.wf-receipt { border-bottom-width: 1px; }
.wf-receipt-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
}
.wf-receipt[data-close="open"] {
  border-bottom: 0;
  padding-bottom: 2px;
  position: relative;
}
/* The document literally does not end: a dotted stub continues past its edge. */
.wf-receipt[data-close="open"]::after {
  content: "";
  position: absolute;
  left: 16px;
  bottom: -13px;
  width: 0;
  height: 13px;
  border-left: 2px dotted var(--wf-line);
}
.wf-receipt[data-close="open"] .wf-receipt-foot { border-top: 0; padding-top: 2px; color: var(--wf-attention); }
.wf-receipt[data-close="rejected"] .wf-receipt-foot { border-top: 2px dotted var(--ink); color: var(--wf-stop); }
.wf-receipt[data-close="approved"] .wf-receipt-foot { border-top: 2px solid var(--ink); color: var(--wf-attention); }
.wf-receipt[data-close="receipt"] .wf-receipt-foot { border-top: 2px solid var(--ink); color: var(--wf-evidence); }
.wf-receipt[data-close="settled"] .wf-receipt-foot { border-top: 4px double var(--ink); color: var(--wf-value); }
.wf-receipt[data-close="earned"] .wf-receipt-foot { border-top: 4px double var(--ink); color: var(--wf-living); }
.wf-receipt-mark {
  margin-left: auto;
  font: 500 10px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--wf-soft);
}
/* A link in the foot mark is a standalone control, not a link in a sentence,
   so it takes the house 44px floor. Grown by hit area, not by type size. */
.wf-receipt-mark a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1px;
  color: var(--wf-value);
}

/* ── THE JUDGMENT GATE, WITH BOTH BRANCHES ─────────────────────────────────
   The two branches are always in the DOM. `data-taken` decides which one is
   drawn as the path this packet's authored rule actually took. A packet with
   no decision marks neither, and the gate stays open. */
.wf-gate[data-open="yes"] { border-bottom-style: dashed; }
.wf-branches { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
@media (max-width: 720px) { .wf-branches { grid-template-columns: minmax(0, 1fr); } }
.wf-branch[data-taken] { border-left: 3px solid var(--wf-line); }
.wf-branch[data-taken="no"] { border-left-style: dashed; opacity: 0.66; }
.wf-branch[data-taken="yes"] .wf-branch-k { color: var(--ink); }
.wf-taken {
  display: block;
  margin-top: 6px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-branch[data-taken="yes"] .wf-taken { color: var(--wf-living); }
.wf-gate-result { margin: 8px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--ink); }
.wf-gate-actor { margin: 3px 0 0; font: 500 11px/1.5 var(--mono, ui-monospace, monospace); color: var(--wf-soft); }

/* ── THE PROOF BUNDLE, AS A JUDGEABLE ITEM ─────────────────────────────────
   The queue on Verify is a list of evidence strips inside ONE open gate, not
   a grid of cards. Each strip carries its own manifest rows and its own
   verdict controls; nothing about it is nested in a second surface. */
.wf-bundle { border-top: 2px solid var(--wf-evidence); padding: 8px 0 10px; }
.wf-bundle + .wf-bundle { margin-top: 14px; }
.wf-bundle-k { margin: 0 0 5px; font: 700 12px/1.4 var(--mono, ui-monospace, monospace); color: var(--ink); word-break: break-all; }
.wf-bundle-checks { margin: 8px 0 4px; }
.wf-bundle-checks legend {
  padding: 0;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-bundle-checks label {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink);
}
/* The checkbox's HIT AREA is the whole 44px label row: clicking a label
   activates the control it wraps, which is why the ROW carries the floor and
   the glyph does not. No explicit height on the input, so it stays the
   platform's own control at the platform's own size. */
.wf-bundle-checks input { flex: none; margin: 0; }
.wf-bundle-note { margin: 6px 0 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
.wf-hash { font: 500 11px/1.5 var(--mono, ui-monospace, monospace); color: var(--wf-evidence); word-break: break-all; }

/* ── THE VERIFIER ──────────────────────────────────────────────────────────
   One input and one act, welded together like a control port. It is the
   intake of the evidence field, not a search box on a page. */
.wf-verify { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; margin: 10px 0 0; }
.wf-verify input {
  flex: 1 1 22ch;
  min-width: 0;
  min-height: 44px;
  font: 500 13px/1.4 var(--mono, ui-monospace, monospace);
  color: var(--ink);
  background: var(--wf-face-2);
  border: 2px solid var(--wf-line);
  border-radius: 0;
  padding: 10px 12px;
}
.wf-verify input:focus { outline: 2px solid var(--wf-value); outline-offset: 1px; }

/* ── THE RECORD TRACE (Me) ─────────────────────────────────────────────────
   Receipts sit ON the spine at full weight behind a solid rail. Declarations
   and testimony are set back behind a DASHED rail, in smaller type, under
   their own heading. Blur every label and the two are still two things. */
.wf-record-group + .wf-record-group { margin-top: 14px; }
.wf-record-group > .wf-record-k { color: var(--wf-soft); }
.wf-record-group[data-strength="strong"] > .wf-record-k { color: var(--ink); }
.wf-record li { margin: 0; }
.wf-record li + li { margin-top: 4px; }
.wf-record li b { display: block; font-size: 13px; color: var(--ink); }
.wf-record li span { display: block; font: 500 10.5px/1.5 var(--mono, ui-monospace, monospace); color: var(--wf-soft); word-break: break-word; }
.wf-record--weak li b { font-size: 12.5px; color: var(--wf-soft); font-weight: 600; }
.wf-record-what { margin: 0 0 6px; font-size: 12px; line-height: 1.45; color: var(--muted); }
.wf-record--weak .wf-record-what { font-size: 11.5px; color: var(--wf-soft); }

/* ── MOBILE ────────────────────────────────────────────────────────────────
   Same law as the base sheet: one vertical spine, labelled ledger rows, no
   nested grid, and the DOM order is the visual order. */
@media (max-width: 900px) {
  .wf-rec > div { grid-template-columns: 84px minmax(0, 1fr); gap: 1px 10px; padding: 6px 0; }
  .wf-spine { padding-left: 20px; }
  .wf-spine li { grid-template-columns: minmax(0, 1fr); gap: 1px; }
  .wf-receipt .wf-receipt-head { padding: 8px 14px 7px; }
  .wf-receipt .wf-state { margin-left: 0; }
  .wf-rec, .wf-part { padding-left: 14px; padding-right: 14px; }
  .wf-notclaims, .wf-disposition { margin-left: 14px; margin-right: 14px; }
  .wf-receipt[data-close="open"]::after { left: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   WAVE 5 — THE MACHINE TWIN AND THE DEEPER LENSES (issue #883, §11 Wave 5)

   Waves 2-4 gave the six OPERATING surfaces one field, one packet and one
   evidence grammar. The eight surfaces this wave touches were the ones that
   still looked like sibling products: Connect was an AI product, Money a KPI
   dashboard, Standard a numbered doctrine, Institutions a marketing grid,
   Safety a list page, About a second truncated loop diagram, Protocols a box
   catalogue, and Regenerative Finance a tabbed mini-site with its own theme.

   Wave 5's gate: NO MAJOR PUBLIC PAGE INTRODUCES A COMPETING LIFECYCLE DIAGRAM
   OR A SEPARATE PRODUCT GRAMMAR.

   So this section adds exactly six things, and every one of them is a way of
   saying "this page is a LENS on the one field", never a new product surface:

     .wf-lens        the quiet locator #883 §4 asks for — PLACE / NEED / WORK /
                     PROOF / RECEIPT / RECORD with the current zoom named. It
                     is the single mark that makes eight pages read as eight
                     views of one machine.
     .wf-board       the control board: ONE intake gate (CREATE / POST) drawn
                     ABOVE three operating controls (VOTE / FUND / DO). The
                     gate makes work; the controls operate on work already in
                     the field. That distinction is the wave's other law.
     .wf-rail        infrastructure beneath a named node. A STOPPED rail's line
                     is LITERALLY BROKEN — a gap in the rule — and carries its
                     stop word and date. Nothing here is ambiently "live".
     .wf-invariant   a band drawn ACROSS the field: a condition that holds at
                     every stage rather than at one. Safety is the only one.
     .wf-standing    the place record as a ladder of rungs with the held rung
                     marked and the lapse path drawn as a return.
     .wf-twin        the human view and the machine view of ONE object, side by
                     side, sharing an id, a state and a next call.

   NO NEW TOKEN SYSTEM, AGAIN. Every colour below is one of the six --wf-*
   semantic roles declared at the top of this sheet under BOTH themes. There is
   still no `.card` and no `border-radius: 999px` in this file.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── THE LOCATOR ───────────────────────────────────────────────────────────
   Six stage names in causal order, hairline-joined. The one this page is a
   lens over carries aria-current and is drawn at ink weight over a solid rule;
   the rest stay soft over a hairline. Blur the words and you can still see
   where in the field you are standing, which is the whole job. */
.wf-lens { margin: 0 0 clamp(12px, 1.6vw, 20px); }
.wf-lens-k {
  margin: 0 0 5px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-lens ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 2px;
}
.wf-lens li {
  padding: 5px 11px 6px 0;
  border-top: 1px solid var(--wf-line-soft);
  font: 600 10px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-soft);
  flex: 1 1 auto;
  min-width: 0;
}
/* The current zoom: a solid rule instead of a hairline, ink instead of soft,
   and a marker before the word. Three signals, none of them colour. */
.wf-lens li[aria-current] {
  border-top: 3px solid var(--ink);
  color: var(--ink);
  font-weight: 700;
}
.wf-lens li[aria-current]::before { content: "\25B8\00a0"; }
.wf-lens p {
  margin: 6px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--wf-soft);
  max-width: 84ch;
}
.wf-lens a { color: inherit; }

/* ── THE CONTROL BOARD ─────────────────────────────────────────────────────
   #883 Wave 5: "define CREATE / POST as the intake gate while retaining
   VOTE / FUND / DO as the three primary controls." So the gate is drawn as a
   GATE — full width, above the field, with a stem running down into it — and
   the three controls are drawn as the welded ports they already are on the
   front door. One is how work enters; three are how work in the field is
   operated. The shapes say so before the words do. */
.wf-board { margin: 0; }
.wf-intake {
  /* The gate is an ANCHOR — it is the door work enters through, so it is a
     link and not a div wrapping one. An anchor is inline by default, and an
     inline box does not give its border and padding a height: the gate
     rendered as a 4px sliver with its own text spilling out of it. Rendered
     capture, not a measurement, is what caught that. */
  display: block;
  position: relative;
  border: 2px solid var(--wf-line);
  border-bottom-width: 3px;
  background: var(--wf-face);
  padding: 9px 14px 11px;
}
.wf-intake::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -14px;
  height: 14px;
  width: 0;
  border-left: 3px solid var(--wf-line);
}
.wf-intake-k {
  display: block;
  margin: 0 0 2px;
  font: 600 clamp(17px, 1.7vw, 21px)/1.1 "Fraunces", Georgia, serif;
  color: var(--ink);
}
.wf-intake-role {
  display: block;
  margin: 0 0 6px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wf-evidence);
}
.wf-intake p { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.wf-intake:hover .wf-intake-k { color: var(--wf-value); }
.wf-ports {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-top: 22px;
}
.wf-ports > .wf-port::after { display: none; }
/* Each operating port keeps a stem UP to the gate's own rule, so the three are
   visibly downstream of the one and not four equal doors. */
.wf-ports > .wf-port {
  position: relative;
  margin-top: 12px;
}
.wf-ports > .wf-port::before {
  content: "";
  position: absolute;
  left: 18px;
  top: -14px;
  height: 14px;
  width: 0;
  border-left: 2px solid var(--wf-line);
}
@media (max-width: 720px) {
  .wf-ports { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .wf-intake::after { left: 18px; }
}

/* ── A RAIL, AND A BROKEN ONE ──────────────────────────────────────────────
   A rail is infrastructure beneath a named node of the field. Its left edge
   carries its state, and a stopped rail's edge is drawn with a REAL GAP in it.
   Remove every colour and a stopped rail is still a broken line; that is #883's
   "historical/stopped rails visually broken and labeled rather than ambiently
   live", drawn instead of asserted. */
.wf-rails { list-style: none; margin: 10px 0 0; padding: 0; border-top: 1px solid var(--wf-line); }
.wf-rail {
  position: relative;
  display: grid;
  grid-template-columns: minmax(150px, 216px) minmax(0, 1fr);
  gap: 4px 18px;
  padding: 10px 0 12px 16px;
  border-bottom: 1px solid var(--wf-line-soft);
  align-items: start;
}
.wf-rail::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 3px;
  background: var(--wf-line);
}
.wf-rail[data-state="live"]::before { background: var(--wf-living); }
.wf-rail[data-state="parked"]::before {
  background: repeating-linear-gradient(to bottom, var(--wf-unknown) 0 5px, transparent 5px 10px);
}
/* STOPPED: the rail runs, and then it stops. A third of it is simply absent. */
.wf-rail[data-state="stopped"]::before {
  background: linear-gradient(to bottom, var(--wf-stop) 0 33%, transparent 33% 67%, var(--wf-stop) 67% 100%);
}
/* DEAD: the rail ends and does not resume. */
.wf-rail[data-state="dead"]::before {
  background: linear-gradient(to bottom, var(--wf-unknown) 0 30%, transparent 30% 100%);
}
.wf-rail-k { margin: 0; font: 600 14.5px/1.25 "Fraunces", Georgia, serif; color: var(--ink); }
.wf-rail-node {
  display: block;
  margin-top: 2px;
  font: 500 10px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-rail-v { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.wf-rail-v + .wf-rail-v { margin-top: 6px; }
.wf-rail-v b { color: var(--ink); }
.wf-rail-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font: 700 10px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-unknown);
}
.wf-rail[data-state="live"] .wf-rail-state { color: var(--wf-living); }
.wf-rail[data-state="stopped"] .wf-rail-state { color: var(--wf-stop); }
.wf-rail[data-state="parked"] .wf-rail-state { color: var(--wf-soft); }
@media (max-width: 620px) {
  .wf-rail { grid-template-columns: minmax(0, 1fr); gap: 5px; }
}

/* ── THE INVARIANT BAND ────────────────────────────────────────────────────
   A condition that holds at EVERY stage rather than at one, so it is drawn
   across the field instead of on a node. Only safety uses it. The stop hue is
   reserved for exactly this and for rejection, and it never travels alone. */
.wf-invariant {
  border-top: 3px solid var(--wf-stop);
  border-bottom: 3px solid var(--wf-stop);
  padding: 11px 0 13px;
  margin: clamp(16px, 2vw, 26px) 0 0;
}
.wf-invariant-k {
  margin: 0 0 4px;
  font: 700 10px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--wf-stop);
}
.wf-invariant > p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink); max-width: 80ch; }
.wf-invariant > p + p { margin-top: 7px; }
/* The stages the band crosses, named, so "at every stage" is a list and not a
   claim. Each one carries the boundary that applies to it. */
.wf-span {
  list-style: none;
  margin: 11px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: 0;
}
.wf-span li { padding: 6px 12px 8px 11px; border-left: 2px solid var(--wf-stop); }
.wf-span b {
  display: block;
  font: 700 9.5px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--wf-stop);
}
.wf-span span { display: block; margin-top: 2px; font-size: 12px; line-height: 1.42; color: var(--muted); }

/* ── THE STANDING LADDER ───────────────────────────────────────────────────
   The place record, as rungs. The rung a place HOLDS is drawn on a solid rail
   at ink weight; the rungs above it are dashed and dimmed because they are not
   held; and the lapse path is the field's own return line, pointing back down.
   No badge, no plaque, no ring of achievement — a ladder with a current rung. */
.wf-standing { list-style: none; margin: 12px 0 0; padding: 0; }
.wf-rung {
  position: relative;
  padding: 8px 0 10px 15px;
  border-left: 3px solid var(--wf-line);
}
.wf-rung + .wf-rung { margin-top: 2px; }
.wf-rung[data-held="no"] { border-left-style: dashed; opacity: 0.72; }
.wf-rung[data-held="yes"] { border-left-color: var(--wf-living); border-left-width: 5px; }
.wf-rung-k {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 3px 11px;
  font: 600 15.5px/1.2 "Fraunces", Georgia, serif;
  color: var(--ink);
}
.wf-rung-n {
  font: 700 9.5px/1.6 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-rung[data-held="yes"] .wf-rung-n { color: var(--wf-living); }
.wf-rung p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); max-width: 76ch; }
.wf-lapse {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 12px 0 0;
  padding: 8px 0 0 15px;
  border-left: 3px dotted var(--wf-attention);
}
.wf-lapse p { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); max-width: 78ch; }

/* ── THE HUMAN ↔ MACHINE TWIN ──────────────────────────────────────────────
   #883 §8, Connect: "add split human/machine view of one packet and its next
   call; visually prove it is the same Workfield, not an AI product." So the
   two views sit in one frame with one rule between them, and the machine side
   is a manifest of real doors rather than a code sample: same id, same state,
   same next act, printed from the same projection the plate was drawn from. */
.wf-twin-split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 0;
  align-items: start;
  margin-top: 12px;
}
.wf-twin-side { min-width: 0; }
.wf-twin-side + .wf-twin-side {
  padding-left: clamp(14px, 1.8vw, 26px);
  margin-left: clamp(14px, 1.8vw, 26px);
  border-left: 2px solid var(--wf-evidence);
}
.wf-twin-k {
  margin: 0 0 7px;
  font: 700 9.5px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-twin-side + .wf-twin-side .wf-twin-k { color: var(--wf-evidence); }
.wf-calls { list-style: none; margin: 0; padding: 0; }
.wf-calls li { padding: 6px 0 7px; border-top: 1px solid var(--wf-line-soft); }
.wf-calls li:first-child { border-top: 0; padding-top: 0; }
.wf-calls b {
  display: block;
  font: 700 9.5px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wf-soft);
}
.wf-calls code {
  display: block;
  margin-top: 2px;
  font: 500 11.5px/1.5 var(--mono, ui-monospace, monospace);
  color: var(--wf-evidence);
  word-break: break-word;
}
.wf-calls span { display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
@media (max-width: 860px) {
  .wf-twin-split { grid-template-columns: minmax(0, 1fr); }
  .wf-twin-side + .wf-twin-side {
    padding: 12px 0 0;
    margin: 14px 0 0;
    border-left: 0;
    border-top: 2px solid var(--wf-evidence);
  }
}

/* ── THE LENS FOOT ─────────────────────────────────────────────────────────
   Every lens ends by naming the surface it is a lens ON, so no reference page
   is ever a terminal destination. A row of real routes, never a taxonomy. */
.wf-exits {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
  margin: 14px 0 0;
}

/* ── SMALL SHARED PIECES the eight lenses need ─────────────────────────────
   A definition row (a term and what it means) and a figure that sits BESIDE
   the thing it describes. Both exist so a lens never has to reach for a card. */
.wf-defs { margin: 10px 0 0; border-top: 1px solid var(--wf-line); }
.wf-defs > div {
  display: grid;
  grid-template-columns: minmax(132px, 200px) minmax(0, 1fr);
  gap: 3px 18px;
  padding: 9px 0 10px;
  border-bottom: 1px solid var(--wf-line-soft);
}
.wf-defs dt {
  font: 700 10.5px/1.5 var(--mono, ui-monospace, monospace);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink);
}
.wf-defs dd { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.wf-defs dd b { color: var(--ink); }
.wf-defs dd + dd { margin-top: 5px; }
@media (max-width: 620px) {
  .wf-defs > div { grid-template-columns: minmax(0, 1fr); gap: 3px; }
}
.wf-figure {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin: 5px 0 0;
}
.wf-figure b {
  font: 600 20px/1 "Fraunces", Georgia, serif;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.wf-figure span { font-size: 12px; line-height: 1.45; color: var(--muted); }
