/* Warbirds.io — chunky slab UI to match the blocky world. */

:root {
  --crimson: #e84a4a;
  --cobalt: #4a7de8;
  --gold: #f4c542;
  --slab: rgba(24, 28, 38, 0.88);
  --slab-border: #0d0f15;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #87b7e0;
  font-family: "Courier New", ui-monospace, monospace;
  color: #eef2f6;
  /* No browser gestures over the playfield (double-tap zoom, overscroll). */
  touch-action: manipulation;
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
input { -webkit-user-select: text; user-select: text; }

#game { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

/* Help text swaps with the input mode (body.touch is set on coarse-pointer
   devices by main.js). */
body:not(.touch) .touch-only { display: none; }
body.touch .desktop-only { display: none; }

#ui { position: fixed; inset: 0; pointer-events: none; }
#ui button, #ui input { pointer-events: auto; }

.hidden { display: none !important; }

/* ---------- join screen ---------- */
#join-screen, #disconnect-screen {
  position: absolute; inset: 0;
  display: flex; justify-content: center;
  background: linear-gradient(rgba(10, 20, 40, 0.35), rgba(10, 20, 40, 0.65));
  pointer-events: auto;
  /* Scroll the overlay (sized to the visible viewport) whenever the card is
     taller than the window, so every option — plane stats, TAKE OFF, the
     controls help — stays reachable. margin:auto on the card centers it when
     it fits and lets the whole thing scroll when it doesn't (using auto
     margins rather than align-items:center, which would clip the top in an
     overflowing flex container). */
  height: 100dvh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.join-card {
  background: var(--slab);
  border: 4px solid var(--slab-border);
  box-shadow: 0 8px 0 var(--slab-border), inset 0 0 0 2px rgba(255,255,255,0.07);
  padding: 28px 36px;
  max-width: 720px;
  margin: auto;
  text-align: center;
}

.title {
  margin: 0 0 4px;
  font-size: 56px;
  letter-spacing: 6px;
  color: var(--gold);
  text-shadow: 4px 4px 0 #7a5a12, 8px 8px 0 rgba(0,0,0,0.35);
}
.title.small { font-size: 36px; }
.title-tld { color: #eef2f6; text-shadow: 4px 4px 0 #1b2330, 8px 8px 0 rgba(0,0,0,0.35); }

.tagline { margin: 0 0 22px; color: #9fb6cc; letter-spacing: 2px; }

/* ---------- theater switcher ---------- */
/* The doors between the air / naval / land / combined servers. Blocky chips in
   the same slab family as the unit tabs so they read as "part of the cabinet,"
   not a web nav bar. Populated + unhidden by setupModeRibbon (main.js) only when
   there's another theater to reach; a solo deploy never sees it. */
#mode-ribbon {
  display: flex; flex-wrap: wrap; gap: 6px;
  justify-content: center; align-items: stretch;
  /* Sits above the footer links; a hairline sets the switcher off from the
     lobby content so it reads as "leave for another theater," not more roster. */
  margin: 18px 0 2px; padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
#mode-ribbon.hidden { display: none; }
.mode-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; font-size: 12px; font-weight: bold; letter-spacing: 1px;
  color: #8d9aa8; background: #161a24;
  border: 3px solid var(--slab-border); text-decoration: none;
}
.mode-chip .mode-ic { font-size: 15px; line-height: 1; }
/* Links to the other theaters warm up on hover; the tap target is the whole chip. */
a.mode-chip:hover { color: #cfe0ee; background: #1b2130; border-color: #26324a; }
a.mode-chip:active { transform: translateY(2px); }
/* "You are here" — gold, inert, unmistakable. */
.mode-chip.current {
  color: var(--gold); background: #1b1f2b; border-color: var(--gold);
  cursor: default;
}

/* ---------- join footer / about link ---------- */
.join-footer { margin: 16px 0 0; }
.footer-link {
  color: #8d9aa8; font-size: 13px; letter-spacing: 2px;
  text-decoration: none; border-bottom: 2px solid transparent;
}
.footer-link:hover { color: var(--gold); border-bottom-color: var(--gold); }
/* The build stamp names the shell generation this device is actually running
   (kept in lockstep with sw.js CACHE_VERSION by the swcache guard) — the tell
   for "your phone is still flying last week's deploy". Quieter than the links:
   it's a gauge, not a destination. */
.build-stamp { color: #5b6673; font-size: 11px; letter-spacing: 2px; }
/* Stick telemetry overlay (?stickdebug=1 / triple-tap the build stamp): the
   flight recorder for "the stick does nothing on my phone" reports. Sits
   clear of the HUD corners; never eats a touch. */
#stick-debug {
  position: fixed; left: 8px; top: 64px; z-index: 40; margin: 0;
  font: 10px/1.5 ui-monospace, Menlo, monospace; letter-spacing: 0.5px;
  color: #9fe08f; background: rgba(10, 16, 24, 0.75);
  padding: 6px 8px; border: 1px solid #2a3a4c; border-radius: 4px;
  pointer-events: none; white-space: pre;
}
/* The leaderboard link is a button (opens an in-page overlay) but reads as the
   sibling anchors. */
button.footer-link {
  font: inherit; font-size: 13px; letter-spacing: 2px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 0; cursor: pointer;
}

/* ---------- leaderboard / hall of fame ---------- */
/* .lb-card is the overlay-card sizing shared by the daily-missions and
   flight-school pop-ups. The hall of fame itself is now a standalone page
   (/leaderboard, .lb-page) rendered on the .about-body site chrome. */
.lb-card { position: relative; max-width: 560px; width: min(560px, 94vw); }
#daily-close {
  position: absolute; top: 10px; right: 14px;
  background: none; border: 0; color: #8d9aa8;
  font-size: 30px; line-height: 1; cursor: pointer;
}
#daily-close:hover { color: var(--gold); }
.lb-cat { margin: 18px 0 0; text-align: left; }
.lb-cat h3 {
  margin: 0 0 6px; color: var(--gold);
  font-size: 15px; letter-spacing: 2px;
}
.lb-table { width: 100%; border-collapse: collapse; font-size: 15px; }
.lb-table th {
  color: #8d9aa8; text-align: left; font-weight: normal;
  padding: 3px 8px; border-bottom: 2px solid #2a3140; font-size: 12px;
}
.lb-table td { padding: 4px 8px; border-bottom: 1px solid rgba(255,255,255,0.05); }
.lb-table td.rank { color: #76838f; width: 2em; text-align: right; }
.lb-table td.val { text-align: right; color: #eef2f6; font-weight: bold; }
.lb-table td.num { text-align: right; color: #9fb6cc; }
.lb-table tr:nth-child(1) td.rank { color: var(--gold); }
.lb-name { color: #eef2f6; text-decoration: none; }
a.lb-name:hover { color: var(--gold); text-decoration: underline; }
.lb-title { color: #f4c542; font-size: 10px; letter-spacing: 0.5px; margin-left: 6px; }
.lb-empty { color: #76838f; font-style: italic; padding: 4px 8px; }
#leaderboard-status { margin: 18px 0 0; color: #8d9aa8; text-align: center; }

/* Standalone /leaderboard page: the boards tile into a responsive grid on the
   wide about-page column, instead of the single narrow stack the old overlay
   used. Each .lb-cat is a self-contained board so they flow cleanly. */
.lb-page #leaderboard-body {
  display: grid; gap: 10px 28px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  margin-top: 12px;
}
.lb-page .lb-cat { margin: 10px 0 0; }

/* Pilot profile page (roadmap #27). */
#pilot-body { text-align: left; margin-top: 6px; }
.pf-ace { color: var(--gold); font-weight: 700; letter-spacing: 1px; }
.pf-h { color: #cdd8e2; font-size: 13px; letter-spacing: 1px; text-transform: uppercase; margin: 22px 0 8px; }
.pf-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 10px; margin-top: 10px; }
.pf-tile {
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--slab-border);
  border-radius: 4px; padding: 10px 8px; text-align: center;
}
.pf-val { display: block; font-size: 22px; font-weight: 700; color: #eef2f6; }
.pf-label { display: block; font-size: 10px; letter-spacing: 0.6px; color: #8d9aa8; text-transform: uppercase; margin-top: 2px; }
.pf-ranks { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.pf-rank { background: rgba(212, 184, 74, 0.14); border: 1px solid rgba(212, 184, 74, 0.4); color: #f4c542; border-radius: 3px; padding: 3px 8px; font-size: 12px; }
.pf-rank em { color: #cdd8e2; font-style: normal; }
.pf-fav { margin-top: 14px; padding: 10px 12px; border-left: 3px solid var(--gold); background: rgba(255, 255, 255, 0.03); }
.pf-fav-name { display: block; font-weight: 700; color: #eef2f6; font-size: 16px; }
.pf-fav-sub { display: block; font-size: 11px; color: #8d9aa8; letter-spacing: 0.4px; }
.pf-ribbons { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 8px; }
.pf-ribbon {
  display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 3px;
  border: 1px solid var(--slab-border); background: rgba(255, 255, 255, 0.03); font-size: 12px;
}
.pf-ribbon.earned { border-color: rgba(212, 184, 74, 0.5); }
.pf-ribbon.locked { opacity: 0.72; }
.pf-ribbon-name { flex: 1; color: #dbe3ec; letter-spacing: 0.4px; }
.pf-ribbon.locked .pf-ribbon-name { color: #9aa7b3; }
.pf-ribbon-done { color: #f4c542; font-size: 11px; white-space: nowrap; }
.pf-ribbon-bar { flex: 0 0 54px; height: 6px; background: rgba(255, 255, 255, 0.08); border-radius: 3px; overflow: hidden; }
.pf-ribbon-bar span { display: block; height: 100%; background: #6a8ec8; }
.pf-ribbon-need { color: #8d9aa8; font-size: 11px; white-space: nowrap; }
.pf-heat-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.pf-heat-cap { color: #8d9aa8; font-size: 11px; font-style: italic; }
#pilot-status { margin: 18px 0 0; color: #8d9aa8; text-align: center; }

.join-row { display: flex; gap: 10px; justify-content: center; }

#name-input {
  font: inherit; font-size: 18px;
  padding: 10px 12px;
  background: #11141c; color: #eef2f6;
  border: 3px solid var(--slab-border);
  outline: none; width: 220px;
}
#name-input:focus { border-color: var(--gold); }

button {
  font: inherit; font-size: 18px; font-weight: bold;
  padding: 10px 22px;
  color: #1b1405;
  background: var(--gold);
  border: 3px solid var(--slab-border);
  box-shadow: 0 4px 0 var(--slab-border);
  cursor: pointer;
}
button:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--slab-border); }
button:disabled { background: #6b6b6b; cursor: default; }
/* The join/respawn CTA reads as an intentional locked state, not a blank grey
   box: a dimmed gold with legible dark label (U10). */
#play-btn:disabled { background: #b79433; color: #2a2205; opacity: 0.85; }

#join-status { min-height: 1.2em; color: #9fb6cc; margin: 14px 0 6px; }

button.ghost { background: #2a3140; color: #c9d6e4; }

/* ============ training / flight school ============ */
#training-screen {
  position: absolute; inset: 0; z-index: 30;
  display: flex; justify-content: center;
  background: linear-gradient(rgba(10, 20, 40, 0.55), rgba(10, 20, 40, 0.82));
  pointer-events: auto;
  height: 100dvh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#training-close {
  position: absolute; top: 10px; right: 14px;
  background: none; border: 0; color: #8d9aa8;
  font-size: 30px; line-height: 1; cursor: pointer;
}
#training-close:hover { color: var(--gold); }
#training-list { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
.train-item {
  display: block; width: 100%; text-align: left;
  font: inherit; cursor: pointer;
  padding: 12px 14px;
  color: #eef2f6; background: #1a2230;
  border: 3px solid var(--slab-border);
  box-shadow: 0 3px 0 var(--slab-border);
}
.train-item:hover { border-color: var(--gold); background: #202a3b; }
.train-item:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--slab-border); }
.train-item .ti-name {
  display: block; color: var(--gold);
  font-size: 16px; font-weight: bold; letter-spacing: 1px;
}
.train-item .ti-blurb { display: block; color: #9fb6cc; font-size: 13px; margin-top: 3px; }

/* The way out of flight school and back to the war — a persistent top-left
   corner button so a player who wanders in never has to scroll to find the
   door. Shown only when the training server knows where the main game lives
   (see setupTraining). */
#training-home {
  position: absolute; top: 12px; left: 14px; z-index: 2;
  font-size: 14px; padding: 8px 14px;
}

/* In-game: one-time briefing card. */
#training-brief {
  position: absolute; inset: 0; z-index: 25;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10, 20, 40, 0.55);
  pointer-events: auto;
}
.brief-card {
  max-width: 460px; width: min(460px, 92vw);
  background: var(--slab); border: 3px solid var(--slab-border);
  box-shadow: 0 6px 0 var(--slab-border);
  padding: 20px 22px; text-align: left;
}
.brief-card h2 { margin: 0 0 8px; color: var(--gold); letter-spacing: 1px; font-size: 20px; }
.brief-card p { margin: 0 0 10px; color: #d7e2ee; font-size: 14px; line-height: 1.5; }
#brief-tips { margin: 0 0 16px; padding-left: 18px; color: #9fb6cc; font-size: 13px; }
#brief-tips li { margin: 3px 0; }
.brief-actions { display: flex; gap: 10px; }
.brief-actions button { font-size: 15px; padding: 8px 16px; }

/* In-game: persistent corner control to leave the drill. */
#training-exit {
  position: absolute; top: 8px; left: 8px; z-index: 12;
  font-size: 12px; font-weight: bold; padding: 6px 10px;
  background: #2a3140; color: #c9d6e4;
  border: 2px solid var(--slab-border); box-shadow: 0 2px 0 var(--slab-border);
  pointer-events: auto;
}
#training-exit:hover { color: var(--gold); }

/* Unit picker: a row of category tabs over the stat cards for the active tab. */
#unit-tabs {
  display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px;
  border-bottom: 3px solid var(--slab-border);
}
.unit-tab {
  font-size: 12px; font-weight: bold; letter-spacing: 1px;
  padding: 7px 12px; margin-bottom: -3px;
  color: #8d9aa8; background: #161a24;
  border: 3px solid var(--slab-border); box-shadow: none;
}
.unit-tab:active { transform: none; }
.unit-tab.active { color: var(--gold); background: #1b1f2b; border-bottom-color: #1b1f2b; }

#unit-select { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.plane-card {
  /* flex-basis sized to the card name so five cards fit a desktop row without
     overflowing; wraps to a second row on narrower windows instead of
     bleeding off the side. */
  flex: 1 1 116px; min-width: 0; padding: 10px 8px;
  background: #11141c; border: 3px solid var(--slab-border);
  cursor: pointer; text-align: left; font-size: 12px;
  color: #b7c6d4;
}
.plane-card.selected { border-color: var(--gold); background: #1b1f2b; }
/* Career-locked hull: dimmed, not selectable, with a requirement badge. */
.plane-card.locked { cursor: not-allowed; opacity: 0.5; position: relative; }
.plane-card.locked:hover { border-color: var(--slab-border); }
.plane-card .lock-badge {
  display: block; margin-top: 6px; padding: 2px 5px;
  background: #2a1d12; border: 1px solid #6b4a23; color: #f0b35a;
  font-size: 10px; letter-spacing: 0.5px; text-align: center; border-radius: 2px;
}
/* PAINT SHOP row (roadmap #25): earnable cosmetic scheme swatches. */
#paint-row {
  display: flex; align-items: center; gap: 10px;
  margin: 8px 0 2px; flex-wrap: wrap;
}
#paint-row.hidden { display: none; }
.paint-label {
  font-size: 11px; letter-spacing: 1px; color: #76838f; font-weight: 600;
}
.paint-swatches { display: flex; gap: 7px; flex-wrap: wrap; }
.paint-swatch {
  width: 30px; height: 30px; border-radius: 4px; cursor: pointer;
  border: 2px solid var(--slab-border); padding: 0;
  font-size: 12px; line-height: 1; color: #e7ecf2;
  display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.paint-swatch.equipped { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(212, 184, 74, 0.4); }
.paint-swatch.locked { cursor: not-allowed; opacity: 0.5; }
.paint-swatch.locked:hover { border-color: var(--slab-border); }

.plane-card h3 {
  margin: 0 0 4px; font-size: 14px; color: #eef2f6; letter-spacing: 0.5px;
  /* Names must never wrap mid-word ("Sparrowha/wk"): one line, ellipsize as
     a last resort. Type is sized so the longest name fits a 5-across card. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.plane-card .stat { display: flex; align-items: center; gap: 6px; margin-top: 3px; }
.plane-card .stat label { width: 34px; color: #76838f; font-size: 10px; }
.plane-card .stat .bar { height: 7px; }
.plane-card .role { color: #8d9aa8; font-style: italic; min-height: 2.4em; display: block; margin-bottom: 4px; }

#device-hint { color: #6f8fae; font-size: 12px; margin-top: 4px; }

.controls-help {
  margin: 14px 0; padding: 10px;
  background: rgba(0,0,0,0.3);
  border: 2px solid var(--slab-border);
  font-size: 14px; line-height: 1.8;
}

.blurb { font-size: 13px; color: #b7c6d4; line-height: 1.5; margin-bottom: 0; }
.gold { color: var(--gold); font-weight: bold; }

/* ---------- hud ---------- */
#top-bar {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 14px; align-items: center;
  background: var(--slab);
  border: 3px solid var(--slab-border);
  padding: 6px 14px;
  font-size: 18px; font-weight: bold;
  /* left:50% + translateX centring shrink-fits an abs-pos box to the space
     RIGHT of centre — on a 667px phone that's 334px, and the score wrapped
     into a two-line tower that crushed the banner under it. Size to content
     instead; the viewport cap keeps a monster score string on screen. */
  width: max-content; max-width: 96vw;
}

.team-chip.crimson { color: var(--crimson); }
.team-chip.cobalt { color: var(--cobalt); }
#timer { color: #eef2f6; }
#zone-state { color: #8d9aa8; letter-spacing: 1px; font-size: 14px; }
#zone-state.crimson { color: var(--crimson); }
#zone-state.cobalt { color: var(--cobalt); }
#zone-state.contested { color: var(--gold); }

#crosshair {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  font-size: 26px; color: rgba(255, 255, 255, 0.85);
  text-shadow: 0 0 4px #000;
}
#crosshair.hitmarker { color: var(--gold); }

/* Tank main-gun reload readout, just under the crosshair. */
#reload-indicator {
  position: absolute; left: 50%; top: calc(50% + 26px);
  transform: translateX(-50%);
  font-size: 13px; font-weight: 600; letter-spacing: 0.06em;
  white-space: nowrap; text-shadow: 0 0 4px #000; pointer-events: none;
}
#reload-indicator.loading { color: #ffcf6b; }
#reload-indicator.ready { color: #8ef0a0; }

/* Naval turret readout ("GUNS 4/6"), under the reload line. Amber while part
   of the battery is masked, so the broadside nudge reads at a glance. */
#turret-status {
  position: absolute; left: 50%; top: calc(50% + 44px);
  transform: translateX(-50%);
  font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
  color: #9fe7b0; white-space: nowrap; text-shadow: 0 0 4px #000;
  pointer-events: none;
}
#turret-status.partial { color: #ffcf6b; }

#aim-cursor {
  position: absolute; left: 50%; top: 50%;
  font-size: 30px; color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 0 5px #000;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* Off-screen enemy edge markers (touch only — desktop has freelook + a big
   minimap). Positioned/rotated per frame from JS; hidden on non-touch. */
.edge-marker {
  position: absolute; left: 0; top: 0;
  font-size: 26px; line-height: 1;
  pointer-events: none; z-index: 6;
  text-shadow: 0 0 3px #000, 0 0 6px #000, 0 0 2px #000;
}
.edge-marker.crimson { color: var(--crimson); }
.edge-marker.cobalt { color: var(--cobalt); }
body:not(.touch) .edge-marker { display: none; }
/* Hull-theater target markers (spotted enemy tanks/ships) show on every
   platform — unlike a bandit filling the sky, a spotted hull is a handful of
   pixels on the terrain and needs the callout even on a big screen. */
body:not(.touch) .edge-marker.hull { display: block; }

#lead-pip {
  position: absolute; left: -100px; top: -100px;
  font-size: 20px; color: var(--gold);
  text-shadow: 0 0 4px #000;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* Level-bombing pipper (Leviathan only): a ring marking the predicted bomb
   impact point, with a center cross. Cyan to read distinctly from the gold
   gunnery lead pip. */
#bombsight {
  position: absolute; left: -100px; top: -100px;
  width: 26px; height: 26px;
  transform: translate(-50%, -50%);
  border: 2px solid #5fe3ff;
  border-radius: 50%;
  box-shadow: 0 0 4px #000, inset 0 0 3px rgba(0, 0, 0, 0.6);
  pointer-events: none;
}
#bombsight i {
  position: absolute; left: 50%; top: 50%;
  width: 2px; height: 2px;
  background: #5fe3ff;
  box-shadow:
    0 0 3px #000,
    -9px 0 0 -0px #5fe3ff, 9px 0 0 0 #5fe3ff,
    0 -9px 0 0 #5fe3ff, 0 9px 0 0 #5fe3ff;
  transform: translate(-50%, -50%);
}

/* Jets-era seeker ring (docs/early-jets-era.md): the boresight circle at
   screen center. Caged it's a faint ghost; tracking it turns amber and closes
   toward boresight as the lock winds up; full lock burns solid red. The chips
   under it count rails (▲) and flares (✺). */
#seeker {
  position: absolute; left: 50%; top: 50%;
  width: 0; height: 0;
  pointer-events: none;
}
#seeker .seeker-ring {
  position: absolute; left: 0; top: 0;
  width: 74px; height: 74px;
  transform: translate(-50%, -50%) scale(1.5);
  border: 2px dashed rgba(200, 220, 240, 0.28);
  border-radius: 50%;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.6);
}
#seeker.seeker-track .seeker-ring {
  border-style: solid;
  border-color: #ffd76b;
  animation: seeker-blink 0.32s step-end infinite;
}
#seeker.seeker-lock .seeker-ring {
  border-style: solid;
  border-color: #ff5a5a;
  box-shadow: 0 0 10px rgba(255, 90, 90, 0.55);
  animation: none;
}
@keyframes seeker-blink {
  50% { opacity: 0.35; }
}
#seeker .seeker-label {
  position: absolute; left: 0; top: 46px;
  transform: translateX(-50%);
  font-weight: bold; letter-spacing: 1px; font-size: 12px;
  color: #ffd76b; text-shadow: 0 0 4px #000;
  white-space: nowrap;
}
#seeker.seeker-lock .seeker-label { color: #ff7b7b; }
#seeker .seeker-chips {
  position: absolute; left: 0; top: 62px;
  transform: translateX(-50%);
  font-size: 12px; letter-spacing: 1px;
  color: #bcd2e8; text-shadow: 0 0 4px #000;
  white-space: nowrap;
}

#protect-banner, #warning-banner {
  position: absolute; left: 50%; transform: translateX(-50%);
  font-weight: bold; letter-spacing: 2px;
  padding: 4px 14px;
  border: 2px solid var(--slab-border);
  /* Same shrink-to-fit trap as #top-bar: the long warnings ("HULL BLOCKED —
     BACK UP…") were one bad break from wrapping on narrow phones. */
  width: max-content; max-width: 96vw;
}
#protect-banner { top: 64px; background: rgba(74, 125, 232, 0.25); color: #bcd2ff; }
#warning-banner { top: 64px; background: rgba(232, 74, 74, 0.3); color: #ffd2d2; }
/* Ground-proximity PULL UP: a brighter, pulsing red so it reads as urgent. */
#warning-banner.danger {
  background: rgba(232, 40, 40, 0.85); color: #fff;
  border-color: #ff5a5a;
  animation: warn-pulse 0.55s ease-in-out infinite;
}
@keyframes warn-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 rgba(255, 90, 90, 0); }
  50% { opacity: 0.7; box-shadow: 0 0 16px rgba(255, 90, 90, 0.7); }
}

