/* ═══════════════════════════════════════════════════════════════════════════
   TIBERIUM CONTROL
   An operations board for a nineteen-year-old RTS that maybe forty people
   are playing at any given moment. Built to answer one question fast:
   is anyone on, and can I join them?

   Colour carries meaning, never decoration:
     tiberium green .. live, in combat
     amber .......... staging, waiting for players
     red ............ locked, or a broken link
     steel blue ..... idle population in the chart
   Every status colour is doubled by a word or a shape, because green and
   amber collapse into each other under deuteranopia.
   ═══════════════════════════════════════════════════════════════════════ */

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

:root {
  /* Colour, type, radii, elevation and motion all come from Arcline —
     see arcline-skin.css, which seeds the system and bridges the names
     this file still uses (--void, --deck, --ink, --tib, --nod …).
     Only layout metrics that are genuinely this board's own live here. */
  --rail-l: 264px;
  --rail-r: 292px;
  --pad: 18px;
}

/* ─────────────────────────────────────────────────────────────────── base */

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--void);
  color: var(--ink);
  font: 400 13px/1.5 var(--mono);
  font-variant-numeric: tabular-nums;
  overflow-x: hidden;
}

/* faint engineering grid + vignette, both inert */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--tib) 3%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--tib) 3%, transparent) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 120% 90% at 50% 0%, #000 20%, transparent 78%);
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(ellipse 90% 60% at 50% 0%, transparent 40%, rgba(0,0,0,.7) 100%);
}
body > * { position: relative; z-index: 1; }

h1, h2 { margin: 0; font-weight: 600; }
button, input { font: inherit; color: inherit; }

/* several elements below set an explicit display, which would beat the UA
   rule for [hidden] — make the attribute win everywhere */
[hidden] { display: none !important; }

.sr {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 20;
  background: var(--tib); color: #04120a; padding: 8px 14px;
  font-weight: 600; text-decoration: none; transition: top .12s;
}
.skip:focus { top: 8px; }

:focus-visible {
  outline: 2px solid var(--tib);
  outline-offset: 2px;
}

/* shared label style — the small caps mono used on every panel */
.panel__label, .eyebrow {
  font-size: 10px; font-weight: 600; letter-spacing: .24em;
  text-transform: uppercase; color: var(--ink-2);
}

/* ───────────────────────────────────────────────────────────────── topbar */

.topbar {
  position: sticky; top: 0; z-index: 12;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0 var(--pad); height: 46px;
  background: color-mix(in srgb, var(--canvas) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.topbar__mark { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* The brand is a link home on every page, so it is styled on every page.
   It lived in player.css while only that page wrapped it in an anchor,
   which left the board rendering it as a default underlined link. */
.topbar__home {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: inherit;
  text-decoration: none;
}
.topbar__home:hover .topbar__name { color: var(--brand-text, currentColor); }
.topbar__home:focus-visible { outline: 2px solid var(--focus, currentColor); outline-offset: 3px; }
.sigil { width: 21px; height: 21px; color: var(--tib); flex: none; }
.topbar__name {
  font-family: var(--disp); font-weight: 700; font-size: 15px;
  letter-spacing: .07em; text-transform: uppercase; white-space: nowrap;
}
.topbar__sub {
  font-size: 10px; letter-spacing: .18em; color: var(--ink-3);
  text-transform: uppercase; padding-left: 10px; border-left: 1px solid var(--line-2);
}

.topbar__meta { display: flex; align-items: center; gap: 14px; }

/* The page's own bits are hoisted into a wrapper inside .topbar__meta, but
   they were written as direct children of that flex row and still need to
   behave like them — otherwise the pill and the button stack instead of
   sitting side by side. display:contents removes the wrapper from layout
   and hands its children straight back to the row. */
.topbar__extra { display: contents; }

/* ── the header search ─────────────────────────────────────────────────
   Lived in player.css while only the two player pages had it. The search
   is in the shared header now, so it has to be styled on every page, and
   style.css is the only stylesheet all five of them load. */
/* the header search, and its results */
.find {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1 1 240px;
  max-width: 460px;
  height: var(--field-height);
  padding: 0 var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--muted);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.find:hover { border-color: var(--muted); }
.find:focus-within { border-color: var(--brand); box-shadow: var(--ring); }
.find svg { width: 15px; height: 15px; flex: none; }
.find input {
  flex: 1; min-width: 0;
  border: 0; background: none; color: var(--text);
  font-family: var(--font-sans); font-size: .875rem;
}
.find input::placeholder { color: var(--muted); }
.find input:focus-visible { outline: none; }
.find__key {
  flex: none;
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--rule-strong);
  background: var(--panel);
  font-family: var(--font-mono);
  font-size: .625rem;
  color: var(--muted);
}
.find:focus-within .find__key { opacity: 0; }

.find--top { height: var(--control-height-sm); max-width: 240px; flex: 0 1 240px; }

.findlist {
  position: absolute;
  top: 42px;
  inset-inline-end: var(--pad);
  z-index: 30;
  width: min(320px, calc(100vw - 32px));
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  border-radius: var(--radius-md);
  border: 1px solid var(--rule-strong);
  background: var(--glass-surface-strong);
  -webkit-backdrop-filter: blur(var(--glass-blur-lg)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur-lg)) saturate(var(--glass-saturate));
  box-shadow: var(--edge), var(--shadow-xl);
}
.findlist a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: .8125rem;
  text-decoration: none;
}
.findlist a:hover,
.findlist a:focus-visible,
.findlist [aria-selected="true"] a { background: var(--brand-soft); color: var(--brand-text); }
.findlist small { font-family: var(--font-mono); font-size: .625rem; color: var(--muted); }


.pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  padding: 4px 9px; border: 1px solid var(--line-2); color: var(--ink-2);
  /* The search now shares this row, so the pill has to hold one line rather
     than break in half when the bar gets tight. */
  white-space: nowrap; flex: none;
}
.pill__dot { width: 6px; height: 6px; flex: none; background: currentColor; }
.pill[data-state="live"]  { color: var(--tib);  border-color: color-mix(in srgb, var(--tib) 34%, transparent); }
.pill[data-state="stale"] { color: var(--gdi);  border-color: color-mix(in srgb, var(--gdi) 40%, transparent); }
.pill[data-state="down"]  { color: var(--nod);  border-color: color-mix(in srgb, var(--nod) 45%, transparent); }
.pill[data-state="live"] .pill__dot { animation: beat 2.4s ease-in-out infinite; }
@keyframes beat { 0%,100% { opacity: 1 } 50% { opacity: .28 } }

.kv { display: flex; align-items: baseline; gap: 7px; font-size: 11px; color: var(--ink); }
.kv b {
  font-weight: 500; font-size: 9px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-3);
}

.refresh {
  display: inline-flex; align-items: center; gap: 7px;
  background: transparent; border: 1px solid var(--line-2); color: var(--ink-2);
  padding: 5px 10px; cursor: pointer;
  font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  transition: color .15s, border-color .15s;
}
.refresh svg { width: 11px; height: 11px; }
.refresh:hover { color: var(--tib); border-color: color-mix(in srgb, var(--tib) 40%, transparent); }
.refresh[data-busy="1"] svg { animation: spin .9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg) } }

/* the thin bar that drains toward the next refresh */
.topbar__tick { position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; }
.topbar__tick span {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, transparent, var(--tib));
  opacity: .5;
}

/* ─────────────────────────────────────────────────────────────────── hero */

.hero {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) 452px;
  align-items: center; gap: 56px;
  padding: 30px var(--pad) 28px;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

/* Kane, kept to a rumour behind the plot — it must never compete with a number */
.hero__art {
  position: absolute; inset: -20% 12% -20% 28%;
  background: url("/assets/keyart.webp") center / contain no-repeat;
  opacity: .22;
  mask-image: radial-gradient(ellipse 62% 72% at 50% 46%, #000 6%, transparent 68%);
  filter: saturate(.4) contrast(1.2) brightness(.82);
}
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(90deg, var(--void) 12%, color-mix(in srgb, var(--canvas) 60%, transparent) 34%, color-mix(in srgb, var(--canvas) 25%, transparent) 58%, color-mix(in srgb, var(--canvas) 80%, transparent) 82%),
    linear-gradient(to bottom, transparent 58%, var(--void) 100%);
}
.hero > .hero__say, .hero > .theatre { position: relative; }

.hero__say { max-width: 44ch; }
.eyebrow { margin: 0 0 14px; }

.hero__title {
  font-family: var(--disp); font-weight: 700;
  font-size: clamp(26px, 2.5vw, 34px); line-height: 1.06;
  letter-spacing: .005em; text-transform: uppercase; color: var(--ink);
  margin-bottom: 22px;
}
.hero__title span { color: var(--ink-3); }

/* the readout — four numbers, hairline-ruled, right-aligned into a column so
   the digits stack into a single edge you can scan in one pass */
.readout { margin: 0 0 18px; border-top: 1px solid var(--line); }
.readout__row {
  display: grid; grid-template-columns: 74px minmax(0, 1fr) auto;
  align-items: baseline; gap: 18px;
  padding: 9px 0 8px; border-bottom: 1px solid var(--line);
}
.readout dt {
  order: 2; font-family: var(--disp); font-size: 15px; font-weight: 500;
  letter-spacing: .01em; color: var(--ink-2);
}
.readout dd {
  order: 1; margin: 0; text-align: right;
  font-family: var(--disp); font-weight: 700; font-size: 34px; line-height: .92;
  font-variant-numeric: tabular-nums; color: var(--tib);
}
.readout .delta {
  order: 3; font-size: 10px; letter-spacing: .1em; color: var(--ink-3);
  white-space: nowrap;
}
.readout .delta[data-dir="up"]   { color: var(--tib); }
.readout .delta[data-dir="down"] { color: var(--ink-2); }
.readout__row.is-amber dd { color: var(--gdi); }
.readout__row.is-dim  dd { color: var(--ink-3); }
.readout__row.is-dim  dt { color: var(--ink-3); }

.say__note {
  margin: 0; font-size: 12px; color: var(--ink-2); max-width: 48ch; line-height: 1.6;
}

.hero__legend {
  display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 20px;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3);
}
.hero__legend span { display: inline-flex; align-items: center; gap: 7px; }
.key { width: 9px; height: 9px; flex: none; }
.key--live  { background: var(--tib); clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }
.key--stage { border: 1px solid var(--gdi); clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }
.key--lock  { border: 1px solid var(--nod); border-radius: 50%; }
.key--idle  { background: var(--scrin); opacity: .6; border-radius: 50%; width: 5px; height: 5px; }

/* ── the plot ───────────────────────────────────────────────────────────── */

.theatre { margin: 0; position: relative; }
.theatre__cap {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding-bottom: 10px; margin-bottom: 6px; border-bottom: 1px solid var(--line);
}
.theatre__hint { font-size: 10px; color: var(--ink-3); letter-spacing: .04em; }
#plot { width: 100%; height: auto; display: block; overflow: visible; }

