/**
 * XALIAN DESIGN SYSTEM
 * =============================================================================
 * This file carries two layers. Version 4 ("one site, featured components,
 * immersive experiences" — docs/DESIGN_SYSTEM.md) is the ratified contract
 * and the layer new work reads: quiet chrome, one accent (the viable
 * signal), square corners with the chamfer reserved for glass and the
 * primary key, the helix spinner, no terminal props. Version 3 ("one relay,
 * many terminals") is kept underneath, additive only, until each page
 * migrates off `data-terminal` onto `data-tier` (section 11 of the doc) —
 * its terminal material blocks and furniture classes (.g-case, .g-crt,
 * .g-paper*, .g-key*, .g-screen, .g-readout*, .g-lamp, .g-hazard-strip,
 * .g-rivet-rule) are untouched by the v4 migration and must keep working
 * exactly as before.
 *
 * Namespace is --g-* / .g-* for both layers.
 */

/* -------------------------------------------------------------------------
   TOKENS
   ------------------------------------------------------------------------- */

:root {
	/* =========================================================================
	   VERSION 4 PRIMITIVES (docs/DESIGN_SYSTEM.md section 3)
	   The room, surfaces, glass, ink, the viable accent (three tiers of one
	   hue), semantic status colours, corners and motion. Mirrored in
	   designTokens.js, paired in designTokens.test.js.
	   ========================================================================= */

	/* Room + surfaces. Warm near-black; each surface a step warmer/lighter. */
	--g-room: #121110;
	--g-s0: #191816;
	--g-s1: #201f1c;
	--g-s2: #282723;
	--g-s3: #31302b;

	/* Glass: live data only. Darker than the room. */
	--g-glass: #0e100f;

	/* Edges. */
	--g-edge: rgba(217, 210, 192, 0.10);
	--g-edge-hi: rgba(255, 244, 214, 0.07);
	--g-edge-strong: rgba(217, 210, 192, 0.22);
	--g-glass-edge: rgba(217, 210, 192, 0.14);

	/* Ink: bone rather than white. */
	--g-ink: #d9d2c0;
	--g-ink-2: #9a9382;
	--g-ink-3: #6c6659;
	--g-ink-4: #4a4640;

	/* The viable signal: the accent. Three tiers of one hue, the bright one
	   only ever small (docs/DESIGN_SYSTEM.md section 3.1). */
	--g-viable-hi: #86ffb5;
	--g-viable: #4fc98d;
	--g-viable-lo: #2f8f63;
	--g-viable-tint: rgba(134, 255, 181, 0.10);
	--g-viable-ink: #08150e;

	/* Semantic status, separate from the accent and the element hues. */
	--g-plague: #b5566c;
	--g-plague-tint: rgba(181, 86, 108, 0.14);
	--g-plague-ink: #fff1f3;
	/* Muted plague text for the outline/quiet destructive state (rest and
	   hover, before the fill commits): not in docs/DESIGN_SYSTEM.md's table
	   by name, taken from docs/design/v4-foundations.html's .btn.danger. */
	--g-plague-outline-ink: #e8a4b4;
	--g-caution: #cfa54a;
	--g-caution-tint: rgba(207, 165, 74, 0.14);
	--g-neutral-status: #8a97a6;

	/* Corners: square everywhere except the chamfer, reserved for glass and
	   the one primary key (docs/DESIGN_SYSTEM.md section 5). */
	--g-cut: 12px;
	--g-cut-key: 8px;
	--g-chamfer: polygon(var(--g-cut) 0, 100% 0, 100% calc(100% - var(--g-cut)), calc(100% - var(--g-cut)) 100%, 0 100%, 0 var(--g-cut));
	--g-chamfer-key: polygon(var(--g-cut-key) 0, 100% 0, 100% calc(100% - var(--g-cut-key)), calc(100% - var(--g-cut-key)) 100%, 0 100%, 0 var(--g-cut-key));

	/* Motion (docs/DESIGN_SYSTEM.md section 7). */
	--g-dur-1: 120ms;
	--g-dur-2: 200ms;
	--g-dur-3: 320ms;
	--g-ease-out: cubic-bezier(.2, .7, .2, 1);
	--g-ease-in: cubic-bezier(.6, 0, .8, .4);

	/* Type faces (docs/DESIGN_SYSTEM.md section 4): Saira for anything that
	   labels or heads, Atkinson Hyperlegible for prose, Martian Mono for
	   values, Iceland for the wordmark only. */
	--g-font-legend: 'Saira', 'Barlow Condensed', Impact, sans-serif;
	--g-font-body: 'Atkinson Hyperlegible', 'Barlow', system-ui, sans-serif;
	--g-font-data: 'Martian Mono', 'IBM Plex Mono', ui-monospace, Menlo, monospace;
	--g-font-brand: 'Iceland', var(--g-font-legend);

	/* Type scale, in pixels per the doc: display 40, title 32, heading 24,
	   subhead 19, legend 11.5 (tracked .1em), lead 17, body 15, small 13.5. */
	--g-size-display: 44px;
	--g-size-title: 40px;
	--g-size-heading: 24px;
	--g-size-subhead: 19px;
	--g-size-legend: 11.5px;
	--g-size-lead: 17px;
	--g-size-body-v4: 15px;
	--g-size-small-v4: 13.5px;
	--g-track-legend: .1em;
	--g-track-heading: .06em;

	/* =========================================================================
	   VERSION 4 SEMANTIC ALIASES (docs/DESIGN_SYSTEM.md section 3.5)
	   ========================================================================= */
	--g-surface-page: var(--g-room);
	--g-surface-0: var(--g-s0);
	--g-surface-1: var(--g-s1);
	--g-surface-2: var(--g-s2);
	--g-surface-live: var(--g-glass);
	--g-surface-float: var(--g-s2);
	--g-text: var(--g-ink);
	--g-text-2: var(--g-ink-2);
	--g-text-3: var(--g-ink-3);
	--g-focus: var(--g-viable-hi);
	--g-status-ok: var(--g-viable);
	--g-status-danger: var(--g-plague);
	--g-status-warn: var(--g-caution);
	--g-status-info: var(--g-neutral-status);

	/* =========================================================================
	   VERSION 3 TOKENS (kept; see header comment)
	   ========================================================================= */
	/* --- the room ---------------------------------------------------------
	   Warm near-black, tinted brown rather than blue. A hangar, not a showroom.
	   Repointed to the v4 room primitive: same warm near-black idea, one value. */
	--g-void: var(--g-room);

	/* --- hull -------------------------------------------------------------
	   Enamelled steel in olive drab. Three steps — recessed, standard, raised —
	   deliberately close together, because it is all one pressed sheet.
	   Repointed to the v4 surface steps (docs/DESIGN_SYSTEM.md section 3.3). */
	--g-hull-lo: var(--g-s0);
	--g-hull: var(--g-s1);
	--g-hull-hi: var(--g-s2);
	--g-seam: #0a0a07;

	/* Bevel. A painted edge catches light along the top and drops shadow below.
	   These two values are what make a panel read as an object. */
	--g-bevel-light: rgba(255, 244, 214, 0.11);
	--g-bevel-dark: rgba(0, 0, 0, 0.6);
	--g-rule: rgba(216, 207, 184, 0.14);
	--g-rule-faint: rgba(216, 207, 184, 0.06);

	/* --- brass ------------------------------------------------------------
	   Bezels, trim rings and fasteners. Oxidised, not polished. */
	--g-brass: #b08d3f;
	--g-brass-dark: #6b5423;
	--g-brass-light: #d8b45e;

	/* --- printed matter ---------------------------------------------------
	   Bone-white silkscreen and cream bakelite. Never pure white — paint yellows.
	   --g-ink is declared once, above, as the v4 ink primitive (#d9d2c0);
	   --g-ink-mid/--g-ink-low repoint to the v4 secondary/tertiary ink. */
	--g-ink-mid: var(--g-ink-2);
	--g-ink-low: var(--g-ink-3);
	--g-ink-invert: #14120c;

	/* --- phosphor ---------------------------------------------------------
	   The CRT. The only pure saturated light in the interface, confined to
	   .g-screen. */
	--g-phosphor: #74ffb0;
	--g-phosphor-dim: rgba(116, 255, 176, 0.42);
	--g-phosphor-a20: rgba(116, 255, 176, 0.20);
	--g-screen-glass: #07120c;

	/* --- lamps ------------------------------------------------------------
	   Bulbs behind coloured plastic. */
	--g-lamp-amber: #ffb037;
	--g-lamp-red: #e4483c;
	--g-lamp-off: #3d3a30;

	/* --- hazard -----------------------------------------------------------
	   Painted warning livery, straight off a loading bay. Repointed: hazard
	   livery is deliberately avoided in v4 (docs/DESIGN_SYSTEM.md section
	   13), so this now reads the viable fill rather than its own hue. */
	--g-hazard: var(--g-viable);
	--g-hazard-dark: #6d5108;

	/* --- sides ------------------------------------------------------------
	   The two seats at any table, as the Duel paints them: your pieces rimmed
	   in cyan, the rival's in brass. Shared by every game so a side reads the
	   same way everywhere. */
	--g-team-one: #3bbedf;
	--g-team-two: #c39738;

	/* --- element energy ---------------------------------------------------
	   Unchanged, and the fixed point of the whole system: fire is red because
	   fire is red. The hull went colourless so these own every saturated pixel. */
	--g-el-fire: #e5735f;
	--g-el-water: #6a9fd8;
	--g-el-air: #d8e6ee;
	--g-el-electric: #e9c93a;
	--g-el-rock: #a98a6a;
	--g-el-plant: #83a44b;
	--g-el-chemical: #58c3ba;
	--g-el-light: #f5ec9a;
	--g-el-dark: #7378c4;
	--g-el-metal: #a4a8ad;
	--g-el-psychic: #dc9fd2;
	--g-el-ghost: #a886cf;
	--g-el-ice: #8fd6ee;
	--g-el-sand: #dba873;

	/* The element in scope. One class on a container retunes everything inside. */
	--g-el: var(--g-phosphor);

	/* --- stat colours -----------------------------------------------------
	   Semantic and independent of element: attack is red, defense blue, speed
	   yellow-green, stamina and recovery green. Each "special" variant is a
	   darker shade of its standard pair so the two read as related. */
	--g-stat-standard-attack: #a84032;
	--g-stat-special-attack: #753027;
	--g-stat-standard-defense: #535dc2;
	--g-stat-special-defense: #494f8c;
	--g-stat-speed: #d0d466;
	--g-stat-evasion: #aaad53;
	--g-stat-stamina: #4bbf4e;
	--g-stat-recovery: #479e4a;

	/* --- charts -----------------------------------------------------------
	   Recharts paints these from JS, so they are mirrored in designTokens.js. */
	--g-chart-range-track: #ecff8234;
	--g-chart-points-fill: #80dbff34;
	--g-chart-bar-label: #ffffff50;
	--g-chart-cursor-fill: #ffffff25;
	--g-chart-axis: #ddd4bd;

	/* --- type -------------------------------------------------------------
	   Oswald is a mid-century poster and signage face: the condensed caps
	   stencilled onto equipment and painted on placards. IBM Plex Mono is the
	   machine's own output — a terminal line, a printed slip. Neither is a
	   "sci-fi" typeface, because the fiction is industrial, not futuristic. */
	--g-font-ui: var(--g-font-body);

	/* --g-size-micro/--g-size-tiny bumped a hair for Barlow Condensed: its
	   caps run a touch smaller than Oswald's at the same rem size, and the
	   smallest legends (asset plates, tabs) were the first to feel thin. */
	--g-size-micro: 0.7rem;
	--g-size-tiny: 0.8125rem;
	--g-size-small: 0.875rem;
	--g-size-body: 1rem;
	--g-size-lead: 1.125rem;
	--g-size-h3: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
	--g-size-h2: clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem);
	--g-size-h1: clamp(2.5rem, 1.8rem + 3.4vw, 4.25rem);
	--g-size-readout: clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem);

	/* Re-tuned once for Barlow Condensed (round3-coherence.md): it is already
	   a condensed face, unlike Oswald's semi-condensed, so the same tracking
	   read airy rather than stencilled. Pulled in a touch and the small
	   sizes bumped so caps at --g-size-tiny/--g-size-micro stay legible at
	   the tighter spacing. */
	--g-track-label: 0.1em;
	--g-track-wide: 0.2em;

	/* --- space ------------------------------------------------------------ */
	--g-1: 4px;
	--g-2: 8px;
	--g-3: 12px;
	--g-4: 16px;
	--g-5: 24px;
	--g-6: 32px;
	--g-7: 48px;
	--g-8: 64px;
	--g-9: 96px;

	/* --- geometry ---------------------------------------------------------
	   Streamline moderne: softly rounded housings, not sharp corners and not
	   sci-fi chamfers. Moulded plastic and pressed steel both have a radius. */
	/* Square everywhere in v4 (docs/DESIGN_SYSTEM.md section 5); the chamfer
	   (--g-chamfer/--g-chamfer-key, declared above) replaces radius as the
	   one signature cut, reserved for glass and the primary key. */
	--g-radius: 0;
	--g-radius-panel: 0;
	--g-radius-housing: 0;
	--g-hairline: 1px;

	/* --- light ------------------------------------------------------------
	   Hull does not emit. Screens and lamps do. */
	--g-relief: inset 0 1px 0 var(--g-bevel-light), inset 0 -1px 0 var(--g-bevel-dark);
	--g-drop: 0 1px 0 rgba(0, 0, 0, 0.5), 0 4px 14px rgba(0, 0, 0, 0.5);
	/* v4: the one shadow for things that float over the page (modal, drawer,
	   popover, toast, menu, search results). Nothing else casts one. */
	--g-shadow-float: 0 12px 28px rgba(0, 0, 0, 0.45);
	--g-recess: inset 0 2px 6px rgba(0, 0, 0, 0.8), inset 0 -1px 0 var(--g-bevel-light);

	/* --- motion -----------------------------------------------------------
	   Mechanical. Switches throw; they do not glide. */
	--g-snap: 90ms cubic-bezier(0.3, 0, 0.2, 1);
	--g-move: 200ms cubic-bezier(0.3, 0, 0.2, 1);

	--g-measure: 68ch;

	--g-layer-nav: 500;
	--g-layer-modal: 1000;

	/* --- material tokens (v3, "one relay, many terminals") ----------------
	   Every [data-terminal="..."] block below sets all of these; the values
	   here are the "panel" terminal's defaults, i.e. the version 2 look kept
	   as the migration baseline (docs/DESIGN_SYSTEM.md section 3 and 6).
	   --g-trim*/--g-accent* are the new names for --g-brass*/--g-hazard*; both
	   pairs carry literal duplicate values (not var() aliases) so the token
	   mirror test in designTokens.test.js can check each one independently. */
	--g-face: var(--g-hull);
	--g-face-ink: var(--g-ink);
	--g-face-ink-mid: var(--g-ink-mid);
	--g-face-ink-low: var(--g-ink-low);
	/* The face's own recessed/raised steps, for a terminal object's nested
	   surfaces (a counter's lip, a cover plate's screw well, a keybank).
	   :root's panel terminal aliases these to the room's hull steps, which is
	   a no-op (its object IS the hull, unlike every other terminal) — every
	   other terminal below sets these as its own literal colours instead of
	   drawing on the (now single, shared) --g-hull-lo/--g-hull-hi. */
	--g-face-lo: var(--g-hull-lo);
	--g-face-hi: var(--g-hull-hi);

	--g-trim: #b08d3f;
	--g-trim-dark: #6b5423;
	--g-trim-light: #d8b45e;

	--g-accent: var(--g-viable);
	--g-accent-ink: var(--g-viable-ink);

	/* --g-glass is declared once, above, as the v4 primitive (#0e100f); every
	   [data-terminal] block below still overrides it with its own literal
	   screen-glass colour, which wins for that terminal's descendants
	   (nearest declaration in the tree, not source order). */
	--g-vfd: var(--g-phosphor);
	--g-vfd-glass: var(--g-screen-glass);

	--g-paper: #ddd4bd;
	--g-paper-ink: #23231a;
	/* Darkened from #6b665a (4.09:1 against --g-paper) so labels clear the
	   4.5:1 contrast floor; kept out of the --g-ink-low pairing on purpose,
	   see designTokens.js material.paperInkFaint. */
	--g-paper-ink-faint: #5c584d;
	--g-paper-rule: rgba(35, 35, 26, 0.2);

	/* One type system, core (Rule A / round3-coherence.md): Barlow Condensed
	   is the legend face everywhere, IBM Plex Mono the machine's output
	   everywhere, Special Elite the typewriter everywhere, Barlow the prose
	   everywhere. No [data-terminal] block below overrides any of these four
	   — the v3 build let each terminal set its own legend face and that was
	   the single biggest thing that made the site read as six unrelated
	   products (docs/DESIGN_SYSTEM.md Rule A). */
	/* --g-font-legend is declared once, above, as the v4 primitive (Saira). */
	--g-font-out: var(--g-font-data);
	--g-font-paper: 'Special Elite', 'IBM Plex Mono', monospace;
	/* --g-font-ui is declared once, above, repointed to --g-font-body. */

	/* Legacy names for --g-font-legend/--g-font-out, kept because a lot of
	   existing CSS still spells them this way. Since none of the four core
	   font tokens are overridden per terminal any more, these two aliases no
	   longer need redeclaring inside every [data-terminal] block the way
	   section 10's lesson describes for a genuinely material var() chain —
	   there is nothing left for any terminal to retune. */
	--g-font-stencil: var(--g-font-legend);
	--g-font-mono: var(--g-font-data);

	/* --g-font-nameplate is the one exception: the single face that stays the
	   terminal's own, used only by .g-nameplate and .g-stamp. :root's value
	   (IBM Plex Mono) covers the panel baseline and the readout mode; every
	   other terminal below sets its own. */
	--g-font-nameplate: 'IBM Plex Mono', ui-monospace, Menlo, monospace;

	/* 0..1: how much scuff, tape shadow and fade a terminal's furniture shows.
	   The panel is the clean migration baseline, so it carries none. */
	--g-wear: 0;
	--g-lamp-on: var(--g-phosphor);

	/* Screen bloom retunes to whichever phosphor is in scope automatically,
	   because it reads --g-phosphor rather than a literal. */
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);

	/* --- interaction-state and semantic tokens, formerly raw hex -----------
	   Hover/checked/danger states that were literal hex scattered through the
	   component rules below. Panel-only for now; a terminal that needs its own
	   hover or danger treatment can override these same names. */
	--g-hull-hover: var(--g-s3);
	--g-accent-hover: #5fd89b;
	--g-danger: var(--g-plague);
	--g-danger-ink: var(--g-plague-ink);
	--g-danger-edge: #43110e;
	--g-danger-hover: #94332d;
	--g-check-on: #40340b;
	--g-hazard-stripe: #15130c;

	/* Two colours the readout mode needs regardless of which terminal is
	   hosting it (it is a mode, not a place: docs/DESIGN_SYSTEM.md section 3),
	   plus the near-black ink used for a classification tab printed on a
	   saturated element colour on any terminal. */
	--g-readout-phosphor: #e8e6da;
	--g-readout-phosphor-dim: rgba(232, 230, 218, 0.4);
	--g-readout-glass: #0c100d;
	--g-readout-ink: #0b0d0b;
	--g-tab-ink: #1a1a1a;
}