#flight-data {
  position: absolute; left: 16px; bottom: 16px;
  background: var(--slab); border: 3px solid var(--slab-border);
  padding: 10px 14px; display: flex; flex-direction: column; gap: 6px;
  min-width: 170px;
}
.gauge { display: flex; align-items: baseline; gap: 8px; font-size: 16px; }
.gauge label { color: #8d9aa8; font-size: 12px; width: 32px; }
.gauge span { font-size: 22px; font-weight: bold; min-width: 64px; text-align: right; }
.gauge small { color: #8d9aa8; }

.bar {
  flex: 1; height: 12px; background: #11141c;
  border: 2px solid var(--slab-border); position: relative;
}
.bar .fill { height: 100%; width: 50%; background: var(--gold); }
.bar.big { height: 18px; }

#hp-wrap {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 22px; width: 280px;
}
#hp-fill { background: #62d655; transition: width 0.15s; }
#hp-fill.hurt { background: #e8a23a; }
#hp-fill.critical { background: var(--crimson); }

/* Localized-damage subsystem panel: compact bars above the health bar. */
#subsys {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 46px;
  display: flex; gap: 10px; padding: 4px 8px;
  background: var(--slab); border: 2px solid var(--slab-border);
}
.subsys-cell { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.subsys-cell label { color: #8d9aa8; font-size: 9px; letter-spacing: 0.5px; }
.subsys-bar { width: 48px; height: 5px; background: #11141c; border: 1px solid var(--slab-border); overflow: hidden; }
.subsys-fill { height: 100%; width: 100%; background: #62d655; transition: width 0.2s; }
.subsys-fill.hurt { background: #e8a23a; }
.subsys-fill.crit { background: var(--crimson); }
#pilot-veil {
  position: fixed; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.3s; z-index: 7;
  background: radial-gradient(circle at 50% 50%, rgba(40,0,0,0) 40%, rgba(70,0,0,0.85) 98%);
}

#minimap {
  position: absolute; right: 16px; bottom: 16px;
  border: 3px solid var(--slab-border);
  background: #123;
  image-rendering: pixelated;
}
/* ---------- battleship plot table (big guns targeting) ---------- */
/* The whole-screen plotting surface that replaces the cramped corner chart
   while manning a main battery. A backdrop darkens the 3D world for clarity;
   only the canvas and buttons take pointer events, so the bail control and
   touch zones underneath stay reachable. */
#plot-table {
  position: absolute; inset: 0; z-index: 6;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(6, 10, 16, 0.5), rgba(4, 7, 12, 0.85));
}
#plot-table.hidden { display: none; }
/* While manning the big guns the corner HUD and touch flight cluster give way
   to the plot table. */
body.manning-main #minimap,
body.manning-main #touch-controls { display: none; }

/* The status banner floats over the top of the chart; the action bar floats
   over the bottom. Both ride inside the frame so the chart itself fills the
   full height of the screen. */
#plot-banner {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  z-index: 2; pointer-events: none;
  font-size: 15px; letter-spacing: 0.08em; text-align: center; white-space: nowrap;
  color: var(--gold);
  background: rgba(8, 12, 18, 0.86);
  border: 2px solid var(--slab-border); border-radius: 6px;
  padding: 7px 16px; max-width: 94%;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
}
#plot-banner.ready { color: #7bff8a; }