.plot__grid circle { fill: none; stroke: var(--line-2); stroke-width: 1; }
.plot__grid line { stroke: var(--line); stroke-width: 1; }
.plot__grid text {
  fill: var(--ink-3); font-size: 9px; letter-spacing: .16em;
  font-family: var(--mono); text-anchor: middle;
}
.plot__hub line, .plot__hub circle { stroke: var(--line-hot); stroke-width: 1; }
.plot__sweep {
  transform-box: view-box; transform-origin: 310px 310px;
  animation: sweep 9s linear infinite;
}
@keyframes sweep { to { transform: rotate(360deg) } }

/* ── idle players: specks in the dark beyond the rings ──────────────────── */

.plot__stars .star { cursor: pointer; }
.star__hit { fill: transparent; pointer-events: all; }
.star__dot {
  fill: var(--scrin); fill-opacity: .5; pointer-events: none;
  animation: twinkle 5.5s ease-in-out infinite;
}
@keyframes twinkle {
  0%, 100% { fill-opacity: .22; }
  50%      { fill-opacity: .8; }
}
.star:hover .star__dot,
.star:focus-visible .star__dot,
.star.is-hot .star__dot {
  fill: var(--scrin); fill-opacity: 1; animation: none;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--scrin) 95%, transparent));
}
.star.is-hot .star__dot { r: 3.4; }
/* the dimming rule below must not swallow a speck that is the focus */
#plot.has-focus .star:not(.is-hot) .star__dot { fill-opacity: .12; animation: none; }

.node { cursor: pointer; }
.node__hit { fill: transparent; pointer-events: all; }
.node__spoke, .node__label, .node__flare, .node__lock { pointer-events: none; }
.node__spoke { stroke: var(--line); stroke-width: 1; }
.node__hex   { stroke-width: 1.4; fill: none; transition: stroke-width .15s; }
.node__core  { stroke: none; }
.node__flare { fill: none; stroke-width: 1; opacity: 0; }
.node__lock  { fill: none; stroke: var(--nod); stroke-width: 1.2; opacity: .9; }
.node__obs   { fill: var(--scrin); }
.node--playing .node__hex  { stroke: var(--tib); }
.node--playing .node__core { fill: var(--tib); }
.node--playing .node__flare{ stroke: var(--tib); }
.node--staging .node__hex  { stroke: var(--gdi); }
.node--staging .node__core { fill: var(--gdi); }
.node--staging .node__flare{ stroke: var(--gdi); }
.node__label {
  font-family: var(--mono); font-size: 9px; fill: var(--ink-2);
  text-anchor: middle; pointer-events: none; opacity: 0; transition: opacity .15s;
}
.node:hover .node__hex, .node.is-hot .node__hex { stroke-width: 2.4; }
.node:hover .node__label, .node.is-hot .node__label { opacity: 1; }
.node.is-hot .node__spoke { stroke: var(--line-hot); }
#plot.has-focus .node:not(.is-hot) { opacity: .26; }

.theatre__empty {
  position: absolute; inset: auto 0 46%; text-align: center;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3);
}

/* floating readout, shared by plot and chart */
.tip {
  position: absolute; z-index: 30; pointer-events: none;
  min-width: 168px; max-width: 250px;
  background: color-mix(in srgb, var(--surface) 97%, transparent); border: 1px solid var(--line-hot);
  padding: 9px 11px; font-size: 11px; line-height: 1.45;
  box-shadow: 0 12px 30px rgba(0,0,0,.6);
}
.tip__t {
  font-family: var(--disp); font-size: 13px; font-weight: 600;
  letter-spacing: .02em; color: var(--ink); margin-bottom: 5px;
  overflow-wrap: anywhere;
}
.tip__r { display: flex; justify-content: space-between; gap: 14px; color: var(--ink-2); }
.tip__r b { font-weight: 500; color: var(--ink); }
.tip__tag {
  display: inline-block; margin-bottom: 6px; padding: 1px 6px;
  font-size: 9px; letter-spacing: .18em; text-transform: uppercase;
  border: 1px solid currentColor;
}
.tip__tag--playing { color: var(--tib); }
.tip__tag--staging { color: var(--gdi); }
.tip__tag--idle { color: var(--scrin); }
.tip__names { margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line); color: var(--ink-2); overflow-wrap: anywhere; }
.tip__names b { display: block; font-weight: 500; font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 3px; }

/* the plot tip is anchored in viewport space so no panel can clip it */
#tip { position: fixed; }

/* On a touch screen the tip must be tappable: with pointer-events off, a tap
   lands on whatever sits beneath it and selects that instead of closing. */
@media (hover: none) {
  .tip { pointer-events: auto; cursor: pointer; }
  #tip { max-width: min(320px, calc(100vw - 24px)); }
}

/* ──────────────────────────────────────────────────────────────── console */

/* The three columns stretch to a common height, so each one's content has to
   fill its box or you get ragged dead space in one and a row sliced in half in
   another. Every panel is a flex column: head fixed, body takes the slack. */
.console {
  display: grid;
  grid-template-columns: var(--rail-l) minmax(0, 1fr) var(--rail-r);
  /* A DEFINITE row height, not a floor. `min-height` let the roster's own
     content size the row, so a busy night pushed this past 1300px and the
     inner overflow never engaged. minmax caps it and the lists scroll. */
  grid-template-rows: minmax(0, 560px);
  border-bottom: 1px solid var(--line);
}
.rail {
  border-right: 1px solid var(--line); background: var(--deck);
  display: flex; flex-direction: column; min-height: 0;
}
.rail > .panel { flex: 1; }

.panel {
  background: var(--deck); min-width: 0;
  display: flex; flex-direction: column; min-height: 0;
}
.panel__head { flex: none; }
.panel--stage { border-right: 1px solid var(--line); }
.rail > .panel + .panel { border-top: 1px solid var(--line); }

