/* =========================================================================
   Galaxy Dog's — Pong Arena Blitz
   Layout is deliberately dumb: the CSS only has to centre a fixed-aspect
   box and stack full-bleed overlays on top of it. All gameplay drawing
   happens on the canvas in design-space coordinates (see js/config.js).
   ========================================================================= */

:root {
  --bg:        #05060f;
  --ink:       #e8f4ff;
  --accent:    #48e5ff;  /* player cyan   */
  --danger:    #ff4d6d;  /* enemy red     */
  --gold:      #ffd166;  /* orb / score   */
  --panel:     rgba(6, 10, 26, 0.88);
}

* { box-sizing: border-box; }

/* -------------------------------------------------------------------------
   THE STAGE BOX, and the UI scale derived from it.

   These live on :root rather than on #stage because the ROOT FONT SIZE is
   derived from them, and html can only read variables defined on itself.

   WHY THE ROOT FONT SIZE IS TIED TO THE STAGE:
   The canvas has always rendered a fixed 480x854 design space scaled to fit.
   The DOM overlays did not — their type scaled (vh/stage-based clamps) but
   their BOXES did not: a 46px ship tile stayed 46px whether the stage was 480
   wide or 253. So the menu grew relative to its container as the container
   shrank, and on a small embed the LAUNCH button was pushed off the bottom.
   CrazyGames' desktop player hands the iframe roughly 253x450 CSS pixels and
   their mobile app is not much larger, which is where this surfaced.

   Anchoring 1rem to the stage makes every rem-sized box scale exactly like
   the canvas does, so the menu keeps its proportions at any size and cannot
   outgrow the stage. The bounds are deliberately wide: a tight clamp would
   re-break the guarantee at the extremes, which is the bug this replaces.
   ------------------------------------------------------------------------- */
:root {
  --stage-w: min(100vw, calc(100vh * 480 / 854));
  --stage-h: min(100vh, calc(100vw * 854 / 480));
}

@supports (height: 100dvh) {
  /* Dynamic viewport units where supported — stops mobile browser chrome from
     cropping the bottom of the playfield when the URL bar hides/shows. */
  :root {
    --stage-w: min(100dvw, calc(100dvh * 480 / 854));
    --stage-h: min(100dvh, calc(100dvw * 854 / 480));
  }
}

html {
  font-size: max(7.5px, clamp(6px, calc(var(--stage-w) * 16 / 480), 30px));
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
  overflow: hidden;
  /* Kill mobile tap highlight / text selection so rapid tapping feels clean */
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  overscroll-behavior: none;
  touch-action: manipulation;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Subtle vignette behind the letterboxed stage */
  background:
    radial-gradient(ellipse at 50% 30%, #10173a 0%, #05060f 65%, #02030a 100%);
}

/* -------------------------------------------------------------------------
   #stage — the 480:854 portrait playfield, scaled to fit any screen.
   The min() pair locks the aspect ratio deterministically: fit by width on
   tall screens, fit by height on short/landscape ones. No media query needed.
   ------------------------------------------------------------------------- */
#stage {
  position: relative;
  /* Sized from the root variables above. The overlays inside size themselves
     against the STAGE, not the viewport: a heading in vh units grows with the
     screen height while this box stays a narrow letterboxed column — which is
     exactly how the title ended up wider than the panel it sits in and got
     clipped on phones. */
  width:  var(--stage-w);
  height: var(--stage-h);
  overflow: hidden;
  border-radius: 10px;
  box-shadow: 0 0 60px rgba(72, 229, 255, 0.10), 0 0 0 1px rgba(72,229,255,0.14);
}

#game {
  display: block;
  width: 100%;
  height: 100%;
  /* touch-action is NOT inherited, so setting it on body does not cover the
     canvas. `none` hands every gesture to the game: without it, mobile
     browsers keep double-tap-to-zoom and pan, and rapid lane tapping — the
     core control — would randomly zoom the playfield instead of moving. */
  touch-action: none;
}

/* -------------------------------------------------------------------------
   Overlays (menu / game over). Drawn as DOM instead of canvas so buttons get
   native tap targets and accessibility for free.
   ------------------------------------------------------------------------- */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;

  /* -----------------------------------------------------------------------
     WHY `safe center` AND `overflow-y: auto`.

     The menu's content is a fixed ~820px tall — pickers, buttons and rows that
     do not shrink — while the stage height follows the window. On anything
     under about 850px the column overflowed, and `justify-content: center`
     overflows in BOTH directions: the surplus is split evenly above and below,
     so the TITLE slid off the top of the stage and became unreachable, because
     there was no scrolling either.

     `safe center` centres only while it fits and falls back to flex-start the
     moment it does not, so the overflow all goes to the bottom — where
     `overflow-y: auto` makes it reachable. Nothing can be lost off the top.
     ----------------------------------------------------------------------- */
  justify-content: center;
  justify-content: safe center;
  overflow-y: auto;
  overscroll-behavior: contain;

  /* Plain rem now that 1rem tracks the stage (see :root): these stay in exact
     proportion at every size. They were also simply too generous — 38px of
     padding top and bottom plus ~7px between sixteen rows spent 180px of an
     854px stage on empty space, which is most of why the menu overflowed at
     its own design size. */
  gap: 0.3rem;
  padding: 1.1rem clamp(1rem, calc(var(--stage-w, 100vw) * 0.07), 2.6rem);
  text-align: center;
  background: var(--panel);
  backdrop-filter: blur(3px);
  z-index: 10;
}

/* -------------------------------------------------------------------------
   Keyboard-only affordances. Same-keyboard co-op and an arrow-key legend are
   not merely unhelpful on a phone, they are impossible to act on — and they
   cost ~70px of a stage that is already tight there. `pointer: coarse` tests
   the PRIMARY input, so a touchscreen laptop (which reports `fine`) keeps
   them; only genuinely touch-driven devices drop them.
   ------------------------------------------------------------------------- */
/* !important for the same reason .hidden carries it: these targets set their
   own `display` later in the file (.coop-toggle is inline-flex), and an equal
   specificity rule that appears earlier simply loses. Without it this query
   matched and did nothing. */