/* Fire-control solution readout: a brass-cornered plotting slip pinned to the
   top-right of the chart. It lists the data points the ballistic computer
   collected for the firing solution once the solve timer expires. */
#plot-readout {
  position: absolute; top: 14px; right: 14px; z-index: 2; pointer-events: none;
  min-width: 188px; max-width: 38%;
  font-size: 12px; letter-spacing: 0.06em; line-height: normal; text-align: left;
  color: #f0e4c8;
  background: linear-gradient(170deg, rgba(20, 16, 10, 0.93), rgba(10, 8, 5, 0.93));
  border: 2px solid #7a5a32; border-radius: 6px;
  box-shadow: 0 0 0 2px #2c2014, 0 6px 20px rgba(0, 0, 0, 0.55);
  padding: 8px 10px 9px;
}
#plot-readout.hidden { display: none; }
#plot-readout-head {
  font-weight: bold; letter-spacing: 0.16em; font-size: 11px;
  color: #7bff8a; text-align: center;
  padding-bottom: 6px; margin-bottom: 6px;
  border-bottom: 1px solid rgba(122, 90, 50, 0.7);
}
#plot-readout-rows { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; }
#plot-readout-rows dt { color: #b9a778; white-space: nowrap; }
#plot-readout-rows dd {
  margin: 0; text-align: right; font-weight: bold; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
#plot-readout-rows dd.hot { color: #ffd76b; }       /* dropped-charge / plunging fire */
#plot-readout-rows dd.good { color: #7bff8a; }      /* spotter-tightened pattern */

#plot-frame { position: relative; pointer-events: none; line-height: 0; }
/* The chart reads as a sheet of nautical paper in a brass-and-leather mount:
   an aged-brass inner edge, a dark leather surround, and a warm inner glow that
   ages the corners of the parchment. */
#plot-canvas {
  pointer-events: auto; touch-action: none; cursor: crosshair;
  border: 3px solid #7a5a32;
  background: #e7d9bd;
  box-shadow:
    0 0 0 3px #2c2014,
    0 14px 36px rgba(0, 0, 0, 0.6),
    inset 0 0 64px rgba(120, 90, 50, 0.22);
}

/* Magnifier loupe: rides above the dragging finger so the aim point is never
   hidden under the thumb. A brass-rimmed lens over the paper chart. */
#plot-loupe {
  position: fixed; z-index: 7; pointer-events: none;
  width: 132px; height: 132px;
  border: 3px solid #7a5a32; border-radius: 50%;
  background: #e7d9bd;
  box-shadow:
    0 0 0 2px #2c2014,
    0 6px 16px rgba(0, 0, 0, 0.6),
    inset 0 0 18px rgba(90, 64, 32, 0.4);
}
#plot-loupe.hidden { display: none; }

#plot-bar {
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%);
  z-index: 2; pointer-events: none;
  display: flex; align-items: center; gap: 12px; max-width: 94%; flex-wrap: wrap;
  justify-content: center; line-height: normal;
}
#plot-bar button {
  pointer-events: auto;
  font: inherit; font-weight: bold; letter-spacing: 1px;
  border: 3px solid var(--slab-border);
  box-shadow: 0 4px 0 var(--slab-border);
  padding: 12px 22px; border-radius: 8px;
  background: rgba(42, 49, 64, 0.92); color: #c9d6e4;
}
#plot-bar button:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--slab-border); }
#plot-reaim { color: var(--gold); }
#plot-primary { min-width: 200px; background: var(--gold); color: #1b1405; }
#plot-primary:disabled {
  background: rgba(42, 49, 64, 0.7); color: #6b7686;
  box-shadow: 0 4px 0 var(--slab-border); transform: none;
}
#plot-primary.set { background: #7bff8a; color: #06210b; }
#plot-primary.fire {
  background: var(--crimson); color: #ffe9e9;
  animation: plot-fire-pulse 0.9s ease-in-out infinite;
}
@keyframes plot-fire-pulse {
  0%, 100% { box-shadow: 0 4px 0 var(--slab-border), 0 0 0 0 rgba(232, 74, 74, 0); }
  50%      { box-shadow: 0 4px 0 var(--slab-border), 0 0 22px 5px rgba(232, 74, 74, 0.6); }
}

#killfeed {
  position: absolute; top: 64px; right: 16px;
  display: flex; flex-direction: column; gap: 4px; align-items: flex-end;
  font-size: 14px;
}
.feed-line {
  background: var(--slab); border: 2px solid var(--slab-border);
  padding: 3px 10px; opacity: 1; transition: opacity 0.6s;
}
.feed-line .crimson { color: var(--crimson); font-weight: bold; }
.feed-line .cobalt { color: var(--cobalt); font-weight: bold; }
.feed-line.fade { opacity: 0; }
/* Chat shares this stream with the combat log. A subtle comms accent — a soft
   cyan left rule, a cooler translucent slab, and a 💬 tag — sets talk apart
   from kills without shouting. */
.feed-line.chat {
  border-left: 3px solid #57c7d4;
  background: linear-gradient(90deg, rgba(87, 199, 212, 0.16), rgba(24, 28, 38, 0.88) 60%);
  font-style: italic;
}
.feed-line.chat .chat-tag { font-style: normal; margin-right: 5px; opacity: 0.8; font-size: 12px; }
/* While composing, resurface the recent thread even after it's faded. */
body.chatting .feed-line.chat { opacity: 1; }
/* Spawn tactical picture (roadmap #55): live map + heading rose. */
#spawn-tac {
  display: flex; gap: 14px; align-items: center; justify-content: center;
  margin: 10px 0 4px;
}
#spawn-tac.hidden { display: none; }
#spawn-map { border: 2px solid var(--slab-border); background: #0d111a; }
#spawn-rose { display: flex; flex-direction: column; align-items: center; gap: 6px; }
#spawn-rose .rose-label { color: #76838f; font-size: 10px; letter-spacing: 2px; }
#spawn-rose .rose-grid { display: grid; grid-template-columns: repeat(3, 44px); gap: 4px; }
#spawn-rose button {
  height: 44px; background: #11141c; border: 2px solid var(--slab-border);
  color: #b7c6d4; font-size: 15px; cursor: pointer;
}
#spawn-rose button[data-d="-1"] { font-size: 9px; letter-spacing: 1px; }
#spawn-rose button.sel { border-color: var(--gold); color: var(--gold); background: #1b1f2b; }
@media (max-width: 700px) {
  #spawn-map { width: 150px; height: 150px; }
  #spawn-rose .rose-grid { grid-template-columns: repeat(3, 40px); }
  #spawn-rose button { height: 40px; }
}

/* OVERTIME chip (roadmap #16): pulsing gold tag under the score bar. */
#overtime-chip {
  position: absolute; left: 50%; top: 52px; transform: translateX(-50%);
  background: var(--slab); border: 2px solid var(--gold); color: var(--gold);
  padding: 2px 10px; font-size: 12px; letter-spacing: 2px;
  pointer-events: none; animation: ot-pulse 2s ease-in-out infinite;
}
#overtime-chip.hidden { display: none; }
@keyframes ot-pulse {
  0%, 100% { opacity: 0.65; }
  50% { opacity: 1; }
}

/* Comms wheel (roadmap #17): radial quick-chat, centered on screen. */
#comms-wheel {
  position: absolute; inset: 0; pointer-events: none; z-index: 40;
}
#comms-wheel.hidden { display: none; }
#comms-wheel .cw-slice {
  position: absolute; transform: translate(-50%, -50%);
  background: var(--slab); border: 2px solid var(--slab-border);
  color: #b7c6d4; padding: 6px 12px; font-size: 13px; letter-spacing: 1px;
  white-space: nowrap;
}
#comms-wheel .cw-slice.hover { border-color: var(--gold); color: var(--gold); background: #1b1f2b; }
#comms-wheel .cw-hub {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  color: #76838f; font-size: 10px; letter-spacing: 2px;
}
/* Cinematic kill-confirm banner: silhouette + "SPARROWHAWK ✈ victim". */
#kill-banner {
  position: absolute; left: 50%; top: 34%;
  transform: translate(-50%, -8px); opacity: 0;
  display: flex; align-items: center; gap: 10px;
  background: var(--slab); border: 2px solid var(--gold);
  padding: 6px 14px; color: var(--gold);
  font-size: 16px; letter-spacing: 1px; white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.08s ease-out, transform 0.08s ease-out;
}
#kill-banner.show { opacity: 1; transform: translate(-50%, 0); }
#kill-banner canvas { display: block; }

/* Bonus tag on a feed line (e.g. WINGMAN ×1.2). */
.feed-badge {
  color: var(--gold); font-size: 11px; letter-spacing: 0.5px;
  border: 1px solid #6b5a23; padding: 0 4px; margin-left: 4px;
}
/* Strafing a bailed pilot's chute (roadmap #1) is branded in red. */
.feed-badge.dishonor { color: #ff6b5a; border-color: #7a3028; }

/* Only the composer lives here now — the chat history rides the top-right feed
   (see .feed-line.chat). Anchored bottom-left, within thumb reach on touch. */
#chat {
  position: absolute; left: 16px; bottom: 148px;
  display: flex; flex-direction: column; gap: 4px;
  max-width: min(440px, 44vw);
  font-size: 14px;
}
#chat-entry {
  display: flex; align-items: center; gap: 6px;
  background: var(--slab); border: 2px solid var(--gold);
  padding: 4px 10px;
}
.chat-prompt { color: var(--gold); font-weight: bold; }
#chat-input {
  font: inherit; font-size: 14px;
  flex: 1; min-width: 280px;
  background: transparent; border: none; outline: none;
  color: #eef2f6;
}
#chat-input::placeholder { color: #76838f; }

/* The top-right text feed is a desktop luxury: on anything smaller than a
   desktop window the whole scrolling column — kills, spotting, capture calls
   and chatter — eats screen the fight can't spare, so drop the entire feed and
   the chat composer with it. The important beats still land as centered banners
   (#message) and audio. Breakpoint matches the join card's small-screen arm
   (phones both ways, tablets, cramped windows). */
@media (max-width: 760px), (max-height: 560px) {
  #chat,
  #killfeed { display: none; }
}

#message {
  position: absolute; left: 50%; top: 30%;
  transform: translate(-50%, -50%);
  font-size: 30px; font-weight: bold; letter-spacing: 3px;
  text-shadow: 3px 3px 0 #000;
  text-align: center;
}

/* Stream "now playing" chip: shown only in director mode, names the current
   procedural soundtrack theme with a little animated equalizer. */
#now-playing {
  position: absolute; left: 16px; bottom: 16px;
  display: flex; align-items: center; gap: 10px;
  background: var(--slab); border: 2px solid var(--slab-border);
  padding: 6px 12px; font-size: 13px; letter-spacing: 1px;
  box-shadow: 0 3px 0 var(--slab-border);
}
#now-playing.hidden { display: none; }
.np-eq { display: flex; align-items: flex-end; gap: 2px; height: 14px; width: 16px; }
.np-eq span {
  flex: 1; background: var(--gold); height: 100%;
  transform-origin: bottom; animation: np-bounce 0.9s ease-in-out infinite;
}
.np-eq span:nth-child(2) { animation-delay: 0.3s; }
.np-eq span:nth-child(3) { animation-delay: 0.6s; }
@keyframes np-bounce {
  0%, 100% { transform: scaleY(0.25); }
  50% { transform: scaleY(1); }
}
.np-text { display: flex; flex-direction: column; line-height: 1.25; }
.np-label { color: #8d9aa8; font-size: 9px; letter-spacing: 2px; }
.np-name { color: var(--gold); font-weight: bold; }
#now-playing.np-bump { animation: np-flash 0.5s ease-out; }
@keyframes np-flash {
  0% { border-color: var(--gold); box-shadow: 0 0 12px rgba(244, 197, 66, 0.7), 0 3px 0 var(--slab-border); }
  100% { border-color: var(--slab-border); box-shadow: 0 3px 0 var(--slab-border); }
}

/* Killcam badge: persistent for the whole death replay so it plainly reads as
   a killcam and keeps the killer's name on screen (see hud.setKillcamTag). */
#killcam-tag {
  position: absolute; left: 50%; top: 12%;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: 14px;
  pointer-events: none; white-space: nowrap;
  animation: kc-in 0.35s ease-out;
}
#killcam-tag.hidden { display: none; }
.kc-rule {
  width: 90px; height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.kc-rule:last-child { transform: scaleX(-1); }
.kc-body { display: flex; flex-direction: column; align-items: center; line-height: 1.2; }
/* Death-recap coach line under the killer's name (roadmap #54). */
.kc-coach {
  margin-top: 6px; max-width: 480px; white-space: normal; text-align: center;
  color: #d8c184; font-size: 13px; font-style: italic;
}
.kc-coach.hidden { display: none; }
/* Same coach line on the respawn card, for crash deaths with no killcam. */
#death-coach {
  margin: 6px auto 0; max-width: 520px; text-align: center;
  color: #d8c184; font-size: 13px; font-style: italic;
}
#death-coach.hidden { display: none; }
.kc-label {
  color: var(--gold); font-weight: bold;
  font-size: 22px; letter-spacing: 6px;
  text-shadow: 2px 2px 0 #000;
}
.kc-by {
  color: #8d9aa8; font-size: 10px; letter-spacing: 3px;
  text-transform: uppercase; margin-top: 2px;
}
.kc-name {
  color: #fff; font-weight: bold;
  font-size: 17px; letter-spacing: 2px;
  text-shadow: 2px 2px 0 #000;
}
/* Skip affordance: quiet, under the coach line, fading in a beat late so the
   badge itself lands first. */