.panel__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  height: 38px; padding: 0 14px;
  border-bottom: 1px solid var(--line);
  background: var(--deck-2);
}
.panel__aside { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.panel__body { padding: 14px; flex: 1; display: flex; flex-direction: column; min-height: 0; }

/* ── population chart ───────────────────────────────────────────────────── */

.chart { position: relative; flex: 0 1 auto; height: 250px; min-height: 130px; }
#popchart { width: 100%; height: 100%; display: block; }
#pop-grid line { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
#pop-grid text { fill: var(--ink-3); font-size: 8px; font-family: var(--mono); }
.area { stroke: none; }
.area--combat { fill: var(--tib-deep); fill-opacity: .55; }
.area--lobby  { fill: var(--cold);    fill-opacity: .42; }
.area__edge { fill: none; stroke: var(--tib); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.cross { stroke: var(--ink-3); stroke-width: 1; vector-effect: non-scaling-stroke; }
.cross__dot { fill: var(--tib); stroke: var(--deck); stroke-width: 1.5; }
.chart__empty {
  position: absolute; inset: 0; display: grid; place-items: center;
  padding: 0 14px; text-align: center; font-size: 11px; color: var(--ink-3);
  background: var(--deck);
}
.chart__ymax {
  position: absolute; top: 0; right: 0; padding: 1px 3px;
  font-size: 9px; color: var(--ink-3); background: var(--deck);
  pointer-events: none;
}
.tip--chart { min-width: 130px; }

.legend {
  flex: none;
  display: flex; flex-wrap: wrap; gap: 4px 16px;
  margin: 12px 0 0; padding: 0; list-style: none;
  font-size: 11px; color: var(--ink-2);
}
.legend li { display: inline-flex; align-items: center; gap: 7px; }
.legend b { font-weight: 600; color: var(--ink); }
.sw { width: 10px; height: 10px; flex: none; }
.sw--combat { background: var(--tib-deep); }
.sw--lobby  { background: var(--cold); }

.peaks {
  flex: none;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line);
}
.peaks div { min-width: 0; }
.peaks dt {
  font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3);
}
.peaks dd { margin: 3px 0 0; font-size: 15px; color: var(--ink); }

/* Scroll shadows: the covering gradients scroll *with* the content (local) and
   the shadows do not (scroll), so an edge only darkens when there is genuinely
   more content past it. Stops a list ending flush at a section boundary from
   looking sliced. */
.scroller {
  background:
    linear-gradient(var(--deck) 30%, transparent) center top / 100% 26px no-repeat local,
    linear-gradient(transparent, var(--deck) 72%) center bottom / 100% 30px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0)) center top / 100% 13px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0)) center bottom / 100% 15px no-repeat scroll;
}

/* ── ledger ─────────────────────────────────────────────────────────────── */

.filters { display: flex; gap: 6px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid var(--line-2); color: var(--ink-3);
  padding: 3px 8px; cursor: pointer;
  font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  transition: color .15s, border-color .15s, background .15s;
}
.chip b { font-weight: 600; color: var(--ink-2); }
.chip:hover { color: var(--ink-2); border-color: var(--line-hot); }
.chip.is-on { color: var(--ink); border-color: var(--line-hot); background: var(--raised); }
.chip.is-on b { color: var(--tib); }

.table-wrap { position: relative; flex: 1; min-height: 0; overflow: auto; }