@media (pointer: coarse) {
  .kbd-only { display: none !important; }
}

/* The same two rows are also the first thing to go on a SHORT stage. When the
   stage is height-constrained its height equals the viewport's, so this reads
   the stage accurately for the case that matters: CrazyGames' desktop player
   gives the iframe about 253x450, where these two rows are ~15% of the column.
   Nobody is playing same-keyboard two-player in a 253px-wide embed. */
@media (max-height: 620px) {
  .kbd-only { display: none !important; }
}

/* The scrollbar would sit over the artwork and looks wrong on a game canvas. */
.overlay::-webkit-scrollbar { width: 0; height: 0; }
.overlay { scrollbar-width: none; }

/* -------------------------------------------------------------------------
   .hidden is a UTILITY and must work on ANY element.

   It used to be written once per component (.overlay.hidden, .btn-ghost.hidden,
   .pause-btn.hidden, and six more), which meant hiding a new element silently
   did nothing until someone remembered to add a matching rule. That is exactly
   how the ONLINE button shipped visible in a build with online co-op disabled:
   JS added the class, no rule matched, and the player was invited into a lobby
   that could never connect.

   `!important` is deliberate: "hidden" is not a suggestion, and a utility that
   loses to component specificity is the bug this replaces.
   ------------------------------------------------------------------------- */
.hidden { display: none !important; }

.overlay h1 {
  margin: 0;
  /* Sized against the stage width, not the viewport height. "GALAXY DOG'S" is
     12 characters plus tracking, so it needs roughly 9% of the available width
     per character-pair to survive the overlay's 8% padding on a 390px phone.
     The clamp keeps it sane on very small and very large screens. */
  /* Sized by BOTH axes. Width keeps it inside the panel (the original clip);
     height keeps it proportionate on a short window, where a title tuned only
     to width eats a quarter of the menu. min() takes whichever is tighter. */
  font-size: min(
    clamp(1.05rem, calc(var(--stage-w, 100vw) * 0.078), 2.6rem),
    calc(var(--stage-h, 100vh) * 0.052)
  );
  letter-spacing: 0.10em;
  /* Never wrap: "GALAXY DOG" / "'S" on two lines looks broken. With the width
     -derived size above it always fits, and this makes any future regression
     obvious immediately rather than silently rewrapping. */
  white-space: nowrap;
  max-width: 100%;
  color: var(--accent);
  text-shadow: 0 0 18px rgba(72, 229, 255, 0.55);
}

.overlay h2 {
  margin: 0 0 0.4rem;
  font-size: max(7.5px, clamp(0.9rem, 3vh, 1.2rem));
  font-weight: 500;
  letter-spacing: 0.28em;
  color: var(--ink);
  opacity: 0.75;
}

#resultTitle.win { color: var(--gold); text-shadow: 0 0 18px rgba(255, 209, 102, 0.6); }
#resultTitle.lose { color: var(--danger); text-shadow: 0 0 18px rgba(255, 77, 109, 0.55); }

.hint {
  margin: 0;
  font-size: max(7.5px, clamp(0.75rem, 2.2vh, 0.95rem));
  line-height: 1.6;
  opacity: 0.8;
}

.hint.small { font-size: max(7.5px, clamp(0.65rem, 1.8vh, 0.8rem)); opacity: 0.5; }
.result-line { margin: 0; opacity: 0.75; font-size: max(7.5px, clamp(0.75rem, 2.2vh, 0.95rem)); }

/* Final score readout ---------------------------------------------------- */
.scorebox {
  display: flex;
  gap: 1.4rem;
  margin: 0.8rem 0 0.4rem;
}

.scorebox > div { display: flex; flex-direction: column; gap: 0.25rem; }
.scorebox .lbl { font-size: max(7.5px, 0.62rem); letter-spacing: 0.18em; opacity: 0.5; }
.scorebox .val { font-size: max(7.5px, clamp(1rem, 3.4vh, 1.5rem)); color: var(--gold); font-weight: 700; }

/* Buttons ---------------------------------------------------------------- */
.btn {
  margin-top: 0.9rem;
  padding: 0.85rem 2.6rem;
  font: inherit;
  font-size: max(7.5px, clamp(0.85rem, 2.6vh, 1.05rem));
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--bg);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: 0 0 24px rgba(72, 229, 255, 0.45);
  transition: transform 0.08s ease, box-shadow 0.2s ease;
}

.btn:active { transform: scale(0.96); box-shadow: 0 0 10px rgba(72, 229, 255, 0.3); }
.btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* -------------------------------------------------------------------------
   Rank + XP. The badge sprites are tall and narrow (64x294), so they are
   height-constrained and allowed to keep their aspect ratio.
   ------------------------------------------------------------------------- */
.rank-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: 0.5rem 0 0.2rem;
  width: min(280px, 80%);
}

.rank-badge {
  height: clamp(2.375rem, 7vh, 3.375rem);
  width: auto;
  filter: drop-shadow(0 0 8px rgba(72, 229, 255, 0.4));
}

.rank-info { flex: 1; display: flex; flex-direction: column; gap: 0.25rem; text-align: left; }
.rank-name { font-size: max(7.5px, clamp(0.8rem, 2.4vh, 1rem)); font-weight: 700; letter-spacing: 0.08em; color: var(--accent); }
.rank-next { font-size: max(7.5px, 0.62rem); opacity: 0.55; letter-spacing: 0.04em; }

.xp-bar {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.13);
  overflow: hidden;
}

.xp-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--gold));
  /* Slow enough that the fill reads as a reward, not a repaint. */
  transition: width 900ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---- Hull picker -------------------------------------------------------- */
.ship-picker {
  display: flex;
  gap: 0.45rem;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0.3rem 0 0.1rem;
}

.ship-opt {
  /* rem, not px: these tiles are the single largest block in the menu (two
     rows of them) and pinning them to px is what made the menu grow relative
     to a shrinking stage. 2.875rem == the original 46px at design size. */
  width: 2.875rem; height: 2.875rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px;
  border: 1px solid rgba(72, 229, 255, 0.25);
  background: rgba(72, 229, 255, 0.05);
  cursor: pointer;
  padding: 0;
  transition: transform 0.1s ease, border-color 0.2s ease, background 0.2s ease;
}