.kc-skip {
  margin-top: 8px; color: #76838f; font-size: 10px; letter-spacing: 3px;
  text-transform: uppercase; text-shadow: 1px 1px 0 #000;
  opacity: 0; animation: kc-skip-in 0.5s ease-out 1.2s forwards;
}
@keyframes kc-skip-in {
  to { opacity: 0.85; }
}
@keyframes kc-in {
  0% { opacity: 0; transform: translateX(-50%) translateY(-8px); }
  100% { opacity: 1; transform: translateX(-50%) translateY(0); }
}
body.touch .kc-label { font-size: 17px; letter-spacing: 4px; }
body.touch .kc-rule { width: 50px; }


/* ---------- respawn screen ----------
   The respawn screen IS the join screen (#join-screen), shown verbatim — same
   masthead, unit picker, deck choice, daily missions and controls. There's no
   death banner; the killcam replay is what names who got you. The `respawning`
   class is only an internal marker (so a per-frame setRespawn(false) won't hide
   the first-join screen before you've spawned), with no visual effect. */

/* LAUNCH FROM base / carrier deck — sits under the unit cards. */
#respawn-deck { margin-top: 4px; margin-bottom: 16px; }
.gs-label {
  width: 100%; font-size: 11px; letter-spacing: 2px; color: #8d9aa8;
  margin-bottom: 6px;
}
.gun-chip {
  padding: 5px 10px; font-size: 12px; letter-spacing: 1px;
  background: #2a3140; color: #c9d6e4;
  border: 2px solid var(--slab-border);
  box-shadow: 0 2px 0 var(--slab-border);
}
.gun-chip.picked { background: var(--gold); color: #1a1408; border-color: var(--gold); }
.gun-chip:disabled { background: #20242e; color: #5a6473; }
.gun-chip.destroyed { text-decoration: line-through; }

/* Daily missions: shown on both the join and respawn screens. */
#respawn-daily { margin: 16px auto 0; max-width: 360px; }
#respawn-daily:empty { display: none; }
.daily-head {
  font-size: 11px; letter-spacing: 2px; color: #8d9aa8; text-align: left;
}
.daily-row { margin-top: 8px; text-align: left; }
.daily-row .daily-desc {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 12px; color: #c9d6e4;
}
.daily-row .daily-have { color: var(--gold); font-variant-numeric: tabular-nums; }
.daily-bar {
  margin-top: 4px; height: 6px;
  background: #20242e; border: 1px solid var(--slab-border);
}
.daily-fill { height: 100%; background: var(--gold); transition: width 0.3s; }
.daily-row.done .daily-desc { color: #7bff8a; }
.daily-row.done .daily-have::before { content: "✓ "; }
.daily-row.done .daily-fill { background: #4cae5a; }

#daily-screen {
  position: absolute; inset: 0; z-index: 30;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6, 10, 16, 0.72);
}
#daily-body { margin: 8px 0; }
#daily-body .daily-row { margin-top: 12px; }

/* ============ settings > keybindings ============ */
/* Same modal chrome as the daily/flight-school overlays, but this card is a bit
   wider and scrolls internally: the full control list is long, and TAKE OFF
   should never be more than a DONE-click away. */
#settings-screen {
  position: absolute; inset: 0; z-index: 30;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6, 10, 16, 0.78);
  pointer-events: auto;
}
.settings-card {
  max-width: 620px; width: min(620px, 96vw);
  max-height: 92dvh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  text-align: left;
}
#settings-close {
  position: absolute; top: 10px; right: 14px;
  background: none; border: 0; color: #8d9aa8;
  font-size: 30px; line-height: 1; cursor: pointer;
}
#settings-close:hover { color: var(--gold); }
.settings-card .title, .settings-card .tagline { text-align: center; }

#keybind-list { margin-top: 14px; }
.kb-group-head {
  margin: 16px 0 6px; padding-bottom: 3px;
  color: var(--gold); font-size: 13px; letter-spacing: 2px;
  border-bottom: 2px solid #2a3140;
}
.kb-group-head:first-child { margin-top: 4px; }

/* One control per row: name on the left, its bound key(s) + editing controls on
   the right. Reuses the chunky-slab language — dark panel, block border. */
.kb-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px; margin-top: 4px;
  background: rgba(255,255,255,0.03);
  border: 2px solid var(--slab-border);
}
.kb-row.kb-conflict { border-color: var(--crimson); }
.kb-name { flex: 1 1 auto; font-size: 14px; color: #dbe3ec; }
.kb-hold { color: #8d9aa8; font-size: 11px; letter-spacing: 1px; }
.kb-binds { display: flex; flex-wrap: wrap; gap: 5px; justify-content: flex-end; }

/* A single bound key. Reads as a keycap; clicking it re-records that key. */
.kb-chip {
  font: inherit; font-size: 13px; font-weight: bold;
  min-width: 34px; padding: 4px 9px;
  color: #eef2f6; background: #11141c;
  border: 2px solid #3a4150;
  box-shadow: 0 2px 0 var(--slab-border);
  cursor: pointer;
}
.kb-chip:hover { border-color: var(--gold); color: var(--gold); }
.kb-chip:active { transform: translateY(2px); box-shadow: 0 0 0 var(--slab-border); }
.kb-chip.kb-empty { color: #76838f; font-style: italic; font-weight: normal; }
/* Listening for the next keypress — pulses gold so it's unmistakable which key
   you're about to set. */
.kb-chip.kb-listening {
  color: #1b1405; background: var(--gold); border-color: var(--gold);
  animation: kbPulse 0.9s ease-in-out infinite;
}
@keyframes kbPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }

/* "+ add another key" and the per-row reset — quiet until hovered. */
.kb-add, .kb-reset-one {
  font: inherit; font-size: 13px; font-weight: bold;
  padding: 4px 8px; min-width: 30px;
  color: #9fb2c8; background: #2a3140;
  border: 2px solid var(--slab-border); box-shadow: none;
  cursor: pointer;
}
.kb-add:hover, .kb-reset-one:hover { color: var(--gold); }
.kb-add:active, .kb-reset-one:active { transform: translateY(2px); }

.kb-note {
  margin: 12px 0 4px; padding: 8px 10px;
  background: rgba(0,0,0,0.3); border: 2px solid var(--slab-border);
  font-size: 12px; line-height: 1.6; color: #b7c6d4;
}
.kb-note b { color: #eef4fa; }
.kb-note.kb-flash { border-color: var(--gold); color: #f4e2a8; }

/* Preferences: the three pilot toggles that were previously only reachable by
   pressing their key blind (I / V / T). Same persistence, now discoverable. */
#settings-prefs { margin-top: 14px; }
.kb-pref {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 8px; margin-top: 4px;
  background: rgba(255,255,255,0.03); border: 2px solid var(--slab-border);
  cursor: pointer; font-size: 14px; color: #dbe3ec;
}
.kb-pref input { width: 16px; height: 16px; accent-color: var(--gold); cursor: pointer; }
.kb-pref .kb-pref-name { flex: 1; }
.kb-pref .kb-pref-key { color: #8d9aa8; font-size: 12px; }

.settings-actions {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
  margin-top: 18px;
}
#keybind-reset { font-size: 15px; }

/* On-screen help tokens (join card + HUD hint bar) mirror the live binding,
   uppercased to match the terse control-card voice ("SPACE", "SHIFT"). */
[data-kb], [data-kb-pair] { text-transform: uppercase; }
.rebind-nudge { color: #8d9aa8; font-style: italic; }

#scoreboard {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  background: var(--slab); border: 4px solid var(--slab-border);
  padding: 16px 24px;
  min-width: 420px;
}
#scoreboard table { width: 100%; border-collapse: collapse; font-size: 16px; }
#scoreboard th { color: #8d9aa8; text-align: left; padding: 4px 10px; border-bottom: 2px solid #2a3140; }
#scoreboard td { padding: 4px 10px; }
#scoreboard tr.me { background: rgba(244, 197, 66, 0.12); }
#scoreboard td.crimson { color: var(--crimson); }
#scoreboard td.cobalt { color: var(--cobalt); }
#scoreboard .bot-tag { color: #76838f; font-size: 12px; }
#scoreboard .title-tag { color: #f4c542; font-size: 11px; letter-spacing: 0.5px; }

/* ============ round intel summary ============ */
#intel-card {
  position: absolute; inset: 0; z-index: 8;
  display: flex; align-items: center; justify-content: center;
  background: rgba(8, 10, 16, 0.55);
  cursor: pointer;
}
.intel-inner {
  background: var(--slab); border: 4px solid var(--slab-border);
  padding: 20px 28px; text-align: center;
  width: min(580px, 94vw); max-height: 92vh; overflow: auto;
}
#intel-head {
  margin: 0; font-size: 26px; font-weight: bold; letter-spacing: 2px;
  text-shadow: 2px 2px 0 #000;
}
#intel-sub { margin-top: 4px; font-size: 13px; letter-spacing: 1px; color: #b7c6d4; }
#intel-sub .crimson, #intel-cols .crimson, #intel-top .crimson { color: var(--crimson); }
#intel-sub .cobalt, #intel-cols .cobalt, #intel-top .cobalt { color: var(--cobalt); }
#intel-timeline {
  margin-top: 14px; width: 100%; height: auto;
  border: 2px solid var(--slab-border); background: rgba(8, 12, 20, 0.55);
}
#intel-cols { margin-top: 14px; display: flex; gap: 14px; }
.intel-col {
  flex: 1; padding: 8px 10px;
  background: rgba(13, 16, 24, 0.6); border: 2px solid var(--slab-border);
}
.intel-col h3 {
  margin: 0 0 6px; font-size: 14px; letter-spacing: 2px;
  border-bottom: 2px solid #2a3140; padding-bottom: 4px;
}
.intel-col.crimson h3 { color: var(--crimson); }
.intel-col.cobalt h3 { color: var(--cobalt); }
.intel-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; padding: 2px 0; color: #c9d6e4;
}
.intel-ico { width: 18px; text-align: center; }
.intel-val { width: 28px; text-align: right; font-weight: bold; color: #eef2f6; }
.intel-lbl { color: #8d9aa8; letter-spacing: 0.5px; }
#intel-top { margin-top: 14px; }
#intel-top h4 {
  margin: 0 0 6px; font-size: 12px; letter-spacing: 2px; color: #8d9aa8;
}
.intel-ace {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; padding: 2px 0; justify-content: center;
}
.intel-rank {
  width: 18px; height: 18px; line-height: 18px; text-align: center;
  background: var(--gold); color: #1a1408; font-weight: bold; font-size: 12px;
}
.intel-title { color: var(--gold); font-size: 11px; letter-spacing: 0.5px; }
.intel-kills { color: #eef2f6; font-weight: bold; }
.intel-foot { margin-top: 14px; font-size: 11px; letter-spacing: 1px; color: #6c7a89; }
body.touch .intel-inner { padding: 14px 16px; }
body.touch #intel-head { font-size: 20px; }
body.touch .intel-row, body.touch .intel-ace { font-size: 12px; }

#hint-bar {
  position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%);
  font-size: 11px; color: rgba(255,255,255,0.55); text-shadow: 1px 1px 0 #000;
}

#damage-flash {
  position: fixed; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 55%, rgba(220, 40, 40, 0.55) 100%);
  opacity: 0; transition: opacity 0.4s;
}

/* Directional damage flash (roadmap #56): four screen-edge arcs, one lit
   toward the quarter the fire came from. */
#dmg-dir { position: fixed; inset: 0; pointer-events: none; }
.dmg-arc { position: absolute; opacity: 0; }
.dmg-front { top: 0; left: 0; right: 0; height: 22%;
  background: linear-gradient(to bottom, rgba(255, 45, 45, 0.6), rgba(255, 45, 45, 0)); }
.dmg-back { bottom: 0; left: 0; right: 0; height: 22%;
  background: linear-gradient(to top, rgba(255, 45, 45, 0.6), rgba(255, 45, 45, 0)); }
.dmg-left { top: 0; bottom: 0; left: 0; width: 15%;
  background: linear-gradient(to right, rgba(255, 45, 45, 0.6), rgba(255, 45, 45, 0)); }
.dmg-right { top: 0; bottom: 0; right: 0; width: 15%;
  background: linear-gradient(to left, rgba(255, 45, 45, 0.6), rgba(255, 45, 45, 0)); }

/* Stall-margin ribbon (roadmap #56): a small vertical bar by the G-meter. */
#stall-gauge { align-items: flex-end; }
#stall-gauge label { align-self: center; }
.stall-track {
  width: 6px; height: 44px; position: relative;
  background: rgba(0, 0, 0, 0.4); border: 1px solid var(--slab-border);
}
#stall-ribbon {
  position: absolute; left: 0; bottom: 0; width: 100%;
  height: 0%; background: #5fe07a; transition: height 0.08s linear;
}

/* Bomb-release confidence ring (roadmap #56): a dispersion circle on the pip. */
#bomb-ring {
  position: absolute; left: -100px; top: -100px;
  transform: translate(-50%, -50%);
  border: 2px solid #9aa3ad; border-radius: 50%;
  box-shadow: 0 0 3px #000; opacity: 0.75; pointer-events: none;
}

/* G-meter colour states (the gauge digit). */
#g-load.g-warn { color: #f4c542; }
#g-load.g-crit { color: var(--crimson); }

/* G-physiology veils: black grey-out tunnel and red-out wash. Opacity and
   the vignette radius are driven from hud.gForce(); kept under the HUD. */
#g-veil, #g-redout {
  position: fixed; inset: 0; pointer-events: none; z-index: 3;
  opacity: 0;
}
#g-redout { background: rgba(150, 0, 0, 1); }