/* Element keying. */
.g-el-fire { --g-el: var(--g-el-fire); }
.g-el-water { --g-el: var(--g-el-water); }
.g-el-air { --g-el: var(--g-el-air); }
.g-el-electric { --g-el: var(--g-el-electric); }
.g-el-rock { --g-el: var(--g-el-rock); }
.g-el-plant { --g-el: var(--g-el-plant); }
.g-el-chemical { --g-el: var(--g-el-chemical); }
.g-el-light { --g-el: var(--g-el-light); }
.g-el-dark { --g-el: var(--g-el-dark); }
.g-el-metal { --g-el: var(--g-el-metal); }
.g-el-psychic { --g-el: var(--g-el-psychic); }
.g-el-ghost { --g-el: var(--g-el-ghost); }
.g-el-ice { --g-el: var(--g-el-ice); }
.g-el-sand { --g-el: var(--g-el-sand); }

/* -------------------------------------------------------------------------
   TERMINALS (v3, "one relay, many terminals")
   One block per data-terminal, each setting every material token in the
   table in docs/DESIGN_SYSTEM.md section 6. Element hues and stat colours
   are core and never appear here. Values are taken from the ratified
   mockups in docs/design/terminal-mockups.html (the .t-field / .t-registry /
   .t-archive / .t-relay / .t-readout blocks). "panel" needs no block: its
   values live in :root above as the migration baseline.
   ------------------------------------------------------------------------- */

/* FIELD — ECHELON-era portable survey unit: gunmetal case, off-white enamel
   face, color CRT under dark glass, one-line amber VFD status strip. */
[data-terminal='field'] {
	/* The room (--g-void/--g-hull*/--g-seam) is core (Rule A) and is not set
	   here; the case's own gunmetal body is --g-face-lo/--g-face-hi below. */
	--g-face: #cfc8b6;
	--g-face-lo: #262829;
	--g-face-hi: #4a4d4d;
	/* Ink on the room is core, ink on the face is material (Rule A /
	   round3-coherence.md): the field unit's light enamel face needs dark
	   ink, so these three stay literal rather than aliasing :root's --g-ink*
	   (which is now the room's light-on-dark value, unrelated to this face). */
	--g-face-ink: #1e1d19;
	--g-face-ink-mid: #5b584f;
	--g-face-ink-low: #8a857a;

	--g-trim: #2b2b28;
	--g-trim-dark: #1a1a18;
	--g-trim-light: #4a4a45;

	--g-accent: #c8572b;
	--g-accent-ink: #f5efe2;

	--g-glass: #0f0d0a;
	--g-screen-glass: #0f0d0a;
	--g-phosphor: #e9e3d2;
	--g-phosphor-dim: rgba(233, 227, 210, 0.5);
	--g-phosphor-a20: rgba(233, 227, 210, 0.2);
	/* Redeclared so its var(--g-phosphor) resolves against THIS terminal's
	   phosphor: a custom property's var() references are substituted once,
	   at the element carrying the declaration, so leaving this only in :root
	   would bloom every screen in the panel terminal's green forever (S2). */
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);

	--g-vfd: #ffb347;
	--g-vfd-glass: #1a1208;

	--g-paper: #e9e2cc;
	--g-paper-ink: #2b2a26;
	--g-paper-ink-faint: #5b584f;
	--g-paper-rule: rgba(30, 29, 25, 0.25);

	/* Legend/output/paper/ui are core now (Rule A); Michroma survives only as
	   the field unit's own nameplate face, used nowhere else on this
	   terminal. */
	--g-font-nameplate: 'Michroma', sans-serif;

	--g-radius: 3px;
	--g-wear: 0.6;
	--g-lamp-on: #ffb347;

	/* A screen terminal: any mounted photo (a reconditioning tag, not an ID
	   card) stays a plain plate. */
	--g-photo-filter: none;
}

/* REGISTRY — Kozrak's arena counter: black lacquer, gold leaf, a docket under
   a steel clip, a one-line amber ledger, two bakelite keys in sockets. */
[data-terminal='registry'] {
	/* The room is core; the counter's own lacquer body is face-lo/face-hi. */
	--g-face: #e6dcc6;
	--g-face-lo: #070505;
	--g-face-hi: #1c1515;
	/* --g-face here doubles as the docket's paper tone (see --g-paper below);
	   the counter's own body (.g-counter, reading --g-face-ink*) is the dark
	   lacquer carried in --g-face-lo/--g-face-hi, so its ink is the light
	   gold this terminal used to force onto the whole room's --g-ink. Ink on
	   the room is core, ink on the face is material (Rule A). */
	--g-face-ink: #e9dfc8;
	--g-face-ink-mid: #a89d86;
	--g-face-ink-low: #6e6558;

	--g-trim: #c9a44a;
	--g-trim-dark: #7a5f24;
	--g-trim-light: #e0c882;

	--g-accent: #8f1d1d;
	--g-accent-ink: #f3e9d3;

	--g-glass: #120a0a;
	--g-screen-glass: #120a0a;
	--g-phosphor: #e7c98a;
	--g-phosphor-dim: rgba(231, 201, 138, 0.4);
	--g-phosphor-a20: rgba(231, 201, 138, 0.2);
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);

	--g-vfd: #e7c98a;
	--g-vfd-glass: #120a0a;

	--g-paper: #e6dcc6;
	--g-paper-ink: #1d1710;
	--g-paper-ink-faint: #6b5f4c;
	--g-paper-rule: rgba(143, 29, 29, 0.35);

	/* Legend/output/paper are core now; Cinzel survives only as the
	   registry's nameplate face (the counter's engraved name, the docket's
	   admission stamp). */
	--g-font-nameplate: 'Cinzel', serif;

	--g-radius: 0;
	--g-wear: 0.3;
	--g-lamp-on: #e4483c;

	/* The docket's ID photo: a black-and-white admission photo, not a colour
	   print. */
	--g-photo-filter: grayscale(1) contrast(1.15);
}

/* ARCHIVE — reading desk in the Poseidas Deep Archive: dark sea-slate under
   a warm lamp pool, a yellowed catalogue card. No live display. */
[data-terminal='archive'] {
	/* The room is core; the desk's own slate body is face-lo/face-hi. */
	--g-face: #f8f5ec;
	--g-face-lo: #2e3b3e;
	--g-face-hi: #465659;
	/* The desk's own body (.g-desk, reading --g-face-ink*) is the dark
	   sea-slate carried in --g-face-lo/--g-face-hi, so its ink is the light
	   value this terminal used to force onto the whole room's --g-ink. Ink
	   on the room is core, ink on the face is material (Rule A). */
	--g-face-ink: #e6dfcc;
	--g-face-ink-mid: #a9b3b0;
	--g-face-ink-low: #7d8886;

	--g-trim: #7d9397;
	--g-trim-dark: #5b6f72;
	--g-trim-light: #a8bbbe;

	--g-accent: #1f5f6b;
	--g-accent-ink: #f3f7f6;

	/* The archive has no screen; these stay defined (every terminal sets every
	   token) but nothing on this terminal reads them. */
	--g-glass: #1c2426;
	--g-screen-glass: #1c2426;
	--g-phosphor: #1f5f6b;
	--g-phosphor-dim: rgba(31, 95, 107, 0.4);
	--g-phosphor-a20: rgba(31, 95, 107, 0.2);
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);
	--g-vfd: #1f5f6b;
	--g-vfd-glass: #1c2426;

	--g-paper: #e6d9b6;
	--g-paper-ink: #3b3428;
	/* Darkened from #6f6553 (4.09:1 against --g-paper, below the 4.5:1 floor). */
	--g-paper-ink-faint: #635a4a;
	--g-paper-rule: rgba(70, 90, 100, 0.2);

	/* Legend/output/paper/ui are core now; Spectral survives only as the
	   archive's nameplate face (the desk's own name plate, the card's file
	   stamp). */
	--g-font-nameplate: 'Spectral', serif;

	--g-radius: 0;
	--g-wear: 0.8;
	--g-lamp-on: #1f5f6b;

	/* The sepia plate on the card's corner mounts. */
	--g-photo-filter: sepia(0.55) contrast(1.05) brightness(0.96);
}

/* RELAY — hand-built Zolto QED unit: sheet-steel cover plate, screws and
   vents, a salvaged colour tube in a frame on standoffs, one cable, tape. */
