/* © 2026 William C. Chesher. All Rights Reserved. */
/* launch.css - the launch design system compiled for the game: tokens (night, day), the ln-* components, and the shell's own surfaces */

/* No build step. Three parts, in this order:
     1. the fonts, self-hosted (OFL; licenses beside them in fonts/), latin only, the weights in use
     2. the tokens from the design system's tokens.json: Night always, whatever the computer prefers (Maestro,
        2026-10-16: "Night default across the board"); Day only when the student chooses it (data-theme="day").
        The Night colours are emitted a second time under .ln-night, for a frame that is night by nature
        (the broadcast, the control room) and must stay night on a Day page
     3. the design system's components (components/bundle.css, verbatim but its font @import and body rule),
        then the shell: title screen, console, message center, the bay, the manifest, the teacher's room,
        and the three flourishes the shell owns: 01 the Quindar caption bar, 02 hold to sign, 05 rolling digits.
   Do not invent hues: every color below is a token. */

/* ==================================================================================================
   1. Fonts
   ================================================================================================== */
@font-face { font-family: "Barlow"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/barlow-400.woff2") format("woff2"); }
@font-face { font-family: "Barlow"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/barlow-600.woff2") format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/barlow-condensed-600.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 100 800; font-display: swap; src: url("fonts/jetbrains-mono.woff2") format("woff2"); }
@font-face { font-family: "DSEG7 Classic"; font-style: normal; font-weight: 400 700; font-display: swap; src: url("fonts/dseg7-classic-700.woff2") format("woff2"); }

/* ==================================================================================================
   2. Tokens (generated from the design system's tokens.json; edit there, then here)
   ================================================================================================== */
:root {
  --font-display: "Barlow Condensed", "Arial Narrow", system-ui, sans-serif;
  --font-body: Barlow, system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 40px;
  --space-7: 64px;
  --radius-0: 0px;
  --radius-1: 2px;
  --blur-glass: 16px;
  --flow-drift: 90s;
  --flow-ui: 240ms;
  --ease-machined: cubic-bezier(0.2, 0, 0, 1);
  --ground: #0a0a0c;
  --surface: #121215;
  --surface-raised: #1b1b1f;
  --hairline: #2c2c31;
  --edge: #6e6e76;
  --text-muted: #9a9aa2;
  --text-secondary: #bdbdc3;
  --text: #e9e9eb;
  --flare: #ffffff;
  --on-flare: #0a0a0c;
  --accent: #ff7a2e;
  --on-accent: #0a0a0c;
  --accent-glow: #ff7a2e73;
  --accent-wash: #ff7a2e1f;
  --accent-line: #ff7a2ea6;
  --glass: #16161ab8;
  --veil-1: #ffe6cc0a;
  --veil-2: #ffe6cc14;
  --veil-3: #ffe6cc26;
  --flare-glow: #fff1e04d;
  --key-light: #ffd2a614;
  --shade: #00000099;
  --stream: #8e8e9666;
  --stream-lit: #ffc38acc;
  --telemetry: #7f8fa3;
  --shadow-lift: 0 1px 0 #ffe6cc14 inset, 0 12px 32px -12px #000000cc;
  --shadow-deep: 0 24px 64px -16px #000000f2;
  --glow-accent: 0 0 0 1px #ff7a2e8c, 0 0 18px 2px #ff7a2e59, 0 0 48px 8px #ff7a2e26;
  --glow-flare: 0 0 0 1px #fff1e099, 0 0 22px 4px #ffd2a640;
  --depth-inset: inset 0 1px 0 #ffe6cc26, inset 0 -24px 48px -24px #000000b3;
  color-scheme: dark;
}
:root[data-theme="day"] {
  --ground: #f3f3f4;
  --surface: #ffffff;
  --surface-raised: #e9e9eb;
  --hairline: #d6d6da;
  --edge: #7f7f87;
  --text-muted: #5c5c63;
  --text-secondary: #3c3c42;
  --text: #17171a;
  --flare: #000000;
  --on-flare: #ffffff;
  --accent: #a8460b;
  --on-accent: #ffffff;
  --accent-glow: #a8460b40;
  --accent-wash: #a8460b14;
  --accent-line: #a8460bc0;
  --glass: #ffffffb8;
  --veil-1: #3a20000a;
  --veil-2: #3a200012;
  --veil-3: #3a20001f;
  --flare-glow: #00000026;
  --key-light: #ffb36b1f;
  --shade: #17171a33;
  --stream: #5c5c6352;
  --stream-lit: #a8460bb3;
  --telemetry: #4a5563;
  --shadow-lift: 0 1px 0 #ffffff inset, 0 12px 28px -14px #17171a40;
  --shadow-deep: 0 24px 56px -18px #17171a59;
  --glow-accent: 0 0 0 1px #a8460b80, 0 0 14px 1px #a8460b33;
  --glow-flare: 0 0 0 1px #00000080, 0 0 16px 2px #00000026;
  --depth-inset: inset 0 1px 0 #ffffff, inset 0 -24px 40px -28px #17171a26;
  color-scheme: light;
}
.ln-night {
  --ground: #0a0a0c;
  --surface: #121215;
  --surface-raised: #1b1b1f;
  --hairline: #2c2c31;
  --edge: #6e6e76;
  --text-muted: #9a9aa2;
  --text-secondary: #bdbdc3;
  --text: #e9e9eb;
  --flare: #ffffff;
  --on-flare: #0a0a0c;
  --accent: #ff7a2e;
  --on-accent: #0a0a0c;
  --accent-glow: #ff7a2e73;
  --accent-wash: #ff7a2e1f;
  --accent-line: #ff7a2ea6;
  --glass: #16161ab8;
  --veil-1: #ffe6cc0a;
  --veil-2: #ffe6cc14;
  --veil-3: #ffe6cc26;
  --flare-glow: #fff1e04d;
  --key-light: #ffd2a614;
  --shade: #00000099;
  --stream: #8e8e9666;
  --stream-lit: #ffc38acc;
  --telemetry: #7f8fa3;
  --shadow-lift: 0 1px 0 #ffe6cc14 inset, 0 12px 32px -12px #000000cc;
  --shadow-deep: 0 24px 64px -16px #000000f2;
  --glow-accent: 0 0 0 1px #ff7a2e8c, 0 0 18px 2px #ff7a2e59, 0 0 48px 8px #ff7a2e26;
  --glow-flare: 0 0 0 1px #fff1e099, 0 0 22px 4px #ffd2a640;
  --depth-inset: inset 0 1px 0 #ffe6cc26, inset 0 -24px 48px -24px #000000b3;
  color-scheme: dark;
  color: var(--text);
}


/* ==================================================================================================
   The design system's components (components/bundle.css)
   ================================================================================================== */

/* launch components: plain classes on the tokens. One light source, top left; one accent, ignition, that glows. */
.ln-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-4); }
.ln-col { display: grid; gap: var(--space-3); padding: var(--space-4); }
.ln-eyebrow { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .24em; text-transform: uppercase; color: var(--text-muted); }
:where(.ln-btn, .ln-panel, .ln-placard):focus-visible { outline: 2px solid var(--flare); outline-offset: 3px; box-shadow: var(--glow-flare); }

/* Button */
.ln-btn { appearance: none; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); min-height: 44px; padding: 0 var(--space-5);
  font-family: var(--font-display); font-size: 0.9375rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  border-radius: var(--radius-0); border: 1px solid var(--edge); background: transparent; color: var(--text); cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.ln-btn:hover { border-color: var(--text); }
.ln-btn:hover { background: var(--veil-2); }
.ln-btn-primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); box-shadow: var(--glow-accent); }
.ln-btn-primary:hover { background: var(--accent); filter: brightness(1.08); }
/* a primary that cannot be pressed yet stops being orange: muted words on orange could not be read ("unreadable") */
.ln-btn-primary:disabled, .ln-btn-primary[aria-disabled="true"] { background: transparent; color: var(--text-muted); border-color: var(--hairline);
  box-shadow: none; animation: none; filter: none; }
.ln-btn-hold { border-width: 2px; border-color: var(--flare); color: var(--flare); background: var(--veil-1); }
.ln-btn:disabled { border-color: var(--hairline); color: var(--text-muted); cursor: not-allowed; }

/* Panel: lit from the top-left corner, falling into shade */
.ln-panel { position: relative; padding: var(--space-5); border-radius: var(--radius-0); box-shadow: var(--shadow-lift);
  background: radial-gradient(120% 90% at 0% 0%, var(--key-light), transparent 55%), var(--surface); border-top: 1px solid var(--hairline); }
.ln-panel-title { margin: var(--space-1) 0 var(--space-3); font-family: var(--font-display); font-size: 1.25rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--text); }
.ln-panel :where(p) { margin: 0; font-size: 0.875rem; line-height: 1.45; color: var(--text-secondary); max-width: 52ch; }
.ln-panel-raised { background: radial-gradient(120% 90% at 0% 0%, var(--key-light), transparent 55%), var(--surface-raised); box-shadow: var(--shadow-deep); }
.ln-panel-glass { background: radial-gradient(120% 90% at 0% 0%, var(--veil-3), transparent 50%), var(--glass); box-shadow: var(--depth-inset), var(--shadow-deep);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.2); backdrop-filter: blur(var(--blur-glass)) saturate(1.2); border-top: 1px solid var(--veil-3); }
.ln-panel-active { border-top: 1px solid var(--accent-line); background: radial-gradient(120% 90% at 0% 0%, var(--accent-wash), transparent 60%), var(--surface); }
.ln-panel-active .ln-eyebrow { color: var(--accent); }

/* Readout */
.ln-readout { display: grid; gap: var(--space-1); min-width: 9rem; padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
.ln-readout-value { font-family: var(--font-mono); font-size: 1.75rem; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--text); line-height: 1.05; }
.ln-readout-unit { font-size: 0.8125rem; color: var(--text-muted); margin-left: .35em; }
.ln-readout-live .ln-readout-value { color: var(--accent); text-shadow: 0 0 18px var(--accent-glow); }
.ln-readout-live { border-top-color: var(--accent-line); }

/* Countdown */
.ln-countdown { display: grid; gap: var(--space-2); justify-items: start; }
.ln-countdown-clock { display: inline-flex; align-items: baseline; gap: .35em; font-family: "DSEG7 Classic", var(--font-mono); font-size: 3rem; font-weight: 500; letter-spacing: .02em; font-variant-numeric: tabular-nums; color: var(--accent); line-height: 1;
  text-shadow: 0 0 24px var(--accent-glow), 0 0 2px var(--accent-glow); }
.ln-countdown-step { font-family: var(--font-display); font-size: 0.9375rem; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--text-secondary); }
.ln-countdown-hold .ln-countdown-clock { color: var(--text-muted); text-shadow: none; }
.ln-countdown-legend { font-family: var(--font-display); font-size: .3em; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--text-secondary); text-shadow: none; }
.ln-countdown-face { display: inline-grid; }
.ln-countdown-face > * { grid-area: 1 / 1; }
.ln-countdown-ghost { opacity: .1; text-shadow: none; }
.ln-countdown-ghost::before { content: attr(data-ghost); }

/* Placard: a hazmat diamond in monochrome. The fill pattern, not a hue, tells the class apart, and the word is always printed. */
.ln-placard { display: inline-grid; justify-items: center; gap: var(--space-2); }
.ln-placard-diamond { width: 52px; height: 52px; transform: rotate(45deg); border: 2px solid var(--text); background: var(--surface); }
.ln-placard-word { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .18em; text-transform: uppercase; color: var(--text-secondary); }
.ln-placard-fuel .ln-placard-diamond { background: var(--text); }
.ln-placard-oxidizer .ln-placard-diamond { background: repeating-linear-gradient(0deg, var(--text) 0 3px, transparent 3px 8px); }
.ln-placard-energetic .ln-placard-diamond { background: radial-gradient(var(--text) 1.6px, transparent 1.8px) 0 0 / 8px 8px; }
.ln-placard-heat .ln-placard-diamond { background: repeating-linear-gradient(90deg, var(--text) 0 3px, transparent 3px 8px); }
.ln-placard-stored .ln-placard-diamond { box-shadow: inset 0 0 0 5px var(--surface), inset 0 0 0 7px var(--text); }
.ln-placard-selected .ln-placard-diamond { border-color: var(--accent); box-shadow: var(--glow-accent); }
.ln-placard-selected.ln-placard-stored .ln-placard-diamond { box-shadow: inset 0 0 0 5px var(--surface), inset 0 0 0 7px var(--text), var(--glow-accent); }
.ln-placard-selected .ln-placard-word { color: var(--accent); }

/* Alarm: the klaxon. White on black with a pulsing edge, never red, never more than three flashes a second. */
.ln-alarm { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3) var(--space-4); align-items: center; padding: var(--space-4) var(--space-5);
  background: var(--flare); color: var(--on-flare); border-radius: var(--radius-0); position: relative; }
.ln-alarm { box-shadow: var(--glow-flare); }
.ln-alarm::before { content: ""; position: absolute; inset: -5px; border: 2px solid var(--flare); box-shadow: var(--glow-flare); pointer-events: none; }
.ln-alarm-tag { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .24em; text-transform: uppercase; padding: var(--space-1) var(--space-2); border: 1px solid var(--on-flare); }
.ln-alarm-text { font-family: var(--font-display); font-size: 1.25rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.ln-alarm-detail { grid-column: 2; font-size: 0.875rem; margin-top: calc(var(--space-2) * -1); }
:root:not(.is-still) .ln-alarm::before { animation: ln-klaxon 1s steps(2, jump-none) infinite; }
@keyframes ln-klaxon { 0% { opacity: 1; } 100% { opacity: 0; } }

/* Flow: space as a current. A canvas field of particles drifting along slow curved streamlines, behind everything. */
.ln-flow { position: relative; overflow: hidden; background: radial-gradient(70% 90% at 12% 0%, var(--key-light), transparent 60%), var(--ground); }
.ln-flow canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ln-flow > :not(canvas) { position: relative; }

/* Ambient motion: nothing is ever still. Slow, under the threshold of attention, and all of it off under reduced motion. */
.ln-panel { overflow: hidden; isolation: isolate; }
.ln-panel > * { position: relative; z-index: 1; }
.ln-panel::before { content: ""; position: absolute; inset: -40%; z-index: 0; pointer-events: none;
  background: radial-gradient(35% 35% at 30% 30%, var(--key-light), transparent 70%); opacity: .5; }
/* The seam's light runs along the panel's top edge on the compositor: the hairline is nine panels wide, its gradient
   repeating every three, and it slides six to the right in a loop (ln-seam, a transform), which is the same light at
   the same pace the background-position sweep drew, without repainting the panel every frame. The panel's overflow
   clips it. */
.ln-panel::after { content: ""; position: absolute; left: 0; width: 900%; top: 0; height: 1px; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--veil-3) 40%, var(--stream-lit) 50%, var(--veil-3) 60%, transparent); background-size: 33.3333% 100%; opacity: .7; }
/* .ln-stage panels show their overflow (the 3D tilt), so their seam stays one panel wide and still. */
.ln-stage .ln-panel::after { width: 100%; background-size: 300% 100%; }
.ln-panel-active::after { background-image: linear-gradient(90deg, transparent, var(--accent-line) 40%, var(--accent) 50%, var(--accent-line) 60%, transparent); opacity: 1; }
.ln-readout { position: relative; overflow: hidden; }
.ln-readout::after { content: ""; position: absolute; left: 0; top: -1px; height: 1px; width: 30%; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--veil-3), transparent); }
.ln-readout-live::after { background: linear-gradient(90deg, transparent, var(--accent), transparent); }

:root:not(.is-still) .ln-panel::before { animation: ln-keylight 26s ease-in-out infinite alternate; }
:root:not(.is-still) .ln-panel::after { animation: ln-seam 9s linear infinite; }
:root:not(.is-still) .ln-panel-glass::before { animation-duration: 34s; }
:root:not(.is-still) .ln-readout::after { animation: ln-scan 6s linear infinite; }
/* The primary's breath is its glow, on a layer of its own whose opacity breathes (ln-breathe-glow): a box-shadow
   animated in place restyled and repainted the button every frame, about sixty style recalculations a second on every
   console screen with a primary on it (the engine probe, 2026-11-04). The button keeps the breath's low point, the
   layer adds the full glow back at its peak. Under Still the button keeps its full glow and nothing breathes. */
:where(.ln-btn-primary, .ln-placard-selected .ln-placard-diamond) { position: relative; }
:root:not(.is-still) .ln-btn-primary:not(:disabled, [aria-disabled="true"]),
:root:not(.is-still) .ln-placard-selected .ln-placard-diamond { box-shadow: 0 0 0 1px var(--accent-line), 0 0 8px 0 var(--accent-glow); }
:root:not(.is-still) .ln-btn-primary:not(:disabled, [aria-disabled="true"])::after,
:root:not(.is-still) .ln-placard-selected .ln-placard-diamond::after { content: ""; position: absolute; inset: -1px; pointer-events: none;
  box-shadow: var(--glow-accent); animation: ln-breathe-glow 4.5s ease-in-out infinite; }