/* Elevator-trim gauge: a strip with a centre detent and a tick that rides
   right for nose-up trim, left for nose-down. Dims when auto-trim is off. */
.trim-detent {
  position: absolute; top: -2px; bottom: -2px; left: 50%; width: 1px;
  transform: translateX(-0.5px); background: rgba(255, 255, 255, 0.4);
}
#trim-tick {
  position: absolute; top: -2px; bottom: -2px; width: 3px; left: 50%;
  transform: translateX(-1.5px); background: var(--gold);
  transition: left 0.08s linear;
}
#trim-gauge.off { opacity: 0.4; }
#trim-gauge.off #trim-tick { background: #9aa3ad; }

/* Pre-stall warning flag, just under the crosshair. */
#stall-warn {
  position: absolute; left: 50%; top: 58%; transform: translateX(-50%);
  font-weight: bold; letter-spacing: 3px; font-size: 18px;
  color: #1b1405; background: var(--gold);
  padding: 3px 12px; border: 2px solid var(--slab-border);
  animation: stall-blink 0.45s steps(2, start) infinite;
}
@keyframes stall-blink { 50% { opacity: 0.35; } }

#autopilot-ind {
  position: absolute; left: 50%; top: 96px; transform: translateX(-50%);
  font-weight: bold; letter-spacing: 2px; font-size: 14px;
  color: #bfe6ff; background: rgba(74, 125, 232, 0.22);
  padding: 3px 12px; border: 2px solid var(--slab-border);
}
/* Touch flies the autopilot hands-off (let go of the stick, no button), so the
   centre flag is the on-screen state there too — parked just above the health
   bar, clear of the top banners and the mid-screen toast lane. */
body.touch #autopilot-ind {
  top: auto; bottom: calc(40px + env(safe-area-inset-bottom));
  font-size: 12px;
}

/* ---------- naval conning panel ---------- */
#naval-panel {
  position: absolute; left: 16px; bottom: 132px;
  display: flex; align-items: center; gap: 10px;
  background: var(--slab); border: 3px solid var(--slab-border);
  padding: 6px 12px; font-size: 14px; font-weight: bold; letter-spacing: 1px;
  /* The chips double as buttons — the touch path to X/R/T/G (and a mouse
     convenience): tap the shell chip to cycle ammo, REPAIR/BOOST/DC to fire
     the matching consumable. Lifted above the touch steer/look zones so a
     tap reaches the chip instead of grabbing the virtual stick. */
  pointer-events: auto;
  z-index: 31;
}
#naval-panel span { cursor: pointer; -webkit-user-select: none; user-select: none; touch-action: manipulation; }
/* On a phone the panel had become a mid-screen slab: two rows of chips parked
   exactly on the horizon band where every enemy silhouette (and your own bow)
   lives — the "can't see the game" report in one element. The chips now stack
   as a slim column on the LEFT RAIL, slotted between the SPD readout above and
   the engine telegraph below, so the whole battle band stays glass. The rail
   was already chrome in the player's mind (gauges → lever); this just fills
   its empty middle. Labels compress to match (hud.js speaks SMK/REP/BST on
   touch) and the torpedo/ATGM chip folds into the BOMB button that actually
   fires it (.cooling below), so the column stays five rows worst-case. */
body.touch #naval-panel {
  font-size: 12px; padding: 5px 6px; gap: 4px;
  left: calc(10px + env(safe-area-inset-left));
  right: auto; bottom: auto; top: 84px;
  flex-direction: column; align-items: stretch;
}
body.touch #naval-panel span { padding: 4px 6px; text-align: center; white-space: nowrap; }
/* Display-only on touch (the BOMB button is the trigger AND the readiness
   lamp there) — a chip that can't be tapped doesn't get a row. */
body.touch #naval-torp { display: none; }
/* No fire, no flooding — no row. */
#naval-dot:empty { display: none; }
#naval-shell { padding: 2px 9px; border: 2px solid var(--slab-border); }
#naval-shell.naval-he { color: #ffd05a; background: rgba(244, 197, 66, 0.18); }
#naval-shell.naval-ap { color: #ff8a5a; background: rgba(255, 122, 46, 0.20); }
#naval-shell.naval-ss { color: #ffe39a; background: rgba(255, 227, 154, 0.22); }
#naval-dc.dc-ready { color: #7CFC7C; }
#naval-dc.dc-active { color: #bfe6ff; }
#naval-dc.dc-cooldown { color: #8d9aa8; }
#naval-dot { color: #ff7b2e; font-size: 13px; }
#naval-torp { padding: 2px 8px; border: 2px solid var(--slab-border); }
#naval-torp.torp-ready { color: #7CFC7C; }
#naval-torp.torp-cooldown { color: #8d9aa8; }

/* ---------- naval binocular gunsight ---------- */
#naval-scope { position: absolute; inset: 0; pointer-events: none; z-index: 30; }
/* A soft optical vignette so it reads as "through the glass". */
#naval-scope .scope-mask {
  position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 50%,
    rgba(0,0,0,0) 30%, rgba(0,0,0,0.18) 52%, rgba(0,0,0,0.72) 70%, rgba(0,0,0,0.92) 100%);
}
/* WoWS-style reticle: a wide horizontal lead scale with notches rising off
   it, and a short vertical centre stroke — not a full crosshair. */
#naval-scope .scope-reticle {
  position: absolute; left: 50%; top: 50%; width: min(80vw, 980px); height: 46vh;
  transform: translate(-50%, -50%);
}
#naval-scope .sr-h {
  position: absolute; top: 50%; left: 0; height: 1px; width: 100%;
  transform: translateY(-0.5px); background: rgba(120,230,150,0.55);
}
#naval-scope .sr-vc {
  position: absolute; left: 50%; top: 50%; width: 1px; height: 36px;
  transform: translate(-0.5px, -50%); background: rgba(120,230,150,0.9);
}
/* Lead notches: minor every half unit, taller numbered majors every unit
   (one unit = a nominal hull's travel over one shell flight — main.js lays
   them out). They rise off the scale line like a ruler. */
#naval-scope .sr-notch {
  position: absolute; top: 50%; width: 1px; height: 9px;
  transform: translate(-0.5px, -100%); background: rgba(120,230,150,0.7);
}
#naval-scope .sr-notch.major {
  height: 16px; background: rgba(120,230,150,0.95);
}
#naval-scope .sr-notch.major::after {
  content: attr(data-n);
  position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
  color: rgba(120,230,150,0.85); font-size: 10px; letter-spacing: 0;
}
#naval-scope .scope-label {
  position: absolute; left: 50%; bottom: 7%; transform: translateX(-50%);
  color: rgba(120,230,150,0.8); font-size: 12px; letter-spacing: 2px;
}
/* Range-dial hold buttons: the touch path to "aim for distance" (desktop has
   the mouse and the scroll wheel too). Parked on the right edge, inside the
   scope glass, big enough for thumbs. */
#naval-scope .scope-rng-btns {
  position: absolute; right: calc(3% + env(safe-area-inset-right)); top: 50%;
  transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 14px;
  pointer-events: auto;
}
#naval-scope .scope-rng-btns button {
  width: 58px; height: 58px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font: 600 15px/1.1 inherit; letter-spacing: 1px;
  color: rgba(140,240,165,0.95);
  background: rgba(10, 30, 18, 0.45);
  border: 1px solid rgba(120,230,150,0.55);
  touch-action: none; user-select: none; -webkit-user-select: none;
}
#naval-scope .scope-rng-btns button small { font-size: 9px; letter-spacing: 2px; opacity: 0.8; }
#naval-scope .scope-rng-btns button.held { background: rgba(120,230,150,0.3); }
/* Bigger thumb targets on coarse pointers. */
body.touch #naval-scope .scope-rng-btns button { width: 72px; height: 72px; }
/* Rangefinder readout: live range to the sighted target and the locked solution. */
#naval-scope .scope-range {
  position: absolute; left: 50%; top: 16%; transform: translateX(-50%);
  color: rgba(120,230,150,0.92); font-size: 15px; letter-spacing: 2px;
  text-align: center; line-height: 1.5; text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}
#naval-scope .scope-range .set { color: #7CFC7C; font-weight: 600; }
#naval-scope .scope-range .max { color: #ff8f7a; font-weight: 600; }
#naval-scope .scope-range .nolock { color: rgba(120,230,150,0.55); }

/* ---------- touch controls ---------- */
#touch-controls { position: absolute; inset: 0; pointer-events: none; }

.tc-zone { position: absolute; pointer-events: auto; touch-action: none; }
#tc-steer-zone { left: 0; top: 56px; bottom: 0; width: 50%; }
#tc-look-zone { right: 0; top: 56px; bottom: 0; width: 50%; }

#tc-stick-base {
  position: absolute; width: 148px; height: 148px;
  margin: -74px 0 0 -74px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.4);
  background: rgba(24, 28, 38, 0.3);
  display: none; pointer-events: none;
}
#tc-stick-base.on { display: block; }
#tc-stick-knob {
  position: absolute; left: 50%; top: 50%; width: 52px; height: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  background: rgba(244, 197, 66, 0.9);
  border: 3px solid var(--slab-border);
  box-shadow: 0 2px 0 var(--slab-border);
}

.tc-btn {
  position: absolute; pointer-events: auto; touch-action: none;
  border-radius: 50%;
  border: 3px solid var(--slab-border);
  box-shadow: 0 4px 0 var(--slab-border);
  font: inherit; font-weight: bold; letter-spacing: 1px;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
}
.tc-btn:active { transform: none; } /* the generic button press-drop reads as jitter here */
.tc-btn.held { transform: scale(0.92); box-shadow: 0 1px 0 var(--slab-border); }

#tc-fire {
  width: 96px; height: 96px; font-size: 17px;
  right: calc(16px + env(safe-area-inset-right));
  bottom: calc(24px + env(safe-area-inset-bottom));
  background: rgba(244, 197, 66, 0.88); color: #1b1405;
}
#tc-bomb {
  width: 64px; height: 64px; font-size: 12px;
  right: calc(124px + env(safe-area-inset-right));
  bottom: calc(44px + env(safe-area-inset-bottom));
  background: rgba(232, 74, 74, 0.85); color: #ffe9e9;
}
/* Tubes reloading / ATGM cooling: the button that fires them is also the
   readiness lamp (hud.js toggles this while conning), so the old TORP/ATGM
   chip row could leave the screen. Dimmed, not hidden — the control stays
   where the thumb learned it. */
#tc-bomb.cooling { opacity: 0.45; }
#tc-bail {
  display: none;
  width: 64px; height: 64px; font-size: 12px;
  right: calc(124px + env(safe-area-inset-right));
  bottom: calc(44px + env(safe-area-inset-bottom));
  background: rgba(42, 49, 64, 0.9); color: #c9d6e4;
}
#touch-controls.gun-mode #tc-bail { display: flex; }
#touch-controls.gun-mode #tc-bomb,
#touch-controls.gun-mode #tc-throttle { display: none; }
/* Drive mode (vehicle / warship): keep the throttle — the engine telegraph —
   and the BOMB button (torpedoes at sea); add BAIL (leave the ship). BAIL
   shares the BOMB slot in gun mode, so shift it clear here. */
#touch-controls.drive-mode #tc-bail {
  display: flex;
  right: calc(284px + env(safe-area-inset-right));
}
#tc-zoom {
  width: 64px; height: 64px; font-size: 12px;
  right: calc(204px + env(safe-area-inset-right));
  bottom: calc(44px + env(safe-area-inset-bottom));
  background: rgba(64, 168, 108, 0.82); color: #eafff0;
}
/* Jets era: the second weapon row. These shipped with .tc-btn's bare
   position:absolute and NO offsets, so both buttons piled up at the
   container's top-left corner — FLARE half off the screen, MSL entirely
   gone; "there's no missile fire button on mobile" was the exact report.
   MSL rides above FIRE (the launch thumb is the trigger thumb), FLARE
   above BOMB — the panic button stays one reach from the stick-free hand.
   Seeker blue and flare orange match their HUD moments. */
#tc-msl {
  width: 64px; height: 64px; font-size: 12px;
  right: calc(32px + env(safe-area-inset-right));
  bottom: calc(136px + env(safe-area-inset-bottom));
  background: rgba(110, 178, 255, 0.85); color: #eaf3ff;
}
#tc-flare {
  width: 64px; height: 64px; font-size: 12px;
  right: calc(124px + env(safe-area-inset-right));
  bottom: calc(124px + env(safe-area-inset-bottom));
  background: rgba(236, 148, 60, 0.85); color: #fff3e2;
}

/* Spectate vantage controls — bottom-centre PREV/NEXT pills. The bar itself
   is click-through so taps between the buttons fall to the playfield. */
#tc-spectate {
  position: absolute; pointer-events: none;
  left: 50%; transform: translateX(-50%);
  bottom: calc(22px + env(safe-area-inset-bottom));
  display: flex; gap: 18px; z-index: 5;
}
#tc-spectate .tc-btn {
  position: static; pointer-events: auto;
  width: 128px; height: 54px; border-radius: 27px;
  font-size: 15px;
  background: rgba(42, 49, 64, 0.9); color: #c9d6e4;
}

#tc-throttle {
  position: absolute; pointer-events: auto; touch-action: none;
  left: calc(12px + env(safe-area-inset-left));
  bottom: calc(64px + env(safe-area-inset-bottom));
  /* Top-capped, not %-sized: at 32% height on a 390px-tall phone the lever's
     upper travel slid under the air theater's full seven-row gauge stack
     (top: 48px + ~184px tall) — full throttle lived beneath the BMB row.
     240px clears the stack with a hair of daylight; the e2e mobile overlap
     guard fails the build if these two ever meet again. */
  top: calc(240px + env(safe-area-inset-top));
  width: 56px;
  background: rgba(24, 28, 38, 0.45);
  border: 3px solid var(--slab-border);
  display: flex; align-items: flex-end;
}
#tc-throttle-fill { width: 100%; background: rgba(244, 197, 66, 0.8); }
/* Live percent readout sits inside the slider's bottom so it never reaches up
   into the top-anchored gauge stack (was overlapping the BMB row). */