[data-terminal='relay'] {
	/* The room is core; the cover plate's own steel body is
	   face-lo/face-hi. */
	--g-face: #0a0c10;
	--g-face-lo: #05060a;
	--g-face-hi: #141821;
	--g-face-ink: #d8dde8;
	--g-face-ink-mid: #7f889a;
	--g-face-ink-low: #4f5766;

	--g-trim: #2b3444;
	--g-trim-dark: #1a1f2a;
	--g-trim-light: #55607a;

	--g-accent: #e0364a;
	--g-accent-ink: #fff3f2;

	--g-glass: #07090d;
	--g-screen-glass: #07090d;
	--g-phosphor: #dfe4ea;
	--g-phosphor-dim: rgba(223, 228, 234, 0.45);
	--g-phosphor-a20: rgba(223, 228, 234, 0.2);
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);

	/* The bloodstorm-crimson trace signal, not a print strip: a relay does not
	   print, but it still has a status voice, carried on the CRT itself. */
	--g-vfd: #e2bd43;
	--g-vfd-glass: #0a0c12;

	/* No paper on a relay. Reuse the tape label's colours. */
	--g-paper: #e9e2cc;
	--g-paper-ink: #2b2a26;
	/* Darkened from #7f889a (2.75:1 against --g-paper, well below the 4.5:1
	   floor: the relay has no real paper, but the token still has to pass if
	   anything reads it, e.g. the styleguide's reference section). */
	--g-paper-ink-faint: #5a616d;
	--g-paper-rule: rgba(43, 52, 68, 0.3);

	/* Legend/output/paper are core now; Chakra Petch survives only as the
	   relay's nameplate face (the .g-nameplate on the navbar and the cover
	   plate). */
	--g-font-nameplate: 'Chakra Petch', sans-serif;

	--g-radius: 2px;
	--g-wear: 0.5;
	--g-lamp-on: #e2bd43;

	/* A screen terminal: no photo plate stock to tint. */
	--g-photo-filter: none;
}

/* READOUT — the Generator's own voice: paper-white text on dark glass, no
   legends, one key. A mode, not a place: applied to a .g-crt while a
   creature prints, on whichever terminal is hosting it. */
[data-terminal='readout'] {
	/* The room is core. Readout is a mode, not a place (section 3): it hosts
	   no case/counter/desk/cover-plate of its own, but every terminal sets
	   every material token, so face-lo/face-hi mirror --g-face here rather
	   than being left to fall back to the (unrelated) room steps. */
	--g-face: #0b0d0b;
	--g-face-lo: #060706;
	--g-face-hi: #111411;
	--g-face-ink: #e6e4d8;
	--g-face-ink-mid: #8d8f84;
	--g-face-ink-low: #565850;

	--g-trim: #2a2e2a;
	--g-trim-dark: #161916;
	--g-trim-light: #3a3e39;

	--g-accent: #e8e6da;
	--g-accent-ink: #0b0d0b;

	--g-glass: #0c100d;
	--g-screen-glass: #0c100d;
	--g-phosphor: #e8e6da;
	--g-phosphor-dim: rgba(232, 230, 218, 0.4);
	--g-phosphor-a20: rgba(232, 230, 218, 0.2);
	--g-screen-bloom: 0 0 26px color-mix(in srgb, var(--g-phosphor) 45%, transparent);

	--g-vfd: #e8e6da;
	--g-vfd-glass: #0c100d;

	/* No paper: the readout is the machine's voice, not a printed record. */
	--g-paper: #e8e6da;
	--g-paper-ink: #0b0d0b;
	--g-paper-ink-faint: rgba(232, 230, 218, 0.4);
	--g-paper-rule: rgba(42, 46, 42, 0.3);

	/* No legends on a readout (section 3), so this mode never actually reads
	   --g-font-legend/--g-font-ui; core's IBM Plex Mono / Barlow apply if
	   anything does. --g-font-nameplate stays IBM Plex Mono, same as :root. */

	--g-radius: 0;
	--g-wear: 0;
	--g-lamp-on: #e8e6da;

	/* A screen terminal: no photo plate stock to tint. */
	--g-photo-filter: none;
}

/* -------------------------------------------------------------------------
   THE HULL
   The page is a painted bulkhead. No grid, no scanlines, no vignette — that
   equipment belongs on the screens.
   ------------------------------------------------------------------------- */

.g-console {
	position: relative;
	min-height: 100vh;
	background-color: var(--g-void);
	/* uneven light across a big enamelled surface */
	background-image:
		radial-gradient(ellipse 110% 60% at 25% -10%, rgba(255, 236, 194, 0.05), transparent 62%),
		radial-gradient(ellipse 80% 50% at 95% 108%, rgba(255, 236, 194, 0.028), transparent 60%);
	color: var(--g-ink);
	font-family: var(--g-font-ui);
}

/* Paint tooth. One small turbulence tile at low opacity — what stops a large
   flat surface reading as a CSS gradient.
   `position: fixed` pinned this pseudo-element's box to the viewport instead
   of .g-console's own (often much taller) box, so the tile only tiled across
   the first 900px of any page and stopped dead there: a hard seam at one
   viewport height on every page tall enough to scroll (round1-findings.md
   S1). .g-console is already `position: relative`, so `absolute` sizes this
   to the console's real height and keeps tiling the whole way down. */
.g-console::before {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	z-index: 1;
	opacity: 0.18;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

.g-console > * {
	position: relative;
	z-index: 2;
}

/* =========================================================================
   VERSION 4: PAGE ROOT
   The v4 page root, sibling of .g-console (which stays for unmigrated
   pages). Same warm room, same faint paint-tooth grain and edge vignette as
   .g-console has, drawn the same way (a pseudo layer, `position: absolute`,
   never `fixed` — docs/DESIGN_SYSTEM.md section 14). No terminal furniture.
   ========================================================================= */

.g-page {
	position: relative;
	min-height: 100vh;
	background-color: var(--g-surface-page);
	background-image:
		radial-gradient(ellipse 110% 60% at 25% -10%, rgba(255, 236, 194, 0.05), transparent 62%),
		radial-gradient(ellipse 80% 50% at 95% 108%, rgba(255, 236, 194, 0.028), transparent 60%);
	color: var(--g-text);
	font-family: var(--g-font-body);
	font-size: var(--g-size-body-v4);
	line-height: 1.5;
}

.g-page::before {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	z-index: 1;
	opacity: 0.18;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

.g-page > * {
	position: relative;
	z-index: 2;
}

/* Type roles, v4 (docs/DESIGN_SYSTEM.md section 4). Saira for anything that
   labels or heads, uppercase with tracking; Atkinson Hyperlegible for prose;
   Martian Mono for values, always tabular. */
.g-display {
	font-family: var(--g-font-legend);
	font-weight: 600;
	font-size: var(--g-size-display);
	text-transform: uppercase;
	line-height: .95;
	letter-spacing: .01em;
	color: var(--g-text);
	margin: 0;
}

.g-page .g-link {
	color: var(--g-text);
	text-decoration-color: var(--g-ink-3);
}

.g-page .g-link:hover { text-decoration-color: var(--g-text); }

.g-page .g-masthead { margin: var(--g-6) 0 var(--g-5); }

.g-page .g-title {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-title);
	line-height: .95;
	letter-spacing: .01em;
	color: var(--g-text);
}

/* One hierarchy on chrome pages: title 40 > heading 24 > subhead 19 > legend.
   The v3 .g-h2/.g-h3 sizes were larger than the page title. */
.g-page .g-h2,
.g-page .g-panel-head .g-h2 { font-family: var(--g-font-legend); font-size: var(--g-size-heading); letter-spacing: var(--g-track-heading); color: var(--g-text); }
.g-page .g-h3 { font-family: var(--g-font-legend); font-size: var(--g-size-subhead); font-weight: 500; letter-spacing: var(--g-track-heading); color: var(--g-text); }

/* Labels sit on the second ink, never the third: the third fails the
   contrast floor on the room (audit 2026-09-09). */
.g-page .g-spec-key,
.g-page .g-label,
.g-page .g-record-term,
.g-page .g-legend { font-family: var(--g-font-legend); color: var(--g-text-2); }


/* Art mounts on chrome pages (Nick, 2026-09-09): one flat square in the
   element hue with the black silhouette on it. The legacy .<element>-color
   wrapper (typeColors.css) and the component's inline gradient carry no
   color of their own, so there is never a second square inside the mount. */
.g-page .xalian-image-wrapper[class*='-color'] { background: transparent !important; }

/* The square keeps the old plate's soft vignette (the hue at the center,
   falling to a darker rim) and the silhouette fills it edge to edge, with
   just enough margin that limbs do not touch the frame. */
.g-page .enc-tile-art,
.g-page .enc-species-mount,
.g-page .home-species-plate,
.g-page .account-tile-plate,
.g-page .gen-record-plate {
	background-color: var(--g-el);
	background-image: radial-gradient(circle at 50% 50%, transparent 58%, rgba(0, 0, 0, 0.28) 100%);
	padding: 4%;
}

.g-page .gen-record-plate {
	background-image:
		radial-gradient(circle at 50% 50%, transparent 58%, rgba(0, 0, 0, 0.28) 100%),
		linear-gradient(160deg, var(--g-el), var(--g-el-2, var(--g-el)));
}

.g-page .enc-tile-art-img,
.g-page .enc-species-portrait,
.g-page .home-species-plate-img,
.g-page .gen-record-plate-img,
.g-page .account-tile-plate .xalian-image-wrapper {
	width: 100%;
	height: auto;
}

/* A chip with no element in scope is neutral, never the accent. */
.g-page { --g-el: var(--g-neutral-status); }

/* Values are never italic. */
.g-page .g-mono,
.g-page .g-data-v4,
.g-page .move-rating,
.g-page .g-spec-val { font-style: normal; }

/* Consistency pass (2026-09-09, second polish round). One masthead rhythm on
   every chrome page: a kicker, the title, an optional one-line subtitle 8px
   under it, and 24px to the first object. Pages do not add their own top
   padding above the masthead. */
.g-page .g-masthead-heading { gap: var(--g-2); }
.g-page .g-masthead-heading > p:last-child { margin: 0; }

/* A pressed segment is a selected filter, not the page's forward action:
   it marks itself with the viable underline the tabs use, never a fill. */
.g-page .g-segment[aria-pressed='true'] {
	color: var(--g-text);
	background: var(--g-s0);
	border-color: var(--g-edge-strong);
	box-shadow: inset 0 -2px 0 var(--g-viable);
}

/* An empty state is a quiet solid frame on level 0, not a dashed box. */
.g-page .g-empty {
	border: 1px solid var(--g-edge);
	background: var(--g-s0);
	text-align: left;
	padding: var(--g-5);
}
.g-page .g-empty b { font-size: var(--g-size-legend); letter-spacing: var(--g-track-legend); color: var(--g-text-2); margin-bottom: var(--g-3); }

/* A spec plate reads as one table: keys on a fixed column, values tabular. */
.g-page .g-spec { gap: var(--g-2) var(--g-5); }
.g-page .g-spec-key { font-size: var(--g-size-legend); letter-spacing: var(--g-track-legend); }
.g-page .g-spec-val { font-family: var(--g-font-data); font-size: var(--g-size-small-v4); color: var(--g-text); }

/* Record rows are 12px rows on hairlines. */
.g-page .g-record { padding: var(--g-3) 0; gap: var(--g-2) var(--g-5); }
.g-page .g-record:hover { background: transparent; }
.g-page .g-record-body { font-family: var(--g-font-body); font-size: var(--g-size-small-v4); color: var(--g-text-2); }

/* Phones: the masthead's action row wraps under the title as one row of
   equal keys, never a stack of full-width buttons. Meter names take a
   narrower column so the strip keeps its length. */
@media (max-width: 720px) {
	.g-page .g-masthead-aside { width: 100%; flex-wrap: wrap; }
	.g-page .g-masthead-aside .g-btn { flex: 1 1 0; min-width: 0; padding-left: var(--g-3); padding-right: var(--g-3); font-size: 12px; white-space: nowrap; }
	.g-page .g-meter-row { grid-template-columns: 7rem 1fr 3.5rem; gap: var(--g-2); }
	.g-page .g-meter-name { font-size: var(--g-size-legend); letter-spacing: var(--g-track-legend); }
}

/* Move set (xalianMoveSet.js): the four generated moves as a rated list.
   Rating in the data face, name in the legend face, description as one line
   of quiet prose. Shared by the generator, the account record and the duel
   attack chooser, so it lives here and nowhere else. */
.xalian-move-set {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.move-row {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: var(--g-4);
	align-items: baseline;
	padding: var(--g-3) 0;
	border-bottom: var(--g-hairline) solid var(--g-rule-faint);
}

.move-row:last-child { border-bottom: 0; padding-bottom: 0; }
.move-row:first-child { padding-top: 0; }

.move-detail { min-width: 0; }

.move-rating {
	font-family: var(--g-font-data);
	font-size: var(--g-size-lead);
	font-style: normal;
	font-variant-numeric: tabular-nums;
	color: var(--g-text);
	min-width: 2.25rem;
	text-align: right;
}

.move-name {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-body-v4);
	font-weight: 600;
	letter-spacing: var(--g-track-legend);
	text-transform: uppercase;
	color: var(--g-text);
	margin: 0;
}

.move-description {
	font-family: var(--g-font-body);
	font-size: var(--g-size-small-v4);
	font-style: normal;
	letter-spacing: normal;
	text-transform: none;
	color: var(--g-text-2);
	margin: var(--g-1) 0 0;
}

/* A chip that is also a link keeps the chip's ink. */
.g-page a.g-chip { color: var(--g-ink-invert); text-decoration: none; }
.g-page a.g-chip--outline { color: var(--g-el); }

.g-title-v4 {
	font-family: var(--g-font-legend);
	font-weight: 600;
	font-size: var(--g-size-title);
	text-transform: uppercase;
	line-height: .95;
	letter-spacing: .01em;
	color: var(--g-text);
	margin: 0;
}

.g-heading-v4 {
	font-family: var(--g-font-legend);
	font-weight: 600;
	font-size: var(--g-size-heading);
	text-transform: uppercase;
	letter-spacing: var(--g-track-heading);
	color: var(--g-text);
	margin: 0;
}

.g-subhead-v4 {
	font-family: var(--g-font-legend);
	font-weight: 500;
	font-size: var(--g-size-subhead);
	text-transform: uppercase;
	letter-spacing: var(--g-track-heading);
	color: var(--g-text);
	margin: 0;
}

.g-legend-v4 {
	font-family: var(--g-font-legend);
	font-weight: 500;
	font-size: var(--g-size-legend);
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	color: var(--g-text-2);
}

.g-lead-v4 {
	font-family: var(--g-font-body);
	font-size: var(--g-size-lead);
	max-width: 62ch;
	color: var(--g-text);
	margin: 0;
}

.g-body-v4 {
	font-family: var(--g-font-body);
	font-size: var(--g-size-body-v4);
	max-width: 62ch;
	color: var(--g-text-2);
	margin: 0;
}

.g-small-v4 {
	font-family: var(--g-font-body);
	font-size: var(--g-size-small-v4);
	color: var(--g-text-2);
}

.g-data-v4 {
	font-family: var(--g-font-data);
	font-variant-numeric: tabular-nums;
	font-size: var(--g-size-body-v4);
	color: var(--g-text);
}

.g-figure-v4 {
	font-family: var(--g-font-data);
	font-variant-numeric: tabular-nums;
	font-size: var(--g-size-heading);
	color: var(--g-text);
}

.g-data-v4,
.g-figure-v4 {
	overflow-wrap: break-word;
}

/* Masthead, restyled: kicker legend tracked in ink-3, title 32 Saira 600
   uppercase (docs/DESIGN_SYSTEM.md section 4). Layout is unchanged from
   .g-masthead below (shared with v3), which the v4 kicker/title classes
   above are meant to be used inside of. */
.g-page .g-masthead .g-kicker,
.g-page .g-kicker {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-legend);
	letter-spacing: var(--g-track-legend);
	color: var(--g-text-2);
}