table.ledger { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* Fixed widths keep every row the same height. Without this a long map name
   wraps and the table goes ragged, which is what makes a dense list feel messy. */
table.ledger col.c-state { width: 96px; }
table.ledger col.c-game  { width: 24%; }
table.ledger col.c-map   { width: 30%; }
table.ledger col.c-host  { width: 17%; }
table.ledger col.c-slots { width: 138px; }
table.ledger col.c-obs   { width: 58px; }
table.ledger th {
  position: sticky; top: 0; z-index: 2;
  background: var(--deck-2); text-align: left; font-weight: 500;
  font-size: 9px; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3);
  padding: 9px 12px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.ledger td {
  padding: 0 12px; height: 40px; border-bottom: 1px solid var(--line);
  vertical-align: middle; font-size: 12px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
table.ledger tbody tr { cursor: pointer; transition: background .12s; }
table.ledger tbody tr:hover { background: var(--deck-2); }
table.ledger tbody tr.is-hot { background: var(--raised); }
table.ledger tbody tr.is-hot td:first-child { box-shadow: inset 2px 0 0 var(--tib); }
table.ledger tbody tr.is-staging.is-hot td:first-child { box-shadow: inset 2px 0 0 var(--gdi); }
.col-slots { width: 132px; }
.col-obs { width: 54px; }
.col-state { width: 96px; }

/* state: shape + word, never colour alone */
.state { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.state i { width: 8px; height: 8px; flex: none; clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }
.state--playing { color: var(--tib); }
.state--playing i { background: currentColor; }
.state--staging { color: var(--gdi); }
.state--staging i { border: 1px solid currentColor; }

.g-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
.g-title {
  color: var(--ink); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.g-map, .g-host {
  color: var(--ink-2); display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lockmark {
  flex: none; color: var(--nod); font-size: 9px; letter-spacing: .12em;
  text-transform: uppercase; border: 1px solid color-mix(in srgb, var(--nod) 45%, transparent);
  padding: 1px 5px; line-height: 1.5;
}

.slots { display: flex; align-items: center; gap: 9px; }
.slots__bar { flex: 1; min-width: 44px; height: 6px; background: var(--line); display: flex; gap: 2px; }
.slots__bar i { flex: 1; background: var(--line-2); }
.slots__bar i.on { background: var(--tib-deep); }
.slots--staging .slots__bar i.on { background: var(--gdi); }
.slots__n { color: var(--ink); font-size: 11px; white-space: nowrap; }
.slots__n em { font-style: normal; color: var(--ink-3); }

.obs { color: var(--scrin); font-size: 11px; }
.obs--none { color: var(--ink-3); }

.rosterline {
  padding: 0 12px 11px; font-size: 11px; color: var(--ink-2);
  border-bottom: 1px solid var(--line); overflow-wrap: anywhere;
}
.rosterline span { color: var(--ink); }
.rosterline em { font-style: normal; color: var(--ink-3); }

.empty {
  margin: 0; padding: 30px 16px; text-align: center;
  font-size: 12px; color: var(--ink-3); line-height: 1.6;
}

/* ── roster ─────────────────────────────────────────────────────────────── */

.panel--roster { display: flex; flex-direction: column; }
.roster__search {
  flex: none;
  display: flex; align-items: center; gap: 9px;
  padding: 0 14px; height: 40px; border-bottom: 1px solid var(--line);
  color: var(--ink-3);
}
.roster__search svg { width: 13px; height: 13px; flex: none; }
.roster__search input {
  flex: 1; min-width: 0; background: none; border: 0; padding: 0;
  font-size: 12px; color: var(--ink);
}
.roster__search input::placeholder { color: var(--ink-3); }
.roster__search input:focus { outline: none; }
.roster__search:focus-within { color: var(--tib); }

.roster {
  margin: 0; padding: 0; list-style: none;
  flex: 1; min-height: 0; overflow: auto;
}
.roster li {
  display: grid; grid-template-columns: 10px minmax(0,1fr) auto;
  align-items: center; gap: 9px;
  padding: 7px 14px; border-bottom: 1px solid var(--line);
  cursor: default; transition: background .12s;
}
.roster li:hover { background: var(--deck-2); }
.roster li.is-hot { background: var(--raised); }
.roster .nick { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.roster .where { font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); }
.roster .dot { width: 8px; height: 8px; }
.roster li.p-playing { cursor: pointer; }
.roster li.p-staging { cursor: pointer; }
.roster li.p-playing .dot { background: var(--tib); clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }
.roster li.p-playing .where { color: var(--tib); }
.roster li.p-staging .dot { border: 1px solid var(--gdi); clip-path: polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); }
.roster li.p-staging .where { color: var(--gdi); }
.roster li.p-lobby { cursor: pointer; }
.roster li.p-lobby .dot { background: var(--scrin); opacity: .55; border-radius: 50%; width: 5px; height: 5px; margin-left: 1px; }
.roster li.p-lobby.is-hot .dot { opacity: 1; }
.roster li.p-lobby.is-hot .where { color: var(--scrin); }

/* ───────────────────────────────────────────────────────── command centre */

/* The archive is Nod's intelligence wing, so it gets Nod's chrome: gunmetal,
   red hairlines, the Operations Center standing over it. Red is used ONLY for
   framing here — every data mark below keeps its validated colour, because the
   moment red means "structure" and "locked" at once, the board stops reading. */
.cc {
  position: relative; overflow: hidden;
  padding: 0 0 26px;
  border-top: 1px solid color-mix(in srgb, var(--nod-deep) 30%, transparent);
  border-bottom: 1px solid var(--line);
  box-shadow: inset 0 14px 26px -14px rgba(0, 0, 0, .85);
  background:
    radial-gradient(ellipse 60% 150% at 12% 0%, color-mix(in srgb, var(--nod-deep) 8%, transparent), transparent 62%),
    linear-gradient(180deg, #0b0709 0%, var(--void) 46%);
}
.cc > * { position: relative; z-index: 1; }

.cc__head {
  position: relative;
  display: flex; align-items: center; gap: clamp(16px, 2vw, 30px);
  padding: 22px var(--pad);
  border-bottom: 1px solid color-mix(in srgb, var(--nod-deep) 18%, transparent);
}
/* the structure, as a mark on the left rather than a backdrop */
.cc__head::after {
  content: ""; order: -1; flex: none;
  width: clamp(104px, 11vw, 156px); aspect-ratio: 1;
  background: url("/assets/opscenter.webp") center / contain no-repeat;
  filter: drop-shadow(0 8px 26px color-mix(in srgb, var(--nod-deep) 38%, transparent));
  animation: powered 6s ease-in-out infinite;
}
@keyframes powered {
  0%, 100% { filter: drop-shadow(0 8px 22px color-mix(in srgb, var(--nod-deep) 28%, transparent)); }
  50%      { filter: drop-shadow(0 8px 34px color-mix(in srgb, var(--nod-deep) 48%, transparent)); }
}

.cc__lockup { flex: none; }
.cc__head .eyebrow { color: var(--nod); margin: 0 0 7px; }
.cc__title {
  font-family: var(--disp); font-size: clamp(21px, 2.2vw, 30px); font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; line-height: 1;
  text-shadow: 0 0 26px color-mix(in srgb, var(--nod-deep) 30%, transparent);
}

/* the answer most people came for, said plainly and once */
.best {
  margin-left: auto; padding: 11px 16px 12px;
  border: 1px solid color-mix(in srgb, var(--nod-deep) 30%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--nod-deep) 9%, transparent), transparent);
  max-width: 44ch; min-width: 0;
}
.best__label {
  margin: 0; font-size: 9px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--nod);
}

/* the live figure, and how it compares with a normal night */
.best__live { display: flex; align-items: baseline; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.best__live b {
  font-family: var(--disp); font-weight: 700; font-size: 30px; line-height: 1;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.best__unit { font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3); }
.best__vs {
  margin-left: auto; font-size: 10.5px; letter-spacing: .02em; color: var(--ink-2);
  white-space: nowrap;
}
.best__vs[data-dir="up"]   { color: var(--tib); }
.best__vs[data-dir="down"] { color: var(--gdi); }

/* A bar, not a curve. It reads the same on day one as it will in a month,
   because there is no axis of unobserved hours to leave holes in. */
.gauge { margin-top: 14px; }
.gauge__track {
  position: relative; height: 8px; background: var(--line);
  border: 1px solid var(--line-2);
}
.gauge__fill {
  position: absolute; inset: 0 auto 0 0; width: 0;
  background: linear-gradient(90deg, var(--tib-deep), var(--tib));
  transition: width .7s cubic-bezier(.4, 0, .2, 1);
}
/* A slow scan across the whole track, so a live number never looks like a
   screenshot. It lives in its own clipped layer rather than inside the fill:
   as a child of the fill it measured itself against the fill's width and ran
   off the end of it. The marker stays outside this layer so its label above
   the bar is not clipped away. */
.gauge__sheen { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.gauge__sheen::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 36%;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--tib) 34%, transparent), transparent);
  animation: sheen 3.8s ease-in-out infinite;
}
/* 36%-wide band: -100% parks it just off the left edge, 278% just off the right */
@keyframes sheen {
  0%        { transform: translateX(-100%); }
  70%, 100% { transform: translateX(278%); }
}