.ship-opt img { width: 34px; height: 34px; image-rendering: auto; }
.ship-opt:active { transform: scale(0.94); }
.ship-opt.selected { border-color: var(--gold); background: rgba(255, 209, 102, 0.14); }

/* Locked hulls stay visible but unmistakably out of reach. */
.ship-opt.locked { cursor: not-allowed; border-color: rgba(255,255,255,0.1); background: rgba(255,255,255,0.03); }
.ship-opt.locked img { filter: grayscale(1) brightness(0.4); }
.ship-opt.locked::after {
  content: attr(data-rank);
  position: absolute;
  font-size: max(7.5px, 0.55rem); font-weight: 700; color: var(--ink); opacity: 0.75;
}
.ship-opt { position: relative; }

/* -------------------------------------------------------------------------
   Daily missions. Compact by necessity — they sit on the menu, above the
   fold, on a phone. Progress bars rather than counters, because a bar that
   is nearly full is far more motivating than the text "18/25".
   ------------------------------------------------------------------------- */
.missions { width: min(300px, 86%); display: flex; flex-direction: column; gap: 0.3rem; margin: 0.15rem 0; }

.mission {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: max(7.5px, 0.68rem); text-align: left;
}
.mission-bar { flex: 1; height: 4px; border-radius: 999px; background: rgba(255,255,255,0.12); overflow: hidden; }
.mission-fill { height: 100%; border-radius: 999px; background: var(--accent); transition: width 500ms ease; }
.mission-text { opacity: 0.8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; }
.mission-xp { opacity: 0.5; font-size: max(7.5px, 0.6rem); }
.mission.done .mission-text { color: var(--gold); opacity: 1; text-decoration: line-through; }
.mission.done .mission-fill { background: var(--gold); }

.streak-badge {
  font-size: max(7.5px, 0.62rem); letter-spacing: 0.1em; color: var(--gold);
  opacity: 0.9; margin-top: 0.1rem;
}

/* ---- Secondary buttons and menu links ----------------------------------- */
.btn-ghost {
  background: transparent;
  color: var(--accent);
  border: 1px solid rgba(72,229,255,0.45);
  box-shadow: none;
  padding: 0.6rem 1.8rem;
  margin-top: 0.5rem;
}
.btn-ghost:active { transform: scale(0.96); }
.btn-ghost.hidden { display: none; }

/* wrap + column-gap: five labels in one nowrap row overflowed the stage on a
   phone and were clipped at BOTH edges (LEADERBOARD and SHOP ran off-screen in
   the CrazyGames mobile app). Wrapping degrades to two tidy rows instead. */
.menu-links {
  display: flex; flex-wrap: wrap; justify-content: center;
  column-gap: 1rem; row-gap: 0.1rem; margin-top: 0.4rem; max-width: 100%;
}
.link-btn {
  background: none; border: 0; padding: 0.3rem 0.2rem;
  color: var(--ink); opacity: 0.55; cursor: pointer;
  font: inherit; font-size: max(7.5px, 0.66rem); letter-spacing: 0.14em; font-weight: 700;
}
.link-btn:active { opacity: 1; }

/* ---- Leaderboard --------------------------------------------------------- */
.panel-title { font-size: max(7.5px, clamp(1.1rem, 4vh, 1.5rem)) !important; letter-spacing: 0.18em; }
.board-list {
  list-style: none; padding: 0; margin: 0.4rem 0;
  width: min(300px, 88%); max-height: calc(var(--stage-h, 100vh) * 0.42); overflow-y: auto;
  display: flex; flex-direction: column; gap: 0.22rem;
}
.board-row {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: max(7.5px, 0.74rem); padding: 0.32rem 0.5rem;
  border-radius: 6px; background: rgba(255,255,255,0.04);
}
.board-row.me { background: rgba(72,229,255,0.14); color: var(--accent); font-weight: 700; }
.board-rank { width: 1.6rem; opacity: 0.6; }
.board-name { flex: 1; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-score { color: var(--gold); font-weight: 700; }
.board-round { opacity: 0.5; font-size: max(7.5px, 0.62rem); width: 2.4rem; text-align: right; }

.handle-row { display: flex; gap: 0.4rem; align-items: center; margin-top: 0.4rem; }
.handle-input {
  background: rgba(255,255,255,0.07); border: 1px solid rgba(72,229,255,0.3);
  border-radius: 6px; color: var(--ink); padding: 0.4rem 0.6rem;
  font: inherit; font-size: max(7.5px, 0.75rem); width: 10rem; text-align: center;
}
.handle-input:focus { outline: none; border-color: var(--accent); }

/* ---- Mode select --------------------------------------------------------- */
.mode-row { display: flex; gap: 0.4rem; flex-wrap: wrap; justify-content: center; margin-top: 0.5rem; }
.mode-btn {
  padding: 0.42rem 0.8rem; border-radius: 999px; font: inherit;
  font-size: max(7.5px, 0.62rem); font-weight: 700; letter-spacing: 0.12em;
  background: transparent; color: var(--accent);
  border: 1px solid rgba(72,229,255,0.4); cursor: pointer;
}
.mode-btn:active { transform: scale(0.96); }
.mode-btn.locked { color: var(--ink); opacity: 0.35; border-color: rgba(255,255,255,0.15); cursor: not-allowed; }
.mode-btn.done { opacity: 0.45; }
.mode-btn.daily { color: var(--gold); border-color: rgba(255,209,102,0.5); }

/* ---- Bolts --------------------------------------------------------------- */
.bolts-bar {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem;
  font-size: max(7.5px, 0.68rem); font-weight: 700; letter-spacing: 0.06em;
  color: var(--gold); margin: 0.2rem 0;
}
.bolts-bar .refill { color: var(--ink); opacity: 0.45; font-weight: 400; font-size: max(7.5px, 0.58rem); }
.bolts-bar.big { font-size: max(7.5px, 0.9rem); margin: 0.3rem 0 0.5rem; }

/* ---- Continue button ----------------------------------------------------- */
.btn-continue {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  background: var(--gold); color: #241408;
  box-shadow: 0 0 26px rgba(255,209,102,0.5);
  padding-left: 1.6rem; padding-right: 2rem;
}
.btn-continue.hidden { display: none; }
.wrench-icon { width: 26px; height: 26px; image-rendering: pixelated; }

/* ---- Shop ---------------------------------------------------------------- */
.shop-hero {
  display: flex; align-items: center; gap: 0.7rem;
  width: min(300px, 88%); padding: 0.6rem;
  border-radius: 10px; background: rgba(255,209,102,0.09);
  border: 1px solid rgba(255,209,102,0.3); text-align: left;
}
.shop-item-img { width: 62px; height: 62px; image-rendering: pixelated; flex: 0 0 auto; }
.shop-item-name { font-size: max(7.5px, 0.74rem); font-weight: 700; color: var(--gold); letter-spacing: 0.06em; }
.shop-item-desc { font-size: max(7.5px, 0.58rem); opacity: 0.65; line-height: 1.4; margin-top: 0.2rem; }

.shop-packs { display: flex; flex-direction: column; gap: 0.3rem; width: min(300px, 88%); margin: 0.5rem 0; }
.pack {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.6rem;
  border-radius: 8px; background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08); font-size: max(7.5px, 0.68rem);
}
.pack.best { border-color: rgba(72,229,255,0.5); background: rgba(72,229,255,0.08); }
.pack-name { flex: 1; text-align: left; font-weight: 700; }
.pack-sub { font-size: max(7.5px, 0.55rem); opacity: 0.5; font-weight: 400; display: block; }
.pack-price {
  padding: 0.25rem 0.6rem; border-radius: 999px;
  background: rgba(255,255,255,0.1); font-size: max(7.5px, 0.6rem); font-weight: 700;
  opacity: 0.6;
}