:root:not(.is-still) .ln-placard-selected .ln-placard-diamond::after { animation-duration: 3s; }
:root:not(.is-still) .ln-readout-live .ln-readout-value, :root:not(.is-still) .ln-countdown-clock { animation: ln-breathe-text 3.6s ease-in-out infinite; }
:root:not(.is-still) .ln-countdown-hold .ln-countdown-clock { animation: none; }
:root:not(.is-still) .ln-btn, :root:not(.is-still) .ln-panel { transition: transform var(--flow-ui) ease, background .15s, border-color .15s; }
:root:not(.is-still) .ln-btn:hover { transform: translateX(2px); }
@keyframes ln-keylight { 0% { transform: translate(-6%, -4%); } 50% { transform: translate(8%, 5%); } 100% { transform: translate(-2%, 9%); } }
@keyframes ln-seam { from { transform: translateX(-66.6667%); } to { transform: translateX(0); } }
:root:not(.is-still) .ln-stage .ln-panel::after { animation: none; }
@keyframes ln-scan { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
@keyframes ln-breathe-box { 0%, 100% { box-shadow: var(--glow-accent); } 50% { box-shadow: 0 0 0 1px var(--accent-line), 0 0 8px 0 var(--accent-glow); } }
@keyframes ln-breathe-glow { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@keyframes ln-breathe-text { 0%, 100% { text-shadow: 0 0 24px var(--accent-glow), 0 0 2px var(--accent-glow); } 50% { text-shadow: 0 0 10px var(--accent-glow); } }

/* Depth: real 3D. A stage sets perspective; panels tilt toward the pointer and their contents sit at different depths. */
.ln-stage { perspective: 1100px; perspective-origin: 50% 40%; }
.ln-stage .ln-panel { transform-style: preserve-3d; transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateZ(var(--z, 0px)); will-change: transform; overflow: visible; }
.ln-stage .ln-panel::before { inset: 0; overflow: hidden; }
.ln-stage .ln-panel > .ln-eyebrow { transform: translateZ(14px); }
.ln-stage .ln-panel > .ln-panel-title { transform: translateZ(30px); }
.ln-stage .ln-panel > p { transform: translateZ(18px); }
.ln-stage .ln-panel > .ln-readout, .ln-stage .ln-panel > .ln-btn { transform: translateZ(40px); }
.ln-plane-back { --z: -120px; opacity: .8; }
.ln-plane-mid { --z: 0px; }
.ln-plane-front { --z: 90px; }
:root:not(.is-still) .ln-stage .ln-panel { transition: transform .5s cubic-bezier(.2,.7,.3,1); animation: ln-hover 14s ease-in-out infinite alternate; }
:root:not(.is-still) .ln-stage .ln-panel.ln-tracking { animation: none; transition: transform .12s linear; }
@keyframes ln-hover { 0% { transform: rotateX(4deg) rotateY(-7deg) translateZ(var(--z, 0px)); } 100% { transform: rotateX(-3deg) rotateY(6deg) translateZ(calc(var(--z, 0px) + 12px)); } }

/* Telemetry: a glyph field for the space areas; a click sends a ping. Script in components/Telemetry/preview.html. */
.ln-telemetry { position: relative; overflow: hidden; background: radial-gradient(70% 90% at 88% 0%, var(--key-light), transparent 60%), var(--ground); cursor: crosshair; }
.ln-telemetry canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ln-telemetry > :not(canvas) { position: relative; cursor: auto; }

/* ==================================================================================================
   3. The shell: launch's own surfaces, composed from the tokens and the ln-* classes above.
   One accent per view, square corners everywhere, light from the top left, words never color alone.
   ================================================================================================== */
/* A brief alarm (alpha/answer.js, the hit as it lands): six pulses, then a steady edge, so a card the crew reads for
   minutes does not flash for minutes. */
:root:not(.is-still) .ln-alarm.ln-alarm-brief::before { animation-iteration-count: 6; }
.alpha-beat-alarm { margin: var(--space-3) 0 var(--space-4); }

/* THE TRIM (wchesher, 2026-10-26: "this many square edges is tedious without something to break it up... what about a
   subtle matrix of lights or a chrome planel design worked in or chrome glints occassionally", then "do the chrome
   glints and light matrix"). shell.js gives every .ln-panel one .ln-trim: a corner matrix of tiny lamps, two or three
   of them lit and slowly blinking on their own clocks, and a chrome glint that crosses the panel's face once in a
   long while, each panel on its own delay (--glint-delay, --lamp-delay). Under Still, the lamps hold and no glint
   passes. It sits under the words and takes no pointer. */
.ln-panel > .ln-trim { position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.ln-trim-lamps { position: absolute; top: 10px; right: 10px; width: 45px; height: 25px;
  background: radial-gradient(circle, var(--text-muted) 1.7px, transparent 2.3px) 0 0 / 10px 10px; opacity: .32; }
.ln-trim-lamps::before, .ln-trim-lamps::after { content: ""; position: absolute; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 6px var(--accent-glow); opacity: .9; }
.ln-trim-lamps::before { left: 12px; top: 2px; }
.ln-trim-lamps::after { left: 32px; top: 12px; background: var(--good, #3bd6a6); box-shadow: 0 0 4px var(--good, #3bd6a6); }
.ln-trim-glint { position: absolute; top: -20%; bottom: -20%; left: 0; width: 38%; opacity: 0;
  background: linear-gradient(105deg, transparent 0 38%, rgba(255, 255, 255, .05) 45%, rgba(255, 255, 255, .13) 50%,
    rgba(255, 255, 255, .05) 55%, transparent 62% 100%); transform: translateX(-120%) skewX(-12deg); }
:root[data-theme="day"] .ln-trim-glint { background: linear-gradient(105deg, transparent 0 40%, rgba(255, 255, 255, .45) 50%, transparent 60% 100%); }
:root:not(.is-still) .ln-trim-lamps::before { animation: ln-lamp 5.2s steps(1, end) infinite; animation-delay: var(--lamp-delay, 0s); }
:root:not(.is-still) .ln-trim-lamps::after { animation: ln-lamp 7.9s steps(1, end) infinite; animation-delay: calc(var(--lamp-delay, 0s) * -1.7); }
:root:not(.is-still) .ln-trim-glint { animation: ln-glint 23s ease-in-out infinite; animation-delay: var(--glint-delay, 0s); }
@keyframes ln-lamp { 0%, 62% { opacity: .9; } 63%, 71% { opacity: .15; } 72%, 100% { opacity: .9; } }
@keyframes ln-glint { 0%, 88% { opacity: 0; transform: translateX(-120%) skewX(-12deg); }
  89% { opacity: 1; } 96% { opacity: 1; transform: translateX(300%) skewX(-12deg); } 97%, 100% { opacity: 0; transform: translateX(300%) skewX(-12deg); } }
@media print { .ln-trim { display: none; } }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  /* a control reached by Tab or Shift+Tab is never under the sticky header or the caption bar's reserved band
     (shell.js publishes --caption-band from the bar's own height), nor under Alpha's sticky move bar or seam
     (console.js publishes --sticky-band from whichever is up) */
  scroll-padding-top: calc(64px + var(--space-4) + var(--sticky-band, 0px)); scroll-padding-bottom: var(--caption-band, 120px); }
body {
  margin: 0; min-height: 100vh; min-height: 100dvh; background: var(--ground); color: var(--text);
  font-family: var(--font-body); font-size: 1rem; line-height: 1.5;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
}
::selection { background: var(--accent-wash); color: var(--text); }
h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); font-weight: 600; text-transform: uppercase; text-wrap: balance; }
p { margin: 0; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }
.visually-hidden, .surface .is-echo { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--text-muted); }
.secondary { color: var(--text-secondary); }

/* Focus: the flare ring, everywhere, keyboard only. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--flare); outline-offset: 3px; box-shadow: var(--glow-flare); border-radius: var(--radius-1);
}
/* One focus look on an Alpha console (console.js paintMission): the side column (H.A.L., the chairs, the drawer) takes
   Alpha's ring with a ground gap (alpha.css --al-focus) instead of the flare outline and glow; the Alpha regions keep
   their own rules, the hotspot's bracket included. */
/* Just my job (Maestro, 2026-10-28, "redesign the console so that they get limited information"; "simple simple
   simple"): on Alpha's console a student sees their own move, their own chair's cards, H.A.L. and the case file. A
   crewmate's card (alpha/fold.js data-crewmate), the step's whole plan under the move bar and the base map leave the
   page; proposals waiting on this student still reach them through For you. The window's caption is a word the
   picture already says. */
body.is-alpha-console #direction,
body.is-alpha-console #surface [data-crewmate],
body.is-alpha-console #base-panel,
body.is-alpha-console #proposals-panel,
body.is-alpha-console .console-window .porthole-caption { display: none !important; }
body.is-alpha-console :not(.al-page, .al-night, .al-page *, .al-night *):focus-visible {
  outline: none; box-shadow: var(--al-focus, 0 0 0 2px #0d0d0c, 0 0 0 4px #ffffff);
}
/* A heading the console focuses for a screen reader (the phase title at every step, tabindex -1) shows no ring here
   either, as [tabindex="-1"]:focus says everywhere else: the rule above outranked it, and the title's white ring showed
   at the column's edges past the act card's curtain during the cold open (QA pass, 2026-10-31). */
body.is-alpha-console :is(h1, h2, h3)[tabindex="-1"]:focus { box-shadow: none; }

/* Type, on the system's scale */
.display-xl { font-family: var(--font-display); font-size: 4rem; line-height: .95; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.display-l { font-family: var(--font-display); font-size: 2.25rem; line-height: 1; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.title { font-family: var(--font-display); font-size: 1.25rem; line-height: 1.2; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
.eyebrow { font-family: var(--font-mono); font-size: 0.6875rem; line-height: 1.3; font-weight: 500; letter-spacing: .24em; text-transform: uppercase; color: var(--text-muted); }
.body-s { font-size: 0.875rem; line-height: 1.45; }
.data { font-family: var(--font-mono); font-size: 0.875rem; line-height: 1.4; font-variant-numeric: tabular-nums; }
.cue { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .08em; color: var(--text-muted); }

/* A square status mark: never a dot, never color alone (its word always sits beside it). */
.square { display: inline-block; width: 8px; height: 8px; flex: none; border: 1px solid var(--edge); background: transparent;
  transition: background var(--flow-ui), border-color var(--flow-ui), box-shadow var(--flow-ui); }
.square.is-filled { background: var(--text-secondary); border-color: var(--text-secondary); }
.square.is-lit { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 10px var(--accent-glow); }

/* Buttons: the system's, with a compact size and a full-width option */
.ln-btn { text-decoration: none; white-space: nowrap; }
.ln-btn-compact { min-height: 44px; padding: 0 var(--space-4); font-size: 0.875rem; letter-spacing: .14em; }
.ln-btn-block { width: 100%; }
.ln-btn-quiet { border-color: transparent; color: var(--text-secondary); }
.ln-btn-quiet:hover { border-color: var(--edge); color: var(--text); }
/* "On" is said the way the tabs say it: the accent edge and an underline, never a fainter border than "off" */
.ln-btn[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); background: var(--accent-wash); color: var(--text); }
.ln-btn:disabled:hover { background: transparent; transform: none; }
/* A control at its limit keeps its focus (aria-disabled) and looks as a disabled one does */
.ln-btn[aria-disabled="true"] { border-color: var(--hairline); color: var(--text-muted); cursor: not-allowed; }
.ln-btn[aria-disabled="true"]:hover { background: transparent; transform: none; }

/* Fields: a mono label over a machined input */
.field { display: grid; gap: var(--space-2); }
.field-label { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .2em; text-transform: uppercase; color: var(--text-secondary); }
.field-hint { font-size: 0.8125rem; line-height: 1.4; color: var(--text-muted); }
.field-hint a { color: var(--text); text-underline-offset: 3px; }
.input { width: 100%; min-height: 48px; padding: 0 var(--space-3); border-radius: var(--radius-0); border: 1px solid var(--edge);
  background: var(--surface-raised); color: var(--text); font-size: 1rem; transition: border-color .15s, background .15s; }
.input::placeholder { color: var(--text-muted); opacity: 1; }
.input:hover { border-color: var(--text-secondary); }
.input:focus-visible { border-color: var(--flare); }
.input-code { font-family: var(--font-mono); letter-spacing: .18em; text-transform: uppercase; font-variant-numeric: tabular-nums; }
.input-code::placeholder { letter-spacing: .18em; }
textarea.input { min-height: 72px; padding: var(--space-3); line-height: 1.45; resize: vertical; }
.counter { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .08em; color: var(--text-muted); justify-self: end; font-variant-numeric: tabular-nums; }
.counter.is-low { color: var(--text); }

/* The message line under a control: what the console said back */
.reply { min-height: 1.45em; font-size: 0.875rem; line-height: 1.45; color: var(--text-secondary); display: flex; gap: var(--space-2); align-items: baseline; }
.reply:empty { min-height: 0; }
.reply-tag { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; flex: none; }
.reply.is-refused .reply-tag { color: var(--text); padding: 1px 6px; border: 1px solid var(--text); }
.reply.is-accepted .reply-tag { color: var(--accent); }

/* ---- the backdrop: the Flow field behind the title screen ---------------------------------------- */
.backdrop { position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(70% 90% at 12% 0%, var(--key-light), transparent 60%), radial-gradient(60% 70% at 88% 100%, var(--accent-wash), transparent 70%), var(--ground); }
.backdrop canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.backdrop-telemetry { background: radial-gradient(70% 90% at 88% 0%, var(--key-light), transparent 60%), var(--ground); }
/* The glyph field stays clear of the words: it fades out behind the headline column (beside the panels on a
   wide screen, above them when they stack), so no glyph sits under a letter. */
.backdrop-telemetry canvas { -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 62%); mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 62%); }
@media (max-width: 880px) {
  .backdrop-telemetry canvas { -webkit-mask-image: linear-gradient(to bottom, transparent 0, transparent 55%, #000 85%); mask-image: linear-gradient(to bottom, transparent 0, transparent 55%, #000 85%); }
}
.over-backdrop { position: relative; z-index: 1; }
/* A quiet zone under the words (data-quiet): type that sits on a moving field stands on a halo of the ground, so a
   streak or a glyph fades out at the edge of each letter and keeps moving everywhere else. Inherited by every line
   inside, cheap on a shared school PC (no frame of the field changes), and the same under the station's still frame. */
[data-quiet] { text-shadow: 0 0 2px var(--ground), 0 0 12px var(--ground); }

/* ---- the Percival mark, inline so it takes the theme ------------------------------------------- */
.mark { display: block; flex: none; }
.mark .orbit { fill: none; stroke: var(--edge); }
.mark .transfer { fill: none; stroke: var(--text); stroke-linecap: round; }
.mark .sun { fill: var(--edge); }
.mark .earth { fill: var(--text); }
.mark .mars { fill: var(--accent); }
.mark-ignition .mars { filter: drop-shadow(0 0 1.2px var(--accent-glow)); }
.lockup .wordmark { fill: var(--text); }
:root:not(.is-still) .mark-draw .transfer { stroke-dasharray: 48; stroke-dashoffset: 48; animation: mark-transfer 2.4s var(--ease-machined) .3s forwards; }
:root:not(.is-still) .mark-draw .mars { opacity: 0; animation: mark-arrive .6s var(--ease-machined) 2.3s forwards; }
@keyframes mark-transfer { to { stroke-dashoffset: 0; } }
@keyframes mark-arrive { to { opacity: 1; } }

/* ---- the title screen ---------------------------------------------------------------------------- */
.title-screen { position: relative; z-index: 1; min-height: 100vh; min-height: 100dvh; display: grid; grid-template-rows: 1fr auto;
  padding: clamp(24px, 5vh, 64px) max(16px, 5vw) 0; }
/* The words and the sign-in stand in one column on the left; the station (station/window.js, set right of centre) has
   the rest of the window to itself (wchesher, 2026-10-26: "why are we covering the space station?" -- the sign-in sat
   in a right-hand column, over the ring). */
.title-grid { width: 100%; max-width: 1180px; margin: 0; display: grid; gap: var(--space-5) var(--space-6);
  align-content: center; grid-template-columns: minmax(0, 520px); }
.title-grid .sign-in { max-width: 440px; }
.brand { display: grid; gap: var(--space-5); align-content: center; max-width: 560px; }
.brand-mark { width: 88px; height: 88px; margin-left: -6px; }
.brand-eyebrow { display: flex; flex-wrap: wrap; gap: 0 .9em; }
.brand-title { font-size: clamp(64px, 8.4vw, 112px); line-height: .88; letter-spacing: .05em; margin-left: -.04em; }
.brand-line { font-size: 1.1875rem; line-height: 1.5; color: var(--text-secondary); max-width: 34ch; }
.brand-data { display: grid; grid-template-columns: repeat(3, auto); justify-content: start; gap: var(--space-2) var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--hairline); max-width: 560px; }
.brand-data div { display: grid; gap: 4px; align-content: start; }
.brand-data dt, .brand-data dd { white-space: nowrap; }
.brand-data dd { margin: 0; }
.brand-data .value { font-family: var(--font-mono); font-size: 0.875rem; color: var(--text); font-variant-numeric: tabular-nums; }
/* a short window keeps the sign-in on screen: the facts row and the big mark step aside */
@media (min-width: 881px) and (max-height: 960px) {
  .brand { gap: var(--space-4); }
  .brand-mark { width: 56px; height: 56px; }
  .brand-data { display: none; }
}
/* a school console (1366 by 768) keeps Board the station over the fold: the title and the gaps come in, the words stay
   (the QA pass, 2026-10-31: the button sat at y 758) */
@media (min-width: 881px) and (max-height: 820px) {
  .title-screen { padding-top: 20px; }
  .title-grid { gap: var(--space-4) var(--space-6); }
  .brand { gap: var(--space-3); }
  .brand-mark { width: 44px; height: 44px; }
  .brand-title { font-size: clamp(56px, 6vw, 76px); }
  .sign-in { gap: var(--space-4); padding: var(--space-4) var(--space-5); }
  .sign-in form { gap: var(--space-3); }
}

.sign-in { width: 100%; padding: var(--space-5); display: grid; gap: var(--space-5); }
.sign-in .ln-panel-title { margin: 0; }
.segments { display: grid; grid-template-columns: repeat(var(--segments, 2), minmax(0, 1fr)); border: 1px solid var(--edge); margin: 0; padding: 0; min-width: 0; }
.segments legend { padding: 0; }
.segment { position: relative; display: block; }
.segment input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.segment span { display: grid; place-items: center; min-height: 44px; padding: 0 var(--space-3); font-family: var(--font-display); font-weight: 600;
  font-size: 0.875rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); transition: background .15s, color .15s; }
.segment + .segment span { border-left: 1px solid var(--edge); }
.segment input:hover + span { color: var(--text); background: var(--veil-1); }
.segment input:checked + span { color: var(--text); background: var(--veil-3); box-shadow: inset 0 -2px 0 var(--accent); }
.segment input:focus-visible + span { outline: 2px solid var(--flare); outline-offset: 2px; }
.sign-in form { display: grid; gap: var(--space-4); }
.sign-in .two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.sign-in .ln-btn-primary { margin-top: var(--space-2); min-height: 52px; font-size: 1rem; }
.sign-in .reply { justify-content: flex-start; }
.sign-in .reply:empty { display: none; }
.input-door { min-height: 56px; font-size: 1.375rem; }
/* After the door: one card at a time, entering from the left (still: it appears). */
.arrival { display: grid; gap: var(--space-4); }
:root:not(.is-still) .arrival:not([hidden]) { animation: arrival-enter 240ms var(--ease-machined) both; }
@keyframes arrival-enter { from { opacity: 0; transform: translateX(-12px); } }
.choices { display: grid; gap: var(--space-2); }
.choice { display: grid; gap: 6px; width: 100%; padding: var(--space-4); text-align: left; background: var(--veil-1); border: 1px solid var(--edge);
  border-radius: var(--radius-0); color: var(--text); font: inherit; cursor: pointer; transition: background .15s, border-color .15s; }
button.choice:hover, button.choice:focus-visible { background: var(--veil-3); border-color: var(--accent); }
button.choice:focus-visible { outline: 2px solid var(--flare); outline-offset: 2px; }
.choice-form { cursor: default; }
.choice-title { font-family: var(--font-display); font-weight: 600; font-size: 1.125rem; letter-spacing: .1em; text-transform: uppercase; }
.choice-note { font-size: 0.875rem; line-height: 1.4; color: var(--text-secondary); }
/* the whole card is the button; this says so (wchesher, 2026-10-25, a student on the crew card: "I dont have a code") */
.choice-action { justify-self: start; margin-top: var(--space-2); pointer-events: none; }
.join-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-2); margin-top: var(--space-2); }
.join-row .ln-btn { min-height: 48px; margin: 0; }
.boarding-code { font-size: clamp(44px, 6vw, 64px); padding: var(--space-3) 0; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.not-you { margin: calc(var(--space-2) * -1) 0 0; }
/* The station's hail at the door (story login.ignition, static/story/prologue.js): the script's STATION line in the
   station's own capitals, said once as the mark finishes drawing, the seam drawing under it, then spent to grey. */
.station-hail { position: relative; margin: 0 0 calc(var(--space-2) * -1); padding-bottom: var(--space-3); display: flex; align-items: flex-start; gap: 10px;
  font-family: var(--font-mono); font-size: 0.75rem; line-height: 1.6; letter-spacing: .14em; color: var(--text); transition: color 600ms; }
.station-hail .square { margin-top: calc((1.6em - 8px) / 2); }
.station-hail::before, .station-hail::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; }
.station-hail::before { background: var(--hairline); }
.station-hail::after { background: var(--accent-line); transform: scaleX(0); transform-origin: left; transition: transform var(--flow-ui) var(--ease-machined); }
.station-hail.is-speaking::after { transform: scaleX(1); }
.station-hail.is-spent { color: var(--text-muted); }
.station-hail.is-spent::after { transform-origin: right; }
.station-hail .word { display: inline-block; transition: opacity 180ms var(--ease-machined), transform 180ms var(--ease-machined); }
.station-hail .word.is-pending { opacity: 0; transform: translateX(-4px); }
:root.is-still .station-hail, :root.is-still .station-hail::after, :root.is-still .station-hail .word { transition: none; }

/* ---- the station footer -------------------------------------------------------------------------- */
.station-footer { position: relative; z-index: 1; width: 100%; max-width: 1320px; margin: 0 auto; padding: var(--space-6) max(16px, 2vw) var(--space-5);
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); align-items: center; justify-content: space-between; }
/* The corner counter (story login.ignition): small, fixed, never in the way, never explained. It sits on its own plate,
   so the screen scrolling under it (the directives, the site cards, the logs at 1366) passes beneath the plate and
   never through the letters (audit C6). It starts clear of the suite's Feedback button (suite-feedback.js: 28px round,
   8px in, the same place across the suite), at the 44px its own note beside the button uses: at 16px the button sat on
   the "T" of "T MINUS" below 1180px wide (QA pass, 2026-10-31). */
.corner-counter { position: fixed; left: max(44px, 2vw); bottom: 10px; z-index: 5; margin: 0; pointer-events: none;
  padding: 4px 8px; background: var(--glass); -webkit-backdrop-filter: blur(var(--blur-glass)); backdrop-filter: blur(var(--blur-glass));
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.corner-counter:empty { display: none; }
/* The mission day as a readout (segment.js segmentCounter; Maestro, 2026-11-06: "mission day on lit panel should be
   analog readout font"): the words stay this small mono, engraved either side; only the number sits in the glass, lit
   over its unlit segments, right-aligned in a fixed window so a rolling count never shifts the words. */
.corner-counter { display: flex; align-items: baseline; gap: .7em; }
.corner-counter .ln-countdown-legend { font: inherit; letter-spacing: inherit; text-transform: none; color: inherit; }
.corner-counter-digits { font-family: "DSEG7 Classic", var(--font-mono); font-weight: 700; font-size: 1.45em; line-height: 1; letter-spacing: .04em;
  color: var(--accent); text-shadow: 0 0 8px var(--accent-glow); }
.corner-counter-digits > .ln-countdown-lit { justify-self: end; }
/* Docked in the header on Alpha's console (console.js placeCounter): the same small mono, in the header's flow, off the boards. */
.header-tools > .corner-counter { position: static; padding: 0 var(--space-2) 0 0; background: none; -webkit-backdrop-filter: none; backdrop-filter: none;
  white-space: nowrap; }
/* Narrower than the dock (console.js COUNTER_DOCKS), a docked counter takes no room for the frame or two before the media
   query's change moves it back to the corner: a console resized from 1366 to 760 measured the header sideways in between. */
@media (max-width: 1180px) { .header-tools > .corner-counter { display: none; } }
.station-footer { padding-bottom: calc(var(--space-5) + 24px); }
.disclaimer { font-size: 0.75rem; line-height: 1.5; color: var(--text-muted); max-width: 72ch; }
.footer-controls { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.footer-controls a { font-size: 0.8125rem; color: var(--text-muted); text-underline-offset: 3px; padding: 12px 6px; }
.footer-controls a:hover { color: var(--text); }

/* ---- the console header ------------------------------------------------------------------------- */
.deck-header { position: sticky; top: 0; z-index: 20; background: var(--glass); -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.2);
  backdrop-filter: blur(var(--blur-glass)) saturate(1.2); }
.deck-header::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--hairline) 12%, var(--hairline) 88%, transparent); }
.deck-header-inner { max-width: 1320px; margin: 0 auto; padding: 0 max(16px, 2vw); min-height: 64px; display: grid; align-items: center; gap: var(--space-4);
  grid-template-columns: auto minmax(0, 1fr) auto; }
.wordmark { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; }
.wordmark .mark { width: 30px; height: 30px; }
.wordmark-text { font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; letter-spacing: .14em; text-transform: uppercase; line-height: 1; }
/* On the crew screen the mark alone carries the name (the title screen has the wordmark), so the eight
   session words keep their room inside the 1320px header at every width */
.deck-header .wordmark-text { display: none; }
.crew-badge { display: grid; gap: 1px; padding-left: var(--space-4); border-left: 1px solid var(--hairline); }
.crew-badge .value { font-family: var(--font-mono); font-size: 0.875rem; letter-spacing: .16em; color: var(--text); }
/* Mission Alpha's badge in the crew code's place (alpha/assignment.js): the patch, then the crew and the student's name
   and chair; it opens the assignment card. */
.alpha-badge { display: flex; align-items: center; gap: var(--space-2); min-width: 0; margin: 0; padding: 2px var(--space-2) 2px var(--space-4);
  border: 0; border-left: 1px solid var(--hairline); background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.alpha-badge[hidden] { display: none; }
.alpha-badge:hover .alpha-badge-who, .alpha-badge:focus-visible .alpha-badge-who { color: var(--accent); }
.alpha-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.alpha-badge .assignment-patch { width: 32px; height: 32px; flex: none; }
.alpha-badge-words { display: grid; gap: 1px; min-width: 0; }
.alpha-badge-who { font-family: var(--font-mono); font-size: 0.8125rem; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 34ch; }
.alpha-badge-crew { white-space: nowrap; }

/* The assignment card: the staff badge's layout (brand/decals/badges, a printed card, so its own fixed inks) beside
   the assignment rows. */
.assignment { width: min(820px, calc(100vw - 2 * var(--space-4))); max-height: calc(100dvh - 2 * var(--space-5)); margin: auto; padding: 0;
  border: 1px solid var(--hairline); border-top: 1px solid var(--accent-line); background: var(--surface); color: var(--text); box-shadow: var(--shadow-deep); }
.assignment[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.assignment-foot { display: flex; justify-content: flex-end; padding: var(--space-3) var(--space-5) var(--space-4); border-top: 1px solid var(--hairline); }
.assignment::backdrop { background: var(--shade); }
.assignment-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-4); align-items: start; padding: var(--space-5) var(--space-5) var(--space-3); }
.assignment-title { margin: var(--space-1) 0 0; font-family: var(--font-display); font-size: 2rem; line-height: 1; letter-spacing: .08em; text-transform: uppercase; }
.assignment-body { display: grid; grid-template-columns: 220px minmax(0, 1fr); grid-auto-rows: max-content; gap: var(--space-5); align-items: start; overflow-y: auto;
  padding: var(--space-3) var(--space-5) var(--space-5); }
.assignment-rows { display: grid; grid-template-columns: 9.5rem minmax(0, 1fr); gap: var(--space-3) var(--space-4); margin: 0; }
.assignment-rows dt { padding-top: 3px; }
.assignment-rows dd { margin: 0; font-size: 0.9375rem; line-height: 1.45; color: var(--text-secondary); }
.assignment-rows dd strong { color: var(--text); font-weight: 600; }
.assignment-chair { display: block; }
.badge-card { --badge-band: #18181b; --badge-face: #e8e8ea; --badge-window: #d6d6da; --badge-ink: #17171a; --badge-quiet: #6e6e76;
  --badge-stripe: #ff7a2e; display: grid; grid-template-rows: auto 1fr auto; aspect-ratio: 80 / 118; border-radius: 10px; overflow: hidden;
  background: var(--badge-face); color: var(--badge-ink); box-shadow: var(--shadow-lift); }
.badge-card-band { display: flex; align-items: center; padding: var(--space-4) var(--space-4) var(--space-3); background: var(--badge-band);
  --text: #e9e9eb; --edge: #8e8e96; --accent: #ff7a2e; }
.badge-card-band .lockup { width: auto; height: 22px; }
.badge-card-face { display: grid; justify-items: center; align-content: start; gap: var(--space-1); padding: var(--space-4) var(--space-3) var(--space-3); text-align: center; }
.badge-card-window { display: grid; place-items: center; width: 62%; aspect-ratio: 400 / 480; margin-bottom: var(--space-2); background: var(--badge-window); }
.badge-card-window .assignment-patch { width: 86%; height: auto; }
.badge-card-name { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 1.375rem; line-height: 1.1; letter-spacing: .14em; text-transform: uppercase;
  overflow-wrap: anywhere; }
.badge-card-chair { margin: 0; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em; text-transform: uppercase; }
.badge-card-station { margin: 0; font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--badge-quiet); }
.badge-card-stripe { height: 14px; background: var(--badge-stripe); }
.header-tools { display: flex; align-items: center; gap: var(--space-2); }
.link-state { display: inline-flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-2); }
#link-time:empty { display: none; }

/* The phase stepper: where the crew is in the mission */
.stepper { display: flex; align-items: center; justify-content: center; gap: 0; margin: 0; padding: 0; list-style: none; min-width: 0; }
.stepper li { display: flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
/* The rules between steps take the slack: they grow to 28px and give way first, down to 6px, so eight
   sessions fit beside the crew badge and the tools on a 1280 screen without crowding either. */
.stepper li + li { flex: 0 1 auto; min-width: 0; }
.stepper li + li::before { content: ""; flex: 0 1 28px; min-width: 6px; height: 1px; background: var(--hairline); margin-left: 8px; }
/* Crowded (console.js fitStepper): the part the crew is on keeps its name, the others stand as their squares. */
.stepper.is-crowded li:not([aria-current="step"]) .stepper-word { display: none; }
.stepper.is-crowded li + li::before { flex-basis: 20px; }
.stepper li.is-done { color: var(--text-secondary); }
.stepper li.is-done .square { background: var(--text-secondary); border-color: var(--text-secondary); }
.stepper li[aria-current="step"] { color: var(--text); }
.stepper li[aria-current="step"] .square { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 10px var(--accent-glow); }
.stepper-compact { display: none; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text); }

/* ---- the console ---------------------------------------------------------------------------------- */
.console { position: relative; z-index: 1; max-width: 1320px; margin: 0 auto; padding: var(--space-6) max(16px, 2vw) max(160px, calc(var(--caption-band, 0px) + var(--space-6))); /* room to scroll the last rows clear of the caption bar's band */
  display: grid; grid-template-columns: minmax(0, 1fr) 384px; gap: var(--space-6) var(--space-5); align-items: start; }
