/* Modem Warfare — art direction from the Monday mockups, rebuilt in CSS/SVG.
   Deep navy sea · phosphor-green sonar lines · signal-amber highlights ·
   bold stencil type · chunky touch targets. No webfonts: system condensed
   faces only, so the shell needs nothing from the network.

   Thursday (ruling 3, "one unmoved screen"): the four match screens —
   placement, handshake, round, game over — lay out inside a fixed viewport
   and never scroll. Everything that has a size on those screens is sized
   from --avail, the height the screen area actually has (kept by a
   ResizeObserver in app.js; the CSS fallback is the dynamic viewport), never
   from the content. Home keeps the ordinary flow and may scroll. */

:root {
  --navy: #061a2e;
  --navy-2: #0a2540;
  --navy-3: #10324f;
  --ink: #03101c;
  --phosphor: #3dff8f;
  --phosphor-dim: rgba(61, 255, 143, 0.28);
  --phosphor-line: rgba(61, 255, 143, 0.12);
  --amber: #ffb100;
  --amber-dim: rgba(255, 177, 0, 0.22);
  --fire: #ff6a1f;
  --red: #ff3b3b;
  --foam: #e6f2f5;
  --muted: #8fb0bf;
  --stencil: "Impact", "Haettenschweiler", "Franklin Gothic Demi Cond", "Arial Narrow", "Roboto Condensed", sans-serif-condensed, sans-serif;
  --mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Roboto Mono", monospace;
  --tap: 56px;
  --radius: 10px;
  --topbar: 48px;
  --avail: calc(100vh - 68px);
  --avail: calc(100dvh - 68px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--navy);
  color: var(--foam);
  font-family: var(--stencil);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  overscroll-behavior: none;
}

body {
  position: relative;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* The sea: layered sonar grid lines, fading downwards like depth. */
.sea {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 70% at 50% -10%, var(--navy-3) 0%, transparent 60%),
    repeating-linear-gradient(0deg, var(--phosphor-line) 0 1px, transparent 1px 28px),
    repeating-linear-gradient(90deg, var(--phosphor-line) 0 1px, transparent 1px 28px),
    linear-gradient(180deg, var(--navy) 0%, var(--ink) 100%);
}

/* ---------------------------------------------------------- top bar --- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: var(--topbar);
  padding: 4px 12px;
  background: rgba(6, 26, 46, 0.85);
  border-bottom: 1px solid var(--phosphor-dim);
  backdrop-filter: blur(4px);
}
.topbar__back {
  justify-self: start;
  min-height: 36px;
  padding: 0 10px;
  color: var(--phosphor);
  background: transparent;
  border: 1px solid var(--phosphor-dim);
  border-radius: 6px;
  font: inherit;
  font-size: 14px;
  letter-spacing: inherit;
  text-transform: inherit;
}
.topbar__title { font-size: 16px; color: var(--phosphor); letter-spacing: 0.18em; white-space: nowrap; }
.topbar__session { justify-self: end; font-family: var(--mono); font-size: 11px; color: var(--muted); text-transform: none; white-space: nowrap; }
body[data-screen="home"] .topbar { display: none; }

/* ---------------------------------------------------------- screens --- */
#screens { position: relative; z-index: 1; width: 100%; max-width: 520px; margin: 0 auto; padding: 16px 16px 40px; }
.screen { display: flex; flex-direction: column; gap: 16px; min-height: calc(100vh - 48px); }
.screen[hidden] { display: none; }

/* The fixed viewport: on a match route the body is a column the height of
   the viewport, the top bar keeps its height, and the screen area takes the
   rest and clips. The active match screen is a flex column inside it; its
   last row sits at the bottom (thumb zone) when there is slack. */