/* -------------------------------------------------------------------------
   TYPE
   ------------------------------------------------------------------------- */

.g-kicker,
.g-label {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	margin: 0;
}

.g-kicker { color: var(--g-ink-low); }
.g-label { color: var(--g-ink-mid); }

.g-title {
	font-family: var(--g-font-stencil);
	/* 600, not 700: Barlow Condensed loads only 500/600 (index.html); 700
	   would synthetically embolden in every browser that does that at all,
	   which reads worse than the face's own heaviest real weight. */
	font-weight: 600;
	font-size: var(--g-size-h1);
	text-transform: uppercase;
	letter-spacing: 0.005em;
	line-height: 0.95;
	color: var(--g-ink);
	margin: 0;
}

.g-h2 {
	font-family: var(--g-font-stencil);
	font-weight: 600;
	font-size: var(--g-size-h2);
	text-transform: uppercase;
	letter-spacing: 0.015em;
	line-height: 1;
	color: var(--g-ink);
	margin: 0;
}

.g-h3 {
	font-family: var(--g-font-stencil);
	font-weight: 600;
	font-size: var(--g-size-h3);
	text-transform: uppercase;
	letter-spacing: 0.02em;
	color: var(--g-ink);
	margin: 0;
}

.g-body {
	font-family: var(--g-font-ui);
	font-size: var(--g-size-body);
	line-height: 1.65;
	color: var(--g-ink-mid);
	max-width: var(--g-measure);
}

.g-mono {
	font-family: var(--g-font-mono);
	font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------------------
   PANEL
   Enamelled steel bolted to the hull. Matte. Depth is the bevel plus, where
   it earns it, four rivets.
   ------------------------------------------------------------------------- */

/* Restyled for v4: level 1 card. Matte, hairline edge, one inset top
   highlight, square (docs/DESIGN_SYSTEM.md section 5). */
.g-panel {
	--panel-fill: var(--g-s1);
	position: relative;
	padding: var(--g-5);
	background: var(--panel-fill);
	border: var(--g-hairline) solid var(--g-edge);
	border-radius: var(--g-radius-panel);
	box-shadow: inset 0 1px 0 var(--g-edge-hi);
}

.g-panel--raised { --panel-fill: var(--g-s2); }

.g-panel--recessed {
	--panel-fill: var(--g-s0);
	box-shadow: none;
}

/* Fasteners, one per corner — drawn, not marked up, and small enough to read
   as construction rather than as ornament. */
.g-panel--bolted {
	background-image:
		radial-gradient(circle at 11px 11px, rgba(0,0,0,0.6) 1.5px, var(--g-trim-dark) 2.4px, var(--g-bevel-light) 3px, transparent 3.6px),
		radial-gradient(circle at calc(100% - 11px) 11px, rgba(0,0,0,0.6) 1.5px, var(--g-trim-dark) 2.4px, var(--g-bevel-light) 3px, transparent 3.6px),
		radial-gradient(circle at 11px calc(100% - 11px), rgba(0,0,0,0.6) 1.5px, var(--g-trim-dark) 2.4px, var(--g-bevel-light) 3px, transparent 3.6px),
		radial-gradient(circle at calc(100% - 11px) calc(100% - 11px), rgba(0,0,0,0.6) 1.5px, var(--g-trim-dark) 2.4px, var(--g-bevel-light) 3px, transparent 3.6px);
}

/* The stencilled title strip along the top of a panel. */
.g-panel-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--g-3);
	padding-bottom: var(--g-2);
	margin-bottom: var(--g-4);
	border-bottom: var(--g-hairline) solid var(--g-rule);
}

/* On a narrow panel the legend and its annotation fight for the same line and
   both wrap. Stack them instead, and drop the annotation down a step. */
@media (max-width: 720px) {
	.g-panel-head {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--g-1);
	}
}

/* Keyed to an element.
   This was a coloured strip across the top edge, which is the house style of
   every dashboard card ever made and said nothing about this machine. It is now
   painted livery: a corner flash sprayed onto the plate, the way a unit marking
   or a hazard classification is applied to real equipment. Drawn as a
   background so the panel's rounded corner clips it for free. */
.g-panel--tagged {
	background-image:
		linear-gradient(135deg,
			var(--g-el) 0 40px,
			var(--g-seam) 40px 43px,
			transparent 43px);
	background-size: 72px 72px;
	background-position: top left;
	background-repeat: no-repeat;
}

/* The element's designation, stencilled onto the plate beside the flash.
   Set data-tag on the panel to print it. */
.g-panel--tagged[data-tag] { position: relative; }

.g-panel--tagged[data-tag]::after {
	content: attr(data-tag);
	position: absolute;
	top: var(--g-3);
	left: 56px;
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-wide);
	color: var(--g-ink-low);
	pointer-events: none;
}

/* -------------------------------------------------------------------------
   SCREEN
   A CRT set into a hole in the panel, behind a brass bezel. The only thing in
   the system that emits light, and the only place scanlines exist.
   ------------------------------------------------------------------------- */

.g-screen {
	position: relative;
	padding: var(--g-4);
	background:
		radial-gradient(ellipse 120% 90% at 50% 40%, rgba(116, 255, 176, 0.055), transparent 70%),
		var(--g-screen-glass);
	border: 2px solid var(--g-trim-dark);
	border-radius: var(--g-radius);
	box-shadow:
		var(--g-recess),
		0 0 0 1px rgba(0, 0, 0, 0.8),
		var(--g-screen-bloom);
	color: var(--g-phosphor);
	font-family: var(--g-font-mono);
	overflow: hidden;
}

/* Scanlines and the curve of the glass — confined to the screen, which is the
   entire point of having a screen. */
.g-screen::after {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.32) 0 1px, transparent 1px 3px),
		radial-gradient(ellipse 130% 130% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.6) 100%);
}

.g-screen-line {
	font-family: var(--g-font-mono);
	font-size: var(--g-size-tiny);
	line-height: 1.7;
	color: var(--g-phosphor);
	text-shadow: 0 0 6px var(--g-phosphor-dim);
	margin: 0;
}

.g-screen-line--dim {
	color: var(--g-phosphor-dim);
	text-shadow: none;
}

.g-readout {
	font-family: var(--g-font-mono);
	font-variant-numeric: tabular-nums;
	font-size: var(--g-size-readout);
	font-weight: 500;
	line-height: 1;
	color: var(--g-el);
	text-shadow: 0 0 14px color-mix(in srgb, var(--g-el) 55%, transparent);
}

.g-readout-unit {
	font-family: var(--g-font-mono);
	font-size: var(--g-size-tiny);
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-phosphor-dim);
}

/* -------------------------------------------------------------------------
   LIVERY
   ------------------------------------------------------------------------- */

.g-hazard-strip {
	height: 12px;
	background-image: repeating-linear-gradient(
		-45deg,
		var(--g-hazard) 0 11px,
		var(--g-hazard-stripe) 11px 22px
	);
	border-radius: 2px;
	box-shadow: var(--g-relief);
	opacity: 0.9;
}

.g-seam-rule {
	height: 2px;
	border: 0;
	margin: var(--g-5) 0;
	background: linear-gradient(180deg, var(--g-seam) 0 1px, var(--g-bevel-light) 1px 2px);
}

/* A riveted trim strip — used to break up long runs of bare panel. */
.g-rivet-rule {
	height: 8px;
	border: 0;
	margin: var(--g-5) 0;
	background-image:
		linear-gradient(180deg, var(--g-seam) 0 1px, var(--g-bevel-light) 1px 2px, transparent 2px),
		radial-gradient(circle at 6px 6px, var(--g-trim-dark) 1.4px, transparent 2px);
	background-size: 100% 100%, 28px 100%;
	background-repeat: no-repeat, repeat-x;
}

/* -------------------------------------------------------------------------
   METER
   Segmented, because an instrument quantises. A recessed strip of bulbs let
   into the hull, lit in the element's colour.
   ------------------------------------------------------------------------- */

/* Restyled for v4: a plain square track, no segmented bulbs, no glow
   (docs/DESIGN_SYSTEM.md section 5 and 6). */
.g-meter {
	position: relative;
	height: 8px;
	background-color: rgba(255, 255, 255, 0.06);
	border-radius: 0;
	box-shadow: none;
	overflow: hidden;
}

.g-meter-track {
	position: absolute;
	inset: 0;
}

/* Headroom the stat could still grow into. */
.g-meter-ghost {
	position: absolute;
	inset: 0;
	background: color-mix(in srgb, var(--g-el) 30%, transparent);
}

/* What the stat actually is. */
.g-meter-fill {
	position: absolute;
	inset: 0;
	background: var(--g-el);
	transition: width var(--g-dur-2) var(--g-ease-out);
}

.g-meter-row {
	display: grid;
	grid-template-columns: 8.5rem 1fr 3.5rem;
	align-items: center;
	gap: var(--g-3);
	padding: var(--g-1) 0;
}

.g-meter-name {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
}

.g-meter-value {
	font-family: var(--g-font-mono);
	font-variant-numeric: tabular-nums;
	font-size: var(--g-size-tiny);
	color: var(--g-ink);
	text-align: right;
}

/* -------------------------------------------------------------------------
   CHIP
   A printed classification label, like a sticker on a specimen jar.
   ------------------------------------------------------------------------- */

/* Chips are content: they carry an element hue and name an element
   (docs/DESIGN_SYSTEM.md section 6). Square, dark text on the hue. */
.g-chip {
	display: inline-flex;
	align-items: center;
	padding: 2px var(--g-3);
	font-family: var(--g-font-legend);
	font-size: 11px;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	color: var(--g-ink-invert);
	background: var(--g-el);
	border-radius: 0;
	box-shadow: none;
}

.g-chip--outline {
	color: var(--g-el);
	background: transparent;
	border: var(--g-hairline) solid color-mix(in srgb, var(--g-el) 55%, transparent);
	box-shadow: none;
}

/* -------------------------------------------------------------------------
   CONTROLS
   A button is a moulded bakelite key that sits proud of the panel and travels
   when pressed.
   ------------------------------------------------------------------------- */

/* Restyled for v4 (docs/DESIGN_SYSTEM.md section 6): flat, square, no
   bevel/glow/travel. Secondary rank by default; --btn-primary is the one
   accent-filled key per screen, chamfered. Four ranks, five states each. */
.g-btn {
	--btn-face: var(--g-s2);
	--btn-ink: var(--g-text);
	--btn-edge: var(--g-edge);
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--g-2);
	padding: var(--g-3) var(--g-5);
	font-family: var(--g-font-legend);
	font-size: 13px;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	color: var(--btn-ink);
	background: var(--btn-face);
	border: var(--g-hairline) solid var(--btn-edge);
	border-radius: var(--g-radius);
	box-shadow: inset 0 1px 0 var(--g-edge-hi);
	cursor: pointer;
	transition: background var(--g-dur-1) var(--g-ease-out), color var(--g-dur-1) var(--g-ease-out);
}

.g-btn:hover:not(:disabled) { --btn-face: var(--g-s3); }

.g-btn:active:not(:disabled) { --btn-face: var(--g-s1); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5); }

.g-btn:focus-visible {
	outline: 2px solid var(--g-focus);
	outline-offset: 2px;
}

/* The one primary action per screen: viable fill, chamfered, no shadow. */
.g-btn--primary {
	--btn-face: var(--g-viable);
	--btn-ink: var(--g-viable-ink);
	--btn-edge: transparent;
	clip-path: var(--g-chamfer-key);
	box-shadow: none;
}

.g-btn--primary:hover:not(:disabled) { --btn-face: var(--g-accent-hover); }
.g-btn--primary:active:not(:disabled) { --btn-face: var(--g-viable-lo); box-shadow: none; }

/* No fill, no edge — the rank for a page's secondary actions (Sign in). */
.g-btn--quiet {
	--btn-face: transparent;
	--btn-ink: var(--g-text-2);
	--btn-edge: transparent;
	box-shadow: none;
}

.g-btn--quiet:hover:not(:disabled) { --btn-face: var(--g-s1); --btn-ink: var(--g-text); }
.g-btn--quiet:active:not(:disabled) { --btn-face: var(--g-s0); box-shadow: none; }

/* Outline at rest so a delete action does not shout; fills only once the
   person is reaching for it (docs/DESIGN_SYSTEM.md section 6). */
.g-btn--danger {
	--btn-face: transparent;
	--btn-ink: var(--g-plague-outline-ink);
	--btn-edge: var(--g-plague);
	box-shadow: none;
}