.console-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); min-width: 0; }
.console-side { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); min-width: 0; }
.phase-intro { display: grid; gap: var(--space-3); padding: 0 0 var(--space-2); }
.phase-intro .display-l { font-size: clamp(30px, 3.4vw, 40px); }
.duties { display: grid; gap: var(--space-2); margin: var(--space-2) 0 0; padding: 0; list-style: none; max-width: 78ch; }
.duties li { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: var(--space-3); font-size: 0.9375rem; color: var(--text-secondary); }
.duties .eyebrow { padding-top: 4px; }
/* Bravo on Luna, a replay (luna_last_time.py): the call made on this step last play, the duties band's shape */
.luna-last-time:not([hidden]) { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 2px var(--space-3); margin: var(--space-3) 0 0;
  max-width: 78ch; padding-top: var(--space-2); border-top: 1px solid var(--hairline); font-size: 0.9375rem; color: var(--text-secondary); }
.luna-last-time .eyebrow { grid-row: span 2; padding-top: 4px; }
/* what this play just filed on the step before (luna_last_time.just_filed): the duties band's shape, the accent's ink */
.luna-just-filed:not([hidden]) { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: var(--space-3); margin: var(--space-3) 0 0;
  max-width: 78ch; font-size: 0.9375rem; color: var(--text); }
.luna-just-filed .eyebrow { padding-top: 4px; color: var(--accent); }
/* a crewmate hands the step's call to the student (luna_chairs.handover): their name, then their line */
.luna-handover:not([hidden]) { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: var(--space-3); margin: var(--space-2) 0 0;
  max-width: 78ch; font-size: 0.9375rem; color: var(--text); }
.luna-handover .eyebrow { padding-top: 4px; }
/* An Alpha step's "What to do" (alpha/directions.js): the step's whole plan, folded under the next move unless the
   student opens it: why, the goal, numbered actions with their chairs, done when. The student's own lines lead: the
   accent bar, bold words, the "you" tag. */
.direction { max-width: 78ch; border: 1px solid var(--hairline); border-left: 2px solid var(--accent-line); background: var(--surface);
  padding: var(--space-3) var(--space-4); transition: border-color var(--flow-ui) var(--ease-machined); }
.direction-head { display: grid; gap: var(--space-1); cursor: pointer; list-style: none; }
.direction-head::-webkit-details-marker { display: none; }
.direction-head .eyebrow::after { content: " / hide"; letter-spacing: .12em; }
.direction:not([open]) .direction-head .eyebrow::after { content: " / show"; }
.direction-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.direction-why { font-size: 0.9375rem; line-height: 1.45; color: var(--text-secondary); }
.direction-goal { font-size: 1.0625rem; line-height: 1.4; color: var(--text); }
.direction-do { display: grid; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0 0 0 1.5em; font-size: 0.9375rem; line-height: 1.45; color: var(--text-secondary); }
.direction-do li { padding-left: var(--space-2); border-left: 2px solid transparent; overflow-wrap: anywhere; }
.direction-text { display: block; }
.direction-do li::marker { font-family: var(--font-mono); color: var(--text-muted); }
.direction-do li.is-mine { border-left-color: var(--accent); color: var(--text); font-weight: 600; }
.direction-do li.is-mine::marker { color: var(--accent); }
.direction-chair { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
.direction-do li.is-mine .direction-chair { color: var(--accent); }
.direction-done { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); align-items: baseline; margin: var(--space-3) 0 0; font-size: 0.9375rem; color: var(--text-secondary); }
@keyframes direction-nudge { 0%, 100% { box-shadow: none; } 40% { box-shadow: var(--glow-accent); } }
/* The control the next move names, marked on the screen itself while it is the seat's move (feedback #212: "a direction
   marker to show what you need to do and where you need to go"); lit, by Show me or the two-minute nudge, it glows. */
[data-your-move] { outline: 2px solid var(--accent-line); outline-offset: 3px; }
[data-direction-lit] { outline: 2px solid var(--accent); outline-offset: 3px; box-shadow: var(--glow-accent); }
/* THE DARK PANEL (Maestro, 2026-11-06: "gravitas", "details and flourishes that add gravitas", "highly selective"; the
   Gravitas list, item 02). On the Alpha console's work surface a lamp's legend is engraved and unlit at rest; the one
   press that wants the student (the move bar's pin, alpha/directions.js) is the one lit, the one-lit-press ruling in
   hardware. A press that cannot go stays dark whatever it is. A lamp is .al-btn-lamp, or a board's own lit press drawn
   without it (the rover's Forward, logic/hand_drive.css). A plain press the bar pins takes the lamp's edge and glow and
   keeps its own legend colour. The lamp test (alpha/lamp_test.js) lights every lamp once. */
body.is-alpha-console:not(.is-lamp-test) #surface :is(.al-btn-lamp, .hd-move[data-key="forward"]):not([data-your-move]):not(:disabled):not([aria-disabled="true"]) {
  background: transparent; border-color: var(--al-edge); color: var(--al-text); box-shadow: none; filter: none;
  text-shadow: 0 1px 0 rgb(0 0 0 / .55), 0 -1px 0 rgb(255 255 255 / .06); }
:root[data-theme="day"] body.is-alpha-console:not(.is-lamp-test) #surface :is(.al-btn-lamp, .hd-move[data-key="forward"]):not([data-your-move]) { text-shadow: 0 1px 0 rgb(255 255 255 / .8), 0 -1px 0 rgb(0 0 0 / .12); }
body.is-alpha-console:not(.is-lamp-test) #surface :is(.al-btn-lamp, .hd-move[data-key="forward"]):not([data-your-move]):not(:disabled):not([aria-disabled="true"]):hover { background: var(--al-dust-2); border-color: var(--al-text); }
body.is-alpha-console #surface .al-btn[data-your-move]:not(.al-btn-lamp):not(:disabled):not([aria-disabled="true"]) {
  border-color: var(--al-lamp); box-shadow: var(--al-glow-lamp); }
body.is-alpha-console.is-lamp-test :is(.al-btn-lamp, .hd-move[data-key="forward"]), body.is-alpha-console.is-lamp-test :is(.al-btn-lamp, .hd-move[data-key="forward"]):is(:disabled, [aria-disabled="true"]) {
  background: var(--al-lamp); border-color: var(--al-lamp); color: var(--al-on-lamp); box-shadow: var(--al-glow-lamp); text-shadow: none; transition: none; }
body.is-alpha-console.is-lamp-test .ln-trim-lamps { opacity: .9; background-image: radial-gradient(circle, var(--accent) 1.7px, transparent 2.3px); }
body.is-alpha-console.is-lamp-test .ln-trim-lamps::before, body.is-alpha-console.is-lamp-test .ln-trim-lamps::after { animation: none; opacity: 1; }
/* The next move (alpha/directions.js mountNextMove): the first line under the heading, held under the header while the
   student scrolls into the work; under the act card (z 6), which curtains the column while a part opens. Theirs leads
   in the accent; a crewmate's move and done-for-now stay quiet. Stuck, it takes the accent edge and pulses once. */
.next-move { position: sticky; top: calc(64px + var(--space-2)); z-index: 5; display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center; gap: var(--space-2) var(--space-4); padding: var(--space-3) var(--space-4);
  border: 1px solid var(--accent-line); border-left: 3px solid var(--accent); background: var(--glass);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.2); backdrop-filter: blur(var(--blur-glass)) saturate(1.2); }
.next-move[hidden] { display: none; }
.next-move-eyebrow { color: var(--accent); white-space: nowrap; }
.next-move-words { display: grid; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.next-move-text { font-size: 1rem; line-height: 1.4; font-weight: 600; color: var(--text); }
.next-move-then { font-size: 0.875rem; line-height: 1.4; color: var(--text-secondary); }
.next-move-chair { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); white-space: nowrap; }
/* A chair's tape (alpha/directions.js crewmateTape): in a solo play the student's own chair above their move, and a
   crewmate's name card, chair first. A word on label tape, never a chair colour (Design, alpha-one-student.md); the
   tokens are alpha.css's, with its values in case the bar paints before an Alpha sheet is linked. */
.next-move-head { display: grid; gap: var(--space-1); justify-items: start; }
.next-move-tape { display: inline-block; padding: 2px var(--space-2) 1px; border-radius: 2px; background: var(--al-tape, #d8cdb9);
  color: var(--al-on-tape, #1a1814); font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; line-height: 1.5;
  clip-path: polygon(0 8%, 3% 0, 97% 6%, 100% 0, 99% 92%, 100% 100%, 2% 96%, 0 100%); }
/* A crewmate's face beside their name card (alpha/crew_faces.js): head and shoulders, small, the card at its side. Until
   their film is there the card stands alone. */
.next-move-who { display: grid; grid-template-columns: auto auto; align-items: center; gap: var(--space-3); justify-content: start; }
.next-move-face { display: block; width: 48px; border-radius: 2px; overflow: hidden; background: var(--al-surface, #15130f); }
.next-move-face > .portrait { width: 100%; }
.next-move.is-theirs, .next-move.is-done { border-color: var(--hairline); border-left-color: var(--text-muted); }
.next-move.is-theirs .next-move-eyebrow, .next-move.is-theirs .next-move-chair, .next-move.is-done .next-move-eyebrow { color: var(--text-secondary); }
.next-move.is-theirs .next-move-text { font-weight: 500; color: var(--text-secondary); }
/* The hint ladder's rung H.A.L. said last (alpha/directions.js hintLadder): under the move, in H.A.L.'s mono tag. */
.next-move-hint { display: flex; gap: var(--space-2); align-items: baseline; font-size: 0.875rem; line-height: 1.4; color: var(--text); }
.next-move-hint-who { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); white-space: nowrap; }
/* a story line under the move: two lines at most, the captions keep it whole (directions.js, the third QA pass) */
.next-move-line { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
  font-size: 0.875rem; line-height: 1.4; color: var(--text-secondary); }
.next-move-line-who { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase;
  margin-right: var(--space-2); }
.next-move.is-nudged { border-color: var(--accent); background: linear-gradient(var(--accent-wash), var(--accent-wash)), var(--glass); }
:root:not(.is-still) .next-move.is-moving { animation: direction-nudge 1.2s var(--ease-machined) 1; }
@media (max-width: 760px) {
  .next-move { grid-template-columns: minmax(0, 1fr) auto; }
  .next-move-eyebrow, .next-move-head, .next-move-who, .next-move-words { grid-column: 1 / -1; }
}
/* The dealt chairs (alpha/dealt.js): above the board until the crew's first move. Your chair leads; a crewmate's
   chair and its trade stay quiet. */
.dealt { display: grid; gap: var(--space-2); padding: var(--space-3) var(--space-4); border: 1px solid var(--hairline);
  border-left: 3px solid var(--accent); background: var(--glass); }
.dealt[hidden] { display: none; }
.dealt .eyebrow { color: var(--accent); }
.dealt-mine, .dealt-crew { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.dealt-mine li { color: var(--text); line-height: 1.4; }
.dealt-crew li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); color: var(--text-secondary); }
.surface { min-height: 360px; }
.surface > .ln-panel { padding: var(--space-5) var(--space-5) var(--space-6); }
.surface-loading { display: grid; place-items: center; align-content: center; gap: var(--space-4); min-height: 360px; }

/* The loading line: one hairline across the top of the window while heavy bytes arrive, an ignition fill and a
   mono reading under its right end. It fades at one. Above the header, so a scene's own chrome never hides it. */
.load-line { position: fixed; inset: 0 0 auto 0; z-index: 61; height: 2px; background: var(--hairline); pointer-events: none;
  transition: opacity var(--flow-ui) var(--ease-machined); }
.load-line.is-done { opacity: 0; }
.load-line-fill { position: absolute; inset: 0; background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform var(--flow-ui) var(--ease-machined); }
.load-line-reading { position: absolute; top: 6px; right: max(16px, 2vw); font-family: var(--font-mono); font-size: 0.625rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--text-secondary); }
:root.is-still .load-line, :root.is-still .load-line-fill { transition: none; }

/* Section heads inside a panel */
.section-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-4); }
.section-head .ln-panel-title { margin: 0; }
.owner { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); }
.owner b { font-weight: 500; color: var(--text-secondary); }
.lede { font-size: 0.9375rem; line-height: 1.5; color: var(--text-secondary); max-width: 62ch; }
.panel-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); margin-top: var(--space-5); }
.panel-actions .note { font-size: 0.8125rem; color: var(--text-muted); max-width: 44ch; }

/* Tabs inside the build surface */
.tabs { display: flex; gap: 0; margin: 0 0 var(--space-5); border-bottom: 1px solid var(--hairline); overflow-x: auto; scrollbar-width: none; }
.tab { appearance: none; border: 0; background: none; cursor: pointer; display: grid; gap: 2px; text-align: left; min-height: 56px; padding: var(--space-2) var(--space-5) var(--space-3) 0;
  margin-right: var(--space-5); box-shadow: inset 0 -2px 0 transparent; transition: box-shadow var(--flow-ui), color .15s; }
.tab { flex: none; white-space: nowrap; }
.engine-step { font-family: var(--font-mono); font-size: 1.5rem; font-weight: 300; letter-spacing: 0; }
.tab-name { font-family: var(--font-display); font-weight: 600; font-size: 1.125rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }
.tab-state { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }
.tab:hover .tab-name { color: var(--text-secondary); }
.tab[aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--accent); }
.tab[aria-selected="true"] .tab-name { color: var(--text); }

/* Cards: a selectable, lit choice (chairs, sites, decision options) */
.cards { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.card { position: relative; display: grid; gap: var(--space-3); align-content: start; padding: var(--space-5); background: var(--veil-1);
  border: 1px solid var(--hairline); border-top-color: var(--veil-3); text-align: left; color: var(--text);
  transition: border-color .15s, background .15s, box-shadow var(--flow-ui); }
/* Where the box itself is what a student presses, its edge reads (--edge); hairlines stay for dividers */
button.card { appearance: none; cursor: pointer; font: inherit; border-color: var(--edge); }
button.card:hover { background: var(--veil-2); border-color: var(--edge); }
.card.is-chosen { border-color: var(--accent-line); background: radial-gradient(120% 90% at 0% 0%, var(--accent-wash), transparent 70%), var(--veil-1); }
.card .title { color: var(--text); }
.card-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 22px; }
.card-top .eyebrow { margin: 0; }
.card-tag { margin-left: auto; font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .2em; text-transform: uppercase;
  padding: 2px 6px; border: 1px solid var(--edge); color: var(--text-secondary); }
.card.is-chosen .card-tag { border-color: var(--accent); color: var(--accent); }
.facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px var(--space-4); margin: 0; }
.facts dt, .facts .fact-term { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); padding-top: 2px; }
.facts dd, .facts .fact-value { margin: 0; font-family: var(--font-mono); font-size: 0.875rem; color: var(--text); }
/* In a Luna board card (the ice methods, the slingshot tracks), each fact stacks its term over its value: side by side, the long spaced terms
   took the card's width and left the value a word per line (the cold walk, 2026-11-03). */
.ice-methods .card .facts { grid-template-columns: minmax(0, 1fr); gap: 2px; }
.ice-methods .card .facts dd { margin-bottom: var(--space-2); }
.card .note { font-size: 0.875rem; line-height: 1.45; color: var(--text-secondary); }

/* Chairs */
/* A chair card is a column: whatever the description's length, the holder and the button sit at its foot, level
   across the row. */
.card.chair { display: flex; flex-direction: column; }
/* What the chair is asked to do leads, in the text's own color; what it owns follows, quieter. */
.chair-asked { font-size: 0.9375rem; line-height: 1.45; color: var(--text); }
.chair-holder { margin-top: auto; font-family: var(--font-mono); font-size: 0.875rem; letter-spacing: .06em; color: var(--text); min-height: 1.4em; }
.chair-holder.is-open { color: var(--text-muted); }
.chair .ln-btn { align-self: flex-start; margin-top: var(--space-2); }
/* Holding all three chairs (one player), the accent is spent on the card under the pointer, not on the whole row. */
.cards.chairs[data-all-chosen] .card.is-chosen { border-color: var(--edge); background: var(--veil-1); }
.cards.chairs[data-all-chosen] .card.is-chosen .card-tag { border-color: var(--edge); color: var(--text-secondary); }
.cards.chairs[data-all-chosen] .card.is-chosen:is(:hover, :focus-within) { border-color: var(--accent-line); background: radial-gradient(120% 90% at 0% 0%, var(--accent-wash), transparent 70%), var(--veil-1); }
.cards.chairs[data-all-chosen] .card.is-chosen:is(:hover, :focus-within) .card-tag { border-color: var(--accent); color: var(--accent); }
.share { display: grid; gap: var(--space-3); grid-template-columns: minmax(0, 1fr) auto; align-items: center; margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--hairline); }
.share-code { font-family: var(--font-mono); font-size: 2.5rem; font-weight: 500; letter-spacing: .24em; line-height: 1; color: var(--text); }
.lock-row { display: grid; gap: var(--space-3); justify-items: start; margin-top: var(--space-6); }
.leave-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-top: var(--space-5); }

/* Goals */
.goal-list { display: grid; gap: var(--space-3); margin: 0; padding: 0; list-style: none; counter-reset: goal; }
.goal { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: var(--space-3); }
.goal-rank { font-family: var(--font-mono); font-size: 1.25rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.goal:first-child .goal-rank { color: var(--accent); }
.goal-tools { display: flex; gap: var(--space-1); }
.goal-tools .ln-btn { min-width: 44px; padding: 0 var(--space-3); font-size: 0.75rem; }

/* The sort board (surfaces/sort.js): a pile to sort, then the two columns side by side */
.sort-chairs { margin: var(--space-4) 0; }
.sort-pile { display: grid; gap: var(--space-3); align-content: start; margin-top: var(--space-5); }
.sort-pile .ln-eyebrow { margin: 0; }
.sort-key { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-3); margin: var(--space-4) 0 0; }
.sort-key > div { padding: var(--space-3) var(--space-4); border-left: 2px solid var(--accent); background: rgba(255, 255, 255, .03); }
.sort-key dt { font-family: var(--font-display); font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
.sort-key dd { margin: 4px 0 0; color: var(--text-secondary); line-height: 1.45; }
.sort-columns { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.sort-list { display: grid; gap: var(--space-3); margin: 0; padding: 0; list-style: none; }
.sort-card { padding: var(--space-4); }
.sort-card .eyebrow { margin: 0; }
.sort-text { font-size: 0.9375rem; line-height: 1.45; color: var(--text); }
.sort-tools { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.sort-tools .ln-btn { min-width: 44px; }
.sort-empty { margin: 0; }
.locked-goals { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.locked-goals li { display: grid; grid-template-columns: 40px 1fr; gap: var(--space-3); font-size: 1rem; }

/* Part one's two duties (surfaces/contract.js): the landing list and the budget split. One hue: the vehicle
   is the accent, the surface its glow on an accent edge, the reserve the graphite left over. */
.contract-actions { align-items: start; justify-content: space-between; }
.contract-actions > .status-word { min-height: 48px; }
.split-bar { display: flex; gap: 2px; height: 14px; margin-top: var(--space-5); }
.split-segment { flex-basis: 0; min-width: 0; border: 1px solid var(--hairline); }
:root:not(.is-still) .split-segment { transition: flex-grow var(--flow-ui) var(--ease-machined); }
.split-segment.is-vehicle, .split-line.is-vehicle .split-key { background: var(--accent); border-color: var(--accent); }
.split-segment.is-surface, .split-line.is-surface .split-key { background: var(--accent-glow); border-color: var(--accent-line); }
.split-segment.is-reserve, .split-line.is-reserve .split-key { background: var(--veil-2); border-color: var(--edge); }
.split-lines { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: grid; }
.split-line { display: grid; grid-template-columns: 12px minmax(0, 1fr) 72px 128px 112px; align-items: center; gap: var(--space-4);
  padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
.split-key { width: 12px; height: 12px; border: 1px solid; }
.split-name { display: grid; gap: 2px; }
.split-name b { font-family: var(--font-display); font-weight: 600; font-size: 1.125rem; letter-spacing: .08em; text-transform: uppercase; }
.split-note { font-size: 0.8125rem; color: var(--text-muted); }
.split-percent { font-family: var(--font-mono); font-size: 1.5rem; font-variant-numeric: tabular-nums; text-align: right; }
.split-line.is-vehicle .split-percent { color: var(--accent); }
.split-million { display: grid; justify-items: end; font-family: var(--font-mono); font-size: 0.9375rem; font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.split-drawn { font-size: 0.6875rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); }
.split-steps { display: flex; gap: var(--space-2); justify-content: end; }
.split-steps .ln-btn { width: 48px; padding: 0; }
.split-steps .ln-btn[aria-disabled="true"] { color: var(--text-muted); border-color: var(--hairline); cursor: not-allowed; }
.split-left { justify-self: end; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); }
.split-share { margin-top: var(--space-5); }
.launch-deck-source.is-listed { color: var(--accent); }
@media (max-width: 720px) {
  .split-line { grid-template-columns: 12px minmax(0, 1fr) auto; }
  .split-million, .split-steps, .split-left { grid-column: 2 / -1; justify-self: start; justify-items: start; }
}

/* Engines */
.engine-deck { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: var(--space-6); align-items: center; }
.stepper-control { display: flex; align-items: center; gap: var(--space-4); }
.stepper-control .ln-btn { width: 56px; min-height: 56px; padding: 0; font-family: var(--font-mono); font-size: 1.5rem; letter-spacing: 0; }
.engine-count { display: grid; justify-items: center; gap: var(--space-1); min-width: 120px; }
.engine-count .digits { font-size: 4rem; color: var(--accent); text-shadow: 0 0 22px var(--accent-glow); }
.engine-rules { display: grid; gap: 0; }
.rule-line { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: baseline; gap: var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
.rule-line .value { font-family: var(--font-mono); font-size: 1.375rem; font-variant-numeric: tabular-nums; }
.verdict { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; padding: 2px 6px; border: 1px solid var(--edge); color: var(--text-secondary); white-space: nowrap; }
.verdict.is-good { border-color: var(--accent-line); color: var(--accent); }
.unit-case { text-transform: none; letter-spacing: .04em; }
.verdict.is-bad { border-color: var(--flare); background: var(--flare); color: var(--on-flare); }

/* Cargo list */
.mass-meter { display: grid; gap: var(--space-2); margin-bottom: var(--space-5); }
.mass-meter-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.meter { position: relative; height: 6px; background: var(--veil-2); overflow: hidden; }
.meter-fill { position: absolute; inset: 0; background: var(--accent); transform-origin: left; transform: scaleX(0); transition: transform 420ms var(--ease-machined); box-shadow: 0 0 12px var(--accent-glow); }
.cargo-list { margin: 0; padding: 0; list-style: none; display: grid; }
.cargo-row { display: grid; grid-template-columns: 136px minmax(0, 1fr) 64px 72px 104px; align-items: center; gap: var(--space-3); min-height: 60px; padding: var(--space-2) 0; border-top: 1px solid var(--hairline); }
.cargo-row.is-aboard .cargo-name { color: var(--text); }
.cargo-name { font-size: 0.9375rem; color: var(--text-secondary); }
.cargo-row .data { text-align: right; color: var(--text-secondary); }
.cargo-row .ln-btn { justify-self: end; }
.cargo-head { min-height: 32px; border-top: 0; }
.cargo-head > * { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); }
.plan-offer { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3) var(--space-5); align-items: center; padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5); background: var(--veil-1); border-left: 2px solid var(--accent-line); }

/* Placards: the system's diamond, small, with its word */
.placard { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
.placard-diamond { width: 13px; height: 13px; flex: none; transform: rotate(45deg); border: 1.5px solid var(--text); background: var(--surface); margin: 3px; }
.placard-none .placard-diamond { border-style: dashed; border-color: var(--edge); }
.placard-fuel .placard-diamond { background: var(--text); }
.placard-oxidizer .placard-diamond { background: repeating-linear-gradient(0deg, var(--text) 0 1.5px, transparent 1.5px 4px); }
.placard-energetic .placard-diamond { background: radial-gradient(var(--text) 1px, transparent 1.2px) 0 0 / 4px 4px; }
.placard-heat .placard-diamond { background: repeating-linear-gradient(90deg, var(--text) 0 1.5px, transparent 1.5px 4px); }
.placard-stored .placard-diamond { box-shadow: inset 0 0 0 2px var(--surface), inset 0 0 0 3.5px var(--text); }
.placard-word { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The bay: three decks by four sectors, between the oxygen header and the methane dome */
.bay-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.bay { display: grid; gap: 10px; }
.bay-tank { appearance: none; width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: 44px; padding: 0 var(--space-4);
  border: 1px solid var(--hairline); background: var(--veil-1); color: var(--text-secondary); font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .18em; text-transform: uppercase; }
button.bay-tank { cursor: pointer; border-color: var(--edge); }
.bay-tank .placard-word { color: var(--text-muted); }
.bay-deck { display: grid; grid-template-columns: 56px repeat(4, minmax(0, 1fr)); gap: 10px; align-items: stretch; }
.deck-label { display: grid; align-content: center; gap: 2px; font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .18em; text-transform: uppercase; color: var(--text-muted); }
.slot { appearance: none; position: relative; display: grid; align-content: space-between; gap: var(--space-2); min-height: 92px; padding: var(--space-3); text-align: left; cursor: pointer;
  background: var(--surface-raised); border: 1px solid var(--hairline); color: var(--text); transition: border-color .15s, background .15s, box-shadow var(--flow-ui); }
.slot:hover { border-color: var(--edge); background: var(--veil-2); }
.slot.is-empty { background: transparent; border-style: dashed; border-color: var(--edge); }
.slot.is-empty:hover { border-color: var(--edge); }
.slot-label { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .14em; color: var(--text-muted); display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); white-space: nowrap; }
.slot-name { font-size: 0.8125rem; line-height: 1.25; color: var(--text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.slot.is-selected, .bay-tank.is-selected { border-color: var(--accent); box-shadow: var(--glow-accent); }
.slot.is-target { border-color: var(--accent-line); border-style: solid; background: var(--accent-wash); }
.slot.is-conflict { box-shadow: inset 0 0 0 1px var(--text); }
.slot.is-conflict.is-selected { box-shadow: inset 0 0 0 1px var(--text), var(--glow-accent); }
.conflict-tag { font-family: var(--font-mono); font-size: 0.5625rem; letter-spacing: .16em; text-transform: uppercase; padding: 1px 4px; background: var(--flare); color: var(--on-flare); }
.conflict-short { display: none; }
/* Headings focused by script on a phase change move the reader, not the ring */
[tabindex="-1"]:focus { outline: none; box-shadow: none; }
.slot { container-type: inline-size; }
/* A narrow slot keeps the mark the pairs list uses (X = touching or keep-out), not a clipped word */
@container (max-width: 150px) { .conflict-word { display: none; } .conflict-short { display: inline; } .conflict-tag { padding: 1px 5px; } }
.bay.is-locked .slot { cursor: default; }
/* Barriers sit ON an edge: a solid bar in the gap between two nodes, with its word for a screen reader */
.barrier { position: absolute; background: var(--text); pointer-events: none; z-index: 2; }
.barrier-right { top: 10%; bottom: 10%; right: -8px; width: 6px; }
.barrier-left { top: 10%; bottom: 10%; left: -8px; width: 6px; }
.barrier-up { left: 10%; right: 10%; top: -8px; height: 6px; }
.barrier-down { left: 10%; right: 10%; bottom: -8px; height: 6px; }
.barrier-wrap { background: repeating-linear-gradient(0deg, var(--text) 0 4px, transparent 4px 7px); }
.bay-side { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-5); align-content: start; padding-top: var(--space-5); border-top: 1px solid var(--hairline); }
.tray { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.tray .ln-btn { width: 100%; justify-content: space-between; font-family: var(--font-body); font-weight: 400; font-size: 0.875rem; letter-spacing: 0; text-transform: none; padding: 0 var(--space-3); }
.pairs { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.pairs li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2); font-size: 0.8125rem; line-height: 1.4; color: var(--text-secondary); }
.mark-x, .mark-o { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; width: 20px; height: 20px; display: grid; place-items: center; border: 1px solid var(--text); }
.mark-x { background: var(--flare); color: var(--on-flare); border-color: var(--flare); }
.legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }

/* Integration steps */
.steps { margin: 0; padding: 0; list-style: none; display: grid; }
.step { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: var(--space-4); align-items: center; padding: var(--space-4) 0; border-top: 1px solid var(--hairline); }
.step-number { font-family: var(--font-mono); font-size: 1.75rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.step-name { font-size: 1.0625rem; color: var(--text-secondary); }
.step.is-next .step-number { color: var(--accent); text-shadow: 0 0 16px var(--accent-glow); }
.step.is-next .step-name, .step.is-done .step-name { color: var(--text); }
.step-live { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); margin-top: var(--space-1); }
.status-word { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); display: inline-flex; align-items: center; gap: var(--space-2); }
.status-word.is-done { color: var(--text-secondary); }
.held { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-3); align-items: start; padding: var(--space-4); margin-bottom: var(--space-5); border: 1px solid var(--edge); background: var(--veil-1); }
.held .square { margin-top: 6px; background: var(--text); border-color: var(--text); }

/* Readiness lines (console summary and the manifest) */
.lines { display: grid; gap: var(--space-4); }
.line { display: grid; gap: var(--space-3); padding: var(--space-5); background: var(--veil-1); border-top: 1px solid var(--veil-3); }
.line.is-signed { background: radial-gradient(120% 90% at 0% 0%, var(--accent-wash), transparent 70%), var(--veil-1); border-top-color: var(--accent-line); }
.line-statement { font-family: var(--font-display); font-weight: 600; font-size: 1.75rem; letter-spacing: .1em; text-transform: uppercase; line-height: 1.05; }
.line-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2) var(--space-4); }
.line-rationale { font-size: 1rem; color: var(--text); max-width: 62ch; }
.line-rationale::before { content: "\201C"; color: var(--text-muted); }
.line-rationale::after { content: "\201D"; color: var(--text-muted); }
.blocked { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-1); }
.blocked li { font-size: 0.875rem; color: var(--text-secondary); display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2); }
.blocked li::before { content: "NOT YET"; font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .18em; color: var(--text-muted); padding-top: 3px; }
.ready-card { display: grid; gap: var(--space-4); justify-items: start; padding: var(--space-5) 0 var(--space-6); margin-bottom: var(--space-2); }
.ready-card .display-xl { color: var(--accent); text-shadow: 0 0 28px var(--accent-glow); }