#tc-throttle span {
  position: absolute; left: 50%; bottom: 4px; transform: translateX(-50%);
  font-size: 11px; font-weight: bold; letter-spacing: 0.5px;
  color: #fff; text-shadow: 0 0 4px #000, 0 1px 2px #000;
  white-space: nowrap; pointer-events: none;
}

/* First-flight coach: ghosted labels over the live control zones. Each fades
   the first time its control is used; the whole layer force-fades after 20 s.
   Non-interactive so it never eats a control touch. */
#tc-coach { position: absolute; inset: 0; pointer-events: none; z-index: 4; }
.coach-label {
  position: absolute;
  opacity: 0.55; color: #fff;
  font-weight: bold; letter-spacing: 2px; font-size: 20px; text-align: center;
  text-shadow: 0 0 6px #000, 0 2px 5px #000;
  transition: opacity 0.5s ease;
}
.coach-label.faded { opacity: 0; }
.coach-arc { display: block; font-size: 42px; line-height: 1; margin-bottom: 2px; }
#coach-steer { left: 25%; top: 56%; transform: translate(-50%, -50%); }
/* Below the minimap + killfeed lane so the label never rides a feed line. */
#coach-look { left: 72%; top: 65%; transform: translate(-50%, -50%); }
/* Beside the slider, vertically centred on it — the lane above the slider
   belongs to the gauge stack (BMB row included). */
#coach-thr {
  left: calc(80px + env(safe-area-inset-left));
  bottom: calc(64px + 14%);
  font-size: 15px; letter-spacing: 1px; white-space: nowrap;
}

/* ---------- iOS "add to home screen" hint (join screen) ---------- */
#ios-install-hint {
  position: relative;
  margin: 12px auto 0;
  max-width: 360px;
  padding: 10px 30px 10px 12px;
  border: 2px solid var(--gold);
  border-radius: 4px;
  background: rgba(244, 197, 66, 0.1);
  color: #e9eefa;
  font-size: 13px;
  line-height: 1.45;
  text-align: left;
}
#ios-install-hint b { color: var(--gold); }
#ios-install-hint.hidden { display: none; }
.ios-share-glyph {
  display: inline-block;
  padding: 0 5px;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-weight: bold;
}
#ios-install-dismiss {
  position: absolute;
  top: 2px; right: 4px;
  border: none; background: none;
  color: #9aa6bf; font-size: 20px; line-height: 1;
  cursor: pointer; padding: 2px 6px;
}
#ios-install-dismiss:hover { color: #e9eefa; }

/* ---------- rotate-to-landscape gate ---------- */
#rotate-overlay {
  display: none; position: fixed; inset: 0; z-index: 50;
  align-items: center; justify-content: center; text-align: center;
  background: rgba(10, 14, 22, 0.94);
  pointer-events: auto;
}
.rotate-card { font-size: 20px; font-weight: bold; letter-spacing: 3px; color: var(--gold); }
.rotate-icon { font-size: 64px; line-height: 1.2; }
@media (orientation: portrait) {
  body.touch #rotate-overlay { display: flex; }
}

/* While the join/respawn card is up, the flight HUD behind it is just noise —
   the killcam has already played (it precedes this screen), so clear the deck.
   Applies on every platform (desktop respawn had the same clutter). #message
   (join toasts) and the killcam tag are intentionally left visible. */
body.spawn-open #top-bar, body.spawn-open #flight-data, body.spawn-open #minimap,
body.spawn-open #hp-wrap, body.spawn-open #killfeed, body.spawn-open #chat,
body.spawn-open #crosshair { display: none; }

/* ---------- mobile hud layout (body.touch) ---------- */
body.touch #hint-bar { display: none; }
body.touch #top-bar {
  pointer-events: auto; /* tap toggles the scoreboard */
  top: max(6px, env(safe-area-inset-top));
  gap: 10px; padding: 4px 10px; font-size: 14px;
}
body.touch #zone-state { font-size: 11px; }
/* Gauges move out from under the left thumb, up to the top-left corner. */
body.touch #flight-data {
  left: calc(10px + env(safe-area-inset-left));
  top: 48px; bottom: auto;
  padding: 6px 10px; gap: 3px; min-width: 132px;
}
body.touch .gauge { font-size: 13px; gap: 6px; }
body.touch .gauge span { font-size: 16px; min-width: 46px; }
body.touch #minimap {
  width: 112px; height: 112px;
  top: 48px; bottom: auto;
  right: calc(10px + env(safe-area-inset-right));
}
/* Plot table: tighten the action bar and banner for short landscape phones so
   the chart canvas can claim more of the limited height. */
body.touch #plot-table { gap: 8px; }
body.touch #plot-banner { font-size: 12px; padding: 5px 12px; }
body.touch #plot-bar { gap: 8px; }
body.touch #plot-bar button { padding: 9px 16px; }
body.touch #plot-primary { min-width: 150px; }
body.touch #plot-readout { top: 10px; right: 10px; min-width: 150px; font-size: 11px; padding: 6px 8px 7px; }
body.touch #plot-readout-rows { gap: 2px 8px; }
/* Tuck the feed into the right column directly under the minimap (top 48 +
   112 tall + 10 gap), keep it narrow, and ellipsize long bot names so entries
   never run into the play area or under the FIRE cluster (U3). */
body.touch #killfeed { top: 170px; right: calc(10px + env(safe-area-inset-right)); font-size: 12px; max-width: 34vw; }
body.touch .feed-line {
  max-width: 34vw; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Chat carries a real message, so let it wrap instead of ellipsizing away. */
body.touch .feed-line.chat {
  white-space: normal; overflow: visible; overflow-wrap: anywhere; text-align: left;
}
/* Chat shares the left half with the gauges, the throttle slider and the
   virtual stick: start it below the full gauge stack (incl. the BMB row) and
   indent it clear of the slider so lines never sit on either. */
body.touch #chat {
  left: calc(76px + env(safe-area-inset-left));
  bottom: auto; top: 232px;
  max-width: 36vw; font-size: 12px;
}
body.touch #hp-wrap { width: 200px; bottom: 12px; }
/* No aim-cursor glyph on touch: the stick knob under the thumb already shows
   the commanded deflection, so the floating gold ⌖ was a second cursor
   cluttering the centre of the screen. The white gunsight (#crosshair) is the
   only reticle. */
body.touch #aim-cursor { display: none; }
body.touch #crosshair {
  font-size: 32px;
  text-shadow: 0 0 4px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.5);
}
body.touch #message { font-size: 22px; letter-spacing: 2px; }
/* The now-playing chip sits bottom-left with a plain 16px inset, which tucks it
   under the notch if the phone is rotated with the island on the LEFT (landscape
   goes both ways). Mirror the map/feed: respect whichever side the notch lands
   on, and lift clear of the home-indicator strip along the bottom. */
body.touch #now-playing {
  left: max(16px, env(safe-area-inset-left));
  bottom: max(16px, env(safe-area-inset-bottom));
}

/* ---------- mobile spectate: a clean watch-only frame (body.spectating.touch)
   A spectator flies nothing, so the SPD/ALT/THR gauges, the health bar and the
   throttle slider are all dead furniture reading zeros. Strip them, park the
   minimap in the top-right corner, and hand the comms feed a narrow lane
   pinned to the right edge so callouts stop landing on the PREV/RECENTER/NEXT
   pills at the bottom of the screen. */
body.spectating.touch #flight-data,
body.spectating.touch #hp-wrap { display: none; }
/* The watch view rides the right edge, and landscape has two orientations, so
   respect whichever side the notch lands on. `max(6px, safe-area-inset-right)`
   does exactly that: when the phone is rotated with the notch on the RIGHT the
   inset wins and the map/feed stop at the notch boundary; rotated the other way
   the inset is ~0, the 6px floor wins, and they pull tight to the bare edge. */
body.spectating.touch #minimap {
  top: max(8px, env(safe-area-inset-top));
  right: max(6px, env(safe-area-inset-right));
}
/* Feed hugs the same right edge directly under the minimap (top 8 + 112 tall +
   gap) and stays narrow so callouts stack in a tight right column instead of
   reaching back across the buttons. */
body.spectating.touch #killfeed {
  top: 128px;
  right: max(6px, env(safe-area-inset-right));
  max-width: 34vw;
}
body.spectating.touch .feed-line,
body.spectating.touch .feed-line.chat { max-width: 34vw; text-align: right; }
/* The composer, when open, rides the same right rail instead of the left. */
body.spectating.touch #chat {
  left: auto; top: auto;
  right: max(6px, env(safe-area-inset-right));
  bottom: calc(72px + env(safe-area-inset-bottom));
  max-width: 34vw;
}
/* Drop the PREV/RECENTER/NEXT pills to the very bottom edge (the safe-area
   inset already lifts them clear of the home indicator) so the watch view
   reads as map-top / feed-right / controls-bottom with the sky in the middle. */
body.spectating.touch #tc-spectate {
  bottom: calc(8px + env(safe-area-inset-bottom));
}

/* ---------- naval theater, touch: de-stack the small-screen HUD ----------
   The ship overlays (RNG readout, DETECTED banner, fleet orders, the gunnery
   readouts, and the range dial) all wanted the same slivers of a phone screen
   and piled on top of each other. Give each its own lane. */
/* A warship has no trim and its throttle already reads out live on the
   telegraph slider ("THR 70") — so at sea the air theater's gauge stack
   shrinks to the one number a captain glances at: SPD. Two fewer rows of
   chrome in the top-left, and the conning column below starts higher. */
body.naval.touch #thr-gauge, body.naval.touch #trim-gauge { display: none; }
/* …and with one gauge left, the air stack's min-width is just dead slab. */
body.naval.touch #flight-data { min-width: 0; }
/* The DETECTED / TORPEDOES / SHOAL banner earns its center-top slot, but at
   desktop scale it read as a quarter-screen wall on a phone. Same words,
   HUD-sized. */
body.touch #warning-banner, body.touch #protect-banner {
  font-size: 12px; letter-spacing: 1.5px; padding: 4px 10px; top: 46px;
}
/* Fleet orders / callouts wrap tight and sit in their own lane just under the
   DETECTED banner — clear of the conning column on the left rail (x ≲ 76) —
   instead of a full-width wall of text that slid behind the panel. */
body.naval.touch #message {
  font-size: 16px; letter-spacing: 1px; top: 124px;
  /* Symmetric left/right (not left:50%) so a centred message can use the full
     width instead of shrink-to-fitting into the right half and stacking tall. */
  left: 82px; right: 82px; max-width: none;
  transform: translateY(-50%); line-height: 1.25;
}
/* RNG rangefinder drops below the DETECTED banner (top ~64) rather than landing
   on it. */
body.naval.touch #naval-scope .scope-range {
  top: 96px; font-size: 14px; letter-spacing: 1.5px;
}
/* While scoped the binocular view is the point; hand the minimap's top-right
   corner to the range dial so the two stop overlapping, and pull the killfeed
   in clear of the dial that now lives on that edge. */
body.naval-scoped.touch #minimap { display: none; }
body.naval-scoped.touch #killfeed { right: calc(96px + env(safe-area-inset-right)); }
/* The range dial rides the right edge, vertically centred in the corner the
   minimap just vacated — clear of the FIRE cluster below it. */
body.naval.touch #naval-scope .scope-rng-btns { gap: 14px; }
body.naval.touch #naval-scope .scope-rng-btns button { width: 64px; height: 64px; }
/* Keep the two-line control brief / gunsight label from riding on the ranging
   bar at the very bottom. */
body.naval.touch #naval-scope .scope-label {
  bottom: calc(34px + env(safe-area-inset-bottom)); font-size: 11px;
}
/* The gunnery readouts (● READY, GUNS n/n — swing broadside) live under the
   crosshair on desktop; on a phone that dead-centre band collides with the
   conning panel, the reticle, and (centred) the BAIL button. Anchor them in the
   free bottom-left corner — right of the throttle, below the panel, left of the
   health bar — where nothing else competes. */
body.naval.touch #reload-indicator,
body.naval.touch #turret-status {
  /* 78px, not 66: the telegraph slider ends at x≈68 and its THR readout sits
     at its foot — at 66 the two lines fused into "THR 70 ● READY" text soup. */
  left: calc(78px + env(safe-area-inset-left)); transform: none;
  top: auto; text-align: left;
}
body.naval.touch #reload-indicator { bottom: calc(74px + env(safe-area-inset-bottom)); }
body.naval.touch #turret-status {
  bottom: calc(54px + env(safe-area-inset-bottom)); font-size: 11px;
}
/* The respawn screen is the join screen, so it inherits the join screen's
   touch overlay-scroll and sizing — nothing respawn-specific to style. */
body.touch #scoreboard { min-width: 0; width: min(480px, 94vw); padding: 10px 12px; }
body.touch #scoreboard table { font-size: 13px; }
body.touch .gun-chip { padding: 7px 12px; } /* finger-sized */