.g-btn--danger:hover:not(:disabled) { --btn-face: var(--g-plague-tint); }
.g-btn--danger:active:not(:disabled) { --btn-face: var(--g-plague); --btn-ink: var(--g-plague-ink); box-shadow: none; }

/* A square key carrying a glyph instead of a legend. */
.g-btn--icon {
	padding: 0;
	width: 36px;
	height: 36px;
	font-size: var(--g-size-body);
	line-height: 1;
}

.g-btn:disabled {
	opacity: 0.4;
	cursor: not-allowed;
	box-shadow: none;
}

/* Text entry is a screen, so it is phosphor on glass.
   The !important flags are load-bearing: bootstrap ships a `.form-control`
   rule in an injected <style> tag, which outranks any linked stylesheet at
   equal specificity. */
/* Restyled for v4: matte s0 fill, hairline edge, focus is the emitter ring
   (docs/DESIGN_SYSTEM.md section 6). */
.g-input,
.g-select {
	width: 100%;
	padding: var(--g-3) var(--g-4);
	font-family: var(--g-font-body) !important;
	font-size: 14px;
	color: var(--g-text) !important;
	background: var(--g-s0) !important;
	border: 1px solid var(--g-edge-strong) !important;
	border-radius: var(--g-radius) !important;
	box-shadow: none !important;
	transition: border-color var(--g-dur-1) var(--g-ease-out);
}

.g-input::placeholder { color: var(--g-text-3); }

.g-input:hover,
.g-select:hover {
	border-color: rgba(217, 210, 192, 0.35) !important;
}

.g-input:focus,
.g-select:focus {
	outline: 2px solid var(--g-focus);
	outline-offset: 1px;
	border-color: transparent !important;
	box-shadow: none !important;
}

.g-input--error {
	border-color: var(--g-plague) !important;
	background: var(--g-plague-tint) !important;
}

.g-input:disabled,
.g-select:disabled {
	opacity: 0.4;
}

.g-select {
	appearance: none;
	padding-right: var(--g-7);
	background-image:
		linear-gradient(45deg, transparent 50%, var(--g-text-2) 50%),
		linear-gradient(135deg, var(--g-text-2) 50%, transparent 50%);
	background-position: right 20px center, right 14px center;
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
	cursor: pointer;
}

/* A typed field on paper, not a screen: a request slip on the archive's
   desk, a form field on a docket. Transparent stock, a typewriter face, and
   a dotted rule where the screen's glass and bezel would be. */
.g-input--paper {
	background: transparent !important;
	border: none !important;
	border-bottom: 1px dotted var(--g-paper-ink-faint) !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	color: var(--g-paper-ink) !important;
	font-family: var(--g-font-paper) !important;
}

.g-input--paper::placeholder { color: var(--g-paper-ink-faint); opacity: 0.8; }

.g-input--paper:focus {
	outline: none;
	border-color: var(--g-paper-ink) !important;
	box-shadow: none !important;
}

.g-field-label {
	display: block;
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-low);
	margin-bottom: var(--g-2);
}

/* Restyled for v4: flat, square, no recessed housing (docs/DESIGN_SYSTEM.md
   section 6). */
.g-segmented {
	display: inline-flex;
}

.g-segment {
	padding: 6px 12px;
	font-family: var(--g-font-legend);
	font-size: 13px;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	color: var(--g-text-2);
	background: var(--g-s2);
	border: 1px solid var(--g-edge);
	margin-left: -1px;
	border-radius: 0;
	box-shadow: none;
	cursor: pointer;
	transition: background var(--g-dur-1) var(--g-ease-out), color var(--g-dur-1) var(--g-ease-out);
}

.g-segment:hover:not([aria-pressed='true']) {
	background: var(--g-s3);
	color: var(--g-text);
}

.g-segment[aria-pressed='true'] {
	color: var(--g-viable-ink);
	background: var(--g-viable);
	border-color: transparent;
}

.g-segment:focus-visible {
	outline: 2px solid var(--g-focus);
	outline-offset: -3px;
}

/* A toggle with a real throw. */
.g-check {
	display: inline-flex;
	align-items: center;
	gap: var(--g-3);
	cursor: pointer;
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-body);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
}

.g-check input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
}

/* Restyled for v4: a toggle, not a bakelite switch. Pills are the one
   exception to square corners (docs/DESIGN_SYSTEM.md section 5). */
.g-check-box {
	position: relative;
	width: 16px;
	height: 16px;
	flex: none;
	background: var(--g-s0);
	border: 1px solid var(--g-edge-strong);
	border-radius: 0;
	box-shadow: none;
	transition: background var(--g-dur-1) var(--g-ease-out), border-color var(--g-dur-1) var(--g-ease-out);
}

.g-check:hover .g-check-box { border-color: var(--g-ink-2); }

.g-check-box::after {
	content: '';
	position: absolute;
	left: 4px;
	top: 1px;
	width: 5px;
	height: 9px;
	border: solid var(--g-viable-ink);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) scale(0);
	transition: transform var(--g-dur-1) var(--g-ease-out);
}

.g-check input:checked + .g-check-box { background: var(--g-viable); border-color: transparent; }
.g-check input:checked + .g-check-box::after { transform: rotate(45deg) scale(1); }

.g-check input:focus-visible + .g-check-box {
	outline: 2px solid var(--g-focus);
	outline-offset: 2px;
}

/* -------------------------------------------------------------------------
   LAMPS
   Bulbs behind coloured plastic. Lit or unlit — they do not pulse.
   ------------------------------------------------------------------------- */

.g-lamp {
	display: inline-flex;
	align-items: center;
	gap: var(--g-2);
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
}

.g-lamp::before {
	content: '';
	width: 10px;
	height: 10px;
	border-radius: 50%;
	flex: none;
	background: var(--g-phosphor);
	box-shadow: 0 0 8px var(--g-phosphor), inset 0 -2px 2px rgba(0, 0, 0, 0.45);
}

.g-lamp--amber::before {
	background: var(--g-lamp-amber);
	box-shadow: 0 0 8px var(--g-lamp-amber), inset 0 -2px 2px rgba(0, 0, 0, 0.45);
}

.g-lamp--red::before {
	background: var(--g-lamp-red);
	box-shadow: 0 0 8px var(--g-lamp-red), inset 0 -2px 2px rgba(0, 0, 0, 0.45);
}

.g-lamp--off::before {
	background: var(--g-lamp-off);
	box-shadow: inset 0 -2px 2px rgba(0, 0, 0, 0.55);
}

/* -------------------------------------------------------------------------
   FEEDBACK
   ------------------------------------------------------------------------- */

/* Restyled for v4: a toast, level 2, strong edge, a status dot
   (docs/DESIGN_SYSTEM.md section 6). --g-notice-dot is the dot's colour. */
.g-notice {
	--tone: var(--g-viable-hi);
	--g-notice-dot: var(--tone);
	display: flex;
	align-items: flex-start;
	gap: var(--g-3);
	padding: var(--g-3) var(--g-4);
	background: var(--g-s2);
	border: 1px solid var(--g-edge-strong);
	border-left: 1px solid var(--g-edge-strong);
	border-radius: var(--g-radius);
	box-shadow: var(--g-shadow-float);
	font-family: var(--g-font-body);
	font-size: 13.5px;
	color: var(--g-text);
}

.g-notice::before {
	content: '';
	width: 8px;
	height: 8px;
	margin-top: 6px;
	flex: none;
	border-radius: 50%;
	background: var(--g-notice-dot);
}

.g-notice--alert { --tone: var(--g-plague); }
.g-notice--ok { --tone: var(--g-viable-hi); }
.g-notice--inert { --tone: var(--g-neutral-status); }

.g-notice-title {
	display: block;
	font-family: var(--g-font-stencil);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--tone);
}

/* Working: a sweep across a recessed strip. Indeterminate on purpose — the
   machine will not pretend to know how long it needs. */
.g-working {
	display: flex;
	align-items: center;
	gap: var(--g-3);
}

.g-working-bar {
	position: relative;
	flex: 1;
	height: 14px;
	overflow: hidden;
	background: var(--g-seam);
	border-radius: 2px;
	box-shadow: var(--g-recess);
}

.g-working-bar::after {
	content: '';
	position: absolute;
	top: 2px;
	bottom: 2px;
	left: 0;
	width: 30%;
	background-image: repeating-linear-gradient(90deg, var(--g-hazard) 0 7px, transparent 7px 10px);
	animation: g-sweep 1.4s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

@keyframes g-sweep {
	0% { transform: translateX(-110%); }
	100% { transform: translateX(360%); }
}

.g-working-label {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
	white-space: nowrap;
}

/* Restyled for v4: a dashed hairline box, no bevel (docs/DESIGN_SYSTEM.md
   section 6). */
.g-empty {
	padding: var(--g-7) var(--g-4);
	text-align: center;
	border: 1px dashed var(--g-edge-strong);
	border-radius: var(--g-radius);
	font-family: var(--g-font-body);
	font-size: 14px;
	font-weight: 400;
	color: var(--g-text-2);
}

.g-empty b {
	display: block;
	font-family: var(--g-font-legend);
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	color: var(--g-text);
	font-size: 13px;
	font-weight: 500;
	margin-bottom: var(--g-1);
}

/* -------------------------------------------------------------------------
   SPECIMEN MOUNT
   Artwork behind glass in a brass-bezelled housing, bolted to the panel.
   ------------------------------------------------------------------------- */

.g-specimen {
	position: relative;
	aspect-ratio: 1;
	padding: 8px;
	background: linear-gradient(160deg, var(--g-hull-hi), var(--g-hull));
	border: 2px solid var(--g-trim-dark);
	border-radius: var(--g-radius-housing);
	box-shadow: var(--g-relief), var(--g-drop);
}

.g-specimen-inner {
	position: relative;
	height: 100%;
	background: color-mix(in srgb, var(--g-el) 80%, transparent);
	border-radius: var(--g-radius);
	box-shadow: var(--g-recess);
	overflow: hidden;
}

.g-specimen-inner img,
.g-specimen-inner svg,
.g-specimen-inner > div {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* -------------------------------------------------------------------------
   COLLECTIONS
   ------------------------------------------------------------------------- */

.g-tile {
	display: block;
	text-decoration: none;
	padding: var(--g-2);
	background: var(--g-hull);
	border: var(--g-hairline) solid var(--g-seam);
	border-radius: var(--g-radius);
	box-shadow: var(--g-relief);
	transition: background var(--g-snap), transform var(--g-snap);
}

.g-tile:hover {
	background: var(--g-hull-hi);
	transform: translateY(-1px);
}

.g-tile-art {
	aspect-ratio: 1;
	background: color-mix(in srgb, var(--g-el) 85%, transparent);
	border-radius: 2px;
	box-shadow: var(--g-recess);
	overflow: hidden;
}

.g-tile-meta {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--g-2);
	padding: var(--g-2) var(--g-1) 0;
}

.g-tile-name {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-body);
	font-weight: 600;
	text-transform: uppercase;
	color: var(--g-ink);
}

.g-tile-id {
	font-family: var(--g-font-mono);
	font-size: var(--g-size-micro);
	color: var(--g-ink-low);
}

.g-record {
	display: grid;
	grid-template-columns: minmax(8rem, 15rem) 1fr;
	gap: var(--g-3) var(--g-5);
	padding: var(--g-4);
	border-bottom: var(--g-hairline) solid var(--g-rule-faint);
	transition: background var(--g-snap);
}

.g-record:hover { background: rgba(255, 244, 214, 0.03); }

.g-record-term {
	font-family: var(--g-font-stencil);
	font-weight: 600;
	font-size: var(--g-size-lead);
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	/* a printed term on the hull, not machine output: it does not emit. Records
	   inside an element-keyed container still retune, via .g-el-* below. */
	color: var(--g-ink);
	margin: 0;
}

[class*='g-el-'] .g-record-term {
	color: var(--g-el);
}

.g-record-body {
	font-family: var(--g-font-ui);
	font-size: var(--g-size-small);
	line-height: 1.6;
	color: var(--g-ink-mid);
	margin: 0;
}

/* Key/value, as printed on a spec plate riveted to the machine. */
.g-spec {
	display: grid;
	grid-template-columns: minmax(7rem, auto) 1fr;
	gap: var(--g-2) var(--g-5);
	align-items: baseline;
}

.g-spec-key {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-low);
}

.g-spec-val {
	font-family: var(--g-font-mono);
	font-size: var(--g-size-small);
	font-variant-numeric: tabular-nums;
	color: var(--g-ink);
}

.g-data {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--g-font-mono);
	font-size: var(--g-size-tiny);
}

.g-data th {
	text-align: left;
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-low);
	padding: var(--g-2) var(--g-3);
	border-bottom: var(--g-hairline) solid var(--g-rule);
}

.g-data td {
	padding: var(--g-2) var(--g-3);
	border-bottom: var(--g-hairline) solid var(--g-rule-faint);
	color: var(--g-ink);
	font-variant-numeric: tabular-nums;
}

.g-data tr:hover td { background: rgba(255, 244, 214, 0.03); }

.g-link {
	color: var(--g-el);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}

.g-link:hover { color: var(--g-ink); }

/* -------------------------------------------------------------------------
   LAYOUT
   ------------------------------------------------------------------------- */

/* One max-width for every page (round3-coherence.md rule 3): 1440px is the
   widest shell already in use anywhere on the site (reclamation.css's
   .rec-shell--match/--intro/--draft modifiers), so this raises every other
   page's frame to match rather than narrowing that one. Body copy still
   caps at --g-measure regardless — only the outer frame and the terminal
   object inside it get wider. */
.g-shell {
	max-width: 1440px;
	margin: 0 auto;
	padding: 0 var(--g-5);
}

.g-measure { max-width: var(--g-measure); }

/* -------------------------------------------------------------------------
   FRAME (v3, "one frame" — round3-coherence.md rule 3)
   Every page: navbar, .g-shell, .g-masthead, then the terminal object at
   full shell width. No page centers a narrower object in the shell.
   ------------------------------------------------------------------------- */