/* ---- hold to sign (flourish 02) ------------------------------------------------------------------ */
.hold { --progress: 0; position: relative; display: inline-grid; place-items: center; min-width: 240px; min-height: 60px; padding: 0 var(--space-5);
  background: var(--surface-raised); border: 1px solid var(--edge); border-radius: var(--radius-0); cursor: pointer; overflow: hidden;
  touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; color: var(--text); }
.hold:hover { border-color: var(--text-secondary); }
.hold-fill { position: absolute; inset: 0; background: var(--accent); transform-origin: left; transform: scaleX(var(--progress)); }
.hold-label, .hold-label-lit { grid-area: 1 / 1; position: relative; font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
.hold-label-lit { color: var(--on-accent); clip-path: inset(0 calc(100% - var(--progress) * 100%) 0 0); }
.hold-frame { display: grid; gap: var(--space-2); justify-items: start; }
.hold.is-done { border-color: var(--accent); }
.hold.is-done .hold-label-lit { clip-path: none; }
.hold.is-armed { border-color: var(--accent); box-shadow: var(--glow-accent); }
.hold.is-tapped { border-color: var(--accent); box-shadow: var(--glow-accent); }   /* a click on a hold: shell.js says to hold it */
.reply.is-tap { color: var(--accent); }
.hold.is-pulse { box-shadow: var(--glow-accent); transition: box-shadow 240ms; }
.hold:disabled { cursor: not-allowed; border-color: var(--hairline); color: var(--text-muted); background: transparent; }
.hold-note { font-size: 0.8125rem; color: var(--text-muted); }
.hold-compact { min-width: 180px; min-height: 48px; }
.hold-compact .hold-label, .hold-compact .hold-label-lit { font-size: 1rem; }

/* ---- rolling digits (flourish 05) ---------------------------------------------------------------- */
.digits-face { display: inline-flex; align-items: baseline; }
.digits { display: inline-flex; align-items: baseline; font-family: var(--font-mono); font-variant-numeric: tabular-nums; line-height: 1; white-space: nowrap; }
.digit { display: inline-block; height: 1em; width: .6em; overflow: hidden; position: relative; vertical-align: top; }
.digit-strip { display: flex; flex-direction: column; transition: transform 220ms var(--ease-machined); will-change: transform; }
.digit-strip span { display: block; height: 1em; line-height: 1em; text-align: center; }
.digit-static { display: inline-block; width: .6em; text-align: center; line-height: 1em; height: 1em; }
.digit-static.is-separator { width: .38em; }
.digit-static.is-letter { width: auto; padding: 0 .08em; }

/* ---- readouts ------------------------------------------------------------------------------------- */
.readouts { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-5); }
.readouts .ln-readout, .hero-counts .ln-readout { min-width: 0; }
.readouts .ln-readout-value { font-size: 1.625rem; display: flex; align-items: baseline; }
.readouts .ln-readout-value .digits { font-size: 1em; }
.readout-of { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-muted); margin-top: 2px; }
/* Flourish 06: lost, the values step down to muted (240 ms); regained, a changed one lands in the accent and
   cools to text over 900 ms. */
.readouts .ln-readout-value { transition: color 900ms var(--ease-machined), text-shadow 900ms var(--ease-machined); }
.ln-panel.is-last-known .readouts .ln-readout .ln-readout-value { color: var(--text-muted); text-shadow: none; animation: none; transition: color var(--flow-ui); }
.readouts .ln-readout.is-regained .ln-readout-value { color: var(--accent); text-shadow: 0 0 18px var(--accent-glow); transition: none; }

/* ---- the message center --------------------------------------------------------------------------- */
.inbox { margin: 0; padding: 0; list-style: none; display: grid; }
.letter + .letter { border-top: 1px solid var(--hairline); }
.letter-row { appearance: none; width: 100%; display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; min-height: 60px;
  padding: var(--space-3) var(--space-2) var(--space-3) 0; background: none; border: 0; text-align: left; cursor: pointer; color: var(--text); transition: background .15s; }
.letter-row:hover { background: var(--veil-1); }
.letter-row[aria-expanded="true"] { background: var(--veil-2); }
.letter-from { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); display: block; margin: 3px 0; }
.letter-subject { display: block; font-size: 0.9375rem; line-height: 1.3; color: var(--text-secondary); overflow-wrap: break-word; }
.letter.is-unread .letter-subject { color: var(--text); font-weight: 600; }
.letter-tag { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
.letter.is-waiting .letter-tag { color: var(--accent); }
.letter-body { display: grid; gap: var(--space-4); padding: var(--space-4) 0 var(--space-5) var(--space-5); }
.letterhead { margin: 0; padding-bottom: var(--space-3); border-bottom: 1px solid var(--hairline); }
.memo { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 2px var(--space-4); margin: 0; }
.memo dt { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); padding-top: 3px; }
.memo dd { margin: 0; font-size: 0.875rem; color: var(--text-secondary); }
.letter-text { font-size: 1rem; line-height: 1.6; color: var(--text); max-width: 60ch; }
.intern { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-3); align-items: start; padding: var(--space-3) var(--space-4); background: var(--veil-1); }
.intern-lens { width: 10px; height: 10px; margin-top: 5px; background: var(--accent); box-shadow: 0 0 10px var(--accent-glow); }
.intern-line { font-size: 0.875rem; color: var(--text-secondary); }
.decision { display: grid; gap: var(--space-3); padding-top: var(--space-2); }
.options { display: grid; gap: var(--space-2); margin: 0; padding: 0; border: 0; min-width: 0; }
.option { position: relative; display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: var(--space-3); align-items: center; min-height: 48px; padding: var(--space-2) var(--space-3);
  border: 1px solid var(--edge); cursor: pointer; font-size: 0.9375rem; transition: border-color .15s, background .15s; }
.option:hover { background: var(--veil-1); }
.option input { appearance: none; width: 14px; height: 14px; margin: 0; border: 1px solid var(--text-secondary); display: grid; place-items: center; cursor: pointer; }
.option input:checked { border-color: var(--accent); }
.option input:checked::after { content: ""; width: 6px; height: 6px; background: var(--accent); }
.option:has(input:checked) { border-color: var(--accent-line); background: var(--accent-wash); }
.option:has(input:focus-visible) { outline: 2px solid var(--flare); outline-offset: 2px; }
.option input:focus-visible { outline: none; box-shadow: none; }
.decision-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.receipt { font-family: var(--font-mono); font-size: 0.8125rem; line-height: 1.5; color: var(--text-secondary); padding: var(--space-3) var(--space-4); border-left: 2px solid var(--accent-line); background: var(--veil-1); }
:root:not(.is-still) .letter.is-new { animation: arrive 480ms var(--ease-machined) both; }
:root:not(.is-still) .enter { animation: arrive var(--flow-ui) var(--ease-machined) both; }
/* Waiting on (G#12): the chair holding the step; the square pulses full once a second while they are here. */
.waiting-on { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0 0 var(--space-4); padding: var(--space-2) 0; border-bottom: 1px solid var(--hairline); font-size: 0.875rem; }
.waiting-on .eyebrow { color: var(--accent); }
.waiting-on .waiting-step { color: var(--text-secondary); }
.waiting-on .waiting-propose { color: var(--text-muted); flex-basis: 100%; font-size: 0.8125rem; }
.waiting-on .square.is-present { background: var(--accent); border-color: var(--accent); }
/* It blinks on a layer of its own (opacity), not by repainting the square's background every frame. */
:root:not(.is-still) .waiting-on .square.is-present { position: relative; background: transparent; }
:root:not(.is-still) .waiting-on .square.is-present::before { content: ""; position: absolute; inset: 0; background: var(--accent);
  animation: waiting-pulse 1s steps(2, jump-none) infinite; }
@keyframes waiting-pulse { from { opacity: 1; } to { opacity: 0; } }

/* Since you were here (G#13): one card before the step for a student back after half an hour. */
.since-card { display: grid; gap: var(--space-4); justify-items: start; margin-bottom: var(--space-5); }
.since-card .since-title { color: var(--accent); }
.since-card .since-title:focus { outline: none; }
.back-note { margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); border-left: 3px solid var(--accent); background: var(--surface-2, transparent); }

/* The handoff (G#11): the receipt under the closed surface, accent cooling to text; then a seam draws across
   while the closed surface steps back and drifts right. */
.surface { position: relative; }
.handoff-receipt { margin: var(--space-4) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--hairline); font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text); }
:root:not(.is-still) .handoff-receipt { animation: receipt-cool 1200ms var(--ease-machined) both; }
@keyframes receipt-cool { from { color: var(--accent); opacity: 0; transform: translateY(4px); } 20% { opacity: 1; transform: none; } to { color: var(--text); } }
.surface.is-handing-off > * { opacity: .4; transform: translateX(12px); transition: opacity 600ms var(--ease-machined), transform 600ms var(--ease-machined); }
.surface.is-handing-off::after { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--accent); transform-origin: left; animation: seam-draw 600ms var(--ease-machined) both; }
@keyframes seam-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes arrive { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: none; } }

/* Proposals and the crew */
.proposals { margin: 0; padding: 0; list-style: none; display: grid; }
.proposal { display: grid; gap: var(--space-2); padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
.proposal-text { font-size: 0.9375rem; color: var(--text); }
.proposal-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.roster { margin: 0; display: grid; gap: 0; }
.roster div { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); padding: var(--space-3) 0; border-top: 1px solid var(--hairline); align-items: baseline; }
.roster dt { font-family: var(--font-display); font-weight: 600; font-size: 0.9375rem; letter-spacing: .1em; text-transform: uppercase; color: var(--text-secondary); }
.roster dd { margin: 0; font-family: var(--font-mono); font-size: 0.8125rem; color: var(--text); text-align: right; }
.roster .is-you dt { color: var(--text); }
.you { font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .18em; color: var(--accent); margin-left: var(--space-2); }

/* ---- the caption bar (flourish 01) ---------------------------------------------------------------- */
.caption-bar { position: fixed; left: 50%; bottom: max(16px, env(safe-area-inset-bottom, 0px)); z-index: 40; width: min(720px, calc(100% - 32px));
  transform: translate(-50%, calc(100% + 32px)); opacity: 0; pointer-events: none;
  background: var(--glass); -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.2); backdrop-filter: blur(var(--blur-glass)) saturate(1.2);
  box-shadow: var(--depth-inset), var(--shadow-deep); padding: 14px 18px 16px; display: grid; gap: 6px;
  transition: transform var(--flow-ui) var(--ease-machined), opacity var(--flow-ui); }
.caption-bar.is-shown { transform: translate(-50%, 0); opacity: 1; }
/* Beside the console's side column, the bar is centred over the main column so it never covers the inbox or proposals */
@media (min-width: 1181px) {
  body:has(#crew-screen:not([hidden])) .caption-bar:not(.is-docked) {
    --console-width: min(100vw, 1320px); --console-pad: max(16px, 2vw);
    --main-width: calc(var(--console-width) - 2 * var(--console-pad) - 384px - var(--space-5));
    left: calc((100vw - var(--console-width)) / 2 + var(--console-pad) + var(--main-width) / 2);
    width: min(640px, calc(var(--main-width) - 32px)); }
}
.caption-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* One case in the bar: the speaker in Barlow Condensed caps, the line in Barlow, sentence case. */
.caption-speaker { font-family: var(--font-display); font-weight: 600; letter-spacing: .12em; color: var(--text-secondary); }
.caption-text { font-size: 1.125rem; line-height: 1.4; min-height: 1.4em; color: var(--text); transition: color 600ms; }
.caption-text.is-spent { color: var(--text-muted); }
.caption-text .word { display: inline-block; transition: opacity 180ms var(--ease-machined), transform 180ms var(--ease-machined); }
.caption-text .word.is-pending { opacity: 0; transform: translateX(-4px); }
.caption-seam { position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--accent-line); transform: scaleX(0); transform-origin: left; transition: transform var(--flow-ui) var(--ease-machined); }
.caption-seam.is-on { transform: scaleX(1); }
.caption-seam.is-off { transform-origin: right; }

/* ---- the mission manifest: its own rules are in manifest.css; these few are shared with other pages ---- */
.ledger { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.ledger th { font-family: var(--font-mono); font-size: 0.625rem; font-weight: 500; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); text-align: left; padding: 0 var(--space-3) var(--space-2) 0; }
.ledger td { padding: var(--space-3) var(--space-3) var(--space-3) 0; border-top: 1px solid var(--hairline); color: var(--text-secondary); vertical-align: top; }
.ledger td:first-child { color: var(--text); }
.ledger .number { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.ledger th.number { text-align: right; }
.ledger-scroll { overflow-x: auto; }
.stepper-compact.manifest-label { display: block; justify-self: center; }
.sign-form { display: grid; gap: var(--space-3); }

/* ---- the teacher's room ----------------------------------------------------------------------------- */
.teacher-page { position: relative; z-index: 1; max-width: 1320px; margin: 0 auto; padding: var(--space-6) max(16px, 2vw) 0; display: grid; gap: var(--space-5); }
.teacher-sign-in { min-height: calc(100vh - 160px); display: grid; align-items: center; grid-template-columns: minmax(0, 1fr) minmax(320px, 440px); gap: var(--space-6); }
.teacher-panels { display: grid; gap: var(--space-5); }
.made-codes { display: grid; grid-template-columns: auto auto; gap: var(--space-2) var(--space-5); justify-content: start; padding: var(--space-4); background: var(--veil-2); border-left: 2px solid var(--accent-line); }
.made-codes .value { font-family: var(--font-mono); font-size: 1.5rem; letter-spacing: .2em; color: var(--text); }
.crew-table td .phase { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text); white-space: nowrap; }
.chips { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-2); }
.chip { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .06em; padding: 2px 6px; border: 1px solid var(--hairline); color: var(--text-secondary); white-space: nowrap; }
.chip.is-done { border-color: var(--edge); color: var(--text); }
.role-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 2px; font-size: 0.8125rem; }
.role-list .eyebrow { font-size: 0.625rem; letter-spacing: .16em; margin-right: var(--space-2); }
.tails { display: grid; gap: var(--space-2); }
.tail summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; gap: var(--space-3); font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-secondary); }
.tail ol { margin: 0; padding: 0 0 var(--space-3) var(--space-5); font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-secondary); display: grid; gap: 2px; }
.purge { border-top: 1px solid var(--hairline); }
.purge fieldset { border: 1px solid var(--edge); padding: var(--space-3) var(--space-4); margin: 0; display: grid; gap: var(--space-2); }
.purge legend { padding: 0 var(--space-2); }
.purge label.choice { display: flex; gap: var(--space-3); align-items: center; min-height: 44px; font-size: 0.9375rem; cursor: pointer; }
.purge input[type="radio"] { width: 18px; height: 18px; accent-color: var(--text); }
.ln-btn-danger { border-color: var(--flare); color: var(--flare); }
.ln-btn-danger:hover { background: var(--flare); color: var(--on-flare); }

/* ---- the developer drawer, behind #developer --------------------------------------------------------- */
.developer { margin-top: var(--space-6); }
.developer pre { max-height: 320px; overflow: auto; font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-secondary); background: var(--veil-1); padding: var(--space-3); }

/* ---- M3: the story on the console, the game bay, the review, the objectives, launch day, the debrief ---- */
/* The act card is a curtain over the whole main column while it plays: nothing below it jumps, and nothing peeks
   out clipped beneath it (the page title used to). The act sits high, in the first screen; the curtain lifts
   on the machined ease once the title has drifted off with the flow. */
.console-main { position: relative; }
.act-card { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
.act-card .story-act { height: 100%; align-content: start; padding-top: clamp(96px, 22vh, 220px);
  box-shadow: var(--shadow-deep); pointer-events: auto; }
.act-card .story-act[data-state="leaving"] { opacity: 0; transform: translateY(-12px);
  transition: opacity var(--flow-ui) var(--ease-machined) 300ms, transform var(--flow-ui) var(--ease-machined) 300ms; }
/* H.A.L.'s message center heads the side column; it scrolls inside itself so the readouts stay in reach. */
.story-slot .mc { max-width: none; min-height: 16rem; max-height: min(52vh, 30rem); }
.story-slot:empty { display: none; }

/* ---- the side column: one lit plane ---------------------------------------------------------------- */
/* wchesher, 2026-10-27: "this needs some real functional redesign. It needs vision: its too boxy and unattractive".
   The side column was a stack of framed boxes, each with its own light, its own corner of lamps and its own shadow.
   It is one plane now, lit once from its top-left corner as the design system has every panel lit ("hierarchy comes
   from what the light reaches, not from boxes and borders"): H.A.L., the readouts, proposals, letters and chairs are
   sections of it, parted by the travelling seam (.ln-panel::after) and nothing else. What waits on the student heads
   it (For you, console.js paintForYou), lit in the accent; H.A.L.'s feed is next, on air (story/message-center.js). */
.console-side { gap: 0; align-self: start; isolation: isolate;
  background: radial-gradient(120% 36% at 0% 0%, var(--key-light), transparent 60%), var(--glass); box-shadow: var(--depth-inset), var(--shadow-deep);
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(1.2); backdrop-filter: blur(var(--blur-glass)) saturate(1.2); }
.console-side > .ln-panel { box-shadow: none; border-top: 0; }
.console-side > .ln-panel:not(.ln-panel-active) { background: none; }
.console-side > .ln-panel-active { background: linear-gradient(180deg, var(--accent-wash), transparent 70%); }
.console-side > .ln-panel::before, .console-side > .ln-panel > .ln-trim { display: none; }
.console-side .story-slot .mc { background: none; box-shadow: none; -webkit-backdrop-filter: none; backdrop-filter: none; min-height: 20rem; max-height: min(72vh, 44rem); }
.for-you { display: grid; gap: var(--space-3); padding: var(--space-4) var(--space-5) var(--space-5);
  background: linear-gradient(100deg, var(--accent-wash), transparent 85%); box-shadow: inset 0 1px 0 var(--accent-line); }
.for-you[hidden] { display: none; }
.for-you, .console-side > .rail-head { grid-column: 1 / -1; }
.for-you .ln-eyebrow { color: var(--accent); }
.for-you-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-4); }
.for-you-item { display: grid; gap: var(--space-2); justify-items: start; }
.for-you-item .eyebrow { color: var(--text-muted); }
.for-you-text { margin: 0; font-size: 1rem; line-height: 1.4; color: var(--text); max-width: 40ch; }

.game-mount { min-width: 0; }