/* where a normal hour would sit */
.gauge__usual {
  position: absolute; top: -4px; bottom: -4px; width: 2px;
  background: var(--gdi); transform: translateX(-1px);
  box-shadow: 0 0 6px color-mix(in srgb, var(--gdi) 75%, transparent);
}
.gauge__usual::after {
  content: "usual"; position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
  font-size: 8px; letter-spacing: .14em; text-transform: uppercase; color: var(--gdi);
}
.gauge__scale {
  display: flex; justify-content: space-between; margin-top: 7px;
  font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3);
}

@media (prefers-reduced-motion: reduce) {
  .gauge__fill { transition: none; }
  .gauge__sheen { display: none; }
}

.best__say { margin: 8px 0 0; font-size: 11px; color: var(--ink-2); line-height: 1.5; }

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

/* archive counters */
.arc {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 1px; margin: 0 0 1px; background: var(--line);
  border: 1px solid var(--line);
}
.arc > div { background: var(--deck); padding: 13px 15px; min-width: 0; }
.cc .arc { border-color: color-mix(in srgb, var(--nod-deep) 16%, transparent); background: color-mix(in srgb, var(--nod-deep) 16%, transparent); }
.cc .cc__grid { border-color: color-mix(in srgb, var(--nod-deep) 16%, transparent); background: color-mix(in srgb, var(--nod-deep) 16%, transparent); }
.cc .panel__head { border-bottom-color: color-mix(in srgb, var(--nod-deep) 16%, transparent); }
.arc dt {
  font-size: 9px; letter-spacing: .17em; text-transform: uppercase; color: var(--ink-3);
}
.arc dd {
  margin: 5px 0 0; font-family: var(--disp); font-size: 24px; font-weight: 700;
  color: var(--ink); line-height: 1;
}
.arc dd small {
  display: block; margin-top: 4px; font-family: var(--mono);
  font-size: 10px; font-weight: 400; color: var(--ink-3); letter-spacing: .04em;
}

.cc__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px minmax(0, 1fr);
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-top: 0;
}
.cc__when { grid-column: 1 / -1; }

/* Row two is three panels across: maps, match length, then the crew ring in
   the narrow middle column. Adding the length panel pushed the leaderboard
   onto a row of its own where it sat in column one with two empty columns
   beside it, which is what the tinted gap was. It spans the full row now,
   and the table is better for the width. */
.cc__ops { grid-column: 1 / -1; }

/* ── the dials ──────────────────────────────────────────────────────────── */

.dials {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px; padding: 14px 14px 18px;
}
.dial { margin: 0; min-width: 0; }
.dial__cap {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 0 4px 10px; margin-bottom: 4px; border-bottom: 1px solid var(--line);
  font-size: 10px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink-2);
}
.dial__sub {
  font-weight: 400; letter-spacing: .06em; text-transform: none; color: var(--ink-3);
}
.dial__svg { width: 100%; max-width: 296px; height: auto; display: block; margin-inline: auto; overflow: visible; }

.dial__rings circle { fill: none; stroke: var(--line); stroke-width: 1; }
.dial__marks line { stroke: var(--line); stroke-width: 1; }
.dial__marks line.is-major { stroke: var(--line-hot); }
.dial__tick {
  fill: var(--ink-3); font-family: var(--mono); font-size: 9px;
  letter-spacing: .08em; text-anchor: middle;
}
.dial__now { stroke: var(--gdi); stroke-width: 1.3; stroke-dasharray: 3 3; opacity: .8; }
.dial__peak { fill: var(--tib); stroke: var(--void); stroke-width: 1.4; }
.dial__dot { fill: var(--tib); }

.dial__fill { stroke: none; }
.dial__edge {
  fill: none; stroke: var(--tib); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--tib) 55%, transparent));
}

/* The shape grows out of the hub. Driven by a keyframe rather than a class
   toggle: these nodes are rebuilt on every render, so the animation fires on
   insertion and cannot be missed by a timing race. */