.g-masthead {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--g-4);
	/* Consistent margin below the navbar and above the object, on every
	   page, regardless of terminal. */
	margin: var(--g-7) 0 var(--g-6);
}

/* The kicker-over-title block, on the left. Plain block children stack on
   their own; this wrapper exists so .g-masthead-aside has something to sit
   beside rather than wrapping under the title. */
.g-masthead-heading {
	display: flex;
	flex-direction: column;
	gap: var(--g-2);
	min-width: 0;
}

/* The optional right-hand slot: one .g-key, or a .g-nameplate. */
.g-masthead-aside {
	display: flex;
	align-items: center;
	gap: var(--g-3);
	flex: none;
}

@media (max-width: 720px) {
	.g-masthead {
		flex-direction: column;
		align-items: flex-start;
	}
}

/* A generic wrapper the terminal bodies extend: every object (.g-case,
   .g-counter, .g-desk, .g-cover-plate) spans the shell width with the same
   outer margin, so no page centers a narrower object inside .g-shell. */
.g-case,
.g-counter,
.g-desk,
.g-cover-plate,
.g-object {
	width: 100%;
	margin: 0 auto var(--g-8);
}

@media (max-width: 640px) {
	.g-record { grid-template-columns: 1fr; gap: var(--g-2); }
}

/* -------------------------------------------------------------------------
   REDUCED MOTION
   ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.g-working-bar::after {
		animation: none;
		width: 100%;
		opacity: 0.6;
	}

	.g-btn,
	.g-meter-fill,
	.g-segment,
	.g-check-box::after,
	.g-tile {
		transition: none;
	}
}

/* -------------------------------------------------------------------------
   CONSOLE HEADER
   The navbar as a bulkhead strip: enamelled metal, stencilled legends, one
   hazard-painted key. Overrides bootstrap, hence the specificity.
   ------------------------------------------------------------------------- */

.xalian-navbar.navbar {
	background: linear-gradient(180deg, var(--g-hull-hi) 0%, var(--g-hull) 100%) !important;
	border: 0 !important;
	border-bottom: 2px solid var(--g-seam) !important;
	box-shadow: inset 0 1px 0 var(--g-bevel-light), 0 3px 10px rgba(0, 0, 0, 0.6);
	padding: var(--g-2) 0 !important;
	z-index: var(--g-layer-nav) !important;
}

.xalian-navbar .nav-link {
	font-family: var(--g-font-stencil) !important;
	font-size: var(--g-size-body) !important;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid) !important;
	padding: var(--g-2) var(--g-4) !important;
	transition: color var(--g-snap);
}

.xalian-navbar .nav-link:hover,
.xalian-navbar .nav-link:focus-visible {
	color: var(--g-ink) !important;
}

.xalian-navbar .xalian-generator-navbar-button {
	color: var(--g-accent-ink) !important;
	background: var(--g-hazard);
	border: var(--g-hairline) solid var(--g-hazard-dark);
	border-radius: var(--g-radius);
	box-shadow: var(--g-relief), 0 3px 0 var(--g-seam);
	margin-left: var(--g-3);
	font-style: normal !important;
	font-weight: 600;
	transition: background var(--g-snap), transform var(--g-snap);
}

.xalian-navbar .xalian-generator-navbar-button:hover {
	background: var(--g-accent-hover);
	color: var(--g-accent-ink) !important;
}

.xalian-navbar .xalian-generator-navbar-button:active {
	transform: translateY(3px);
	box-shadow: var(--g-recess);
}

.xalian-navbar .navbar-auth-button-wrapper { margin-left: var(--g-2); }

.xalian-navbar .navbar-auth-button-wrapper .btn {
	font-family: var(--g-font-stencil) !important;
	font-size: var(--g-size-body) !important;
	font-style: normal !important;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink) !important;
	background: var(--g-hull-hi) !important;
	border: var(--g-hairline) solid var(--g-seam) !important;
	border-radius: var(--g-radius) !important;
	padding: var(--g-1) var(--g-4) !important;
	box-shadow: var(--g-relief), 0 3px 0 var(--g-seam) !important;
	/* just above the collapse breakpoint the bar is tight and these were
	   breaking "SIGN IN" across two lines */
	white-space: nowrap;
}

.xalian-navbar .navbar-auth-button-wrapper .btn:hover {
	background: var(--g-hull-hover) !important;
}

.xalian-navbar .navbar-toggler {
	border: var(--g-hairline) solid var(--g-seam);
	border-radius: var(--g-radius);
	background: var(--g-hull-hi);
	box-shadow: var(--g-relief);
	padding: var(--g-2) var(--g-3);
}

.xalian-navbar .username-navbar-link {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-body);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-hazard);
	text-decoration: none;
}

/* -------------------------------------------------------------------------
   BOOTSTRAP TABS
   react-bootstrap <Tabs> renders .nav-tabs, whose defaults are blue links on a
   white pill. Restyled as the same bank of selector keys as .g-segmented.
   ------------------------------------------------------------------------- */

.g-tabs.nav-tabs {
	/* the rail is the bank the keys are set into, so it ends where they do
	   rather than running as an empty bar to the far edge of the page */
	display: inline-flex;
	width: auto;
	max-width: 100%;
	border-bottom: var(--g-hairline) solid var(--g-rule);
	gap: 3px;
	padding: 3px 3px 0;
	background: var(--g-seam);
	border-radius: var(--g-radius) var(--g-radius) 0 0;
}

.g-tabs.nav-tabs .nav-link {
	font-family: var(--g-font-stencil);
	font-size: var(--g-size-small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
	background: var(--g-hull);
	border: 0;
	border-radius: 2px 2px 0 0;
	box-shadow: var(--g-relief);
	padding: var(--g-2) var(--g-5);
	transition: background var(--g-snap), color var(--g-snap);
}

.g-tabs.nav-tabs .nav-link:hover:not(.active) {
	background: var(--g-hull-hi);
	color: var(--g-ink);
	border: 0;
}

.g-tabs.nav-tabs .nav-link.active {
	color: var(--g-ink-invert);
	background: var(--g-hazard);
	border: 0;
}

.g-tabs.nav-tabs .nav-link:focus-visible {
	outline: 2px solid var(--g-phosphor);
	outline-offset: -3px;
}

/* On a phone the bank wrapped onto a second row and left a ragged empty block
   of rail beside it. A key bank on a machine does not wrap - it runs off the
   edge and you slide it. */
@media (max-width: 575px) {
	.g-tabs.nav-tabs {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
	}

	.g-tabs.nav-tabs::-webkit-scrollbar { display: none; }

	.g-tabs.nav-tabs .nav-link {
		white-space: nowrap;
		padding: var(--g-2) var(--g-4);
	}
}

/* The meter's name column is fixed at 8.5rem, which on a phone leaves the
   strip itself barely 100px. */
@media (max-width: 575px) {
	.g-meter-row {
		grid-template-columns: 6.5rem 1fr 4rem;
		gap: var(--g-2);
	}
}

/* A slider is a track with a thumb you can grip: recessed channel, moulded
   knob, no gradients. */
.g-range {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	height: 14px;
	background: transparent;
	cursor: pointer;
}

/* Restyled for v4: flat track, square thumb, no bevel. */
.g-range::-webkit-slider-runnable-track {
	height: 4px;
	background: var(--g-s2);
	border-radius: 2px;
	box-shadow: none;
}

.g-range::-moz-range-track {
	height: 4px;
	background: var(--g-s2);
	border-radius: 2px;
	box-shadow: none;
}

.g-range::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 14px;
	height: 14px;
	margin-top: -5px;
	background: var(--g-viable);
	border: none;
	border-radius: 0;
	box-shadow: none;
}

.g-range::-moz-range-thumb {
	width: 14px;
	height: 14px;
	background: var(--g-viable);
	border: none;
	border-radius: 0;
	box-shadow: none;
}

.g-range:focus-visible {
	outline: 2px solid var(--g-focus);
	outline-offset: 4px;
}

/* The nav sits on the same rail as page content. */
/* .xalian-navbar/.navbar-shell below (and the whole "CONSOLE HEADER" block
   above it) is dead: navbar.js carries .relay-navbar/.g-cover-plate now, not
   .xalian-navbar. Left alone here (not in this round's scope) rather than
   deleted; pages/relay.css's real .relay-navbar-shell carries the live
   max-width fix, next to it. */
.xalian-navbar .navbar-shell {
	max-width: 1440px;
	margin: 0 auto;
	padding-left: var(--g-5);
	padding-right: var(--g-5);
}

/* bootstrap pads the brand, which pushed the wordmark 30px off the rail every
   page title sits on */
.xalian-navbar .navbar-brand {
	padding-left: 0;
	padding-right: var(--g-5);
}

/* The sticky nav measures against the window while page content measures
   against the scroll area, so the two rails were 5px apart on any page tall
   enough to scroll. Reserving the gutter makes both measure the same box. */
html {
	scrollbar-gutter: stable;
}

/* -------------------------------------------------------------------------
   MEDIUM COMPONENTS (v3)
   Every piece of content lives in exactly one medium: HULL (painted metal,
   fixed, never emits), PAPER (printed once, variable, committed, no
   buttons), or SCREEN (live, variable, the only thing that emits). See
   docs/DESIGN_SYSTEM.md section 2, rule B. Each class below is labelled with
   its medium in a one-line comment. All of them read material tokens and
   retune automatically under any [data-terminal] ancestor.
   ------------------------------------------------------------------------- */

/* === HULL ================================================================ */

/* HULL. The field unit's face: a case with a hinge strip along the top and
   four corner screws, matching .t-field in the mockups. */
.g-case {
	/* Ink on the room is core, ink on the face is material (Rule A /
	   round3-coherence.md): re-scope --g-ink* to this face's own ink so
	   every descendant that reads --g-ink (legends, keys, the masthead
	   nameplate slot, spec keys/values) paints correctly without a
	   per-component override. */
	--g-ink: var(--g-face-ink);
	--g-ink-mid: var(--g-face-ink-mid);
	--g-ink-low: var(--g-face-ink-low);
	position: relative;
	padding: var(--g-5);
	background: var(--g-face);
	color: var(--g-face-ink);
	border-radius: var(--g-radius-panel);
	box-shadow: var(--g-relief), var(--g-drop);
}

/* HULL. The hinge knuckles along the top of a case, where the lid folds. */
.g-case-hinge {
	height: 12px;
	margin: 0 0 var(--g-4);
	background: linear-gradient(180deg, var(--g-trim-light), var(--g-trim-dark));
	border-radius: 0 0 3px 3px;
	box-shadow: inset 0 -2px 3px rgba(0, 0, 0, 0.6);
}

/* HULL. One corner screw. Position with a modifier or inline style:
   .g-case-screw--tl / --tr / --bl / --br. */
.g-case-screw {
	position: absolute;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: radial-gradient(circle at 40% 35%, var(--g-trim-light), var(--g-trim-dark));
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.6);
	pointer-events: none;
}

.g-case-screw--tl { left: 9px; top: 9px; }
.g-case-screw--tr { right: 9px; top: 9px; }
.g-case-screw--bl { left: 9px; bottom: 9px; }
.g-case-screw--br { right: 9px; bottom: 9px; }

/* HULL. A line of fixed text: an asset number, a company name. Never
   variable data. */
.g-asset-plate {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-micro);
	letter-spacing: var(--g-track-wide);
	color: var(--g-face-ink-mid);
	text-transform: uppercase;
	border-top: 1px dashed color-mix(in srgb, var(--g-face-ink) 25%, transparent);
	padding-top: var(--g-2);
	display: flex;
	justify-content: space-between;
	gap: var(--g-3);
}

/* HULL. The registry: a lacquered counter with a lit top edge and a dark
   front lip you stand behind. */
.g-counter {
	/* Ink on the room is core, ink on the face is material (Rule A). */
	--g-ink: var(--g-face-ink);
	--g-ink-mid: var(--g-face-ink-mid);
	--g-ink-low: var(--g-face-ink-low);
	position: relative;
	padding: var(--g-6) var(--g-5) 0;
	background:
		linear-gradient(180deg, rgba(255, 255, 255, 0.05), transparent 18%),
		radial-gradient(90% 40% at 50% 0%, color-mix(in srgb, var(--g-trim) 8%, transparent), transparent 70%),
		linear-gradient(180deg, var(--g-face-hi), var(--g-face));
	color: var(--g-ink);
	border-radius: var(--g-radius);
	box-shadow: var(--g-relief), var(--g-drop);
}

/* HULL. The dark front lip below the counter's writing surface. */
.g-counter-lip {
	height: 16px;
	margin: var(--g-4) calc(var(--g-5) * -1) 0;
	background: linear-gradient(180deg, var(--g-face-lo), var(--g-seam));
	border-top: 1px solid var(--g-trim);
	box-shadow: inset 0 3px 4px rgba(0, 0, 0, 0.8);
}

/* HULL. The recessed well the docket's clip sits in / the space it pins to. */
.g-clip-well { position: relative; padding-top: var(--g-3); }

/* HULL. The archive: a dark desk surface lit by one warm reading-lamp pool.
   The card is the lit thing; the desk stays dim around it. */
.g-desk {
	/* Ink on the room is core, ink on the face is material (Rule A). */
	--g-ink: var(--g-face-ink);
	--g-ink-mid: var(--g-face-ink-mid);
	--g-ink-low: var(--g-face-ink-low);
	position: relative;
	padding: var(--g-6) var(--g-5) var(--g-5);
	background:
		radial-gradient(75% 60% at 50% 40%, rgba(255, 236, 190, 0.35) 0%, rgba(255, 225, 170, 0.12) 40%, transparent 75%),
		linear-gradient(180deg, var(--g-face-hi), var(--g-face-lo));
	color: var(--g-ink);
	border-radius: var(--g-radius);
	box-shadow: var(--g-relief), var(--g-drop);
}

/* HULL. The relay: a sheet-steel cover plate over the electronics, with
   screws and low louvred vents where the warm parts sit. */