.review-report { display: grid; grid-template-columns: minmax(0, max-content) minmax(0, 1fr); gap: var(--space-2) var(--space-5); margin: var(--space-5) 0; padding: var(--space-4) 0;
  border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.review-report dt { margin: 0; padding-top: 3px; }
.review-report dd { margin: 0; font-family: var(--font-mono); font-size: 0.875rem; color: var(--text); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.review-question { margin: 0 0 var(--space-4); padding-left: var(--space-4); border-left: 2px solid var(--accent-line); display: grid; gap: var(--space-1); }
.review-question .title { font-size: 1.25rem; line-height: 1.3; color: var(--text); max-width: 40ch; }
/* Part 2's close: the ignition bench's case 2 beside the question, red or never run (review.js evidence). */
.review-question .review-evidence { margin: 0; display: grid; gap: var(--space-1); max-width: 40ch; color: var(--text); }
/* The review's lines (alpha/review.js): one per chair, the student's own as a field, a crewmate's as their words. */
.review-lines { display: grid; gap: var(--space-3); margin: var(--space-3) 0; padding: 0; list-style: none; }
.review-line { display: grid; gap: var(--space-1); padding-left: var(--space-3); border-left: 1px solid var(--hairline); }
/* A replay's Last time card behind Help (alpha/last_time.js): label over words, the student's own lines in the story face. */
.last-time-rows { display: grid; gap: var(--space-3); margin: var(--space-3) 0 0; }
.last-time-row { display: grid; gap: var(--space-1); }
.last-time-row dd { margin: 0; color: var(--text); }
/* A replay's line from last time (review.js, Keep or Rewrite): quoted as written, the two presses under it. */
.review-last-time { margin: 0; font-style: italic; color: var(--text); }
/* A solo play's crewmate row (review.js crewmateRow): their face and name card, as on the move bar, over their line. */
.review-crewmate { display: flex; align-items: center; gap: var(--space-3); margin: 0; }
.review-crewmate-face { display: block; width: 48px; flex: none; border-radius: 2px; overflow: hidden; background: var(--al-surface, #15130f); }
.review-crewmate-face > .portrait { width: 100%; }
/* How the part's boards went (alpha/review.js boards): the crew's number, and the class's beside it, quiet and in mono. */
.review-boards { display: grid; gap: var(--space-2); margin: var(--space-5) 0 0; padding-top: var(--space-4); border-top: 1px solid var(--hairline); }
.review-board-numbers { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.review-board-numbers li { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: var(--space-4); align-items: baseline; }
.review-board-yours, .review-board-most { font-family: var(--font-mono); font-size: 0.875rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.review-board-title { display: grid; gap: 2px; min-width: 0; }
.review-board-of { font-size: 0.8125rem; color: var(--text-secondary); }
.review-board-yours { color: var(--text); }
.review-board-most { color: var(--text-secondary); }
@media (max-width: 760px) { .review-board-numbers li { grid-template-columns: minmax(0, 1fr); gap: 0; } }
/* A chair's box with its Write it beside it, not under it, so the three lines and the filing fit nearer the first
   screen (the game analysis, W6). */
@media (min-width: 761px) {
  .review-line:has(> textarea) { grid-template-columns: minmax(0, 1fr) auto; align-items: end; column-gap: var(--space-3); }
  .review-line:has(> textarea) > .field-label { grid-column: 1 / -1; }
  .review-line > .panel-actions { margin: 0; }
}

.objective-list { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
/* Cards in a row are one height (wchesher, 2026-10-26, of the landing list: "these need to align"): the card fills
   its item's first row, so a title that wraps to three lines grows the row, not the one card, and every title holds
   to the top. What follows a card in its item (the reason field under a chosen objective) sits beneath it. Where
   subgrid is understood, the items in a row share their two rows, so a chosen card with its field below keeps the
   same edge as its neighbours too; there the space between rows is each item's own top padding, because a gap on
   the list would also open between a card and the empty row beneath it. */
.objective-list li { display: grid; grid-template-rows: 1fr; grid-auto-rows: auto; }
.objective-list li > .card ~ * { margin-top: var(--space-2); }
@supports (grid-template-rows: subgrid) {
  .objective-list { row-gap: 0; margin-top: calc(var(--space-5) - var(--space-3)); }
  .objective-list li { grid-row: span 2; grid-template-rows: subgrid; padding-top: var(--space-3); }
}
.objective-list .card { width: 100%; height: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit; }
.launch-head .ln-panel { display: grid; gap: var(--space-4); }
.launch-deck { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr); gap: var(--space-4) var(--space-6); align-items: start; padding: var(--space-4) 0; border-top: 1px solid var(--hairline); }
.launch-deck-count { display: grid; gap: var(--space-1); }
.launch-deck-count .display-l { font-variant-numeric: tabular-nums; color: var(--text); }
.launch-deck-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.launch-deck-cards li { display: grid; grid-template-columns: 12px minmax(0, 1fr); gap: 2px var(--space-3); align-items: baseline; font-size: 0.9375rem; color: var(--text-secondary); }
.launch-deck-cards li.is-lost { color: var(--text); }
.launch-deck-cards li.is-lost .square { background: var(--flare); border-color: var(--flare); }
.launch-deck-source { grid-column: 2; font-size: 0.8125rem; color: var(--text-muted); }
.launch-status { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-4); margin: 0; }
.launch-status .eyebrow { margin: 0; }
.launch-start { display: grid; gap: var(--space-3); padding-top: var(--space-4); border-top: 1px solid var(--hairline); }
.launch-stage { min-width: 0; }
/* While the broadcast runs it takes the console's full width; H.A.L. and the readouts wait below it. */
@media (min-width: 1181px) {
  .is-broadcast .console { grid-template-columns: minmax(0, 1fr); }
  .is-broadcast .console-side { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
}
/* The broadcast captions its own program feed; the shell's bar would only replay the session's backlog over it. */
body.is-broadcast .caption-bar { display: none; }
/* The count brings the feed up under the header, which parks the step's duty lines beneath the glass; through it
   they read as ghost text over the crew badge. While the feed is the screen the header is solid. */
body.is-broadcast .deck-header { background: var(--ground); -webkit-backdrop-filter: none; backdrop-filter: none; }
.launch-broadcast { min-width: 0; }
.launch-continue { display: flex; justify-content: flex-end; margin-top: var(--space-4); }
.hold-dialog { width: min(520px, calc(100vw - 32px)); max-width: none; border: 1px solid var(--edge); color: var(--text); padding: var(--space-5); }
.hold-dialog::backdrop { background: rgb(0 0 0 / .62); }
.hold-form { display: grid; gap: var(--space-3); }
.hold-form .ln-panel-title { margin: 0; }

/* ---- sign off (signoff.js): the header's last button, and the one question it asks --------------- */
/* A small card over the console, never a page: the padding is on the body so a click on the dialog itself is
   outside the card, and Stay holds the focus, so a stray press or a stray Enter changes nothing. */
.sign-off-dialog { width: min(440px, calc(100vw - 32px)); max-width: none; margin: auto; padding: 0;
  border: 1px solid var(--hairline); border-top: 1px solid var(--accent-line); color: var(--text); }
.sign-off-dialog::backdrop { background: var(--shade); }
.sign-off-body { padding: var(--space-5); }
.sign-off-body .ln-panel-title { margin-bottom: var(--space-2); }
.sign-off-dialog .sign-off-question { font-size: 0.9375rem; color: var(--text); max-width: 40ch; }
.sign-off-dialog .panel-actions { justify-content: flex-end; }
:root:not(.is-still) .sign-off-dialog[open] { animation: sign-off-in var(--flow-ui) var(--ease-machined) both; }
@keyframes sign-off-in { from { opacity: 0; transform: translateY(-6px); } }

.debrief-headline { color: var(--text); text-wrap: balance; margin: var(--space-3) 0; }
.debrief-slot { display: grid; gap: var(--space-4); }
.debrief-document { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.debrief-document li { display: grid; gap: var(--space-1); }
.debrief-document li p { max-width: 64ch; font-size: 0.9375rem; color: var(--text); }
.debrief-chart { min-width: 0; overflow: hidden; }
.debrief-seed { font-size: 0.9375rem; letter-spacing: .08em; color: var(--text); overflow-wrap: anywhere; margin: var(--space-3) 0; }
.debrief-counts { list-style: none; margin: var(--space-4) 0; padding: 0; display: grid; gap: var(--space-2); }
.debrief-counts li { display: grid; grid-template-columns: minmax(0, 14rem) minmax(0, 1fr); gap: var(--space-1) var(--space-4); align-items: baseline; font-size: 0.875rem; color: var(--text-secondary); }

/* ---- M4: the day-one guess, the site's sentence, the day's weather, the crew arrival review ---------- */
.guess-question { font-family: var(--font-display); font-size: clamp(22px, 2.2vw, 28px); line-height: 1.25; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text); max-width: 34ch; margin: var(--space-2) 0 var(--space-6); text-wrap: balance; }
.guess-dial { display: grid; gap: var(--space-3); max-width: 560px; margin-bottom: var(--space-6); }
.guess-readout { display: flex; align-items: baseline; gap: var(--space-3); margin: 0; }
.guess-number { font-family: var(--font-display); font-size: 6rem; line-height: .9; font-weight: 600; letter-spacing: .02em;
  font-variant-numeric: tabular-nums; color: var(--text); min-width: 3ch; }
.guess-unit { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .24em; text-transform: uppercase; color: var(--text-muted); }
.guess-range { -webkit-appearance: none; appearance: none; width: 100%; height: 44px; margin: 0; background: transparent; cursor: pointer; --fill: 50%; }
.guess-range::-webkit-slider-runnable-track { height: 2px; background: linear-gradient(90deg, var(--accent) var(--fill), var(--hairline) var(--fill)); }
.guess-range::-moz-range-track { height: 2px; background: var(--hairline); }
.guess-range::-moz-range-progress { height: 2px; background: var(--accent); }
.guess-range::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; margin-top: -8px; border-radius: 0;
  background: var(--text); border: 1px solid var(--edge); box-shadow: 0 0 0 4px var(--ground); }
.guess-range::-moz-range-thumb { width: 18px; height: 18px; border-radius: 0; background: var(--text); border: 1px solid var(--edge); }
.guess-range:focus-visible { outline: none; }
.guess-range:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--ground), var(--glow-accent); }
.guess-range:focus-visible::-moz-range-thumb { box-shadow: var(--glow-accent); }
.guess-scale { display: flex; justify-content: space-between; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-muted); }
.guess-dial + .field { max-width: 560px; }
.site-why { margin-top: var(--space-5); max-width: 640px; }

.launch-weather { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-4); margin: 0;
  padding-bottom: var(--space-3); border-bottom: 1px solid var(--hairline); }
.launch-weather-words { font-size: 0.9375rem; color: var(--text-secondary); }
.launch-weather.is-at-limit .launch-weather-words { color: var(--text); }
.launch-weather.is-at-limit .eyebrow { color: var(--accent); }

.debrief-headline { font-size: clamp(26px, 2.6vw, 34px); line-height: 1.1; max-width: 26ch; }
.debrief-facts { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: var(--space-2) var(--space-4); margin: var(--space-5) 0 0;
  padding-top: var(--space-4); border-top: 1px solid var(--hairline); max-width: 72ch; }
.debrief-facts dt { padding-top: 3px; }
.debrief-facts dd { margin: 0; font-size: 0.9375rem; line-height: 1.5; color: var(--text-secondary); }
.debrief-numbers { width: 100%; border-collapse: collapse; margin: var(--space-2) 0 var(--space-6); font-variant-numeric: tabular-nums; }
.debrief-numbers th, .debrief-numbers td { text-align: left; padding: var(--space-3) var(--space-3) var(--space-3) 0; border-bottom: 1px solid var(--hairline); vertical-align: baseline; }
.debrief-numbers thead th { padding-top: 0; font-weight: 500; }
.debrief-numbers tbody th { font-weight: 600; font-size: 0.9375rem; color: var(--text); }
.debrief-numbers td { color: var(--text-secondary); }
.debrief-value { font-size: 1.125rem; color: var(--text); }
/* The harvest review's seventh screen: ours, nobody's, Percival's, and what we did next */
/* The harvest so far, folded under the last two calls once the review is read (alpha/harvest.js) */
.alpha-harvest-before { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--hairline); }
.alpha-harvest-before > summary { cursor: pointer; color: var(--text-secondary); }
.alpha-review-kinds { width: 100%; margin: var(--space-2) 0 var(--space-4); border-collapse: collapse; }
.alpha-review-kinds th, .alpha-review-kinds td { text-align: left; padding: var(--space-2) var(--space-3) var(--space-2) 0; border-bottom: 1px solid var(--hairline); vertical-align: top; font-size: 0.875rem; line-height: 1.45; }
.alpha-review-kinds thead th { font-weight: 500; }
.alpha-review-kinds td { color: var(--text-secondary); }
.alpha-review-kinds td:last-child { color: var(--text); }
/* A phone reads each consequence as a stack: whose it was, then what the crew did next, each under its column's name */
@media (max-width: 640px) {
  .alpha-review-kinds thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .alpha-review-kinds tr { display: grid; gap: var(--space-1); padding: var(--space-3) 0; border-bottom: 1px solid var(--hairline); }
  .alpha-review-kinds td { display: block; padding: 0; border: 0; }
  .alpha-review-kinds td:empty { display: none; }
  .alpha-review-kinds td::before { content: attr(data-label); display: block; font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); }
}
.debrief-verdict { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase; }
.debrief-numbers .is-pass .debrief-verdict { color: var(--text-secondary); }
.debrief-numbers .is-pass .square { background: var(--text-secondary); border-color: var(--text-secondary); }
.debrief-numbers .is-fail .debrief-verdict { color: var(--text); }
.debrief-numbers .is-fail .square { background: transparent; border-color: var(--text); }
.debrief-document li.is-direction p { font-size: 0.875rem; font-style: italic; color: var(--text-muted); max-width: 64ch; }
.debrief-line { display: grid; gap: var(--space-2); }
.debrief-line > p { max-width: 64ch; font-size: 0.9375rem; line-height: 1.55; color: var(--text); margin: 0; }
.debrief-quote { margin: var(--space-1) 0; padding: var(--space-1) 0 var(--space-1) var(--space-4); border-left: 2px solid var(--accent-line); max-width: 60ch; }
.debrief-quote p { margin: 0; font-family: var(--font-body); font-size: 1.0625rem; line-height: 1.5; color: var(--text); }
.debrief-subhead { margin: var(--space-6) 0 var(--space-2); font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .24em; text-transform: uppercase; color: var(--text-muted); }
.debrief-nominal { display: grid; gap: var(--space-3); margin-top: var(--space-5); }
.debrief-direction { margin: 0; font-size: 0.875rem; line-height: 1.55; font-style: italic; color: var(--text-muted); max-width: 70ch; }
.debrief-pull { margin: var(--space-5) 0 0; padding: var(--space-5) 0 0; border-top: 1px solid var(--hairline); }
.debrief-pull blockquote { margin: 0; }
.debrief-pull blockquote p { margin: 0 0 var(--space-3); font-family: var(--font-display); font-size: clamp(24px, 2.4vw, 32px); line-height: 1.2;
  letter-spacing: .04em; text-transform: uppercase; color: var(--text); max-width: 30ch; text-wrap: balance; }
.debrief-percival { display: grid; gap: var(--space-4); justify-items: start; padding: var(--space-7) var(--space-5) var(--space-6);
  border-top: 1px solid var(--hairline); }
.debrief-percival-line { margin: 0; font-family: var(--font-display); font-size: clamp(22px, 2.2vw, 28px); line-height: 1.25; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text); max-width: 36ch; text-wrap: balance; }
.debrief-percival-mark { margin-top: var(--space-5); opacity: .55; }

/* ---- M4: the exit ticket, the holding room, the failure review ------------------------------------ */
.ticket { display: grid; gap: var(--space-3); }
.ticket-question { display: grid; gap: var(--space-1); margin: 0; font-size: 1rem; line-height: 1.5; color: var(--text); max-width: 60ch; }
.ticket-question.body-s { font-size: 0.875rem; }
.ticket-speaker { color: var(--text-muted); }
.ticket-label { font-family: var(--font-mono); letter-spacing: .2em; }
.ticket-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.ticket-line { margin: 0; padding: var(--space-1) 0 var(--space-1) var(--space-4); border-left: 2px solid var(--accent-line); font-size: 0.9375rem; line-height: 1.5; color: var(--text); }
.ticket-panel .field { margin: 0; }
/* Part one's question weighs the crew's goals, so they stand beside it (ticket.js ticketGoals): to the right of the
   question and the field where there is room, under the question where there is not. */
.ticket.has-goals { grid-template-columns: minmax(0, 1fr) minmax(220px, 300px); column-gap: var(--space-5); align-items: start; }
.ticket.has-goals > :not(.ticket-goals) { grid-column: 1; }
.ticket.has-goals > .ticket-goals { grid-column: 2; grid-row: 1 / span 4; }
.ticket-goals { display: grid; gap: var(--space-2); padding: var(--space-3) var(--space-4); background: var(--veil-1); border-left: 2px solid var(--accent-line); }
.ticket-goal-list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.ticket-goal-list li { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: var(--space-2); font-size: 0.9375rem; line-height: 1.4; color: var(--text); }
.ticket-goal-rank { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .08em; color: var(--text-muted); padding-top: 2px; }
.ticket-goals.is-compact .ticket-goal-list li { font-size: 0.8125rem; }
@media (max-width: 760px) {
  .ticket.has-goals { grid-template-columns: minmax(0, 1fr); }
  .ticket.has-goals > .ticket-goals { grid-column: 1; grid-row: auto; }
}

.holding-line { display: flex; align-items: flex-start; gap: var(--space-4); margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--hairline); }
.holding-pulse { flex: none; width: 10px; height: 10px; margin-top: 6px; background: var(--accent); box-shadow: var(--glow-accent); }
.holding-words { display: grid; gap: var(--space-1); }
/* Crew Training offered at Done for now (surfaces/holding.js): one quiet row under the room's own lines */
.holding-training { margin-top: var(--space-4); }
.holding-visit { margin: 0 0 var(--space-4); }
.holding-visit:empty { display: none; }
.holding-training .ln-panel { display: grid; gap: var(--space-3); justify-items: start; }
.holding-station { font-family: var(--font-mono); font-size: 0.9375rem; letter-spacing: .18em; text-transform: uppercase; color: var(--text); }

/* Mission Alpha's base map (alpha/basemap.js): a blueprint sheet in the station's own line work. Built marks are drawn
   in text grey, what is still to come faint and dashed where it will stand, the mark reached last in the one warm line,
   the link home (the ping, the flight) in telemetry blue. The crater is the darkest thing on the sheet and stays dark.
   Labels are mono capitals; the sentence under the sheet carries the words, so nothing rests on a label alone. */
.basemap-sheet { display: block; width: 100%; height: auto; overflow: visible; font-family: var(--font-mono); }
.basemap-frame rect { fill: none; stroke: var(--hairline); stroke-width: 1; }
.basemap-title { fill: var(--text-muted); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; }
.basemap-label { fill: var(--text-muted); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }
.basemap-ground path { fill: none; stroke: var(--edge); stroke-width: 1; stroke-linecap: round; }
.basemap-ground .basemap-towers { stroke-width: 2; stroke-linecap: butt; }
.basemap-ground .basemap-ramp { stroke-dasharray: 3 3; }
.basemap-crater { fill: var(--ground); stroke: var(--hairline); stroke-width: 1; }
.basemap-ridge path { fill: none; stroke: var(--edge); stroke-width: 1; }
.basemap-ridge.is-passed path { stroke: var(--hairline); }
.basemap-ridge.is-built path { fill: var(--veil-2); stroke: var(--text-secondary); }
.basemap-ridge.is-built text { fill: var(--text); }
.basemap-ridge.is-newest path { fill: var(--accent-wash); stroke: var(--accent); stroke-width: 1.5; }
.basemap-ridge.is-newest text { fill: var(--accent); }
.basemap-mark { fill: none; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
.basemap-mark * { vector-effect: non-scaling-stroke; }
.basemap-mark.is-ahead { stroke: var(--edge); stroke-opacity: .45; stroke-dasharray: 2 2.5; }
.basemap-mark.is-built { stroke: var(--text-secondary); }
.basemap-mark.is-newest { stroke: var(--accent); stroke-width: 1.75; }
.basemap-mark .basemap-link { stroke-dasharray: 4 3; }
.basemap-mark.is-built .basemap-link { stroke: var(--telemetry); }
.basemap-mark .basemap-limits { stroke-dasharray: 1 3.5; }
.basemap-mark.is-built .basemap-limits { stroke: var(--edge); }
:root:not(.is-still) .basemap-mark.is-arriving { animation: basemap-arrive 1.6s var(--ease-machined) 1 both; }
@keyframes basemap-arrive { 0% { opacity: 0; } 30% { opacity: 1; stroke-width: 3; } 100% { opacity: 1; } }
.basemap-count { display: grid; gap: var(--space-1); margin: var(--space-3) 0 0; }
.basemap-latest { font-size: 0.875rem; line-height: 1.45; color: var(--text-secondary); }

/* The holding room's "Built in part N": the sheet beside the part's marks in words, under the review's filed line. */
.holding-built { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--space-2) var(--space-5); align-items: start; margin-top: var(--space-6); }
.holding-built > .eyebrow { grid-column: 1 / -1; margin: 0; }
.holding-built-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.holding-built-list li { display: grid; gap: 2px; padding-left: var(--space-3); border-left: 2px solid var(--hairline); }
.holding-built-list li.is-newest { border-left-color: var(--accent-line); }
.holding-built-name { font-family: var(--font-mono); font-size: 0.8125rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text); }
.holding-built-line { font-size: 0.9375rem; line-height: 1.45; color: var(--text-secondary); }

/* Part 7's racks (alpha/harvest.js): one rack a chair, three across where there is room, each brought in with one
   press; a rack that is in shows its weight on the food line in the mono face. */
.alpha-racks { display: grid; gap: var(--space-3); }
.alpha-racks .lede { margin: 0; }
.alpha-racks-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--space-3); }
.alpha-rack { display: grid; gap: var(--space-2); align-content: start; padding-left: var(--space-3); border-left: 2px solid var(--hairline); }
.alpha-rack.is-in { border-left-color: var(--accent-line); }
.alpha-rack .eyebrow, .alpha-rack p { margin: 0; }
.alpha-rack-weight, .alpha-racks-total { margin: 0; font-family: var(--font-mono); font-size: 0.875rem; color: var(--text); }
@media (max-width: 760px) { .holding-built { grid-template-columns: minmax(0, 1fr); } }

.failure-loss { margin: 0 0 var(--space-2); }
.failure-file { margin-top: var(--space-5); max-width: 640px; }
.failure-filed { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid; gap: var(--space-3); max-width: 72ch; }
.failure-filed li { display: grid; gap: var(--space-1); }
.failure-sentence { margin: 0; padding: var(--space-1) 0 var(--space-1) var(--space-4); border-left: 2px solid var(--accent-line); font-size: 0.9375rem; line-height: 1.5; color: var(--text); }
.failure-ruling { display: flex; align-items: center; gap: var(--space-3); margin: var(--space-6) 0 0; padding-top: var(--space-4); border-top: 1px solid var(--hairline);
  font-family: var(--font-mono); font-size: 0.8125rem; letter-spacing: .18em; text-transform: uppercase; color: var(--text); }
:root:not(.is-still) .holding-pulse { animation: holding-pulse 2.4s ease-in-out infinite; }
@keyframes holding-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* Mission Alpha's seam (console.js paintSeam): a step done, its screen kept and dimmed under one line that names what
   is next. The holding room's pulse and type, so a hand-off reads the same everywhere. */
.alpha-seam { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); margin: 0 0 var(--space-5);
  padding: var(--space-4) var(--space-5); border: 1px solid var(--hairline); border-left: 2px solid var(--accent);
  background: var(--surface-raised); }
/* Held under the header as the move bar is (the QA pass, 2026-10-31: after Seam 4's last probe scrolled the board, the
   seam's Continue sat above the window and the student saw no next control). The move bar is down while a seam is up
   (console.js nextMove.update(null)), so the two never stack; the act card's curtain (z 6) still passes over it. */
.alpha-seam { position: sticky; top: calc(64px + var(--space-2)); z-index: 5; box-shadow: var(--shadow-lift);
  /* the page's scroll-padding-top reserves --sticky-band, which is this card's own height while it is up: its own
     scrollIntoView takes that back, or the page scrolls to clear the card from itself (the solo plays, 2026-10-31: the
     seam's Continue at y -108 on a replay's site) */
  scroll-margin-top: calc(-1 * var(--sticky-band, 0px)); }