/* ---- Shared collection-panel copy --------------------------------------- */
.panel-intro {
  width: min(390px, 88%);
  margin: 0.15rem 0 0.45rem;
  color: rgba(232,244,255,0.62);
  font-size: max(7.5px, 0.62rem);
  line-height: 1.4;
  text-align: center;
}

/* ---- Options ------------------------------------------------------------- */
.opt-list {
  width: min(390px, 92%);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0.2rem 0 0.45rem;
}
.opt-group {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.5rem;
  border: 1px solid rgba(72,229,255,0.12);
  border-radius: 10px;
  background: rgba(5,9,22,0.62);
}
.opt-group-title {
  margin: 0 0 0.05rem;
  color: var(--accent);
  font-size: max(7.5px, 0.62rem);
  letter-spacing: 0.16em;
  text-align: left;
}

.opt-row {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.45rem 0.55rem; border-radius: 8px;
  background: rgba(255,255,255,0.04); text-align: left;
}
.opt-label { flex: 1; min-width: 0; font-size: max(7.5px, 0.72rem); font-weight: 700; }
.opt-desc { font-size: max(7.5px, 0.55rem); opacity: 0.5; line-height: 1.3; margin-top: 0.1rem; font-weight: 400; }
.opt-value { min-width: 2.4rem; color: var(--accent); font-size: max(7.5px, 0.6rem); text-align: right; }

/* Switch — a plain button styled as a toggle, so it stays keyboard-usable. */
.opt-switch {
  flex: 0 0 auto; width: 44px; height: 24px; border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.2); background: rgba(255,255,255,0.08);
  position: relative; cursor: pointer; padding: 0;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.opt-switch::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--ink); opacity: 0.75;
  transition: transform 0.18s ease, background 0.18s ease;
}
.opt-switch.on { background: rgba(72,229,255,0.35); border-color: var(--accent); }
.opt-switch.on::after { transform: translateX(20px); background: var(--accent); opacity: 1; }

.opt-slider { flex: 0 0 90px; accent-color: var(--accent); }