.g-cover-plate {
	/* Ink on the room is core, ink on the face is material (Rule A). */
	--g-ink: var(--g-face-ink);
	--g-ink-mid: var(--g-face-ink-mid);
	--g-ink-low: var(--g-face-ink-low);
	position: relative;
	padding: var(--g-6) var(--g-5) var(--g-5);
	background:
		linear-gradient(180deg, rgba(255, 255, 255, 0.06), transparent 30%),
		linear-gradient(160deg, var(--g-face-hi), var(--g-face) 55%, var(--g-face-lo));
	border: 1px solid var(--g-trim);
	border-radius: var(--g-radius);
	box-shadow: var(--g-relief), var(--g-drop);
}

.g-cover-plate::before {
	content: '';
	position: absolute;
	inset: 6px;
	pointer-events: none;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: calc(var(--g-radius) + 2px);
}

/* HULL. One cross-head screw on the cover plate. Position with an inline
   style or a modifier class the way .g-case-screw is positioned. */
.g-cover-screw {
	position: absolute;
	width: 11px;
	height: 11px;
	border-radius: 50%;
	background: radial-gradient(circle at 40% 35%, var(--g-trim-light), var(--g-trim-dark));
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
	pointer-events: none;
}

.g-cover-screw::before,
.g-cover-screw::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	background: var(--g-face-lo);
}

.g-cover-screw::before { width: 7px; height: 1.4px; transform: translate(-50%, -50%); }
.g-cover-screw::after { width: 1.4px; height: 7px; transform: translate(-50%, -50%); }

/* HULL. Low louvred vents, drawn as a stack of slots. */
.g-cover-vents {
	height: 40px;
	background-image: repeating-linear-gradient(
		180deg,
		var(--g-seam) 0 4px,
		transparent 4px 12px
	);
	border-radius: 2px;
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.6);
}

/* HULL. The stencilled unit name and its rev/warning line, silkscreened on
   the cover plate. */
.g-cover-stencil {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-micro);
	letter-spacing: var(--g-track-wide);
	color: var(--g-trim-light);
	text-transform: uppercase;
	opacity: 0.85;
}

.g-cover-stencil small {
	display: block;
	font-family: var(--g-font-out);
	font-size: 0.6rem;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-low);
	text-transform: none;
}

/* HULL. Frames a .g-crt in a steel bezel on four standoffs, for a screen
   that is a bolted-on part rather than built into the face (the relay's
   tube, in a frame, bolted to the cover plate). */
.g-tube {
	position: relative;
	padding: var(--g-1);
	margin: var(--g-2);
	border-radius: calc(var(--g-radius) + 6px);
	background: linear-gradient(160deg, var(--g-trim-light), var(--g-trim-dark));
	box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
}

.g-tube .g-crt { margin: 0; }

/* HULL. One standoff bolt at a corner of .g-tube. */
.g-standoff {
	position: absolute;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: radial-gradient(circle at 40% 35%, var(--g-trim-light), var(--g-trim-dark) 60%);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 0 2px var(--g-face-lo);
	pointer-events: none;
}

.g-standoff--tl { left: -6px; top: -6px; }
.g-standoff--tr { right: -6px; top: -6px; }
.g-standoff--bl { left: -6px; bottom: -6px; }
.g-standoff--br { right: -6px; bottom: -6px; }

/* HULL. A recessed bank keys sit in, with real travel. */
.g-keybank {
	/* Ink on the room is core, ink on the face is material (Rule A). Kept
	   here too (not just on the enclosing object) so a keybank used outside
	   .g-case/.g-counter/.g-desk/.g-cover-plate still reads face ink. */
	--g-ink: var(--g-face-ink);
	--g-ink-mid: var(--g-face-ink-mid);
	--g-ink-low: var(--g-face-ink-low);
	display: flex;
	flex-wrap: wrap;
	gap: var(--g-3);
	align-items: center;
	padding: var(--g-3);
	background: var(--g-face-lo);
	border-radius: var(--g-radius);
	box-shadow: var(--g-recess);
}

/* HULL. The socket one key sits in, deep enough to show the key's side
   wall and the shadow it drops. */
.g-key-socket {
	padding: 4px;
	background: var(--g-seam);
	border-radius: calc(var(--g-radius) + 2px);
	box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.85), inset 0 -1px 0 rgba(255, 255, 255, 0.05);
}

/* HULL. A moulded key: a lit top edge, a 5px side wall, and a drop shadow
   onto the socket. Disabled keys are unpowered, not faded (per Rule C). */
.g-key {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--g-2);
	padding: var(--g-3) var(--g-5);
	font-family: var(--g-font-legend);
	font-size: var(--g-size-small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink);
	background: var(--g-face-hi);
	border: 0;
	border-radius: var(--g-radius);
	box-shadow:
		inset 0 1px 0 var(--g-bevel-light),
		inset 0 -1px 0 rgba(0, 0, 0, 0.3),
		0 5px 0 var(--g-seam),
		0 7px 8px rgba(0, 0, 0, 0.6);
	cursor: pointer;
	transition: transform var(--g-snap), box-shadow var(--g-snap);
}

/* A key is part of the terminal's own face, not the room's hull, so its
   hover state lightens --g-face-hi rather than reading the room's fixed
   --g-hull-hover (which would tint every terminal's keys the same way). */
.g-key:hover:not(:disabled) { background: color-mix(in srgb, var(--g-face-hi) 85%, white); }

.g-key:active:not(:disabled) {
	transform: translateY(4px);
	box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.7);
}

.g-key:focus-visible {
	outline: 2px solid var(--g-phosphor);
	outline-offset: 2px;
}

.g-key--primary {
	color: var(--g-accent-ink);
	background: var(--g-accent);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.25),
		inset 0 -1px 0 rgba(0, 0, 0, 0.25),
		0 5px 0 var(--g-trim-dark),
		0 7px 8px rgba(0, 0, 0, 0.6);
}

/* Unpowered, not faded: the cap is still moulded there, the legend is dead. */
.g-key:disabled {
	color: var(--g-ink-low);
	background: var(--g-face-lo);
	cursor: not-allowed;
	box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.7);
	transform: none;
}

/* HULL. A fixed, painted-on legend. Never variable data. */
.g-legend {
	font-family: var(--g-font-legend);
	font-size: var(--g-size-tiny);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-label);
	color: var(--g-ink-mid);
	margin: 0;
}

/* HULL. The reconditioning-tape label: a strip of tape stuck on at a slight
   angle, its shadow deepening with --g-wear. */
.g-tape {
	display: inline-block;
	background: var(--g-paper);
	color: var(--g-paper-ink);
	font-family: var(--g-font-out);
	font-size: var(--g-size-micro);
	letter-spacing: var(--g-track-label);
	padding: 2px var(--g-3);
	transform: rotate(-2deg);
	box-shadow: 0 calc(1px + var(--g-wear) * 3px) calc(2px + var(--g-wear) * 4px) rgba(0, 0, 0, calc(0.3 + var(--g-wear) * 0.3));
}

/* HULL. A stencilled or engraved plate carrying the object's own name — the
   one place a terminal's --g-font-nameplate face appears outside .g-stamp
   (round3-coherence.md, Rule A / section 6). A single line: field face-lo
   ground with a trim border, registry Cinzel, archive Spectral, relay
   Chakra Petch, readout and the panel baseline IBM Plex Mono. Used by the
   navbar (the relay's own name, replacing a plain .g-legend) and by
   .g-masthead-aside on any page that wants the object's designation next to
   the page title. */
.g-nameplate {
	display: inline-flex;
	align-items: center;
	padding: 2px var(--g-4);
	background: var(--g-face-lo);
	/* Not var(--g-ink): --g-face-lo is always a dark, recessed step, but
	   --g-ink resolves to whichever ink is in scope where a .g-nameplate is
	   placed — light on the room, but the face's own (possibly dark) ink
	   inside a rescoped object such as .g-case (Rule A). Mixing a touch of
	   the plate's own colour into white keeps a faint material tint while
	   staying light regardless of which terminal or scope is in effect. */
	color: color-mix(in srgb, var(--g-face-lo) 12%, white);
	font-family: var(--g-font-nameplate);
	font-size: var(--g-size-tiny);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--g-track-wide);
	border: var(--g-hairline) solid var(--g-trim);
	border-radius: 2px;
	white-space: nowrap;
}

/* === PAPER ================================================================ */

/* PAPER. Matte stock, printed once, committed. Ages by --g-wear: foxing and
   edge darkening scale with it. No buttons ever go inside .g-paper. */
.g-paper {
	position: relative;
	background: var(--g-paper);
	color: var(--g-paper-ink);
	font-family: var(--g-font-paper);
	padding: var(--g-5) var(--g-4) var(--g-4);
	transform: rotate(calc(-0.6deg * var(--g-wear) - 0.2deg));
	box-shadow:
		0 1px 0 rgba(255, 255, 255, 0.25),
		0 calc(6px + var(--g-wear) * 10px) calc(10px + var(--g-wear) * 12px) rgba(0, 0, 0, calc(0.35 + var(--g-wear) * 0.3)),
		0 0 0 1px rgba(0, 0, 0, 0.35);
	background-image:
		radial-gradient(18px 12px at 12% 78%, rgba(120, 80, 30, calc(var(--g-wear) * 0.2)), transparent 70%),
		radial-gradient(10px 8px at 86% 30%, rgba(120, 80, 30, calc(var(--g-wear) * 0.18)), transparent 70%),
		radial-gradient(26px 16px at 70% 92%, rgba(120, 80, 30, calc(var(--g-wear) * 0.16)), transparent 70%),
		linear-gradient(90deg, rgba(90, 70, 40, calc(var(--g-wear) * 0.12)), transparent 12%, transparent 88%, rgba(90, 70, 40, calc(var(--g-wear) * 0.16))),
		linear-gradient(180deg, rgba(90, 70, 40, calc(var(--g-wear) * 0.14)), transparent 10%, transparent 90%, rgba(90, 70, 40, calc(var(--g-wear) * 0.2)));
}

.g-paper .g-kicker,
.g-paper .g-label,
.g-paper .g-legend,
.g-paper .g-spec-key,
.g-paper .g-meter-name { color: var(--g-paper-ink-faint); }

.g-paper .g-title,
.g-paper .g-h2,
.g-paper .g-h3,
.g-paper .g-body,
.g-paper .g-mono,
.g-paper .g-record-body,
.g-paper .g-spec-val,
.g-paper .g-record-term,
.g-paper .g-meter-value { color: var(--g-paper-ink); }

.g-paper .g-link {
	color: var(--g-paper-ink);
	text-decoration: underline;
}

/* PAPER. The registry docket: cream stock with a red margin rule and a
   hatched liver along the top edge, clipped to the counter above it. */
.g-paper--docket {
	background-image:
		linear-gradient(90deg, transparent 0 22px, var(--g-paper-rule) 22px 23px, transparent 23px);
}

.g-paper--docket::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 6px;
	background: repeating-linear-gradient(90deg, var(--g-accent) 0 14px, transparent 14px 20px);
	opacity: 0.7;
}

/* PAPER. The archive's index card: ruled lines, a rod hole at the bottom
   centre, and a row of classification tabs on the top edge. */
.g-paper--card {
	border-radius: 2px 3px 2px 4px;
	background-image:
		linear-gradient(0deg, transparent 0 23px, var(--g-paper-rule) 23px 24px),
		radial-gradient(18px 12px at 12% 78%, rgba(120, 80, 30, calc(var(--g-wear) * 0.16)), transparent 70%),
		radial-gradient(10px 8px at 86% 30%, rgba(120, 80, 30, calc(var(--g-wear) * 0.14)), transparent 70%);
	background-size: 100% 24px, 100% 100%, 100% 100%;
	background-position: 0 10px, 0 0, 0 0;
}

.g-paper--card::after {
	content: '';
	position: absolute;
	left: 50%;
	bottom: 6px;
	width: 11px;
	height: 11px;
	margin-left: -5.5px;
	border-radius: 50%;
	background: var(--g-hull);
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(80, 60, 30, 0.35);
}

/* PAPER. The row of colored classification tabs along a card's top edge. */
.g-paper-tabs {
	position: absolute;
	top: -1px;
	right: var(--g-4);
	display: flex;
	gap: 4px;
}

.g-tab {
	font-family: var(--g-font-out);
	font-size: var(--g-size-micro);
	letter-spacing: var(--g-track-label);
	text-transform: uppercase;
	padding: 3px 9px 4px;
	color: var(--g-tab-ink);
	background: var(--g-el);
	border-radius: 0 0 2px 2px;
	filter: saturate(0.75) brightness(0.94);
}

/* PAPER. A narrow printer slip. */
.g-paper--slip {
	max-width: 22rem;
	padding: var(--g-3) var(--g-3) var(--g-4);
	font-size: var(--g-size-small);
}

/* PAPER. An admission or approval stamp, inked and slightly rotated. */
.g-stamp {
	display: inline-block;
	border: 3px double var(--g-accent);
	color: var(--g-accent);
	/* The stamp is the one other place a terminal's own nameplate face
	   appears (docs/DESIGN_SYSTEM.md Rule A / section 6): an admission stamp
	   is engraved rubber, not a silkscreened legend. */
	font-family: var(--g-font-nameplate);
	font-weight: 700;
	font-size: var(--g-size-tiny);
	letter-spacing: var(--g-track-wide);
	padding: var(--g-2) var(--g-3);
	transform: rotate(-8deg);
	opacity: 0.85;
	text-transform: uppercase;
	text-align: center;
	line-height: 1.2;
	mix-blend-mode: multiply;
}

.g-stamp small {
	display: block;
	font-family: var(--g-font-out);
	font-size: 0.6rem;
	letter-spacing: var(--g-track-label);
	font-weight: 400;
}

/* PAPER (furniture, drawn as hull metal). A steel clip pinning paper down. */
.g-clip {
	position: absolute;
	left: 50%;
	top: -9px;
	transform: translateX(-50%);
	width: 64px;
	height: 18px;
	border-radius: 9px 9px 3px 3px;
	background: linear-gradient(180deg, var(--g-trim-light), var(--g-trim) 55%, var(--g-trim-dark));
	box-shadow: 0 2px 3px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.6);
	z-index: 2;
}