.alpha-seam[hidden] { display: none; }
.alpha-seam-mark { flex: none; width: 10px; height: 10px; background: var(--accent); box-shadow: var(--glow-accent); }
.alpha-seam-words { flex: 1 1 240px; display: grid; gap: var(--space-1); min-width: 0; }
.alpha-seam-next { font-family: var(--font-mono); font-size: 0.9375rem; letter-spacing: .18em; text-transform: uppercase; color: var(--text); }
.alpha-seam-owed { font-size: 1rem; line-height: 1.4; font-weight: 600; color: var(--text); }
.alpha-seam:not([hidden]) + .surface { opacity: .6; }
/* Last time, this time (alpha/recap.js): on a returning student's first open of a part the card is the column. The
   board waits beneath until Continue; the act card's curtain may still pass over it. */
.console-main[data-recapping] > :not(.alpha-recap):not(.act-card) { display: none; }
.alpha-recap { display: grid; gap: var(--space-4); max-width: 720px; margin: 0 0 var(--space-5); padding: var(--space-5) var(--space-6);
  border: 1px solid var(--hairline); border-left: 2px solid var(--accent); background: var(--surface-raised); }
.alpha-recap[hidden] { display: none; }
/* Continue held in view at the window's foot while the card is longer than the window (the QA pass, 2026-10-31: at
   y 869 under a 768 px fold), at the card's end once it is not */
.alpha-recap > [data-key="alpha-recap-continue"] { position: sticky; bottom: var(--space-4); justify-self: start; z-index: 1;
  box-shadow: var(--shadow-lift); }
.alpha-recap-since { color: var(--accent); }   /* the since card's own line, when the recap is the return card */
.alpha-recap-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.alpha-recap-head > .eyebrow { margin: 0; }
.alpha-recap-map { margin: 0; max-width: 420px; }
.alpha-recap-rows { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-4); margin: 0; }
.alpha-recap-rows dt { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); padding-top: 3px; }
.alpha-recap-rows dd { margin: 0; color: var(--text); }
.alpha-recap-now { margin-top: var(--space-3); padding-top: var(--space-4); border-top: 1px solid var(--hairline); }
.alpha-recap-line { margin: 0; color: var(--text-secondary); max-width: 62ch; }
.alpha-recap-move { display: grid; gap: var(--space-1); padding: var(--space-3) var(--space-4); border: 1px solid var(--accent-line); }
.alpha-recap-move.is-theirs { border-color: var(--hairline); }
.alpha-recap-move-text { font-weight: 600; color: var(--text); }
.alpha-recap-chair { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
.alpha-recap > .ln-btn { justify-self: start; }
@media (max-width: 640px) { .alpha-recap { padding: var(--space-4); } .alpha-recap-rows { grid-template-columns: 1fr; gap: var(--space-1); }
  .alpha-recap-rows dd { margin-bottom: var(--space-2); } }
/* A replay's board opens on its stretch goal (logic/stretch_lead.js; the chair's cut): the recap card's label and words,
   quiet, with no lamp and no accent, since the lit press stays the student's move and nothing here is marked. */
.alpha-stretch-lead { display: grid; gap: var(--space-3); max-width: 720px; margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4);
  border-left: 2px solid var(--hairline); }
.alpha-stretch-lead[hidden] { display: none; }
.alpha-stretch-lead-goal { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-1) var(--space-4); margin: 0; }
.alpha-stretch-lead-goal dt { font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); padding-top: 3px; }
.alpha-stretch-lead-goal dd { margin: 0; color: var(--text); }
.alpha-stretch-lead-goal dd.alpha-stretch-lead-last { color: var(--text-secondary); }
@media (max-width: 640px) { .alpha-stretch-lead-goal { grid-template-columns: 1fr; } .alpha-stretch-lead-goal dd { margin-bottom: var(--space-2); } }
/* Mission Alpha's close (ending.js, audit S9): the last card in the display face. The cards take the left half and the
   game's one Moon the right (M7): the Moon from Earth with the town's light, held in view while the cards play. */
.alpha-ending { display: grid; gap: var(--space-3); align-content: start; }
/* The case file on the end card paints every entry: the journal's content-visibility skip (alpha.css) left its last
   entries as 120 px of blank above CASE CLOSED until each was scrolled to (the fourth QA pass, 2026-10-31). */
.alpha-ending .al-journal-list > li { content-visibility: visible; contain-intrinsic-size: none; }
.alpha-ending-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.alpha-ending-moon { position: sticky; top: var(--space-4); }
.alpha-ending-moon .moon-beat { aspect-ratio: 1 / 1; max-height: 70vh; }
@media (max-width: 900px) { .alpha-ending-split { grid-template-columns: 1fr; } .alpha-ending-moon { position: static; } }
.alpha-close { position: relative; display: grid; place-items: center; align-content: center; min-height: clamp(280px, 52vh, 560px); margin-top: var(--space-4);
  overflow: hidden; background: var(--ground); }
.alpha-close-patch { position: relative; width: clamp(88px, 14vw, 140px); height: auto; filter: drop-shadow(0 2px 18px rgba(0, 0, 0, .6)); }
.alpha-close-words { position: relative; margin: 0; padding: var(--space-5); text-align: center;
  font-family: var(--font-display); font-weight: 700; font-size: clamp(2.5rem, 7vw, 5.5rem); line-height: 1; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text); text-shadow: 0 2px 24px rgba(0, 0, 0, .6); }
:root:not(.is-still) .alpha-close-words, :root:not(.is-still) .alpha-close-patch { animation: alpha-close-in 1.2s ease-out both; }
@keyframes alpha-close-in { from { opacity: 0; letter-spacing: .2em; } to { opacity: 1; letter-spacing: .06em; } }
/* Beside the Moon (M7) the close has half the panel. */
.alpha-ending-split .alpha-close { min-height: clamp(200px, 32vh, 360px); }
.alpha-ending-split .alpha-close-words { font-size: clamp(2rem, 4vw, 3.5rem); }
/* Play again (ending.js againCard, the chair's cut): under the close, one line and the one lit press. */
.alpha-again { display: grid; gap: var(--space-2); justify-items: center; padding: var(--space-5) var(--space-4); text-align: center; }
.alpha-again p { margin: 0; }
.alpha-again-said:empty { display: none; }
/* Play 3's capstone (alpha/ending.js): the student's three directives, each with its crewmate's line, before M7. The
   Moon waits out of sight, never display: none, so the globe measures and draws at its size. */
.alpha-ending-moon.is-held { visibility: hidden; }
.alpha-capstone { display: grid; gap: var(--space-3); }
/* Play 3's last screen (alpha/ending.js): the archive folded to its closing line, the capstone beside the Moon, and
   CASE CLOSED under the Moon in the first screen of a 768 px console. */
.alpha-ending-archive > summary, .alpha-ending-file > summary { cursor: pointer; }
.alpha-ending-split.is-capstone .alpha-ending-moon { display: grid; gap: var(--space-3); }
.alpha-ending-split.is-capstone .alpha-ending-moon .moon-beat { max-height: 48vh; }
.alpha-capstone-list { display: grid; gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
.alpha-capstone-item { display: grid; gap: var(--space-1); }
.alpha-capstone-item p { margin: 0; }
.alpha-capstone-sentence { font-size: 1.15rem; }
:root:not(.is-still) .alpha-seam:not([hidden]) + .surface { transition: opacity var(--flow-ui) ease; }
:root:not(.is-still) .alpha-seam:not([hidden]) { animation: alpha-seam-in 420ms cubic-bezier(.2,.7,.3,1) both; }
:root:not(.is-still) .alpha-recap:not([hidden]) { animation: alpha-seam-in 420ms cubic-bezier(.2,.7,.3,1) both; }
:root:not(.is-still) .alpha-seam-mark { animation: holding-pulse 2.4s ease-in-out infinite; }
@keyframes alpha-seam-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* ---- the fore window, down the page's left side ---------------------------------------------------- */
/* wchesher, 2026-10-27: "the window is not supposed to be enbedded in the content pane. it is supposed to be embedded
   down the left side of the page", and "Large". While the landing list is up (surfaces/contract.js), the Ops Deck's
   fore window (station/window.js stationPorthole) stands as the console's first column: as tall as the screen under
   the header and held there as the page scrolls. The content pane and the side column keep their widths; the page
   widens by the window, and the header with it. Where all three do not fit, the side column drops under the content
   pane and the window stays down the left; on a phone it becomes a band above the content. */
/* Thirty percent narrower (wchesher, 2026-10-30: "reduce the window width by 30% and reclaim that real estate"): 196 to
   322 px, about 220 px on a 1366 by 768 console instead of 314, and the content column beside it takes the rest. */
.console { --window-column: clamp(196px, 16.1vw, 322px); --window-top: calc(64px + var(--space-5)); }
.console-window { display: grid; grid-column: 1; grid-row: 1; position: sticky; top: var(--window-top);
  height: calc(100vh - var(--window-top) - var(--space-5)); min-height: 440px; }
.console-window[hidden] { display: none; }
.console-window > .porthole { min-height: 0; }
.console:has(> .console-window:not([hidden])) { max-width: calc(1320px + var(--window-column) + var(--space-5));
  grid-template-columns: var(--window-column) minmax(0, 1fr) 384px; }
body:has(.console-window:not([hidden])) .deck-header-inner { max-width: calc(1320px + clamp(196px, 16.1vw, 322px) + var(--space-5)); }
@media (max-width: 1240px) {
  .console:has(> .console-window:not([hidden])) { grid-template-columns: var(--window-column) minmax(0, 1fr); }
  .console-window { grid-row: 1 / span 2; }
  .console:has(> .console-window:not([hidden])) > :is(.console-main, .console-side) { grid-column: 2; }
  .console:has(> .console-window:not([hidden])) > .console-side { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
}
@media (max-width: 1040px) {
  .console { --window-column: clamp(168px, 21vw, 210px); }
}
@media (max-width: 760px) {
  .console:has(> .console-window:not([hidden])) { grid-template-columns: minmax(0, 1fr); }
  .console:has(> .console-window:not([hidden])) > :is(.console-main, .console-side) { grid-column: 1; }
  .console-window { grid-row: auto; position: relative; top: 0; height: 220px; min-height: 0; }
}

/* On Alpha the window stands on every Waypoint part (console.js paintAlphaWindow; Maestro, 2026-10-28: "the window on
   the left. embedded. all the time"), and the board was built for about 53rem (logic/hand_drive.css).
   HELP IS THE DOOR (console.js helpDoor; Design, 2026-10-28: "Help opens H.A.L., the case file and its Still open,
   captions, and the line again"). The side column is not on Alpha's page: the board takes the whole column beside the
   window at every width, and Help opens the side column as a panel over the board's right side, under the header. The
   captions never dock in it: they keep the foot of the window, where every heard line is written. */
.help-door, .help-close { display: none; }
body.is-alpha-console .help-door { display: inline-flex; }
body.is-alpha-console .console > .console-side,
body.is-alpha-console .console-side .caption-dock { display: none; }
@media (min-width: 761px) {
  body.is-alpha-console .console:has(> .console-window:not([hidden])) { grid-template-columns: var(--window-column) minmax(0, 1fr); }
  body.is-alpha-console .console-window { grid-row: 1; }
}
body.is-alpha-console .console:not(:has(> .console-window:not([hidden]))) { grid-template-columns: minmax(0, 1fr); }
/* On Alpha's console the captions play at the window's foot, over the picture's bottom edge, so a heard line never
   covers the board (console.js windowCaptions). A phone's window is a 220 px band: there they keep the screen's foot. */
.window-caption-dock { display: none; }
@media (min-width: 761px) {
  /* inside the glass's 1 px edge and 6 px frame (station/window.js .porthole-glass) */
  body.is-alpha-console .console-window > .window-caption-dock { display: block; position: absolute; inset: auto 7px 7px 7px; z-index: 1; padding: 0; }
  /* H.A.L.'s line in the window wraps, never cut ("Ten degrees in the common room. The": the Parts 4 to 7 pass) */
  body.is-alpha-console .console-window > .window-caption-dock .caption-text { white-space: normal; overflow-wrap: anywhere; overflow: visible;
    text-overflow: clip; max-height: none; }
  /* ...and it is written whole the moment it lands: in a column this narrow the word-by-word reveal left a line's last
     words as blank space under its first ("BREAK FOUND. LINK 11. 5", "The shadow won't": the fourth QA pass,
     2026-10-31), which read as a caption cut off mid-sentence. The bar's pacing (how long the line holds) is unchanged. */
  body.is-alpha-console .console-window > .window-caption-dock .caption-text .word.is-pending { opacity: 1; transform: none; }
  body.is-alpha-console .console-window > .window-caption-dock .caption-bar.is-docked { margin: 0; padding: 12px 14px 14px;
    background: color-mix(in srgb, var(--ground) 86%, transparent);
    -webkit-backdrop-filter: blur(var(--blur-glass)); backdrop-filter: blur(var(--blur-glass)); box-shadow: inset 0 1px 0 var(--hairline); }
}
body.is-alpha-console.is-help-open > .console-side { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start;
  position: fixed; z-index: 40; inset: calc(64px + var(--space-5)) max(16px, 2vw) var(--space-5) auto; margin: 0; align-self: stretch;
  width: min(26rem, calc(100vw - 32px)); max-height: none; overflow: auto; overscroll-behavior: contain;
  background: var(--surface); border: 1px solid var(--hairline); box-shadow: var(--shadow-deep); }
/* Each row its content's height. The open panel is a fixed-height grid that scrolls, and once H.A.L.'s feed overflows it,
   Chromium shrank the auto rows of the panels that clip (.ln-panel, overflow: hidden) to their padding, 48 px: the
   Moon's entry lost its words and button under the feed (measured 2026-10-30, the Moon behind Help). */
body.is-alpha-console.is-help-open > .console-side { grid-auto-rows: max-content; }
body.is-alpha-console.is-help-open .console-side:focus { outline: none; }
body.is-alpha-console.is-help-open .console-side > .rail-head { position: static; background: none; }
body.is-alpha-console.is-help-open .help-close { display: inline-flex; justify-self: end; margin: var(--space-3) var(--space-3) 0 0; }
/* The Moon behind Help (alpha/moon_door.js): an entry under Close, and the globe over the whole console once opened,
   under a thin bar that names it and leads back. Above the Help panel (40); the globe's own page fills the rest. */
.moon-door { display: grid; gap: var(--space-2); justify-items: start; }
.moon-door-note { margin: 0; color: var(--text-secondary); }
.moon-door-layer { position: fixed; inset: 0; z-index: 60; display: grid; grid-template-rows: auto minmax(0, 1fr); background: #000; }
.moon-door-bar { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3);
  padding: var(--space-2) max(16px, env(safe-area-inset-right, 0px)) var(--space-2) max(16px, env(safe-area-inset-left, 0px));
  background: var(--surface); box-shadow: inset 0 -1px 0 var(--hairline); }
.moon-door-room { position: relative; min-height: 0; }
.moon-door-room > .moon { position: absolute; inset: 0; min-height: 0; }

/* ---- the pinned rail ------------------------------------------------------------------------------ */
/* The Alpha game analysis (P3 and item 6, approved by wchesher 2026-10-28: "Go with your recommendations"). Deep in a
   long board the right column was empty, because the rail scrolled away with the page, and the caption bar floated over
   the board's own controls (the panel's connection rows, Ping's Send, at 1366 by 768). Wherever the side column stands
   beside the board as a rail, it is pinned under the header at the window's height and scrolls inside itself; H.A.L.
   and its ask box head it and stay put while the rest slides under them; and captions dock beneath the ask box, in the
   rail, so no caption is ever over a control (shell.js CaptionBar.place moves the bar here while the dock is drawn).
   Where the side column drops under the board (narrow screens, the window's middle widths, the broadcast), none of
   this applies and the caption bar keeps the foot of the window. */
.console { --rail-top: calc(64px + var(--space-2)); --rail-height: calc(100vh - var(--rail-top) - var(--space-5)); }  /* level with the move bar (.next-move) */
.rail-head { display: grid; min-width: 0; }
.caption-dock { display: none; }
@media (min-width: 1181px) and (max-width: 1240px) {
  body:not(.is-broadcast) .console:not(:has(> .console-window:not([hidden]))) > .console-side {
    position: sticky; top: var(--rail-top); max-height: var(--rail-height); overflow-y: auto; scrollbar-width: thin; }
}
@media (min-width: 1241px) {
  body:not(.is-broadcast) .console > .console-side {
    position: sticky; top: var(--rail-top); max-height: var(--rail-height); overflow-y: auto; scrollbar-width: thin; }
}
@media (min-width: 1181px) {
  body:not(.is-broadcast) .console-side > .rail-head { position: sticky; top: 0; z-index: 2; background: var(--surface); }
  body:not(.is-broadcast) .console-side > .rail-head .mc { max-height: min(calc(var(--rail-height) - 13rem), 36rem); min-height: 18rem; }
  body:not(.is-broadcast) .caption-dock { display: block; padding: 0 var(--space-5); }
}
/* Between 1181 and 1240 px the window takes a column and the side column drops under the board: no rail. */
@media (min-width: 1181px) and (max-width: 1240px) {
  body:has(.console-window:not([hidden])) .console-side > .rail-head { position: static; background: none; }
  body:has(.console-window:not([hidden])) .console-side > .rail-head .mc { max-height: min(72vh, 44rem); min-height: 20rem; }
  body:has(.console-window:not([hidden])) .caption-dock { display: none; }
}
.caption-bar.is-docked { position: relative; left: auto; bottom: auto; width: auto; transform: none; opacity: 1; display: none;
  margin: 0 0 var(--space-4); padding: var(--space-3) 0 0; background: none; box-shadow: inset 0 1px 0 var(--hairline);
  -webkit-backdrop-filter: none; backdrop-filter: none; pointer-events: auto; }
.caption-bar.is-docked.is-shown { display: grid; animation: caption-dock-in var(--flow-ui) var(--ease-machined); }
.caption-bar.is-docked .caption-text { font-size: 1rem; }
@keyframes caption-dock-in { from { opacity: 0; transform: translateY(4px); } }
.is-still .caption-bar.is-docked.is-shown { animation: none; }

/* ---- small screens -------------------------------------------------------------------------------- */
@media (max-width: 1180px) {
  .console { grid-template-columns: minmax(0, 1fr); }
  .console-side { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
}
@media (max-width: 1040px) {
  .stepper { display: none; }
  .stepper-compact { display: block; justify-self: center; }
}
@media (max-width: 880px) {
  .title-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); align-items: start; }
  .brand { gap: var(--space-4); }
  .brand-mark { width: 64px; height: 64px; }
  .brand-data { display: none; }
  .teacher-sign-in { grid-template-columns: minmax(0, 1fr); align-items: start; min-height: 0; }
  .engine-deck { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
}
@media (max-width: 640px) {
  .title-screen { padding-top: var(--space-5); }
  .brand-title { font-size: 4rem; }
  .brand-line { font-size: 1.0625rem; }
  .sign-in { padding: var(--space-4); }
  .sign-in .two { grid-template-columns: minmax(0, 1fr); }
  .deck-header-inner { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-3); min-height: 56px; }
  .wordmark-text { display: none; }
  .crew-badge { padding-left: var(--space-3); }
  .alpha-badge { padding-left: var(--space-3); }
  .alpha-badge-crew { display: none; }
  .alpha-badge-chair { display: none; }
  .alpha-badge-who { max-width: 14ch; }
  .assignment-head { padding: var(--space-4) var(--space-4) var(--space-2); }
  .assignment-body { grid-template-columns: minmax(0, 1fr); padding: var(--space-2) var(--space-4) var(--space-4); }
  .badge-card { width: 200px; aspect-ratio: auto; justify-self: center; }
  .assignment-rows { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .assignment-rows dd { margin-bottom: var(--space-3); }
  .console { padding-top: var(--space-5); gap: var(--space-5); }
  .console-side { grid-template-columns: minmax(0, 1fr); }
  .surface > .ln-panel { padding: var(--space-4) var(--space-4) var(--space-5); }
  .duties li { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .cards { grid-template-columns: minmax(0, 1fr); }
  .share { grid-template-columns: minmax(0, 1fr); }
  .share-code { font-size: 2rem; }
  .goal { grid-template-columns: 28px minmax(0, 1fr); }
  .launch-deck { grid-template-columns: minmax(0, 1fr); }
  .review-report { grid-template-columns: minmax(0, 1fr); }
  .review-report dd { margin-bottom: var(--space-2); }
  .debrief-counts li { grid-template-columns: minmax(0, 1fr); }
  .debrief-facts { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .debrief-facts dd { margin-bottom: var(--space-2); }
  .debrief-numbers th:nth-child(3), .debrief-numbers td:nth-child(3) { display: none; }
  .debrief-value { font-size: 1rem; }
  .guess-number { font-size: 4.5rem; }
  .goal-tools { grid-column: 2; }
  .cargo-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name action" "placard numbers"; row-gap: var(--space-1); }
  .cargo-row .cargo-name { grid-area: name; }
  .cargo-row .placard { grid-area: placard; }
  .cargo-row .cargo-numbers { grid-area: numbers; }
  .cargo-row .ln-btn { grid-area: action; }
  .cargo-head { display: none; }
  .plan-offer { grid-template-columns: minmax(0, 1fr); }
  .bay-deck { grid-template-columns: 30px repeat(4, minmax(0, 1fr)); gap: 8px; }
  .deck-label .deck-word { display: none; }
  .slot { min-height: 84px; padding: var(--space-2); }
  .slot-name { font-size: 0.6875rem; hyphens: auto; overflow-wrap: anywhere; }
  .bay-tank { text-align: left; letter-spacing: .12em; font-size: 0.625rem; }
  .bay-tank .placard-word { display: none; }
  .slot .placard-word { display: none; }
  .step { grid-template-columns: 40px minmax(0, 1fr); }
  .step > :last-child { grid-column: 2; justify-self: start; }
  .readouts .ln-readout-value { font-size: 1.375rem; }
  .line-statement { font-size: 1.5rem; }
  .hold { min-width: 0; width: 100%; }
  .caption-text { font-size: 1rem; }
  .stepper-compact.manifest-label, .print-button { display: none; }
  #stepper-compact { display: none; }
  /* A ledger becomes one labelled card per row on a phone: no sideways scroll, no squeezed columns */
  .ledger thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .ledger, .ledger tbody, .ledger tr, .ledger td { display: block; width: 100%; }
  .ledger tr { padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
  .ledger td { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: var(--space-3); padding: 2px 0; border-top: 0; }
  .ledger td::before { content: attr(data-label); font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); padding-top: 3px; }
  .ledger td.number { text-align: left; }
  .ledger td > * { grid-column: 2; }
  .deck-header-inner .header-tools { grid-column: 3; justify-self: end; }
  .header-tools { gap: 4px; }
  .header-tools .ln-btn { padding-inline: 10px; letter-spacing: .12em; }
}
/* A phone holds Manifest, Station and Sign off only set tighter, with no sideways scroll at 360. */
@media (max-width: 419px) {
  .deck-header-inner { gap: var(--space-2); }
  .header-tools { gap: 2px; }
  .header-tools .ln-btn { padding-inline: 7px; letter-spacing: .06em; }
}
@media (min-width: 641px) { .cargo-numbers { display: contents; } }

/* Reduced motion: no ambient motion anywhere. The hold fill still runs, because it is the information. */
.is-still *, .is-still *::before, .is-still *::after { scroll-behavior: auto !important; }
.is-still .digit-strip, .is-still .caption-text .word, .is-still .caption-seam, .is-still .caption-bar, .is-still .meter-fill { transition: none !important; }

/* ---- captions, as the student set them ---------------------------------------------------------- */
html[data-captions="large"] .caption-text { font-size: 1.5rem; line-height: 1.35; }
html[data-captions="large"] .caption-speaker, html[data-captions="large"] .caption-bar .cue { font-size: 0.875rem; }
html[data-captions="large"] .caption-bar:not(.is-docked) { width: min(860px, calc(100% - 32px)); }
/* Top: under the header, entering from above, so the bar never sits over a surface's own controls */
html[data-captions-at="top"] .caption-bar:not(.is-docked) { top: calc(64px + var(--space-3)); bottom: auto; transform: translate(-50%, calc(-100% - 96px)); }
html[data-captions-at="top"] .caption-bar.is-shown:not(.is-docked) { transform: translate(-50%, 0); }
/* Captions follow the ear (shell.js 01, Maestro 2026-10-27: "I want the captions to be gone"). Any caption marked
   data-heard is written only when nothing was heard: "no" shows; "pending" (its take asked for) and "yes" (it played)
   stay hidden, holding their place. The student's Always (Station drawer, data-captions-show) writes every one. */
html[data-captions-show="unheard"] [data-heard]:not([data-heard="no"]) { visibility: hidden; }
/* Docked in the rail (the pinned rail), a hidden caption takes no room: the rail does not open a gap for it. */
html[data-captions-show="unheard"] .caption-bar.is-docked[data-heard]:not([data-heard="no"]) { display: none; }
html[data-captions-at="top"] .console { padding-bottom: var(--space-6); }

/* ---- skip to the console, shown when it has focus ----------------------------------------------- */
.skip-link { position: fixed; left: max(16px, 2vw); top: 0; z-index: 60; transform: translateY(-120%); padding: var(--space-3) var(--space-4);
  background: var(--flare); color: var(--on-flare); font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase; text-decoration: none; }
.skip-link:focus { transform: none; }

/* ---- the station drawer --------------------------------------------------------------------------- */
/* Furniture, not flow: it enters from the right edge, glass over the console, which keeps running behind it. */
.station-button[aria-expanded="true"] { border-color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); color: var(--text); }
/* While the console is silent: a quiet mono word after a hairline, never a second control. */
.station-sound { padding-left: var(--space-2); border-left: 1px solid var(--hairline); font-family: var(--font-mono); font-size: 0.625rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase; color: var(--text-muted); }
.station-sound[hidden] { display: none; }
/* A phone has no room for the word (the header would push the page sideways): the button's name still says
   "sound off" to a screen reader, and a press still opens the drawer at Sound. */
@media (max-width: 419px) { .station-sound { display: none; } }
.drawer { position: fixed; inset: 0 0 0 auto; width: min(460px, 100vw); height: 100vh; height: 100dvh; max-width: 100vw; max-height: none; margin: 0; padding: 0;
  border: 0; border-left: 1px solid var(--hairline); color: var(--text); overflow: hidden;
  background: radial-gradient(90% 40% at 0% 0%, var(--key-light), transparent 60%), var(--surface);
  box-shadow: var(--shadow-deep); }
.drawer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.drawer::backdrop { background: var(--shade); }
:root:not(.is-still) .drawer[open] { animation: drawer-in var(--flow-ui) var(--ease-machined) both; }
:root:not(.is-still) .drawer[open]::backdrop { animation: drawer-scrim var(--flow-ui) var(--ease-machined) both; }
:root:not(.is-still) .drawer.is-leaving { animation: drawer-out 200ms var(--ease-machined) both; }
:root:not(.is-still) .drawer.is-leaving::backdrop { animation: drawer-scrim 200ms var(--ease-machined) reverse both; }
@keyframes drawer-in { from { transform: translateX(32px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes drawer-out { from { transform: none; opacity: 1; } to { transform: translateX(32px); opacity: 0; } }
@keyframes drawer-scrim { from { opacity: 0; } to { opacity: 1; } }

.drawer-head { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-4); align-items: start; padding: var(--space-5) var(--space-5) var(--space-4); }
/* the accent seam: the one lit line in the drawer, drawn under its title */
.drawer-head::after { content: ""; position: absolute; left: var(--space-5); right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, var(--accent-line), var(--hairline) 40%, transparent); }
.drawer-title { margin: var(--space-1) 0 var(--space-2); font-family: var(--font-display); font-size: 2rem; line-height: 1; letter-spacing: .1em; }
.drawer-running { font-size: 0.875rem; color: var(--text-secondary); max-width: 34ch; }
.drawer-close { margin-right: calc(var(--space-2) * -1); }
.drawer-body { overflow-y: auto; overscroll-behavior: contain; counter-reset: band; scrollbar-width: thin; scrollbar-color: var(--edge) transparent; }
/* a short fade where the bands pass under the seam and the footer, instead of a hard cut through a line of text */
.drawer-body { mask-image: linear-gradient(to bottom, transparent, #000 var(--space-4), #000 calc(100% - var(--space-4)), transparent); }
.drawer-band { display: grid; gap: var(--space-4); padding: var(--space-5); border-top: 1px solid var(--hairline); scroll-margin-top: 0; }
.drawer-band:first-child { border-top: 0; }
.drawer-band-title { display: flex; align-items: baseline; gap: var(--space-3); font-family: var(--font-display); font-size: 1.0625rem; letter-spacing: .16em; color: var(--text); }
.drawer-band-title::before { counter-increment: band; content: counter(band, decimal-leading-zero) / ""; font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500; letter-spacing: .08em; color: var(--text-muted); }
.drawer-label { font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: .2em; text-transform: uppercase; color: var(--text-secondary); padding: 0; }
.drawer-field { display: grid; gap: var(--space-2); }
.drawer-choice { border: 0; margin: 0; padding: 0; min-width: 0; }
.drawer-choice legend { margin-bottom: var(--space-2); }
.drawer-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4); }

/* The mixer: four faders on one bus each, a mixing desk in miniature. Square caps, a lit fill, mono values. */
.mixer { display: grid; gap: var(--space-1); transition: opacity var(--flow-ui); }
.mixer.is-off { opacity: .55; }
.level-row { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr) 2.5rem auto; align-items: center; gap: 0 var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--hairline); }
.level-row:first-child { border-top: 0; }
.level-carries { grid-column: 1 / -1; font-size: 0.8125rem; color: var(--text-muted); margin-top: -2px; }
.level-reply { grid-column: 1 / -1; }
.level-reply:empty { display: none; }
.level-value { font-family: var(--font-mono); font-size: 0.875rem; font-variant-numeric: tabular-nums; color: var(--text); text-align: right; white-space: pre; }
.level-test { min-height: 44px; padding: 0 var(--space-3); font-size: 0.75rem; }
.level { --fill: 50%; appearance: none; -webkit-appearance: none; width: 100%; height: 44px; margin: 0; background: transparent; cursor: pointer; }
.level::-webkit-slider-runnable-track { height: 2px; background: linear-gradient(90deg, var(--accent) var(--fill), var(--edge) var(--fill)); }
.level::-moz-range-track { height: 2px; background: var(--edge); }
.level::-moz-range-progress { height: 2px; background: var(--accent); }
.level::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 22px; margin-top: -10px; border-radius: 0; background: var(--text); border: 1px solid var(--ground); box-shadow: inset 0 -3px 0 var(--accent); }
.level::-moz-range-thumb { width: 12px; height: 22px; border-radius: 0; background: var(--text); border: 1px solid var(--ground); box-shadow: inset 0 -3px 0 var(--accent); }
.level:focus-visible { outline: 2px solid var(--flare); outline-offset: 2px; box-shadow: none; }
.mixer.is-off .level::-webkit-slider-runnable-track { background: linear-gradient(90deg, var(--text-muted) var(--fill), var(--edge) var(--fill)); }
.mixer.is-off .level::-moz-range-progress { background: var(--text-muted); }

/* The loop: what was said, newest first, each line where and when it was said */
.loop-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-3); padding-top: var(--space-2); }
.loop { margin: 0; padding: 0; list-style: none; display: grid; }
.loop-line { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr) auto; gap: 2px var(--space-3); align-items: baseline; padding: var(--space-3) 0; border-top: 1px solid var(--hairline); }
.loop-line:first-child { border-top-color: var(--accent-line); }
.loop-time { font-size: 0.75rem; color: var(--text-muted); }
.loop-who { grid-column: 2; }
.loop-text { grid-column: 2; font-size: 0.9375rem; line-height: 1.45; color: var(--text); }
.loop-play { grid-column: 3; grid-row: 1 / span 2; align-self: center; min-height: 44px; padding: 0 var(--space-3); font-size: 0.75rem; }