.dial__area > * {
  transform-box: view-box; transform-origin: 150px 150px;
  animation: dial-in .8s cubic-bezier(.16, .9, .3, 1) both;
}
@keyframes dial-in {
  from { transform: scale(.05); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}
#dial-week .dial__area > *  { animation-delay: .09s; }
#dial-month .dial__area > * { animation-delay: .18s; }

/* the peak marker breathes so the eye finds it */
.dial__peak { animation: peak-pulse 2.6s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes peak-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }

.dial__mid {
  fill: var(--ink); font-family: var(--disp); font-size: 15px; font-weight: 700;
  text-anchor: middle; letter-spacing: .01em;
}
.dial__midsub {
  fill: var(--ink-3); font-family: var(--mono); font-size: 7.5px;
  letter-spacing: .2em; text-anchor: middle; text-transform: uppercase;
}
.dial__svg.is-probing .dial__mid { fill: var(--tib); }

.dial__hit { fill: transparent; cursor: crosshair; }
.dial__hit:hover { fill: color-mix(in srgb, var(--tib) 7%, transparent); }

@media (prefers-reduced-motion: reduce) {
  .dial__area > *, .dial__peak { animation: none; opacity: 1; }
}

/* ── who plays together ─────────────────────────────────────────────────── */

/* Everyone who has ever finished a game beside somebody else sits on the rim.
   All 1700-odd pairings drawn at once is a hairball, so the resting state shows
   only the strongest few and the pointer asks for one person's links at a time.
   Names sit below the circle: anything written across the middle competes with
   the chords passing through it. */
.crew__body { padding: 10px 10px 12px; }
#crew { width: 100%; max-width: 268px; margin: 0 auto; display: block; overflow: visible; cursor: crosshair; }

.crew__links path, .crew__focus path {
  fill: none; stroke: var(--tib); stroke-linecap: round;
}
.crew__links path { stroke-opacity: .13; stroke-width: .6; transition: stroke-opacity .18s; }
#crew.is-probing .crew__links path { stroke-opacity: .03; }
.crew__focus path { stroke-opacity: .9; stroke-linejoin: round; }

.crew__dot { fill: var(--tib); fill-opacity: .5; transition: fill-opacity .15s; }
#crew.is-probing .crew__dot { fill-opacity: .14; }
.crew__dot.is-linked { fill-opacity: .95; }
.crew__dot.is-hot {
  fill-opacity: 1; filter: drop-shadow(0 0 6px var(--tib));
}

.crew__read {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  min-height: 62px;
}
.crew__who {
  margin: 0; font-family: var(--disp); font-size: 14px; font-weight: 700;
  color: var(--ink); letter-spacing: .01em; overflow-wrap: anywhere;
}
.crew__who small {
  display: block; margin-top: 2px; font-family: var(--mono); font-size: 9px;
  font-weight: 400; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-3);
}
.crew__note { margin: 6px 0 0; font-size: 10.5px; color: var(--ink-2); line-height: 1.5; }

/* the busiest few, named — so the biggest dots are findable without hunting */
.crew__hubs { margin: 7px 0 0; display: flex; flex-wrap: wrap; gap: 4px; }
.crew__hubs button {
  background: transparent; border: 1px solid var(--line-2); color: var(--ink-2);
  padding: 2px 6px; font-size: 9.5px; letter-spacing: .04em; cursor: pointer;
  max-width: 15ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: color .15s, border-color .15s;
}
.crew__hubs button:hover, .crew__hubs button.is-on {
  color: var(--tib); border-color: color-mix(in srgb, var(--tib) 45%, transparent);
}

/* find a name without hunting the rim for it */
.crew__find {
  display: flex; align-items: center; gap: 5px; color: var(--ink-3);
  border: 1px solid var(--line-2); padding: 2px 7px; max-width: 116px;
}
.crew__find svg { width: 11px; height: 11px; flex: none; }
.crew__find input {
  flex: 1; min-width: 0; background: none; border: 0; padding: 0;
  font-size: 10.5px; color: var(--ink);
}
.crew__find input::placeholder { color: var(--ink-3); }
.crew__find input:focus { outline: none; }
.crew__find:focus-within { color: var(--tib); border-color: color-mix(in srgb, var(--tib) 45%, transparent); }

.crew__dot.is-found { fill-opacity: 1; fill: var(--scrin); }

/* ── map frequency ──────────────────────────────────────────────────────── */

.maps {
  margin: 0; padding: 0; list-style: none;
  flex: 1; min-height: 0; max-height: 376px; overflow: auto;
}
.maps li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 3px 12px; padding: 9px 14px; border-bottom: 1px solid var(--line);
}
.maps li:last-child { border-bottom: 0; }
.maps .m-name {
  font-size: 12px; color: var(--ink); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.maps .m-n { font-size: 12px; color: var(--tib); text-align: right; }
.maps .m-bar { grid-column: 1 / -1; height: 4px; background: var(--line); }
.maps .m-bar i { display: block; height: 100%; background: var(--tib-deep); }
.maps .m-meta { grid-column: 1 / -1; font-size: 10px; color: var(--ink-3); }

/* ── operatives ─────────────────────────────────────────────────────────── */

.panel__label.has-cameo { display: inline-flex; align-items: center; gap: 9px; }
.cameo {
  width: 26px; height: 26px; object-fit: contain; padding: 1px;
  border: 1px solid var(--line-2); background: var(--deck);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tib) 8%, transparent);
}

.table-wrap--ops { flex: none; max-height: 380px; }
table.ops td, table.ops th { padding: 8px 12px; }
table.ops .num { text-align: right; }
table.ops td.num { color: var(--ink); font-size: 11px; }
table.ops td.num.is-zero { color: var(--ink-3); }
table.ops .o-nick {
  color: var(--ink); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 22ch; display: inline-block;
}
table.ops td.battle { color: var(--tib); }
table.ops td.lobby  { color: var(--gdi); }
table.ops tbody tr:hover { background: var(--deck-2); }

/* ─────────────────────────────────────────────────────────────── factions */

.orders { padding: 34px var(--pad) 30px; border-bottom: 1px solid var(--line); }
.orders__head { max-width: 62ch; margin-bottom: 22px; }
.orders__head p { margin: 10px 0 0; font-size: 12px; color: var(--ink-2); }