/* ---- Medals -------------------------------------------------------------- */
.medal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(135px, 1fr));
  gap: 0.5rem;
  width: min(410px, 92%);
  margin: 0.15rem 0 0.45rem;
}
.medal {
  position: relative;
  min-height: 116px;
  border-radius: 10px; padding: 0.6rem; text-align: left;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08);
}
.medal.earned { background: rgba(255,209,102,0.13); border-color: rgba(255,209,102,0.5); }
.medal-head { display: flex; align-items: center; gap: 0.45rem; }
.medal-icon {
  flex: 0 0 32px; width: 32px; height: 32px; display: grid; place-items: center;
  border-radius: 50%; color: rgba(232,244,255,0.5); background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.1); font-size: 0.85rem;
}
.medal.earned .medal-icon { color: #07101d; background: var(--gold); box-shadow: 0 0 16px rgba(255,209,102,0.32); }
.medal-name { font-size: max(7.5px, 0.7rem); font-weight: 700; letter-spacing: 0.04em; }
.medal.earned .medal-name { color: var(--gold); }
.medal-desc { font-size: max(7.5px, 0.58rem); opacity: 0.62; line-height: 1.35; margin-top: 0.45rem; }
.medal-status { margin-top: 0.45rem; color: rgba(232,244,255,0.5); font-size: max(7.5px, 0.54rem); letter-spacing: 0.08em; }
.medal.earned .medal-status { color: var(--gold); }
.medal-progress { height: 5px; margin-top: 0.25rem; border-radius: 999px; overflow: hidden; background: rgba(255,255,255,0.1); }
.medal-progress span { display: block; height: 100%; border-radius: inherit; background: var(--accent); }

/* ---- XP award on the results screen ------------------------------------- */
.xp-award { width: min(280px, 82%); display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.6rem; }
.xp-gain { font-size: max(7.5px, clamp(0.85rem, 2.6vh, 1.05rem)); font-weight: 700; color: var(--gold); letter-spacing: 0.06em; }
.result-rank { font-size: max(7.5px, 0.7rem); color: var(--accent); font-weight: 700; letter-spacing: 0.1em; }
.unlock-note { font-size: max(7.5px, 0.72rem); color: var(--accent); font-weight: 700; letter-spacing: 0.06em; }
.unlock-note.hidden { display: none; }

.bolt-award {
  width: min(280px, 82%); display: flex; justify-content: space-between; gap: 0.6rem;
  margin-top: 0.55rem; padding-top: 0.45rem; border-top: 1px solid rgba(255,209,102,0.22);
  font-size: max(7.5px, 0.65rem); letter-spacing: 0.08em;
}
.bolt-gain { color: var(--gold); font-weight: 700; }
.bolt-wallet { color: var(--ink); opacity: 0.65; }
.continue-balance {
  margin: 0.3rem 0 0; font-size: max(7.5px, 0.58rem); color: var(--gold);
  opacity: 0.72; letter-spacing: 0.06em;
}
.continue-balance.hidden { display: none; }

/* Mute toggle — small, unobtrusive, always reachable above the overlays. */
.icon-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 20;
  /* 44px is the minimum comfortable touch target (Apple HIG / WCAG 2.5.5).
     The visible circle stays small via the transparent border-box padding,
     so it does not crowd the HUD while remaining easy to hit with a thumb. */
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  touch-action: manipulation;
  line-height: 1;
  color: var(--accent);
  background: rgba(6, 10, 26, 0.55);
  border: 1px solid rgba(72, 229, 255, 0.3);
  border-radius: 50%;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.icon-btn:active { transform: scale(0.92); }
.icon-btn.muted { color: #6b7590; border-color: rgba(120, 130, 160, 0.3); opacity: 0.6; }
.icon-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Loading progress bar */
.bar {
  width: min(220px, 60%);
  height: 5px;
  margin-top: 0.5rem;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 3px;
  overflow: hidden;
}

.bar-fill {
  width: 0%;
  height: 100%;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
  transition: width 0.15s ease;
}


/* ---- Tutorial skip -------------------------------------------------------- */
.skip-btn {
  position: absolute; bottom: 12px; right: 12px; z-index: 25;
  background: rgba(4,6,16,0.7); border: 1px solid rgba(255,255,255,0.18);
  color: var(--ink); opacity: 0.7; border-radius: 999px;
  padding: 0.5rem 1rem; font: inherit; font-size: max(7.5px, 0.62rem);
  font-weight: 700; letter-spacing: 0.14em; cursor: pointer;
  min-width: 64px; min-height: 44px;   /* stays a comfortable touch target */
}
.skip-btn.hidden { display: none; }

/* ---- Rewarded video offer ------------------------------------------------- */
.btn-reward {
  background: transparent; color: var(--gold);
  border: 1px solid rgba(255,209,102,0.6); box-shadow: none;
  font-size: max(7.5px, 0.72rem); padding: 0.6rem 1.4rem;
}
.btn-reward.hidden { display: none; }

.result-links { display: flex; gap: 1.2rem; margin-top: 0.5rem; }


/* ---- Pause ---------------------------------------------------------------
   The pause button sits left of the mute toggle. Both are 44px targets so a
   thumb can hit either without looking.
   ------------------------------------------------------------------------- */
/* The pause glyph is drawn, not typed.
   The first version used the "❙❙" characters at 13px next to a 17px 🔇
   emoji, and it was effectively invisible: those bar glyphs are hairline
   thin, they render inconsistently across platforms, and next to a chunky
   emoji they read as nothing at all. Two CSS bars are identical everywhere
   and can be given real weight. */
.pause-btn { right: 62px; gap: 4px; }
.pause-btn.hidden { display: none; }
.pause-btn i {
  display: block;
  width: 4px;
  height: 15px;
  border-radius: 1px;
  background: var(--accent);
  box-shadow: 0 0 6px rgba(72, 229, 255, 0.6);
}
.pause-btn:active i { background: #fff; }

.pause-links { display: flex; gap: 1.1rem; margin-top: 0.8rem; flex-wrap: wrap; justify-content: center; }

/* ---- In-game music picker ------------------------------------------------ */
.music-picker-wrap { margin-top: 0.9rem; width: min(300px, 88%); }
.music-label { font-size: max(7.5px, 0.58rem); letter-spacing: 0.2em; opacity: 0.45; margin-bottom: 0.35rem; }
.music-picker { display: flex; gap: 0.35rem; flex-wrap: wrap; justify-content: center; }

.music-opt {
  flex: 1 1 calc(50% - 0.35rem);
  padding: 0.45rem 0.4rem; border-radius: 8px;
  background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1);
  color: var(--ink); font: inherit; font-size: max(7.5px, 0.66rem); font-weight: 700;
  cursor: pointer; min-height: 44px;
}
.music-opt .sub { display: block; font-size: max(7.5px, 0.52rem); opacity: 0.5; font-weight: 400; margin-top: 0.1rem; }
.music-opt.active { border-color: var(--accent); background: rgba(72,229,255,0.15); color: var(--accent); }
.music-opt.loading { opacity: 0.5; cursor: progress; }


/* ---- CRT filter (opt-in) --------------------------------------------------
   Scanlines plus a vignette, painted over the canvas with pointer-events
   off so it can never intercept a tap. Purely decorative and free when the
   class is absent.
   ------------------------------------------------------------------------- */
#stage.crt-on::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.22) 0px,
      rgba(0, 0, 0, 0.22) 1px,
      rgba(0, 0, 0, 0) 1px,
      rgba(0, 0, 0, 0) 3px
    ),
    radial-gradient(ellipse at center, rgba(0,0,0,0) 55%, rgba(0,0,0,0.45) 100%);
  mix-blend-mode: multiply;
}

/* A faint colour-bleed pass, sold as phosphor rather than a bug. */
#stage.crt-on::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 6;
  background: linear-gradient(90deg,
    rgba(255,0,60,0.035), rgba(0,255,200,0.02) 50%, rgba(60,120,255,0.035));
}


/* ---- Story cards ----------------------------------------------------------
   Deliberately quiet typography: the cards are short and the game is loud,
   so the contrast is what makes them land.
   ------------------------------------------------------------------------- */
