/* ══════════════════════════════════════════════════════════════════════════
   HOUSE.CSS — THE ONE SHEET (S4 fold, 2026-07-16)

   PART A = the house zones        (was masthead.css §1–§8)
   PART B = the console chrome     (was console.css  §1–§13)

   § references elsewhere in code and docs map as:
   "masthead.css §N" = part A §N  ·  "console.css §N" = part B §N.

   The cascade is the former LINK ORDER (masthead THEN console), preserved
   verbatim by concatenation — no rule moved, no selector changed at the fold.
   The door consumes this sheet too: its page style out-cascades part B's base
   by source order; part B's tabular numerals now reach the door's digits —
   the house voice, deliberately. profile-surface.css remains the manual
   pair's surface block until S3 dissolves it.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   THE HOUSE STYLESHEET  ·  single source, consumed by every surface (§15 Law A)
   Rendered into by masthead.js. Renovate here; never inline, never hardcode.

   THE ZONE MODEL (founder template, 2026-07-15) — the house is a vertical
   stack of ZONES. Every zone: the SAME minimum height (--band) that GROWS with
   its content, the SAME --edge margins, the same spacing to its vertical
   extents, and NEVER a line. Each zone can be switched OFF FOR DISPLAY but is
   DORMANT, never deleted (the display button at the door is the model).
   INFILL is the only variable:
       masthead   — no infill         logo · display button · language ONLY
       sub-nav    — no infill (= masthead)  navigation / flow; EMPTY band on the
                                      door — breathing space, never content
       content    — theme background  the working sheets; its vertical extents
                                      ARE the bands either side
       readback   — --fill-secondary  PERSISTENT READBACK (verdict strips, store
                                      state); empty band on the door
       footer     — --fill-primary    content switches: the trading line by
                                      DEFAULT, info display when a page needs it
       lost       — display none      THE LOST-THINGS HOLD: displaced live
                                      elements awaiting placement — dormant,
                                      relationships intact, nothing deleted

   Sections:  1 TOKENS · 2 ZONE PRIMITIVES + SWITCHES · 3 MASTHEAD · 4 HEADER
              ANCHORING · 5 SUB-NAV ZONE · 6 READBACK ZONE · 7 FOOTER ZONE ·
              8 RESPONSIVE
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══ 1 · TOKENS ═══ every value lives here, once ═══════════════════════════ */
:root {
  --edge: clamp(16px, 4vw, 36px);      /* the one horizontal margin, house-wide */
  --band: 60px;                        /* masthead = info panel = footer height */
  --clear: var(--band);                /* the zone flanking the masthead — EQUAL to the band (founder 2026-07-13) */
  --hx: clamp(20px, 3vw, 40px);        /* primary header clearance from the logo anchor */
  --fs-nav: 13px;                      /* the page-navigation register (console switcher, pair nav) */
  --fs-tab: 12px;                      /* the view-tab register (plate tabs) */
  --sup-drop: 5.3px;                    /* metric-derived baseline drop for the lockup superscript + word (Univers 45; re-probe on a face change) — house-wide so the caption sits right on EVERY page */
  /* --anchor-x + --h-anchor are MEASURED live by masthead.js: the logo's right
     extent, and a snap to the left margin when a primary would cross the page edge */

  /* THE TWO HOUSE FILLS (founder ruling 2026-07-13 — sampled from the reference
     site: footer = PRIMARY, band-above-footer = SECONDARY. Every secondary fill
     in the house consumes --fill-secondary; the footer consumes --fill-primary.) */
  --fill-primary: #000;                /* the footer fill · class:fixed(founder ruling 2026-07-13; sampled rung — first in the F-5 queue when the manual arrives) */
  --fill-secondary: #EAEAEA;           /* THE GROUND RAMP (founder ground-hierarchy ruling 2026-07-22) · class:fixed(DERIVED through the palette engine: CI neutral cast at L(CI ground #F9F9F9) − 0.045 — the working ground and the verdict bar were ΔL 0.001 apart, INVERTED, and read as one grey; the page now steps working-surface → verdict bar → black band. Measured on this fill: --info-ink 9.40:1 · --info-dim 5.70:1 · band signals ≥3:1 · pinned by derive-house-palette --check) */
  --ink-secondary: #363b40;            /* the SECONDARY-register ink · class:fixed(founder 2026-07-13 — one token for font, companion to --fill-secondary; the info-panel header reads in it) */
  --ink-effect: var(--ink-secondary);  /* the FONT GESTURE colour — what lettering flashes to on hover/open; ONE token so every gesture flashes the SAME (founder 2026-07-13) */
  --info-ink: var(--ink-secondary); --info-dim: #565b61; /* on --fill-secondary: WCAG 9.40 / 5.70 (§15 Law B, re-measured at the ground ramp 2026-07-22) · class:fixed(the readback ink pair — fixed ground by ruling) */
  --lockup-ink: var(--ink-secondary); /* the lockup TEXT family — dark veins override with their own scheme ink so the whole lockup switches together (the family law, founder 2026-07-22) */
  --leader: #949494;                   /* THE DOOR LEADER TONE (founder 2026-07-24) · class:fixed(DERIVED through the palette engine: the highest-lightness CI-neutral cast (ciCastAt) that clears WCAG 1.4.3's 3:1 large-text floor on --panel — latent by lightness, brand-family by the cast, legible by the contrast engine; retires the hand-typed --latent from the door leaders, --latent stays the disabled 'in the workshop' tone; pinned by derive-house-palette --check) */
}

/* ═══ 2 · ZONE PRIMITIVES + SWITCHES ═══════════════════════════════════════ */
/* a band zone: --band tall (grows), edge margin, no line, content centred */
.zone-band { min-height: var(--band); padding-inline: var(--edge); display: flex; align-items: center; gap: clamp(12px, 2.5vw, 24px); border: none; }
/* the clearance zone: the breathing region below the masthead — min height that
   grows, NO infill, NO line. Empty on the door; holds the sub-nav on consoles. */
.zone-clear { min-height: var(--clear); padding-inline: var(--edge); border: none; background: none; }
/* ZONE SWITCHES — a band switches OFF FOR DISPLAY by body attribute; the markup
   stays, dormant, never deleted (founder template 2026-07-15: "like the display
   button itself"). */
body[data-band-subnav="off"] #subnav,
body[data-band-readback="off"] .readback,
body[data-band-footer="off"] .blackband { display: none; }
/* THE LOST-THINGS HOLD — the dormant home for elements displaced from a zone
   whose placement is not yet ruled (never delete an element the engine still
   binds: purge the ZONE, keep the RELATIONSHIP). Render nothing; bindings
   (rowstate.js etc.) still find their mounts here. */
#lost { display: none; }
/* THE PRE-PAINT LANGUAGE GATE (boot.js decides during parse; lang.js releases
   after the walk): in DE the static chrome never flashes English — paint holds
   until translated. EN is canonical: no gate, no cost. Failsafe in boot.js. */
html[data-lang="de"]:not([data-lang-ready]) body { visibility: hidden; }

