/* StarShot v2 — Astral Pirates theme */

:root {
  --void: #070b16;
  --panel: #10182b;
  --panel-edge: #2a3554;
  --parchment: #17203a;
  --gold: #d4a748;
  --gold-bright: #f2c96a;
  --crimson: #c33e3e;
  --teal: #3ea89b;
  --violet: #8b6fc9;
  --ink: #e8e0cc;
  --ink-dim: #9a97a8;
  --move: #3ea86b;
  --attack: #c9503e;
  --desperate: #a86fd4;
  --shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  background: var(--void);
  color: var(--ink);
  font-family: "Space Grotesk", "Segoe UI", sans-serif;
  overflow: hidden;
}

#starfield {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.screen {
  position: relative;
  z-index: 1;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: auto;
}

.hidden { display: none !important; }

h1, h2, .brand, .poster-title, .banner-text {
  font-family: "Pirata One", "IM Fell English", serif;
  letter-spacing: 0.04em;
}

.build-footer {
  flex: 0 0 auto;
  margin: 8px auto 14px;
  max-width: calc(100% - 24px);
  padding: 6px 10px;
  color: var(--ink-dim);
  font-size: 11px;
  line-height: 1.35;
  text-align: center;
}

/* ── buttons ─────────────────────────────── */
.btn {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 600;
  border: 1px solid var(--panel-edge);
  background: linear-gradient(180deg, #1b2542, #131b31);
  color: var(--ink);
  border-radius: 8px;
  padding: 9px 18px;
  cursor: pointer;
  transition: transform 0.12s, box-shadow 0.12s, filter 0.12s;
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.15); box-shadow: 0 4px 14px rgba(0,0,0,.4); }
.btn:active { transform: translateY(1px); }
.btn.gold {
  background: linear-gradient(180deg, #e3b95a, #b98a2e);
  border-color: #8a6620;
  color: #241a05;
  text-shadow: 0 1px 0 rgba(255,255,255,.25);
}
.btn.crimson {
  background: linear-gradient(180deg, #d15252, #93312d);
  border-color: #6e211e;
  color: #fff2ea;
}
.btn.ghost { background: transparent; }
.btn.small { padding: 5px 12px; font-size: 12px; }
.btn.big { padding: 14px 26px; font-size: 17px; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; filter: grayscale(0.4); }
.btn-sub { display: block; font-size: 11px; font-weight: 400; opacity: .75; }

/* ── auth poster ─────────────────────────── */
/* `justify-content: center` on a fixed-height flex column clips the TOP of an
   over-tall child with no way to scroll to it — and the poster grew a ship. So
   centre with `margin: auto` on the poster instead, which collapses to
   flex-start once it overflows, and let the screen scroll. */
#screen-auth { align-items: center; justify-content: flex-start; overflow-y: auto; }
#screen-auth .auth-poster { margin: auto 0; }

.auth-poster {
  width: min(420px, 92vw);
  padding: 42px 38px 34px;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(212,167,72,0.08), transparent 60%),
    linear-gradient(180deg, #141d36, #0d1426);
  border: 2px solid var(--gold);
  border-radius: 14px;
  outline: 1px solid #5c4a1d;
  outline-offset: 6px;
  box-shadow: var(--shadow), inset 0 0 60px rgba(0,0,0,.5);
  text-align: center;
}
/* Still used by admin.html's lock poster; the player sign-in poster leads with
   the ship instead. */
.poster-skull { font-size: 64px; filter: drop-shadow(0 0 14px rgba(212,167,72,.6)); }
/* The poster's centrepiece: a real captain's ship, as wide as the poster's
   content box allows (dogfight.js measures this element). The vh cap is a
   height budget — the ship is roughly square, so on a short window it has to
   give way or the sign-in buttons fall off the bottom. Shrunk from the old
   34vh to make room for the captain's name/record + "another captain" below
   it, which share the same budget. */
.auth-ship {
  /* Width AND height both cap at 28vh: dogfight.js fits the ship to this box
     on both axes (see measureSize there), so a long/narrow hull (2:1+
     aspect) shrinks to fit instead of overflowing top/bottom with its guns
     and engines cropped off — the "ship drawn without components" bug. */
  display: flex; justify-content: center; align-items: center; min-height: 1px;
  width: min(100%, 28vh); height: min(100%, 28vh); max-height: 28vh;
  margin: 0 auto 4px;
}
.auth-captain {
  display: flex; flex-direction: row; align-items: baseline; justify-content: center; gap: 8px;
  margin-bottom: 6px; font-family: "Pirata One", serif;
}
.auth-captain.hidden { display: none; }
.auth-captain-name { font-size: 17px; color: var(--gold-bright); }
.auth-captain-record { font-size: 12px; color: var(--ink-dim); letter-spacing: .04em; }
/* Ship itself is the "another captain" control now -- .clickable is only
   toggled on when the showcase pool has more than one captain to cycle to. */
.auth-ship.clickable { cursor: pointer; }

/* ── dogfighting ship (dogfight.js) ────────
   The <img> is the posed ship raster, sized in JS from the raster's own
   dimensions. Its tracer fx canvas is a SEPARATE element appended straight to
   <body> (see dogfight.js) — fixed to the true viewport so shots can cross the
   whole page, over every button, rather than being clipped to the ship's own
   box. pointer-events:none keeps it from blocking clicks on what it's drawn
   over.
   Two z-index tiers, matching what each ship sits behind:
   - .df-fx (background ships — the sign-in poster, the lobby card): above
     ordinary page chrome so shots still cross the topbar, but BELOW every
     full-screen overlay (.overlay/.bd-player-overlay/.mi-overlay start at 60)
     so StarDock, StarBreach, and any picker cover the tracers exactly as they
     already cover the ship art itself — dimmed together, not shots painted on
     top of a popup the ship is hidden behind.
   - .df-fx-front (the match-intro roster): those ships ARE the foreground —
     their own overlay is what the shots need to cross — so this sits above
     even that (70). */
.dogfight { position: relative; line-height: 0; pointer-events: none; }
.df-ship { display: block; image-rendering: pixelated; }
.df-fx {
  position: fixed; inset: 0; width: 100vw; height: 100vh;
  pointer-events: none; z-index: 8;
}
.df-fx-front { z-index: 90; }
.poster-title { font-size: 64px; color: var(--gold-bright); text-shadow: 0 0 24px rgba(212,167,72,.35); }
.poster-sub { letter-spacing: .42em; color: var(--crimson); font-weight: 600; margin-top: 2px; font-size: 13px; }
.poster-flavor { font-family: "IM Fell English", serif; font-style: italic; color: var(--ink-dim); margin: 16px 0 22px; line-height: 1.5; }

.auth-tabs { display: flex; gap: 6px; justify-content: center; margin-bottom: 14px; }
.auth-tab {
  background: none; border: none; color: var(--ink-dim);
  font-family: "Pirata One", serif; font-size: 20px; cursor: pointer; padding: 4px 14px;
  border-bottom: 2px solid transparent;
}
.auth-tab.active { color: var(--gold-bright); border-bottom-color: var(--gold); }

#auth-form { display: flex; flex-direction: column; gap: 10px; }
#auth-form input {
  background: #0a1020; border: 1px solid var(--panel-edge); border-radius: 8px;
  color: var(--ink); padding: 12px 14px; font-size: 15px; font-family: inherit;
}
#auth-form input:focus { outline: none; border-color: var(--gold); }
.auth-error { color: #ff9a8a; min-height: 20px; margin-top: 10px; font-size: 13px; }
.auth-divider { color: var(--ink-dim); font-size: 12px; letter-spacing: .2em; margin: 14px 0 10px; }
.google-signin { display: flex; justify-content: center; min-height: 44px; color-scheme: light; }
.pw-form { display: flex; gap: 10px; flex-wrap: wrap; }
.pw-form input {
  background: #0a1020; border: 1px solid var(--panel-edge); border-radius: 8px;
  color: var(--ink); padding: 10px 12px;
}
.microsoft-signin {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 280px; min-height: 40px; margin-top: 10px; padding: 0 12px;
  background: #fff; color: #3c4043; border: 1px solid #dadce0; border-radius: 20px;
  font-size: 14px; font-family: inherit; cursor: pointer;
}
.microsoft-signin:hover { background: #f7f8f8; }
.discord-signin {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 280px; min-height: 40px; margin-top: 10px; padding: 0 12px;
  background: #5865f2; color: #fff; border: 1px solid #4752c4; border-radius: 20px;
  font-size: 14px; font-family: inherit; cursor: pointer;
}
.discord-signin:hover { background: #4752c4; }

/* ── topbar ──────────────────────────────── */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 18px;
  background: linear-gradient(180deg, rgba(16,24,43,.95), rgba(16,24,43,.75));
  border-bottom: 1px solid var(--panel-edge);
  backdrop-filter: blur(4px);
  flex: 0 0 auto;
  /* backdrop-filter creates a stacking context; without its own z-index the
     topbar (and everything in it, like .user-popup) paints below whatever
     sibling content follows it in the DOM, popup z-index notwithstanding. */
  position: relative;
  z-index: 100;
}
/* Name, action buttons, admin link and account menu all share this one row —
   they used to stack onto three, eating vertical space the board/lobby panels
   never got back. `.topbar-actions` carries the auto margin that pushes
   everything after the brand to the right; wrapping is the fallback for a
   narrow desktop window, not the default. */
#screen-lobby .topbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}
.brand { font-size: 26px; color: var(--gold-bright); flex: 0 1 auto; }
.brand-skull { filter: drop-shadow(0 0 8px rgba(212,167,72,.7)); }
.brand-tag { font-family: "Space Grotesk"; font-size: 11px; color: var(--ink-dim); letter-spacing: .1em; }
.topbar-right { display: flex; align-items: center; gap: 10px; }
.admin-test-row { display: flex; align-items: center; gap: 6px; opacity: 0.55; }
.admin-test-row .btn { font-size: 11px; padding: 4px 8px; }
.admin-test-row:hover { opacity: 1; }
.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
  justify-content: flex-end;
}
.topbar-admin-row {
  display: flex;
  align-items: center;
}
/* Icon-only variants of the topbar action buttons; shown only on phone
   (see the phone media query), where full labels don't fit one row. */
.tb-icon { display: none; }
.topbar-account {
  position: relative;
}
.user-chip {
  color: var(--gold); font-weight: 600;
  display: block; overflow: hidden; white-space: nowrap; min-width: 0; max-width: 100%;
}
.user-chip-scroll { display: inline-block; }
.user-chip-scroll.scrolling { animation: userChipScroll var(--marquee-time, 6s) ease-in-out infinite; }
@keyframes userChipScroll {
  0%, 12% { transform: translateX(0); }
  50%, 62% { transform: translateX(var(--marquee-shift, 0)); }
  100% { transform: translateX(0); }
}
.user-menu-button {
  align-items: center;
  display: inline-flex;
  gap: 8px;
}
.hamburger {
  color: var(--gold-bright);
  font-size: 15px;
  line-height: 1;
}
.user-popup {
  background: rgba(7, 11, 22, 0.98);
  border: 1px solid rgba(212, 167, 72, 0.38);
  border-radius: 8px;
  box-shadow: var(--shadow);
  display: grid;
  gap: 8px;
  min-width: 180px;
  padding: 8px;
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 95;
}
.user-popup .btn {
  justify-content: flex-start;
  text-align: left;
  width: 100%;
}

/* ── lobby ───────────────────────────────── */
.lobby-grid {
  display: grid; grid-template-columns: 310px minmax(360px, 1fr) 340px; gap: 18px;
  padding: 18px; max-width: 1440px; margin: 0 auto; width: 100%;
}
.panel {
  background: linear-gradient(180deg, rgba(20,29,54,.92), rgba(13,20,38,.92));
  border: 1px solid var(--panel-edge);
  border-radius: 12px;
  padding: 18px;
  box-shadow: var(--shadow);
}
.panel-title { color: var(--gold-bright); font-size: 26px; margin-bottom: 12px; }
.panel-sub { color: var(--gold); font-size: 15px; letter-spacing: .06em; text-transform: uppercase; margin: 18px 0 8px; }

/* Your Ship card on the landing page (center column, above Raids). */
.my-ship-card {
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
  background: radial-gradient(120% 100% at 50% 0%, rgba(30,44,80,.55), rgba(11,17,33,.55));
  padding: 12px 14px;
  margin-bottom: 18px;
}
.my-ship-card:empty { display: none; }
.my-ship-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  cursor: pointer; border-radius: 6px;
}
.my-ship-head[role="button"]:hover .my-ship-editlink { opacity: 1; }
.my-ship-head[role="button"]:focus-visible { outline: 1px solid var(--gold); outline-offset: 2px; }
.my-ship-eyebrow { color: var(--gold); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }
.my-ship-editlink { color: var(--gold-bright); font-size: 12px; opacity: .8; transition: opacity .15s; }
.my-ship-body { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.my-ship-hex {
  width: 100%; display: block; background: none; border: 1px solid transparent; border-radius: 10px;
  padding: 4px; cursor: pointer; line-height: 0; transition: border-color .15s;
}
.my-ship-hex:hover { border-color: var(--gold); }
.my-ship-hex svg { display: block; width: 100%; max-height: 260px; margin: 0 auto; }
/* The ship fills the panel's width — dogfight.js measures this button's content
   box, so it must not constrain the art any further. */
.my-ship-hex .dogfight { margin: 0 auto; }
.my-ship-meta { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.my-ship-name { color: var(--gold-bright); font-size: 22px; font-family: "Pirata One", serif; }
.my-ship-select {
  background: rgba(8,13,26,.85); color: var(--ink, #e8e0cc);
  border: 1px solid var(--panel-edge); border-radius: 6px; padding: 5px 8px; font-size: 14px; max-width: 240px;
}
.my-ship-guestnote { color: var(--ink-dim, #9aa6bd); font-size: 12px; font-style: italic; }

.sail-row { display: flex; align-items: center; gap: 16px; }
.lobby-setup .sail-row,
.lobby-setup .crew-controls {
  align-items: stretch;
  flex-direction: column;
}
.lobby-setup .btn.big,
.lobby-setup #btn-create-match {
  width: 100%;
}
.duel-row { display: flex; gap: 12px; width: 100%; }
.lobby-pvp-challenge { border-bottom: 1px solid var(--panel-edge); padding-bottom: 16px; margin-bottom: 10px; }
.lobby-pvp-challenge .panel-title { margin-bottom: 10px; }
.lobby-pvp-challenge #btn-create-match { width: 100%; margin-top: 10px; }
.lobby-open-raids { margin-top: 18px; border-top: 1px solid var(--panel-edge); padding-top: 2px; }
.lobby-section-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.lobby-section-head .panel-sub { margin-bottom: 8px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.aid-code-entry { margin: 2px 0 10px; padding: 8px; border: 1px solid rgba(214,166,54,.45); border-radius: 5px; background: rgba(214,166,54,.08); }
.aid-code-label { display: block; margin-bottom: 5px; color: var(--gold-bright); font-size: 12px; font-weight: 600; }
.aid-code-entry form { display: flex; gap: 6px; }
.aid-code-entry input { min-width: 0; flex: 1; }
.aid-code-entry .btn { flex: 0 0 auto; }
.auth-aid-entry { width: 100%; margin: 10px 0 0; }
.auth-aid-entry input { width: 100%; text-align: center; }
.raid-aid-code { margin-top: 3px; color: var(--gold-bright); font: 600 12px "Space Grotesk", sans-serif; }
.raid-cap-bar { display: flex; gap: 10px; flex-wrap: wrap; margin: 6px 0 10px; padding: 6px 8px; border: 1px solid rgba(214,166,54,.45); border-radius: 5px; color: var(--gold-bright); font-size: 12px; }
.lobby-pvp-challenge { margin-top: 18px; }
.lobby-pvp-challenge > #btn-pvp-raid { width: 100%; margin-bottom: 8px; }
.lobby-pvp-challenge > .duel-row,
.lobby-pvp-challenge > #btn-create-match { display: none; }
.pvp-raid-builder,
.arena-builder { max-width: min(760px, 94vw); max-height: 90vh; overflow: auto; }
.pvp-raid-builder .crew-builder,
.arena-builder .crew-builder { display: block; }
.arena-notice {
  color: var(--gold-bright);
  background: rgba(214, 166, 54, .12);
  border: 1px solid rgba(214, 166, 54, .45);
  border-radius: 5px;
  padding: 6px 10px;
  font-size: 12px;
  margin: 0 0 10px;
}
.lobby-setup .duel-row .btn.big { width: auto; flex: 1; }
.duel-btn { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.duel-btn .btn-icon { font-size: 20px; line-height: 1; }
.lobby-setup .advanced-features,
.lobby-setup .foes-group,
.lobby-setup .flesh-foes {
  width: 100%;
}
.queue-status { color: var(--ink-dim); display: flex; align-items: center; gap: 10px; }
.spinner {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid var(--gold); border-top-color: transparent;
  animation: spin 0.9s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

.crew-builder { display: flex; flex-direction: column; gap: 10px; }
.crew-controls { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* One unscoped grid — the arena overlay relocates .crew-builder to
   document.body, so any rule scoped under .lobby-setup silently stops
   applying there and the picker falls back to ragged flex-wrap rows with
   names starting at different offsets per card. A single rule with no
   ancestor scoping means the in-page builder and the arena overlay can
   never disagree, in either desktop or mobile widths. */
#ai-pickers {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  width: 100%;
}
.ai-pick {
  align-items: center;
  border: 1px solid var(--panel-edge); border-radius: 10px; padding: 7px 5px;
  background: #0d1426; cursor: pointer; text-align: center; user-select: none;
  display: grid;
  gap: 5px;
  grid-template-areas:
    "name name name"
    "face blurb count";
  grid-template-columns: auto minmax(0, 1fr) auto;
  min-height: 46px;
  transition: border-color .15s, box-shadow .15s;
}
.ai-pick .ai-face { font-size: 18px; grid-area: face; line-height: 1; }
.ai-pick .ai-name {
  color: var(--ink);
  font-size: 12px;
  font-weight: 800;
  grid-area: name;
  line-height: 1.15;
  min-width: 0;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ai-pick .ai-blurb {
  color: var(--ink-dim);
  font-size: 9.5px;
  font-style: italic;
  grid-area: blurb;
  line-height: 1.12;
  min-width: 0;
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ai-pick .ai-count { color: var(--gold-bright); font-weight: 800; font-size: 15px; grid-area: count; }
.ai-pick.picked { border-color: var(--gold); box-shadow: 0 0 10px rgba(212,167,72,.35); }
.arena-ai-pick {
  appearance: none;
  color: var(--ink);
  font: inherit;
  grid-template-areas: "icon rank count";
  grid-template-columns: 1fr auto auto;
  min-width: 0;
  min-height: 58px;
  padding: 7px 9px;
  text-align: left;
}
.arena-ai-pick .arena-ai-icon {
  align-items: center;
  color: var(--gold-bright);
  display: inline-flex;
  grid-area: icon;
  height: 32px;
  justify-content: center;
  width: 36px;
}
.arena-ai-pick .arena-ai-icon { font-size: 28px; line-height: 1; }
.arena-ai-pick .arena-ai-icon img { display: block; height: 32px; image-rendering: pixelated; object-fit: contain; width: 32px; }
.arena-ai-pick .arena-ai-rank { color: var(--ink-dim); font-size: 17px; font-weight: 900; grid-area: rank; letter-spacing: .04em; }
.arena-ai-pick .ai-count { align-self: start; grid-area: count; justify-self: end; }
.arena-ai-pick:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
.open-seats-label { color: var(--ink-dim); font-size: 13px; }
.open-seats-label select { background: #0d1426; color: var(--ink); border: 1px solid var(--panel-edge); border-radius: 6px; padding: 4px 6px; }
.ai-level-label,
.open-seats-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ai-level-label #ai-level,
.open-seats-label #open-seats {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.choice-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.choice-button {
  background: #0d1426;
  border: 1px solid var(--panel-edge);
  border-radius: 8px;
  color: var(--ink-dim);
  cursor: pointer;
  font: 700 12px "Space Grotesk", sans-serif;
  min-height: 34px;
  padding: 7px 10px;
}
.choice-button.active {
  background: rgba(212, 167, 72, 0.18);
  border-color: rgba(212, 167, 72, 0.7);
  color: var(--gold-bright);
  box-shadow: 0 0 0 1px rgba(212, 167, 72, 0.18) inset;
}
.choice-button:disabled,
.choice-button.disabled {
  cursor: not-allowed;
  opacity: 0.35;
}
.choice-buttons.compact .choice-button {
  min-width: 38px;
  padding-left: 12px;
  padding-right: 12px;
}
.flesh-foes .choice-button {
  font-size: 16px;
  min-height: 40px;
}
.ai-level-label .choice-buttons {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.ai-level-label .choice-button {
  font-size: 12px;
  min-height: 34px;
  padding: 7px 5px;
  white-space: nowrap;
}
.flesh-foes {
  min-width: 220px;
}

.match-list { display: flex; flex-direction: column; gap: 8px; }
.match-row {
  align-items: center;
  background: #0d1426;
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(0, 1fr) max-content;
  padding: 10px 14px;
}
.match-info { min-width: 0; }
.match-row .match-name { font-weight: 600; }
.match-row .match-meta { color: var(--ink-dim); font-size: 12px; line-height: 1.35; }
.match-actions {
  display: flex;
  flex: 0 0 auto;
  flex-wrap: nowrap;
  gap: 6px;
  justify-content: flex-end;
  min-width: max-content;
}
.match-actions .btn { white-space: nowrap; }
.match-actions .btn:not(:only-child):not([title]) { min-width: 84px; }
.match-actions .btn[title] { min-width: 36px; }
.match-row.complete { opacity: .65; }
.raid-row {
  display: flex; flex-direction: column; gap: 3px;
  padding: 6px 10px;
}
.raid-row-bottom { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.raid-row-bottom .match-name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.raid-row-bottom .btn { flex: 0 0 auto; }
.raid-status-box {
  display: inline-block; align-self: flex-start;
  border-radius: 5px; padding: 1px 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
}
.raid-status-red { background: rgba(195,62,62,.22); border: 1px solid rgba(255,105,97,.65); color: #ff9a94; }
.raid-status-green { background: rgba(95,180,120,.2); border: 1px solid rgba(111,220,140,.6); color: #8be6a4; }
.raid-status-yellow { background: rgba(224,196,104,.2); border: 1px solid rgba(224,196,104,.65); color: #e0c468; }
.raid-status-blue { background: rgba(95,179,255,.18); border: 1px solid rgba(95,179,255,.6); color: #8fc7ff; }
.raid-status-purple { background: rgba(178,126,255,.18); border: 1px solid rgba(178,126,255,.62); color: #d4bcff; }
.raid-row-answered {
  border-color: var(--pop-color, var(--gold)) !important;
  box-shadow: 0 0 0 1px var(--pop-color, var(--gold)), 0 0 10px 1px var(--pop-color, var(--gold));
  animation: raidPop 1.4s ease-in-out infinite;
}
@keyframes raidPop { 50% { box-shadow: 0 0 0 1px var(--pop-color, var(--gold)), 0 0 16px 4px var(--pop-color, var(--gold)); } }
.raid-pager { display: flex; align-items: center; gap: 6px; }
.raid-pager .btn { min-width: 28px; padding: 2px 8px; }
#general-sos-page-label { font-size: 11px; }
.match-expansions {
  display: inline-flex;
  gap: 3px;
  margin-left: 6px;
  vertical-align: 1px;
}
.match-expansion {
  background: rgba(62,168,155,.18);
  border: 1px solid rgba(62,168,155,.55);
  border-radius: 4px;
  color: #9ce7db;
  font-size: 10px;
  font-weight: 800;
  line-height: 1.35;
  padding: 1px 5px;
}
.empty-note { color: var(--ink-dim); font-style: italic; font-size: 13px; padding: 6px 2px; }
.battle-history-notice {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 2px 2px; border-top: 1px dashed var(--panel-edge); font-size: 12px;
}

.maintenance-banner {
  margin: 14px auto 0; max-width: 1244px; width: calc(100% - 36px);
  border: 1px solid var(--gold); border-radius: 10px;
  background: rgba(212,167,72,.12); color: var(--gold-bright);
  padding: 12px 18px; font-size: 14px;
  animation: calloutPop .35s ease-out;
}

.players-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 20px; }
.player-row {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--panel-edge); border-radius: 8px;
  padding: 7px 10px; background: #0d1426; font-size: 13px;
}
.player-row .player-dot { color: #6fdc8c; font-size: 10px; }
.player-row .player-name { font-weight: 600; flex: 1 1 auto; }
.player-row .player-record { color: var(--ink-dim); font-size: 11px; }

.challenge-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  border: 1px solid var(--crimson); border-radius: 10px;
  background: rgba(195,62,62,.12); padding: 10px 12px; margin-bottom: 8px;
  animation: calloutPop .35s ease-out;
}
.challenge-banner.outgoing { border-color: var(--gold); background: rgba(212,167,72,.08); }
.challenge-banner .challenge-actions { display: flex; gap: 6px; }

.badge-turn {
  background: var(--gold); color: #241a05; border-radius: 5px; padding: 1px 8px;
  font-size: 11px; font-weight: 700; margin-left: 6px;
  animation: turnPulse 1.4s ease-in-out infinite;
}
@keyframes turnPulse { 50% { box-shadow: 0 0 12px rgba(212,167,72,.9); } }

/* Lobby "How to Play" button: twinkles until the tutorial has been opened
   at least once (see Tutorial.showDeck / lobby.js). */
.btn.twinkle {
  border-color: var(--gold);
  animation: helpTwinkle 1.6s ease-in-out infinite;
}
@keyframes helpTwinkle {
  0%, 100% { box-shadow: 0 0 0 rgba(212,167,72,0); }
  50%      { box-shadow: 0 0 12px rgba(212,167,72,.9); }
}
@media (prefers-reduced-motion: reduce) {
  .btn.twinkle { animation: none; }
}
.match-row.your-turn { border-color: var(--gold); }
.badge-fled {
  background: rgba(154,151,168,.18); color: #cfcbdd; border-radius: 5px;
  padding: 1px 8px; font-size: 11px; margin-left: 6px;
}

.leaderboard { width: 100%; border-collapse: collapse; font-size: 14px; }
.leaderboard th { text-align: left; color: var(--ink-dim); font-weight: 400; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; padding: 4px 6px; }
.leaderboard td { padding: 6px; border-top: 1px solid rgba(42,53,84,.5); }
.leaderboard tr:first-child td { color: var(--gold-bright); }
.title-holders {
  border: 1px solid rgba(212,167,72,.42);
  border-radius: 8px;
  background: rgba(212,167,72,.08);
  margin-bottom: 14px;
  padding: 8px 10px;
}
.title-row {
  align-items: center;
  display: grid;
  gap: 8px;
  grid-template-columns: 86px minmax(0, 1fr) auto;
  font-size: 12px;
  padding: 3px 0;
}
.title-name { color: var(--gold-bright); font-weight: 700; }
.leaderboard-timer {
  background: rgba(154,151,168,.18);
  border-radius: 999px;
  height: 4px;
  margin-top: 8px;
  overflow: hidden;
}
.leaderboard-timer span {
  animation: leaderboardFill 10s linear forwards;
  background: var(--gold);
  display: block;
  height: 100%;
  width: 0;
}
@keyframes leaderboardFill { to { width: 100%; } }
.profile-card { line-height: 1.9; color: var(--ink-dim); }
.profile-card b { color: var(--ink); }
.profile-username { color: var(--ink-dim); font-size: 12px; }
.name-flagged-note { color: #e08a4d; font-size: 12px; line-height: 1.4; display: inline-block; }
.name-modal input { text-transform: none; }
.feedback-badge {
  display: inline-flex; align-items: center; gap: 4px;
  background: rgba(212,167,72,.18); border: 1px solid rgba(212,167,72,.55);
  color: var(--gold-bright); border-radius: 999px; padding: 1px 7px;
  font-size: 11px; font-weight: 700; line-height: 1.5; white-space: nowrap;
}

/* ── game layout ─────────────────────────── */
.game-grid {
  display: grid;
  /* Fleet/Log used to be a third, always-visible column here (270px). It's
     now a pop-out drawer docked to the board's own left edge (see
     .fleet-panel / .fleet-drawer-toggle below) so the board gets that width
     back; only Orders remains a fixed side column. */
  grid-template-columns: minmax(0, 1fr) 560px;
  gap: 12px; padding: 12px;
  flex: 1 1 auto; min-height: 0;
}
.game-banner {
  font-family: "Pirata One", serif; font-size: 22px; color: var(--gold-bright);
  text-shadow: 0 0 12px rgba(212,167,72,.4);
}

.fleet-panel { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
/* Desktop: Fleet/Log as a pop-out drawer docked to the board's left edge,
   rather than its own always-visible grid column (see .game-grid above).
   Lives inside #board-wrap in the HTML so this positions against the board,
   not the whole game-grid. Phone keeps its own bottom-sheet treatment
   (:root[data-device="phone"] .fleet-panel, further down) untouched — this
   whole block is scoped off phone so the two can never fight over the same
   properties. */
:root[data-device="desktop"] .fleet-panel {
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 270px;
  z-index: 6;
  border-radius: 0 12px 12px 0;
  box-shadow: 10px 0 30px rgba(0,0,0,.45);
  transform: translateX(-100%);
  transition: transform 200ms ease;
}
:root[data-device="desktop"] .fleet-panel.open { transform: translateX(0); }
:root[data-device="desktop"] .fleet-drawer-toggle {
  position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  z-index: 7;
  writing-mode: vertical-rl; text-orientation: mixed;
  background: rgba(13,20,38,.92);
  border: 1px solid var(--panel-edge); border-left: none;
  border-radius: 0 8px 8px 0;
  color: var(--gold-bright);
  font: 700 12px "Space Grotesk", sans-serif; letter-spacing: .06em; text-transform: uppercase;
  padding: 16px 6px;
  cursor: pointer;
  transition: left 200ms ease, border-color .15s;
}
:root[data-device="desktop"] .fleet-drawer-toggle:hover { border-color: var(--gold); }
:root[data-device="desktop"] #board-wrap.fleet-drawer-open .fleet-drawer-toggle { left: 270px; }
:root[data-device="phone"] .fleet-drawer-toggle { display: none; }
.side-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 10px; }
.side-tab {
  background: rgba(13,20,38,.88);
  border: 1px solid var(--panel-edge);
  border-radius: 7px;
  color: var(--ink-dim);
  cursor: pointer;
  font: 700 12px "Space Grotesk", sans-serif;
  min-height: 34px;
}
.side-tab.active {
  background: rgba(212,167,72,.18);
  border-color: rgba(212,167,72,.65);
  color: var(--gold-bright);
}
.side-tab-panel { display: none; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.side-tab-panel.active { display: flex; flex-direction: column; }
#fleet-list { display: flex; flex: 1 1 auto; flex-direction: column; gap: 8px; overflow-y: auto; min-height: 0; }
.fleet-card {
  border: 1px solid var(--panel-edge); border-left-width: 4px; border-radius: 8px;
  padding: 8px 10px; background: #0d1426; font-size: 13px;
}
.fleet-card { cursor: pointer; transition: border-color .15s; }
.fleet-card:hover { border-color: var(--gold); }
.fleet-card.mine { background: #101a30; }
.fleet-card .fc-name { font-weight: 700; display: flex; justify-content: space-between; align-items: center; }
.fleet-card .fc-body { display: flex; gap: 10px; align-items: center; margin-top: 4px; }
.fleet-card .fc-mini svg { display: block; }

/* ── shared ship-raster frame clock ────────────────────────────────────────
   Animated ship art emits one <image> per animation frame, all tagged
   .sp-frame with a data-frame index; a single JS timer (shipview.js) stamps
   the current index on <html> and these rules show exactly one of them.

   This replaces per-element SMIL <animate>, which re-rasterised the whole SVG
   on every tick and rebuilt its timeline on every re-render. Anything that
   needs a cycling ship raster should join this clock rather than starting a
   timer or animation of its own — see docs/context/rendering_performance.md. */
.sp-frame { visibility: hidden; }
html[data-sp-frame="0"] .sp-frame[data-frame="0"],
html[data-sp-frame="1"] .sp-frame[data-frame="1"],
html[data-sp-frame="2"] .sp-frame[data-frame="2"],
html[data-sp-frame="3"] .sp-frame[data-frame="3"] { visibility: visible; }
/* No clock running (reduced motion, or the low performance tier): the first
   frame is the ship's resting pose and simply stays up. */
html:not([data-sp-frame]) .sp-frame[data-frame="0"] { visibility: visible; }
.fleet-card .fc-sub { color: var(--ink-dim); font-size: 11px; display: flex; flex-direction: column; gap: 2px; }
.ship-modal { max-width: 760px; width: min(760px, 94vw); }
.ship-modal-zoom-wrap {
  overflow: hidden; touch-action: none; /* we handle pinch ourselves */
  border-radius: 8px;
}
.ship-modal-zoom-inner {
  transform-origin: center center; transition: transform .06s linear;
}
.ship-cell.selectable { cursor: pointer; }
.ship-cell.selectable polygon { filter: drop-shadow(0 0 6px rgba(212,167,72,.75)); }
.ship-cell.selectable:hover polygon { stroke: var(--gold-bright) !important; stroke-width: 3; }
.ship-cell.picked polygon { stroke: var(--gold-bright) !important; stroke-width: 3; }
.ship-cell.picked { opacity: .85; }
.fleet-card .vp { color: var(--gold-bright); }
.fleet-card.dead { opacity: .5; filter: grayscale(.7); }
.fleet-card .status-dot { font-size: 10px; }
.shield-pips { letter-spacing: 2px; color: var(--teal); }
.hull-pips { letter-spacing: 2px; color: var(--crimson); }
.badge-ai { background: rgba(139,111,201,.25); color: #c9b3ee; border-radius: 4px; padding: 1px 6px; font-size: 10px; }
.badge-you { background: rgba(212,167,72,.25); color: var(--gold-bright); border-radius: 4px; padding: 1px 6px; font-size: 10px; }
.badge-ally { background: rgba(62,168,155,.25); color: #9ce7db; border-radius: 4px; padding: 1px 6px; font-size: 10px; font-weight: 700; }
.fleet-card.ally { background: rgba(62,168,155,.08); }
.team-score {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}
.team-score-pill {
  border: 1px solid var(--panel-edge);
  border-left-width: 3px;
  border-radius: 6px;
  color: var(--ink-dim);
  font-size: 12px;
  padding: 3px 8px;
}
.team-score-pill.mine { color: var(--ink); background: rgba(62,168,155,.1); }
.team-score-pill strong { color: var(--gold-bright); }
.badge-title { background: rgba(62,168,155,.22); color: #9ce7db; border-radius: 4px; padding: 1px 6px; font-size: 10px; }
.badge-alpha { background: rgba(224,86,60,.25); color: #ff9b7f; border-radius: 4px; padding: 1px 6px; font-size: 10px; font-weight: 700; letter-spacing: 0.03em; vertical-align: middle; }
.badge-wait { color: var(--ink-dim); font-size: 10px; }
.badge-ready { color: var(--move); font-size: 10px; }

.group-box {
  border: 1px solid var(--panel-edge);
  border-radius: 8px;
  padding: 10px 12px;
  background: rgba(10,16,32,.55);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.group-box-title { color: var(--gold); font-size: 11px; text-transform: uppercase; margin-bottom: -2px; }
.advanced-features-toggle {
  all: unset;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--gold);
  font-size: 11px;
  text-transform: uppercase;
}
.advanced-features-toggle:hover { color: var(--gold-bright); }
.advanced-features-arrow { font-size: 9px; }
.advanced-features-body { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.foes-group { align-items: flex-start; }

.expansion-box {
  border: 1px solid var(--panel-edge);
  border-radius: 8px;
  padding: 10px 12px;
  background: rgba(10,16,32,.55);
}
.expansion-title { color: var(--gold); font-size: 11px; text-transform: uppercase; margin-bottom: 6px; }
.expansion-toggle { display: flex; align-items: center; gap: 8px; color: var(--ink); font-size: 13px; }
.expansion-toggle input { accent-color: var(--gold); }
.expansion-toggle {
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 5px 6px;
}
.expansion-toggle.active {
  background: rgba(212, 167, 72, 0.12);
  border-color: rgba(212, 167, 72, 0.42);
  color: var(--gold-bright);
}
.expansion-toggle input {
  flex: 0 0 auto;
  height: 18px;
  width: 18px;
}
.expansion-detail {
  border-left: 2px solid rgba(212, 167, 72, 0.35);
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -2px 0 4px 15px;
  padding: 4px 0 6px 10px;
}
.expansion-detail .open-seats-label {
  width: 100%;
}
.expansion-detail .open-seats-label select {
  min-width: min(260px, 100%);
}
.coop-box { margin-top: 8px; }
.coop-detail {
  border-left: 2px solid rgba(62, 168, 155, 0.4);
  margin: -2px 0 4px 15px;
  padding: 4px 0 6px 10px;
}
.coop-hint { color: var(--ink-dim); font-size: 12px; margin: 2px 0 8px; }
.coop-roster { display: flex; flex-direction: column; gap: 6px; }
.coop-roster-row {
  align-items: center;
  display: flex;
  gap: 8px;
  justify-content: space-between;
}
.coop-roster-name { color: var(--ink); font-size: 13px; }
.coop-team-buttons { display: inline-flex; gap: 4px; }
.coop-team-btn {
  background: rgba(10, 16, 32, 0.6);
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  color: var(--ink-dim);
  cursor: pointer;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 8px;
}
.coop-team-btn.active.coop-team-crew {
  background: rgba(62, 168, 155, 0.22);
  border-color: rgba(62, 168, 155, 0.7);
  color: #9ce7db;
}
.coop-team-btn.active.coop-team-raiders {
  background: rgba(224, 86, 60, 0.22);
  border-color: rgba(224, 86, 60, 0.7);
  color: #ff9b7f;
}
.match-expansion-coop {
  background: rgba(120, 92, 220, 0.2);
  border-color: rgba(120, 92, 220, 0.6);
  color: #c3b3ff;
}
.builder-icon-btn {
  align-items: center;
  display: inline-flex;
  font-size: 15px;
  justify-content: center;
  min-height: 32px;
  min-width: 36px;
  padding: 5px 8px;
}
.tutorial-steps { display: grid; gap: 10px; text-align: left; color: var(--ink-dim); font-size: 13px; line-height: 1.4; }
.tutorial-role { margin-left: 18px; padding-left: 10px; border-left: 2px solid rgba(212,167,72,.3); }
.tutorial-alpha-note { text-align: left; font-size: 12px; font-style: italic; color: #ff9b7f; margin: -4px 0 10px; }

.log-actions {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 8px;
}
.action-log { flex: 1 1 auto; overflow-y: auto; font-size: 12px; line-height: 1.55; color: var(--ink-dim); min-height: 0; }
.action-log .log-entry { padding: 3px 4px; border-bottom: 1px solid rgba(42,53,84,.35); }
.action-log .log-entry.hit { color: #f0b0a0; }
.action-log .log-entry.loot { color: var(--gold); }
.action-log .log-entry.round { color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 14px; }

/* board */
.board-wrap {
  position: relative; border-radius: 12px; overflow: hidden;
  border: 1px solid var(--panel-edge); background:
    radial-gradient(60% 50% at 30% 30%, rgba(62,120,168,.10), transparent),
    radial-gradient(50% 45% at 72% 68%, rgba(139,60,90,.10), transparent),
    #060a14;
  min-height: 0;
}
#board { width: 100%; height: 100%; display: block; }
/* Blitz's 3D view (blitz3d.js). Sits under #fx so every existing FX.* effect
   (lasers, impacts, plumes) still draws over it via Board.hexToScreen's
   mirror-aware projection — see board.js's mirrorCall / blitz3d.js's header
   comment. Only ever shown for a Blitz match; classic games never remove its
   `hidden` class. */
#board3d { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
#fx { position: absolute; inset: 0; pointer-events: none; }
.blitz3d-fps {
  position: absolute; left: 10px; top: 10px; z-index: 5;
  font: 11px/1 ui-monospace, Menlo, Consolas, monospace; color: #9ee7ff;
  background: rgba(4,7,14,.7); border: 1px solid #2b3f66; border-radius: 4px;
  padding: 3px 6px; pointer-events: none;
}
.board-controls { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.zoom-controls {
  display: flex;
  gap: 4px;
  padding: 3px;
  border: 1px solid rgba(42,53,84,.7);
  border-radius: 8px;
  background: rgba(6,10,20,.58);
}
.zoom-controls .btn {
  min-width: 30px;
  padding: 4px 7px;
  text-align: center;
}
.board-callout {
  position: absolute; left: 50%; top: 14%; transform: translateX(-50%);
  font-family: "Pirata One", serif; font-size: 34px; color: var(--gold-bright);
  text-shadow: 0 0 18px rgba(212,167,72,.65), 0 2px 4px #000;
  pointer-events: none; animation: calloutPop .5s ease-out;
  z-index: 5; white-space: nowrap;
}
.board-callout.crimson { color: #ff8d7a; text-shadow: 0 0 18px rgba(201,80,62,.7), 0 2px 4px #000; }
.board-status-stack {
  position: absolute; left: 14px; top: 12px; z-index: 4;
  max-width: min(420px, calc(100% - 110px));
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.starfall-status,
.captain-status {
  border: 1px solid rgba(212,167,72,.65);
  border-radius: 8px;
  padding: 8px 10px;
  background: rgba(9,14,27,.84);
  box-shadow: 0 6px 20px rgba(0,0,0,.35);
}
.captain-status { border-color: rgba(126,216,255,.55); }
.scenario-status {
  box-sizing: border-box;
  cursor: pointer;
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  height: 34px;
  max-width: 34px;
  width: 34px;
  min-height: 34px;
  overflow: hidden;
  padding: 5px;
  transition: max-width 180ms ease, padding 180ms ease, border-color 180ms ease, width 180ms ease;
}
.scenario-status::before {
  align-self: center;
  color: var(--gold-bright);
  content: attr(data-icon);
  font-family: "Pirata One", serif;
  font-size: 18px;
  line-height: 1;
  text-align: center;
}
.scenario-status b,
.scenario-status span {
  grid-column: 2;
  min-width: 0;
  opacity: 0;
  pointer-events: none;
  transform: translateX(-6px);
  transition: opacity 130ms ease, transform 130ms ease;
  width: min(360px, calc(100vw - 70px));
}
.scenario-status:hover,
.scenario-status:focus-within,
.scenario-status.status-expanded {
  height: auto;
  max-width: min(420px, calc(100vw - 28px));
  padding: 8px 10px;
  width: max-content;
}
.scenario-status:hover b,
.scenario-status:hover span,
.scenario-status:focus-within b,
.scenario-status:focus-within span,
.scenario-status.status-expanded b,
.scenario-status.status-expanded span {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(0);
}
.scenario-status.status-rolled-up,
.scenario-status.status-rolled-up:hover,
.scenario-status.status-rolled-up:focus-within {
  height: 34px;
  max-width: 34px;
  padding: 5px;
  width: 34px;
}
.scenario-status.status-rolled-up b,
.scenario-status.status-rolled-up span,
.scenario-status.status-rolled-up:hover b,
.scenario-status.status-rolled-up:hover span,
.scenario-status.status-rolled-up:focus-within b,
.scenario-status.status-rolled-up:focus-within span {
  opacity: 0;
  pointer-events: none;
  transform: translateX(-6px);
}
.starfall-status b,
.captain-status b { display: block; color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 18px; line-height: 1; }
.captain-status b { color: #9ee7ff; }
.starfall-status span,
.captain-status span { display: block; color: var(--ink-dim); font-size: 11px; line-height: 1.25; margin-top: 3px; }
@keyframes calloutPop {
  0% { transform: translateX(-50%) scale(.6); opacity: 0; }
  60% { transform: translateX(-50%) scale(1.08); opacity: 1; }
  100% { transform: translateX(-50%) scale(1); }
}

/* ── StarBreach boss UI ── */
.boss-callout {
  position: absolute; left: 50%; top: 12%; transform: translateX(-50%);
  z-index: 6; min-width: 240px; max-width: 360px;
  background: rgba(20,10,26,.94); border: 1px solid #a86ad1; border-radius: 10px;
  padding: 10px 14px; box-shadow: 0 0 26px rgba(168,106,209,.4), 0 8px 24px rgba(0,0,0,.5);
  animation: calloutPop .4s ease-out; pointer-events: none;
}
.boss-callout b {
  display: block; font-family: "Pirata One", serif; font-size: 22px; color: #d9a6ff;
  text-shadow: 0 0 14px rgba(168,106,209,.7);
}
.boss-callout .bc-sources { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 5px; }
.boss-callout .bc-source {
  font-size: 10px; padding: 2px 7px; border-radius: 8px;
  background: rgba(168,106,209,.18); border: 1px solid rgba(168,106,209,.5); color: #e6c8ff;
}
.boss-callout .bc-bar { margin-top: 7px; height: 7px; border-radius: 4px; background: rgba(255,255,255,.1); overflow: hidden; }
.boss-callout .bc-bar-fill { height: 100%; background: linear-gradient(90deg,#a86ad1,#ff6a8a); }
/* Mini battle board: discrete progress boxes + one chip row per boss phase. */
.boss-mini-board {
  position: absolute; right: 12px; bottom: 12px; z-index: 4; max-width: 360px;
  border: 1px solid rgba(168,106,209,.55); border-radius: 10px;
  background: rgba(9,14,27,.88); padding: 10px 14px; cursor: pointer;
}
.boss-mini-board:hover { border-color: rgba(217,166,255,.9); }
.bmb-track { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; }
.bmb-track-label { font-size: 11px; color: #d9a6ff; margin-right: 4px; font-family: "Pirata One", serif; }
.bmb-box {
  width: 12px; height: 12px; border-radius: 3px; box-sizing: border-box;
  border: 1px solid rgba(255,255,255,.28); background: rgba(255,255,255,.05);
  font-size: 8px; line-height: 10px; text-align: center; color: rgba(255,255,255,.55);
}
.bmb-box.filled { background: linear-gradient(135deg,#a86ad1,#ff6a8a); border-color: #d9a6ff; color: #16081f; }
.bmb-box.major { border-width: 2px; width: 14px; height: 14px; line-height: 11px; }
.bmb-box.major.online { box-shadow: 0 0 6px rgba(212,167,72,.85); }
.bmb-rows { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.bmb-row { display: flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.bmb-phase {
  font-family: "Pirata One", serif; font-size: 12px; min-width: 34px; text-align: right;
  margin-right: 2px;
}
.bmb-chip {
  display: inline-block; min-width: 17px; height: 15px; padding: 0 2px; border-radius: 4px;
  border: 1px solid; box-sizing: border-box; font-size: 9px; line-height: 13px; text-align: center;
  background: rgba(255,255,255,.05);
}
.bmb-chip.off {
  border-style: dashed; color: #555 !important; opacity: .65;
  background: rgba(20,20,26,.8); text-decoration: line-through;
}
.bmb-chip.fleet { border-color: #9aa3b8; color: #9aa3b8; border-radius: 8px; }
.bmb-none { color: var(--ink-dim); font-size: 10px; }
/* Turn progression through the boss's action stacks */
.bmb-row.done { opacity: .45; }
.bmb-row.resolving { outline: 1px solid rgba(212,167,72,.55); outline-offset: 2px; border-radius: 4px; }
.bmb-row.resolving .bmb-phase { text-shadow: 0 0 8px currentColor; }
.bmb-now { display: flex; align-items: center; gap: 4px; margin: 1px 0; height: 7px; }
.bmb-now span { color: var(--gold-bright); font-size: 8px; line-height: 1; }
.bmb-now::after { content: ""; flex: 1; height: 2px; border-radius: 1px; background: linear-gradient(90deg, var(--gold-bright), rgba(212,167,72,0)); }
.boss-mini-board .bmb-track-label { font-size: 17px; margin-right: 6px; }
.boss-mini-board .bmb-box { width: 18px; height: 18px; border-radius: 4px; font-size: 12px; line-height: 17px; }
.boss-mini-board .bmb-box.major { width: 21px; height: 21px; line-height: 19px; }
.boss-mini-board .bmb-rows { gap: 5px; margin-top: 9px; }
.boss-mini-board .bmb-row { gap: 5px; }
.boss-mini-board .bmb-phase { font-size: 18px; margin-right: 3px; min-width: 51px; }
.boss-mini-board .bmb-chip { border-radius: 5px; font-size: 14px; height: 23px; line-height: 21px; min-width: 26px; padding: 0 3px; }
.boss-mini-board .bmb-none { font-size: 15px; }
.boss-mini-board .bmb-now { gap: 6px; height: 11px; margin: 2px 0; }
.boss-mini-board .bmb-now span { font-size: 12px; }
/* Vertical boss progress rail on the side of the space board */
.boss-progress-rail {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  z-index: 4; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 6px; cursor: pointer;
  border: 1px solid rgba(168,106,209,.55); border-radius: 10px;
  background: rgba(9,14,27,.88);
  max-height: calc(100% - 150px); overflow-y: auto;
}
.boss-progress-rail:hover { border-color: rgba(217,166,255,.9); }
.boss-progress-rail .bmb-track-label { margin: 0 0 3px; }
.bmb-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.bmb-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 11px; }
/* Doubled-width board (specific selector: the later .picker rule would
   otherwise cap max-width at 520px). */
.picker.boss-board-modal {
  max-width: min(1440px, 96vw); width: min(1440px, 96vw);
  /* Nothing here needs selecting — a stray selection mid-drag otherwise eats
     later drags until it's cleared. */
  user-select: none; -webkit-user-select: none;
}
/* Progress track in the modal: full panel width, large readable boxes that
   wrap onto a new line rather than shrinking. Wrapped rows get extra breathing
   room, and the last box of a row shows a loop arrow pointing to the next row. */
.boss-board-modal .bmb-track { margin-top: 10px; gap: 5px; row-gap: 12px; justify-content: center; padding: 0 20px; }
.bmb-box { position: relative; }
.bmb-box.bmb-wrap-end::after {
  content: "↴"; position: absolute; right: -16px; top: 55%;
  color: #8a8a96; font-size: 14px; line-height: 1; pointer-events: none;
  font-family: "Space Grotesk", "Segoe UI Symbol", sans-serif;
}
.boss-board-modal .bmb-track-label { font-size: 16px; margin-right: 6px; }
.boss-board-modal .bmb-box {
  width: 26px; height: 26px; font-size: 15px; line-height: 24px; border-radius: 5px;
}
.boss-board-modal .bmb-box.major { width: 30px; height: 30px; line-height: 26px; }
/* Overlay that links progression-track boxes to their action chips. */
.boss-progress-links { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; z-index: 5; }
/* Phones: the battle board takes the whole window, and the map flexes to fill
   whatever height the track/legend/close button leave over. */
:root[data-device="phone"] .picker.boss-board-modal {
  /* 100% (not 100vw) so a scrollbar can't force horizontal overflow. */
  width: 100%; max-width: 100%;
  min-height: calc(100dvh - var(--mobile-hud-space));
  max-height: calc(100dvh - var(--mobile-hud-space));
  border-radius: 0; border-left: 0; border-right: 0;
  box-sizing: border-box; padding: 14px 10px;
  display: flex; flex-direction: column; overflow-y: auto;
}
:root[data-device="phone"] .boss-board-modal .boss-modal-map {
  flex: 1 0 54vh;
  height: auto;
  min-height: 54vh;
  overflow: auto;
  touch-action: pan-x pan-y;
}
/* Shield-region target picker */
.boss-region-picker { max-width: 600px; }
.boss-region-map { width: 100%; overflow: auto; }
.boss-region-cell:hover { filter: brightness(1.35); }
.brp-regions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; justify-content: center; }
.brp-region {
  border: 1px solid; border-radius: 8px; background: rgba(255,255,255,.05);
  color: var(--ink); font-size: 12px; padding: 5px 10px; cursor: pointer;
}
.brp-region.picked { box-shadow: 0 0 8px rgba(217,166,255,.5); }
.brp-lanes { margin-top: 8px; display: flex; align-items: center; flex-wrap: wrap; gap: 5px; justify-content: center; }
.brp-lane {
  min-width: 26px; padding: 3px 7px; border-radius: 6px; cursor: pointer;
  border: 1px solid rgba(212,167,72,.6); background: rgba(255,255,255,.05); color: var(--ink);
  font-family: "Pirata One", serif; font-size: 13px;
}
.brp-lane.picked { background: rgba(212,167,72,.35); box-shadow: 0 0 7px rgba(212,167,72,.6); }
.brp-actions { margin-top: 12px; display: flex; gap: 10px; justify-content: center; }
.sb-pause-toggle {
  background: rgba(9,14,27,.84);
  border: 1px solid rgba(168,106,209,.55);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,.35);
  cursor: pointer; user-select: none; color: var(--ink-dim);
}
.sb-pause-toggle input {
  grid-column: 2; grid-row: 1 / span 2; align-self: center;
  justify-self: center;
  height: 18px;
  width: 18px;
  opacity: 0; pointer-events: none; transform: translateX(-6px);
  transition: opacity 130ms ease, transform 130ms ease;
}
.sb-pause-toggle:hover input,
.sb-pause-toggle:focus-within input,
.sb-pause-toggle.status-expanded input {
  opacity: 1; pointer-events: auto; transform: translateX(0);
}
.sb-pause-toggle b,
.sb-pause-toggle span { grid-column: 3; }
.sb-continue {
  position: absolute; left: 50%; bottom: 60px; transform: translateX(-50%); z-index: 8;
}
.sb-continue:hover { transform: translateX(-50%) translateY(-1px); }
.sb-continue:active { transform: translateX(-50%) translateY(1px); }
/* The battle-board map is a zoom/pan viewport: starts at 2x, wheel/pinch zooms,
   drag pans. Overflow is clipped rather than scrolled. */
.boss-modal-map {
  width: 100%; height: 58vh; position: relative; overflow: hidden;
  touch-action: none; cursor: grab;
  user-select: none; -webkit-user-select: none;
  border: 1px solid rgba(168,106,209,.3); border-radius: 8px;
}
.boss-modal-map:active { cursor: grabbing; }
.boss-modal-map svg { display: block; }
.boss-lane-mark text { paint-order: stroke; stroke: #10182b; stroke-width: 3px; }
.boss-detail-shield { fill: none; stroke-width: 2; stroke-linecap: round; filter: drop-shadow(0 0 3px rgba(126,216,255,.45)); }
.boss-circuit-link { opacity: .18; transition: opacity .12s ease, filter .12s ease; }
.boss-circuit-link.active { opacity: .24; }
.boss-circuit-link.hot { opacity: 1; filter: drop-shadow(0 0 5px var(--trace-color)); }
.boss-circuit-link.hot .boss-circuit-line { stroke-width: 2.2; }
.boss-circuit-link.hot .boss-circuit-dot { r: 3; }
.boss-circuit-hotspot { cursor: pointer; transition: filter .12s ease; }
/* Hover lights the whole circuit: chip, hull component, and track box. */
.boss-circuit-hotspot.hot { filter: brightness(1.55) drop-shadow(0 0 4px rgba(255,255,255,.5)); }
.boss-component-node { transition: filter .12s ease; }
.boss-component-node.hot { filter: brightness(1.6) drop-shadow(0 0 6px rgba(255,255,255,.65)); }
.bmb-box.hot { filter: brightness(1.7); box-shadow: 0 0 8px rgba(255,255,255,.6); }
/* Bottom row of the battle-board modal: shields | progress track | legend on
   desktop; on phones it stacks with the track first (right under the map). */
.boss-modal-bottom { display: flex; gap: 18px; align-items: flex-start; margin-top: 10px; }
.boss-modal-bottom .boss-modal-side { flex: 0 1 260px; text-align: left; }
.boss-modal-bottom .boss-modal-side h4 { margin-top: 0; }
.boss-modal-center { flex: 1 1 auto; min-width: 0; }
.boss-modal-center .bmb-track { margin-top: 0; }
:root[data-device="phone"] .boss-modal-bottom { flex-direction: column; align-items: stretch; gap: 10px; }
/* In column direction the desktop flex-basis (260px) would become height. */
:root[data-device="phone"] .boss-modal-bottom .boss-modal-side { flex: 0 0 auto; }
:root[data-device="phone"] .boss-modal-center { order: -1; }
.boss-modal-side { min-width: 190px; flex: 1; font-size: 12px; color: var(--ink-dim); }
.boss-modal-side h4 { font-family: "Pirata One", serif; color: #d9a6ff; margin: 8px 0 3px; font-size: 16px; }
.boss-modal-side table { width: 100%; border-collapse: collapse; }
.boss-modal-side td { padding: 2px 4px; border-bottom: 1px solid rgba(255,255,255,.07); }
.boss-track { margin-top: 6px; height: 12px; border-radius: 6px; background: rgba(255,255,255,.08); position: relative; overflow: hidden; }
.boss-track .bt-fill { position: absolute; left: 0; top: 0; bottom: 0; background: linear-gradient(90deg,#a86ad1,#ff6a8a); }
.boss-track .bt-tick { position: absolute; top: 0; bottom: 0; width: 2px; background: rgba(255,255,255,.4); }
.boss-track .bt-tick.active { background: var(--gold-bright); }
.board-wrap.shake { animation: shake .4s; }

.replay-controls {
  position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; z-index: 6;
  background: rgba(13,20,38,.92); border: 1px solid var(--gold);
  border-radius: 10px; padding: 8px 14px; box-shadow: var(--shadow);
}
.replay-controls .rc-label { color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 15px; }
.replay-controls input[type="range"] { width: 110px; accent-color: var(--gold); }
#replay-speed-label { color: var(--ink-dim); font-size: 12px; min-width: 26px; }
@keyframes shake {
  10%, 90% { transform: translate(-2px, 1px); }
  30%, 70% { transform: translate(3px, -2px); }
  50% { transform: translate(-3px, 2px); }
}

/* hex + ships (SVG) */
.hex-cell { fill: rgba(30,42,74,.25); stroke: rgba(78,98,150,.35); stroke-width: .6; }
.hex-cell.rim { fill: rgba(30,42,74,.12); }
.vault-core { filter: drop-shadow(0 0 6px rgba(212,167,72,.8)); }
.ship-token { cursor: pointer; }
.ship-token.dead { opacity: .35; filter: grayscale(1); }
.ship-token.targetable:hover .ship-hull { stroke: var(--gold-bright); stroke-width: 2.5; }
.ship-label { font-family: "Space Grotesk"; font-size: 9px; fill: #dfe6ff; text-anchor: middle; paint-order: stroke; stroke: #060a14; stroke-width: 2.5px; }

/* ── orders panel / cards ────────────────── */
.orders-panel { display: flex; flex-direction: column; min-height: 0; overflow: visible; position: relative; z-index: 8; }

.pile-row { display: flex; gap: 10px; }
.pile {
  width: 46px; height: 62px; border-radius: 6px; position: relative;
  border: 1px solid #3c4a76;
  background:
    radial-gradient(60% 45% at 50% 32%, rgba(212,167,72,.35), transparent 70%),
    repeating-linear-gradient(45deg, #1a2340 0 6px, #151d36 6px 12px);
  box-shadow: 2px 2px 0 #0a1020, 4px 4px 0 #0d1428, 6px 6px 10px rgba(0,0,0,.5);
}
.pile::after { content: "☠"; position: absolute; inset: 0; display: grid; place-items: center; color: rgba(212,167,72,.75); font-size: 20px; }
.pile.discard-pile { filter: grayscale(.35) brightness(.8); }
.pile.discard-pile::after { content: "⚓"; }
.pile-count {
  position: absolute; right: -7px; bottom: -7px; z-index: 2;
  background: var(--gold); color: #241a05; font-weight: 700; font-size: 11px;
  border-radius: 50%; width: 22px; height: 22px; display: grid; place-items: center;
  box-shadow: 0 2px 6px rgba(0,0,0,.5);
}

/* Three action stacks side by side, each a vertical column: label, cards, seal. */
.order-slots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 12px 0; position: relative; }
/* "ORDERS" watermark fills the space where the old panel title used to sit,
   only while every slot is still empty (order-slots.no-orders-placed, toggled
   in renderOrdersPanel) -- so it reads as a title until the first card lands,
   then gets covered like the empty-slot hints already are. */
.order-slots::before {
  content: "ORDERS";
  display: none;
  position: absolute; inset: 0;
  align-items: center; justify-content: center;
  font-family: "Pirata One", serif; font-size: 34px; letter-spacing: .1em;
  color: var(--gold); opacity: .16; text-transform: uppercase;
  pointer-events: none; z-index: 0;
}
.order-slots.no-orders-placed::before { display: flex; }
.order-slot {
  border: 1px dashed rgba(212,167,72,.4); border-radius: 10px; padding: 9px;
  background: rgba(10,16,32,.6); min-height: 200px;
  display: grid; gap: 8px;
  /* Cards row fits one 114px front card plus headroom for a stacked back
     card's lift (see .order-slot.stacked below) -- still well short of the
     old two-row-wrap height, since a stack only ever needs that headroom
     once, not a whole second card height. */
  grid-template-rows: auto minmax(122px, 1fr) auto;
  justify-items: center;
  transition: border-color .15s, box-shadow .15s;
  cursor: pointer;
  position: relative;
}
.order-slot.receiving { border-color: var(--gold-bright); box-shadow: 0 0 14px rgba(212,167,72,.35); }
.order-slot.armed {
  border-style: solid; border-color: var(--gold-bright);
  box-shadow: 0 0 18px rgba(212,167,72,.5), inset 0 0 24px rgba(212,167,72,.08);
}
/* Submitted orders shown read-only while the round replays */
.order-slot.replaying { min-height: 170px; grid-template-rows: auto minmax(110px, 1fr) auto; }
.order-slot.replaying .slot-cards { min-height: 110px; }
.order-slot.playing {
  border-style: solid; border-color: var(--gold-bright);
  box-shadow: 0 0 18px rgba(212,167,72,.6), inset 0 0 24px rgba(212,167,72,.12);
}
.order-slot.playing .slot-label { color: var(--gold-bright); text-shadow: 0 0 10px rgba(212,167,72,.7); }
.order-slot.played { opacity: .55; }
.replay-seal { font-size: 11px; color: var(--ink-dim); letter-spacing: .5px; }
.replay-seal.overdrive { color: #ff8d6b; }
.order-slot .slot-label { font-family: "Pirata One", serif; font-size: 18px; color: var(--gold); text-align: center; line-height: 1; }
.order-slot .slot-cards { display: flex; gap: 7px; min-height: 122px; align-items: center; justify-content: center; flex-wrap: wrap; width: 100%; }

/* A stack whose cards don't fit side by side at natural width (toggled by
   updateSlotOverlap() in game.js) overlaps them like a fanned hand instead
   of wrapping to a second row: the front card (last in play order -- see
   orderedStackCardsForDisplay, which is also why Move always ends up front
   of Attack) sits at the row's normal base position, fully visible: every
   other ("back") card is lifted straight up so its own title stays visible
   above the front card's top edge, rather than being hidden entirely.
   Device-agnostic: desktop's 82x114 .card.in-slot needs this exactly as
   often as phone's 58x82 one does (see game.js). Numeric offsets here are
   sized for the desktop card; the phone media query below fully overrides
   them for its smaller card and its own (unchanged) reveal style. */
.order-slot.stacked .slot-cards {
  align-items: flex-end; flex-wrap: nowrap; gap: 0;
  justify-content: center; overflow: visible;
}
.order-slot.stacked .card.in-slot { margin-left: -46px; }
.order-slot.stacked .card.in-slot:first-child { margin-left: 0; }
.order-slot.stacked .card.in-slot:not(:last-child) { transform: translateY(-42px); }
.order-slot.stacked .card.in-slot:nth-child(1) { z-index: 1; }
.order-slot.stacked .card.in-slot:nth-child(2) { z-index: 2; }
.order-slot.stacked .card.in-slot:nth-child(3) { z-index: 3; }
.order-slot.stacked .card.in-slot:hover { z-index: 10; }
.slot-empty {
  align-items: center;
  color: var(--ink-dim);
  display: inline-flex;
  flex-direction: column;
  font-size: 11px;
  font-style: italic;
  gap: 3px;
  line-height: 1.15;
  text-align: center;
}
.slot-empty-action { display: none; }
.seal-toggle {
  width: 58px; height: 28px; border-radius: 999px; cursor: pointer; border: 2px solid #6e5a24;
  display: grid; place-items: center; user-select: none;
  background: radial-gradient(circle at 35% 30%, #d4a748, #7a5c1c);
  box-shadow: inset 0 -3px 6px rgba(0,0,0,.4), 0 2px 8px rgba(0,0,0,.5);
  transition: transform .15s;
}
.seal-toggle:hover { transform: scale(1.07); }
.seal-toggle.overdrive {
  background: radial-gradient(circle at 35% 30%, #e86a4a, #7c1f16);
  border-color: #5e1812;
  box-shadow: inset 0 -3px 6px rgba(0,0,0,.4), 0 0 16px rgba(232,106,74,.7);
  animation: flamePulse 1.2s ease-in-out infinite;
}
@keyframes flamePulse { 50% { box-shadow: inset 0 -3px 6px rgba(0,0,0,.4), 0 0 26px rgba(232,106,74,.95); } }
.seal-mode-text {
  color: #241a05;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: uppercase;
}

.seal-toggle.overdrive .seal-mode-text {
  color: #fff0df;
  font-size: 8px;
}

.seal-control {
  align-items: center;
  display: grid;
  gap: 5px;
  grid-template-columns: auto auto;
  justify-content: center;
  width: 100%;
}

.seal-details {
  z-index: 120;
}

.seal-details-button {
  background: rgba(10, 16, 32, 0.86);
  border: 1px solid rgba(212, 167, 72, 0.42);
  border-radius: 50%;
  color: var(--gold-bright);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  height: 22px;
  line-height: 20px;
  padding: 0;
  text-align: center;
  width: 22px;
}

.seal-details-button:hover,
.seal-details-button:focus {
  border-color: var(--gold-bright);
  outline: none;
}

.slot-shot-preview {
  background: rgba(6, 10, 20, 0.96);
  border: 1px solid rgba(212, 167, 72, 0.54);
  border-radius: 8px;
  box-shadow: 0 16px 38px rgba(0, 0, 0, 0.55);
  color: var(--ink);
  display: grid;
  font-size: 13px;
  gap: 7px;
  line-height: 1.38;
  opacity: 0;
  padding: 10px 12px;
  pointer-events: none;
  position: absolute;
  left: 0;
  top: calc(100% - 4px);
  transform: translateY(-4px);
  transition:
    opacity 140ms ease 520ms,
    transform 140ms ease 520ms,
    visibility 0s linear 660ms;
  visibility: hidden;
  width: min(300px, 78vw);
  z-index: 1000;
}
.slot-shot-preview.mobile-popup {
  opacity: 1;
  pointer-events: auto;
  position: relative;
  transform: none;
  transition: none;
  visibility: visible;
  width: 100%;
}
.shot-preview-picker {
  max-width: 420px;
}

.order-slot:nth-child(2) .slot-shot-preview {
  left: 50%;
  transform: translate(-50%, -4px);
}

.order-slot:nth-child(3) .slot-shot-preview {
  left: auto;
  right: 0;
}

.seal-details:hover .slot-shot-preview,
.seal-details:focus-within .slot-shot-preview {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 520ms;
  visibility: visible;
}

.order-slot:nth-child(2) .seal-details:hover .slot-shot-preview,
.order-slot:nth-child(2) .seal-details:focus-within .slot-shot-preview {
  transform: translate(-50%, 0);
}

.shot-preview-kicker {
  color: var(--gold-bright);
  font-family: "Pirata One", serif;
  font-size: 18px;
  line-height: 1;
}

.shot-preview-row {
  display: grid;
  gap: 2px;
}

.shot-preview-row b {
  color: #fff4cf;
  font-size: 13px;
}

.shot-preview-row span,
.shot-preview-note {
  color: var(--ink-dim);
}

.shot-preview-note {
  font-size: 12px;
}

/* physical cards */
.card {
  width: 96px; height: 134px; border-radius: 9px; position: relative;
  background: linear-gradient(168deg, #202b4e 0%, #151d38 55%, #10172c 100%);
  border: 1px solid #3c4a76; color: var(--ink);
  box-shadow: 0 3px 8px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.06);
  cursor: pointer; user-select: none; flex: 0 0 auto;
  transition: transform .18s, box-shadow .18s;
  transform-style: preserve-3d;
  font-size: 10px;
}
.card:hover { transform: translateY(-14px) scale(1.32) rotate(0deg) !important; z-index: 30; box-shadow: 0 16px 34px rgba(0,0,0,.7); }
.card .card-top {
  display: flex; justify-content: space-between; align-items: center;
  padding: 5px 7px 3px; font-weight: 700; font-size: 9.5px; letter-spacing: .02em;
}
.card .card-icon { font-size: 20px; text-align: center; margin-top: 6px; filter: drop-shadow(0 0 5px rgba(255,255,255,.25)); }
.card .card-name { font-family: "IM Fell English", serif; text-align: center; font-size: 11px; padding: 4px 5px 0; line-height: 1.15; }
.card .card-text { text-align: center; color: var(--ink-dim); padding: 3px 6px; line-height: 1.3; font-size: 9px; }
.card.no-card-text .card-text { display: none; }
.card .card-trim { position: absolute; inset: 3px; border-radius: 7px; border: 1px solid; pointer-events: none; opacity: .55; }
.card.fam-move .card-trim { border-color: var(--move); }
.card.fam-attack .card-trim { border-color: var(--attack); }
.card.fam-hybrid .card-trim { border-image: linear-gradient(135deg, var(--move), var(--attack)) 1; }
.card.has-desperate::after {
  content: "☄"; position: absolute; right: 5px; bottom: 4px; color: var(--desperate);
  font-size: 13px; filter: drop-shadow(0 0 4px rgba(168,111,212,.9));
}
.card.in-slot { width: 82px; height: 114px; font-size: 9px; }
.card.in-slot .card-icon { font-size: 18px; margin-top: 4px; }
.card.in-slot .card-name { font-size: 10px; }
.card.in-slot .card-text { font-size: 8px; }
.card.in-slot:hover { transform: translateY(-4px) scale(1.35) !important; }
.card.in-slot.compact-slot .card-name,
.card.in-slot.compact-slot .use-tag {
  display: none;
}
.card.in-slot.compact-slot .card-icon {
  margin-top: 7px;
}
.card.in-slot.compact-slot .card-text {
  color: var(--ink);
  font-size: 9px;
  font-weight: 700;
  line-height: 1.18;
  padding: 5px 7px 0;
}
.card.desperate-face { background: linear-gradient(168deg, #33204e 0%, #241540 55%, #180e2e 100%); }
.card.desperate-face .card-trim { border-color: var(--desperate); }
.card.selected { outline: 2px solid var(--gold-bright); box-shadow: 0 0 18px rgba(212,167,72,.6); }
.card .use-tag {
  position: absolute; left: 4px; bottom: 4px; font-size: 8px; border-radius: 3px; padding: 0 4px;
  background: rgba(0,0,0,.5); color: var(--ink-dim);
}
.card-back {
  background:
    radial-gradient(55% 40% at 50% 34%, rgba(212,167,72,.4), transparent 70%),
    repeating-linear-gradient(45deg, #1a2340 0 6px, #151d36 6px 12px);
}
.card-back .back-skull { position: absolute; inset: 0; display: grid; place-items: center; font-size: 34px; color: rgba(212,167,72,.85); }

/* Hand as a roomy wrapping spread — cards full-size, no overlap. */
.hand-area {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start;
  gap: 12px; min-height: 158px; padding: 12px 4px 6px; position: relative;
}
.hand-area .card { width: 104px; height: 144px; font-size: 10.5px; }
.hand-area .card .card-icon { font-size: 21px; }
.hand-area .card .card-name { font-size: 12px; }
.hand-area .card .card-text { font-size: 10px; }
.hand-area .card:hover { transform: translateY(-8px) scale(1.12) !important; }
.hand-note { color: var(--ink-dim); font-style: italic; text-align: center; width: 100%; padding: 30px 10px; }
.hand-note .waiting-timer { display: inline-block; margin-top: 8px; color: var(--gold-bright); font-style: normal; font-size: 13px; letter-spacing: 0.02em; }

/* ── Blitz ─────────────────────────────────────────────────────────────
   A transparent HUD overlaid directly on the board (#blitz-hud, 2D or 3D
   alike): a normal-shaped card rail pinned to the bottom edge under the
   ship model, an Overdrive lever on the left, per-player speed bars on the
   right, and two cycling buttons (render mode / camera vantage) up top —
   replacing the classic .orders-panel entirely for Blitz so the play area
   is never obscured (see the .game-grid / .orders-panel / mobile-game-hud
   overrides under body.blitz-mode below). See blitz-ui.js and
   docs/context/blitz_implementation_plan.md's HUD-rework phase. */
.card-dock-clone { transform-origin: top left; }

.blitz-hud {
  position: absolute; inset: 0; z-index: 12;
  /* Only the islands below opt back in — gaps between them stay click/drag
     -through so orbiting the 3D camera and tapping a move/target still
     reach the canvas underneath. */
  pointer-events: none;
}
.blitz-hud > * { pointer-events: auto; }

/* The rail stretches the full width to centre the cards, and it comes AFTER
   the lever/speed bars in the DOM — so its own box (padding strips included)
   would sit on top of them and swallow every click. Only the actual cards,
   mode buttons and charge chips take pointer events; their containers stay
   transparent to them. */
.blitz-rail, .blitz-card-rail, .blitz-mode-buttons, .blitz-charges { pointer-events: none; }
.blitz-card-rail > *, .blitz-mode-buttons > *, .blitz-charges > * { pointer-events: auto; }

.blitz-rail {
  position: absolute; left: 0; right: 0; bottom: env(safe-area-inset-bottom);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 0 96px; /* clears the overdrive lever / speed bars beside it */
}
.blitz-charges { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.charge-chip {
  display: flex; align-items: center; gap: 4px; padding: 3px 7px; border-radius: 12px;
  background: rgba(212,167,72,.12); border: 1px solid rgba(212,167,72,.5);
  font-size: 10px; color: var(--gold-bright); cursor: default;
}
.charge-chip-icon { font-size: 11px; }

.blitz-mode-buttons {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
}
.blitz-mode-buttons:empty { display: none; }
.blitz-desperate-mode { border-color: #ff5a5a; color: #ff8a7a; }

/* Cards fill the gap between the ship model and the bottom edge: sized off
   the viewport (not a fixed px height) and wrapped rather than scrolled —
   an overflow scroller here produced a stray scrollbar under the rail for
   the sake of a few px, and a hand this small never needs one. */
.blitz-card-rail {
  display: flex; gap: 10px; align-items: flex-end; justify-content: center;
  flex-wrap: nowrap; width: 100%; overflow: visible;
}
/* Cards share the rail's width evenly (capped, so a 2-card hand doesn't get
   billboards) rather than being fixed-size — that keeps the whole hand on
   ONE row at any hand size and any screen width, with no scroller and no
   wrapping up over the ship model. Height follows from the card aspect. */
.blitz-card-rail .card {
  flex: 1 1 0; min-width: 0; max-width: 124px;
  width: auto; height: auto;
  aspect-ratio: 96 / 134;
}
.blitz-card-rail .card.armed { transform: translateY(-10px); outline: 2px solid var(--gold-bright); box-shadow: 0 0 20px rgba(212,167,72,.7); }
.blitz-card-rail .card.last-chance { animation: blitz-last-chance-pulse 1.1s ease-in-out infinite; }
@keyframes blitz-last-chance-pulse {
  0%, 100% { box-shadow: 0 3px 8px rgba(0,0,0,.55), 0 0 0 rgba(255,90,90,0); }
  50% { box-shadow: 0 3px 8px rgba(0,0,0,.55), 0 0 16px rgba(255,90,90,.85); }
}
.blitz-endgame-actions { display: flex; gap: 10px; justify-content: center; }

/* Overdrive lever — a vertical track with a knob that slides toward the top
   when armed, left edge of the board. */
.blitz-overdrive { position: absolute; left: 10px; bottom: calc(8px + env(safe-area-inset-bottom)); z-index: 2; }
.blitz-overdrive-btn {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: none; border: none; padding: 0; cursor: pointer;
}
.blitz-overdrive-btn.disabled { opacity: .35; cursor: default; }
.lever-track {
  width: 34px; height: 108px; border-radius: 17px; position: relative;
  background: rgba(10,15,30,.65); border: 1px solid rgba(212,167,72,.4);
  box-shadow: inset 0 2px 6px rgba(0,0,0,.5);
}
.lever-knob {
  position: absolute; left: 3px; bottom: 3px; width: 26px; height: 26px; border-radius: 50%;
  background: linear-gradient(160deg, #3c4a76, #202b4e); border: 1px solid rgba(212,167,72,.5);
  display: grid; place-items: center; font-size: 13px;
  transition: transform .22s cubic-bezier(.22,.8,.3,1), box-shadow .22s;
}
.blitz-overdrive-btn.active .lever-knob {
  transform: translateY(-76px);
  border-color: #ff5a5a; box-shadow: 0 0 14px rgba(255,90,90,.75);
}
.lever-label {
  font-size: 10px; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .04em;
}
.blitz-overdrive-btn.active .lever-label { color: #ff8a7a; }

/* Speed bars — yours wide and gold-lit, everyone else's thin beside it.
   Hovering an opponent's bar glances the camera their way (blitz-ui.js);
   tapping any bar opens the all-ships popup. */
.blitz-speed {
  position: absolute; right: 10px; bottom: calc(8px + env(safe-area-inset-bottom)); z-index: 2;
  display: flex; flex-direction: row; align-items: flex-end; gap: 5px;
}
.blitz-speed-bar {
  display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer;
}
.blitz-speed-stack {
  width: 14px; min-height: 30px; display: flex; flex-direction: column-reverse; gap: 2px;
  align-items: center;
}
.blitz-speed-bar.mine .blitz-speed-stack { width: 24px; }
.blitz-speed-seg {
  width: 100%; border-radius: 2px; background: #4f86d1; transition: opacity .3s;
}
.blitz-speed-bar.mine .blitz-speed-seg { background: var(--gold-bright); box-shadow: 0 0 6px rgba(212,167,72,.5); }
.blitz-speed-seg.aging { background: #2a3d63; opacity: .55; }
.blitz-speed-bar.mine .blitz-speed-seg.aging { opacity: .4; }
.blitz-speed-value {
  font-size: 10px; font-weight: 700; color: var(--ink-dim); text-shadow: 0 1px 3px rgba(0,0,0,.8);
}
.blitz-speed-bar.mine .blitz-speed-value { font-size: 13px; color: var(--gold-bright); }

.blitz-speed-popup {
  position: absolute; right: 10px; bottom: 90px;
  background: rgba(10,15,30,.92); border: 1px solid rgba(212,167,72,.4); border-radius: 8px;
  padding: 8px 10px; min-width: 130px; box-shadow: 0 8px 24px rgba(0,0,0,.6);
}
.blitz-speed-popup-title {
  font-family: "Pirata One", serif; color: var(--gold-bright); font-size: 13px;
  text-align: center; margin-bottom: 4px;
}
.blitz-speed-popup-row {
  display: flex; justify-content: space-between; gap: 12px; font-size: 12px;
  color: var(--ink-dim); padding: 2px 0;
}
.blitz-speed-popup-row.mine { color: var(--ink); font-weight: 700; }

/* body.blitz-mode: set by blitz-ui.js's render()/reset() alongside #blitz-hud
   itself. Removes the classic .orders-panel column/sheet entirely, since
   Blitz's controls now live over the board (above) rather than beside or
   under it — the whole point of this rework. */
body.blitz-mode .game-grid { grid-template-columns: minmax(0, 1fr); }
body.blitz-mode .orders-panel { display: none; }

/* On-board arrows/target hexes (board.js renderOptions) — hover feedback
   only; geometry and color come from the server. */
.board-option { transition: opacity .15s; }
.board-option:hover { opacity: 0.75; }

.captain-choice { width: 100%; text-align: center; }
.captain-choice h3 { font-family: "Pirata One", serif; color: var(--gold-bright); font-size: 22px; margin-bottom: 12px; }
.captain-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.captain-card {
  border: 1px solid var(--panel-edge);
  border-radius: 8px;
  background: linear-gradient(180deg, #1b2542, #10182d);
  color: var(--ink);
  padding: 12px 10px;
  min-height: 142px;
  cursor: pointer;
  text-align: center;
}
.captain-card:hover { border-color: var(--gold); transform: translateY(-2px); }
.captain-card b { display: block; color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 20px; }
.captain-card span { display: block; font-size: 12px; margin: 4px 0 8px; }
.captain-card small { display: block; color: var(--ink-dim); font-size: 11px; line-height: 1.3; }

.orders-actions { display: flex; gap: 10px; justify-content: flex-end; align-items: center; margin-top: 4px; }
/* Deck/discard piles sit bottom-left, across from Clear/Seal Orders on the
   right -- pushed apart with margin-right: auto rather than
   justify-content: space-between, which would spread Clear and Seal Orders
   away from each other too. Grid-positioned instead on phone (below). */
.orders-actions > .pile-row { margin-right: auto; }
.orders-hint { color: var(--ink-dim); font-size: 12px; min-height: 18px; margin-top: 8px; text-align: center; }

/* picker overlay */
.overlay {
  position: fixed; inset: 0; z-index: 60; background: rgba(4,7,14,.7);
  display: grid; place-items: center; backdrop-filter: blur(3px);
}
.picker {
  background: linear-gradient(180deg, #182137, #0e1527);
  border: 1px solid var(--gold); border-radius: 14px; padding: 22px 26px;
  box-shadow: var(--shadow); max-width: 520px; text-align: center;
}
.picker h3 { font-family: "Pirata One", serif; color: var(--gold-bright); font-size: 24px; margin-bottom: 14px; }
.pile-info-picker { max-width: 340px; }
.pile-info-picker p { color: var(--ink-dim); font-size: 13px; line-height: 1.35; margin: 8px 0; }
.pile-info-picker b { color: var(--gold-bright); }
.picker .picker-options { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.picker-option {
  border: 1px solid var(--panel-edge); background: #0d1426; color: var(--ink);
  border-radius: 10px; padding: 12px 16px; cursor: pointer; min-width: 108px;
  transition: border-color .15s, transform .15s;
}
.picker-option:hover { border-color: var(--gold); transform: translateY(-2px); }
.picker-option .opt-icon { font-size: 24px; }
.picker-option .opt-label { font-size: 12px; margin-top: 4px; }
.picker-option .opt-sub { font-size: 10px; color: var(--ink-dim); }
.picker-option.desperate { border-color: rgba(168,111,212,.6); background: #1c1230; }
.picker .picker-cancel { margin-top: 16px; }

/* ── match-opening roster (match-intro.js) ─
   Sits above .overlay (60) and the mobile sheets (50): while the ships are
   flying in, nothing else may be on top of them. */
.mi-overlay {
  position: fixed; inset: 0; z-index: 70;
  background: radial-gradient(120% 90% at 50% 100%, rgba(30,44,80,.75), rgba(4,7,14,.92));
  backdrop-filter: blur(4px);
  display: grid; place-items: center;
  overflow: hidden;
  transition: background .3s ease-out, backdrop-filter .3s ease-out;
}
.mi-inner { display: flex; flex-direction: column; align-items: center; gap: 18px; max-width: 100vw; }
.mi-title {
  font-family: "Pirata One", serif; font-size: 38px; color: var(--gold-bright);
  text-shadow: 0 0 24px rgba(212,167,72,.35); text-align: center; padding: 0 16px;
}
.mi-row { display: flex; gap: 26px; align-items: flex-end; justify-content: center; padding: 0 16px; }

.mi-card {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  border: 2px solid var(--mi-seat, var(--panel-edge)); border-radius: 14px;
  background: linear-gradient(180deg, rgba(24,33,55,.75), rgba(14,21,39,.75));
  padding: 18px 20px;
  /* parked below the fold until its turn to launch */
  transform: translateY(115vh);
}
.mi-card.mine { box-shadow: 0 0 30px rgba(212,167,72,.18); }
.mi-card.mi-landed { animation: miFlyUp 620ms cubic-bezier(.16,1,.3,1) forwards; }
@keyframes miFlyUp {
  from { transform: translateY(115vh) scale(.92); }
  85%  { transform: translateY(-14px) scale(1.04); }
  to   { transform: translateY(0) scale(1); }
}
/* The box is reserved at the ship's own aspect ratio (match-intro.js), but
   dogfight.js's fill sizing insets by FILL_SCALE (0.88) and quantises to a
   multiple of 8px, so the raster rarely fills the box exactly. Center it on
   both axes rather than letting it sit block-aligned top/left. */
.mi-art { line-height: 0; display: flex; align-items: center; justify-content: center; }
.mi-chrome { text-align: center; opacity: 0; transition: opacity .12s ease-out; }
.mi-card.mi-chrome-in .mi-chrome { opacity: 1; }
.mi-name { font-family: "Pirata One", serif; font-size: 26px; color: var(--gold-bright); }
.mi-stat { color: var(--ink-dim); font-size: 13px; letter-spacing: .06em; margin-top: 2px; }
.mi-actions {
  display: flex; gap: 12px; align-items: center;
  opacity: 0; transition: opacity .25s ease-out; pointer-events: none;
}
.mi-overlay.mi-ready .mi-actions { opacity: 1; pointer-events: auto; }
.mi-begin { font-size: 18px; padding: 10px 34px; }
/* Present when a match has history to catch up on: "Straight to Orders" next
   to a lighter "Replay the tale so far" — the choice the old separate popup
   used to make you clear before you could even see the board. */
.mi-replay { font-size: 15px; padding: 10px 22px; }

/* Reduced motion: no flight at all, everything simply present. */
.mi-overlay.mi-still .mi-card { transform: none; animation: none; }
.mi-overlay.mi-still .mi-chrome { opacity: 1; }

/* Dismissing clears everything EXCEPT the ships — they have to stay lit while
   they fly down to the board, so only the staging around them fades. These
   must come after the rules they override (equal specificity, later wins). */
.mi-overlay.mi-dismissing {
  background: transparent; backdrop-filter: none; pointer-events: none;
}
.mi-overlay.mi-dismissing .mi-title,
.mi-overlay.mi-dismissing .mi-actions,
.mi-overlay.mi-dismissing .mi-card .mi-chrome { opacity: 0; transition: opacity .15s ease-out; }
.mi-overlay.mi-dismissing .mi-card {
  background: transparent; border-color: transparent; box-shadow: none;
  transition: background .15s ease-out, border-color .15s ease-out, box-shadow .15s ease-out;
}
/* Declared here rather than assigned alongside the transform in JS: a
   transition only starts if the before-change style already had one. Keep the
   duration in step with LAND_MS in match-intro.js. */
.mi-overlay.mi-dismissing .mi-art {
  transition: transform 520ms cubic-bezier(.4,0,.25,1), opacity 520ms ease-in;
}
.mi-overlay.mi-still.mi-dismissing { opacity: 0; transition: opacity .18s ease-out; }

/* Desktop: a roster taller than the viewport (a long/narrow ship — see
   match-intro.js's height clamp above, which now runs on desktop too, not
   just phone) used to overflow `place-items: center` symmetrically with
   `overflow: hidden`, clipping .mi-actions (Begin / Straight to Orders)
   below the fold with no way to reach it — click-off-the-ships was the only
   escape. Mirrors the phone treatment just above: scroll instead of clip,
   top-align (not center) once it doesn't fit, and pin the actions row to
   the bottom of the scroll port so it's reachable the instant the overlay
   opens, never mid-scroll. */
:root[data-device="desktop"] .mi-overlay {
  place-items: stretch;
  overflow-y: auto;
}
:root[data-device="desktop"] .mi-inner {
  width: 100%;
  min-height: 100dvh;
  box-sizing: border-box;
  justify-content: center;
  padding: 24px 0 0;
}
:root[data-device="desktop"] .mi-actions {
  position: sticky;
  bottom: 0;
  z-index: 1;
  /* .mi-inner is align-items:center, so without this the actions row
     shrink-to-fits its buttons and the gradient below paints only a
     Begin-sized patch with a hard cutoff either side. Sticky does NOT
     stretch it — sticky keeps normal flow sizing. */
  align-self: stretch;
  justify-content: center;
  background: linear-gradient(180deg, transparent, rgba(4,7,14,.85) 40%);
  padding: 28px 16px 18px;
  margin-top: -18px; /* the gradient's own transparent lead-in, so it doesn't add a visible gap above the buttons when nothing is scrolled under it yet */
}

/* A token stands down while the roster ship flies into its hex. */
.ship-token.token-handoff { opacity: 0; }

/* ── Arena standby room (arena-standby.js) ──
   The pre-launch "who's aboard" screen for a still-filling Arena Challenge.
   Deliberately simpler than the match-opening roster above: no entrance
   flight, no dismiss-to-board choreography — just cards that appear (or
   don't yet) as seats fill, refreshed by the shared 3s lobby poll. */
.as-overlay {
  position: fixed; inset: 0; z-index: 65;
  background: radial-gradient(120% 90% at 50% 100%, rgba(30,44,80,.7), rgba(4,7,14,.9));
  backdrop-filter: blur(4px);
  display: grid; place-items: center; overflow-y: auto;
}
.as-inner {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  max-width: 100vw; padding: 24px 16px;
}
.as-title { font-family: "Pirata One", serif; font-size: 32px; color: var(--gold-bright); text-align: center; }
.as-sub { color: var(--ink-dim); font-size: 13px; letter-spacing: .04em; }
.as-row { display: flex; flex-wrap: wrap; gap: 22px; align-items: flex-end; justify-content: center; padding: 8px 0; }
.as-card {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  border: 2px solid var(--as-seat, var(--panel-edge)); border-radius: 14px;
  background: linear-gradient(180deg, rgba(24,33,55,.75), rgba(14,21,39,.75));
  padding: 16px 18px;
}
.as-art { line-height: 0; display: flex; align-items: center; justify-content: center; min-height: 80px; }
.as-art-empty {
  color: var(--ink-dim); font-size: 12px; text-align: center; height: 80px;
  display: flex; align-items: center; justify-content: center; padding: 0 8px;
}
.as-berth { border-style: dashed; opacity: .6; }
.as-berth-art { height: 80px; position: relative; }
.as-berth-art::before {
  content: "⚓"; font-size: 28px; color: var(--ink-dim); opacity: .5;
  animation: asBerthPulse 2.4s ease-in-out infinite;
}
@keyframes asBerthPulse { 0%, 100% { opacity: .25; } 50% { opacity: .6; } }
.as-chrome { text-align: center; }
.as-name { font-family: "Pirata One", serif; font-size: 20px; color: var(--gold-bright); }
.as-stat { color: var(--ink-dim); font-size: 12px; letter-spacing: .05em; margin-top: 2px; }
.as-actions { display: flex; gap: 12px; margin-top: 4px; }
:root[data-device="phone"] .as-title { font-size: 24px; }
:root[data-device="phone"] .as-row { gap: 14px; }

/* endgame */
.endgame {
  background: linear-gradient(180deg, #1b2342, #0e1527);
  border: 2px solid var(--gold); border-radius: 16px; padding: 34px 44px;
  text-align: center; max-width: 560px; box-shadow: var(--shadow);
}
.endgame h2 { font-size: 44px; color: var(--gold-bright); text-shadow: 0 0 20px rgba(212,167,72,.5); }
.endgame .eg-sub { color: var(--ink-dim); font-style: italic; margin: 6px 0 18px; }
.endgame table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
.endgame td, .endgame th { padding: 7px 10px; border-top: 1px solid rgba(42,53,84,.6); font-size: 14px; }
.endgame th { color: var(--ink-dim); font-weight: 400; font-size: 11px; text-transform: uppercase; }
.endgame tr.winner td { color: var(--gold-bright); font-weight: 700; }

.endgame { max-width: 860px; max-height: 88vh; overflow-y: auto; }
.eg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 12px; margin: 14px 0 20px; text-align: left; }
.eg-card {
  border: 1px solid var(--panel-edge); border-left-width: 4px; border-radius: 10px;
  background: #0d1426; padding: 10px 12px;
}
.eg-card.winner { border-color: var(--gold); box-shadow: 0 0 14px rgba(212,167,72,.25); border-left-width: 4px; }
.eg-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.eg-rank { color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 18px; }
.eg-card-body { display: flex; gap: 12px; align-items: flex-start; }
.eg-stats { font-size: 12.5px; line-height: 1.75; color: var(--ink); }
.eg-dim { color: var(--ink-dim); font-size: 11.5px; }
.eg-fate { color: var(--ink-dim); font-style: italic; }
.feedback-spot {
  border: 1px solid rgba(212,167,72,.48); border-radius: 10px;
  background: rgba(212,167,72,.08); padding: 12px 14px; margin: 8px 0 18px;
}
.feedback-spot h3 {
  color: var(--gold-bright); font-family: "Pirata One", serif; font-size: 24px; margin-bottom: 4px;
}
.feedback-spot p { color: var(--ink-dim); font-size: 13px; line-height: 1.45; margin-bottom: 10px; }
.eg-sos {
  border: 1px solid rgba(255,105,97,.5); border-radius: 10px;
  background: rgba(255,105,97,.08); padding: 16px 14px; margin: 8px 0 18px;
}
.eg-sos p {
  color: var(--ink); font-size: 19px; line-height: 1.4; margin-bottom: 12px; font-style: italic;
}

.feedback-modal { width: min(560px, 94vw); max-width: 560px; text-align: left; }
.feedback-modal h3 { text-align: center; }
.profiles-modal { width: min(520px, 94vw); max-width: 520px; text-align: left; }
.profiles-modal h3 { text-align: center; }
.profiles-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.profiles-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: #0a1020; border: 1px solid var(--panel-edge); border-radius: 8px;
  padding: 8px 10px;
}
.profiles-row.active { border-color: rgba(212,167,72,.55); background: rgba(212,167,72,.08); }
.profiles-name { color: var(--ink); font-weight: 600; flex: 1 1 auto; }
.profiles-record { color: var(--ink-dim); font-size: 12px; }
.profiles-current { color: var(--gold-bright); font-size: 12px; }
.feedback-copy { color: var(--ink-dim); line-height: 1.5; margin: -4px 0 14px; text-align: center; }
.feedback-form { display: flex; flex-direction: column; gap: 12px; }
.feedback-form label { color: var(--ink-dim); display: flex; flex-direction: column; gap: 5px; font-size: 13px; }
.feedback-form .feedback-bug-report {
  flex-direction: row;
  align-items: center;
  color: var(--gold-bright);
  border: 1px solid rgba(212,167,72,.45);
  border-radius: 8px;
  background: rgba(212,167,72,.08);
  padding: 8px 10px;
}
.feedback-bug-report input { accent-color: var(--gold); }
.feedback-form textarea {
  background: #0a1020; border: 1px solid var(--panel-edge); border-radius: 8px;
  color: var(--ink); font-family: inherit; line-height: 1.4; max-height: 126px;
  min-height: 76px; overflow-y: auto; padding: 9px 10px; resize: vertical;
}
.rating-stars { display: flex; gap: 7px; justify-content: center; }
.star-choice {
  background: transparent; border: 0; color: #5d6070; cursor: pointer;
  font-size: 30px; line-height: 1; padding: 2px 4px;
  text-shadow: 0 1px 2px rgba(0,0,0,.55);
}
.star-choice.selected { color: var(--gold-bright); filter: drop-shadow(0 0 6px rgba(212,167,72,.55)); }
.feedback-actions { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
.feedback-screenshot {
  border: 1px solid rgba(212,167,72,.42);
  border-radius: 8px;
  display: block;
  margin-top: 6px;
  max-width: 100%;
}

/* toast */
.toast {
  position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%);
  background: #2a1518; color: #ffc9bd; border: 1px solid var(--crimson);
  padding: 12px 22px; border-radius: 10px; z-index: 90; box-shadow: var(--shadow);
  animation: calloutPop .3s ease-out;
  /* Purely informational — must never eat a tap meant for whatever's behind it
     (e.g. the StarMap, still interactive while a toast is up). */
  pointer-events: none;
}
.toast.good { background: #14261c; color: #b9eccd; border-color: var(--move); }

.mobile-game-hud,
.mobile-orders-close,
.lobby-mobile-tabs {
  display: none;
}

@media (max-width: 760px), (any-pointer: coarse) and (max-width: 1366px) {
  :root[data-device="phone"] {
    --mobile-hud-space: calc(72px + env(safe-area-inset-bottom));
    --mobile-game-topbar-space: calc(46px + env(safe-area-inset-top));
    --lobby-tab-space: calc(64px + env(safe-area-inset-bottom));
    --lobby-topbar-space: calc(52px + env(safe-area-inset-top));
    --lobby-subtab-space: 62px;
  }

  :root[data-device="phone"] body {
    overflow: hidden;
  }

  :root[data-device="phone"] .screen {
    min-height: 100dvh;
  }

  :root[data-device="phone"] #screen-auth {
    justify-content: flex-start;
    padding: calc(18px + env(safe-area-inset-top)) 0 calc(14px + env(safe-area-inset-bottom));
  }

  :root[data-device="phone"] .auth-poster {
    margin: auto 0;
    padding: 34px 24px 28px;
    width: min(390px, 88vw);
  }

  :root[data-device="phone"] .poster-title {
    font-size: 52px;
  }

  /* A duel keeps full-width ships stacked; a crowded table (.mi-grid, three or
     more captains) goes two-up so everyone is on screen at once. Either way the
     ships still fly up from below one after another. */
  :root[data-device="phone"] .mi-overlay {
    place-items: stretch;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  :root[data-device="phone"] .mi-inner {
    width: 100%;
    gap: 12px;
    padding: calc(14px + env(safe-area-inset-top)) 0 calc(88px + env(safe-area-inset-bottom));
    /* Centred when the roster fits, top-aligned and scrolling when it doesn't. */
    box-sizing: border-box;
    min-height: 100dvh;
    justify-content: center;
  }
  :root[data-device="phone"] .mi-title { font-size: 26px; }
  :root[data-device="phone"] .mi-row {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 18px;
    padding: 0 12px;
  }
  :root[data-device="phone"] .mi-card {
    width: 100%;
    justify-content: center;
  }

  :root[data-device="phone"] .mi-row.mi-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    justify-items: center;
    gap: 12px;
  }
  :root[data-device="phone"] .mi-row.mi-grid .mi-card {
    gap: 8px;
    padding: 12px 10px;
  }
  :root[data-device="phone"] .mi-row.mi-grid .mi-name { font-size: 19px; }
  :root[data-device="phone"] .mi-row.mi-grid .mi-stat { font-size: 11px; letter-spacing: .04em; }
  /* The Begin button must stay reachable however far down the list you are;
     the scrim keeps it legible over whichever ship it happens to sit on. */
  :root[data-device="phone"] .mi-actions {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    padding: 26px 16px calc(14px + env(safe-area-inset-bottom));
    background: linear-gradient(180deg, transparent, rgba(4,7,14,.85) 45%);
  }

  /* Phone: one control row — brand, icon-only action buttons, account chip —
     instead of the old three-row stack. The lobby body below it is handed
     off entirely to the StarMap/Comms tab shell (further down this block). */
  :root[data-device="phone"] #screen-lobby .topbar {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 6px;
    padding: calc(8px + env(safe-area-inset-top)) 8px 8px;
  }

  /* Drop the "v2 · core 0.x" tag on mobile so the brand name doesn't crowd
     the rest of the row out. */
  :root[data-device="phone"] #screen-lobby .brand-tag {
    display: none;
  }

  :root[data-device="phone"] #screen-lobby .brand {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 20px;
  }

  :root[data-device="phone"] .topbar-actions {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 6px;
    margin-left: 0;
  }

  :root[data-device="phone"] .topbar-actions .btn {
    min-height: 34px;
    min-width: 34px;
    padding: 0 8px;
  }

  /* Feedback/How-to collapse to a single icon; Claim My Legend keeps its
     label (there's room once the other two shrink and the account chip is
     capped below) but drops its flag. */
  :root[data-device="phone"] .tb-full,
  :root[data-device="phone"] .tb-emoji {
    display: none;
  }
  :root[data-device="phone"] .tb-icon {
    display: inline;
    font-size: 15px;
  }
  :root[data-device="phone"] #btn-claim-legend.tb-full,
  :root[data-device="phone"] #btn-claim-legend .tb-full {
    display: inline;
  }

  :root[data-device="phone"] .topbar-admin-row {
    flex-basis: 100%;
    justify-content: stretch;
  }

  /* Folded into the account popup (lobby.js) instead of the topbar row above
     — stack its buttons like the rest of the popup instead of the flex row
     meant for the (now phone-unused) topbar placement. */
  :root[data-device="phone"] #lobby-user-popup .topbar-admin-row {
    display: flex;
    flex-direction: column;
    flex-basis: auto;
    gap: 8px;
  }

  :root[data-device="phone"] .user-popup {
    min-width: min(220px, 70vw);
  }

  :root[data-device="phone"] .topbar-account {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 33vw;
  }

  :root[data-device="phone"] .user-menu-button {
    width: 100%;
    min-width: 0;
    min-height: 34px;
    justify-content: space-between;
  }

  /* The StarMap/Comms tab shell (JS-built, see lobby.js) takes over the
     whole lobby body; the old single-column stacked-panel layout is gone.
     Sized by flex-grow rather than a `calc(100dvh - <guessed topbar height>)`
     — the phone topbar can wrap to more than one row (long names, admin
     controls), and a hardcoded guess there used to push .lobby-main's
     content down under the fixed StarMap/Comms bar. */
  :root[data-device="phone"] #screen-lobby {
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }
  :root[data-device="phone"] body.lobby-mobile-active .lobby-grid {
    display: block;
    padding: 0;
    gap: 0;
    max-width: none;
    flex: 1 1 auto;
    min-height: 0;
    box-sizing: border-box;
  }

  :root[data-device="phone"] body.lobby-mobile-active .build-footer {
    display: none;
  }

  :root[data-device="phone"] body.lobby-tab-starmap .lobby-setup,
  :root[data-device="phone"] body.lobby-tab-starmap .lobby-side,
  :root[data-device="phone"] body.lobby-tab-starmap #lobby-comms-panel {
    display: none;
  }

  :root[data-device="phone"] body.lobby-tab-comms .lobby-setup,
  :root[data-device="phone"] body.lobby-tab-comms .lobby-side,
  :root[data-device="phone"] body.lobby-tab-comms .lobby-main {
    display: none;
  }

  :root[data-device="phone"] body.lobby-tab-comms .lobby-grid {
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 8px 8px calc(var(--lobby-tab-space) + var(--lobby-subtab-space));
  }

  /* Sub-tab strip floats just above the StarMap/Comms bar, not at the top —
     within reach of a thumb, and out of the way of scrolled content. */
  :root[data-device="phone"] .lobby-comms-tabs {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    position: fixed;
    left: 10px;
    right: 10px;
    bottom: calc(var(--lobby-tab-space) + 8px);
    z-index: 65;
    background: rgba(7, 11, 22, 0.92);
    border: 1px solid rgba(212, 167, 72, 0.36);
    border-radius: 10px;
    box-shadow: var(--shadow);
    margin: 0;
    padding: 7px;
  }

  :root[data-device="phone"] .lobby-comms-tabs .side-tab {
    padding: 8px 4px;
    font-size: 12px;
    min-height: 38px;
  }

  /* The bottom tab already reads "StarMap"; the in-panel head row (title +
     "current ship" note) is redundant once the map fills the whole screen. */
  :root[data-device="phone"] .starmap-head {
    display: none;
  }

  :root[data-device="phone"] .duel-btn .btn-sub {
    display: none;
  }

  :root[data-device="phone"] #btn-claim-legend-records {
    display: flex;
    width: 100%;
    justify-content: center;
    margin-bottom: 12px;
  }

  :root[data-device="phone"] .panel {
    border-radius: 10px;
    padding: 14px;
  }

  :root[data-device="phone"] .sail-row,
  :root[data-device="phone"] .crew-controls,
  :root[data-device="phone"] .challenge-banner,
  :root[data-device="phone"] .match-row {
    align-items: stretch;
    display: flex;
    flex-direction: column;
  }

  :root[data-device="phone"] .duel-row {
    flex-direction: column;
  }

  :root[data-device="phone"] .duel-btn {
    flex-direction: row;
    gap: 6px;
  }

  :root[data-device="phone"] .match-actions {
    justify-content: stretch;
    min-width: 0;
  }

  :root[data-device="phone"] .match-actions .btn {
    flex: 1 1 auto;
  }

  :root[data-device="phone"] .ai-pick {
    min-height: 48px;
    width: 100%;
  }

  :root[data-device="phone"] .ai-pick .ai-face {
    font-size: 16px;
  }

  :root[data-device="phone"] .ai-pick .ai-name {
    font-size: 15px;
    line-height: 1.15;
  }

  :root[data-device="phone"] .ai-pick .ai-blurb {
    font-size: 8.5px;
    text-align: center;
  }

  :root[data-device="phone"] .ai-pick .ai-count {
    font-size: 13px;
    justify-self: end;
  }

  :root[data-device="phone"] .arena-ai-pick {
    min-height: 56px;
    padding: 6px 7px;
  }

  :root[data-device="phone"] .arena-ai-pick .arena-ai-icon { font-size: 25px; }
  :root[data-device="phone"] .arena-ai-pick .arena-ai-icon img { height: 29px; width: 29px; }

  :root[data-device="phone"] #ai-pickers {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  :root[data-device="phone"] .ai-level-label,
  :root[data-device="phone"] .open-seats-label {
    width: 100%;
  }

  :root[data-device="phone"] .flesh-foes {
    min-width: 0;
  }

  :root[data-device="phone"] .choice-buttons {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    width: 100%;
  }

  :root[data-device="phone"] .choice-buttons.compact {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  :root[data-device="phone"] .choice-button {
    min-height: 44px;
    padding: 10px 6px;
    width: 100%;
  }

  :root[data-device="phone"] .flesh-foes .choice-button {
    font-size: 18px;
  }

  :root[data-device="phone"] .ai-level-label .choice-button {
    align-items: center;
    display: flex;
    font-size: 13px;
    justify-content: center;
    line-height: 1.08;
    min-height: 50px;
    padding: 9px 4px;
    white-space: normal;
  }

  :root[data-device="phone"] .expansion-box {
    width: 100%;
  }

  :root[data-device="phone"] .expansion-toggle {
    align-items: center;
    background: rgba(13, 20, 38, 0.72);
    border-color: rgba(42, 53, 84, 0.9);
    min-height: 52px;
    padding: 12px;
    width: 100%;
  }

  :root[data-device="phone"] .expansion-detail {
    margin-left: 10px;
  }

  :root[data-device="phone"] .expansion-toggle input {
    height: 28px;
    width: 28px;
  }

  :root[data-device="phone"] .btn.big {
    width: 100%;
  }

  /* The onboarding modal's Random + Set Sail share one feedback-actions row;
     don't let .btn.big's phone override push Set Sail onto its own line. */
  :root[data-device="phone"] .onboarding-modal .feedback-actions .btn.big {
    flex: 1;
    width: auto;
  }

  /* New-name entry (first-login onboarding and the change-name modal) is
     easy to fat-finger at desktop size on a phone -- give the input and its
     buttons real touch targets. */
  :root[data-device="phone"] .name-modal,
  :root[data-device="phone"] .onboarding-modal {
    width: min(560px, calc(100vw - 24px));
    max-width: min(560px, calc(100vw - 24px));
  }

  :root[data-device="phone"] #name-input,
  :root[data-device="phone"] #onboard-name {
    font-size: 20px;
    padding: 14px 16px;
    min-height: 52px;
    text-align: center;
  }

  :root[data-device="phone"] .name-modal h3,
  :root[data-device="phone"] .onboarding-modal h3 {
    font-size: 26px;
  }

  :root[data-device="phone"] .name-modal .feedback-actions .btn,
  :root[data-device="phone"] .onboarding-modal .feedback-actions .btn {
    min-height: 48px;
    flex: 1 1 auto;
  }

  :root[data-device="phone"] .build-footer {
    margin-bottom: calc(14px + env(safe-area-inset-bottom));
    padding: 6px 12px;
  }

  :root[data-device="phone"] #screen-game {
    height: 100dvh;
    overflow: hidden;
  }

  :root[data-device="phone"] #screen-game .topbar {
    background: rgba(7, 11, 22, 0.92);
    border-bottom: 1px solid rgba(212, 167, 72, 0.26);
    left: 0;
    min-height: var(--mobile-game-topbar-space);
    padding: calc(4px + env(safe-area-inset-top)) 8px 4px;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 20;
  }

  :root[data-device="phone"] #screen-game .brand {
    font-size: 20px;
  }

  :root[data-device="phone"] #screen-game .game-banner {
    font-size: 16px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  :root[data-device="phone"] #screen-game .topbar-right .btn {
    padding: 5px 8px;
  }

  :root[data-device="phone"] .admin-test-row {
    display: none !important;
  }

  :root[data-device="phone"] .game-grid {
    display: block;
    flex: 1 1 auto;
    inset: var(--mobile-game-topbar-space) 0 var(--mobile-hud-space) 0;
    padding: 0;
    position: fixed;
  }

  :root[data-device="phone"] .board-wrap {
    border: 0;
    border-radius: 0;
    bottom: var(--mobile-hud-space);
    height: auto;
    left: 0;
    position: fixed;
    right: 0;
    top: var(--mobile-game-topbar-space);
    width: 100vw;
  }

  :root[data-device="phone"] #board {
    height: 100%;
    touch-action: none;
    width: 100vw;
  }

  :root[data-device="phone"] .board-controls {
    align-items: center;
    flex-direction: row;
    /* Blitz adds two more buttons (render mode, camera vantage) to this row
       — on a narrow phone they no longer fit on one line next to
       zoom-fit/replay/feedback, and without wrapping the row overflows
       leftward under the fixed #blitz3d-fps badge. Wrapping keeps every
       button on-screen and tappable instead. */
    flex-wrap: wrap;
    justify-content: flex-end;
    left: auto;
    max-width: calc(100vw - 20px);
    right: 10px;
    top: 8px;
    z-index: 24;
  }

  :root[data-device="phone"] .board-controls .btn {
    min-height: 34px;
    min-width: 38px;
    padding: 5px 8px;
  }

  :root[data-device="phone"] .board-controls #zoom-in,
  :root[data-device="phone"] .board-controls #zoom-out {
    display: none;
  }

  :root[data-device="phone"] .board-controls #blitz-render-mode,
  :root[data-device="phone"] .board-controls #blitz-view-step {
    max-width: 108px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  :root[data-device="phone"] .board-controls #btn-game-feedback {
    font-size: 0;
  }

  :root[data-device="phone"] .board-controls #btn-game-feedback::before {
    content: "Feedback";
    font-size: 12px;
  }

  :root[data-device="phone"] .boss-mini-board {
    bottom: 20px;
    max-width: 240px;
    padding: 7px 9px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-track-label {
    font-size: 11px;
    margin-right: 4px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-box {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    font-size: 8px;
    line-height: 10px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-box.major {
    width: 14px;
    height: 14px;
    line-height: 11px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-rows {
    gap: 3px;
    margin-top: 6px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-row {
    gap: 3px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-phase {
    font-size: 12px;
    margin-right: 2px;
    min-width: 34px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-chip {
    border-radius: 4px;
    font-size: 9px;
    height: 15px;
    line-height: 13px;
    min-width: 17px;
    padding: 0 2px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-none {
    font-size: 10px;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-now {
    gap: 4px;
    height: 7px;
    margin: 1px 0;
  }

  :root[data-device="phone"] .boss-mini-board .bmb-now span {
    font-size: 8px;
  }

  :root[data-device="phone"] .board-status-stack {
    left: 10px;
    max-width: calc(100vw - 20px);
    right: 10px;
    top: calc(70px + env(safe-area-inset-top));
    z-index: 19;
  }

  :root[data-device="phone"] .sb-pause-toggle {
    grid-template-columns: 22px 24px minmax(0, 1fr);
  }

  :root[data-device="phone"] .sb-pause-toggle:hover,
  :root[data-device="phone"] .sb-pause-toggle:focus-within,
  :root[data-device="phone"] .sb-pause-toggle.status-expanded {
    width: min(100%, calc(100vw - 20px));
  }

  :root[data-device="phone"] .orders-panel,
  :root[data-device="phone"] .fleet-panel {
    border-radius: 10px 10px 0 0;
    bottom: var(--mobile-hud-space);
    box-shadow: 0 -18px 52px rgba(0, 0, 0, 0.58);
    left: 0;
    max-height: min(76dvh, calc(100dvh - 104px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));
    padding: 10px;
    position: fixed;
    right: 0;
    transform: translateY(106%);
    transition: transform 180ms ease;
    z-index: 50;
  }

  :root[data-device="phone"] .orders-panel {
    overflow-y: auto;
  }

  :root[data-device="phone"] .fleet-panel {
    display: flex;
    min-height: 0;
    overflow: hidden;
  }

  :root[data-device="phone"] body.mobile-orders-open .orders-panel {
    transform: translateY(0);
  }

  :root[data-device="phone"] body.mobile-fleet-open .fleet-panel {
    transform: translateY(0);
  }

  :root[data-device="phone"] #fleet-list {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 8px;
    max-height: none;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 2px;
  }

  :root[data-device="phone"] .fleet-card {
    flex: 0 0 auto;
  }

  :root[data-device="phone"] .mobile-orders-close {
    display: inline-flex;
    justify-content: center;
    margin-left: auto;
    min-height: 32px;
    padding: 5px 12px;
    width: max-content;
  }

  :root[data-device="phone"] .pile {
    height: 38px;
    width: 29px;
  }

  :root[data-device="phone"] .pile-row {
    align-items: center;
    gap: 8px;
  }

  :root[data-device="phone"] .order-slots {
    gap: 7px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin: 6px 0;
  }

  :root[data-device="phone"] .order-slot {
    gap: 5px;
    min-height: 118px;
    padding: 7px 5px;
    grid-template-rows: minmax(62px, 1fr) minmax(38px, auto);
  }

  :root[data-device="phone"] .slot-shot-preview {
    display: none;
  }

  :root[data-device="phone"] .slot-shot-preview.mobile-popup {
    display: grid;
    font-size: 13px;
  }

  :root[data-device="phone"] .shot-preview-kicker {
    font-size: 13px;
  }

  :root[data-device="phone"] .order-slot .slot-label {
    display: none;
  }

  :root[data-device="phone"] .order-slot .slot-cards {
    min-height: 62px;
  }

  /* Phone's .card.in-slot is 58x82 (vs. desktop's 82x114) -- the shared
     .order-slot.stacked rules above (alignment, wrap, z-index) apply as-is.
     The *lift direction* does not, though: phone keeps its own established
     reveal (the front/last card lifts up-left, exposing the back card's
     bottom-left corner) rather than desktop's newer "back card lifts to
     show its title" scheme, so this fully cancels and replaces the shared
     transform instead of just overriding numbers. */
  :root[data-device="phone"] .order-slot.stacked .slot-cards {
    min-height: 106px;
  }

  :root[data-device="phone"] .order-slot.stacked {
    min-height: 162px;
    grid-template-rows: minmax(106px, 1fr) minmax(38px, auto);
  }

  :root[data-device="phone"] .order-slot.stacked .card.in-slot {
    margin-left: -34px;
  }

  :root[data-device="phone"] .order-slot.stacked .card.in-slot:first-child {
    margin-left: 0;
  }

  /* Cancel the desktop back-card lift first; the more specific nth-child(n+2)
     rule right after wins the cascade tie for cards it also matches. */
  :root[data-device="phone"] .order-slot.stacked .card.in-slot:not(:last-child) {
    transform: none;
  }

  :root[data-device="phone"] .order-slot.stacked .card.in-slot:nth-child(n+2) {
    transform: translate(-8px, -24px);
  }

  :root[data-device="phone"] .slot-empty {
    gap: 4px;
  }

  :root[data-device="phone"] .slot-empty-action {
    color: var(--gold-bright);
    display: block;
    font-family: "Pirata One", serif;
    font-size: 22px;
    font-style: normal;
    line-height: 1;
  }

  :root[data-device="phone"] .slot-empty-note {
    font-size: 10px;
  }

  :root[data-device="phone"] .seal-toggle {
    height: 34px;
    width: 70px;
  }

  :root[data-device="phone"] .seal-mode-text {
    font-size: 11px;
  }

  :root[data-device="phone"] .seal-toggle.overdrive .seal-mode-text {
    font-size: 9px;
  }

  :root[data-device="phone"] .seal-control {
    gap: 6px;
    grid-template-columns: minmax(70px, auto) minmax(30px, auto);
    min-height: 38px;
    position: relative;
    z-index: 2;
  }

  :root[data-device="phone"] .seal-details-button {
    font-size: 15px;
    height: 30px;
    line-height: 28px;
    width: 30px;
  }

  :root[data-device="phone"] .card.in-slot {
    height: 82px;
    width: 58px;
  }

  :root[data-device="phone"] .hand-area {
    justify-content: flex-start;
    min-height: 126px;
    overflow-x: auto;
    padding-bottom: 10px;
    flex-wrap: nowrap;
  }

  :root[data-device="phone"] .hand-area .card {
    height: 132px;
    width: 96px;
  }

  :root[data-device="phone"] .hand-area .card:hover,
  :root[data-device="phone"] .card:hover,
  :root[data-device="phone"] .card.in-slot:hover {
    transform: none !important;
  }

  /* Blitz's own bottom rail, thumb-sized. Cards are sized off the viewport so
     they fill the dead space between the ship model and the bottom edge —
     the whole point of putting the rail there — and shrink to fit a bigger
     hand rather than scrolling; a scroller here only ever bought a few px
     and cost a stray scrollbar across the rail. The lever/speed islands get
     narrower gutters than desktop so a phone doesn't waste width on them. */
  /* Asymmetric gutters: the lever is narrow, the speed bars are not. */
  :root[data-device="phone"] .blitz-rail {
    padding: 0 62px 0 44px;
    gap: 4px;
  }

  :root[data-device="phone"] .blitz-card-rail {
    gap: 6px;
  }

  :root[data-device="phone"] .blitz-card-rail .card {
    max-width: 108px;
    font-size: 10px;
  }

  :root[data-device="phone"] .blitz-card-rail .card.armed {
    transform: translateY(-6px);
  }

  :root[data-device="phone"] .lever-track {
    width: 26px;
    height: 84px;
  }

  :root[data-device="phone"] .lever-knob {
    width: 20px;
    height: 20px;
  }

  :root[data-device="phone"] .blitz-overdrive-btn.active .lever-knob {
    transform: translateY(-58px);
  }

  /* The word "Overdrive" is wider than the lever it labels, so on a phone it
     runs under the first card. The flame knob in a lever track reads on its
     own at this size; the button keeps its aria-label for screen readers. */
  :root[data-device="phone"] .lever-label {
    display: none;
  }

  :root[data-device="phone"] .blitz-speed-stack {
    min-height: 22px;
  }

  :root[data-device="phone"] .order-slot.stacked .card.in-slot:nth-child(n+2),
  :root[data-device="phone"] .order-slot.stacked .card.in-slot:nth-child(n+2):hover {
    transform: translate(-8px, -24px) !important;
  }

  :root[data-device="phone"] .orders-actions {
    display: grid;
    align-items: center;
    grid-template-columns: max-content minmax(0, 0.65fr) minmax(0, 1fr);
    margin-top: 2px;
  }

  :root[data-device="phone"] .orders-actions .btn {
    width: 100%;
  }

  :root[data-device="phone"] .orders-hint {
    display: none;
  }

  :root[data-device="phone"] body.mobile-game-active .mobile-game-hud {
    background: rgba(7, 11, 22, 0.92);
    border: 1px solid rgba(212, 167, 72, 0.36);
    border-radius: 10px;
    bottom: calc(10px + env(safe-area-inset-bottom));
    box-shadow: var(--shadow);
    display: grid;
    gap: 7px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    left: 10px;
    padding: 7px;
    position: fixed;
    right: 10px;
    z-index: 70;
  }

  :root[data-device="phone"] body.mobile-game-active .mobile-game-hud .btn {
    min-height: 42px;
    padding: 8px 6px;
  }

  /* Lobby StarMap/Comms tab bar — same recipe as .mobile-game-hud above.
     Scoped to the lobby screen (app.js sets body[data-screen]) so it doesn't
     paint over the battle screen (when a fight is launched from a StarMap
     tile, which doesn't go through Lobby.leave()) or the account screen. */
  :root[data-device="phone"] body[data-screen="lobby"].lobby-mobile-active .lobby-mobile-tabs {
    background: rgba(7, 11, 22, 0.92);
    border: 1px solid rgba(212, 167, 72, 0.36);
    border-radius: 10px;
    bottom: calc(10px + env(safe-area-inset-bottom));
    box-shadow: var(--shadow);
    display: grid;
    align-items: center;
    gap: 7px;
    grid-template-columns: 1fr 1fr auto;
    left: 10px;
    padding: 7px;
    position: fixed;
    right: 10px;
    z-index: 70;
  }

  :root[data-device="phone"] body.lobby-mobile-active .lobby-mobile-tabs .btn {
    min-height: 42px;
    padding: 8px 6px;
  }

  /* StarDock is its own screen (#screen-stardock, [data-screen="stardock"]);
     StarBreach is still a body-level overlay drawn on top of whatever screen
     opened it. :has() lets this hold while StarBreach is open from within
     StarDock too, without the bar reappearing until both are closed. */
  :root[data-device="phone"] body[data-screen="stardock"] .lobby-mobile-tabs,
  :root[data-device="phone"] body[data-screen="stardock"] .lobby-comms-tabs,
  :root[data-device="phone"] body:has(#player-bossdesigner-overlay:not(.hidden)) .lobby-mobile-tabs,
  :root[data-device="phone"] body:has(#player-bossdesigner-overlay:not(.hidden)) .lobby-comms-tabs {
    display: none;
  }

  :root[data-device="phone"] .sos-light {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid rgba(255, 130, 120, .4);
    background: #3a0d12;
    box-shadow: inset 0 0 6px rgba(0, 0, 0, .5);
    padding: 0;
    cursor: default;
  }

  :root[data-device="phone"] .sos-light.active {
    background: #ff4a3d;
    box-shadow: 0 0 10px rgba(255, 74, 61, .85), 0 0 18px rgba(255, 74, 61, .5);
    cursor: pointer;
    animation: sosPulse 1s ease-in-out infinite;
  }

  @keyframes sosPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .45; }
  }

  :root[data-device="phone"] .overlay {
    align-items: end;
    background: rgba(4, 7, 14, 0.42);
    padding: calc(70px + env(safe-area-inset-top)) 10px var(--mobile-hud-space);
    place-items: end center;
  }

  /* The Feedback form is tall enough that bottom-aligning it (the default
     above) pushes its Send/Cancel buttons under the lobby's StarMap/Comms
     bar. Top-aligning keeps them on screen regardless of content length. */
  :root[data-device="phone"] #feedback-overlay {
    align-items: start;
    place-items: start center;
    padding-top: calc(14px + env(safe-area-inset-top));
  }

  /* The Arena Challenge builder (crew slots, roster, team split, post button)
     is tall — bottom-aligning it the same way pushes its controls off the
     bottom of the screen. Top-align it and let it fill the screen. */
  :root[data-device="phone"] .arena-overlay {
    align-items: start;
    place-items: start center;
    padding-top: calc(14px + env(safe-area-inset-top));
    padding-bottom: var(--lobby-tab-space);
  }

  :root[data-device="phone"] .arena-overlay .picker {
    max-height: calc(100dvh - var(--lobby-topbar-space) - var(--lobby-tab-space) - 28px);
  }

  /* Encounter popups should use the full screen height above the
     StarMap/Comms bar, not the generic 72dvh cap below. */
  :root[data-device="phone"] .encounter-overlay {
    align-items: start;
    padding-top: calc(14px + env(safe-area-inset-top));
    padding-bottom: var(--lobby-tab-space);
    place-items: start center;
  }

  :root[data-device="phone"] .encounter-overlay .picker {
    max-height: calc(100dvh - var(--lobby-tab-space) - 28px);
  }

  :root[data-device="phone"] .picker {
    border-radius: 10px;
    max-height: 72dvh;
    max-width: 440px;
    overflow: auto;
    padding: 16px;
    width: 100%;
  }

  :root[data-device="phone"] .picker h3 {
    font-size: 22px;
  }

  :root[data-device="phone"] .picker .picker-options {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Port/Ahead/Starboard: only 3 short options, plenty of room for one row. */
  :root[data-device="phone"] .picker.picker-heading .picker-options {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  :root[data-device="phone"] .picker-option {
    min-width: 0;
    padding: 12px 10px;
  }

  :root[data-device="phone"] .stack-card-picker {
    max-width: 520px;
  }

  :root[data-device="phone"] .stack-card-note {
    color: var(--ink-dim);
    font-size: 12px;
    line-height: 1.3;
    margin: -6px 0 10px;
  }

  :root[data-device="phone"] .stack-card-options {
    display: flex;
    gap: 12px;
    justify-content: center;
    overflow-x: auto;
    padding: 2px 2px 8px;
  }

  :root[data-device="phone"] .stack-card-picker .card .card-name {
    font-size: 14px;
    line-height: 1.12;
    padding-left: 7px;
    padding-right: 7px;
  }

  :root[data-device="phone"] .stack-card-option {
    align-items: center;
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    gap: 8px;
  }

  :root[data-device="phone"] .ship-modal {
    max-height: 78dvh;
  }

  :root[data-device="phone"] .ship-modal svg {
    max-height: 46dvh;
    width: 100%;
  }

  :root[data-device="phone"] .replay-controls {
    bottom: calc(74px + env(safe-area-inset-bottom));
    max-width: calc(100vw - 20px);
  }
}

/* responsive-ish */
@media (max-width: 1500px) {
  .game-grid { grid-template-columns: minmax(0, 1fr) 480px; }
  .hand-area .card { width: 100px; height: 140px; }
}
@media (max-width: 1200px) {
  .game-grid { grid-template-columns: minmax(0, 1fr) 420px; }
  .hand-area .card { width: 88px; height: 122px; }
}
@media (max-width: 1080px) {
  .lobby-grid { grid-template-columns: 1fr; }
}

/* ── auth screen: guest login, policy links ───────────────────────────── */
.guest-signin {
  width: 280px;
  max-width: 100%;
  margin: 0 auto;
  display: block;
}
.guest-note {
  margin: 6px auto 0;
  max-width: 280px;
  font-family: "Space Grotesk", sans-serif;
  font-size: 12px;
  color: var(--ink-dim);
}
.auth-policy-links {
  margin-top: 16px;
  font-family: "Space Grotesk", sans-serif;
  font-size: 13px;
  color: var(--ink-dim);
}
.auth-policy-links a { color: var(--gold-bright); }
.guest-badge {
  font-family: "Space Grotesk", sans-serif;
  font-size: 10px;
  letter-spacing: 1px;
  padding: 1px 5px;
  border: 1px solid var(--ink-dim);
  border-radius: 8px;
  color: var(--ink-dim);
  vertical-align: middle;
}

/* ── onboarding + reauth modals ───────────────────────────────────────── */
.onboarding-modal, .reauth-modal, .delete-modal { max-width: 460px; }
.onboarding-check {
  display: flex !important;
  flex-direction: row !important;
  align-items: flex-start;
  gap: 8px;
  font-family: "Space Grotesk", sans-serif;
  font-size: 14px;
  text-align: left;
}
.onboarding-check input { margin-top: 3px; }
.onboarding-check a { color: var(--gold-bright); }
.reauth-modal .google-signin { margin: 10px auto; }
.reauth-modal .btn { display: block; width: 100%; margin-bottom: 8px; }

/* ── account screen ───────────────────────────────────────────────────── */
.account-wrap { max-width: 760px; margin: 0 auto; padding: 24px 20px 60px; }
.account-section { margin-bottom: 22px; }
.account-line {
  font-family: "Space Grotesk", sans-serif;
  font-size: 15px;
  color: var(--ink);
  margin: 6px 0;
}
.account-line a { color: var(--gold-bright); }
.account-line .muted, .account-section .muted { color: var(--ink-dim); font-size: 13px; }
.account-providers { width: 100%; margin-bottom: 10px; }
.account-link-buttons { margin-top: 4px; }
.account-actions { justify-content: flex-start; }
.settings-toggle { display: inline-flex; gap: 4px; margin-left: 10px; }
.settings-toggle button.active { background: var(--gold); color: #241a05; border-color: var(--gold); }
.account-deleted { text-align: center; padding: 30px 0; }

/* ── claim my legend (guest → permanent account) ──────────────────────── */
.claim-modal { max-width: 440px; }
.claim-modal .google-signin,
.claim-modal .microsoft-signin,
.claim-modal .discord-signin {
  display: block;
  width: 100%;
  margin: 0 auto 8px;
}
#btn-claim-legend { margin-right: 8px; }