.story-card { width: min(320px, 90%); text-align: left; }
.story-chapter {
  font-size: max(7.5px, 0.58rem); letter-spacing: 0.3em; opacity: 0.45; margin-bottom: 0.4rem;
}
.story-title {
  font-size: max(7.5px, clamp(1.1rem, 4.5vh, 1.6rem)) !important;
  letter-spacing: 0.14em; margin: 0 0 0.9rem !important;
}
.story-lines { display: flex; flex-direction: column; gap: 0.65rem; }
.story-lines p {
  margin: 0; font-size: max(7.5px, clamp(0.76rem, 2.3vh, 0.92rem)); line-height: 1.55;
  opacity: 0; transform: translateY(6px);
  animation: storyLine 0.5s ease forwards;
}
.story-lines p:nth-child(1) { animation-delay: 0.10s; }
.story-lines p:nth-child(2) { animation-delay: 0.75s; }
.story-lines p:nth-child(3) { animation-delay: 1.40s; }

@keyframes storyLine { to { opacity: 0.88; transform: translateY(0); } }

@media (prefers-reduced-motion: reduce) {
  .story-lines p { animation: none; opacity: 0.88; transform: none; }
}


/* ---- Co-op toggle --------------------------------------------------------- */
.coop-toggle {
  margin-top: 0.45rem; padding: 0.5rem 1rem; border-radius: 999px;
  background: transparent; border: 1px solid rgba(255,157,226,0.4);
  color: var(--ink); font: inherit; font-size: max(7.5px, 0.62rem); font-weight: 700;
  letter-spacing: 0.12em; cursor: pointer; min-height: 44px;
  display: inline-flex; align-items: center; gap: 0.45rem;
}
.coop-toggle .coop-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255,255,255,0.2); transition: background 0.2s ease;
}
.coop-toggle .coop-sub { opacity: 0.4; font-weight: 400; letter-spacing: 0.04em; }
.coop-toggle.on { border-color: #ff9de2; color: #ff9de2; background: rgba(255,157,226,0.12); }
.coop-toggle.on .coop-dot { background: #ff9de2; box-shadow: 0 0 8px #ff9de2; }


/* ---- Menu backdrop --------------------------------------------------------
   The title screen gets real art behind it: a prairie dog courier and a
   capybara cargo inspector, which is the whole premise stated in one image
   before a word of story is read. The panel colour drops to a scrim so the
   art shows through while white text stays readable on top.
   ------------------------------------------------------------------------- */
#menu {
  background-image:
    linear-gradient(rgba(4,5,14,0.62), rgba(4,5,14,0.88)),
    url('../game-assets/story/menu_bg.jpg');
  background-size: cover;
  background-position: center bottom;
}

/* ---- Story panel art ------------------------------------------------------ */
.story-art {
  width: min(320px, 90%);
  border-radius: 8px;
  margin-bottom: 0.8rem;
  border: 1px solid rgba(72,229,255,0.22);
  display: block;
}
.story-art.hidden { display: none; }


/* ---- Online room ---------------------------------------------------------- */
.room-code {
  margin: 0.6rem 0; padding: 0.7rem 1.4rem; border-radius: 10px;
  background: rgba(72,229,255,0.1); border: 1px solid rgba(72,229,255,0.45);
}
.room-code.hidden { display: none; }
.room-code-label { font-size: max(7.5px, 0.55rem); letter-spacing: 0.24em; opacity: 0.5; }
.room-code-value {
  font-size: max(7.5px, clamp(1.8rem, 7vh, 2.6rem)); font-weight: 700;
  letter-spacing: 0.32em; color: var(--accent);
  text-shadow: 0 0 18px rgba(72,229,255,0.5); margin: 0.2rem 0;
}
.room-code-hint { font-size: max(7.5px, 0.55rem); opacity: 0.45; }

.join-row { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.5rem; }
.room-input {
  width: 6.5rem; text-transform: uppercase; letter-spacing: 0.3em;
  font-weight: 700; font-size: max(7.5px, 0.95rem);
}

/* ---- Bestiary --------------------------------------------------------------
   The overlay owns scrolling. Cards use an auto-fitting grid so a normal
   phone gets one generous column while wider embeds get two. */
.bestiary-list {
  width: min(420px, 92%);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.5rem;
  margin: 0.15rem 0 0.45rem;
}

.bestiary-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  min-height: 108px;
  padding: 0.65rem;
  border: 1px solid rgba(72, 229, 255, 0.16);
  border-radius: 6px;
  background: rgba(8, 12, 26, 0.55);
  text-align: left;
}

/* Unmet entries stay visible but inert — a silhouette is an invitation, an
   empty slot is just a gap. */
.bestiary-row.locked { opacity: 0.45; }

.bestiary-art {
  flex: 0 0 54px;
  width: 54px;
  height: 54px;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 5px;
  font-size: 1.1rem;
  color: rgba(255, 255, 255, 0.5);
}

.bestiary-art img {
  width: 48px;
  height: 48px;
  image-rendering: pixelated;   /* it is pixel art; never smooth it */
}

.bestiary-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.bestiary-body b { font-size: max(7.5px, 0.76rem); letter-spacing: 0.06em; }
.bestiary-body span {
  font-size: max(7.5px, 0.62rem);
  line-height: 1.35;
  opacity: 0.78;
}