/* ═══ 3 · THE MASTHEAD ZONE ═══ logo · display icon · language ═════════════ */
#masthead {
  grid-column: 1 / -1;                 /* the house owns the span; pages never redeclare it (was the legacy header{} rule) */
  display: flex; align-items: flex-start; flex-wrap: nowrap;
  gap: clamp(12px, 3vw, 24px);
  min-height: var(--band); border: none;
  padding: calc(var(--sp) * 1.75) var(--edge) calc(var(--sp) * 1.25);
  padding-top: max(calc(var(--sp) * 1.75), env(safe-area-inset-top));
  padding-left: max(var(--edge), env(safe-area-inset-left));
  padding-right: max(var(--edge), env(safe-area-inset-right));
  min-width: 0;
}
/* THE LOCKUP — one object: mark · superscript · word, complete on EVERY surface.
   The superscript and the word ride the mark from the TOP via the metric-derived
   --sup-drop (NOT the flex-container floor — a floor-relative caption hangs, and
   hangs DIFFERENTLY on each mark because the glyphs carry different viewBox
   padding). One parametric token, every page, every mode. Any part empty ⇒ gone
   (the client wordmark carries no superscript). Never hidden by width — it scales. */
.mh-logo { display: flex; align-items: flex-start; gap: 0; text-decoration: none; color: inherit; flex: 0 0 auto; min-width: 0; }
.mh-mark { height: 36px; width: auto; display: block; }
.mh-sup { margin: var(--sup-drop) 0 0 2px; font-size: 15px; line-height: 1; color: var(--lockup-ink); } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.mh-sup:empty { display: none; }
.mh-cap { margin: var(--sup-drop) 0 0 var(--sp); font-size: 13px; line-height: 1; color: var(--lockup-ink); letter-spacing: 0.02em; white-space: nowrap; }
.mh-cap:empty { display: none; }
/* DARK-CHROME LOCKUP — THE FAMILY LAW (founder finding 2026-07-22): the lockup
   is ONE object; on a dark ground every member switches together. A face that
   supplies an approved reversed mark renders IT — never a CSS inversion of the
   colour artwork (ICD-003 B-1: approved versions only). The single-mark
   committed NEUTRAL glyph keeps the lossless invert (our own one-colour mark;
   currentColor can't cross an <img> boundary). The text members ride
   --lockup-ink, set per dark vein from that vein's OWN scheme (its --dim). */
.mh-mark--dark { display: none; }
body[data-chrome="factory"] .mh-mark--dark, body[data-chrome="blueprint"] .mh-mark--dark { display: block; }
body[data-chrome="factory"] .mh-mark--light, body[data-chrome="blueprint"] .mh-mark--light { display: none; }
/* a SINGLE-mark face (the neutral glyph) is inline currentColor SVG, so it takes
   --lockup-ink per vein and needs no reversal — the filter:invert(1) hack that
   lived here (for the <img> mark that couldn't inherit colour) is retired with
   the move to inline marks (2026-07-24). A face with an approved reversed twin
   still swaps to it above (VID-003 family law). */
/* THE FAMILY FOLLOWS THE MARK — one rule, derived, no hand values (founder,
   fifth catch 2026-07-22: the caption read as a stray tint beside the white
   mark). The SAME switch that shows the reversed white artwork sets the text:
   dark veins ride the vein's own INK (its white register, already measured by
   the vein's scheme); light grounds keep the :root secondary register beside
   the colour mark. class:family(lockup) */
body[data-chrome="factory"] { --lockup-ink: var(--ink); }
body[data-chrome="blueprint"] { --lockup-ink: var(--ink); }