.drawer-screen { display: grid; gap: var(--space-2); padding: var(--space-4); background: var(--veil-1); border-left: 2px solid var(--accent-line); }
.drawer-screen-title { font-family: var(--font-display); font-size: 1.125rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--text); }
.drawer-screen-text { font-size: 0.9375rem; line-height: 1.5; color: var(--text-secondary); }
/* Crew Orientation and Crew Training, run again: one label over one pair */
.drawer-replays { display: grid; gap: var(--space-2); }
.glossary-details summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; }
.glossary { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-1); margin: var(--space-2) 0 0; }
.glossary dt { font-family: var(--font-display); font-size: 0.9375rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--text); padding-top: var(--space-3); border-top: 1px solid var(--hairline); }
.glossary dt:first-child { border-top: 0; padding-top: 0; }
.glossary dd { margin: 0; font-size: 0.875rem; line-height: 1.5; color: var(--text-secondary); }
.seat { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2) var(--space-5); margin: 0; }
.seat dt { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .2em; text-transform: uppercase; color: var(--text-muted); padding-top: 3px; }
.seat dd { margin: 0; font-size: 0.9375rem; color: var(--text); }
.seat dd.mono { letter-spacing: .16em; }
.leave-row { display: grid; gap: var(--space-3); justify-items: start; padding-top: var(--space-2); }
.drawer-foot { padding: var(--space-3) var(--space-5); border-top: 1px solid var(--hairline); min-height: 44px; display: flex; align-items: center; }
.drawer-foot .cue { color: var(--text-secondary); }
@media (max-width: 480px) {
  .drawer { border-left: 0; }
  .drawer-pair { grid-template-columns: minmax(0, 1fr); }
  .level-row { grid-template-columns: minmax(0, 1fr) 2.5rem auto; }
  .level-row > .drawer-label { grid-column: 1 / -1; padding-top: var(--space-2); }
}