/* ---- Live mission and achievement feedback ----------------------------- */
.mission-tracker {
  position: absolute;
  z-index: 13;
  top: calc(var(--stage-h, 100vh) * 0.15);
  left: 10px;
  width: min(220px, calc(100% - 76px));
  padding: 0.55rem 0.65rem;
  border: 1px solid rgba(72,229,255,0.32);
  border-radius: 9px;
  background: rgba(5,9,22,0.82);
  box-shadow: 0 8px 22px rgba(0,0,0,0.24);
  pointer-events: none;
}
.mission-tracker-head { display: flex; justify-content: space-between; gap: 0.4rem; }
.mission-tracker-kicker, .mission-tracker-value {
  color: var(--accent); font-size: max(7.5px, 0.5rem); letter-spacing: 0.1em;
}
.mission-tracker strong {
  display: block; margin: 0.2rem 0 0.3rem; font-size: max(7.5px, 0.62rem);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mission-tracker-bar { display: block; height: 5px; overflow: hidden; border-radius: 999px; background: rgba(255,255,255,0.12); }
.mission-tracker-bar span { display: block; width: 0; height: 100%; border-radius: inherit; background: var(--accent); transition: width 220ms ease; }
.achievement-toast {
  position: absolute;
  z-index: 22;
  right: 10px;
  bottom: 18px;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: min(260px, calc(100% - 20px));
  padding: 0.65rem;
  border: 1px solid rgba(255,209,102,0.55);
  border-radius: 10px;
  background: rgba(7,12,27,0.94);
  box-shadow: 0 0 24px rgba(255,209,102,0.18);
  animation: achievement-in 240ms ease-out;
  pointer-events: none;
}
.achievement-toast-icon { flex: 0 0 34px; width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; background: var(--gold); color: #08101d; }
.achievement-toast b { display: block; color: var(--gold); font-size: max(7.5px, 0.66rem); letter-spacing: 0.08em; }
.achievement-toast small { display: block; margin-top: 0.1rem; color: rgba(232,244,255,0.72); font-size: max(7.5px, 0.56rem); }
@keyframes achievement-in { from { opacity: 0; transform: translateY(10px) scale(0.97); } }

/* ---- Credits --------------------------------------------------------------
   Required by the art and audio licences, so it is a real screen rather than
   a footnote. */
.credits-list {
  width: min(310px, 92%);
  max-height: calc(var(--stage-h, 100vh) * 0.52);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0.5rem 0;
  text-align: left;
}

.credit-row { display: flex; flex-direction: column; gap: 0.12rem; }
.credit-row b {
  font-size: max(7.5px, 0.66rem);
  letter-spacing: 0.16em;
  color: var(--accent);
  opacity: 0.85;
}
.credit-row span { font-size: max(7.5px, 0.72rem); line-height: 1.4; opacity: 0.82; }

/* Cycling option button (Destruction level). Sized to match .opt-switch so
   the options list stays on one visual grid. */
.opt-cycle {
  flex: 0 0 auto;
  min-width: 104px;
  padding: 0.32rem 0.6rem;
  font: inherit;
  font-size: max(7.5px, 0.62rem);
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--accent);
  background: rgba(72, 229, 255, 0.10);
  border: 1px solid rgba(72, 229, 255, 0.38);
  border-radius: 999px;
  cursor: pointer;
}
.opt-cycle:active { transform: scale(0.96); }
.opt-cycle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Selected hull's name and trade-off line. The classes are sidegrades, so the
   cost of each one has to be legible before the player commits to a run. */
.ship-info {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin: -0.15rem 0 0.1rem;
  min-height: 1.9em;          /* reserve the space so the menu never jumps */
}
.ship-info b {
  font-size: max(7.5px, 0.72rem);
  letter-spacing: 0.12em;
  color: var(--accent);
}
.ship-info span {
  font-size: max(7.5px, 0.58rem);
  letter-spacing: 0.10em;
  opacity: 0.62;
}

/* Skill picker. Text chips rather than icons: the four skills are named
   abilities, and a name is far more legible at this size than a glyph. */
.skill-picker {
  display: flex;
  gap: 0.3rem;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0.1rem 0;
}
.skill-opt {
  font: inherit;
  font-size: max(7.5px, 0.55rem);
  font-weight: 700;
  letter-spacing: 0.10em;
  padding: 0.28rem 0.55rem;
  color: var(--sk, var(--accent));
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid color-mix(in srgb, var(--sk, #48e5ff) 45%, transparent);
  border-radius: 999px;
  cursor: pointer;
}
.skill-opt.selected {
  background: color-mix(in srgb, var(--sk, #48e5ff) 22%, transparent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--sk, #48e5ff) 45%, transparent);
}
/* Locked skills stay visible but inert — an empty slot teaches nothing. */
.skill-opt.locked { opacity: 0.32; cursor: default; }


/* -------------------------------------------------------------------------
   LEGIBILITY FLOOR — a CrazyGames submission requirement.

   Their checklist demands readable text at devicePixelRatio:1 across ten
   iframe sizes, ALL of which are landscape. This game is a 480x854 portrait
   column, so the stage is height-constrained in every one of them: their
   800x450 mobile size yields a stage only 253px wide, where the root font
   drops to 8.4px and a 0.6rem label rendered at 5.1 ACTUAL device pixels.

   Raising the whole root scale was not an option — that is what makes the
   menu fit at all, and lifting it reinstates the overflow that hid the LAUNCH
   button on the first submission. So the floor is applied per-label with
   max(): the layout keeps scaling, but no individual piece of text may fall
   below ~7.5px. These are all short single-line labels, so the few pixels
   they gain back cost almost nothing in column height.
   ------------------------------------------------------------------------- */

/* ---- Refit screen ---------------------------------------------------------
   Cards, not a list: the offers are alternatives and have to LOOK mutually
   exclusive. Sized in rem so the whole screen scales with the stage exactly
   like the menu does. */
.refit-offers {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  width: min(320px, 92%);
  margin: 0.5rem 0;
}
.refit-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.7rem;
  text-align: left;
  border-radius: 6px;
  border: 1px solid rgba(72,229,255,0.35);
  background: rgba(10,16,34,0.9);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.refit-card:active { transform: scale(0.98); }
.refit-card .ico {
  font-size: 1.25rem;
  line-height: 1;
  color: var(--accent);
  width: 1.6rem;
  text-align: center;
  flex: 0 0 auto;
}
.refit-card b {
  display: block;
  font-size: max(7.5px, 0.72rem);
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 0.15rem;
}
.refit-card span {
  display: block;
  font-size: max(7.5px, 0.62rem);
  line-height: 1.45;
  opacity: 0.72;
}
/* The risk card is the only one that can make things worse, and says so. */
.refit-card.risk { border-color: rgba(255,138,61,0.55); }
.refit-card.risk .ico, .refit-card.risk b { color: #ff8a3d; }

.refit-slots {
  display: flex;
  gap: 0.35rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 0.3rem;
  min-height: 1.4rem;
}
.refit-slot {
  font-size: max(7.5px, 0.56rem);
  letter-spacing: 0.08em;
  padding: 0.22rem 0.5rem;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.18);
  opacity: 0.75;
}
.refit-slot.empty { opacity: 0.3; }

/* ---- Round report -------------------------------------------------------
   One checkpoint card, no scrolling on a normal phone. The four headline
   numbers form a 2x2 grid so the player can read the result in one glance. */
.round-report {
  width: min(360px, 92%);
  container-type: inline-size;
  padding: 1rem;
  border: 1px solid rgba(72,229,255,0.34);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(12,21,43,0.98), rgba(5,9,22,0.98));
  box-shadow: 0 18px 55px rgba(0,0,0,0.55), 0 0 32px rgba(72,229,255,0.08);
  text-align: center;
}
.round-report-kicker, .round-next-card small, .round-xp-row small {
  display: block; color: var(--accent); font-size: max(7.5px, 0.52rem);
  letter-spacing: 0.2em; font-weight: 700;
}
.round-report h1 {
  max-width: 100%;
  margin: 0.25rem 0 0;
  color: var(--gold);
  font-size: clamp(1rem, 9cqi, 1.8rem);
  line-height: 1.08;
  letter-spacing: clamp(0.035em, 0.8cqi, 0.1em);
  white-space: nowrap;
}
.round-report-note { margin: 0.15rem 0 0.7rem; opacity: 0.58; font-size: max(7.5px, 0.56rem); }
.round-stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.42rem; }
.round-stat-grid > div {
  min-width: 0; padding: 0.55rem; border-radius: 8px;
  background: rgba(255,255,255,0.045); border: 1px solid rgba(255,255,255,0.08);
}
.round-stat-grid span { display: block; opacity: 0.52; font-size: max(7.5px, 0.5rem); letter-spacing: 0.12em; }
.round-stat-grid b { display: block; margin-top: 0.12rem; color: var(--ink); font-size: max(10px, 0.92rem); }
.round-xp-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.7rem;
  margin-top: 0.48rem; padding: 0.56rem 0.65rem; border-radius: 8px;
  text-align: left; background: rgba(255,209,102,0.09); border: 1px solid rgba(255,209,102,0.25);
}
.round-xp-row b { display: block; color: var(--gold); margin-top: 0.08rem; font-size: max(9px, 0.78rem); }
.round-xp-next { max-width: 52%; text-align: right; opacity: 0.7; font-size: max(7.5px, 0.52rem); line-height: 1.35; }
.round-highlights { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.28rem; margin: 0.48rem 0; min-height: 1.1rem; }
.round-highlight {
  padding: 0.2rem 0.42rem; border-radius: 999px; color: #bfeeff;
  background: rgba(72,229,255,0.09); border: 1px solid rgba(72,229,255,0.22);
  font-size: max(7.5px, 0.5rem); letter-spacing: 0.04em;
}
.round-next-card { padding: 0.5rem; margin-bottom: 0.55rem; }
.round-next-card b { display: block; margin-top: 0.12rem; font-size: max(9px, 0.78rem); }
.round-next-card span { display: block; margin-top: 0.12rem; font-size: max(7.5px, 0.56rem); }
.round-report .btn { margin: 0 auto; }
.round-report .btn:disabled { opacity: 0.42; cursor: wait; }

/* ---- Enemy first-contact card ------------------------------------------ */
.enemy-intro-card {
  width: min(340px, 90%); padding: 1rem; text-align: center; border-radius: 15px;
  background: radial-gradient(circle at 50% 22%, rgba(72,229,255,0.13), transparent 43%), rgba(5,9,22,0.98);
  border: 1px solid rgba(72,229,255,0.35); box-shadow: 0 20px 60px rgba(0,0,0,0.62);
}
.enemy-intro-kicker { color: var(--accent); font-size: max(7.5px, 0.58rem); letter-spacing: 0.24em; font-weight: 700; }
.enemy-intro-art {
  width: 112px; height: 112px; margin: 0.55rem auto; display: grid; place-items: center;
  border-radius: 50%; background: rgba(0,0,0,0.32); border: 1px solid currentColor;
  box-shadow: 0 0 28px rgba(72,229,255,0.12);
}
.enemy-intro-art img { max-width: 88px; max-height: 88px; image-rendering: pixelated; }
.enemy-intro-card h1 { margin: 0.25rem 0; font-size: clamp(1.25rem, 6vh, 2rem); }
.enemy-intro-card p { margin: 0.3rem auto 0.55rem; max-width: 28rem; opacity: 0.76; line-height: 1.45; font-size: max(7.5px, 0.66rem); }
.enemy-intro-threat {
  margin: 0 auto 0.7rem; padding: 0.42rem 0.6rem; border-radius: 7px;
  background: rgba(255,255,255,0.05); font-size: max(7.5px, 0.56rem); letter-spacing: 0.06em;
}
.enemy-intro-card .btn { margin: 0 auto; }

@media (max-height: 540px) {
  .round-report, .enemy-intro-card { padding: 0.65rem; }
  .enemy-intro-art { width: 78px; height: 78px; margin: 0.25rem auto; }
  .enemy-intro-art img { max-width: 62px; max-height: 62px; }
  .round-report-note { margin-bottom: 0.35rem; }
}

/* ---- Codex / field manual -------------------------------------------------
   Sections of short rules, not prose. A wall of text in a menu does not get
   read; a stack of one-rule rows does. Locked doctrines stay visible so the
   player can see there is something left to meet. */
.codex-list {
  width: min(320px, 92%);
  max-height: calc(var(--stage-h, 100vh) * 0.58);
  overflow-y: auto;
  text-align: left;
  margin: 0.4rem 0;
}
.codex-section {
  font-size: max(7.5px, 0.6rem);
  letter-spacing: 0.22em;
  color: var(--gold);
  opacity: 0.75;
  margin: 0.7rem 0 0.3rem;
}
.codex-row {
  padding: 0.45rem 0.55rem;
  margin-bottom: 0.3rem;
  border-radius: 5px;
  border: 1px solid rgba(255,255,255,0.10);
  background: rgba(10,16,34,0.75);
}
.codex-row b {
  display: block;
  font-size: max(7.5px, 0.68rem);
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 0.18rem;
}
.codex-row span {
  display: block;
  font-size: max(7.5px, 0.6rem);
  line-height: 1.5;
  opacity: 0.75;
  white-space: pre-line;      /* the counter-play line is a real newline */
}
.codex-row.locked { opacity: 0.42; }
.codex-row.locked b { color: var(--ink); }