/* ---------- small screens (phones, narrow windows) ---------- */
@media (max-width: 760px), (max-height: 560px) {
  /* The overlay-scroll setup now lives in the base rule; here we just allow
     vertical panning on touch and shrink the card to fit narrow viewports. */
  #join-screen, #disconnect-screen { touch-action: pan-y; }
  .join-card {
    padding: 14px 16px; max-width: 94vw;
  }
  .title { font-size: 32px; letter-spacing: 3px; text-shadow: 2px 2px 0 #7a5a12, 4px 4px 0 rgba(0,0,0,0.35); }
  .title.small { font-size: 26px; }
  .tagline { margin-bottom: 10px; font-size: 12px; }
  /* Phones swipe the tab row and the card row sideways rather than wrapping. */
  #unit-tabs { flex-wrap: nowrap; overflow-x: auto; touch-action: pan-x; }
  #unit-select { flex-wrap: nowrap; overflow-x: auto; touch-action: pan-x; }
  .unit-tab { flex: 0 0 auto; }
  .plane-card { flex: 0 0 auto; min-width: 116px; }
  .controls-help { margin: 10px 0; padding: 8px; font-size: 11px; line-height: 1.6; }
  .blurb { font-size: 11px; }
  #name-input { width: 150px; font-size: 16px; }
  .join-row { flex-wrap: wrap; }
  .join-row button { font-size: 16px; padding: 8px 14px; }
}

/* Landscape phones (e.g. 844x390) enter via the max-height arm. Tighten the
   vertical stack so the unit picker, LAUNCH FROM row, callsign and TAKE OFF all
   fit without scrolling (U8) — the masthead shrinks, the tagline goes, and the
   unit cards lose their tall role gutter. The horizontal card-scroll affordance
   (a cut-off next card) is preserved. */
@media (max-height: 560px) {
  .join-card { padding: 10px 16px; }
  .title { font-size: 26px; letter-spacing: 2px; margin-bottom: 2px; }
  .tagline { display: none; }
  #unit-tabs { margin-bottom: 8px; }
  #unit-select { margin-bottom: 8px; }
  .plane-card { min-width: 122px; padding: 7px 9px; }
  .plane-card h3 { font-size: 14px; margin-bottom: 2px; }
  .plane-card .role { min-height: 0; margin-bottom: 3px; font-size: 12px; line-height: 1.25; }
  .plane-card .stat { margin-top: 2px; }
  #respawn-deck { margin-bottom: 8px; }
  #join-status { margin: 8px 0 4px; }
  .controls-help { margin: 8px 0; padding: 6px 8px; font-size: 10px; line-height: 1.5; }
  .blurb { margin-top: 8px; }
}

/* ---------- about page ----------
   An editorial redesign set in Jost — a geometric sans that's deliberately
   unlike the chunky monospace game UI, on a deep cinematic backdrop that lets
   the in-engine stills carry the page. Still flying the brand palette
   (gold / cobalt / crimson) for accents. Everything below is scoped to
   .about-body so the game and blog surfaces are untouched. */
.about-body {
  /* Unlike the playfield, the about page scrolls. Keep the base `height: 100%`
     (html is `overflow: hidden`, so the body itself must be the scroll
     container) and just let it scroll its overflow — overriding the height to
     `auto` here lets the body grow past the clipped html and kills scrolling. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scroll-behavior: smooth;
  background:
    radial-gradient(140% 90% at 50% -10%, rgba(58, 96, 148, 0.45), transparent 62%),
    linear-gradient(180deg, #101926 0%, #0a1019 100%);
  background-attachment: fixed;
  color: #d7e2ee;
  /* Jost first; the system sans stack covers the brief flash before it loads. */
  font-family: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
#about-page {
  min-height: 100%;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 64px 22px 80px;
}
.about-card {
  max-width: 760px; width: 100%;
  text-align: left;
  /* Drop the join modal's chunky slab entirely — the about page reads as a
     clean editorial column, not a game panel. (This also undoes the join
     modal's narrow-viewport fixed-height inner scroll box, which would
     otherwise clip the long content on mobile.) */
  background: none; border: 0; box-shadow: none; padding: 0;
  max-height: none; overflow: visible;
}

/* Masthead: the wordmark and tagline, centered above the lede. */
.about-card .title {
  text-align: center;
  margin: 0 0 10px;
  font-family: "Jost", sans-serif;
  font-weight: 700; font-size: 68px; letter-spacing: 6px;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 4px 28px rgba(244, 197, 66, 0.22);
}
.about-card .title-tld { color: #f1f6fb; text-shadow: none; }
.about-card .tagline {
  text-align: center;
  margin: 0 0 30px;
  font-weight: 300; font-size: 14px;
  letter-spacing: 5px; text-transform: uppercase;
  color: #89a1ba;
}
.about-body .about-lede {
  max-width: 620px; margin: 0 auto 8px; text-align: center;
  font-weight: 300; font-size: 19px; line-height: 1.6; color: #aebdcd;
}
.about-body .shot-hint { color: var(--gold); font-weight: 400; }

/* Livestream embed: a 16:9 responsive frame on the same cinematic backdrop as
   the gallery stills. The padding-top trick holds the aspect ratio while the
   iframe is absolutely positioned to fill it at any width. */
.about-body .live-embed {
  position: relative;
  width: 100%;
  margin: 36px 0 0;
  padding-top: 56.25%;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.45);
}
.about-body .live-embed iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

/* Sections: a tracked gold kicker heading over a comfortable reading column. */
.about-body .about-section { margin: 52px 0; }
.about-body .about-section + .about-section {
  /* Clearer breaks between sections: a hairline rule above each. */
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 52px;
}
.about-body .about-section h2 {
  margin: 0 0 16px;
  font-family: "Jost", sans-serif;
  font-weight: 600; font-size: 15px; letter-spacing: 5px;
  text-transform: uppercase; color: var(--gold);
  text-shadow: none;
}
.about-body .about-section p {
  margin: 0 0 14px; font-weight: 400; font-size: 17px;
  line-height: 1.75; color: #c2d2e2;
}
.about-body .about-section p:last-of-type { margin-bottom: 0; }
.about-body .about-section b { font-weight: 600; color: #e6eef7; }
.about-body .about-section .controls-help { text-align: left; }
.about-body .crimson-text { color: var(--crimson); font-weight: 600; }
.about-body .cobalt-text { color: var(--cobalt); font-weight: 600; }
.about-body .gold { color: var(--gold); font-weight: 600; }

/* Gallery: staged in-engine stills (tools/screenshots), two-up on desktop. */
.about-body .shot-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin: 26px 0 0;
}
.about-body .shot-grid figure { margin: 0; position: relative; }
.about-body .shot-grid img {
  display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 5px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
  image-rendering: auto;
  cursor: zoom-in;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.about-body .shot-grid img:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.55);
}
/* Affordance hinting that a still opens full size on tap/click. */
.about-body .shot-grid figure::after {
  content: "\2922"; /* diagonal expand arrows */
  position: absolute; top: 10px; right: 10px;
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; color: #fff;
  background: rgba(13, 15, 21, 0.66);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 4px;
  pointer-events: none;
  opacity: 0.85;
}
.about-body .shot-grid figcaption {
  margin-top: 11px;
  font-weight: 300; font-size: 13px; line-height: 1.55; color: #93a8be;
}
.about-body .shot-wide { grid-column: 1 / -1; }

/* ---------- table of contents ----------
   A grouped index dropped in after the lede, on the same editorial backdrop.
   Multi-column on desktop; the section anchors it links to are the <section>s
   below. */