.mh-right { display: flex; align-items: baseline; gap: clamp(12px, 2.5vw, 18px); margin-left: auto; margin-top: var(--sup-drop, 5.3px); flex: 0 0 auto; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.mh-lang { display: flex; align-items: baseline; gap: 7px; font-size: 13px; line-height: 1; white-space: nowrap; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.mh-lang .on { font-weight: 700; color: var(--ink, #16191c); }
.mh-lang .off { color: var(--dim, #8b939b); cursor: pointer; }
.mh-lang .off:hover { color: var(--ink, #16191c); }
/* the separator's layout is LOCKED here (align-self + margin) so a page's own
   generic `.sep` rule can never inflate the shared masthead again (founder
   2026-07-13: the masthead must render identically on every page) */
.mh-lang .sep { color: var(--hair, var(--line, #e2e6ea)); align-self: baseline; margin: 0; width: auto; }
/* the display-mode icon — no border, inboard of the language toggle, centred on its midpoint */
.mh-mode { background: none; border: 0; padding: 0; margin: 0; cursor: pointer; display: inline-flex; align-self: center; line-height: 0; }
.mh-mode svg { display: block; }

/* ═══ 4 · HEADER ANCHORING ═══ measured anchor + clash snap (mobile rule) ═══
   Primary headers align to the logo's measured right extent + --hx. When a
   primary would cross the right page margin, masthead.js sets --h-anchor to the
   left margin and BOTH primaries snap there together (founder 2026-07-13).
   Secondary headers (tool lists) share this SAME anchor — no extra offset. */
.h-primary { margin-left: var(--h-anchor, calc(var(--anchor-x, var(--edge)) + var(--hx))); }

/* ═══ 5 · THE SUB-NAV ZONE ═══ navigation / flow ONLY (founder 2026-07-15) ══ */
/* the clearance zone, filled on consoles: Jobs · Setup · Simulation (+ the
   active console's plate tabs). Machine controls NEVER ride this band — the
   60·80 row-state lives inside the Setup work surface (or the lost hold). */
/* THE STYLESHEET ENFORCES TEXT BASELINES (founder 2026-07-13): the switcher and
   the plate tabs — different transforms/sizes — sit on ONE baseline, not matched
   centres. Every nested flexbox on the line re-declares baseline so the baseline
   propagates through it; padding-block (not align:center) keeps the band centred. */
#subnav { min-height: var(--clear); padding-inline: var(--edge); padding-block: calc((var(--clear) - 16px) / 2); grid-column: 1 / -1; display: flex; align-items: baseline; gap: clamp(14px, 3vw, 26px); border: none; }
#subnav:empty { display: none; }
/* THE PAGE-NAVIGATION REGISTER — one register wherever the band navigates
   between PAGES: the console switcher on the auto side AND the manual pair
   (set-up ⇄ profile view). Same function, same clothes (founder 2026-07-16 —
   the pair strip wearing the view-tab register was the drift). */
.mh-nav { display: flex; align-items: baseline; gap: calc(var(--sp) * 2.25); min-width: 0; overflow: hidden; }
.mh-nav a { font-size: var(--fs-nav); line-height: 1; color: var(--faint, #8b939b); text-decoration: none; letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap; }
.mh-nav a:hover { color: var(--dim, #59626a); }
.mh-nav a.on { color: var(--ink, #23282d); }
/* the active console's PLATE TABS (only Simulation uses this) ride the sub-nav
   after the switcher — LOWERCASE + tight (a register apart from the UPPERCASE
   switcher), clearly spaced from the switcher, wrapping UNDER the first tab and
   never back to the page margin (founder 2026-07-13). */
/* NO slot margin (plumb-line law, founder catch 2026-07-16): when the slot
   leads the band (the manual pair nav) its content sits ON the plumb line;
   separation from the switcher is the right-seated tab strip's own doing. */
.mh-subtabs { display: flex; align-items: baseline; flex: 1 1 auto; min-width: 0; }
.mh-subtabs:empty { display: none; }
/* THE SLOT CONTRACT (SPEC §4, one home 2026-07-15): a console's plate-tab strip
   marks itself data-rides-subnav — HIDDEN until its script relocates it into
   this slot (no pre-script flash), then laid out and registered HERE.
   THE VIEW-TAB REGISTER (founder redesign 2026-07-16): view selection, not
   navigation — so it reads a register APART from the uppercase switcher:
   lowercase, unnumbered (the drawing-set numbers were scaffolding), and seated
   at the band's END — left answers "where am I", right answers "which view". */
.tabs[data-rides-subnav] { display: none; }
.mh-subtabs .tabs, .mh-subtabs .tabs[data-rides-subnav] { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-end; gap: 4px clamp(12px, 2.5vw, 20px); padding: 0; background: none; margin: 0 0 0 auto; }
/* the underline register (padding + transparent rule) never moves the TEXT
   baseline — align-items:baseline aligns type, not boxes — so the tabs sit on
   the switcher's line while the active tab keeps its drawn rule */
.mh-subtabs .tabs .tab { font-size: var(--fs-tab); letter-spacing: 0.01em; text-transform: lowercase; color: var(--faint, #8b939b); background: none; border: none; border-bottom: 2px solid transparent; padding: 0 0 calc(var(--sp) / 2); font-family: inherit; cursor: pointer; } /* chrome-scan: justified — underline register (VID-004 §3 tab rule), not a separator */
.mh-subtabs .tabs .tab:hover { color: var(--dim, #59626a); border-color: var(--line, #d7dce1); }
.mh-subtabs .tabs .tab.active { color: var(--ink, #23282d); border-color: var(--ink, #23282d); }
/* a tab may be a LINK to a sibling page of the same group (the manual pair) */
.mh-subtabs .tabs a.tab { text-decoration: none; }

/* (row-state 60·80 styling lives in part B §10 — ONE home; it was
   duplicated here until 2026-07-15. The control itself is Setup work-surface
   furniture, never chrome.) */

/* ═══ 6 · THE READBACK ZONE ═══ persistent readback · light-grey · no line ══
   The band above the footer (founder template 2026-07-15): PERSISTENT READBACK
   — verdict strips, status metrics, store state. FIXED GROUND: the fill and
   the ink set are theme-independent; anything mounted here (verdict strip,
   platekey, status metrics) reads the BAND's tokens, so a chrome vein can
   never push an unreadable palette onto the grey. Ink pairs measured on
   #f7fafb: --info-ink 10.3:1 · --info-dim 7.0:1 (§15 Law B); signal colours
   are the arctic set (recorded light-ground palette). */
.readback, body[data-chrome] .readback {
  /* chrome-scan: fixed-ground — the ONE lawful re-pin of vein tokens: the band
     is FIXED GROUND by ruling (founder 2026-07-15); a chrome vein must never
     push an unreadable palette onto the grey (the seam law's declared case) */
  grid-column: 1 / -1; min-height: var(--band); display: flex; align-items: center;
  gap: clamp(12px, 2.5vw, 24px); padding: 0 var(--edge); border: none;
  background: var(--fill-secondary); color: var(--info-dim);
  font-size: 13px; letter-spacing: 0.04em;
  --bg: transparent; --panel: transparent;
  --ink: #23282d; --dim: #565b61; --faint: #7a828a;
  --line: #d7dce1; --line-soft: #e2e6ea;
  --ok: #2f8a5f; --warn: #96690f; --bad: #b23f36; --blue: #2f7fc2;
  --label-value: #23282d; --label-name: #6e767e; --witness: #7a828a;
}
.readback .band-strong, body[data-chrome] .readback .band-strong { color: var(--info-ink); letter-spacing: 0.12em; text-transform: uppercase; }
.readback .right { margin-left: auto; text-align: right; }
/* a mounted verdict strip fills the band and drops its own ground + edge
   padding (the band already carries both) — one strip, any console, any vein */
.readback #verdict, body[data-chrome] .readback #verdict { background: transparent; padding-inline: 0; flex: 1 1 auto; min-width: 0; }

/* ═══ 7 · THE FOOTER ZONE ═══ black band, --band tall, safe-area aware ═════
   CONTENT SWITCHES (founder template 2026-07-15): the trading line (©) is the
   DEFAULT — masthead.js renders it into an EMPTY #houseband mount; a page that
   needs the space for info display (the HMI consoles — space at a premium)
   supplies its own line and the copyright yields. */
.blackband { background: var(--fill-primary); grid-column: 1 / -1; line-height: 1; min-height: var(--band); display: flex; align-items: center; gap: clamp(12px, 2.5vw, 24px); padding: 0 var(--edge); padding-left: max(var(--edge), env(safe-area-inset-left)); padding-right: max(var(--edge), env(safe-area-inset-right)); padding-bottom: env(safe-area-inset-bottom); }
.blackband .tl { color: #c7ccd1; font-size: 13px; letter-spacing: 0.015em; line-height: 1; }
/* ICD-003 B-2 — THE BRAND-NAME LAW. Wherever the customer's brand name is TYPED
   (as opposed to drawn as the mark) it is lowercase and BOLD. Explicit weight,
   not the UA's default <b>: 700 is the weight our stack maps to UniversCom 65
   Bold, so the rule resolves to the corporate face rather than a synthesised
   one. The name itself never appears in this stylesheet — the face supplies it. */
.brandname { font-weight: 700; }
/* a band link (e.g. the deployed runsheet) rides the same register — quiet,
   underlined only on gesture */
.blackband a.tl { text-decoration: none; }
.blackband a.tl:hover { text-decoration: underline; color: #eef1f3; }
/* the info-display register on black — measured: #eef1f3 ≈ 17.9:1, #c7ccd1 ≈ 12.4:1 */
.blackband .band-strong { color: #eef1f3; font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase; }
.blackband span { color: #c7ccd1; font-size: 13px; letter-spacing: 0.015em; line-height: 1; }
.blackband .right { margin-left: auto; text-align: right; }

/* ═══ 8 · RESPONSIVE ═══════════════════════════════════════════════════════ */
/* THE LOCKUP NEVER AMPUTATES (founder 2026-07-13): the word + superscript ride
   the mark at every width. The identity is never dropped to save space — if
   space is ever truly tight the type SCALES. (The old `.mh-cap{display:none}`
   below 560px was the drift that left the deployed phone showing a bare "W".) */
@media (max-width: 380px) { .mh-cap { font-size: 12px; } .mh-sup { font-size: 15px; } }
/* narrow screens: the info bands wrap WHOLE ITEMS into rows (baseline law —
   an item must never wrap inside itself beside its siblings); the long .right
   note takes its own row. The bands grow; the zone law's min-height stands. */
@media (max-width: 900px) {
  .readback, .blackband { flex-wrap: wrap; row-gap: var(--sp); padding-block: 10px; }
  .readback .right, .blackband .right { margin-left: 0; text-align: left; flex-basis: 100%; }
}

/* ════════════════════════ PART B — THE CONSOLE CHROME ══════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   CONSOLE CHROME  ·  the shared operator-console block (build once, consume
   everywhere — see hmi/CHROME_BLOCKS.md). PART B of house.css (was linked
   AFTER masthead.css by every console — the fold preserves that order); each
   page's inline <style> then carries ONLY its own surface.
   Renovate HERE; never re-implement per console.

   Sections: 1 TOKENS · 2 BASE · 3 FORM CONTROLS · 4 VERDICT STRIP · 5 PLATE
             KEY · 6 TABS · 7 SHEET · 8 STORE VIEW · 9 SIGNALS · 10 ROW-STATE ·
             11 SOLVING OVERLAY · 12 CHROME VEINS · 13 RESPONSIVE
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══ 1 · TOKENS ═══ VID-001/002 recorded palette (no new colour without a ratio) */
:root {
  --bg: #0e0f11; --panel: #141517; --line: #26282c; --line-soft: #1c1e21;
  --ink: #f2f3f4; --dim: #9aa0a7; --faint: #818790;
  --blue: #5cc8ff; --ok: #4cc38a; --bad: #ef5350; --warn: #d9a53f;
  --chrome: #6f7887; --wire: #aab2c0; --hinge-ref: #5b6472; --witness: #5d6674;
  --glass-ext: #2f7fb0; --motor: #d7dbe2; --label-value: #e8eaee; --label-name: #8a9099;
  /* BRF-007 W2 SPLIT ALIASES — the split sites (composition.js:324 object edge ·
     field.js:848 glass-extent line) consume these ROLES on every vein; here they
     alias THIS vein's own --chrome/--glass-ext values byte-for-byte. Render-
     preserving, not a CI mapping — only arctic DERIVES them (generated region). */
  --object-line: #6f7887; --glass-ext-line: #2f7fb0;
  --fs-micro: 11px; --fs-label: 12px; --fs-base: 13px; --fs-strong: 14px;
  /* --ctrl-h: ONE control height, every field/select/button (founder
     2026-07-23 — the token had been declared and consumed by NOTHING while
     the base rule hardcoded 26px; set to the lived value, retune in ONE
     place). --ctrl-w retired the same day: widths are PER-BAND family
     tokens sized by the widest member, never one global number. */
  --sp: 8px; --ctrl-h: 26px; --r: 4px;
  /* THE MEASURE LAW (founder 2026-07-23: clamp the horizontal sprawl): data
     ranks set their own extent BY CONSTRUCTION (max-content tables, band
     width tokens, fit-content controls); EXPLANATORY TEXT never sprawls
     past the reading measure. One token, every surface. */
  --measure-prose: 84ch;
}

/* ═══ 2 · BASE ═══ the console voice (the grid scaffold stays per-console) ═══ */
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: "UniversCom", "Helvetica Now Text", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: var(--fs-base); font-variant-numeric: tabular-nums;
}

/* ═══ 3 · FORM CONTROLS ═══ inputs · selects · custom arrow ═════════════════ */
/* THE CONTROL FAMILY LAW (founder 2026-07-23): every field, select and
   button shares ONE height (--ctrl-h); widths are per-band family tokens
   sized by the band's widest member (see each band's own declaration). */
input, select {
  background: var(--bg); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r);
  font: inherit; font-size: var(--fs-label); height: var(--ctrl-h); padding: 0 var(--sp); font-variant-numeric: tabular-nums;
}
input:focus, select:focus { outline: none; border-color: var(--dim); }
input[type="number"] { text-align: right; -moz-appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
::placeholder { color: var(--faint); opacity: 1; }
input[type="checkbox"] { accent-color: var(--blue); width: 15px; height: 15px; }
.btn { background: none; border: 1px solid var(--line); border-radius: var(--r); color: var(--dim); font: inherit; font-size: var(--fs-label); padding: 0 calc(var(--sp) * 1.5); height: var(--ctrl-h); cursor: pointer; white-space: nowrap; }
.btn:hover { border-color: var(--dim); color: var(--ink); }
.btn.primary { border-color: var(--blue); color: var(--blue); }
.btn[disabled] { opacity: 0.4; cursor: default; }
.btn.mini { padding: 2px 8px; font-size: var(--fs-micro); height: auto; } /* the mini family sizes to itself — a distinct family, not an exception */ /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
/* numeric mm fields: ONE family width — the minimum a 4-digit value + spinner
   requires (founder 2026-07-22: fields in a family standardise to minimum
   required width; the scattered inline 70px hardcodes died here) */
input.mm { width: 76px; }
/* THE CORNER INSTRUMENT (founder 2026-07-23: one curvature, many consumers):
   every rounded element carries CONTINUOUS curvature (squircle), never a
   circular arc — one declaration, the radius stays each family's token.
   Native corner-shape (Chrome 139+); an engine without it ignores the line
   and falls back to arcs — honest degradation, no shim. */
input, select, .btn, .verdict, .card, .card h3 .b, #solving .card, #solving .card2 { corner-shape: squircle; }
/* .meter stays an arc: a 3px bar's 2px rounding is the bar instrument's own
   anatomy, not a corner family (coherence pass 2026-07-23) */
/* ═══ 3b · THE METER ═══ the ONE thin-bar instrument (founder class ruling
   2026-07-16: a win extends across the whole HMI — the manual tool's budget
   bar, the Results utilisation bars and the solve progress are the SAME
   instrument). Track + fill; states tint the fill (on the meter or the fill);
   accent = the action colour (progress). ═══════════════════════════════════ */
.meter { height: 3px; background: var(--line-soft); border-radius: 2px; overflow: hidden; }
.meter > div { height: 100%; width: 0; background: var(--dim); }
.meter.accent > div { background: var(--blue); }
.meter.warn > div, .meter > div.warn { background: var(--warn); }
.meter.over > div, .meter > div.over { background: var(--bad); }

/* segmented toggles (auto|primary|secondary, run-type …) — typographic, no boxes */
.segs { display: inline-flex; gap: calc(var(--sp) * 1.5); align-items: baseline; }
.segs button { background: none; border: none; border-bottom: 2px solid transparent; color: var(--faint); font: inherit; font-size: var(--fs-micro); letter-spacing: 0.1em; text-transform: uppercase; cursor: pointer; padding: 0 0 3px; white-space: nowrap; } /* chrome-scan: justified — underline register */ /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.segs button:hover { color: var(--dim); border-color: var(--line); }
.segs button.on { color: var(--ink); border-color: var(--ink); }

/* ═══ 4 · VERDICT STRIP ═══ .met/.advband split (VID-003), no line ══════════ */
#verdict {
  padding: var(--sp) var(--edge);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--sp) * 3);
  min-height: 44px; background: var(--panel);
}
/* THE VERDICT PILL — the ONE verdict register on every surface (S1 close,
   2026-07-16, founder latitude: the classic's pill — the image-1 good
   example — wins; the bordered badge retires). States tint the pill; idle
   stays quiet. The classic writes the same classes — one implementation. */
.verdict { font-weight: 600; padding: calc(var(--sp) / 2) calc(var(--sp) * 1.5); border-radius: 999px; font-size: var(--fs-label); letter-spacing: 0.06em; background: color-mix(in srgb, var(--faint) 14%, transparent); color: var(--dim); white-space: nowrap; }
.verdict.ok { background: rgba(76, 195, 138, 0.12); color: var(--ok); }
.verdict.warn { background: rgba(255, 167, 38, 0.12); color: var(--warn); }
.verdict.bad { background: rgba(239, 83, 80, 0.12); color: var(--bad); }
.verdict.busy { background: rgba(217, 165, 63, 0.12); color: var(--warn); }
.met { display: flex; flex-direction: column; gap: 1px; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.met .v { color: var(--label-value); font-size: var(--fs-strong); }
.met .k { color: var(--label-name); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; }
#posemeta { flex-basis: 100%; color: var(--dim); font-size: var(--fs-micro); letter-spacing: 0.03em; }
#posemeta:empty { display: none; }
#advband { flex-basis: 100%; color: var(--warn); font-size: var(--fs-micro); line-height: 1.5; }
#advband:empty { display: none; }
/* THE STATE BANDS + THE ANCHORED KEY (founder kind-order law 2026-07-22): the
   strip carries two KINDS — state content (pose metadata · advisories) and the
   REPEATING key line, the same furniture on every console. State renders
   ABOVE; the key is the section's FLOOR. THE SOLVE-NOTES FOLD (founder, same
   day): pose + advisories are second-class next to the metrics row — they
   fold under the house toggle so the work surface breathes, collapsed by
   default. NEVER SILENT: stop-class lines render even collapsed (a refusal
   is never hidden; cautions keep their anchored home in the flagged key
   rows). Open, the region keeps the band minimum (pose + two advisory
   lines, token-derived) so the key holds its position between states. */
#statebands { flex-basis: 100%; }
#statebands:not(.notes-collapsed) { min-height: calc(3 * 1.5 * var(--fs-micro)); }
#statebands .pkx { display: block; padding: 0 0 2px; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
/* FOLD-ALL (founder ruling 2026-07-22 eve, supersedes the stop-lines-stay
   form): collapsed hides EVERY note — the never-silent trace moves UP: the
   verdict badge carries the stop, and the fold toggle carries severity
   count chips (.schip, the one severity-chip grammar). */
#statebands.notes-collapsed #posemeta { display: none; }
#statebands.notes-collapsed #advband { display: none; }
#statebands .pkx .schip { margin-left: calc(var(--sp) * 1.25); }
/* THE METRICS ROW — the section's ANCHORED FLOOR (founder, corrected at the
   fourth catch 2026-07-22: the repeating instrument is THIS row — the same
   badge + readouts, the same place on every console, directly above the black
   band; the key sits above it, state bands above that). Its own wrapping line
   at the strip's end. */
#metsrow { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--sp) * 3); }
/* in-strip, the strip's own gap IS the rhythm — the legend class's stand-alone
   margin doubled it into dead space between state and key (founder refine
   2026-07-22, image 1) */
#verdict .platekey { margin-top: 0; }
/* THE SOLVE-STATE SECTION (W5 sole-occupancy directive, founder 2026-07-22):
   the readback band's SOLE OCCUPANT is the metrics row; state + key live
   HERE — page ground, DIRECTLY above the band, carried by POSITION and
   REGISTER with the key line as this section's floor. No fill, no line —
   the zone grammar's own means. */
#solvestate { padding: calc(var(--sp) * 1.25) var(--edge) var(--sp); }
#solvestate:empty { display: none; }
#solvestate .platekey { margin-top: 0; }
#solvestate #statebands { margin-bottom: var(--sp); }

/* ═══ 4b · LITE CARDS ═══ the Results register (founder redesign 2026-07-15):
   one card per lite — parameters · verdict · METRIC ROWS with utilisation bars
   (value against its own limit; severities from the signal law) · advisories ·
   per-lite export. Shared block: Setup's dormant twin + Results consume it. ═══ */
#lites { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: calc(var(--sp) * 1.25); align-content: start; }
.card { border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); padding: calc(var(--sp) * 1.25) calc(var(--sp) * 1.5); }
.card h3 { margin: 0 0 calc(var(--sp) / 2); font-size: var(--fs-label); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dim); display: flex; gap: calc(var(--sp) * 1.25); align-items: baseline; }
.card h3 .b { font-size: var(--fs-micro); letter-spacing: 0.12em; padding: 2px 8px; border: 1px solid var(--line); border-radius: var(--r); margin-left: auto; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.card h3 .b.ok { color: var(--ok); border-color: var(--ok); }
.card h3 .b.bad { color: var(--bad); border-color: var(--bad); }
.card .param { color: var(--faint); font-size: var(--fs-micro); letter-spacing: 0.02em; margin: 0 0 var(--sp); }
/* the card's metric rows consume the ONE key/value grammar (founder
   2026-07-23: no card-local forms — the eye TUNES, it never gates the
   system): rows are .k/.kt/.kd on the defs column, the meter rides the
   value column, severity speaks the component's flagged classes. The old
   .mrow/.mk/.mv grammar is dead and resurrection-barred. */
.card .mrows { display: grid; gap: 5px; margin: var(--sp) 0; --defs-key-w: 56px; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.card .mrows .kd { font-size: var(--fs-label); }
.card .mrows .kd i { font-style: normal; color: var(--label-name); font-size: var(--fs-micro); }
/* the utilisation bar IS the house meter (§3b) — only its seat in the row
   grid is card-owned; the row's state tints the fill */
.card .mrows .k .meter { grid-column: 2; margin-top: 2px; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.card .k.flagged.sig-caution .meter > div { background: var(--warn); }
.card .k.flagged.sig-stop .meter > div { background: var(--bad); }
.card .k.flagged.sig-stop .kd { color: var(--bad); }
.card .adv { color: var(--warn); font-size: var(--fs-micro); line-height: 1.45; margin: var(--sp) 0; }
.card .adv:empty { display: none; }

/* ═══ 5 · PLATE KEY ═══ WO-2 caption-band legend + WO-5 verdict key ═════════ */
/* separation by SPACING, never a line — the border-top stroke stood in for a
   kind boundary and left at the founder's finding 2026-07-22 (zone law: bands
   never carry lines; the key is furniture and earns clear air instead). */
.platekey { display: flex; flex-wrap: wrap; column-gap: calc(var(--sp) * 3.5); row-gap: var(--sp); margin-top: 2calc(var(--sp) / 2); }
.platekey:empty { display: none; }
.platekey .k { display: inline-flex; gap: var(--sp); align-items: baseline; font-size: var(--fs-micro); line-height: 1.4; min-width: 0; }
.platekey .kt { color: var(--label-value); font-weight: 600; white-space: nowrap; }
.platekey .kd { color: var(--label-name); }
/* flagged severity is the COMPONENT's (one grammar — platekey, cards,
   annexes all consume; founder 2026-07-23) */
.k.flagged .kd { color: var(--label-value); }
.k.flagged.sig-caution .kt { color: var(--warn); }
.k.flagged.sig-stop .kt { color: var(--bad); }
#verdict-key { flex-basis: 100%; }
#verdict-key .keyline { display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--sp) * 0.5) calc(var(--sp) * 2.25); }
/* the keyline's toggle is the house .pkx component (one toggle, every fold) */
#verdict-key .keyline .kt { cursor: help; }
#verdict-key .keyline .kt.sig-stop { color: var(--bad); }
#verdict-key .keyline .kt.sig-caution { color: var(--warn); }
/* the study grid renders ABOVE the chip strip (founder kind-order law
   2026-07-22: detail/state content above; the repeating key line is the
   section's anchored floor — nothing renders below it). Full-basis keeps the
   grid on its own flex line — without it the two registers shared one
   accidental line with a 3px baseline mismatch (measured 16.07). */
/* the study grid's rows are the defs column (one treatment — see §4c);
   here only its seat in the flex host — BENEATH its keyline (the fold
   grammar, founder 2026-07-23: items open after the header, everywhere) */
#verdict-key .keygrid { flex-basis: 100%; margin-top: var(--sp); }

/* ═══ 6 · TABS ═══ drawing-sheet tabs, typographic (Simulation relocates its
   set into the sub-nav via part A §5; the base register lives here) ══════════ */
.tabs { display: flex; align-items: baseline; gap: 2calc(var(--sp) / 2); padding: calc(var(--sp) * 1.5) var(--edge) 0; background: var(--bg); }
.tabs .tab { background: none; border: none; border-bottom: 2px solid transparent; color: var(--faint); font: inherit; font-size: var(--fs-micro); letter-spacing: 0.14em; text-transform: uppercase; padding: 0 0 9px; cursor: pointer; } /* chrome-scan: justified — underline register (VID-004 §3) */ /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.tabs .tab:hover { color: var(--dim); border-color: var(--line); }
.tabs .tab.active { color: var(--ink); border-color: var(--ink); }

/* ═══ 7 · SHEET ═══ the content plate + its heading + scroll stage ══════════ */
.sheet { background: var(--bg); position: relative; display: flex; flex-direction: column; min-height: 0; }
.sheet > h2 { margin: 0; padding: var(--sp) var(--edge) calc(var(--sp) * 0.75); font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); display: flex; align-items: center; gap: calc(var(--sp) * 1.5); }
.sheet > h2 .hint { text-transform: none; letter-spacing: 0.02em; color: var(--witness); font-weight: 400; }
.sheet .stage { flex: 1; min-height: 0; overflow: auto; padding: calc(var(--sp) / 2) var(--edge) calc(var(--sp) * 1.5); }
.note { font-size: var(--fs-micro); color: var(--faint); line-height: 1.5; margin: var(--sp) 0 0; }
/* THE PLATE ANNEX (founder redesign 2026-07-22): the canvas runs FULL HEIGHT;
   the plate's readouts (keys left · values right) and its key share TWO
   aligned columns and ONE quiet register beside it — no bold, no caps —
   wrapping under at the breakpoint. The annex SCROLLS when the key expands:
   the canvas never rescales for a key. The plate key's state is its own
   (esg05-platekey), independent of the strip key. */
.with-annex { display: flex; flex-direction: column; gap: calc(var(--sp) * 1.25); min-height: 0; }
.with-annex.annex-side { flex-direction: row; gap: calc(var(--sp) * 2.25); align-items: stretch; position: relative; }
.plate-canvas { flex: 1 1 auto; min-width: 0; min-height: 0; }
/* wrapped-under, the height-anchored canvas HOLDS (viewer-stability law) —
   the annex flows beneath and scrolls; only the canvas's width flexes */
.with-annex:not(.annex-side) .plate-canvas { flex: 0 0 auto; }
/* ═══ 4c · THE DEFS COLUMN + THE FOLD TOGGLE ═══ (founder 2026-07-22): every
   definition list — plate readouts, plate key, the page key's study grid, the
   setup build sheet — is ONE treatment consuming the ONE key/value grammar
   (keys.js keyRow: .k > .kt + .kd). Keys right-justified toward their values,
   plain weight, no caps; values carry the payload colour; the key column is a
   token each context tunes. Declared AFTER the .platekey rules: the tie-break
   override IS the mechanism (the inline chip form yields to the column
   wherever a host declares .defs-col). Flagged rows keep their signal colours
   (higher specificity, §5). */
.defs-col { display: block; --defs-key-w: 110px; }
.defs-col .k { display: grid; grid-template-columns: var(--defs-key-w) 1fr; column-gap: 10px; align-items: baseline; padding: 1px 0; font-size: var(--fs-micro); line-height: 1.5; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.defs-col .kt { text-align: right; font-weight: 400; white-space: normal; color: var(--label-name); }
.defs-col .kd { color: var(--label-value); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* ONE fold toggle (the strip key, the plate key, the solve notes): contexts
   add placement only, never re-declare the component */
.pkx { background: none; border: none; padding: 0; font: inherit; font-size: var(--fs-micro); letter-spacing: 0.08em; color: var(--blue); font-weight: 600; cursor: pointer; }

.plate-annex { flex: 0 0 auto; min-height: 0; overflow-y: auto; font-size: var(--fs-micro); line-height: 1.5; padding: calc(var(--sp) / 2) 0; --defs-key-w: 84px; }
.annex-side .plate-annex { flex: 0 0 236px; }
/* THE CENTRE LAW (founder 2026-07-23, codified — the door's language): the
   side-seated annex centres on the section's vertical axis; at overflow it
   fills the section and scrolls. FIX 2026-07-24: max-height:100% was CIRCULAR
   under align-items:stretch — the annex's own tall content set the flex line it
   was meant to cap to, so a short primary STRETCHED to the tall annex and left
   an undesigned gap. Absolute-positioned so the annex's height never drives the
   section: the seat takes the PRIMARY's height, the annex fills it (top/bottom
   0), centres its content while it fits (justify: safe center) and scrolls once
   it overflows. */
.annex-side .plate-annex { position: absolute; top: 0; right: 0; bottom: 0; width: 236px; display: flex; flex-direction: column; justify-content: safe center; }
.annex-side .plate-canvas { margin-right: calc(236px + var(--sp) * 2.25); }
.plate-annex .pkx { padding: 0 0 calc(var(--sp) / 2); }
/* THE FREE-EXPANSION REST (founder 2026-07-23, codified — keys.js annexRest
   carries the rule): .folded is the closed paint on EACH fold block —
   readouts and key are sibling folds with independent states (founder
   2026-07-23: the readouts are a key too). Markup always renders in full so
   the vocabulary scan keeps every watched writer's literal in sight. */
.annex-fold.folded .k { display: none; }
.plate-annex .annex-fold + .annex-fold { margin-top: calc(var(--sp) * 1.25); }

/* ═══ 7b · THE WORKFLOW REGISTER ═══ the set-up sheet's stage grammar
   (worksheet.js — unification S1): numbered steps light as the flow advances;
   a LATENT stage exists but hasn't opened on this surface (the door's grey
   law). Shared: auto Setup + the manual set-up page. ═══════════════════════ */
/* THE STAGE RHYTHM (founder 2026-07-23, sheet-wide: one stage treated and
   the next untreated was the lived defect) — every stage clearance is a
   --sp multiple, house-declared so Setup and the manual pair breathe alike */
.step { font-size: var(--fs-micro); letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); margin: calc(var(--sp) * 2.5) 0 calc(var(--sp) * 1.25); }
.step:first-child { margin-top: calc(var(--sp) / 2); }
/* THE STAGE FOLD (founder 2026-07-23): the step line is the stage's fold
   header — same .pkx grammar as every fold; the body folds beneath it.
   Consoles drive the workflow REST (worksheet.js stageRest); the operator's
   toggle overrides, persisted. The last body ends in tokened clearance so
   the fully-scrolled rest is designed. */
.step .pkx { margin-right: calc(var(--sp) * 0.75); }
.step .stephead .segs { margin-left: calc(var(--sp) * 2); }
/* THE STAGE BODY OWNS THE VERTICAL RHYTHM (founder 2026-07-24: the section
   touched with NO clearance — the solverow and the jobstrip met at 0px because
   the gap lived in scattered per-element margins and one was simply missing).
   The container carries ONE gap; every child block is spaced by construction, so
   no element can be missed and none can collide. Child vertical margins are
   zeroed here so the gap is the SOLE source (flex gaps do not collapse). */
.stagebody { display: flex; flex-direction: column; gap: calc(var(--sp) * 2); }
.stagebody[data-stage] > * { margin-block: 0 !important; } /* the container OWNS the vertical rhythm: children carry NO vertical margin so the gap is the sole source. !important is the structural invariant — it must win over any page-inline or id-scoped child margin (main .note, #stackseat, the manual console's tuned margins), which would otherwise double the gap. Deliberate larger breaks are explicit exceptions, not accidental sums. */
.stagebody.folded { display: none; }
.stagebody:last-of-type { margin-bottom: calc(var(--sp) * 3); }
.step .stepno { font-weight: 600; margin-right: calc(var(--sp) * 1.25); }
.step.ready { color: var(--ink); }
.step.latent, .step.latent .stepno { color: var(--latent, #b9c0c7); }
.hint.stage-latent { color: var(--latent, #b9c0c7); }
.solverow { display: flex; align-items: baseline; gap: calc(var(--sp) * 2); --action-w: calc(var(--sp) * 13); }
/* THE STAGE-ACTION BUTTON FAMILY (control-family law §3, founder 2026-07-24):
   the primary action in a solverow ("simulate unit" · "export the set" …) shares
   ONE width token sized to the widest member — a min-width, so the family aligns
   into a consistent action column down the workflow (and the hints align with
   it) while a future longer label grows rather than truncating. Other button
   families (+ lite, the row minis) size to their own content. */
.solverow .btn { min-width: var(--action-w); }
.hint.prose { line-height: 1.6; } /* running-prose hints (release notes) — one variant, house-declared */
.note, .hint.prose, .hint.stage-latent { max-width: var(--measure-prose); } /* the measure law */

/* ═══ 8 · STORE VIEW ═══ the store table, shared board + consoles ═══════════ */
.storeview { display: grid; gap: calc(var(--sp) * 1.25); margin-bottom: calc(var(--sp) * 2); }
.storehead .k { font-weight: 600; }
.storeview button { font: inherit; padding: 2px 10px; } /* rhythm: justified — sub-grid structural anatomy (control/hairline padding), not inter-element rhythm */
.intakezone { border: 1.5px dashed var(--line); padding: calc(var(--sp) * 1.25) calc(var(--sp) * 1.5); }
.intakezone.over { border-color: var(--blue); }
.storetable { border-collapse: collapse; width: 100%; }
.storetable th, .storetable td { text-align: left; padding: calc(var(--sp) / 2) calc(var(--sp) * 1.5) calc(var(--sp) / 2) 0; border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; } /* chrome-scan: justified — table row rules, tabular grammar */
.storetable th { font-weight: 600; }
.storerow { cursor: pointer; }
.storerow:hover td { background: color-mix(in srgb, var(--line) 18%, transparent); }
.jobid { font-weight: 600; }
.schip.sig-stop { color: var(--bad); font-weight: 700; }
.schip.sig-caution { color: var(--warn); }
.storedetail > td { padding: var(--sp) 0 calc(var(--sp) * 1.75); }
.detailgrid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(var(--sp) * 2.25); margin-bottom: var(--sp); }
.storeview .k.head { font-weight: 600; margin-bottom: calc(var(--sp) / 2); }
.storeview .dim { color: var(--dim); }

/* ═══ 9 · SIGNALS ═══ SES-030l symbol-led, colour-bound ════════════════════ */
.sigline { font-size: var(--fs-micro); line-height: 1.7; }
/* advisory lines carry their severity in the INK (founder 2026-07-22: the
   lines rendered classless-grey). stop/caution take the signal colours;
   adjust (→ guidance) and action (▸ offer) stay in the quiet register by
   design — guidance is not an alarm. */
.sigline.sig-stop { color: var(--bad); font-weight: 600; }
.sigline.sig-caution { color: var(--warn); }
.sig-stop { color: var(--bad); }
.sig-caution { color: var(--warn); }
.sig-adjust { color: var(--dim); }
.sig-action { color: var(--blue); font-weight: 600; }

/* ═══ 10 · ROW-STATE ═══ 60 · 80 (hosted inside the Setup work surface; the
   markup renders from rowstate.js — ONE source, ONE style home) ═════════════ */
#rowswitch { display: inline-flex; gap: var(--sp); font-size: 13px; line-height: 1; }
#rowswitch .rows { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; font-size: 13px; line-height: 1; color: var(--faint); }
#rowswitch .rows:hover { color: var(--dim); }
#rowswitch .rows.on { color: var(--ink); font-weight: 700; }

/* ═══ 10b · DROP OVERLAY ═══ one implementation; the page states its hint via
   --drop-hint (what happens to the dropped design on THIS console) ═══════════ */
body.dropping::after {
  content: var(--drop-hint, "drop .obj / .stl"); position: fixed; inset: 10px;
  display: flex; align-items: center; justify-content: center; z-index: 20;
  border: 1px dashed var(--dim); background: rgba(14,15,17,0.8);
  color: var(--ink); font-size: var(--fs-strong); letter-spacing: 0.1em; pointer-events: none;
}

/* ═══ 11b · EXPORT GATES ═══ FR-210/211 prompts that block, decisions that
   become records — shared: Setup exports the set, Results exports per lite ══ */
#gates { border: 1px solid var(--line); background: var(--panel); color: var(--ink); padding: 0; max-width: 560px; }
#gates::backdrop { background: rgba(10,11,13,0.55); }
#gates .g-head { padding: calc(var(--sp) * 1.25) calc(var(--sp) * 1.75); border-bottom: 1px solid var(--line); font-size: var(--fs-label); letter-spacing: 0.16em; text-transform: uppercase; color: var(--dim); } /* chrome-scan: justified — dialog anatomy (modal frame) */
#gates .g-body { padding: calc(var(--sp) * 1.5) calc(var(--sp) * 1.75); display: grid; gap: calc(var(--sp) * 1.5); font-size: var(--fs-micro); }
#gates .g-gate { border: 1px solid var(--line); padding: calc(var(--sp) * 1.25); display: grid; gap: calc(var(--sp) * 0.75); }
#gates .g-gate h4 { margin: 0; font-size: var(--fs-micro); letter-spacing: 0.12em; text-transform: uppercase; color: var(--dim); }
#gates .g-ok { color: var(--ok, #3f8f5f); }
#gates .g-bad { color: var(--bad); }
#gates .g-foot { padding: calc(var(--sp) * 1.25) calc(var(--sp) * 1.75); border-top: 1px solid var(--line); display: flex; gap: var(--sp); justify-content: flex-end; } /* chrome-scan: justified — dialog anatomy (modal frame) */
#gates input[type="text"] { width: 90px; }

/* ═══ 11 · SOLVING OVERLAY ═══ the mid-solve modal + progress ══════════════ */
#solving { position: fixed; inset: 0; display: none; align-items: center; justify-content: center; background: rgba(14,15,17,0.72); z-index: 10; }
#solving.on { display: flex; }
#solving .card, #solving .card2 { border: 1px solid var(--line); background: var(--panel); border-radius: var(--r); padding: calc(var(--sp) * 2.25) calc(var(--sp) * 3.25); color: var(--dim); font-size: var(--fs-label); letter-spacing: 0.08em; min-width: 340px; }
/* the progress bar IS the house meter (§3b, accent) — only its overlay
   spacing and the live width transition are its own */
#progress-track { margin-top: calc(var(--sp) * 1.5); }
#progress-fill { transition: width 0.15s; }
#progress-label { display: block; margin-top: var(--sp); color: var(--faint); font-size: var(--fs-micro); font-variant-numeric: tabular-nums; }

/* ═══ 12 · CHROME VEINS ═══ palette overrides; the geometry reads the vars ══
   Redefining the palette re-skins the whole drawing — no per-element JS. ════ */
body[data-chrome="blueprint"] {
  --bg: #0c2c52; --panel: #0e3059; --line: #35608f; --line-soft: #1e426e;
  --ink: #eef5ff; --dim: #a9c6e8; --faint: #7ba0cc;
  --blue: #ffffff; --glass-ext: #b9d6f4;
  --object-line: #7ba6d6; --glass-ext-line: #b9d6f4; /* W2 split aliases — this vein's own --chrome/--glass-ext values (render-preserving) */
  --chrome: #7ba6d6; --wire: #e6f0ff; --hinge-ref: #6f97c8; --witness: #6f97c8;
  --motor: #eef5ff; --label-value: #ffffff; --label-name: #a9c6e8;
  --ok: #86e0ad; --warn: #ffd166; --bad: #ff8f84;
  color: var(--ink);
  background: radial-gradient(130% 100% at 50% -10%, #123a66 0%, #0a2749 62%, #08203e 100%);
}
/* verdict + footer grounds left the veins 2026-07-15: the READBACK BAND
   (part A §6) is fixed ground — the strip rides it on every console.
   THE HEADER GROUP IS ONE SURFACE (founder 2026-07-15): the sub-nav band
   carries the masthead's fill on every vein — it must never read as content. */
body[data-chrome="blueprint"] header,
body[data-chrome="blueprint"] #subnav,
body[data-chrome="blueprint"] #controls { background: #0d2f58; }
body[data-chrome="blueprint"] main {
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 26px 26px;
}
body[data-chrome="blueprint"] header h1 { letter-spacing: 0.34em; }
/* the frame stays dead (separator law) — but blueprint's plate ground IS the
   gridded field, painted on main under a TRANSPARENT plate (S-era layering; an
   opaque fill buries the grid — lived, fifth catch 2026-07-22). Restored
   transparent; the layering itself is named debt in BRF-007 §6: a vein's
   plate-ground belongs to the SHEET, not the page region. */
body[data-chrome="blueprint"] .sheet { background: transparent; }

body[data-chrome="drafting"] {
  --bg: #eae5d9; --panel: #e5e0d3; --line: #cabf9f; --line-soft: #d8d0bd;
  --ink: #2a251d; --dim: #6a6151; --faint: #948a76;
  --blue: #1d3f5e; --glass-ext: #7a8ea1;
  --object-line: #a89e86; --glass-ext-line: #7a8ea1; /* W2 split aliases — this vein's own --chrome/--glass-ext values (render-preserving) */
  --chrome: #a89e86; --wire: #3a342a; --hinge-ref: #b3a88f; --witness: #b3a88f;
  --motor: #2a251d; --label-value: #2a251d; --label-name: #6a6151;
  --ok: #3c7a4e; --warn: #a5621b; --bad: #a83726;
  color: var(--ink); background: #e9e3d6;
}
body[data-chrome="drafting"] header,
body[data-chrome="drafting"] #subnav,
body[data-chrome="drafting"] #controls { background: #e6e1d4; }
body[data-chrome="drafting"] .sheet { background: var(--panel); } /* ground, not a frame — same law */
body[data-chrome="drafting"] #solving { background: rgba(234,229,217,0.8); }

/* ARCTIC — THE CORPORATE IDENTITY (default vein since SES-030c; founder ruling
   2026-07-21: ARCTIC is the full CI implementation — ICD-003, scope law §5).
   The token block between the markers is GENERATED by
   reference/identity/derive-house-palette.mjs from the customer's own anchors —
   edit the DERIVATION, never the block; the battery leg `house palette`
   re-derives and REFUSES drift. Structural rules after the block consume
   tokens only (§15 Law A). The pre-CI sheet survives byte-identical at
   hmi/superseded/house-v1.css (BRF-007 W2 demotion; see its SUPERSEDED.md). */
/* ▼ GENERATED — arctic CI token block (derive-house-palette.mjs) ▼ */
body[data-chrome="arctic"] {
  --bg: #F9F9F9;            /* derived — own L 0.981, CI cast between grey_mid–white */
  --panel: #ffffff;         /* anchor white — EXACT at output */
  --line: #DBDBDB;          /* derived — own L 0.892, CI cast between grey_mid–white */
  --line-soft: #EAEAEA;     /* derived — own L 0.938, CI cast between grey_mid–white */
  --ink: #231f20;           /* anchor ink — EXACT at output */
  --dim: #575756;           /* anchor grey_dark — EXACT at output */
  --faint: #8E8E8E;         /* anchor grey_mid — EXACT at output · POLISHED ΔL -0.04 → 3.11:1 · ANCHOR grey_mid RELEASED (their grey is not legible at this role on white) */
  --blue: #327695;          /* anchor blue_deep — EXACT at output */
  --glass-ext: #a2c7d5;     /* anchor blue_pale — EXACT at output */
  --chrome: #B2B2B2;        /* derived — own L 0.762, CI cast between grey_mid–white */
  --wire: #545453;          /* derived — own L 0.445, CI cast between ink–grey_dark */
  --hinge-ref: #BFBFBF;     /* derived — own L 0.804, CI cast between grey_mid–white */
  --witness: #BFBFBF;       /* derived — own L 0.804, CI cast between grey_mid–white */
  --motor: #3B3937;         /* derived — own L 0.345, CI cast between ink–grey_dark */
  --label-value: #231f20;   /* anchor ink — EXACT at output */
  --label-name: #757574;    /* derived — own L 0.562, CI cast between grey_dark–grey_mid */
  --ok: #2f8a5f;            /* signal — untouched by rule */
  --warn: #96690f;          /* signal — untouched by rule */
  --bad: #b23f36;           /* signal — untouched by rule */
  --object-line: #848484;   /* derived — CI cast walked from --chrome's L 0.764 to L 0.614: ≥3:1 on BOTH grounds (--line-soft, --panel) */
  --glass-ext-line: #44829E; /* derived — blue-family cast walked from blue_pale L 0.807 to L 0.577: the 0.8 composite over --panel clears 3:1 */
}
/* ▲ GENERATED — arctic CI token block ▲ */
body[data-chrome="arctic"] { color: var(--ink); background: var(--bg); }
body[data-chrome="arctic"] header,
body[data-chrome="arctic"] #subnav,
body[data-chrome="arctic"] #controls { background: var(--panel); }
body[data-chrome="arctic"] .sheet { background: var(--panel); } /* plate = panel; white fill distinguishes — no plate outline on the default theme */
body[data-chrome="arctic"] #solving { background: color-mix(in srgb, var(--bg) 85%, transparent); }

/* ═══ 13 · RESPONSIVE ═══ narrow-screen chrome (full zone grammar in part A §8) */
@media (max-width: 900px) {
  #verdict { gap: calc(var(--sp) * 1.25) calc(var(--sp) * 2.25); }
  .tabs { flex-wrap: wrap; row-gap: var(--sp); }
}