.orders__grid {
  display: grid; grid-template-columns: repeat(9, 1fr); gap: 1px;
  margin: 0; padding: 0; list-style: none;
  background: var(--line); border: 1px solid var(--line);
}
.order {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 9px; padding: 18px 8px 16px; background: var(--deck);
  transition: background .2s;
}
.order:hover { background: var(--deck-2); }
.order b {
  font-family: var(--disp); font-size: 12px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink);
}
.order span:last-child { font-size: 10px; color: var(--ink-3); line-height: 1.4; }
.order__mark {
  width: 46px; height: 46px; object-fit: contain;
  opacity: .62; filter: saturate(.85); transition: opacity .2s, filter .2s;
}
.order:hover .order__mark { opacity: 1; filter: saturate(1.1); }
/* the two vector marks are single-colour paths — tint them via mask */
.order__mark--svg {
  background: currentColor;
  mask: var(--src) center / contain no-repeat;
  -webkit-mask: var(--src) center / contain no-repeat;
}
.order--gdi   .order__mark--svg { color: var(--gdi); }
.order--nod   .order__mark--svg { color: var(--nod); }
.order--scrin .order__mark--svg { color: var(--scrin); }

/* ───────────────────────────────────────────────────────────────── footer */

.foot { padding: 24px var(--pad) 40px; max-width: 92ch; }
.foot p { margin: 0; font-size: 11px; color: var(--ink-3); line-height: 1.7; }
.foot__thin { margin-top: 8px !important; color: #35414a; }

/* ───────────────────────────────────────────────────────────── responsive */

@media (max-width: 1240px) {
  .hero { grid-template-columns: minmax(0,1fr) 400px; }
  :root { --rail-l: 232px; --rail-r: 250px; }
}

@media (max-width: 1080px) {
  .hero { grid-template-columns: minmax(0,1fr); gap: 26px; }
  .hero__art { inset: 0 -18% auto auto; width: 76%; height: 100%; opacity: .16; }
  .theatre { max-width: 460px; margin-inline: auto; width: 100%; }
  .console { grid-template-columns: minmax(0,1fr) var(--rail-r); }
  .rail {
    grid-column: 1 / -1; border-right: 0; border-bottom: 1px solid var(--line);
    display: grid; grid-template-columns: 1fr 1fr;
  }
  .rail > .panel + .panel { border-top: 0; border-left: 1px solid var(--line); }
  .orders__grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 760px) {
  :root { --pad: 13px; }
  /* ── the header on a phone ──────────────────────────────────────────
     Four tabs plus a search field want about 840px of intrinsic width and
     there are 400. Left to wrap on its own it made a three-row header that
     pushed the board off the screen, so the rows are assigned deliberately:
     the brand and the page's pill share the top line, the tabs scroll
     sideways on their own line rather than wrapping into a block, and the
     search takes the full width beneath — where a thumb can actually hit
     it. Nothing is hidden; every tab stays reachable, which is the whole
     point of the change. */
  .topbar { height: auto; flex-wrap: wrap; gap: 8px; padding: 9px var(--pad); }
  .topbar__meta { gap: 10px; flex-wrap: wrap; order: 2; margin-left: auto; }

  .topnav {
    order: 3;
    flex: 1 0 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .topnav::-webkit-scrollbar { display: none; }
  .topnav__link { flex: none; }

  /* The 240px cap is a desktop measure — on a phone the field takes the
     row it was given, which is the difference between a comfortable tap
     target and a stub. */
  .find--top { order: 4; flex: 1 0 100%; max-width: none; }
  .find--top input { width: 100%; }

  /* The results list is positioned against the bar; full width under it is
     the only place it fits without covering the tabs you just used. */
  .findlist { left: var(--pad); right: var(--pad); width: auto; }
  .kv:nth-of-type(2) { display: none; }
  .hero { padding: 28px var(--pad) 26px; }
  .console { grid-template-columns: minmax(0,1fr); }
  .rail { grid-template-columns: 1fr; }
  .rail > .panel + .panel { border-left: 0; border-top: 1px solid var(--line); }
  .panel--stage, .panel--roster { border-right: 0; border-top: 1px solid var(--line); }
  /* the delta drops under its label rather than squeezing the row */
  .readout__row { grid-template-columns: 64px minmax(0, 1fr); row-gap: 2px; }
  .readout .delta { grid-column: 2; order: 4; }
  .theatre__cap { flex-direction: column; align-items: flex-start; gap: 4px; }
  /* drop the map column whole — col, header and cells, or the rest shifts */
  table.ledger col.c-map { width: 0; }
  table.ledger th:nth-child(3), table.ledger td:nth-child(3) { display: none; }
  table.ledger col.c-game { width: 40%; }
  table.ledger col.c-host { width: 26%; }
  .orders__grid { grid-template-columns: repeat(2, 1fr); }
  .console { grid-template-rows: none; }
  .table-wrap, .roster { flex: none; max-height: none; }
  .chart { flex: none; height: 132px; }
}

/* ────────────────────────────────────────────────────────── reduced motion */

@media (max-width: 900px) {
  .cc__head { flex-wrap: wrap; gap: 14px; padding: 16px var(--pad); }
  .cc__head::after { width: 86px; }
  .best { margin-left: 0; width: 100%; max-width: none; }
  .cc__note { max-width: none; }
  .cc__grid { grid-template-columns: minmax(0, 1fr); }
  #crew { max-width: 300px; }
  .dials { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .dial { max-width: 320px; margin-inline: auto; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .plot__sweep { display: none; }
  .cc__head::after { animation: none; }
  .star__dot { animation: none; fill-opacity: .55; }
}