.g-clip::after {
	content: '';
	position: absolute;
	left: 10px;
	right: 10px;
	top: 7px;
	height: 3px;
	background: var(--g-seam);
	border-radius: 2px;
}

/* PAPER. A photograph on corner mounts. Sepia or grayscale per terminal via
   --g-photo-filter (set it inside a terminal block or with a modifier;
   panel and any terminal that does not set it stays a plain plate). */
.g-plate--photo {
	position: relative;
	border: 5px solid var(--g-paper);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
	filter: var(--g-photo-filter, none);
	background: var(--g-el);
}

.g-plate--photo::before,
.g-plate--photo::after {
	content: '';
	position: absolute;
	width: 14px;
	height: 14px;
	background: var(--g-paper-ink);
	z-index: 2;
}

.g-plate--photo::before { left: -5px; top: -5px; clip-path: polygon(0 0, 100% 0, 0 100%); }
.g-plate--photo::after { right: -5px; bottom: -5px; clip-path: polygon(100% 100%, 100% 0, 0 100%); }

/* PAPER. A meter drawn in ink instead of lit bulbs: an outlined track, a
   solid fill with a white hatch overprint. */
.g-meter--ink .g-meter-track,
.g-meter--ink.g-meter {
	background: transparent;
	box-shadow: none;
	border: 1px solid currentColor;
	height: 9px;
	border-radius: 0;
}

.g-meter--ink .g-meter-fill {
	background: currentColor;
	background-image: repeating-linear-gradient(90deg, transparent 0 5px, rgba(255, 255, 255, 0.55) 5px 6px);
	filter: none;
}

/* PAPER. A handwritten cross-reference in the archivist's own hand. */
.g-pencil {
	font-family: 'Caveat', cursive;
	font-size: 1rem;
	color: var(--g-paper-ink-faint);
	transform: rotate(-3deg);
	opacity: 0.85;
	line-height: 1.15;
}

/* PAPER. A typed value on a dotted underline, the way a typewriter fills a
   printed form field. */
.g-paper-field {
	font-family: var(--g-font-paper);
	color: var(--g-paper-ink);
	border-bottom: 1px dotted var(--g-paper-ink-faint);
	padding-bottom: 1px;
}

/* === SCREEN ================================================================ */

/* SCREEN. A colour raster CRT that can carry a full record in element
   colour: bezel, curved-glass highlight, scanlines. The only thing besides
   a lamp that emits. */
.g-crt {
	position: relative;
	padding: var(--g-4);
	background:
		radial-gradient(ellipse 120% 90% at 50% 40%, color-mix(in srgb, var(--g-phosphor) 8%, transparent), transparent 70%),
		var(--g-glass);
	color: var(--g-phosphor);
	font-family: var(--g-font-out);
	border: 2px solid var(--g-trim);
	border-radius: var(--g-radius);
	box-shadow: var(--g-recess), 0 0 0 1px rgba(0, 0, 0, 0.8), var(--g-screen-bloom);
	overflow: hidden;
	display: grid;
	gap: var(--g-3);
}

.g-crt::before {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	border-radius: inherit;
	background: linear-gradient(160deg, rgba(255, 255, 255, 0.09), transparent 38%);
}

.g-crt::after {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.32) 0 1px, transparent 1px 3px);
}

/* Inside a CRT, legends and keys go to the phosphor-dim / phosphor pairing
   and the machine's output face; element chips keep their element hue. */
.g-crt .g-legend,
.g-crt .g-spec-key,
.g-crt .g-meter-name {
	color: var(--g-phosphor-dim);
	font-family: var(--g-font-out);
}

.g-crt .g-record-term,
.g-crt .g-spec-val,
.g-crt .g-meter-value,
.g-crt .move-name {
	color: var(--g-phosphor);
}

.g-crt .g-record-body,
.g-crt .move-description,
.g-crt .g-body {
	color: var(--g-phosphor-dim);
	font-family: var(--g-font-out);
}

.g-crt .move-name {
	font-family: var(--g-font-out);
}

.g-crt .g-link {
	color: var(--g-phosphor);
	text-decoration: underline;
}

/* SCREEN. A one-line status strip: the machine's own voice, not a record.
   Amber on a field terminal, the trace signal on a relay, and so on. */
.g-vfd {
	display: flex;
	justify-content: space-between;
	gap: var(--g-3);
	background: var(--g-vfd-glass);
	color: var(--g-vfd);
	font-family: var(--g-font-out);
	font-size: var(--g-size-small);
	letter-spacing: 0.04em;
	padding: var(--g-2) var(--g-3);
	border-radius: 2px;
	box-shadow: inset 0 0 12px rgba(0, 0, 0, 0.8), 0 0 0 2px var(--g-trim);
}

.g-vfd .g-screen-line--dim,
.g-vfd .dim { color: color-mix(in srgb, var(--g-vfd) 45%, transparent); }

/* SCREEN. The registry's ledger: an amber line set into a recessed bezel
   with two brass screws, per the mockup. */
.g-bezel {
	position: relative;
	padding: var(--g-2) var(--g-6);
	background: linear-gradient(180deg, var(--g-hull), var(--g-hull-hi));
	border: 1px solid var(--g-seam);
	box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.9), 0 1px 0 color-mix(in srgb, var(--g-trim) 25%, transparent);
}

.g-bezel::before,
.g-bezel::after {
	content: '';
	position: absolute;
	top: 50%;
	width: 7px;
	height: 7px;
	margin-top: -3.5px;
	border-radius: 50%;
	background: radial-gradient(circle at 35% 35%, var(--g-trim-light), var(--g-trim-dark));
	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.8);
}

.g-bezel::before { left: 8px; }
.g-bezel::after { right: 8px; }

.g-ledger {
	background: var(--g-glass);
	color: var(--g-phosphor);
	font-family: var(--g-font-out);
	font-size: var(--g-size-small);
	padding: var(--g-2) var(--g-3);
	border: 1px solid var(--g-trim-dark);
	display: flex;
	justify-content: space-between;
	gap: var(--g-3);
	letter-spacing: 0.04em;
	box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.9);
}

.g-ledger .dim { color: var(--g-phosphor-dim); }

/* SCREEN. The Generator's own voice: paper-white monochrome, no element
   colour, no legends. Apply to a .g-crt while a creature is printing. */
.g-readout-mode {
	--g-phosphor: var(--g-readout-phosphor);
	--g-phosphor-dim: var(--g-readout-phosphor-dim);
	--g-glass: var(--g-readout-glass);
	color: var(--g-phosphor);
}

.g-readout-mode [class*='g-el-'],
.g-readout-mode .g-chip,
.g-readout-mode .g-tab { background: var(--g-phosphor); color: var(--g-readout-ink); }

/* A blinking text cursor for the machine's live voice. Off under reduced
   motion, per Rule "motion is mechanical". */
.g-cursor {
	display: inline-block;
	width: 9px;
	height: 14px;
	background: currentColor;
	vertical-align: -2px;
	animation: g-blink 1s steps(1) infinite;
}

@keyframes g-blink { 50% { opacity: 0; } }

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

/* =========================================================================
   VERSION 4: NEW COMPONENTS
   docs/DESIGN_SYSTEM.md sections 5 (chamfer), 6 (spinner, badges, tabs,
   toggle), 8 (brand). Values and technique taken from
   docs/design/v4-foundations.html and docs/design/v4-chrome.html.
   ========================================================================= */

/* --- glass: live-data surface, chamfered ---------------------------------
   Two clipped layers so the hairline follows the cut contour (section 14). */
.g-glass {
	position: relative;
	background: var(--g-glass-edge);
	clip-path: var(--g-chamfer);
	border: 0;
	border-radius: 0;
}

.g-glass::before {
	content: '';
	position: absolute;
	inset: 1px;
	background: var(--g-surface-live);
	clip-path: var(--g-chamfer);
	box-shadow: inset 0 12px 30px rgba(0, 0, 0, 0.35);
	z-index: 0;
}

.g-glass > * {
	position: relative;
	z-index: 1;
}

/* --- badges: state, not content ------------------------------------------
   Chips are content (an element hue); badges are state, in the world's own
   words (section 6). Square pills with a hairline edge. */
.g-badge {
	display: inline-flex;
	align-items: center;
	font-family: var(--g-font-legend);
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	font-size: 11px;
	padding: 2px 8px;
	border-radius: 0;
	border: 1px solid var(--g-edge-strong);
	color: var(--g-text-2);
	background: transparent;
}

.g-badge--ok { border-color: var(--g-viable-lo); color: var(--g-viable-hi); background: var(--g-viable-tint); }
.g-badge--danger { border-color: var(--g-plague); color: var(--g-plague-outline-ink); background: var(--g-plague-tint); }
.g-badge--warn { border-color: var(--g-caution); color: var(--g-caution); background: var(--g-caution-tint); }
.g-badge--info { border-color: var(--g-edge-strong); color: var(--g-neutral-status); background: transparent; }

/* --- tabs ------------------------------------------------------------- */
.g-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
}

.g-tab-link {
	font-family: var(--g-font-legend);
	text-transform: uppercase;
	letter-spacing: var(--g-track-legend);
	font-size: 13px;
	padding: var(--g-2) var(--g-4);
	background: var(--g-s1);
	border: 1px solid var(--g-edge);
	border-bottom: 2px solid transparent;
	color: var(--g-text-2);
	cursor: pointer;
	transition: color var(--g-dur-1) var(--g-ease-out), border-color var(--g-dur-1) var(--g-ease-out);
}

.g-tab-link:hover { color: var(--g-text); }
.g-tab-link.on { color: var(--g-text); border-bottom-color: var(--g-viable); }
.g-tab-link:focus-visible { outline: 2px solid var(--g-focus); outline-offset: -2px; }

/* --- toggle: a mechanism-only variant, no label wrapper ------------------- */
.g-toggle {
	display: inline-block;
	width: 36px;
	height: 20px;
	border-radius: 10px;
	background: var(--g-s2);
	border: 1px solid var(--g-edge);
	position: relative;
	vertical-align: middle;
	cursor: pointer;
	transition: background var(--g-dur-1) var(--g-ease-out);
}

.g-toggle::after {
	content: '';
	position: absolute;
	top: 2px;
	left: 2px;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--g-ink-3);
	transition: transform var(--g-dur-1) var(--g-ease-out), background var(--g-dur-1) var(--g-ease-out);
}

.g-toggle.on { background: var(--g-viable-lo); border-color: transparent; }
.g-toggle.on::after { transform: translateX(16px); background: var(--g-viable-hi); }
.g-toggle:focus-visible { outline: 2px solid var(--g-focus); outline-offset: 2px; }

/* --- helix spinner ---------------------------------------------------------
   The DNA mark with its strands at low opacity and its rungs lighting in
   sequence, top to bottom. Never a skeleton (section 6). The SVG markup is
   the React component in src/components/brand/helixSpinner.js; this is only
   the paint and the animation. */
.g-spinner {
	display: block;
	overflow: visible;
	width: 32px;
	height: auto;
}

.g-spinner--sm { width: 20px; }
.g-spinner--lg { width: 56px; }

.g-spinner .strand {
	fill: none;
	stroke: var(--g-viable-hi);
	stroke-width: 4px;
	stroke-linejoin: round;
	opacity: 0.28;
}

.g-spinner .rung {
	stroke: var(--g-viable-hi);
	stroke-width: 8px;
	stroke-linecap: round;
	opacity: 0.15;
	animation: g-spinner-rung 1.4s var(--g-ease-out) infinite;
	animation-delay: calc(var(--i) * .16s);
}

.g-spinner--sm .rung { stroke-width: 12px; }

@keyframes g-spinner-rung {
	0%, 60%, 100% { opacity: 0.15; }
	20% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.g-spinner .rung { animation: none; opacity: 0.7; }
}

/* --- brand lockup ----------------------------------------------------------
   Helix at left, then the word, in --g-viable-hi (section 8). Navbar size by
   default; --brand modifies to the splash size. */
.g-brand {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	color: var(--g-viable-hi);
	text-transform: uppercase;
	font-family: var(--g-font-brand);
	font-size: 22px;
	letter-spacing: .04em;
	line-height: 1;
	text-decoration: none;
}

.g-brand .strand,
.g-helix .strand {
	fill: none;
	stroke: var(--g-viable-hi);
	stroke-width: 5px;
	stroke-linejoin: round;
}

.g-brand .rung,
.g-helix .rung {
	stroke: var(--g-viable-hi);
	stroke-width: 9px;
	stroke-linecap: round;
}

.g-brand .g-brand-mark {
	height: 28px;
	display: block;
	overflow: visible;
}

.g-brand--big {
	font-size: 64px;
	gap: 22px;
}

.g-brand--big .g-brand-mark { height: 84px; }

/* The splash-size lockup does not shrink its own text, so it must not be
   asked to sit in a column narrower than its content on small viewports. */
@media (max-width: 480px) {
	.g-brand--big {
		font-size: 40px;
		gap: 14px;
	}

	.g-brand--big .g-brand-mark { height: 52px; }
}

/* --- card link: a .g-panel that is a link --------------------------------- */
.g-card-link {
	display: block;
	text-decoration: none;
	color: inherit;
	transition: background var(--g-dur-1) var(--g-ease-out);
}

.g-card-link:hover { background: var(--g-s2); }
.g-card-link:focus-visible { outline: 2px solid var(--g-focus); outline-offset: 2px; }

/* --- react-bootstrap modal hooks -------------------------------------------
   Pass `container` to the react-bootstrap Modal so it portals inside .g-page
   and these tokens apply (section 14). */
.g-page .modal-content {
	background: var(--g-s2);
	color: var(--g-text);
	border: 1px solid var(--g-edge-strong);
	border-radius: 0;
	box-shadow: var(--g-shadow-float), inset 0 1px 0 var(--g-edge-hi);
}

.g-page .modal-backdrop {
	background: var(--g-void);
}

.g-page .modal-backdrop.show {
	opacity: 0.72;
}