.about-body .about-toc {
  margin: 40px 0 4px;
  padding: 26px 28px 28px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(28, 40, 58, 0.5), rgba(16, 24, 38, 0.32));
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
}
.about-body .about-toc-title {
  font-family: "Jost", sans-serif;
  font-weight: 600; font-size: 13px; letter-spacing: 5px;
  text-transform: uppercase; color: var(--gold);
  margin-bottom: 20px;
}
.about-body .about-toc-groups {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 24px 30px;
}
.about-body .about-toc-group { break-inside: avoid; }
.about-body .about-toc-group-name {
  display: flex; align-items: baseline; gap: 9px;
  font-family: "Jost", sans-serif;
  font-weight: 600; font-size: 13.5px; letter-spacing: 1.5px;
  text-transform: uppercase; color: #e2ebf4;
  text-decoration: none;
  padding-bottom: 9px; margin-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.about-body .about-toc-group-name:hover { color: var(--gold); }
.about-body .about-toc-num {
  font-size: 11px; font-weight: 500; letter-spacing: 1px;
  color: var(--gold); opacity: 0.9; flex: none;
}
.about-body .about-toc-links {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 7px;
}
.about-body .about-toc-links a {
  color: #a9bccf; text-decoration: none;
  font-weight: 300; font-size: 15px; line-height: 1.35;
  transition: color 0.15s ease;
}
.about-body .about-toc-links a:hover { color: var(--gold); }
.about-body .about-toc-links .gold { font-weight: 400; }

/* ---------- part dividers ----------
   The top-level grouping banner that opens each part of the page. */
.about-body .about-group-head {
  display: flex; align-items: center; gap: 16px;
  margin: 78px 0 4px;
  scroll-margin-top: 20px;
}
.about-body .about-group-head:first-of-type { margin-top: 58px; }
.about-body .about-group-num {
  font-family: "Jost", sans-serif;
  font-weight: 700; font-size: 15px; letter-spacing: 2px;
  color: var(--gold);
  padding: 4px 10px;
  border: 1px solid rgba(244, 197, 66, 0.4);
  border-radius: 5px;
  flex: none;
}
.about-body .about-group-title {
  margin: 0;
  font-family: "Jost", sans-serif;
  font-weight: 700; font-size: 26px; letter-spacing: 0.5px;
  text-transform: none; color: #f1f6fb;
  text-shadow: none;
}
/* The first section after a divider shouldn't also carry the peer hairline. */
.about-body .about-group-head + .about-section { border-top: 0; padding-top: 0; }
/* Anchored sections shouldn't jam against the top edge on jump. */
.about-body .about-section { scroll-margin-top: 20px; }

/* ---------- full-size image viewer (about gallery) ---------- */
body.lightbox-open { overflow: hidden; }
.lightbox {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(6, 10, 18, 0.93);
  cursor: zoom-out;
}
.lightbox.hidden { display: none; }
.lightbox-figure {
  margin: 0; max-width: 100%; max-height: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.lightbox-img {
  max-width: 100%; max-height: 80vh; max-height: 80dvh;
  width: auto; height: auto;
  border: 3px solid var(--slab-border);
  box-shadow: 0 6px 0 rgba(0, 0, 0, 0.45);
  image-rendering: auto;
}
.lightbox-caption {
  max-width: 680px; text-align: center;
  font-size: 13px; line-height: 1.5; color: #c4d2df;
}
.lightbox-close {
  position: fixed; top: 12px; right: 16px;
  width: 44px; height: 44px;
  font-size: 30px; line-height: 1; font-weight: bold;
  color: #fff; background: var(--slab);
  border: 3px solid var(--slab-border);
  cursor: pointer;
}
.lightbox-close:active { transform: translateY(2px); }

/* ===================================================================
   Dev log (blog)
   Matches the About page: the same Jost editorial treatment set on the
   deep cinematic backdrop, a centered gold wordmark masthead, tracked
   gold kickers, and the gold pill CTAs. The brand palette leads with
   gold for accents. Everything is scoped to .blog-body so the game UI
   and the About page are untouched.
   =================================================================== */
.blog-body {
  /* Like the About page, the blog scrolls. Keep the base `height: 100%` (html
     is `overflow: hidden`, so the body itself must be the scroll container) and
     just let it scroll its overflow — overriding the height to `auto` here lets
     the body grow past the clipped html and kills scrolling on the detail
     pages. */
  min-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Same cinematic gradient as the About page, fixed behind the scroll. */
  background:
    radial-gradient(140% 90% at 50% -10%, rgba(58, 96, 148, 0.45), transparent 62%),
    linear-gradient(180deg, #101926 0%, #0a1019 100%);
  background-attachment: fixed;
  color: #d7e2ee;
  /* Jost first, the system sans stack covers the flash before it loads. */
  font-family: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  -webkit-user-select: text; user-select: text;
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}
.blog-wrap {
  max-width: 760px;
  margin: 0 auto;
  padding: 64px 22px 80px;
}

/* Masthead: centered gold wordmark over a tracked Dev Log kicker,
   mirroring the About page's title/tagline treatment. */
.blog-masthead {
  text-align: center;
  margin: 0 0 44px;
}
.blog-brand {
  display: inline-block;
  font-family: "Jost", sans-serif;
  font-weight: 700; font-size: 68px; letter-spacing: 6px; line-height: 1;
  color: var(--gold); text-decoration: none;
  text-shadow: 0 4px 28px rgba(244, 197, 66, 0.22);
}
.blog-brand span { color: #f1f6fb; text-shadow: none; }
.blog-kicker {
  display: block; margin: 12px 0 0;
  font-weight: 300; font-size: 14px;
  letter-spacing: 5px; text-transform: uppercase; color: #89a1ba;
}

/* ---- index listing ---- */
.blog-lede {
  max-width: 620px; margin: 0 auto; text-align: center;
  font-weight: 300; font-size: 19px; line-height: 1.6; color: #aebdcd;
}
.post-list { list-style: none; margin: 44px 0 0; padding: 0; }
.post-item { padding: 36px 0; border-top: 1px solid rgba(255, 255, 255, 0.08); }
.post-item:first-child { border-top: 0; }
.post-link { display: block; text-decoration: none; color: inherit; }
.post-date {
  font-size: 13px; letter-spacing: 3px; text-transform: uppercase;
  font-weight: 500; color: var(--gold);
}
.post-title {
  margin: 12px 0; font-family: "Jost", sans-serif;
  font-size: 27px; line-height: 1.3; font-weight: 600; color: #f3f6f9;
}
.post-link:hover .post-title { color: var(--gold); }
.post-excerpt { margin: 0; font-weight: 400; font-size: 17px; line-height: 1.7; color: #c2d2e2; }
.post-more {
  display: inline-block; margin-top: 16px;
  font-family: "Jost", sans-serif;
  font-size: 14px; letter-spacing: 2px; text-transform: uppercase;
  font-weight: 600; color: var(--gold);
}
.post-link:hover .post-more { text-decoration: underline; }

/* ---- long-form article ---- */
.post-breadcrumb { margin: 0 0 32px; font-size: 14px; letter-spacing: 1px; }
.blog-article a, .post-breadcrumb a {
  color: var(--gold); text-decoration: none;
}
.blog-article a:hover, .post-breadcrumb a:hover {
  color: #ffd45e; text-decoration: underline;
}
.article-title {
  margin: 0 0 16px; font-family: "Jost", sans-serif;
  font-size: 40px; line-height: 1.16; font-weight: 700;
  letter-spacing: 0; color: #f3f6f9;
}
.article-meta {
  margin: 0 0 36px; font-size: 14px; letter-spacing: 3px;
  text-transform: uppercase; font-weight: 500; color: var(--gold);
}
.article-standfirst {
  margin: 0 0 40px; padding-left: 20px;
  border-left: 3px solid var(--gold);
  font-weight: 300; font-size: 21px; line-height: 1.6; color: #aebdcd;
}
.blog-article h2 {
  margin: 52px 0 16px; font-family: "Jost", sans-serif;
  font-size: 24px; line-height: 1.3; font-weight: 600;
  letter-spacing: 0; color: #f3f6f9;
}
.blog-article p { margin: 0 0 20px; font-size: 17px; line-height: 1.78; color: #c2d2e2; }
.blog-article ul { margin: 0 0 20px; padding-left: 26px; }
.blog-article li { margin: 0 0 14px; font-size: 17px; line-height: 1.78; color: #c2d2e2; }
.blog-article b, .blog-article strong { color: #e6eef7; font-weight: 600; }
.blog-article em { font-style: italic; color: #e6ebf1; }
.blog-article blockquote {
  margin: 30px 0; padding: 4px 0 4px 22px;
  border-left: 3px solid var(--gold);
  font-weight: 300; font-size: 21px; line-height: 1.55; font-style: italic; color: #e6ebf1;
}
.blog-article code {
  font-family: ui-monospace, "SF Mono", Menlo, "Courier New", monospace;
  font-size: 0.86em; padding: 2px 6px; border-radius: 4px;
  background: rgba(255, 255, 255, 0.08); color: #e6ebf1;
}
.blog-article pre {
  margin: 0 0 24px; padding: 16px 18px; overflow-x: auto;
  background: rgba(10, 16, 25, 0.6); border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 8px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
}
.blog-article pre code {
  background: none; padding: 0; border-radius: 0;
  font-size: 13.5px; line-height: 1.7; color: #c2d2e2; white-space: pre;
}
.article-figure { margin: 32px 0 36px; }
.article-figure img {
  display: block; width: 100%; height: auto; border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.4);
}
.article-figure figcaption {
  margin-top: 12px; font-size: 14px; line-height: 1.6;
  color: #9fb0c2; font-style: italic;
}

/* ---- footer actions: the About page's gold pill + tracked text link ---- */
.blog-foot {
  margin-top: 56px; padding-top: 36px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex; align-items: center; gap: 28px;
}
.blog-cta {
  display: inline-block; text-decoration: none;
  font-family: "Jost", sans-serif;
  font-weight: 600; font-size: 15px; letter-spacing: 3px; text-transform: uppercase;
  padding: 13px 30px; border-radius: 6px;
  color: #15171c; background: var(--gold);
  box-shadow: 0 6px 20px rgba(244, 197, 66, 0.28);
  transition: background 0.16s ease, transform 0.12s ease, box-shadow 0.16s ease;
}
.blog-cta:hover {
  background: #ffd45e;
  box-shadow: 0 8px 26px rgba(244, 197, 66, 0.4);
}
.blog-cta:active {
  transform: translateY(2px);
  box-shadow: 0 3px 12px rgba(244, 197, 66, 0.28);
}
.blog-foot a:not(.blog-cta) {
  font-family: "Jost", sans-serif;
  font-weight: 500; font-size: 14px; letter-spacing: 3px;
  text-transform: uppercase; color: #8ba0b6; text-decoration: none;
}
.blog-foot a:not(.blog-cta):hover { color: var(--gold); }

@media (max-width: 640px) {
  .blog-wrap { padding: 40px 18px 64px; }
  .blog-masthead { margin-bottom: 36px; }
  .blog-brand { font-size: 44px; letter-spacing: 4px; }
  .blog-kicker { letter-spacing: 4px; }
  .blog-lede { font-size: 16px; }
  .post-title { font-size: 23px; }
  .article-title { font-size: 30px; }
  .article-standfirst { font-size: 18px; }
  .blog-article h2 { font-size: 21px; margin-top: 44px; }
  .blog-article p, .blog-article li { font-size: 16px; }
  .blog-article blockquote { font-size: 19px; }
  .blog-foot { gap: 20px; margin-top: 44px; padding-top: 28px; }
}

.about-actions { margin-top: 28px; }
.btn-link {
  display: inline-block;
  font-weight: bold; font-size: 18px;
  padding: 10px 22px;
  color: #1b1405; background: var(--gold);
  border: 3px solid var(--slab-border);
  box-shadow: 0 4px 0 var(--slab-border);
  text-decoration: none; letter-spacing: 1px;
}
.btn-link:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--slab-border); }

/* About page: the controls cheat-sheet and footer actions, on-brand with the
   Jost editorial treatment rather than the chunky game-UI slab. */
.about-body .controls-help {
  margin: 22px 0 0; padding: 18px 20px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 6px;
  font-weight: 300; font-size: 15px; line-height: 1.9; color: #b9c8d8;
}
.about-body .controls-help b { font-weight: 600; color: #eef4fa; }
.about-body .about-actions {
  display: flex; align-items: center; gap: 28px;
  margin-top: 56px; padding-top: 36px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.about-body .btn-link {
  font-family: "Jost", sans-serif;
  font-weight: 600; font-size: 15px; letter-spacing: 3px;
  text-transform: uppercase;
  padding: 13px 30px;
  border: 0; border-radius: 6px;
  box-shadow: 0 6px 20px rgba(244, 197, 66, 0.28);
  transition: background 0.16s ease, transform 0.12s ease, box-shadow 0.16s ease;
}
.about-body .btn-link:hover {
  background: #ffd45e;
  box-shadow: 0 8px 26px rgba(244, 197, 66, 0.4);
}
.about-body .btn-link:active {
  transform: translateY(2px);
  box-shadow: 0 3px 12px rgba(244, 197, 66, 0.28);
}
.about-body .about-actions .footer-link {
  font-family: "Jost", sans-serif;
  font-weight: 500; font-size: 14px; letter-spacing: 3px;
  text-transform: uppercase; color: #8ba0b6;
  border-bottom: 0;
}
.about-body .about-actions .footer-link:hover { color: var(--gold); }
/* Away-theater play buttons sit right of the gold TAKE OFF CTA. */
.about-body .about-modes { display: inline-flex; flex-wrap: wrap; gap: 14px; align-items: center; }
/* Outlined, not filled: the away theaters are offered, not shouted — TAKE OFF
   stays the one gold button that pulls the eye. */
.about-body .btn-link.alt {
  color: var(--gold); background: transparent;
  border: 2px solid rgba(244, 197, 66, 0.55);
  box-shadow: none;
  padding: 11px 24px;
}
.about-body .btn-link.alt:hover {
  background: rgba(244, 197, 66, 0.12);
  border-color: var(--gold);
  box-shadow: none;
}

/* Contact page: tappable cards for the support email and community links —
   a bold icon tile beside a label/value stack, on the same editorial backdrop
   as the rest of the about-body pages. */
.about-body .contact-cards {
  display: flex; flex-wrap: wrap; gap: 16px;
  margin: 24px 0 0;
}
.about-body .contact-card {
  display: flex; align-items: center; gap: 18px;
  flex: 1 1 280px;
  padding: 18px 22px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 8px;
  text-decoration: none;
  transition: transform 0.14s ease, border-color 0.14s ease, background 0.14s ease, box-shadow 0.14s ease;
}
.about-body .contact-card:hover {
  transform: translateY(-2px);
  border-color: rgba(244, 197, 66, 0.5);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
}
.about-body .contact-card-icon {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; flex: 0 0 52px;
  font-size: 24px; line-height: 1;
  color: #1b1405; background: var(--gold);
  border-radius: 8px;
}
.about-body .contact-card-icon.reddit { background: #ff4500; color: #fff; }
.about-body .contact-card-icon.discord { background: #5865f2; color: #fff; }
.about-body .contact-card-body { display: flex; flex-direction: column; gap: 3px; }
.about-body .contact-card-label {
  font-family: "Jost", sans-serif;
  font-weight: 500; font-size: 12px; letter-spacing: 3px;
  text-transform: uppercase; color: #8ba0b6;
}
.about-body .contact-card-value {
  font-weight: 600; font-size: 19px; color: #eef4fa;
}

@media (max-width: 760px) {
  /* Trim the page gutters so the 16:9 stills get the full screen width
     instead of being squeezed into a narrow column. */
  #about-page { padding: 32px 14px 56px; }
  .about-card .title { font-size: 44px; letter-spacing: 4px; }
  .about-card .tagline { font-size: 12px; letter-spacing: 4px; margin-bottom: 24px; }
  .about-body .about-lede { font-size: 16px; }
  .about-body .about-section { margin: 38px 0; }
  .about-body .about-section + .about-section { padding-top: 38px; }
  .about-body .about-section h2 { font-size: 14px; letter-spacing: 4px; }
  .about-body .about-section p { font-size: 16px; }
  /* Stack the gallery one-up; full document width per shot, nothing cropped. */
  .about-body .shot-grid { grid-template-columns: 1fr; gap: 18px; }
  .about-body .shot-grid figcaption { font-size: 13px; }
  .about-body .controls-help { font-size: 14px; }
  .about-body .about-actions { gap: 20px; margin-top: 40px; padding-top: 28px; }
  /* TOC stacks one group per row; the part dividers shrink to fit. */
  .about-body .about-toc { padding: 20px 18px 22px; margin-top: 32px; }
  .about-body .about-toc-groups { grid-template-columns: 1fr; gap: 22px; }
  .about-body .about-group-head { margin: 54px 0 4px; gap: 12px; }
  .about-body .about-group-head:first-of-type { margin-top: 44px; }
  .about-body .about-group-title { font-size: 21px; }
}

/* ---------- land-theater gunsights ---------- */
/* Each vehicle looks through its own optic (main.js swaps these classes on
   #naval-scope): the Paladin's fine day sight, the Warden's orange missile
   sight, the Whirlwind's wide flak reflector, the Jackal's iron ring. */
/* Paladin: a full fine crosshair with a drop chevron. */
#naval-scope.scope-mbt .sr-vc { height: 44vh; }
#naval-scope.scope-mbt .scope-reticle::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 10px; height: 10px; transform: translate(-50%, -50%) rotate(45deg);
  border-right: 1.5px solid rgba(120,230,150,0.95);
  border-bottom: 1.5px solid rgba(120,230,150,0.95);
}
/* Warden: the missile sight glows amber, with a steady tracking box. */
#naval-scope.scope-ifv .sr-h,
#naval-scope.scope-ifv .sr-notch { background: rgba(255,190,110,0.6); }
#naval-scope.scope-ifv .sr-vc { background: rgba(255,190,110,0.95); height: 30px; }
#naval-scope.scope-ifv .sr-notch.major { background: rgba(255,190,110,0.95); }
#naval-scope.scope-ifv .sr-notch.major::after { color: rgba(255,190,110,0.9); }
#naval-scope.scope-ifv .scope-range,
#naval-scope.scope-ifv .scope-label { color: rgba(255,190,110,0.9); }
#naval-scope.scope-ifv .scope-reticle::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 46px; height: 46px; transform: translate(-50%, -50%);
  border: 1.5px solid rgba(255,190,110,0.85);
}
/* Whirlwind: a wide flak reflector — concentric lead rings. */
#naval-scope.scope-aaa .scope-reticle::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 34vh; height: 34vh; transform: translate(-50%, -50%);
  border: 1.5px solid rgba(140,220,255,0.65); border-radius: 50%;
}
#naval-scope.scope-aaa .scope-reticle::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 12vh; height: 12vh; transform: translate(-50%, -50%);
  border: 1px solid rgba(140,220,255,0.55); border-radius: 50%;
}
#naval-scope.scope-aaa .sr-h { background: rgba(140,220,255,0.45); }
#naval-scope.scope-aaa .sr-vc { background: rgba(140,220,255,0.9); }
#naval-scope.scope-aaa .scope-range,
#naval-scope.scope-aaa .scope-label { color: rgba(140,220,255,0.9); }
/* Jackal: a plain iron ring and a heavy bottom post — no glass, no glow. */
#naval-scope.scope-rr .scope-reticle::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 20vh; height: 20vh; transform: translate(-50%, -50%);
  border: 3px solid rgba(235,225,200,0.8); border-radius: 50%;
}
#naval-scope.scope-rr .scope-reticle::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 3px; height: 12vh; transform: translate(-50%, 0);
  background: rgba(235,225,200,0.8);
}
#naval-scope.scope-rr .sr-h { background: rgba(235,225,200,0.5); }
#naval-scope.scope-rr .sr-vc { background: rgba(235,225,200,0.0); }
#naval-scope.scope-rr .scope-range,
#naval-scope.scope-rr .scope-label { color: rgba(235,225,200,0.85); }
/* Land panel: a chip greyed out because the hull has no second nature. */
#naval-panel .chip-off { opacity: 0.35; }