@media print {
  .backdrop, .corner-counter, .deck-header, .caption-bar, .station-footer .footer-controls, .sign-form, .hold-frame, .drawer, .skip-link { display: none !important; }
  body { background: #fff; color: #000; }
  [data-quiet] { text-shadow: none; }
}

/* the door's sign-in panel waits for the station's answer (console.js showCard sets data-arrived): a signed-in student's
   reload goes from the backdrop straight to the console, never through a door asking them to sign in */
html:not([data-arrived]) #join-screen .sign-in { visibility: hidden; }

/* the console's first paint, unseen (console.js enter): laid out and painted behind the door, which stays up until the
   console has its title and its board, then the two swap in one frame */
#crew-screen[data-painting] { visibility: hidden; position: fixed; inset: 0; overflow: hidden; }

/* the curtain (console.js seatMe): dark from the moment the console is unhidden until the fly-in is on screen and cuts to
   it, so the console never shows, goes, and comes back. Under the fly-in, over everything else; a press lifts it. */
html[data-seating]::after { content: ""; position: fixed; inset: 0; z-index: 89; background: #000000; }

/* ---- the fly-in (station/fly-in.js): Waypoint from far off, a push in on the crew's deck, a cut, then the seat. It takes
   no pointer, so the console under it answers a press at once; its Skip does. */
.fly-in { position: fixed; inset: 0; z-index: 90; background: #000000; pointer-events: none; opacity: 0;
  transition: opacity 600ms var(--ease-machined, ease); }
.fly-in.is-playing { opacity: 1; }
.fly-in.is-cut { opacity: 0; transition-duration: 420ms; }
.fly-in .station-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.fly-in-skip { position: absolute; right: var(--space-5, 24px); bottom: var(--space-5, 24px); pointer-events: auto; }
/* the seat: the console comes to rest in front of you, a breath closer and soft, then still */
@keyframes fly-in-seat { from { transform: scale(1.035); filter: blur(5px); opacity: .4; } to { transform: none; filter: none; opacity: 1; } }
.fly-in-seat { animation: fly-in-seat 900ms cubic-bezier(.2, .7, .2, 1) both; transform-origin: 50% 40%; }
@media (prefers-reduced-motion: reduce) { .fly-in-seat { animation: none; } }
/* Mission Control between steps (alpha/visit.js): the room over the page, its Back button always in reach */
.alpha-visit { position: fixed; inset: 0; z-index: 80; display: flex; flex-direction: column; background: var(--bg, #000000);
  overflow-y: auto; overscroll-behavior: contain; }
.alpha-visit-bar { position: sticky; top: 0; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--glass); }
.alpha-visit-room { flex: 1 0 auto; min-width: 0; padding: 0 var(--space-4) var(--space-5); }
.alpha-visit .mission-clock, .alpha-visit .mission-phase { display: none; }
html.has-alpha-visit, html.has-alpha-visit body { overflow: hidden; }
.alpha-seam .alpha-visit-open, .holding-visit { flex: none; }

/* Mission Bravo on Luna's ice trade (luna/ice_trade.js): the three ways to mine it, side by side, then the model's runs */
.luna-ice-trade .ice-methods { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-3); margin: var(--space-3) 0; }
.luna-ice-trade .ice-method { display: block; cursor: pointer; padding: var(--space-3); border: 1px solid var(--hairline); }
.luna-ice-trade .ice-method.is-picked { border-color: var(--accent, currentColor); }
.luna-ice-trade .ice-method input { margin-right: 6px; }
.luna-ice-trade .ice-method h4 { display: inline; margin: 0; }
.luna-ice-trade .ice-results td.short { color: var(--bad, #ff6b8a); }
.luna-ice-trade .ice-results td.pass { color: var(--good, #3bd6a6); }
.luna-ice-trade textarea { width: 100%; }

/* THE PLACE AND THE BOARD (alpha/place.js; the Mission Alpha mock, design/alpha-mock/game/mission.html and explore.css;
   wchesher, 2026-11-04: "I dont want to see this console screen any more", "WE DESIGNED NEW SCREENS"). body[data-place]
   is set on Alpha only:
     explore  the step's place, full-bleed under the header: the picture, the hotspots, the box at the top left, the
              tools at the top right, the line at the foot. Nothing of the console shows; Help still opens its column.
     game     the step's board, whole-page under its name and Back, on the plain ground (the mock's board).
     console  only under a seam, a recap or a card: the console as it was, with no board under it. */
body[data-place="console"] #surface,
body[data-place="console"] #next-move,
body[data-place="console"] #direction,
body[data-place="console"] #alpha-heads-up,
body[data-place="console"] #alpha-stretch-lead { display: none !important; }
body[data-place="explore"] .console > :not(.alpha-explore):not(.console-side) { display: none !important; }
body[data-place="explore"] .backdrop,
body[data-place="explore"] #crew-screen > .station-footer { display: none !important; }
body[data-place="game"] #console-window,
body[data-place="game"] #console-side,
body[data-place="game"] .phase-intro,
body[data-place="game"] #alpha-recap,
body[data-place="game"] #alpha-seam,
body[data-place="game"] #dealt,
body[data-place="game"] .backdrop { display: none !important; }
body.is-alpha-console.is-help-open[data-place="game"] > .console-side,
body.is-alpha-console.is-help-open[data-place="explore"] > .console-side { display: grid !important; }
body[data-place="game"] [data-game-away] { display: none !important; }
body[data-place="game"] .console,
body[data-place="game"] .console:has(> .console-window:not([hidden])) { grid-template-columns: minmax(0, 1fr); max-width: 1320px; }
body[data-place="game"] .console-main { grid-column: 1; }
.game-head[hidden] { display: none; }

/* the board's head: its name over the day and place, Back at the right (the mock's board) */
.game-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "where back" "title back"; align-items: center;
  gap: var(--space-1) var(--space-4); padding-bottom: var(--space-3); border-bottom: 1px solid var(--hairline); }
.game-head-where { grid-area: where; margin: 0; }
.game-head-title { grid-area: title; margin: 0; font-family: var(--font-display, "Barlow Condensed", system-ui, sans-serif); font-size: clamp(26px, 2.6vw, 36px); }
.game-back { grid-area: back; display: inline-flex; align-items: center; gap: var(--space-2); }
.game-back[hidden] { display: none; }
.game-back-lamp { width: 10px; height: 10px; border-radius: 50%; border: 1px solid currentColor; }
.game-back-lamp[data-lit="true"] { background: var(--accent, #ff7a2e); border-color: var(--accent, #ff7a2e); box-shadow: 0 0 8px var(--accent-glow, #ff7a2e73); }
.game-back-count { font-size: 0.8125rem; }
@media (max-width: 640px) {
  .game-head { grid-template-columns: minmax(0, 1fr); grid-template-areas: "where" "title" "back"; justify-items: start; }
}

/* the place (the mock's explore shell) */
.alpha-explore { position: fixed; inset: 0; z-index: 18; overflow: hidden; background: var(--ground); --ax-pad: clamp(16px, 5vw, 64px); }
.alpha-explore[hidden] { display: none; }
.ax-stage { position: absolute; left: 50%; top: 50%; width: max(100%, calc(100dvh * 16 / 9)); aspect-ratio: 16 / 9; transform: translate(-50%, -50%); }
.ax-picture { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; filter: brightness(0.5) saturate(0.85); }
.ax-shade { position: absolute; inset: 0; background: linear-gradient(to top, #0a0a0cf5 0%, #0a0a0c00 45%), linear-gradient(to bottom, #0a0a0cd6 0%, #0a0a0c00 30%); }
.ax-spots { position: absolute; inset: 0; z-index: 2; }
.ax-spot { position: absolute; box-sizing: border-box; padding: 6px; border: 1px dashed var(--accent-line, #ff7a2ea6); border-radius: 2px;
  background: var(--accent-wash, #ff7a2e14); color: var(--text); cursor: pointer; text-align: left; display: flex; align-items: flex-start;
  transition: border-color 160ms, box-shadow 200ms, background 200ms; }
.ax-spot span { font-family: var(--font-mono); font-size: clamp(11px, 1vw, 14px); background: #0a0a0cd6; padding: 3px 7px; border-radius: 2px; }
.ax-spot em { font-style: normal; color: var(--accent); }
.ax-spot:hover, .ax-spot:focus-visible { border-style: solid; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-line), 0 0 18px 2px var(--accent-glow); outline: none; }
.ax-spot[data-state="done"], .ax-spot[data-state="later"], .ax-spot[data-state="look"], .ax-spot[data-state="waiting"] { border-color: #bdbdc355; background: transparent; }
.ax-spot[data-state="done"] span, .ax-spot[data-state="later"] span, .ax-spot[data-state="waiting"] span { color: var(--text-muted); }
.ax-hud { position: absolute; inset: 0; z-index: 3; pointer-events: none; display: flex; flex-direction: column; box-sizing: border-box; gap: 12px;
  padding: calc(64px + clamp(12px, 3vh, 28px)) max(var(--ax-pad), env(safe-area-inset-right, 0px)) clamp(20px, 6vh, 48px) max(var(--ax-pad), env(safe-area-inset-left, 0px)); }
.ax-hud > * { pointer-events: auto; }
.ax-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; pointer-events: none; }
.ax-top > * { pointer-events: auto; }
.ax-where { background: #0a0a0cd6; border: 1px solid var(--hairline); padding: 12px 16px; border-radius: 2px; max-width: min(420px, 100%); }
.ax-day { margin: 0; font-family: var(--font-mono); font-size: clamp(13px, 1.3vw, 18px); color: var(--accent-soft-text, #ffc38a); }
.ax-name { margin: 2px 0 8px; font-family: var(--font-display, "Barlow Condensed", system-ui, sans-serif); font-weight: 600; font-size: clamp(30px, 3.6vw, 54px); line-height: 1; }
.ax-tasks { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; max-width: 36ch; }
.ax-tasks li { font-size: clamp(14px, 1.2vw, 17px); color: var(--text-secondary); padding-left: 16px; position: relative; }
.ax-tasks li::before { content: ""; position: absolute; left: 0; top: 0.55em; width: 7px; height: 7px; border: 1px solid var(--accent); }
.ax-tasks li[data-state="done"] { color: var(--text-muted); text-decoration: line-through; }
.ax-tasks li[data-state="done"]::before { background: var(--accent); }
.ax-tools { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.ax-tool { min-height: 40px; padding: 0 16px; border: 1px solid var(--edge, #6e6e76); border-radius: 2px; background: #121215e0; color: var(--text);
  font-family: var(--font-mono); font-size: clamp(12px, 1.1vw, 15px); cursor: pointer; }
.ax-tool:hover { border-color: var(--accent); }
.ax-list { display: none; flex-wrap: wrap; gap: 8px; }
.ax-bottom { margin-top: auto; display: flex; align-items: flex-end; gap: 20px; }
.ax-talk { flex: 1 1 auto; min-width: 0; display: grid; gap: 10px; max-width: 940px; }
.ax-who { margin: 0; font-family: var(--font-display, "Barlow Condensed", system-ui, sans-serif); font-weight: 600; font-size: clamp(16px, 1.72vw, 26px); color: var(--accent); }
.ax-who[hidden] { display: none; }
.ax-line { margin: 0; font-size: clamp(18px, 2.1vw, 34px); line-height: 1.28; font-weight: 500; color: var(--text-secondary); text-wrap: pretty; }
.ax-acts { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.ax-acts:empty { display: none; }
.ax-caption-dock { display: block !important; padding: 0 !important; }
.ax-people { display: flex; flex-direction: column; gap: 8px; flex-shrink: 0; }
.ax-person { min-height: 40px; padding: 6px 14px; border: 1px solid var(--edge, #6e6e76); border-radius: 2px; background: #121215e0; color: var(--text);
  font-weight: 600; font-size: clamp(14px, 1.2vw, 18px); cursor: pointer; }
.ax-person:hover, .ax-person:focus-visible { border-color: var(--accent); outline: none; }
.ax-map { position: absolute; z-index: 6; top: 64px; right: 0; bottom: 0; width: min(420px, 100%); box-sizing: border-box; background: #0f0f12f5;
  border-left: 1px solid var(--hairline); padding: 24px; display: grid; align-content: start; gap: 12px; overflow-y: auto; }
.ax-map[hidden] { display: none; }
.ax-map-title { margin: 0; font-family: var(--font-display, "Barlow Condensed", system-ui, sans-serif); font-size: 32px; font-weight: 600; }
.ax-map-place { display: flex; align-items: center; gap: 14px; padding: 6px; border: 1px solid var(--hairline); border-radius: 2px; background: var(--surface);
  color: var(--text); font-size: 20px; font-weight: 600; cursor: pointer; text-align: left; }
.ax-map-place img { width: 112px; aspect-ratio: 16 / 9; object-fit: cover; }
.ax-map-place.is-here { border-color: var(--accent); }
@media (max-width: 760px), (max-aspect-ratio: 1/1) {
  .ax-spots { display: none; }
  .ax-list { display: flex; }
  .ax-bottom { flex-direction: column-reverse; align-items: stretch; }
  .ax-people { flex-direction: row; flex-wrap: wrap; }
  .ax-picture { filter: brightness(0.38); }
}

/* The crewmates' readings, pinned on the bar to the step's end (alpha/directions.js readReadings; crewmate.js READINGS). */
.next-move-pinned { display: grid; gap: var(--space-1); margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--hairline); }
.next-move-pin { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2); font-size: 0.875rem; line-height: 1.4; color: var(--text); }
.next-move-pin-who { font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: .12em; text-transform: uppercase; color: var(--text-secondary); padding-top: 2px; }

/* THE CASE'S PLACES (detective/detective.js; the Mission Alpha mock's explore screens, design/alpha-mock/game/explore.html
   and explore.css; wchesher, 2026-11-04: "I dont want to see this console screen any more", "WE DESIGNED NEW SCREENS",
   "WHERE ARE THEY"). Parts 5 to 7's rooms are the place of Parts 1 to 4 (THE PLACE AND THE BOARD above, whose ax-
   classes the scene wears): the place's still full-bleed under the header in a 16:9 stage that covers the window, its
   hotspots dashed boxes with their labels at their top left, the box with the part, the place and its tasks at the top
   left, Map / Journal / Phone / Wait at the top right, the line at the foot, and "Talk to" chips with faces. A board of
   the scene (the case board, the seeds) is the mock's board: its name and Back over the plain ground. The console's
   column gives the scene the whole window, and nothing of the console shows under it. */
body[data-place="game"]:has(#surface .dt-scene) .console { max-width: none !important; padding: 0 !important; }
body[data-place="game"]:has(#surface .dt-scene) .console-main > :not(#surface),
body[data-place="game"]:has(#surface .dt-scene) #crew-screen > .station-footer { display: none !important; }
html:has(body[data-place="game"] #surface .dt-scene) { overflow: hidden; }
/* the surface's arrival (.enter) leaves a transform behind, which would make the scene's window that wrapper's box */
:root #surface .enter:has(> .dt-scene) { animation: none; transform: none; }
.dt.dt-scene { position: fixed; inset: 0; z-index: 18; overflow: hidden; background: var(--ground); color: var(--text); font-family: inherit;
  --ax-pad: clamp(16px, 5vw, 64px); }
.dt-scene .ax-hud { gap: 16px; }

/* the picture: the place's frame fills the 16:9 stage, so each hotspot's box (percent of the still) lands where it did */
.dt-scene .ax-stage > .al-place { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; background: var(--ground); }
.dt-scene .al-place::after { display: none; }
.dt-scene .al-place-still { filter: brightness(0.5) saturate(0.85); }
.dt-scene .ax-stage > .ax-shade { z-index: 2; pointer-events: none; }
.dt-scene .al-place .al-hotspot { z-index: 3; box-sizing: border-box; min-width: 0; min-height: 0; padding: 6px; display: flex; align-items: flex-start;
  border: 1px dashed var(--accent-line, #ff7a2ea6); border-radius: 2px; background: var(--accent-wash, #ff7a2e14); color: var(--text); text-align: left;
  transition: border-color 160ms, box-shadow 200ms, background 200ms; }
.dt-scene .al-place .al-hotspot::before { display: none; }
.dt-scene .al-place .al-hotspot .al-hotspot-label { position: static; transform: none; opacity: 1; white-space: normal; max-width: 100%;
  font-family: var(--font-mono); font-size: clamp(11px, 1vw, 14px); letter-spacing: normal; text-transform: none; line-height: 1.35;
  background: #0a0a0cd6; color: var(--text); padding: 3px 7px; border-radius: 2px; box-shadow: none; pointer-events: none; }
.dt-scene .al-place .al-hotspot .al-hotspot-label em { font-style: normal; color: var(--accent); }
.dt-scene .al-place .al-hotspot.is-seen .al-hotspot-label::after { content: none; }
.dt-scene .al-place .al-hotspot.is-seen:not(:has(em)) { border-color: #bdbdc355; background: transparent; }
.dt-scene .al-place .al-hotspot.is-seen:not(:has(em)) .al-hotspot-label { color: var(--text-secondary); }
.dt-scene .al-place .al-hotspot:is(:hover, :focus-visible), .dt-scene .al-place .al-hotspot.is-chosen { border-style: solid; border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-line), 0 0 18px 2px var(--accent-glow); outline: none; }
.dt-scene .al-place .al-hotspot.dt-keepsake { border-color: transparent; background: transparent; }
.dt-scene .al-place .al-hotspot.dt-keepsake:not(:hover):not(:focus-visible) .al-hotspot-label { opacity: 0; }
.dt-scene.is-talking .al-place .al-hotspot { visibility: hidden; }
.dt-scene .al-place[data-closeup] .al-hotspot { visibility: hidden; }
.dt-scene .dt-closeup { z-index: 4; }
.dt-scene .dt-closeup .al-place-still { filter: none; }

/* the box at the top left and the tools at the top right */
.dt-left { display: grid; gap: 12px; align-content: start; max-width: min(420px, 100%); }
.dt-where { display: grid; gap: 0; }
.dt-where-more, .dt-where-count, .dt-where .dt-keepsakes .al-eyebrow { margin: 8px 0 0; font-family: var(--font-mono); font-size: 12px; letter-spacing: normal;
  text-transform: none; color: var(--text-muted); }
.dt-where-count[data-state="on"] { color: var(--accent-soft-text, #ffc38a); }
.dt-where .dt-keepsakes-done { margin: 4px 0 0; font-family: inherit; font-size: 14px; color: var(--text-secondary); }
.dt-panels { max-height: 38vh; overflow-y: auto; background: #0a0a0cd6; border: 1px solid var(--hairline); border-radius: 2px; padding: 12px 16px; }
.dt-tools .dt-tool-count { font-style: normal; color: var(--accent); }
.dt-scene .ax-tool[aria-expanded="true"] { border-color: var(--accent); }
.dt-scene .ax-tool:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }
/* a place the move means sits behind the shut Map: the Map tool carries its lamp */
.dt-scene:has(.dt-map:not(.is-open) [data-your-move]) [data-key="dt:map"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-line), 0 0 14px 1px var(--accent-glow); }

/* the foot: the line (what the place is, or what the chosen hotspot shows, and what can be done there), then the people */
.dt-scene .ax-bottom { pointer-events: none; }
.dt-scene .ax-bottom > * { pointer-events: auto; }
.dt-scene .dt-say { display: grid; gap: 12px; min-width: 0; }
.dt-scene .dt-reply:empty { display: none; }
.dt-scene .dt-reply { margin: 0; font-size: 13px; }
.dt-scene .dt-reading { display: grid; gap: 10px; padding: 0; background: none; border: 0; box-shadow: none; }
.dt-scene .dt-reading > .al-eyebrow:first-child { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(16px, 1.72vw, 26px);
  letter-spacing: normal; text-transform: none; color: var(--accent); }
.dt-scene .dt-reading:not([aria-label]) > .al-eyebrow:first-child { display: none; }   /* the mock's foot is the place's words alone */
.dt-scene .dt-reading > .al-line { margin: 0; font-family: inherit; font-size: clamp(18px, 2.1vw, 34px); line-height: 1.28; font-weight: 500;
  color: var(--text-secondary); text-wrap: pretty; text-shadow: 0 1px 12px #000000; }
.dt-scene .dt-reading > .al-cluster, .dt-scene .ax-acts { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.dt-scene .ax-bottom .al-btn { min-height: 40px; padding: 0 16px; border: 1px solid var(--edge); border-radius: 2px; background: #121215e0; color: var(--text);
  font-family: var(--font-mono); font-size: clamp(12px, 1.1vw, 15px); letter-spacing: normal; text-transform: none; cursor: pointer; }
.dt-scene .ax-bottom .al-btn:hover { border-color: var(--accent); }
.dt-scene .ax-bottom .al-btn-lamp { min-height: 56px; padding: 0 30px; background: var(--accent); color: var(--on-accent);
  border-color: var(--accent); box-shadow: var(--glow-accent); font-family: inherit; font-size: 20px; font-weight: 600; }
.dt-scene .ax-bottom .al-btn:disabled { color: var(--text-muted); border-color: var(--hairline); background: #121215e0; box-shadow: none; cursor: not-allowed; }
.dt-scene .ax-bottom .al-eyebrow { font-family: var(--font-mono); font-size: 12px; letter-spacing: normal; text-transform: none; color: var(--text-muted); }
.dt-scene .dt-lock-body, .dt-scene .dt-lid { background: #121215e0; }
.dt-scene .dt-town { padding: 12px 16px; background: #0a0a0cd6; border: 1px solid var(--hairline); border-radius: 2px; box-shadow: none; }
/* the lines a move plays, in the foot: who, the line, Next (the mock's line and Next); the place's own line waits */
.dt-scene .ax-talk > .dt-caption, .dt-scene .al-talk-body > .dt-caption { display: grid; gap: 10px; padding: 0; background: none; box-shadow: none; }
.dt-scene .dt-caption[hidden] { display: none; }
.dt-scene .dt-caption-who { font-family: var(--font-display); font-weight: 600; font-size: clamp(16px, 1.72vw, 26px); letter-spacing: normal; text-transform: none; color: var(--accent); }
.dt-scene .dt-caption-words { margin: 0; font-family: inherit; font-size: clamp(18px, 2.1vw, 34px); line-height: 1.28; font-weight: 500; color: var(--text); text-wrap: pretty;
  text-shadow: 0 1px 12px #000000; }
.dt-scene .dt-caption.is-machine .dt-caption-words { font-family: var(--font-mono); font-size: clamp(15px, 1.6vw, 24px); }
.dt-scene .dt-caption-more { justify-content: flex-start; gap: 12px; }
.dt-scene .dt-caption-more .al-eyebrow { display: none; }   /* Next says it (the band still moves on with Space) */
.dt-caption-next { display: none; }
.dt-scene .dt-caption-next { display: inline-flex; align-items: center; min-height: 56px; padding: 0 28px; font-family: inherit; font-size: 20px; font-weight: 600; }
.dt-scene .ax-talk:has(> .dt-caption:not([hidden])) .dt-reading > :is(.al-eyebrow:first-child, .al-line) { display: none; }
/* "Talk to" with the face (the mock's chips) */
.dt-scene .al-place-exits.ax-people { position: static; padding: 0; background: none; flex-direction: row; flex-wrap: wrap-reverse; justify-content: flex-end;
  align-items: flex-end; max-width: min(46%, 580px); }
.dt-scene .dt-person { display: inline-flex; align-items: center; gap: 12px; min-height: 64px; padding: 6px 16px 6px 6px; text-align: left; }
.dt-scene .dt-person-face { width: 52px; height: 52px; flex: none; object-fit: cover; object-position: 50% 22%; border-radius: 2px; background: var(--surface);
  display: grid; place-items: center; font-family: var(--font-display); font-size: 24px; color: var(--text-secondary); }
.dt-scene .dt-person[data-unmet] { border-color: var(--accent-line); }

/* talking: the face, the name and role, the line, what to ask and Leave, over the place (the mock's conversation) */
.dt-scene .dt-talk-foot { max-width: 1100px; }
.dt.dt-scene .al-talk { grid-template-columns: clamp(80px, 8.75vw, 112px) minmax(0, 1fr); gap: clamp(16px, 2vw, 28px); align-items: start; }
.dt-scene .al-talk > .al-portrait { max-width: none; aspect-ratio: 1; border: 1px solid var(--hairline); border-radius: 2px;
  background: var(--surface) var(--dt-face, none) 50% 22% / cover no-repeat; }
.dt-scene .al-portrait.dt-has-face > .dt-portrait-plate { display: none; }
.dt-scene .al-talk-body { gap: 12px; }
.dt-scene .al-speaker { gap: 4px 14px; }
.dt-scene .al-speaker-name { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: clamp(18px, 1.72vw, 26px); color: var(--accent);
  text-transform: none; letter-spacing: normal; }
.dt-scene .dt-caption.dt-is-talker .dt-caption-who { display: none; }
/* while a line plays, the conversation is the line and Next (the mock's); what to ask comes back after it */
.dt-scene .al-talk-body:has(> .dt-caption:not([hidden])) > :not(.al-speaker, .dt-caption) { display: none; }
.dt-scene .al-speaker-role { font-family: inherit; font-size: clamp(13px, 1.1vw, 16px); letter-spacing: normal; text-transform: none; color: var(--text-muted); }
.dt-scene .al-talk .al-topics:not(.dt-picks) { display: flex; flex-wrap: wrap; gap: 12px; }
.dt-scene .al-talk .al-topics:not(.dt-picks) .al-topic { display: inline-flex; align-items: center; gap: 10px; width: auto; min-height: 56px; padding: 0 22px;
  border: 1px solid var(--edge); border-radius: 2px; background: #121215e0; color: var(--text); font-family: inherit; font-size: clamp(16px, 1.4vw, 20px); font-weight: 600; }
.dt-scene .al-talk .al-topics:not(.dt-picks) .al-topic::before { font-size: 12px; color: var(--text-muted); }
.dt-scene .al-talk .al-topic:hover, .dt-scene .al-talk .al-topic:focus-visible { border-color: var(--accent); }
.dt-scene .al-talk .al-topic.is-spent { color: var(--text-muted); }
.dt-scene .al-talk .al-topic-show { border-style: dashed; }
.dt-scene .al-talk-body > .al-cluster .al-btn { min-height: 56px; padding: 0 28px; font-family: inherit; font-size: 20px; font-weight: 600; }
.dt-scene .dt-show { max-height: 40vh; overflow-y: auto; padding: 16px; background: #0f0f12f5; border: 1px solid var(--hairline); border-radius: 2px; box-shadow: none; }
.dt-scene .dt-show .dt-picks { max-height: none; }

/* the sheets: Map (the mock's "The town"), and the journal and phone, over the scene's right under the header */
.dt-scene .dt-sheet { position: fixed; z-index: 6; top: 64px; right: 0; bottom: 0; left: auto; width: min(480px, 100%); box-sizing: border-box; margin: 0;
  background: #0f0f12f5; border-left: 1px solid var(--hairline); border-top: 0; padding: 24px; display: grid; align-content: start; gap: 14px; overflow-y: auto; }
.dt-scene .dt-map:not(.is-open) { display: none; }
.dt-sheet-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.dt-sheet-title { margin: 0; font-family: var(--font-display); font-size: 32px; font-weight: 600; color: var(--text); }
.dt-scene .dt-side .al-journal-list { max-height: none; }
.dt-scene .dt-strip { display: grid; gap: 12px; }
.dt-scene .dt-strip .ax-map-place { width: 100%; }
.dt-map-still { width: 112px; aspect-ratio: 16 / 9; flex: none; display: block; object-fit: cover; }
.dt-plate-thumb { background: radial-gradient(70% 60% at 70% 10%, #2c2c31, transparent 70%), var(--ground); }
.dt-scene .ax-map-place .dt-new { margin-left: auto; font-size: 11px; }
.dt-scene .ax-map-place[data-unmet] { border-color: var(--accent-line); }
.dt-scene .ax-map-place:hover, .dt-scene .ax-map-place:focus-visible { border-color: var(--accent); outline: none; }

/* a board of the scene: its name over the plain ground, Back with the tools, the board under them */
.dt-scene.is-board .ax-hud { pointer-events: auto; }
.dt-board { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: grid; align-content: start; gap: 16px; width: 100%; max-width: 1180px; padding-bottom: 8px; }

@media (max-width: 760px), (max-aspect-ratio: 1/1) {
  /* the mock's narrow screen: the place's box and tools, its hotspots as a list of buttons, the line and the people,
     one column that scrolls, over the still */
  .dt.dt-scene { overflow-x: hidden; overflow-y: auto; display: flex; flex-direction: column; }
  .dt-scene .ax-hud { display: contents; }
  .dt-scene .ax-top { order: 1; position: relative; z-index: 1; padding: calc(64px + 12px) 16px 0; }
  .dt-scene .ax-stage { order: 2; position: static; transform: none; width: auto; aspect-ratio: auto; padding: 16px; }
  .dt-scene .ax-stage > .ax-shade, .dt-scene .al-place::before { display: none; }
  .dt-scene .ax-stage > .al-place { position: static; inset: auto; width: auto; height: auto; display: flex; flex-wrap: wrap; gap: 8px; overflow: visible;
    isolation: auto; background: none; container-type: normal; }
  .dt-scene .al-place > :is(.dt-plate, .dt-picture, .al-place-still) { position: fixed; inset: 0; z-index: 0; }
  .dt-scene .al-place-still { filter: brightness(0.38); }
  .dt-scene .al-place .al-hotspot { position: relative; z-index: 1; left: auto; top: auto; width: auto; height: auto; min-height: 44px; padding: 0 14px;
    align-items: center; border-style: solid; border-color: var(--edge); background: #121215e0; }
  .dt-scene .al-place .al-hotspot .al-hotspot-label { background: none; padding: 0; font-size: 14px; }
  .dt-scene .al-place .al-hotspot.dt-keepsake { border-color: transparent; background: transparent; min-width: 44px; }
  .dt-scene .al-place[data-closeup] .al-hotspot, .dt-scene.is-talking .al-place .al-hotspot { display: none; }
  .dt-scene .dt-closeup { position: relative; inset: auto; z-index: 1; flex: 1 0 100%; aspect-ratio: 16 / 9; }
  .dt-scene .dt-closeup .dt-picture, .dt-scene .dt-closeup .al-place-still { position: absolute; }
  .dt-scene .ax-bottom { order: 3; position: relative; z-index: 1; margin-top: auto; padding: 0 16px 24px; }
  .dt-scene .dt-board { order: 2; position: relative; z-index: 1; overflow: visible; padding: 16px; box-sizing: border-box; }
  .dt-left, .dt-scene .ax-where { max-width: 100%; }
  .dt-scene .ax-tools { justify-content: flex-start; }
  .dt.dt-scene .al-talk { grid-template-columns: 72px minmax(0, 1fr); }
  .dt.dt-scene .al-talk > .al-portrait { max-width: none; }
  .dt-scene > .ax-hud > .ax-caption-dock { order: 4; }
  .dt-scene .dt-sheet { width: 100%; border-left: 0; }
  .dt-scene .dt-person { min-height: 52px; }
  .dt-scene .dt-person-face { width: 40px; height: 40px; }
}

/* THE ROOM AND THE DESK (the audit against the Nancy Drew benchmark, 2026-11-05). The place's box, its tools, the lock
   and the line at its foot stood over hotspots: the suit log and Rack 3 under the box, Ruth's photo half under the box
   and the lock, the greenhouse airlock's label under the tools, the line over "Two suits". On a PC window the place is
   now the room and a desk beside it, as the old adventures framed their scene and its interface: the picture whole, at
   16:9, filling the window left of the desk, and the desk (the place's name and its jobs, which fold away, the tools,
   the line and what can be done, the people) a column at the right that never lies over the picture, so no hotspot box
   is under a panel at any window size (test_alpha_room_and_desk.py measures every place at 1366 by 768 and 1920 by
   1080). The sheets (Map, Journal, Phone) open over the picture beside the desk, so the tools that opened them are
   still there to shut them; while someone is talked to, their portrait stands in the room, large, the hotspots put
   away. With the words off the picture it no longer needs darkening for them: a day still is drawn at 0.85, a night
   still lifted (THE NIGHT LIFT below). Narrow windows keep the list layout above. */
@media (min-width: 761px) and (min-aspect-ratio: 1001/1000) {
  html:has(body[data-place="explore"]) { overflow: hidden; }
  .alpha-explore, .dt.dt-scene {
    --ax-head: 64px;
    --ax-col: clamp(360px, 26vw, 500px);
    --ax-w: min(calc(100vw - var(--ax-col)), calc((100dvh - var(--ax-head)) * 16 / 9));
    --ax-h: calc(var(--ax-w) * 9 / 16);
    --ax-top: calc(var(--ax-head) + (100dvh - var(--ax-head) - var(--ax-h)) / 2);
  }
  .alpha-explore > .ax-stage, .dt-scene:not(.is-board) > .ax-stage { left: 0; top: var(--ax-top); width: var(--ax-w); height: var(--ax-h); transform: none; }
  .alpha-explore .ax-shade, .dt-scene .ax-stage > .ax-shade { display: none; }
  .alpha-explore .ax-picture, .dt-scene .al-place-still { filter: brightness(0.85) saturate(0.9); }
  .alpha-explore > .ax-hud, .dt-scene:not(.is-board) > .ax-hud { inset: var(--ax-head) 0 0 auto; width: var(--ax-col); padding: 16px 20px 20px; gap: 16px;
    overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; pointer-events: auto; background: #0c0c0f; border-left: 1px solid var(--hairline); }
  :is(.alpha-explore, .dt-scene:not(.is-board)) .ax-top { flex-direction: column; align-items: stretch; flex-wrap: nowrap; gap: 12px; }
  :is(.alpha-explore, .dt-scene:not(.is-board)) .ax-tools { order: -1; justify-content: flex-start; }
  :is(.alpha-explore, .dt-scene) .ax-where, .dt-scene .dt-left { max-width: none; }
  :is(.alpha-explore, .dt-scene) .ax-name { font-size: clamp(26px, 2.3vw, 40px); }
  :is(.alpha-explore, .dt-scene) .ax-tasks { max-width: none; }
  :is(.alpha-explore, .dt-scene) .ax-tasks li { font-size: clamp(14px, 1vw, 16px); }
  .dt-scene .dt-panels { max-height: none; }
  :is(.alpha-explore, .dt-scene:not(.is-board)) .ax-bottom { margin-top: auto; flex-direction: column; align-items: stretch; gap: 14px; }
  :is(.alpha-explore, .dt-scene) .ax-talk { max-width: none; }
  :is(.alpha-explore, .dt-scene) .ax-who, .dt-scene .dt-reading > .al-eyebrow:first-child, .dt-scene .dt-caption-who,
  .dt-scene .al-speaker-name { font-size: clamp(16px, 1.3vw, 22px); }
  :is(.alpha-explore, .dt-scene) .ax-line, .dt-scene .dt-reading > .al-line, .dt-scene .dt-caption-words { font-size: clamp(16px, 1.25vw, 21px); text-shadow: none; }
  .dt-scene .dt-caption.is-machine .dt-caption-words { font-size: clamp(14px, 1.05vw, 18px); }
  .dt-scene .ax-bottom .al-btn-lamp, .dt-scene .dt-caption-next, .dt-scene .al-talk-body > .al-cluster .al-btn { min-height: 48px; padding: 0 20px; font-size: 18px; }
  .dt-scene .al-place-exits.ax-people { max-width: none; flex-wrap: wrap; justify-content: flex-start; align-items: stretch; }
  .alpha-explore .ax-people { flex-direction: row; flex-wrap: wrap; }
  .dt-scene .dt-person { min-height: 56px; }
  .dt-scene .dt-person-face { width: 44px; height: 44px; }
  .ax-hud .dt-banks { gap: 6px; }
  .ax-hud .dt-lock-body { gap: 8px; padding: 8px; }
  .dt-scene .al-talk .al-topics:not(.dt-picks) .al-topic { min-height: 48px; padding: 0 16px; font-size: 16px; }
  /* the sheets lie over the picture beside the desk, never over the tools */
  .alpha-explore .ax-map, .dt-scene .dt-sheet { top: var(--ax-head); right: var(--ax-col); width: min(460px, calc(100vw - var(--ax-col))); border-right: 1px solid var(--hairline); }
  /* talking: the person stands in the room (the old adventures' conversation), the room dimmed behind them */
  .dt.dt-scene.is-talking .al-talk { grid-template-columns: minmax(0, 1fr); }
  .dt.dt-scene.is-talking .al-talk > .al-portrait { position: fixed; z-index: 4; left: calc(var(--ax-w) / 2); top: calc(var(--ax-top) + var(--ax-h) * 0.06);
    height: calc(var(--ax-h) * 0.88); width: auto; aspect-ratio: 3 / 4; transform: translateX(-50%); box-shadow: 0 24px 80px #000000cc; }
  .dt-scene.is-talking .ax-stage .al-place-still { filter: brightness(0.35) saturate(0.7) blur(2px); }
  /* the move bar's pin on the room draws inside the picture, which now has edges on screen */
  .dt-scene .ax-stage .al-place[data-your-move] { outline-offset: -2px; }
  /* THE NIGHT LIFT (detective/place.js nightLift, a gamma curve of exponent NIGHT_GAMMA, 0.7). Measured 2026-11-05 on
     the seven shipped night stills (1920 wide): their luminance, mean of the seven, was p90 2.6 and p99.5 24.7 of 255 as
     drawn before (brightness 0.5). Lifted: p90 13.0, p99.5 73.9, with 2.5 percent of the lamps (each still's brightest
     0.1 percent) at 250 or over, the 2.4 percent the stills themselves have, where a plain brightness(2.0) clipped 77.8
     percent of them. A stronger curve (exponent 0.5: p90 23.1) lifts the near-black steps from 1 to 14 of 255 and shows
     the stills' compression blocks; 0.7 lifts them to 5. The common room's night still is black at 8 bits (96 percent
     of it zero) and stays black: no lift gets back what is not there; the stills need grading again. */
  .dt-scene .al-place[data-light="night"] > :is(.dt-picture, picture) > .al-place-still,
  .dt-scene .al-place[data-light="night"] > .al-place-still { filter: url(#dt-night-lift) saturate(0.9); }
  .dt-scene.is-talking .al-place[data-light="night"] > :is(.dt-picture, picture) > .al-place-still { filter: url(#dt-night-lift) brightness(0.35) saturate(0.7) blur(2px); }
}
.dt-map-still[data-light="night"] { filter: url(#dt-night-lift); }

/* between places: a short fade up from the dark (alpha/place.js arrive, detective/detective.js ARRIVE_MS) */
@keyframes ax-arrive { from { opacity: 0; } to { opacity: 1; } }
.ax-stage.is-arriving { animation: ax-arrive 360ms ease-out both; }
:root.is-still .ax-stage.is-arriving { animation: none; }
@media (prefers-reduced-motion: reduce) { .ax-stage.is-arriving { animation: none; } }

/* the jobs fold away under the place's name */
.ax-where-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.ax-jobs { flex: none; min-height: 32px; margin-top: 2px; padding: 0 10px; border: 1px solid var(--edge, #6e6e76); border-radius: 2px; background: transparent;
  color: var(--text-secondary); font-family: var(--font-mono); font-size: 12px; cursor: pointer; }
.ax-jobs:hover, .ax-jobs:focus-visible { border-color: var(--accent); color: var(--text); outline: none; }
.ax-jobs[hidden], .ax-tasks[hidden] { display: none; }
.ax-map-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