body[data-match] { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
body[data-match] .topbar { flex: 0 0 auto; }
body[data-match] #screens { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; padding: 8px 10px 10px; }
body[data-match] .screen--match { flex: 1 1 auto; min-height: 0; height: 100%; gap: 8px; position: relative; }
.row--bottom { margin-top: auto; }

.stencil {
  margin: 0;
  font-family: var(--stencil);
  font-weight: 900;
  line-height: 0.92;
  letter-spacing: 0.08em;
  color: var(--foam);
  text-shadow: 0 0 18px rgba(61, 255, 143, 0.25);
  position: relative;
}
.title { font-size: clamp(56px, 18vw, 96px); text-align: center; -webkit-text-stroke: 1px rgba(6, 26, 46, 0.6); }
.h2 { font-size: clamp(24px, 7vw, 36px); text-align: center; }
.h2--left { text-align: left; }
.tagline { margin: 6px 0 0; text-align: center; color: var(--amber); letter-spacing: 0.5em; font-size: 16px; }
.hint { margin: 0; text-align: center; color: var(--muted); font-size: 12px; letter-spacing: 0.18em; }
.muted { color: var(--muted); }
code { font-family: var(--mono); text-transform: none; color: var(--amber); }

/* ------------------------------------------------------------- home --- */
.screen--home { justify-content: space-between; min-height: 100vh; padding-top: 16px; }
.hero { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.sonar { width: min(44vw, 200px); margin-top: 12px; }
.sonar__ring { fill: none; stroke: var(--phosphor); stroke-opacity: 0.55; stroke-width: 1.2; }
.sonar__sweep { fill: var(--phosphor); fill-opacity: 0.22; transform-origin: 100px 100px; animation: sweep 3.6s linear infinite; }
.sonar__blip { fill: var(--amber); animation: blip 3.6s ease-out infinite; }
.sonar__dot { fill: var(--phosphor); }
@keyframes sweep { to { transform: rotate(360deg); } }
@keyframes blip { 0%, 10% { opacity: 1; } 60%, 100% { opacity: 0.15; } }

.stack { display: flex; flex-direction: column; gap: 12px; }
.row { display: flex; gap: 8px; align-items: stretch; }

.btn {
  min-height: var(--tap);
  width: 100%;
  padding: 8px 14px;
  font: inherit;
  font-size: 20px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--phosphor);
  background: linear-gradient(180deg, var(--navy-3), var(--navy-2));
  border: 2px solid var(--phosphor);
  border-radius: var(--radius);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 4px 0 rgba(0, 0, 0, 0.45), 0 0 16px rgba(61, 255, 143, 0.15);
  cursor: pointer;
  transition: transform 80ms ease, box-shadow 80ms ease;
}
.btn:active { transform: translateY(3px); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 1px 0 rgba(0, 0, 0, 0.45); }
.btn:disabled { opacity: 0.4; cursor: default; }
.btn--primary { background: linear-gradient(180deg, #1a5a3c, #0f3d2a); color: #eafff2; }
.btn--amber { color: var(--ink); background: linear-gradient(180deg, #ffc43a, var(--amber)); border-color: #ffd56a; box-shadow: 0 4px 0 #8a5e00, 0 0 18px var(--amber-dim); }
.btn--ghost { background: transparent; border-color: var(--phosphor-dim); color: var(--muted); }
.btn--half { width: auto; flex: 1 1 0; font-size: 17px; padding: 6px 8px; }
.btn--grow { width: auto; flex: 1 1 0; }
.btn--small { min-height: 44px; width: auto; flex: 0 0 auto; font-size: 14px; padding: 6px 12px; }
.btn__sub { font-size: 12px; color: var(--muted); margin-left: 8px; letter-spacing: 0.3em; }

/* Thursday: the TRANSPORT setting, new-game setup on Home. */
.setup { display: flex; flex-direction: column; gap: 6px; padding: 10px; border: 1px solid var(--phosphor-dim); border-radius: var(--radius); background: rgba(3, 16, 28, 0.5); }
.setup__label { font-size: 13px; letter-spacing: 0.22em; color: var(--amber); }
.setup__sub { display: block; margin-top: 2px; font-size: 10px; letter-spacing: 0.16em; color: var(--muted); }
.segmented { display: flex; gap: 6px; padding: 4px; border: 1px solid var(--phosphor-dim); border-radius: var(--radius); }
.seg { flex: 1 1 0; min-height: 48px; font: inherit; font-size: 17px; letter-spacing: 0.16em; color: var(--muted); background: transparent; border: 0; border-radius: 7px; cursor: pointer; }
.seg__sub { display: block; font-size: 10px; letter-spacing: 0.3em; opacity: 0.8; }
.seg[aria-checked="true"] { color: var(--ink); background: var(--phosphor); }

.badge-row { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 6px 16px;
  border-radius: 999px;
  border: 1px solid var(--muted);
  color: var(--muted);
  font-size: 14px;
  letter-spacing: 0.2em;
}
.badge__dot { width: 10px; height: 10px; border-radius: 50%; background: currentColor; }
.badge[data-state="checking"] .badge__dot { animation: pulse 1s ease-in-out infinite; }
.badge[data-state="ready"] { color: var(--phosphor); border-color: var(--phosphor); background: rgba(61, 255, 143, 0.08); box-shadow: 0 0 14px rgba(61, 255, 143, 0.25); }
.badge[data-state="partial"] { color: var(--amber); border-color: var(--amber); }
.badge[data-state="missing"], .badge[data-state="unsupported"] { color: var(--red); border-color: var(--red); }
@keyframes pulse { 50% { opacity: 0.3; } }
.firstrun { margin: 0; font-size: 12px; color: var(--muted); letter-spacing: 0.1em; text-align: center; }
body.offline-ready .firstrun { display: none; }

/* ------------------------------------------------------------ board --- */
.board-wrap { display: flex; justify-content: center; position: relative; flex: 0 0 auto; }
.board {
  display: grid;
  grid-template-columns: 18px repeat(7, 1fr);
  grid-template-rows: 14px repeat(7, 1fr);
  gap: 3px;
  width: min(100%, 400px);
  aspect-ratio: 1;
  padding: 5px;
  background: rgba(3, 16, 28, 0.7);
  border: 1px solid var(--phosphor-dim);
  border-radius: var(--radius);
  user-select: none;
  overflow: hidden;
}
/* Board sizes on the fixed screens: a share of the available height, never
   wider than the screen. */
.board-wrap--placement .board { width: min(100%, calc(var(--avail) * 0.52)); }
.board-wrap--target .board { width: min(100%, calc(var(--avail) * 0.46)); }
.board-wrap--reveal .board { width: min(100%, calc(var(--avail) * 0.42)); }
.board__label { display: grid; place-items: center; font-size: 11px; color: var(--muted); letter-spacing: 0; }
.cell {
  position: relative;
  min-width: 0;
  min-height: 0;
  padding: 0;
  background: var(--navy-2);
  border: 1px solid var(--phosphor-line);
  border-radius: 4px;
  cursor: pointer;
}
.cell::before { content: ""; position: absolute; inset: 35%; border-radius: 50%; background: var(--phosphor); opacity: 0.12; }
/* SHIPS: a ship cell is water with a hull segment drawn over it (js/ships.js).
   The tile keeps its box (the cell is still exactly the cell), its border goes
   quiet so no box line cuts the silhouette, and the segment SVG covers the
   border box edge to edge so the hull runs on into the next cell. */
.cell--ship { background: #0c2a47; border-color: rgba(61, 255, 143, 0.05); }
.cell--ship::before { opacity: 0; }
.cell--bow-h, .cell--stern-h, .cell--bow-v, .cell--stern-v { border-radius: 4px; }
.board--mini .cell--bow-h, .board--mini .cell--stern-h, .board--mini .cell--bow-v, .board--mini .cell--stern-v { border-radius: 2px; }
.cell .ship { position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); display: block; pointer-events: none; z-index: 1; overflow: hidden; }
.cell::after { z-index: 2; }
.cell .impact { z-index: 3; }
.cell--pick { background: var(--amber-dim); border-color: var(--amber); box-shadow: inset 0 0 0 2px var(--amber), 0 0 10px var(--amber-dim); }
.cell--pick::before { background: var(--amber); opacity: 0.9; inset: 38%; }
.cell--miss::before { background: var(--foam); opacity: 0.9; inset: 30%; border: 2px solid var(--foam); background: transparent; }
.cell--hit { background: radial-gradient(circle, var(--fire), #7a1d00 80%); border-color: var(--fire); }
.cell--hit::before { opacity: 0; }
.cell--sunk { background: #2a0a00; border-color: var(--red); }
.cell--shake { animation: shake 160ms ease; }
@keyframes shake { 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
.picks { text-align: center; font-size: 22px; color: var(--amber); letter-spacing: 0.3em; flex: 1 1 0; display: grid; place-items: center; border: 1px dashed var(--amber-dim); border-radius: var(--radius); }

/* The mini board: my fleet at a glance, no labels, beside the fleet strip. */
.board--mini { grid-template-columns: repeat(7, 1fr); grid-template-rows: repeat(7, 1fr); gap: 2px; padding: 3px; width: calc(var(--avail) * 0.19); height: calc(var(--avail) * 0.19); flex: 0 0 auto; }
.board--mini .board__label { display: none; }
.board--mini .cell { border-radius: 2px; }
.fleetline { display: flex; gap: 10px; align-items: stretch; min-height: 0; flex: 0 0 auto; }
.fleetline--reveal { flex: 1 1 auto; min-height: 0; }
.fleetline__col { display: flex; flex-direction: column; gap: 6px; flex: 1 1 0; min-width: 0; min-height: 0; }
/* Fleet status strip: one line per ship, the ship's own silhouette (the board
   segments laid end to end, js/ships.js); a hit segment burns, a sunk ship
   goes dark and settles. */
.fleet { display: flex; flex-direction: column; justify-content: center; gap: 5px; flex: 1 1 0; min-width: 0; }
.fleet__ship { display: flex; align-items: center; gap: 3px; font-size: 11px; letter-spacing: 0.1em; color: var(--muted); }
.fleet__name { width: 56px; flex: 0 0 auto; }
.fleet__hull { height: 16px; width: auto; flex: 0 0 auto; display: block; overflow: hidden; }
.fleet__cell--hit .sh-hull { fill: #5a1a08; }
.fleet__cell--hit .sh-deck { fill: var(--fire); }
.fleet__cell--hit .sh-fit > * { fill: #7a1d00; stroke: #3a0d00; }
.fleet__cell--hit .sh-edge { stroke: var(--fire); }
.fleet__ship--sunk { color: var(--red); }
.fleet__ship--sunk .fleet__hull { opacity: 0.8; transform: translateY(2px) rotate(2deg); }
.fleet__state { margin-left: auto; font-size: 10px; letter-spacing: 0.2em; }

/* ------------------------------------------------ SHIPS: the artwork --- */
/* Haze-grey hulls in the game's palette: a dark side band, a lighter deck,
   plating lines in sea-ink, light superstructure, dark funnels with a
   signal-amber cap. Every part is a class so the states recolour it. */
.ship { --hull: #4b5964; --deck: #7f8e9a; --edge: #b7c5cf; --super: #a7b5bf; --super-top: #cdd7de; --fit: #99a8b3; --fit-dark: #2d3942; --funnel: #2b343c; --cap: var(--amber); --ink-line: rgba(3, 16, 28, 0.35); }
.ship .sh-hull { fill: var(--hull); }
.ship .sh-deck { fill: var(--deck); }
.ship .sh-edge { fill: none; stroke: var(--edge); stroke-width: 1.5; stroke-linecap: butt; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.ship .sh-line { fill: none; stroke: var(--ink-line); stroke-width: 2; }
.ship .sh-super { fill: var(--super); stroke: var(--fit-dark); stroke-width: 1.5; }
.ship .sh-super-top { fill: var(--super-top); stroke: var(--fit-dark); stroke-width: 1.2; }
.ship .sh-window { fill: none; stroke: var(--navy-2); stroke-width: 3; stroke-linecap: round; }
.ship .sh-mast { fill: var(--fit-dark); }
.ship .sh-turret { fill: var(--fit); stroke: var(--fit-dark); stroke-width: 1.8; }
.ship .sh-turret-cap { fill: var(--fit-dark); }
.ship .sh-barrel { fill: none; stroke: var(--fit-dark); stroke-width: 3; stroke-linecap: round; }
.ship .sh-funnel { fill: var(--funnel); stroke: #151b20; stroke-width: 1.2; }
.ship .sh-funnel-cap { fill: var(--cap); opacity: 0.85; }
.ship .sh-pad { fill: none; stroke: var(--fit-dark); stroke-width: 2; }
.ship .sh-pad-core { fill: none; stroke: var(--fit-dark); stroke-width: 2; }
.ship .sh-boat { fill: var(--super-top); stroke: var(--fit-dark); stroke-width: 1.2; }
.ship .sh-tube { fill: var(--fit-dark); }
.ship .sh-fitting { fill: var(--fit-dark); }

/* The mini boards and the strip are too small for fittings to read; the
   silhouette, the deck and the hit colour carry the state there. */
.board--mini .ship .sh-line, .fleet__hull .sh-line { display: none; }
.board--mini .ship .sh-edge, .fleet__hull .sh-edge, .boards-2 .ship .sh-edge { stroke-width: 1; }

/* A hit ship cell: the tile burns (the existing fire treatment), the segment
   scorches dark, and a fireball sits on it so the hit reads at a glance. */
.cell--ship.cell--hit .ship { --hull: #3a1a10; --deck: #6a2e14; --edge: #ff8a4a; --super: #7a3a1c; --super-top: #8a4a26; --fit: #6a3018; --fit-dark: #2a0d04; --funnel: #1d0b05; --cap: #ff8a4a; --ink-line: rgba(0, 0, 0, 0.3); }
.cell--ship.cell--hit::after { content: ""; position: absolute; inset: 24%; border-radius: 50%; background: radial-gradient(circle, #fff1c2 0%, var(--fire) 38%, rgba(255, 106, 31, 0.55) 62%, rgba(255, 106, 31, 0) 100%); box-shadow: 0 0 10px var(--fire); opacity: 0.95; }

/* A sunk ship: a dark wreck, low in the water (cell--settled lowers and tilts
   it); the wreck marker is small so the hull still shows under it. */
.cell--ship.cell--sunk { background: #091624; border-color: transparent; }
.cell--ship.cell--sunk .ship { --hull: #1f1614; --deck: #3d2824; --edge: #c8452f; --super: #3a2823; --super-top: #4c342e; --fit: #36261f; --fit-dark: #150c09; --funnel: #120d0b; --cap: #7a2e1c; --ink-line: rgba(0, 0, 0, 0.3); }
.cell--ship.cell--sunk::after { inset: 38%; opacity: 0.7; background: var(--red); box-shadow: 0 0 6px rgba(255, 59, 59, 0.6); }

/* ------------------------------------------------------------- lamp --- */
.lamp { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.lamp__qr {
  width: min(78vw, 360px);
  aspect-ratio: 1;
  padding: 10px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 0 0 2px var(--phosphor), 0 0 32px rgba(61, 255, 143, 0.3);
  animation: shutter 140ms ease-out;
}
#screen-handshake .lamp__qr { width: min(100%, calc(var(--avail) * 0.34)); }
#screen-round .lamp__qr { width: min(100%, calc(var(--avail) * 0.38)); }
#screen-gameover .lamp__qr { width: min(100%, calc(var(--avail) * 0.32)); }
.lamp__qr:empty { display: none; }
.lamp__qr svg { display: block; width: 100%; height: 100%; }
@keyframes shutter { from { transform: scale(0.92); filter: brightness(0.4); } }
.lamp__caption { font-family: var(--mono); font-size: 11px; line-height: 1.25; color: var(--phosphor); letter-spacing: 0.06em; text-transform: none; text-align: center; word-break: break-all; }
.lamp__hint { font-size: 10px; color: var(--muted); letter-spacing: 0.3em; }

/* A carrier is the one transport presented on a Salute screen: the Lamp
   (QR + scanner) or the Sonar (chirp + listen). app.js hides the other. */
.carrier { display: flex; flex-direction: column; gap: 8px; }

/* ------------------------------------------------ Wednesday: the Sonar --- */
/* --level (0..1) is the captured RMS, driven from the AudioWorklet; the
   sweep arm turns while listening. */
.sonar-row { --level: 0; display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border: 1px solid var(--phosphor-dim); border-radius: var(--radius); background: rgba(3, 16, 28, 0.5); }
.sonar-row__head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.sonar-row__title { font-size: 13px; letter-spacing: 0.25em; color: var(--phosphor); white-space: nowrap; }
.sonar-row__status { font-family: var(--mono); font-size: 10px; color: var(--muted); text-transform: none; text-align: right; min-height: 12px; }
.sonar-row__frame { font-family: var(--mono); font-size: 11px; line-height: 1.25; color: var(--phosphor); text-transform: none; text-align: center; word-break: break-all; min-height: 14px; }
.sweep { position: relative; width: calc(var(--avail) * 0.17); height: calc(var(--avail) * 0.17); max-width: 140px; max-height: 140px; margin: 0 auto; border-radius: 50%; border: 1px solid var(--phosphor-dim); background: radial-gradient(circle, rgba(61, 255, 143, calc(0.06 + var(--level) * 0.5)) 0%, rgba(61, 255, 143, 0.04) 60%, transparent 70%), repeating-radial-gradient(circle, var(--phosphor-line) 0 1px, transparent 1px 16px); overflow: hidden; flex: 0 0 auto; }
.sweep__disc { position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 calc(6px + var(--level) * 40px) rgba(61, 255, 143, calc(0.2 + var(--level) * 0.8)); }
.sweep__arm { position: absolute; left: 50%; top: 50%; width: 50%; height: 2px; margin-top: -1px; transform-origin: 0 50%; background: linear-gradient(90deg, var(--phosphor), transparent); opacity: 0.25; }
.sweep__arm::after { content: ""; position: absolute; left: 0; top: -60px; width: 100%; height: 60px; background: conic-gradient(from 90deg at 0 100%, rgba(61, 255, 143, 0.35), transparent 60deg); opacity: 0; }
.sonar-row--listening .sweep__arm { opacity: 1; animation: sweeparm 2.4s linear infinite; }
.sonar-row--listening .sweep__arm::after { opacity: 1; }
.sonar-row--chirping .sweep__disc { animation: chirpring 0.6s ease-out infinite; }
.sweep__blip { position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; opacity: 0; }
.sweep--hit .sweep__blip { background: var(--phosphor); animation: blipout 900ms ease-out; }
.sweep--again .sweep__blip { background: var(--muted); animation: blipout 600ms ease-out; }
.sweep--miss .sweep__blip { background: var(--red); animation: blipmiss 900ms ease-out; }
@keyframes sweeparm { to { transform: rotate(360deg); } }
@keyframes chirpring { 0% { box-shadow: inset 0 0 0 rgba(255, 177, 0, 0.9); } 100% { box-shadow: inset 0 0 60px rgba(255, 177, 0, 0); } }
@keyframes blipout { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(9); } }
@keyframes blipmiss { 0% { opacity: 1; transform: translate(26px, -18px) scale(1); } 100% { opacity: 0; transform: translate(26px, -18px) scale(4); } }
.sonar-row__heard { min-height: 36px; display: grid; place-items: center; padding: 4px 8px; font-family: var(--mono); font-size: 11px; line-height: 1.2; text-transform: none; text-align: center; color: var(--muted); border: 1px dashed var(--phosphor-dim); border-radius: 8px; word-break: break-word; }
.sonar-row__heard[data-state="heard"] { color: var(--ink); background: var(--phosphor); border-style: solid; animation: slam 180ms ease-out; }
.sonar-row__heard[data-state="again"] { color: var(--phosphor); border-color: var(--phosphor); }
.sonar-row__heard[data-state="miss"] { color: var(--red); border-color: var(--red); border-style: solid; animation: nearmiss 500ms ease; }
@keyframes nearmiss { 20% { transform: translateX(-5px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(3px); } }

/* ------------------------------------------------------------- scan --- */
.scan { display: flex; flex-direction: column; gap: 8px; }
.scan__row { display: flex; align-items: center; gap: 10px; min-height: 16px; }
.scan__video { width: 96px; height: 72px; flex: 0 0 auto; object-fit: cover; background: #000; border-radius: 6px; border: 1px solid var(--phosphor-dim); }
.scan__status { font-family: var(--mono); font-size: 11px; color: var(--muted); text-align: center; text-transform: none; min-height: 14px; flex: 1 1 0; }
.manual { display: flex; gap: 8px; }
/* On the fixed screens the TYPE form floats over the carrier, so it takes no room. */
.screen--match .manual { position: absolute; left: 0; right: 0; bottom: 72px; z-index: 4; padding: 8px; background: var(--ink); border: 1px solid var(--amber); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6); }
.manual__input {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: 6px 10px;
  font-family: var(--mono);
  font-size: 15px;
  letter-spacing: 0.08em;
  color: var(--foam);
  background: var(--ink);
  border: 1px solid var(--phosphor-dim);
  border-radius: 6px;
  text-transform: uppercase;
}
.manual__input::placeholder { color: #3f5c6b; }

.contact {
  min-height: 44px;
  display: grid;
  place-items: center;
  padding: 6px 10px;
  text-align: center;
  font-size: 13px;
  letter-spacing: 0.16em;
  color: var(--muted);
  border: 1px dashed var(--phosphor-dim);
  border-radius: var(--radius);
}
.contact[data-state="contact"] { color: var(--ink); background: var(--phosphor); border-style: solid; animation: slam 180ms ease-out; }
.contact[data-state="duplicate"] { color: var(--phosphor); border-color: var(--phosphor); }
.contact[data-state="rejected"] { color: var(--amber); border-color: var(--amber); border-style: solid; }
@keyframes slam { from { transform: scale(1.08); } }

/* ------------------------------------------------------------ round --- */
.round-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex: 0 0 auto; min-width: 0; }
.round-head .h2 { flex: 0 0 auto; font-size: clamp(20px, 6vw, 32px); white-space: nowrap; }
.tabs { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; }
.tab { flex: 1 1 0; min-width: 0; min-height: 40px; padding: 0 3px; font: inherit; font-size: 11px; letter-spacing: 0.04em; color: var(--muted); background: transparent; border: 1px solid var(--phosphor-dim); border-radius: 7px; white-space: nowrap; overflow: hidden; }
.tab[aria-selected="true"] { color: var(--phosphor); border-color: var(--phosphor); background: rgba(61, 255, 143, 0.08); }
.phase { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; }
.phase[hidden] { display: none; }
.row--fire { align-items: stretch; flex: 0 0 auto; }
.reveal { display: flex; flex-direction: column; gap: 3px; padding: 6px 8px; border: 1px solid var(--phosphor-dim); border-radius: var(--radius); font-family: var(--mono); font-size: 11px; line-height: 1.25; text-transform: none; flex: 1 1 0; min-height: 44px; overflow: auto; }
.reveal__line { color: var(--foam); }
.reveal__line--hit { color: var(--fire); }
.reveal__line--sunk { color: var(--red); font-weight: bold; }

/* --------------------------------------------------------- game over --- */
.gameover-head { display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto; }
.stage { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; }
.stage[hidden] { display: none; }
.stamp-wrap { position: relative; display: grid; place-items: center; padding: 6px 0; flex: 0 0 auto; }
.stamp {
  position: absolute;
  padding: 8px 18px;
  border: 5px solid var(--phosphor);
  border-radius: 8px;
  color: var(--phosphor);
  text-align: center;
  transform: rotate(-14deg);
  background: rgba(6, 26, 46, 0.55);
  box-shadow: 0 0 24px rgba(61, 255, 143, 0.35);
  mix-blend-mode: screen;
  max-width: 92%;
}
.stamp__word { font-size: 56px; line-height: 0.9; letter-spacing: 0.1em; }
.stamp__sub { font-size: 12px; letter-spacing: 0.25em; }
.stamp--pending { color: var(--amber); border-color: var(--amber); box-shadow: 0 0 24px var(--amber-dim); }
.stamp--liar { color: var(--red); border-color: var(--red); }
.tally { text-align: center; font-size: 13px; letter-spacing: 0.18em; color: var(--amber); flex: 0 0 auto; }

/* ------------------------------------------------------------- toast --- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  z-index: 10;
  transform: translateX(-50%);
  max-width: 92vw;
  padding: 10px 18px;
  background: var(--ink);
  color: var(--amber);
  border: 1px solid var(--amber);
  border-radius: 999px;
  font-size: 13px;
  letter-spacing: 0.15em;
  text-align: center;
}
.toast[hidden] { display: none; }

/* ------------------------------------------------------- Tuesday: play --- */
.hint--small { font-size: 10px; letter-spacing: 0.22em; }
.commitline { font-family: var(--mono); font-size: 10px; line-height: 1.25; color: var(--muted); text-align: center; text-transform: none; letter-spacing: 0.04em; word-break: break-all; }
.scan__video--mirror { transform: scaleX(-1); }

.cell--pending::before { background: var(--amber); opacity: 0.45; inset: 42%; }
.cell--hit.cell--burn { animation: burn 600ms ease-out; }
.cell--miss.cell--splash::before { animation: ripple 500ms ease-out; }
.cell--sunk { background: linear-gradient(180deg, #4a1a08, #2a0a00); border-color: var(--red); }
.cell--sunk::after { content: ""; position: absolute; inset: 30%; border-radius: 50%; background: var(--red); opacity: 0.7; }
.cell--flash { animation: flash 300ms ease-in-out 3; }
.board--shake { animation: boardshake 220ms ease; }
@keyframes burn { 0% { transform: scale(1.35); filter: brightness(2.2); } 60% { filter: brightness(1.4); } 100% { transform: scale(1); filter: brightness(1); } }
@keyframes ripple { 0% { transform: scale(0.2); opacity: 1; } 100% { transform: scale(1.8); opacity: 0.3; } }
@keyframes flash { 50% { filter: brightness(2.6); box-shadow: 0 0 12px var(--red); } }
@keyframes boardshake { 20% { transform: translate(-5px, 2px); } 40% { transform: translate(5px, -3px); } 60% { transform: translate(-4px, 1px); } 80% { transform: translate(4px, 2px); } }

/* ------------------------------------------------ Thursday: the feel --- */
/* A shell lands: a ring bursts out of the cell (white for a splash, fire for
   a hit) and the whole screen jolts on a hit. */
.impact { position: absolute; left: 50%; top: 50%; width: 100%; height: 100%; margin: -50% 0 0 -50%; border-radius: 50%; pointer-events: none; border: 2px solid var(--foam); opacity: 0; z-index: 2; }
.impact--miss { animation: splashring 520ms ease-out; }
.impact--hit { border-color: var(--fire); border-width: 3px; box-shadow: 0 0 12px var(--fire), inset 0 0 8px var(--fire); animation: hitring 640ms ease-out; }
@keyframes splashring { 0% { opacity: 1; transform: scale(0.3); } 100% { opacity: 0; transform: scale(2.6); } }
@keyframes hitring { 0% { opacity: 1; transform: scale(0.4); } 50% { opacity: 0.9; } 100% { opacity: 0; transform: scale(3.4); } }
.screens--shake { animation: screenshake 260ms ease; }
.screens--thud { animation: screenthud 360ms cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes screenshake { 15% { transform: translate(-5px, 3px); } 35% { transform: translate(5px, -4px); } 55% { transform: translate(-4px, 2px); } 75% { transform: translate(3px, 3px); } 90% { transform: translate(-1px, -1px); } }
@keyframes screenthud { 20% { transform: translateY(7px); } 50% { transform: translateY(-3px); } 100% { transform: none; } }
/* A ship sinks: each cell lists, slips under and settles as a wreck, one
   after the other from the stern. The wreck stays visible, low in the water. */
.cell--sinking { animation: sink 900ms ease-in both; }
@keyframes sink { 0% { transform: none; filter: brightness(1.6); } 35% { transform: rotate(-7deg) translateY(2%); } 100% { transform: rotate(12deg) translateY(38%) scale(0.86); filter: brightness(0.7); opacity: 0.75; } }
.cell--sunk.cell--settled { transform: rotate(12deg) translateY(38%) scale(0.86); filter: brightness(0.7); opacity: 0.75; }
.fleet__ship--sinking { animation: fleetsink 700ms ease-in both; }
@keyframes fleetsink { 0% { transform: none; } 100% { transform: translateY(2px) rotate(2deg); } }

.banner {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) rotate(-6deg);
  z-index: 3;
  padding: 10px 14px;
  text-align: center;
  font-size: clamp(22px, 7vw, 32px);
  letter-spacing: 0.16em;
  color: var(--ink);
  background: linear-gradient(180deg, #ff6a1f, #c23a00);
  border: 3px solid var(--red);
  border-radius: var(--radius);
  box-shadow: 0 0 28px rgba(255, 59, 59, 0.45);
  animation: bannerslam 320ms cubic-bezier(0.2, 1.4, 0.4, 1);
  pointer-events: none;
  max-width: 96%;
}
.banner--own { background: linear-gradient(180deg, #6b7a86, #45535e); color: var(--foam); border-color: var(--red); }
@keyframes bannerslam { from { transform: translate(-50%, -50%) rotate(-6deg) scale(2); opacity: 0; } to { transform: translate(-50%, -50%) rotate(-6deg) scale(1); opacity: 1; } }

.btn--half.btn--small { flex: 0 0 auto; }

/* ----------------------------------------------- Tuesday: game over ----- */
.outcome { text-align: center; font-size: 14px; letter-spacing: 0.22em; color: var(--foam); }
.outcome[data-result="win"] { color: var(--phosphor); }
.outcome[data-result="loss"] { color: var(--red); }
.outcome[data-result="draw"] { color: var(--amber); }
.boards-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; width: 100%; max-width: calc(var(--avail) * 0.62); }
.boards-2__col { display: flex; flex-direction: column; gap: 4px; align-items: center; min-width: 0; }
.boards-2 .board { width: 100%; grid-template-columns: 12px repeat(7, 1fr); grid-template-rows: 10px repeat(7, 1fr); gap: 2px; padding: 4px; }
.boards-2 .board__label { font-size: 8px; }
.stamp[data-verdict="verified"] { color: var(--phosphor); border-color: var(--phosphor); box-shadow: 0 0 24px rgba(61, 255, 143, 0.35); }
.stamp[data-verdict="liar"] { color: var(--red); border-color: var(--red); box-shadow: 0 0 28px rgba(255, 59, 59, 0.5); }
.stamp[data-verdict="forfeit"] { color: var(--amber); border-color: var(--amber); box-shadow: 0 0 24px var(--amber-dim); }
.stamp[data-verdict="pending"] { color: var(--amber); border-color: var(--amber); box-shadow: 0 0 24px var(--amber-dim); opacity: 0.85; }
.stamp__word { font-size: clamp(36px, 11vw, 52px); }
/* The stamp lands: it comes in big, overshoots, and settles, with a jolt
   through the whole screen (screens--thud) and the stamp thud in audio.js. */
.stamp--land { animation: stampslam 420ms cubic-bezier(0.2, 1.5, 0.4, 1) both; }
@keyframes stampslam { 0% { transform: rotate(-14deg) scale(2.6); opacity: 0; } 60% { transform: rotate(-14deg) scale(0.94); opacity: 1; } 100% { transform: rotate(-14deg) scale(1); opacity: 1; } }
.audit-detail { display: flex; flex-direction: column; gap: 3px; padding: 6px 8px; border: 1px solid var(--phosphor-dim); border-radius: var(--radius); font-family: var(--mono); font-size: 11px; line-height: 1.25; text-transform: none; color: var(--muted); max-height: calc(var(--avail) * 0.16); overflow: auto; flex: 0 0 auto; }
.audit-detail .bad { color: var(--red); }
.audit-detail .good { color: var(--phosphor); }
.contact[data-state="stale"] { color: var(--amber); border-color: var(--amber-dim); }

@media (prefers-reduced-motion: reduce) {
  .sonar__sweep, .sonar__blip, .badge__dot { animation: none; }
  .sonar-row--listening .sweep__arm, .sonar-row--chirping .sweep__disc, .sweep__blip, .sonar-row__heard { animation: none; }
  .cell--shake, .contact[data-state="contact"], .lamp__qr { animation: none; }
  .cell--burn, .cell--splash::before, .cell--flash, .board--shake, .banner, .stamp, .stamp--land { animation: none; }
  .impact, .screens--shake, .screens--thud, .cell--sinking, .fleet__ship--sinking { animation: none; }
}
