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

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: #04060f;
  font-family: 'Segoe UI', system-ui, sans-serif;
  color: #cfe3ff;
  user-select: none;
  -webkit-user-select: none;
  /* stop pull-to-refresh, double-tap zoom and long-press callouts on mobile */
  overscroll-behavior: none;
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

#game { display: block; width: 100vw; height: 100vh; cursor: crosshair; touch-action: none; }
/* iOS: 100vh is the SMALL viewport (as if the browser chrome were showing),
   so under viewport-fit=cover the canvas stops short of the physical screen
   and the page background shows as a black band beneath the HUD. dvh tracks
   the viewport that is actually there. iOS only -- every other platform
   keeps the vh it has always used. */
body.iosApp #game { height: 100dvh; }
#overlay {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
  pointer-events: none; z-index: 5;
}

/* ===== Menus ===== */
/*
 * height, three deep, worst-supported last:
 *   100vh   - the LARGEST viewport. Wrong under any browser chrome, but it is
 *             what every browser understands, so it is the floor.
 *   100dvh  - the current viewport. Correct in a normal mobile browser.
 *   --app-h - measured from visualViewport by game.js. The only one that is
 *             right inside an in-app browser (X, Instagram, Discord), where
 *             the host paints a toolbar over the web view without shrinking
 *             it. Without this the bottom of every menu -- LAUNCH, the nav
 *             bar -- sits under that toolbar, unseeable and untappable.
 * inset:0 still supplies top/left/right; an explicit height simply wins over
 * bottom:0 when all three are set, so the box stops at the visible edge.
 */
.overlay {
  position: fixed; inset: 0;
  height: 100vh;
  height: 100dvh;
  height: var(--app-h, 100dvh);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  background: radial-gradient(ellipse at center, rgba(10,18,40,.92), rgba(2,4,10,.97));
  z-index: 20;
}
.overlay h1 {
  font-size: 56px; letter-spacing: 12px; font-weight: 300;
  color: #7fd4ff; text-shadow: 0 0 30px rgba(80,180,255,.6);
  margin-bottom: 8px;
}
.overlay .sub { color: #8fa8cc; margin-bottom: 40px; }
.overlay .sub b { color: #cfe3ff; }
.overlay .hint { margin-top: 30px; font-size: 12px; color: #5f78a0; letter-spacing: 1px; }

.overlay .warn {
  margin-top: 22px; padding: 9px 20px;
  font-size: 12px; letter-spacing: 1px; color: #ffb27f;
  border: 1px solid rgba(255, 140, 80, .35); border-radius: 8px;
  background: rgba(60, 26, 12, .45);
}

.ships { display: flex; gap: 18px; flex-wrap: wrap; justify-content: center; max-width: 1180px; }
.shipCard {
  width: 218px; padding: 18px;
  border: 1px solid #2a4a7a; border-radius: 8px;
  background: rgba(15,30,60,.5);
  cursor: pointer; text-align: center;
  transition: all .15s;
}
.shipCard:hover {
  border-color: #7fd4ff; background: rgba(25,50,95,.6);
  box-shadow: 0 0 24px rgba(80,180,255,.25);
  transform: translateY(-4px);
}
.shipCard h2 { color: #aee0ff; font-weight: 400; margin-bottom: 12px; }
.shipCard p { font-size: 13px; color: #8fa8cc; margin-top: 10px; line-height: 1.4; }
.shipCard .ability { color: #ffd27f; }
.shipArt { height: 70px; margin: 0 auto; background-position: center; background-repeat: no-repeat; }
.shipArt.bc { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="140" height="70" viewBox="0 0 140 70"><polygon points="10,35 45,20 120,28 132,35 120,42 45,50" fill="%234a7ab0" stroke="%237fd4ff" stroke-width="2"/><rect x="50" y="14" width="30" height="8" fill="%233a5a88" stroke="%237fd4ff"/><rect x="50" y="48" width="30" height="8" fill="%233a5a88" stroke="%237fd4ff"/></svg>'); }
.shipArt.cr { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="140" height="70" viewBox="0 0 140 70"><ellipse cx="70" cy="35" rx="55" ry="16" fill="%23b09a4a" stroke="%23ffd27f" stroke-width="2"/><rect x="30" y="26" width="80" height="18" rx="9" fill="%23887539" stroke="%23ffd27f"/></svg>'); }
.shipArt.ds { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="140" height="70" viewBox="0 0 140 70"><polygon points="6,35 38,28 128,31 136,35 128,39 38,42" fill="%234a7ab0" stroke="%237fd4ff" stroke-width="2"/><rect x="28" y="18" width="44" height="6" fill="%233a5a88" stroke="%237fd4ff"/><rect x="28" y="46" width="44" height="6" fill="%233a5a88" stroke="%237fd4ff"/></svg>'); }
.shipArt.sp { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="140" height="70" viewBox="0 0 140 70"><ellipse cx="64" cy="38" rx="40" ry="20" fill="%233a8868" stroke="%237fffc0" stroke-width="2"/><circle cx="64" cy="18" r="9" fill="none" stroke="%237fffc0" stroke-width="2"/><line x1="64" y1="9" x2="64" y2="28" stroke="%237fffc0" stroke-width="2"/><rect x="98" y="31" width="20" height="14" rx="7" fill="%232f6a52" stroke="%237fffc0" stroke-width="2"/></svg>'); }
.shipArt.dn { background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="140" height="70" viewBox="0 0 140 70"><polygon points="8,35 34,18 116,24 134,35 116,46 34,52" fill="%234a7ab0" stroke="%237fd4ff" stroke-width="2"/><rect x="40" y="10" width="42" height="10" fill="%233a5a88" stroke="%237fd4ff"/><rect x="40" y="50" width="42" height="10" fill="%233a5a88" stroke="%237fd4ff"/><rect x="56" y="24" width="26" height="8" fill="%23264b73" stroke="%237fd4ff"/><circle cx="100" cy="35" r="6" fill="%237fd4ff"/></svg>'); }

.hidden { display: none !important; }

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

/* ===== Multiplayer ===== */
#mpPanel {
  margin-top: 26px; padding: 16px 22px;
  border: 1px solid rgba(110, 165, 230, .25); border-radius: 12px;
  background: rgba(12, 22, 40, .6);
  text-align: center;
}
.mpTitle { font-size: 10px; letter-spacing: 3px; color: #7fd4ff; margin-bottom: 10px; }
.mpRow { display: flex; gap: 8px; justify-content: center; }
.mpRow input {
  width: 130px; padding: 7px 10px;
  font-family: inherit; font-size: 12px; color: #cfe3ff;
  background: rgba(0, 0, 0, .4);
  border: 1px solid #2a4a7a; border-radius: 6px;
}
.mpRow input:focus { outline: none; border-color: #7fd4ff; }
.mpRow button { padding: 7px 18px; font-size: 12px; }
#mpStatus { margin-top: 10px; font-size: 11px; color: #7f9bbd; }
#mpStatus code {
  background: rgba(0, 0, 0, .4); padding: 1px 6px; border-radius: 4px;
  color: #7fe8ff; font-size: 11px;
}
@keyframes netPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
#netPlayers { display: flex; flex-direction: column; gap: 2px; margin-top: 5px; }

/* ===== Generic buttons ===== */
button {
  font-family: inherit; font-size: 13px; color: #cfe3ff;
  background: rgba(20,40,75,.85);
  border: 1px solid #2a4a7a; border-radius: 6px;
  padding: 10px 14px; cursor: pointer;
  transition: all .1s;
}
button:hover:not(:disabled) { border-color: #7fd4ff; background: rgba(35,65,115,.9); }
button:disabled { opacity: .45; cursor: default; }
#endScreen button { font-size: 18px; padding: 14px 40px; margin-top: 20px; }

/* ---- Post-match result screen ------------------------------------------ */
.endSub {
  margin-top: 2px; font-size: 11px; letter-spacing: 2.4px; color: #6f8cae;
  text-transform: uppercase;
}

/* The ladder swing, given the weight it deserves: it is the one number a
   rated player came to this screen to see. */
.endElo {
  display: inline-flex; align-items: baseline; gap: 10px;
  margin: 16px auto 2px; padding: 10px 18px; border-radius: 12px;
  border: 1px solid rgba(110, 165, 230, .3);
  background: linear-gradient(160deg, rgba(14, 30, 52, .95), rgba(8, 18, 32, .95));
}
.endElo.hidden { display: none; }
.eloLabel { font-size: 9px; letter-spacing: 2px; color: #6f8cae; }
.eloFrom { font-size: 15px; color: #7f9bbd; }
.eloArrow { font-size: 11px; }
.eloTo { font-size: 24px; font-weight: 700; color: #eaf4ff; }
.eloDelta { font-size: 14px; font-weight: 700; }
.endElo.eloUp .eloArrow, .endElo.eloUp .eloDelta { color: #6aff8a; }
.endElo.eloDown .eloArrow, .endElo.eloDown .eloDelta { color: #ff8a7a; }
.endElo.eloUp { border-color: rgba(106, 255, 138, .35); }
.endElo.eloDown { border-color: rgba(255, 138, 122, .35); }

/* Both fleets side by side on a desktop, stacked on a phone. */
.endBoards {
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: center;
  width: min(940px, 94vw); margin: 18px auto 4px;
}
.endTeam {
  flex: 1 1 380px; min-width: 0; padding: 12px 14px 10px; border-radius: 12px;
  border: 1px solid rgba(110, 165, 230, .22);
  background: linear-gradient(160deg, rgba(10, 22, 38, .92), rgba(6, 13, 24, .95));
}
.endTeam.endMine { border-color: rgba(127, 212, 255, .38); }
.endTeamHead {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: 8px; padding-bottom: 7px;
  border-bottom: 1px solid rgba(110, 165, 230, .18);
  font-size: 10px; font-weight: 700; letter-spacing: 2.2px; color: #9fd0ff;
}
.endTeamHead i { font-style: normal; font-size: 9px; letter-spacing: 1.6px; }
.endTeamHead .endWon { color: #6aff8a; }
.endTeamHead .endLost { color: #ff8a7a; }

.endTable { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.endTable th {
  padding: 0 6px 6px; font-size: 8.5px; font-weight: 600; letter-spacing: 1.3px;
  color: #6f8cae; text-align: right; white-space: nowrap;
}
.endTable th.l, .endTable td.l { text-align: left; }
.endTable td {
  padding: 5px 6px; text-align: right; color: #cfe3f7;
  border-top: 1px solid rgba(110, 165, 230, .1);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.endTable tr.endMe td { background: rgba(90, 150, 220, .12); color: #eaf6ff; font-weight: 600; }
/* The table's cells are nowrap, so its min-content width can exceed the board.
   Without this it painted OUTSIDE the box and the first column ran off the
   side of the screen. Scrolls inside its own panel instead. */
.endScroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.endAst { color: #9fe0ff; }
.endShip { color: #7f9bbd; font-size: 10.5px; }
.endDmg { color: #ffd27f; }
.endHuman, .endYou {
  margin-left: 6px; padding: 1px 5px; border-radius: 4px; font-style: normal;
  font-size: 8px; letter-spacing: 1px; vertical-align: middle;
}
.endHuman { background: rgba(255, 210, 127, .16); color: #ffd27f; }
.endYou { background: rgba(127, 212, 255, .18); color: #9fe0ff; }

@media (max-width: 900px), (max-height: 620px) {
  .endBoards { gap: 10px; margin: 12px auto 2px; }
  .endTeam { flex: 1 1 100%; padding: 9px 10px 8px; }
  .endTable { font-size: 10.5px; }
  .endTable td { padding: 4px; }
  .eloTo { font-size: 19px; }
  .endElo { margin: 10px auto 0; padding: 8px 14px; gap: 8px; }
}
/* A handset keeps the columns that answer "how did I do": kills, assists,
   deaths, damage, farmed. The hull name is already on the ship card, and
   damage taken is the one number nobody reads first. */
@media (max-width: 620px) {
  .endTable .endOpt { display: none; }
  .endTable { font-size: 10px; }
  .endTable th { padding: 0 4px 5px; letter-spacing: .8px; }
  .endTable td { padding: 4px 4px; }
}

/* ===== Admin panel ===== */
#adminPanel {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 340px; z-index: 30;
  display: flex; flex-direction: column;
  background: rgba(6,12,26,.96);
  border-left: 1px solid #2a4a7a;

}
#admHead {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 14px; border-bottom: 1px solid #2a4a7a;
  font-size: 12px; letter-spacing: 2px; color: #7fd4ff;
}
#admHead button { padding: 4px 10px; font-size: 12px; }
#admActions {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 10px 14px; border-bottom: 1px solid #2a4a7a;
}
#admActions button { padding: 6px 10px; font-size: 11px; }
/* leaving a match throws away a game in progress — set apart from the tuning actions */
#quitMatch { color: #ff9a8c; border-color: rgba(255, 110, 90, .5); }
#quitMatch:hover { border-color: #ff7a6a; color: #fff; }
#admPresets { padding: 8px 14px; border-bottom: 1px solid #2a4a7a; }
.presetRow { display: flex; gap: 6px; margin-bottom: 6px; }
.presetRow input[type="text"], .presetRow select {
  flex: 1; min-width: 0; padding: 4px 7px;
  font-family: inherit; font-size: 11px; color: #cfe3ff;
  background: rgba(0,0,0,.4); border: 1px solid #2a4a7a; border-radius: 3px;
}
.presetRow input[type="text"]:focus, .presetRow select:focus { outline: none; border-color: #7fd4ff; }
.presetRow button { padding: 4px 10px; font-size: 11px; }
#admStatus {
  height: 12px; font-size: 10px; color: #6aff8a; letter-spacing: 1px;
  opacity: 0; transition: opacity .25s;
}

#admBody { flex: 1; overflow-y: auto; padding: 8px 14px 40px; }
#admBody::-webkit-scrollbar { width: 8px; }
#admBody::-webkit-scrollbar-thumb { background: #2a4a7a; border-radius: 4px; }

#admBody details {
  margin-bottom: 6px;
  border: 1px solid rgba(42,74,122,.5); border-radius: 5px;
  background: rgba(15,28,52,.4);
}
#admBody details details { margin: 4px 6px; background: rgba(20,38,68,.5); }
#admBody summary {
  padding: 7px 10px; cursor: pointer;
  font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase;
  color: #aee0ff;
}
#admBody summary:hover { color: #fff; }
.admRow {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px; padding: 3px 10px 3px 16px;
}
.admRow span { font-size: 11px; color: #8fa8cc; flex: 1; }
.admRow input[type="number"] {
  width: 84px; padding: 3px 6px;
  font-family: inherit; font-size: 11px; color: #cfe3ff;
  background: rgba(0,0,0,.4);
  border: 1px solid #2a4a7a; border-radius: 3px;
}
.admRow input[type="number"]:focus { outline: none; border-color: #7fd4ff; }
.admRow input[type="checkbox"] { width: 16px; height: 16px; accent-color: #5ad0ff; }
#btnCancel { display: none; }
body.targeting #btnCancel { display: block; border-color: rgba(150,255,200,.7); color: #9effc0; }

/* Landscape prompt */
/* ===== Asset loading screen ===== */
#loadScreen {
  position: fixed; inset: 0; z-index: 90;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 38%, rgba(28, 74, 124, .55), transparent 60%),
    radial-gradient(ellipse at 80% 80%, rgba(86, 40, 130, .35), transparent 55%),
    radial-gradient(ellipse at 50% 40%, #0b1a2d, #03050c 72%);
  transition: opacity .45s ease;
}
#loadScreen.done { opacity: 0; pointer-events: none; }

/* Two starfields at different speeds — the cheapest possible parallax, drawn
   with repeating gradients so it costs no image and no script. */
.loadStars {
  position: absolute; inset: -50% -50% -50% -50%;
  background-image:
    radial-gradient(1.4px 1.4px at 20% 30%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.2px 1.2px at 70% 20%, rgba(190,225,255,.75), transparent),
    radial-gradient(1.6px 1.6px at 40% 70%, rgba(255,255,255,.7), transparent),
    radial-gradient(1px 1px at 85% 55%, rgba(200,230,255,.7), transparent),
    radial-gradient(1.3px 1.3px at 10% 85%, rgba(255,255,255,.6), transparent),
    radial-gradient(1px 1px at 55% 90%, rgba(180,215,255,.6), transparent);
  background-size: 340px 340px;
  animation: loadDrift 60s linear infinite;
  opacity: .55;
}
.loadStars2 {
  background-size: 620px 620px;
  animation-duration: 110s;
  animation-direction: reverse;
  opacity: .3;
}
@keyframes loadDrift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-340px, -170px, 0); }
}
/* A slow breathing glow behind the wordmark. */
.loadGlow {
  position: absolute; left: 50%; top: 42%; width: min(620px, 90vw); aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(90, 180, 255, .16), transparent 62%);
  animation: loadPulse 4.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes loadPulse {
  0%, 100% { opacity: .55; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;   transform: translate(-50%, -50%) scale(1.08); }
}
.loadInner { position: relative; width: min(380px, 82vw); text-align: center; }
.loadTitle {
  font-size: 22px; letter-spacing: 9px; color: #cfe9ff; margin-bottom: 20px;
  text-shadow: 0 0 22px rgba(127, 212, 255, .45);
}
/* The wordmark. Sized in relative units so it holds up from a phone in
   landscape to a desktop, and glows with the same blue as the chrome around
   it rather than sitting on the page as a flat sticker. */
.brandLogo {
  display: block; width: 100%; max-width: 300px; height: auto; margin: 0 auto;
  filter: drop-shadow(0 0 18px rgba(80, 170, 255, .45));
}
.loadTitle .brandLogo { max-width: min(320px, 74vw); }
.authBrand .brandLogo { max-width: min(300px, 68vw); margin-bottom: 2px; }
.loadBarOuter {
  position: relative;
  height: 5px; background: rgba(127, 212, 255, .12);
  border: 1px solid rgba(127, 212, 255, .18);
  border-radius: 3px; overflow: hidden;
}
.loadBarInner {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, #2f7fc4, #7fd4ff 70%, #cdefff);
  box-shadow: 0 0 14px rgba(127, 212, 255, .8);
  transition: width .35s cubic-bezier(.4, 0, .2, 1);
}
/* A sheen travelling along the track, so the bar still reads as ALIVE during
   the long single-file downloads where the percentage cannot move. */
.loadBarOuter::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.5), transparent);
  transform: translateX(-100%);
  animation: loadSheen 1.8s ease-in-out infinite;
}
@keyframes loadSheen {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
/* Status line and percentage, on one row under the bar. */
.loadFoot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-top: 12px;
}
.loadPct {
  font-size: 12px; font-weight: 600; letter-spacing: 1px;
  color: #9fe0ff; font-variant-numeric: tabular-nums;
}
/* Something to read while a 20MB hull downloads. */
.loadTip {
  margin-top: 22px; min-height: 32px;
  font-size: 11px; line-height: 1.6; color: #6f8cae;
  transition: opacity .4s ease;
}
.loadTip b { color: #9fd0ff; font-weight: 600; }
/* In the lobby the tip sits under the roster rather than centred on a
   backdrop, so it needs its own margins and a rule above it. */
#lobbyTip {
  margin: 12px 0 0; padding-top: 12px;
  border-top: 1px solid rgba(110, 165, 230, .14);
  text-align: center;
}
.loadText {
  margin-top: 12px; font-size: 10px; letter-spacing: 2.5px; color: #7f9bbd;
}
#rotatePrompt {
  /* Must sit above the loading screen and the hangar on portrait phones. */
  position: fixed; inset: 0; z-index: 140;
  display: none; align-items: center; justify-content: center;
  background: #04060f; text-align: center;
}
#rotatePrompt .rotIcon { font-size: 54px; color: #7fd4ff; animation: rot 2.4s ease-in-out infinite; }
#rotatePrompt h2 { margin-top: 14px; font-size: 17px; letter-spacing: 4px; font-weight: 400; color: #aee0ff; }
#rotatePrompt p { margin-top: 8px; font-size: 12px; color: #7f9bbd; }
@keyframes rot { 0%,100% { transform: rotate(0); } 50% { transform: rotate(90deg); } }
@media (orientation: portrait) and (max-width: 950px){
  body.touch #rotatePrompt { display: flex; }
}
@media (max-width: 900px), (max-height: 620px){
  .overlay {
    justify-content: flex-start;
    overflow-y: auto; overflow-x: hidden;
    padding: 10px 10px 16px;
    -webkit-overflow-scrolling: touch;
  }
  .overlay h1 { font-size: 22px; letter-spacing: 5px; margin-bottom: 2px; }
  .overlay .sub { font-size: 10px; margin-bottom: 10px; text-align: center; }
  .overlay .hint { font-size: 9px; margin-top: 8px; text-align: center; line-height: 1.5; }
  .overlay .warn { font-size: 9px; margin-top: 8px; padding: 5px 10px; text-align: center; }

  /* cards become a compact grid instead of a row that runs off-screen */
  /* all five hulls on one row so the panels below stay on screen */
  .ships {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 6px; width: 100%; max-width: none;
  }
  .shipCard { width: auto; padding: 7px; border-radius: 8px; }
  .shipCard h2 { font-size: 11px; margin-bottom: 2px; }
  .shipCard p { font-size: 8px; margin-top: 2px; line-height: 1.25; }
  .shipCard .ability { font-size: 7.5px; }
  .shipArt { height: 22px; background-size: contain; }

  #mpPanel { margin-top: 8px; padding: 7px 10px; width: 100%; max-width: none; }
  .mpTitle { font-size: 9px; margin-bottom: 6px; }
  .mpRow { flex-wrap: wrap; }
  .mpRow input { width: auto; flex: 1 1 110px; min-width: 0; padding: 7px 8px; font-size: 11px; }
  .mpRow button { padding: 7px 14px; font-size: 11px; }
  #mpStatus { font-size: 9px; margin-top: 6px; }

  #endScreen { justify-content: center; }
  #endScreen h1 { font-size: 28px; }
  #endScreen button { font-size: 14px; padding: 10px 26px; }
}
body.touch .shipCard { padding: 14px; }
@media (max-width: 700px){
  #adminPanel { width: 100%; }
  .admRow input[type="number"] { width: 96px; padding: 7px; font-size: 12px; }
  #admActions button { padding: 9px 12px; }
}

/* ===== Account panel (admin) ===== */
#admAccount { padding: 10px 14px; border-bottom: 1px solid #2a4a7a; }
.acctTitle { font-size: 9px; letter-spacing: 1.5px; color: #7fd4ff; margin-bottom: 8px; }
.acctWho { font-size: 11px; color: #8fa8cc; }
.acctWho b { color: #cfe3ff; }
#admAccount .presetRow input { flex: 1 1 0; }
#admAccount button { padding: 5px 10px; font-size: 11px; white-space: nowrap; }
#acctStatus { min-height: 12px; font-size: 10px; letter-spacing: .5px; color: #6aff8a; }

/* ============================================================
   Auth screen
   ============================================================ */
#authScreen {
  background:
    radial-gradient(ellipse at 20% 0%, rgba(40, 90, 170, .28), transparent 60%),
    radial-gradient(ellipse at 80% 100%, rgba(120, 60, 170, .22), transparent 60%),
    linear-gradient(160deg, #060b18, #02040a);
  z-index: 40;
}
.authCard {
  position: relative;
  width: min(430px, 92vw);
  padding: 26px 26px 20px;
  border: 1px solid rgba(120, 175, 240, .26);
  border-radius: 18px;
  background: linear-gradient(160deg, rgba(18, 30, 52, .92), rgba(8, 14, 26, .95));
  box-shadow: 0 24px 70px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(160, 205, 255, .16);

  overflow: hidden;
}
.authGlow {
  position: absolute; top: -60%; left: -20%; right: -20%; height: 120%;
  background: radial-gradient(ellipse at 50% 0%, rgba(90, 208, 255, .16), transparent 65%);
  pointer-events: none;
}
.authBrand {
  position: relative;
  font-size: 26px; font-weight: 300; letter-spacing: 9px; text-align: center;
  color: #9fe0ff; text-shadow: 0 0 26px rgba(80, 180, 255, .55);
  line-height: 0;
}
.authSub {
  position: relative; margin: 8px 0 18px;
  font-size: 11px; line-height: 1.5; text-align: center; color: #7f9bbd;
}
.authTabs {
  position: relative; display: flex; gap: 4px; margin-bottom: 16px;
  padding: 3px; border-radius: 10px; background: rgba(0, 0, 0, .3);
  border: 1px solid rgba(110, 165, 230, .16);
}
.authTab {
  flex: 1; padding: 8px 0; border: none; border-radius: 8px;
  background: transparent; color: #7f9bbd;
  font-size: 10px; font-weight: 700; letter-spacing: 1.6px;
}
.authTab.on {
  background: linear-gradient(160deg, rgba(60, 110, 175, .85), rgba(30, 62, 105, .9));
  color: #eaf4ff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(160, 205, 255, .25);
}
.authField { position: relative; display: block; margin-bottom: 11px; }
.authField > span {
  display: block; margin-bottom: 5px;
  font-size: 9px; font-weight: 600; letter-spacing: 1.6px; color: #6f8cae;
}
.authField input {
  width: 100%; padding: 11px 13px;
  font-family: inherit; font-size: 13px; color: #eaf3ff;
  background: rgba(0, 0, 0, .38);
  border: 1px solid rgba(110, 165, 230, .26); border-radius: 10px;
  transition: border-color .15s, box-shadow .15s;
}
.authField input::placeholder { color: #4e6684; }
.authField input:focus {
  outline: none; border-color: rgba(127, 212, 255, .85);
  box-shadow: 0 0 0 3px rgba(90, 180, 255, .14);
}
.authAdv { margin: 2px 0 14px; }
.authAdv summary {
  font-size: 10px; letter-spacing: 1.2px; color: #6f8cae;
  cursor: pointer; padding: 4px 0;
}
.authAdv summary:hover { color: #9fd0ff; }
.authAdv[open] summary { margin-bottom: 8px; }
.authGo {
  width: 100%; padding: 13px 0; margin-top: 2px;
  border: 1px solid rgba(127, 212, 255, .5); border-radius: 11px;
  background: linear-gradient(160deg, #2f7fc4, #1b4c7d);
  color: #f2faff; font-size: 12px; font-weight: 700; letter-spacing: 2.4px;
  box-shadow: 0 8px 24px rgba(30, 110, 190, .35), inset 0 1px 0 rgba(190, 230, 255, .3);
}
.authGo:hover:not(:disabled) {
  background: linear-gradient(160deg, #3a95e0, #22598f);
  border-color: #9fe0ff;
}
.authGo:disabled { opacity: .55; }
#authMsg {
  min-height: 15px; margin-top: 9px;
  font-size: 10.5px; letter-spacing: .4px; text-align: center; color: #6aff8a;
}
#authMsg.bad { color: #ff9a8a; }
.authGuest {
  display: block; width: 100%; margin-top: 10px; padding: 8px 0;
  background: none; border: none; color: #6f8cae;
  font-size: 11px; letter-spacing: .6px;
}
.authGuest:hover { color: #9fd0ff; background: none; border: none; }

/* Live callsign availability. Sits directly under the field it judges. */
.authHint {
  min-height: 13px; margin: -4px 0 8px;
  font-size: 10px; letter-spacing: .3px; color: #6f8cae;
}
.authHint.good { color: #6aff8a; }
.authHint.bad  { color: #ffb27a; }

/* Three tabs no longer fit the old label size on a narrow card. */
.authTabs .authTab { letter-spacing: 1.1px; }

/* ---- Guest prompts -------------------------------------------------------
   Amber rather than the interface blue: this is the one piece of chrome that
   is asking for something, and it should not read as another button. */
.profClaim, .endClaim {
  border: 1px solid rgba(255, 190, 110, .35);
  background: linear-gradient(160deg, rgba(60, 44, 20, .55), rgba(28, 22, 14, .6));
  border-radius: 12px; padding: 14px 16px; margin: 0 0 14px;
  text-align: left;
}
.profClaimHead, .endClaimHead {
  font-size: 10px; font-weight: 700; letter-spacing: 2px; color: #ffcf95;
  margin-bottom: 6px;
}
.profClaim p, .endClaimBody {
  font-size: 11px; line-height: 1.55; color: #cbb79c; margin: 0 0 10px;
}
.profClaim b, .endClaimBody b { color: #ffe3bd; }
.profClaim input, .endClaim input {
  width: 100%; padding: 10px 12px; margin-bottom: 9px;
  font-family: inherit; font-size: 12.5px; color: #fff3e4;
  background: rgba(0, 0, 0, .4);
  border: 1px solid rgba(255, 190, 110, .3); border-radius: 9px;
}
.profClaim input:focus, .endClaim input:focus {
  outline: none; border-color: rgba(255, 205, 140, .85);
  box-shadow: 0 0 0 3px rgba(255, 180, 90, .13);
}
.profClaimGo, .endClaimGo {
  padding: 11px 18px; border-radius: 10px;
  border: 1px solid rgba(255, 205, 140, .5);
  background: linear-gradient(160deg, #c98a34, #8a5a1d);
  color: #fff6e8; font-size: 11px; font-weight: 700; letter-spacing: 1.8px;
}
.profClaimGo:hover:not(:disabled), .endClaimGo:hover:not(:disabled) {
  background: linear-gradient(160deg, #e0a049, #a56b23); border-color: #ffd9a0;
}
.profClaimGo:disabled, .endClaimGo:disabled { opacity: .55; }
.profClaimGo { width: 100%; }
.profClaimMsg, .endClaimMsg {
  min-height: 14px; margin-top: 7px; font-size: 10.5px; color: #6aff8a;
}
.profClaimMsg.bad, .endClaimMsg.bad { color: #ff9a8a; }

/* The end-of-match panel is wider and centred inside the victory screen. */
.endClaim { width: min(430px, 92vw); margin: 6px auto 18px; }
.endClaimRow { display: flex; gap: 8px; align-items: center; }
.endClaimLater {
  padding: 11px 12px; background: none; border: none;
  color: #a8987f; font-size: 11px; letter-spacing: .5px;
}
.endClaimLater:hover { color: #ffcf95; background: none; border: none; }
/* Four numbers, evenly split — what the account is worth, at a glance. */
.endClaimStats { display: flex; gap: 6px; margin-bottom: 11px; }
.endClaimStats span {
  flex: 1; text-align: center; padding: 8px 2px; border-radius: 8px;
  background: rgba(0, 0, 0, .3); border: 1px solid rgba(255, 190, 110, .18);
  font-size: 8.5px; letter-spacing: 1.1px; color: #a8987f;
}
.endClaimStats b {
  display: block; font-size: 16px; font-weight: 600; letter-spacing: 0;
  color: #ffe3bd; margin-bottom: 2px;
}

/* An unclaimed account is amber in the chip too, so the state is legible
   from the menu without opening anything. */
#acctChip.guestChip { border-color: rgba(255, 190, 110, .55); color: #ffcf95; }

/* A short message in the middle of the screen, in place of alert(). */
#notice {
  position: fixed; left: 50%; top: 28%; transform: translate(-50%, -50%);
  z-index: 60; max-width: min(460px, 88vw); padding: 16px 20px;
  text-align: center; font-size: 12.5px; line-height: 1.6; color: #eaf4ff;
  background: linear-gradient(160deg, rgba(14, 30, 52, .97), rgba(8, 18, 32, .97));
  border: 1px solid rgba(127, 212, 255, .45); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .6);
  animation: noticeIn .18s ease-out;
}
#notice.hidden { display: none; }
@keyframes noticeIn {
  from { opacity: 0; transform: translate(-50%, calc(-50% - 8px)); }
  to   { opacity: 1; transform: translate(-50%, -50%); }
}

/* account chip on the main menu */
#acctChip {
  position: absolute; top: 14px; right: 14px;
  padding: 7px 14px; border-radius: 20px;
  font-size: 10px; font-weight: 600; letter-spacing: 1.4px;
  background: rgba(14, 26, 46, .8);
  border: 1px solid rgba(110, 165, 230, .3);
  color: #9fd0ff; z-index: 3;
}
#acctChip.signedIn { border-color: rgba(106, 255, 138, .5); color: #9effc0; }
@media (max-width: 900px), (max-height: 620px){
  .authCard { width: min(400px, 94vw); padding: 16px 18px 14px; border-radius: 14px; }
  .authBrand .brandLogo { max-width: min(230px, 62vw); }
  .authSub { font-size: 9px; margin: 6px 0 12px; }
  .authTabs { margin-bottom: 11px; }
  .authTab { padding: 7px 0; font-size: 9px; }
  .authField { margin-bottom: 8px; }
  .authField > span { font-size: 8px; margin-bottom: 3px; }
  .authField input { padding: 9px 11px; font-size: 12px; border-radius: 8px; }
  .authGo { padding: 11px 0; font-size: 11px; }
  .authGuest { font-size: 10px; margin-top: 6px; }
  .authTab { letter-spacing: .8px; }
  .authHint { font-size: 9px; }
  .profClaim, .endClaim { padding: 11px 12px; border-radius: 10px; }
  .profClaim p, .endClaimBody { font-size: 10px; }
  .endClaimStats b { font-size: 14px; }
  #authMsg { font-size: 9.5px; }
  #acctChip { top: 8px; right: 8px; padding: 5px 11px; font-size: 9px; }
}

/* ============================================================
   HANGAR — ship selection  (v2: angular military-HUD language)
   ============================================================ */
@font-face {
  font-family: 'Rajdhani';
  src: url('vendor/fonts/rajdhani-500.woff2') format('woff2');
  font-weight: 500; font-display: swap;
}
@font-face {
  font-family: 'Rajdhani';
  src: url('vendor/fonts/rajdhani-600.woff2') format('woff2');
  font-weight: 600; font-display: swap;
}
@font-face {
  font-family: 'Rajdhani';
  src: url('vendor/fonts/rajdhani-700.woff2') format('woff2');
  font-weight: 700; font-display: swap;
}

:root {
  --hg-cyan: #35c8ff;
  --hg-cyan-dim: rgba(53, 200, 255, .55);
  --hg-line: rgba(53, 170, 240, .38);
  --hg-ink: #0a1626;
  --hg-panel: rgba(7, 16, 30, .86);
  --hg-text: #e8f4ff;
  --hg-mute: #6d90b5;
}

body, button, input, select {
  font-family: 'Rajdhani', 'Bahnschrift', 'Segoe UI', system-ui, sans-serif;
}

#shipSelect {
  justify-content: stretch; align-items: stretch;
  padding: 0; overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 118%, rgba(24, 90, 160, .38), transparent 55%),
    radial-gradient(ellipse at 12% -8%, rgba(28, 80, 150, .30), transparent 50%),
    radial-gradient(ellipse at 88% 6%, rgba(20, 60, 120, .26), transparent 45%),
    linear-gradient(178deg, #060d1a 0%, #030710 45%, #051022 100%);
}
/* ONE GL CONTEXT: while the ship-select screen is up (body.hangarLive) the
   hangar is drawn on the match canvas, scissored to #hangarCanvas's box. So
   the canvas is lifted to sit just under the screen, transparent outside the
   pad, and the screen's own backdrop moves to #hangarBackdrop beneath it --
   otherwise the screen would paint over the hull. */
/* No z-index on either: .overlay screens have none, so TREE ORDER stacks
   them, and both of these precede every screen in the document. Giving the
   canvas a z-index put it over the ship-select screen itself. */
#hangarBackdrop { display: none; position: fixed; inset: 0; overflow: hidden; }
body.hangarLive #hangarBackdrop {
  display: block;
  background:
    radial-gradient(ellipse at 50% 118%, rgba(24, 90, 160, .38), transparent 55%),
    radial-gradient(ellipse at 12% -8%, rgba(28, 80, 150, .30), transparent 50%),
    radial-gradient(ellipse at 88% 6%, rgba(20, 60, 120, .26), transparent 45%),
    linear-gradient(178deg, #060d1a 0%, #030710 45%, #051022 100%);
}
body.hangarLive #game { position: fixed; inset: 0; pointer-events: none; }
body.hangarLive #shipSelect { background: transparent; }
body.hangarLive #shipSelect::before { display: none; }
/* hangar floor: perspective grid + hot centre glow */
#hangarBackdrop::before,
#shipSelect::before {
  content: ''; position: absolute; left: -25%; right: -25%; bottom: -14%; height: 60%;
  background:
    radial-gradient(ellipse at 44% 100%, rgba(45, 150, 235, .20), transparent 60%),
    linear-gradient(transparent 0, rgba(58, 150, 235, .10) 1px, transparent 2px) 0 0 / 100% 30px,
    linear-gradient(90deg, transparent 0, rgba(58, 150, 235, .10) 1px, transparent 2px) 0 0 / 46px 100%;
  transform: perspective(560px) rotateX(60deg);
  transform-origin: 50% 100%;
  pointer-events: none;
}
/* whisper of scanlines over everything */
#shipSelect::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(180deg, rgba(140, 200, 255, .022) 0 1px, transparent 1px 3px);
}

/* --- top chrome: angular command strip --- */
.hgTop {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  height: 46px; padding: 0 18px 0 22px;
  background: linear-gradient(180deg, rgba(10, 22, 40, .92), rgba(6, 13, 26, .88));
  border-bottom: 1px solid var(--hg-line);
  box-shadow: 0 1px 0 rgba(53, 200, 255, .12), 0 8px 26px rgba(0, 0, 0, .45);
}
.hgTop::after {
  content: ''; position: absolute; left: 0; right: 62%; bottom: -1px; height: 2px;
  background: linear-gradient(90deg, var(--hg-cyan), transparent);
  filter: drop-shadow(0 0 6px var(--hg-cyan));
}
.hgTitle {
  font-size: 19px; font-weight: 700; letter-spacing: 5px; color: var(--hg-text);
  text-transform: uppercase;
}
.hgTitle em { font-style: normal; color: var(--hg-cyan); margin-right: 10px; }
#acctChip {
  position: static; border-radius: 3px;
  clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  background: rgba(16, 34, 58, .9);
  border: 1px solid var(--hg-line);
  font-family: inherit; font-weight: 700; letter-spacing: 2px;
}

/* --- centre stage --- */
.hgMain { position: relative; flex: 1; min-height: 0; z-index: 1; }
#hangarCanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.hgStage { position: absolute; top: 4.5%; left: 300px; right: 348px; text-align: center; pointer-events: none; }
/* model still downloading — sits where the ship will appear */
#hgLoading {
  position: absolute; top: 50%; left: 300px; right: 348px;
  transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-size: 11px; letter-spacing: 3px; color: #6f8bad; pointer-events: none;
}
.hgSpin {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid rgba(127, 212, 255, .25);
  border-top-color: #7fd4ff;
  animation: hgSpin 0.8s linear infinite;
}
@keyframes hgSpin { to { transform: rotate(360deg); } }
@media (max-width: 900px), (max-height: 620px) { #hgLoading { right: 0; } }
.hgClass {
  display: inline-block; padding: 3px 16px;
  font-size: 12px; font-weight: 700; letter-spacing: 5px; color: var(--hg-cyan);
  text-transform: uppercase;
}
.hgName {
  margin-top: 1px;
  font-size: clamp(34px, 5.8vw, 64px); font-weight: 700; letter-spacing: 12px;
  color: #fff; text-transform: uppercase;
  text-shadow: 0 0 38px rgba(70, 180, 255, .65), 0 0 8px rgba(140, 220, 255, .4), 0 3px 0 rgba(0, 0, 0, .5);
}
.hgTag { margin-top: 3px; font-size: 13px; font-weight: 600; letter-spacing: 4.5px; color: #58b7ef; text-transform: uppercase; }

.hgArrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 54px; height: 92px; z-index: 2; padding: 0;
  font-size: 42px; line-height: 1; color: var(--hg-cyan);
  background: linear-gradient(100deg, rgba(14, 32, 56, .72), rgba(7, 16, 30, .78));
  border: 1px solid var(--hg-line); border-radius: 0;
  clip-path: polygon(0 14px, 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
  text-shadow: 0 0 12px var(--hg-cyan-dim);
  transition: all .15s;
}
.hgArrow:hover {
  color: #fff; border-color: var(--hg-cyan);
  box-shadow: 0 0 22px rgba(53, 200, 255, .35), inset 0 0 16px rgba(53, 200, 255, .12);
  background: linear-gradient(100deg, rgba(22, 48, 82, .85), rgba(10, 24, 44, .9));
}
.hgArrow.left { left: 300px; }
.hgArrow.right { right: 366px; }

.hgDots { position: absolute; bottom: 18px; left: 300px; right: 348px; display: flex; gap: 10px; justify-content: center; z-index: 2; }
.hgDots i { width: 9px; height: 9px; border-radius: 50%; background: rgba(90, 150, 210, .28); transition: all .2s; }
.hgDots i.on { background: var(--hg-cyan); box-shadow: 0 0 12px var(--hg-cyan); transform: scale(1.3); }

/* --- spec panel: chamfered plate with corner brackets --- */
.hgPanel {
  position: absolute; top: 14px; right: 16px; bottom: 14px;
  width: 324px; z-index: 2;
  display: flex; flex-direction: column;
  padding: 20px 20px 16px;
  background: var(--hg-panel);
  border: 1px solid var(--hg-line);
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 22px 100%, 0 calc(100% - 22px));
  box-shadow: inset 0 1px 0 rgba(140, 210, 255, .14), inset 0 0 60px rgba(10, 40, 80, .35);

}
/* glowing top edge */
.hgPanel::before {
  content: ''; position: absolute; top: 0; left: 0; width: 55%; height: 2px;
  background: linear-gradient(90deg, var(--hg-cyan), transparent);
  filter: drop-shadow(0 0 6px var(--hg-cyan));
}

.hgPanelName { font-size: 26px; font-weight: 700; letter-spacing: 3px; color: #fff; text-transform: uppercase; }
.hgPanelClass {
  margin-top: 0; padding-bottom: 11px;
  font-size: 12px; font-weight: 700; letter-spacing: 3.6px; color: var(--hg-cyan);
  text-transform: uppercase;
  border-bottom: 1px solid rgba(53, 170, 240, .25);
}
.hgDesc { margin: 11px 0 13px; font-size: 13px; font-weight: 500; line-height: 1.5; color: #9db8d8; }

.hgStats { display: flex; flex-direction: column; gap: 8px; }
.hgStat { display: flex; align-items: center; gap: 9px; }
.hgStat > span { width: 56px; font-size: 11px; font-weight: 700; letter-spacing: 1.6px; color: var(--hg-mute); }
.hgStat .segs { flex: 1; display: flex; gap: 3px; }
.hgStat .segs i { flex: 1; height: 11px; background: rgba(70, 130, 195, .16); transform: skewX(-14deg); }
.hgStat .segs i.on {
  background: linear-gradient(180deg, #6fd8ff, #1f8fd8);
  box-shadow: 0 0 8px rgba(60, 190, 255, .6);
}
.hgStat > b { width: 30px; text-align: right; font-size: 15px; font-weight: 700; color: #fff; }

.hgAbility {
  position: relative;
  margin-top: 14px; padding: 11px 13px;
  background: linear-gradient(160deg, rgba(52, 34, 78, .45), rgba(24, 16, 40, .55));
  border: 1px solid rgba(168, 110, 255, .3);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%);
}
.hgAbilityHead { font-size: 10px; font-weight: 700; letter-spacing: 3px; color: #a678e8; }
.hgAbilityName { margin-top: 2px; font-size: 16px; font-weight: 700; letter-spacing: 1px; color: #d9b8ff; text-transform: uppercase; }
.hgAbilityDesc { margin-top: 2px; font-size: 11.5px; font-weight: 500; line-height: 1.45; color: #9585b5; }

/* Solo / multiplayer, in the same visual language as the team-size picker
   directly under it so they read as one block of pre-launch choices. */
.hgPlay {
  /* A COLUMN, not three columns. Two modes fitted side by side; the third
     turned every label into two wrapped lines stacked over a wrapped
     sub-label -- an unreadable block. As rows each mode gets the width to
     say its name once, with the note beside it instead of beneath. */
  display: flex; flex-direction: column; gap: 4px; margin: 16px 0 8px; padding: 4px;
  border: 1px solid rgba(90, 150, 220, .28); border-radius: 8px;
  background: linear-gradient(180deg, rgba(12, 26, 45, .75), rgba(8, 16, 28, .75));
}
.hgPlay button {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  text-align: left; padding: 9px 12px;
  border: 1px solid transparent; border-radius: 5px;
  background: transparent; color: #8fb4d8;
  font: 700 12px/1 'Chakra Petch', system-ui, sans-serif; letter-spacing: .14em;
  cursor: pointer; transition: background .14s, color .14s, border-color .14s;
}
.hgPlay button em {
  display: inline; margin: 0; font-style: normal; white-space: nowrap;
  font: 400 10px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: .06em; opacity: .62;
}
.hgPlay button:hover { color: #cfe6ff; background: rgba(70, 130, 200, .16); }
.hgPlay button.on {
  color: #eaf6ff; border-color: rgba(127, 212, 255, .55);
  background: linear-gradient(180deg, rgba(48, 96, 152, .85), rgba(26, 54, 90, .9));
  box-shadow: inset 0 1px 0 rgba(160, 205, 255, .25);
}
/* Locked multiplayer still shows what it is; the padlock says why not yet. */
.hgPlay button.locked em::after { content: ' 🔒'; }
.hgPlay button.locked { color: #7f93ab; }
.hgSelect.locked {
  background: linear-gradient(178deg, #6d7a86 0%, #55606b 55%, #444d56 100%);
  border-color: rgba(200, 215, 230, .5); color: #1b2027;
  box-shadow: none; text-shadow: none;
}
.hgSelect.locked:hover { background: linear-gradient(178deg, #7a8794 0%, #616c78 55%, #4d5761 100%); }

.hgSelect {
  margin-top: 0; padding: 16px 0;
  font-family: inherit; font-size: 19px; font-weight: 700; letter-spacing: 7px;
  color: #241703; text-transform: uppercase;
  background: linear-gradient(178deg, #ffcf5e 0%, #f0a92e 55%, #d18a15 100%);
  border: 1px solid #ffe9a8; border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 16px 100%, 0 calc(100% - 16px));
  box-shadow: 0 0 28px rgba(240, 170, 45, .4), inset 0 1px 0 rgba(255, 246, 214, .9), inset 0 -10px 22px rgba(140, 85, 5, .35);
  text-shadow: 0 1px 0 rgba(255, 240, 190, .6);
  transition: all .12s;
}
.hgSelect:hover {
  background: linear-gradient(178deg, #ffdd7d 0%, #ffb83c 55%, #e09a1e 100%);
  box-shadow: 0 0 40px rgba(250, 185, 60, .55), inset 0 1px 0 rgba(255, 248, 220, .95);
}
.hgSelect span { font-weight: 500; }

/* Secondary to LAUNCH on purpose: this is a dev/testing entry, not the way
   into a real match, and it should never be the button the eye lands on. */
.hgTest {
  margin-top: 8px; padding: 9px 0;
  font-family: inherit; font-size: 11.5px; font-weight: 700; letter-spacing: 2.4px;
  color: #7fd4ff; text-transform: uppercase;
  background: linear-gradient(178deg, rgba(24, 48, 70, .95), rgba(12, 26, 42, .97));
  border: 1px solid rgba(90, 170, 220, .5); border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
  cursor: pointer; transition: all .12s;
}
.hgTest:hover { color: #cfeaff; border-color: rgba(140, 210, 255, .9); background: linear-gradient(178deg, rgba(34, 66, 96, .97), rgba(18, 36, 56, .98)); }
.hgTest em { display: block; font-style: normal; font-size: 8.5px; letter-spacing: 1.4px; color: #5f93b8; margin-top: 2px; }
.hgPerma { margin-top: 9px; font-size: 9.5px; font-weight: 600; letter-spacing: 1.6px; text-align: center; color: #a4713f; }


/* A portrait phone is ~390px wide. The spec panel alone is 246 of that, so
 * there is no second column to be had -- side by side, the two cards simply
 * overlap. Stack instead: the panel keeps the top right, and the readouts
 * become a full-width strip across the empty floor at the bottom, which is
 * dead space in this orientation anyway.
 */
@media (max-width: 700px) and (max-aspect-ratio: 1/1) {
  /* hug the content so the strip below is not sitting on an empty frame */
  .hgPanel { bottom: auto; }
  .hgLeft {
    top: auto; bottom: 34px; left: 10px; right: 10px; transform: none;
    width: auto; max-height: 38%;
    flex-direction: row; align-items: flex-start; gap: 12px;
  }
  /* section labels do not survive the turn into a horizontal strip */
  .hgLeft .hgLeftHead { display: none; }
  .hgLeft .hgStats { flex: 1 1 auto; min-width: 0; }
  .hgLeft .hgAbils { flex: 0 0 auto; max-width: 48%; justify-content: flex-end; }
  /* the centre column has its full width back */
  .hgStage, #hgLoading { left: 14px; }
  .hgArrow.left { left: 8px; }
  /* dots clear the strip rather than sitting under it */
  .hgDots { left: 14px; right: 14px; bottom: 12px; }
}

/* Ability tooltip. Fixed-position and parented to <body> on purpose: inside
 * the left card it would be clipped by that card's own overflow, and the text
 * is wider than the card is. */
.hgTip {
  position: fixed; z-index: 40; max-width: 268px;
  display: flex; flex-direction: column; gap: 5px;
  padding: 10px 12px;
  background: linear-gradient(178deg, rgba(12, 28, 48, .98), rgba(6, 14, 26, .99));
  border: 1px solid rgba(90, 170, 220, .55);
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
  box-shadow: 0 8px 30px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(140, 210, 255, .16);
  pointer-events: none;   /* never steals the hover that opened it */
}
.hgTip b {
  font-size: 11px; font-weight: 700; letter-spacing: 2px;
  color: var(--hg-cyan); text-transform: uppercase;
}
.hgTip span { font-size: 11.5px; line-height: 1.45; color: #b9d2e8; }
.hgTip.hidden { display: none; }
/* the tile that opened it, so the link between the two is obvious */
.hgAbil:focus-visible { outline: none; }
.hgAbil { cursor: help; }

/* --- credits ------------------------------------------------------------- */
#credChip {
  display: flex; align-items: center; gap: 7px;
  margin-right: 10px; padding: 7px 13px;
  font-size: 13px; font-weight: 700; letter-spacing: 1.5px;
  color: #ffe2a0;
  background: linear-gradient(180deg, rgba(50, 38, 12, .9), rgba(24, 18, 6, .95));
  border: 1px solid rgba(234, 181, 67, .55);
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px));
}
#credChip.hidden { display: none; }
  #credChip .credIcon { color: var(--hg-cyan); font-size: 12px; }
/* the number counts up when it changes, so a payout is felt rather than read */
#credChip.credBump { animation: credBump .5s ease-out; }
@keyframes credBump {
  0% { transform: scale(1); }
  35% { transform: scale(1.16); box-shadow: 0 0 22px rgba(255, 205, 90, .8); }
  100% { transform: scale(1); }
}

#checkinModal {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: rgba(2, 6, 14, .82);
}
#checkinModal.hidden { display: none; }
#checkinBox {
  width: min(560px, 92vw); padding: 26px 26px 20px;
  text-align: center;
  background: linear-gradient(178deg, rgba(12, 28, 48, .98), rgba(6, 14, 26, .99));
  border: 1px solid rgba(90, 170, 220, .5);
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 18px));
  box-shadow: 0 18px 60px rgba(0, 0, 0, .7);
}
.ciTitle { font-size: 15px; font-weight: 700; letter-spacing: 4px; color: var(--hg-cyan); }
.ciSub { margin: 7px 0 16px; font-size: 12px; color: #93b2cc; }
.ciLadder { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin-bottom: 18px; }
.ciDay {
  flex: 1 1 0; min-width: 54px; padding: 9px 4px;
  border: 1px solid rgba(90, 150, 210, .3);
  background: rgba(10, 22, 38, .8);
}
.ciDay em { display: block; font-style: normal; font-size: 8px; letter-spacing: 1.6px; color: #6f8bad; }
.ciDay b { display: block; margin-top: 4px; font-size: 13px; color: #cfe6ff; }
.ciDay.done { border-color: rgba(90, 200, 130, .5); background: rgba(16, 44, 28, .8); }
.ciDay.done b { color: #7fe0a0; }
/* today's rung, and the reason the dialog is on screen */
.ciDay.today {
  border-color: rgba(255, 205, 90, .95);
  background: linear-gradient(180deg, rgba(60, 46, 12, .95), rgba(30, 22, 6, .97));
  box-shadow: 0 0 20px rgba(255, 200, 60, .45);
}
.ciDay.today b { color: #ffd77e; }
.ciClaim {
  width: 100%; padding: 13px 0;
  font-family: inherit; font-size: 15px; font-weight: 700; letter-spacing: 5px;
  color: #241703; text-transform: uppercase;
  background: linear-gradient(178deg, #ffcf5e 0%, #f0a92e 55%, #d18a15 100%);
  border: 1px solid #ffe9a8; cursor: pointer;
  clip-path: polygon(0 0, calc(100% - 13px) 0, 100% 13px, 100% 100%, 13px 100%, 0 calc(100% - 13px));
}
.ciClaim:disabled { filter: grayscale(.8); cursor: default; }
.ciLater {
  margin-top: 9px; padding: 6px 0; width: 100%;
  font-family: inherit; font-size: 10.5px; letter-spacing: 2px;
  color: #7f97b0; background: none; border: none; cursor: pointer;
}
.ciLater:hover { color: #cfe6ff; }

/* --- left column: performance + ability kit ---------------------------------
 * The hangar was a spec panel pinned to the right and a large empty area on
 * the left. Everything that is a readout rather than a control now lives over
 * here, which also takes five stat rows and the ability grid out of the right
 * panel -- the panel that had grown tall enough to push LAUNCH off the bottom
 * of a phone. Splitting it shortens both.
 */
.hgLeft {
  /* hugs its content instead of stretching: it holds four bars and a grid
     of icons, and a full-height frame around that is mostly empty box. */
  /* centred on the left edge: the card is short, and hung from the top it
     read as floating in a lot of empty space rather than as one of a pair. */
  position: absolute; top: 50%; left: 16px; transform: translateY(-50%);
  width: 268px; max-height: calc(100% - 28px); z-index: 2;
  display: flex; flex-direction: column; gap: 10px;
  padding: 18px 18px 16px;
  background: var(--hg-panel);
  border: 1px solid var(--hg-line);
  clip-path: polygon(22px 0, 100% 0, 100% calc(100% - 22px), calc(100% - 22px) 100%, 0 100%, 0 22px);
  box-shadow: inset 0 1px 0 rgba(140, 210, 255, .14), inset 0 0 60px rgba(10, 40, 80, .35);
  overflow-y: auto;
}
/* mirror of .hgPanel::before, running from the other corner */
.hgLeft::before {
  content: ''; position: absolute; top: 0; right: 0; width: 55%; height: 2px;
  background: linear-gradient(270deg, var(--hg-cyan), transparent);
  filter: drop-shadow(0 0 6px var(--hg-cyan));
}
.hgLeftHead {
  font-size: 9px; font-weight: 700; letter-spacing: 3px;
  color: var(--hg-cyan); text-transform: uppercase; opacity: .85;
}
.hgLeftHead + .hgStats { margin-bottom: 4px; }

/* Ability kit: every button this hull will have in a match, in the same art
   the ability bar uses, so the two are recognisably the same thing. */
.hgAbils { display: flex; flex-wrap: wrap; gap: 6px; }
.hgAbil {
  width: 38px; height: 38px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(178deg, rgba(20, 42, 66, .95), rgba(10, 22, 38, .97));
  border: 1px solid var(--hg-line);
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px));
  transition: border-color .12s, box-shadow .12s;
}
.hgAbil:hover { border-color: rgba(140, 210, 255, .8); box-shadow: 0 0 12px rgba(60, 190, 255, .35); }
.hgAbil .aico { width: 24px; height: 24px; }

/* SETTINGS, now that the bottom nav is gone. Quieter than TEST BATTLE, which
   is itself quieter than LAUNCH -- three tiers, in the order they matter. */
.hgSettings {
  margin-top: 7px; padding: 8px 0;
  font-family: inherit; font-size: 10px; font-weight: 700; letter-spacing: 2.4px;
  color: #7f97b0; text-transform: uppercase;
  background: transparent;
  border: 1px solid rgba(90, 140, 190, .32); border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 9px 100%, 0 calc(100% - 9px));
  cursor: pointer; transition: all .12s;
}
.hgSettings:hover { color: #cfeaff; border-color: rgba(140, 210, 255, .7); background: rgba(30, 60, 95, .5); }

/* --- multiplayer modal --- */
#mpModal {
  position: absolute; inset: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  background: rgba(2, 5, 12, .74);

}
#mpModal #mpPanel {
  position: relative; margin: 0;
  width: min(440px, 92vw); padding: 20px 22px;
  /* The lobby is taller than a phone in landscape — team columns, a chat log
     and an input — so it ran off both ends of the screen with no way to reach
     the buttons. Cap it to the viewport and let it scroll instead. */
  max-height: 92vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--hg-panel);
  border: 1px solid var(--hg-line); border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 18px));
  box-shadow: 0 24px 70px rgba(0, 0, 0, .65), inset 0 1px 0 rgba(140, 210, 255, .14);
}
#mpModal .mpTitle { font-size: 14px; font-weight: 700; letter-spacing: 5px; }
#mpClose { position: absolute; top: 10px; right: 10px; padding: 5px 11px; font-size: 12px; border-radius: 0; }

/* auth screen inherits the same plate language */
.authCard {
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 24px 100%, 0 calc(100% - 24px));
}
.authBrand { font-family: inherit; font-weight: 700; }
.authGo {
  border-radius: 0;
  clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px));
}
@media (max-width: 900px), (max-height: 620px){
  .hgTop { height: 34px; padding: 0 10px 0 14px; }
  .hgTitle { font-size: 12px; letter-spacing: 3px; }
  .hgStage { right: 238px; top: 3%; }
  .hgName { letter-spacing: 6px; }
  .hgTag { font-size: 9px; letter-spacing: 2.4px; }
  .hgClass { font-size: 9px; letter-spacing: 3px; padding: 2px 10px; }

  .hgArrow { width: 40px; height: 64px; font-size: 30px; }
  .hgArrow.left { left: 194px; }
  .hgArrow.right { right: 246px; }
  .hgDots { right: 238px; bottom: 8px; gap: 7px; }
  .hgDots i { width: 7px; height: 7px; }

  .hgPanel { right: 8px; top: 8px; bottom: 8px; width: 228px; padding: 12px 13px 10px; }
  .hgPanelName { font-size: 17px; letter-spacing: 1.6px; }
  .hgPanelClass { font-size: 9px; letter-spacing: 2.4px; padding-bottom: 7px; }
  .hgDesc { margin: 7px 0 8px; font-size: 9.5px; line-height: 1.4; }
  .hgStats { gap: 5px; }
  .hgStat > span { width: 42px; font-size: 8px; letter-spacing: 1px; }
  .hgStat .segs { gap: 2px; }
  .hgStat .segs i { height: 7px; }
  .hgStat > b { width: 22px; font-size: 11px; }
  .hgAbility { margin-top: 8px; padding: 8px 10px; }
  .hgAbilityHead { font-size: 7.5px; letter-spacing: 2px; }
  .hgAbilityName { font-size: 11.5px; }
  .hgAbilityDesc { font-size: 8.5px; }
  .hgSelect { padding: 12px 0; font-size: 14px; letter-spacing: 4.5px; }
  .hgPerma { font-size: 7px; margin-top: 6px; }

}

/* ============================================================
   HUD v2 — the in-game console adopts the hangar's angular language
   ============================================================ */

/* fix: global touch-action:none killed scrolling in panels on mobile */
#adminPanel, #admBody, .overlay, .authCard {
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
@media (max-width: 900px), (max-height: 620px){
  /* superseded by the bottom detail panel below */

}
#upgradeGrid { display: grid; grid-template-columns: repeat(4, 62px); gap: 4px; }
@media (max-width: 900px), (max-height: 620px){
  #upgradeGrid { grid-template-columns: repeat(4, 54px); gap: 3px; }

  /* ---- Hangar: make the spec panel a scrollable sheet with LAUNCH pinned ---- */
  .hgPanel {
    width: 246px; padding: 10px 12px 0;
    display: flex; flex-direction: column;
    max-height: calc(100% - 12px); overflow: hidden;
  }
  .hgPanelName { font-size: 15px; }
  .hgPanelClass { font-size: 8px; }
  .hgDesc { font-size: 9px; line-height: 1.4; }
  .hgStats { font-size: 9px; }
  .hgAbility { padding: 6px 8px; }
  .hgAbilityHead { font-size: 7px; }
  .hgAbilityName { font-size: 10px; }
  .hgAbilityDesc { font-size: 8.5px; line-height: 1.35; }
  /* everything above LAUNCH scrolls; LAUNCH itself never leaves the screen */
  .hgPanel > :not(.hgSelect):not(.hgPerma) { flex: 0 0 auto; }
  .hgPanel { overflow-y: auto; }
  .hgSelect {
    position: sticky; bottom: 0; z-index: 2;
    margin-top: 8px; padding: 12px 0; font-size: 12px;
  }
  .hgPerma { position: sticky; bottom: 0; font-size: 7.5px; padding-bottom: 8px; }
  /* both columns are narrower here, so the centred stage re-inset follows */
  .hgLeft { top: 50%; left: 8px; max-height: calc(100% - 16px); width: 178px; padding: 10px 12px 12px; gap: 7px; }
  .hgLeftHead { font-size: 7.5px; letter-spacing: 2px; }
  .hgAbils { gap: 4px; }
  .hgAbil { width: 28px; height: 28px; }
  .hgAbil .aico { width: 18px; height: 18px; }
  .hgSettings { font-size: 9px; padding: 7px 0; margin-top: 6px; }
  .hgStage { left: 194px; }
  #hgLoading { left: 194px; }
  .hgDots { left: 194px; }
  .hgName { font-size: 26px; }
  .hgClass, .hgTag { font-size: 8px; }
  .hgTop { padding: 6px 10px; }
  .hgTitle { font-size: 10px; }
  .hgArrow { width: 34px; height: 34px; font-size: 20px; }

  /* ---- Admin panel: full-screen sheet, real touch targets, scrolls ---- */
  #adminPanel { width: 100%; left: 0; }
  #admHead { padding: 14px; font-size: 13px; }
  #admHead button { padding: 10px 16px; font-size: 15px; }
  #admActions { padding: 10px; gap: 7px; }
  #admActions button { padding: 11px 13px; font-size: 12px; flex: 1 1 auto; min-width: 92px; }
  #admAccount, #admPresets { padding: 12px; }
  #admAccount .presetRow, .presetRow { gap: 7px; margin-bottom: 8px; }
  #admAccount button, .presetRow button { padding: 11px 13px; font-size: 12px; }
  .presetRow input[type="text"], .presetRow select, #admAccount input {
    padding: 11px 12px; font-size: 13px;
  }
  #admBody { padding: 10px 12px 60px; }
  #admBody summary { padding: 13px 12px; font-size: 12px; }
  .admRow { padding: 8px 12px; }
  .admRow span { font-size: 12px; }
  .admRow input[type="number"] { width: 110px; padding: 10px; font-size: 13px; }
  .admRow input[type="checkbox"] { width: 24px; height: 24px; }
}
@media (max-height: 480px){
  /* column flex: justify-content is the vertical axis here */
  #authScreen { justify-content: flex-start; padding: 6px 0; overflow-y: auto; }
  .authCard { padding: 12px 16px 10px; }
  .authBrand .brandLogo { max-width: min(180px, 52vw); }
  .authSub { font-size: 8px; margin: 4px 0 8px; }
  .authTabs { margin-bottom: 8px; padding: 2px; }
  .authTab { padding: 6px 0; font-size: 8.5px; }
  .authField { margin-bottom: 6px; }
  .authField > span { font-size: 7.5px; margin-bottom: 2px; }
  .authField input { padding: 7px 10px; font-size: 11px; }
  .authAdv { margin: 0 0 8px; }
  .authAdv summary { font-size: 9px; padding: 2px 0; }
  .authGo { padding: 9px 0; font-size: 10px; }
  #authMsg { min-height: 10px; margin-top: 5px; font-size: 9px; }
  .authGuest { margin-top: 4px; padding: 6px 0; font-size: 10px; }
}
@media (max-width: 900px), (max-height: 620px){
  #upgradeGrid { grid-template-columns: repeat(4, 62px); }
}
@media (max-width: 900px), (max-height: 620px){
  #adminPanel {
    display: block;
    overflow-y: auto; overflow-x: hidden;
    touch-action: pan-y; -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
  }
  #admHead { position: sticky; top: 0; z-index: 5; background: rgba(6, 12, 26, .98); }
  #admBody { flex: none; overflow: visible; max-height: none; padding-bottom: 80px; }
}




/* ============================================================
   Lobby
   ============================================================ */
#lobbyName {
  font-size: 12px; font-weight: 800; letter-spacing: 3px;
  color: #9fd0ff; text-shadow: 0 0 10px rgba(90,180,255,.4);
  margin: 4px 0 10px; text-align: center;
}
#lobbyTeams { display: flex; gap: 10px; }
.lobbyCol {
  flex: 1; min-width: 0;
  border: 1px solid #2c455f; border-radius: 6px;
  background: linear-gradient(180deg, rgba(8,14,24,.9), rgba(5,9,16,.95));
  padding: 8px;
}
.lobbyColHead {
  font-size: 9px; font-weight: 800; letter-spacing: 2.4px;
  padding-bottom: 6px; margin-bottom: 6px;
  border-bottom: 1px solid rgba(88,138,196,.25); text-align: center;
}
.lobbyColHead.blue { color: #7fc4ff; }
.lobbyColHead.red  { color: #ff9a86; }
.lobbyList { min-height: 96px; display: flex; flex-direction: column; gap: 3px; }
.lobP {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 8px; border-radius: 4px;
  background: rgba(30,50,78,.35);
  font-size: 11px; color: #d5e8fa; letter-spacing: .4px;
}
.lobP.me { background: rgba(45,90,150,.4); box-shadow: inset 0 0 0 1px rgba(127,196,255,.35); }
.lobP em {
  font-style: normal; font-size: 7.5px; font-weight: 800; letter-spacing: 1px;
  padding: 2px 5px; border-radius: 3px;
}
.lobHost { background: rgba(255,200,80,.18); color: #ffd76e; }
.lobAi   { background: rgba(150,170,195,.15); color: #9fb4cc; }
.lobYou  { background: rgba(90,208,255,.2); color: #9fe0ff; }
.lobShip { margin-left: auto; font-size: 9px; color: #7fa8d0; letter-spacing: 1px; }
.lobEmpty { padding: 8px; font-size: 10px; color: #4e6684; text-align: center; }
.lobbySwitch {
  width: 100%; margin-top: 7px; padding: 6px 0;
  font-size: 9px; font-weight: 700; letter-spacing: 1.6px;
}
.lobbyHostRow { margin-top: 10px; }
#lobbyStart {
  flex: 1;
  background: linear-gradient(180deg, #2f7fc4, #1b4c7d);
  border-color: rgba(127,212,255,.5); color: #f2faff;
  font-weight: 800; letter-spacing: 2px;
}
/* ===== Multiplayer chat & quick comms ===== */
#chatWrap {
  position: absolute; left: 12px; bottom: 210px; width: min(330px, 42vw);
  z-index: 30; pointer-events: none;
}
#chatLog {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 165px; overflow: hidden; margin-bottom: 6px;
}
.chatLine {
  font-size: 13.75px; line-height: 1.45; color: #cfe3ff;
  text-shadow: 0 1px 3px #000; opacity: 1;
  transition: opacity .6s ease;
}
.chatLine.fading { opacity: 0; }
.chatLine b { color: #7fd4ff; font-weight: 700; }
.chatLine.teamOnly b { color: #6aff8a; }
.chatLine.foe b { color: #ff9a8c; }
.chatLine em { font-style: normal; color: #ffd76e; }
#pingToggle { width: max-content; pointer-events: none; }
#chatQuick { display: flex; gap: 4px; pointer-events: none; }
#chatQuick button {
  padding: 5px 10px; font-family: inherit; font-size: 10px; letter-spacing: 1.6px;
  color: #9fc3e6; background: rgba(10, 22, 38, .72);
  border: 1px solid #2a4a7a; border-radius: 4px; cursor: pointer;
}
#chatQuick button:hover { color: #fff; border-color: #7fd4ff; background: rgba(20, 44, 74, .9); }
#pingMenuToggle.on { color: #04070e; background: #7fd4ff; border-color: #7fd4ff; font-weight: 800; }

/* Expanded quick-comms menu: bigger targets, easy to hit mid-fight and on a
   phone. Sits above the toggle and collapses again as soon as one is chosen. */
#quickList {
  display: flex; flex-direction: column; gap: 5px;
  margin-bottom: 6px; width: max-content; pointer-events: auto;
}
#quickList button {
  display: flex; align-items: center; gap: 9px;
  min-width: 168px; padding: 11px 14px;
  font-family: inherit; font-size: 12px; letter-spacing: 2px; text-align: left;
  color: #cfe3ff; background: rgba(10, 22, 38, .92);
  border: 1px solid #2a4a7a; border-radius: 6px; cursor: pointer;
  animation: quickIn .16s ease-out backwards;
}
#quickList button:nth-child(2) { animation-delay: .03s; }
#quickList button:nth-child(3) { animation-delay: .06s; }
#quickList button:nth-child(4) { animation-delay: .09s; }
#quickList button em {
  font-style: normal; font-size: 14px; width: 18px; text-align: center;
}
#quickList button span { display: inline; }
#quickList button:hover { border-color: #7fd4ff; background: rgba(24, 52, 86, .96); color: #fff; }
#quickList button[data-kind="help"]    em { color: #ffd76e; }
#quickList button[data-kind="defend"]  em { color: #6aff8a; }
#quickList button[data-kind="attack"]  em { color: #ff6a5c; }
#quickList button[data-kind="onmyway"] em { color: #b58cff; }
@keyframes quickIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
#chatEntry {
  display: flex; align-items: center; gap: 6px; margin-top: 6px;
  pointer-events: auto;
}
#chatScope {
  font-size: 9px; letter-spacing: 1.5px; padding: 3px 6px; border-radius: 3px;
  color: #04070e; background: #7fd4ff; font-weight: 800;
}
#chatScope.team { background: #6aff8a; }
#chatInput {
  flex: 1 1 auto; min-width: 0; padding: 5px 8px;
  font-family: inherit; font-size: 11px; color: #cfe3ff;
  background: rgba(4, 10, 20, .92); border: 1px solid #7fd4ff; border-radius: 4px;
}
#chatInput:focus { outline: none; }
/* ===== Ping markers =====
   Four chevrons that slam inward onto the point, over a double shock-ring.
   Reads as "look HERE" at a glance instead of a soft expanding blob, and the
   inward motion pulls the eye to the centre rather than away from it. */
.pingMark {
  position: absolute; width: 0; height: 0; pointer-events: none; z-index: 25;
  --ping: #7fd4ff;
}
.pingMark i {
  position: absolute; width: 13px; height: 13px;
  border-left: 3px solid var(--ping); border-top: 3px solid var(--ping);
  filter: drop-shadow(0 0 4px var(--ping));
  animation: pingChevron 1.15s cubic-bezier(.2, .75, .3, 1) infinite;
}
.pingMark i:nth-child(1) { transform: rotate(45deg);   }
.pingMark i:nth-child(2) { transform: rotate(135deg);  }
.pingMark i:nth-child(3) { transform: rotate(225deg);  }
.pingMark i:nth-child(4) { transform: rotate(315deg);  }
/* each chevron travels in along its own diagonal */
.pingMark i:nth-child(1) { --dx: -1; --dy: -1; }
.pingMark i:nth-child(2) { --dx:  1; --dy: -1; }
.pingMark i:nth-child(3) { --dx:  1; --dy:  1; }
.pingMark i:nth-child(4) { --dx: -1; --dy:  1; }
@keyframes pingChevron {
  0%   { opacity: 0; margin-left: calc(var(--dx) * 34px); margin-top: calc(var(--dy) * 34px); }
  22%  { opacity: 1; }
  70%  { opacity: 1; margin-left: calc(var(--dx) * 9px);  margin-top: calc(var(--dy) * 9px); }
  100% { opacity: 0; margin-left: calc(var(--dx) * 7px);  margin-top: calc(var(--dy) * 7px); }
}
/* shock ring underneath */
.pingMark b {
  position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%; border: 2px solid var(--ping); opacity: 0;
  animation: pingRing 1.15s ease-out infinite;
}
.pingMark b:nth-of-type(2) { animation-delay: .18s; }
@keyframes pingRing {
  0%   { transform: scale(.3); opacity: .9; }
  100% { transform: scale(2.6); opacity: 0; }
}
.pingMark span {
  position: absolute; left: 0; top: -30px; transform: translateX(-50%);
  font-size: 9px; font-weight: 700; letter-spacing: 1.6px;
  color: var(--ping); text-shadow: 0 1px 4px #000; white-space: nowrap;
}
/* minimap ping dot */
.pingDot {
  position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; background: var(--ping, #7fd4ff); pointer-events: none;
  box-shadow: 0 0 6px var(--ping, #7fd4ff);
  animation: pingDot 1.15s ease-out infinite;
}
@keyframes pingDot {
  0%   { transform: scale(.6); opacity: 1; }
  100% { transform: scale(2.4); opacity: 0; }
}
@media (max-width: 900px), (max-height: 620px) {
  #chatWrap { bottom: 150px; width: 54vw; }
  #chatLog { max-height: 105px; }
  #chatQuick button { font-size: 8px; padding: 4px 6px; }
}

#lobbyHint { margin-top: 8px; font-size: 10px; color: #7f9bbd; text-align: center; }
.mpHint { margin-top: 6px; font-size: 10px; color: #5e7a9c; }

/* open lobby list */
#mpOpenLobbies { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.mpLobbyRow {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  background: rgba(20, 40, 65, .5); border: 1px solid #2a4a7a; border-radius: 8px;
  text-align: left;
}
.mpLobbyName { flex: 1 1 auto; font-size: 12px; color: #cfe3ff; letter-spacing: .5px; }
.mpLobbyCount { font-size: 11px; color: #7f9bbd; }
.mpLobbyRow button { padding: 6px 14px; font-size: 11px; }
#mpModal .authAdv { text-align: left; }
#mpModal .authField input { width: 100%; box-sizing: border-box; }


/* ============================================================
   HUD — single coherent pass. Dark glass, clean 1px cyan trim
   with a soft glow, gold accents, block bars, colored numbers.
   One aesthetic, desktop and touch.
   ============================================================ */
:root {
  --h-line: rgba(56, 178, 230, .55);
  --h-line-hi: rgba(120, 214, 255, .8);
  --h-glow: rgba(56, 178, 230, .22);
  --h-glass-a: rgba(8, 16, 27, .93);
  --h-glass-b: rgba(3, 8, 15, .96);
  --h-gold: #eab543;
  --h-text: #d8e9f8;
}
@media (min-width: 901px) and (min-height: 621px){
  #upgradeGrid { grid-template-columns: repeat(4, 62px); gap: 4px; }
}

/* ===== Diagnostics overlay (F3 / ?diag=1) =====
   Deliberately plain and self-contained: it has to be readable on a phone and
   copyable in one tap so numbers from different browsers can be compared. */
#diagPanel {
  position: fixed; top: 10px; left: 10px; z-index: 95;
  width: min(320px, 82vw); padding: 9px 11px 10px;
  background: rgba(4, 10, 20, .93); border: 1px solid #2a4a7a; border-radius: 7px;
  box-shadow: 0 10px 40px rgba(0,0,0,.6);
  pointer-events: auto;
}
.diagHead {
  font-size: 9px; letter-spacing: 2.4px; color: #7fd4ff; margin-bottom: 6px;
  display: flex; justify-content: space-between;
}
.diagHead span { color: #5e7a9c; }
#diagBody {
  margin: 0; font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 10.5px; line-height: 1.5; color: #cfe3ff; white-space: pre-wrap;
  max-height: 52vh; overflow: auto;
}
#diagBody b { color: #6aff8a; font-weight: 700; }
#diagBody i { color: #ff9a8c; font-style: normal; font-weight: 700; }
#diagCopy {
  margin-top: 7px; width: 100%; padding: 6px 0;
  font-family: inherit; font-size: 10px; letter-spacing: 1.6px;
  color: #cfe3ff; background: rgba(20, 44, 74, .9);
  border: 1px solid #2a4a7a; border-radius: 4px; cursor: pointer;
}
#diagCopy:hover { border-color: #7fd4ff; color: #fff; }

/* ===== No-GPU warning =====
   Only ever shown when the context came back on a software rasteriser. The
   wording matters: without it the player concludes the game is broken, when
   the cause is browser configuration and the fix is two clicks away. */
#softwareWarn {
  position: fixed; left: 50%; top: 14px; transform: translateX(-50%);
  /* Above the training box: this is a one-time, dismissible notice and it is
     useless if something else is sitting on top of the sentence. */
  z-index: 130; width: min(520px, 92vw); padding: 13px 16px 14px;
  background: rgba(46, 18, 10, .96); border: 1px solid rgba(255, 140, 90, .55);
  border-radius: 8px; box-shadow: 0 12px 44px rgba(0, 0, 0, .6);
  text-align: left; pointer-events: auto;
}
#softwareWarn b {
  display: block; font-size: 11px; letter-spacing: 2px; color: #ffb27f;
  margin-bottom: 7px;
}
#softwareWarn p { font-size: 11.5px; line-height: 1.55; color: #f0d6c8; margin-bottom: 7px; }
#softwareWarn #swGpu { color: #ff9a8c; font-weight: 700; }
#softwareWarn .swFix { color: #cfe3ff; }
#softwareWarn em { font-style: normal; color: #fff; font-weight: 600; }
#swDismiss {
  padding: 6px 16px; font-size: 11px; letter-spacing: 1.4px;
  background: rgba(90, 40, 24, .9); border-color: rgba(255, 140, 90, .5); color: #ffd9c4;
}

/* Server dropped the match. Deliberately blunt: a frozen board with no
   explanation reads as the game crashing, when the usual cause is the server
   restarting under it. */
#disconnectBox {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 97; width: min(420px, 90vw); padding: 20px 22px; text-align: center;
  background: rgba(10, 18, 32, .97); border: 1px solid #2a4a7a; border-radius: 10px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .7);
}
#disconnectBox b {
  display: block; font-size: 12px; letter-spacing: 3px; color: #ff9a8c; margin-bottom: 9px;
}
#disconnectBox p { font-size: 12px; line-height: 1.55; color: #cfe3ff; margin-bottom: 14px; }
#disconnectBox button { padding: 9px 22px; font-size: 12px; letter-spacing: 1.4px; }

/* Removed from a lobby. Shaped like the disconnect notice above because it is
   read in the same moment and the same way, but amber rather than red: nothing
   has broken and nothing was lost, so it must not read as an error. */
.kickedBox {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 98; width: min(420px, 90vw); padding: 20px 22px; text-align: center;
  background: rgba(10, 18, 32, .97); border: 1px solid #6a5320; border-radius: 10px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .7);
}
.kickedBox b {
  display: block; font-size: 12px; letter-spacing: 2.2px; color: #ffd65a; margin-bottom: 9px;
}
.kickedBox p { font-size: 12px; line-height: 1.55; color: #cfe3ff; margin-bottom: 14px; }
.kickedActions { display: flex; gap: 10px; justify-content: center; }
.kickedBox button { padding: 9px 22px; font-size: 12px; letter-spacing: 1.4px; }
.kickedBox button.ghost {
  background: transparent; border: 1px solid rgba(120, 170, 210, .35); color: #9fc4e4;
}
.kickedBox button.ghost:hover { color: #eaf6ff; border-color: rgba(150, 210, 255, .8); }

/* ───────────────────────────── Profile ─────────────────────────────
   Its own overlay rather than a panel inside the hangar: it is read, not
   played with, and it has to work identically on a phone. */
#profileScreen { display: flex; align-items: center; justify-content: center; padding: 16px; overflow: auto; z-index: 60; }
.profCard {
  position: relative; width: min(680px, 100%); max-height: 92vh; overflow: auto;
  padding: 22px 22px 16px; border-radius: 14px;
  background: linear-gradient(180deg, rgba(11, 22, 38, .98), rgba(6, 12, 22, .99));
  border: 1px solid rgba(90, 150, 210, .35);
  box-shadow: 0 0 0 1px rgba(2, 8, 16, .9), 0 24px 60px rgba(0, 0, 0, .6);
}
.profClose {
  position: absolute; top: 10px; right: 10px; width: 30px; height: 30px;
  background: transparent; border: 1px solid rgba(120, 170, 210, .3); border-radius: 8px;
  color: #9fc4e4; font-size: 14px; cursor: pointer;
}
.profClose:hover { color: #eaf6ff; border-color: rgba(150, 210, 255, .8); }
.profHead { display: flex; gap: 16px; align-items: center; }
.profAvatarWrap { position: relative; flex: 0 0 auto; }
.profAvatar { width: 84px; height: 84px; border-radius: 50%; display: block; border: 2px solid rgba(120, 190, 240, .5); background: #08111d; }
.profAvatarBtn {
  position: absolute; left: 50%; bottom: -6px; transform: translateX(-50%);
  padding: 2px 8px; font-size: 8.5px; letter-spacing: 1px; font-weight: 700;
  background: rgba(10, 22, 36, .95); color: #9fd4ff;
  border: 1px solid rgba(120, 190, 240, .5); border-radius: 20px; cursor: pointer;
}
.profAvatarBtn:hover { color: #fff; border-color: #9fd4ff; }
.profName { font-size: 22px; font-weight: 800; letter-spacing: 1.5px; color: #eaf6ff; }
.profNameRow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.profNameBtn {
  padding: 2px 8px; font-size: 8.5px; letter-spacing: 1px; font-weight: 700;
  background: rgba(10, 22, 36, .95); color: #9fd4ff;
  border: 1px solid rgba(120, 190, 240, .5); border-radius: 20px; cursor: pointer;
}
.profNameBtn:hover { color: #fff; border-color: #9fd4ff; }
.profRename { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.profRename input {
  flex: 1 1 160px; min-width: 0; padding: 6px 10px; font: inherit; font-size: 13px;
  background: rgba(8, 17, 29, .9); color: #eaf6ff;
  border: 1px solid rgba(120, 190, 240, .4); border-radius: 6px;
}
.profRename button {
  padding: 6px 12px; font: inherit; font-size: 12px; font-weight: 700; letter-spacing: .5px;
  background: rgba(10, 22, 36, .95); color: #9fd4ff;
  border: 1px solid rgba(120, 190, 240, .5); border-radius: 6px; cursor: pointer;
}
.profRename button:hover { color: #fff; border-color: #9fd4ff; }
.profRename .profClaimMsg { flex-basis: 100%; }
.profMeta { margin-top: 3px; font-size: 11px; color: #7fa8c8; }
/* segmented control: the settings' two-way switch */
.profSegment { display: inline-flex; border: 1px solid #24455e; border-radius: 999px; overflow: hidden; background: rgba(8,16,26,.6); }
.profSegment button { font: inherit; font-size: 12px; padding: 6px 14px; border: 0; background: transparent; color: #8fb2cc; cursor: pointer; letter-spacing: .5px; }
.profSegment button + button { border-left: 1px solid #24455e; }
.profSegment button.on { background: linear-gradient(180deg, #2b5cff, #1a3fb8); color: #fff; box-shadow: inset 0 0 0 1px rgba(160,210,255,.35); }
.profStats { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; margin: 18px 0 6px; }
/* the level tile's progress to the next level */
.profXpBar { display: block; height: 4px; margin-top: 6px; border-radius: 2px; background: rgba(120, 190, 250, .18); overflow: hidden; }
.profXpBar i { display: block; height: 100%; background: linear-gradient(90deg, #3aa0ff, #7fe3ff); box-shadow: 0 0 6px rgba(90, 200, 255, .6); }
.profStat { padding: 10px 8px; text-align: center; background: rgba(14, 30, 48, .7); border: 1px solid rgba(80, 130, 180, .25); border-radius: 10px; }
.profStatV { font-size: 19px; font-weight: 800; color: #cfeaff; font-variant-numeric: tabular-nums; }
.profStatL { margin-top: 2px; font-size: 9px; letter-spacing: 1.4px; color: #7fa8c8; text-transform: uppercase; }
.profStatS { margin-top: 3px; font-size: 9px; color: #5f8bab; }
.profSection { margin-top: 18px; }
.profSectionHead { font-size: 10px; letter-spacing: 2px; color: #6f9cbf; margin-bottom: 7px; }
.profRecent { display: flex; flex-direction: column; gap: 4px; }
.profRow {
  display: grid; grid-template-columns: 46px 1fr 56px 68px 52px; gap: 8px; align-items: center;
  padding: 7px 10px; font-size: 11.5px; color: #b9d6ee;
  background: rgba(14, 30, 48, .55); border-left: 3px solid rgba(120, 170, 210, .4); border-radius: 6px;
}
.profRow.win { border-left-color: #5ad0a0; }
.profRow.loss { border-left-color: #ff7a6a; }
.profRowResult { font-size: 9px; font-weight: 800; letter-spacing: 1px; }
.profRow.win .profRowResult { color: #5ad0a0; }
.profRow.loss .profRowResult { color: #ff7a6a; }
.profRowKd, .profRowScore, .profRowWhen { font-variant-numeric: tabular-nums; text-align: right; color: #8fb4d4; }
.profEmpty { font-size: 11.5px; color: #6f8fab; margin: 4px 0; }
.profSettings { display: flex; flex-direction: column; gap: 6px; }
.profSetting { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 12px; color: #b9d6ee; padding: 6px 2px; }
.profSetting select, .profSetting input[type="range"] { max-width: 190px; }
.profFoot { margin-top: 18px; display: flex; justify-content: flex-end; }
.profSignOut {
  padding: 8px 18px; font-size: 11px; font-weight: 700; letter-spacing: 1.6px;
  color: #ff9a8a; background: transparent;
  border: 1px solid rgba(255, 122, 106, .4); border-radius: 8px; cursor: pointer;
}
.profSignOut:hover { color: #fff; background: rgba(255, 90, 70, .18); border-color: #ff7a6a; }
/* the "or" divider above the Google button */
.authOr { position: relative; text-align: center; margin: 12px 0 10px; }
.authOr::before { content: ''; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: rgba(120, 170, 210, .22); }
.authOr span { position: relative; padding: 0 10px; font-size: 10px; letter-spacing: 2px; color: #6f9cbf; background: #0a1420; }
#googleBtn { display: flex; justify-content: center; }
@media (max-width: 560px) {
  .profRow { grid-template-columns: 42px 1fr 50px 58px; }
  .profRowWhen { display: none; }
}

/* Google button for the packaged app. Google's own web button cannot run
   there (localhost origin), so this mirrors its shape without pretending to
   be it — the real consent screen appears in Chrome a moment later. */
.googleNative {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 280px; margin: 0 auto; padding: 11px 16px;
  font-family: inherit; font-size: 13.5px; font-weight: 600;
  color: #e8eaed; background: #131314;
  border: 1px solid #8e918f; border-radius: 20px; cursor: pointer;
}
.googleNative::before {
  content: ''; width: 18px; height: 18px; flex: 0 0 18px;
  background: no-repeat center/contain url('data:image/svg+xml;utf8,\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">\
<path fill="%23EA4335" d="M24 9.5c3.5 0 6.6 1.2 9 3.6l6.7-6.7C35.6 2.7 30.1 0 24 0 14.6 0 6.5 5.4 2.6 13.2l7.8 6.1C12.3 13.2 17.7 9.5 24 9.5z"/>\
<path fill="%234285F4" d="M46.1 24.6c0-1.6-.1-3.1-.4-4.6H24v9.1h12.4c-.5 2.9-2.2 5.4-4.7 7l7.6 5.9c4.4-4.1 6.8-10.815 6.8-17.4z"/>\
<path fill="%23FBBC05" d="M10.4 28.7c-.5-1.4-.8-2.9-.8-4.7s.3-3.3.8-4.7l-7.8-6.1C.9 16.3 0 20 0 24s.9 7.7 2.6 10.8l7.8-6.1z"/>\
<path fill="%2334A853" d="M24 48c6.5 0 11.9-2.1 15.9-5.8l-7.6-5.9c-2.1 1.4-4.8 2.3-8.3 2.3-6.3 0-11.7-3.7-13.6-9.8l-7.8 6.1C6.5 42.6 14.6 48 24 48z"/></svg>');
}
.googleNative:hover:not(:disabled) { background: #1e1f20; border-color: #cdd1d3; }
.googleNative:disabled { opacity: .55; cursor: default; }


/* ---- Mode selector (ship selection) ----------------------------------- */
/* A segmented control rather than a native <select>: the panel is all flat
   angular chrome and a browser dropdown reads as a form control dropped into
   a game. Sits directly above LAUNCH because it changes what LAUNCH does. */
.hgMode {
  display: flex;
  gap: 6px;
  margin: 0 0 10px;
  padding: 4px;
  border: 1px solid rgba(90, 150, 220, 0.28);
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(12, 26, 45, 0.75), rgba(8, 16, 28, 0.75));
}
.hgMode button {
  flex: 1;
  padding: 9px 6px 8px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: #8fb4d8;
  font: 600 12px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.14em;
  cursor: pointer;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.hgMode button em {
  display: block;
  margin-top: 4px;
  font: 400 10px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.06em;
  opacity: 0.62;
  font-style: normal;
}
.hgMode button:hover { color: #cfe6ff; background: rgba(70, 130, 200, 0.16); }
.hgMode button.on {
  color: #eaf6ff;
  border-color: rgba(120, 200, 255, 0.55);
  background: linear-gradient(180deg, rgba(46, 120, 200, 0.55), rgba(24, 70, 130, 0.55));
  box-shadow: 0 0 14px rgba(80, 170, 255, 0.25) inset;
}


/* ---- Onboarding walkthrough ------------------------------------------- */
#tutBox {
  position: fixed;
  left: 50%;
  top: 74px;
  transform: translateX(-50%);
  z-index: 60;
  /* 15% up from 560/12/17/13: on a desktop monitor the box was small
     enough to read as a toast notification and get ignored — which for the
     one panel that teaches the game is the worst possible outcome. Every
     phone rule below overrides these, so handsets are unaffected. */
  /* Shrink to the text, cap at the configured width.
     A fixed width means a one-line step renders as a mostly-empty slab -- and
     since this box sits over the battlefield, every empty pixel is board you
     cannot see for no reason. */
  width: max-content;
  max-width: min(var(--tut-w, 420px), calc(100vw - 32px));
  padding: 14px 19px 16px;
  /* Amber, matching the coaching tips that take over when training ends.
     They teach the same kind of thing and they used to look like two
     unrelated systems -- one blue panel, one amber toast -- which made the
     handover read as a change of subject rather than a continuation. */
  border: 1px solid rgba(255, 190, 90, 0.42);
  border-left: 3px solid #ffbe5a;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(30, 22, 10, 0.95), rgba(14, 11, 6, 0.95));
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.55);
  pointer-events: auto;
}
/* The box has to fit on the screen it is teaching.
   The control-scheme step is the tallest one -- two option buttons and a
   confirm under a paragraph -- and on a landscape handset it ran off the
   bottom with "Use this" below the fold, which is the one control that step
   cannot do without. Cap it to the viewport and let the overflow scroll. */
#tutBox {
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#tutBox.hidden { display: none; }
#tutBox .tutStep {
  font: 600 11.5px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.22em;
  color: #c79a58;
  text-transform: uppercase;
}
#tutBox .tutTitle {
  margin: 6px 0 4px;
  font: 700 20px/1.15 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.04em;
  color: #ffd79a;
}
#tutBox .tutBody {
  font: 400 15px/1.45 'Chakra Petch', system-ui, sans-serif;
  color: #e3cfae;
}
#tutBox .tutSkip {
  margin-top: 12px;
  padding: 6px 14px;
  border: 1px solid rgba(200, 160, 90, 0.38);
  border-radius: 5px;
  background: transparent;
  color: #b9975f;
  font: 500 11px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.1em;
  cursor: pointer;
}
#tutBox .tutSkip:hover { color: #ffd79a; border-color: rgba(255, 200, 110, 0.6); }


/* Training: the control the current step is asking for. Deliberately loud —
   the refit grid is eight near-identical tiles and prose alone does not find
   them for a first-time player. */
.tutPick {
  position: relative;
  border-color: rgba(255, 214, 90, 0.9) !important;
  box-shadow: 0 0 0 2px rgba(255, 214, 90, 0.55), 0 0 18px rgba(255, 200, 60, 0.45);
  animation: tutPulse 1.1s ease-in-out infinite;
}
@keyframes tutPulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(255, 214, 90, 0.45), 0 0 14px rgba(255, 200, 60, 0.3); }
  50%      { box-shadow: 0 0 0 3px rgba(255, 230, 140, 0.8), 0 0 24px rgba(255, 210, 80, 0.6); }
}

/* The refit tiles are styled by `.cmd.upg` — two classes, which outranks a
   lone `.tutPick`, so the glow was set and then immediately overridden. Match
   that specificity and use outline, which nothing else on these buttons sets. */
/* ABILITIES is a GOLD button by design, so the gold tutorial outline below
   landed gold-on-gold and read as no highlight at all -- which is exactly how
   it looked to a player being told to "open ABILITIES". White-hot instead, so
   it separates from the button underneath it. */
#abilityToggle.tutPick {
  outline: 3px solid #ffffff !important;
  outline-offset: 3px;
  box-shadow: 0 0 0 6px rgba(120, 220, 255, .45), 0 0 34px rgba(150, 230, 255, .9) !important;
  animation: tutPulse 0.9s ease-in-out infinite !important;
}

.cmd.upg.tutPick,
[data-slot].tutPick,
.tutPick {
  outline: 3px solid rgba(255, 214, 90, 0.95) !important;
  outline-offset: 2px;
  box-shadow: 0 0 22px rgba(255, 200, 60, 0.75) !important;
  animation: tutPulse 1.1s ease-in-out infinite !important;
  z-index: 5;
}


/* Training: an upgrade the current step is not asking for. Disabled rather
   than hidden, so the player still sees the full refit menu they will have
   free run of the moment training ends. */
.cmd.upg.tutLocked,
.rfCard.tutLocked {
  opacity: 0.32 !important;
  filter: grayscale(0.7);
  cursor: not-allowed;
}

/* Locked during training: unclickable and quiet. No animation — only the
   tiles the step is ASKING for should move. */
.cmd.upg.tutLocked,
.rfCard.tutLocked,
[data-slot].tutLocked {
  pointer-events: none !important;
  animation: none !important;
  outline: none !important;
  box-shadow: none !important;
}

/* The highlight has to read on buttons that are ALREADY gold — the ABILITIES
   toggle is amber with its own glow, so a gold outline on it was invisible.
   Motion carries it instead of colour: nothing else in the HUD scales. */
@keyframes tutPulseScale {
  0%, 100% { transform: scale(1);    outline-color: rgba(120, 240, 255, 0.95); }
  50%      { transform: scale(1.07); outline-color: rgba(255, 255, 255, 1); }
}
.cmd.upg.tutPick,
#abilityToggle.tutPick,
[data-slot].tutPick,
.tutPick {
  outline: 3px solid rgba(120, 240, 255, 0.95) !important;
  outline-offset: 3px !important;
  box-shadow: 0 0 26px rgba(120, 220, 255, 0.85) !important;
  animation: tutPulseScale 0.9s ease-in-out infinite !important;
  transform-origin: center;
  z-index: 6;
}

/* Training panel on phones. The desktop box is sized for a 560px column on a
   wide screen; on a handset that filled most of the display and buried the
   game it was explaining. Tighter type, less padding, pinned near the top. */
@media (max-width: 900px), (pointer: coarse) {
  #tutBox {
    top: 56px;
    width: calc(100vw - 20px);
    max-width: none;
    padding: 8px 12px 10px;
    border-radius: 8px;
  }
  #tutBox .tutStep { font-size: 9px; letter-spacing: 0.18em; }
  #tutBox .tutTitle { margin: 4px 0 3px; font-size: 14px; }
  #tutBox .tutBody { font-size: 11.5px; line-height: 1.35; }
  #tutBox .tutSkip { margin-top: 7px; padding: 4px 10px; font-size: 10px; }
}
/* Landscape handsets have almost no vertical room — keep it to a strip. */
@media (max-height: 520px) and (pointer: coarse) {
  #tutBox { top: 44px; padding: 6px 10px 8px; }
  #tutBox .tutBody { font-size: 11px; }
}

/* ---- Training panel: header row, collapse, and a phone-sized box -------- */
#tutBox .tutHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
#tutBox .tutMinBtn {
  width: 26px;
  height: 26px;
  flex: none;
  border: 1px solid rgba(200, 160, 90, 0.4);
  border-radius: 5px;
  background: transparent;
  color: #c79a58;
  font: 600 15px/1 system-ui, sans-serif;
  cursor: pointer;
}
#tutBox .tutMinBtn:hover { color: #ffd79a; border-color: rgba(255, 200, 110, 0.7); }

/* Collapsed: just the step counter and the button, so the instruction can be
   dismissed while it is being carried out without losing your place. */
#tutBox.tutMin .tutTitle,
#tutBox.tutMin .tutBody,
#tutBox.tutMin .tutSkip { display: none; }
#tutBox.tutMin {
  width: auto;
  min-width: 0;
  padding: 6px 8px;
}

/* Phones: a compact card, NOT a full-width banner. It sat across the whole
   screen and took the top third — over the battlefield it was describing. */
@media (max-width: 900px), (pointer: coarse) {
  #tutBox {
    left: auto;
    right: 10px;
    transform: none;
    top: 52px;
    width: min(320px, 66vw);
    max-width: none;
    padding: 8px 10px 10px;
  }
  #tutBox .tutStep { font-size: 9px; }
  #tutBox .tutTitle { font-size: 13px; margin: 3px 0 2px; }
  #tutBox .tutBody { font-size: 11px; line-height: 1.32; }
  #tutBox .tutSkip { margin-top: 6px; padding: 3px 9px; font-size: 10px; }
  #tutBox .tutMinBtn { width: 30px; height: 30px; }   /* still a touch target */
}

/* The collapse control reads as a chevron on the panel's own edge, not as a
   button bolted into the corner. Borderless until touched, so it disappears
   into the card the way the rest of this HUD does. */
#tutBox .tutMinBtn {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: #6f96b8;
  font: 400 13px/1 system-ui, sans-serif;
  opacity: 0.75;
  transition: color 0.15s, background 0.15s, opacity 0.15s;
}
#tutBox .tutMinBtn:hover {
  color: #dcefff;
  background: rgba(90, 150, 210, 0.18);
  opacity: 1;
}
#tutBox.tutMin .tutMinBtn { color: #c79a58; opacity: 0.9; }
@media (pointer: coarse) {
  /* Bigger hit area on touch without making the glyph itself heavier. */
  #tutBox .tutMinBtn { width: 30px; height: 30px; font-size: 14px; }
}

/* Smaller still on phones: the card was overlapping the refit and ability
   panels on the right, which are exactly the controls the step is pointing
   at. Narrower, and parked on the LEFT where only the minimap lives (and that
   sits at the bottom). */
@media (max-width: 900px), (pointer: coarse) {
  #tutBox {
    left: 10px;
    right: auto;
    top: 62px;
    width: min(272px, 40vw);
    padding: 7px 9px 8px;
    border-radius: 7px;
  }
  #tutBox .tutStep { font-size: 8.5px; letter-spacing: 0.16em; }
  #tutBox .tutTitle { font-size: 12px; margin: 2px 0 2px; }
  #tutBox .tutBody { font-size: 10.5px; line-height: 1.3; }
  #tutBox .tutSkip { margin-top: 5px; padding: 3px 8px; font-size: 9.5px; }
}
/* Very short landscape phones: trim again so it never reaches the HUD. */
@media (max-height: 480px) and (pointer: coarse) {
  #tutBox { top: 50px; width: min(248px, 36vw); }
  #tutBox .tutBody { font-size: 10px; }
}

/* ---- Training: desktop position ---------------------------------------- */
/* Off to the right rather than dead centre. Centred, it sat over the fight
   and the ship name; the right column is chrome the player is already
   looking at for the refit and ability panels. */
@media (min-width: 901px) and (pointer: fine) {
  #tutBox {
    left: auto;
    right: 18px;
    transform: none;
    top: 74px;
    width: min(380px, 30vw);
  }
}

/* ---- Hull lock during training ----------------------------------------- */
/* One hull until training is done: the walkthrough names Missile Pods and
   Judgement Cannon, which only the Vindicator has. */
/* The arrows used to be switched off outright here, so during training the
   other four hulls could not be looked at, only guessed at. They browse
   normally now -- a hull you cannot fly yet is worth seeing, it is what the
   training is FOR -- and the lock moves to the launch button instead. */
body.lockedHullView .hgSelect { cursor: not-allowed; }
body.lockedHullView .hgSelect:not(.locked) { cursor: pointer; }
/* the readouts stay legible; the pad gets the badge */
body.lockedHullView .hgLeft { opacity: .72; }
body.lockedHullView .hgStage::before {
  /* Set per hull by renderHangar: training says one thing, an unearned hull
     says another. Hardcoding it here meant every locked hull claimed the
     reason was training. */
  content: attr(data-lock);
  position: absolute; left: 50%; top: -6px;
  transform: translateX(-50%);
  padding: 5px 14px;
  font-size: 9.5px; font-weight: 700; letter-spacing: 2.4px;
  color: #ffcf5e; white-space: nowrap;
  background: rgba(8, 16, 30, .92);
  border: 1px solid rgba(240, 175, 60, .45);
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 8px 100%, 0 calc(100% - 8px));
}
body.hullLocked .hgStage::after {
  content: 'Training flies the Vindicator — other hulls unlock after';
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  padding: 5px 12px;
  border: 1px solid rgba(120, 170, 220, 0.3);
  border-radius: 6px;
  background: rgba(8, 16, 28, 0.8);
  color: #8fb4d8;
  font: 500 11px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.08em;
  white-space: nowrap;
  pointer-events: none;
}

/* ---- Pre-match countdown ----------------------------------------------- */
#countdown {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(4, 10, 20, 0.55), rgba(2, 5, 10, 0.82));
}
#countdown.hidden { display: none; }
#countdownNum {
  font: 800 92px/1 'Chakra Petch', system-ui, sans-serif;
  color: #eaf6ff;
  text-shadow: 0 0 40px rgba(90, 180, 255, 0.65);
  animation: cdPop 0.9s ease-out;
}
#countdownSub {
  font: 600 13px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.42em;
  color: #7fb0d8;
}
@keyframes cdPop {
  0%   { transform: scale(1.35); opacity: 0.15; }
  30%  { transform: scale(1);    opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}

/* ---- Lobby chat --------------------------------------------------------- */
#lobbyChat { margin: 10px 0 4px; }
/* Short screens: the send row sticks to the bottom of the scrolling panel so
   it is always in reach, rather than sitting below the fold. */
@media (max-height: 640px) {
  #lobbyChat .chatRow {
    position: sticky; bottom: 0;
    background: var(--hg-panel); padding: 6px 0 2px; margin-top: 4px;
  }
  #lobbyChatLog { max-height: 84px; }
  #mpModal #mpPanel { padding: 12px 14px; }
}
#lobbyChatLog {
  height: 128px;
  overflow-y: auto;
  padding: 6px 8px;
  border: 1px solid rgba(90, 150, 220, 0.25);
  border-radius: 6px;
  background: rgba(6, 14, 26, 0.6);
  font: 400 12px/1.45 'Chakra Petch', system-ui, sans-serif;
  color: #b9d4ea;
}
#lobbyChat .chatRow { display: flex; gap: 6px; margin-top: 6px; }
#lobbyChatInput { flex: 1; min-width: 0; }

/* ---- Player settings vs live tuning ------------------------------------ */
/* Non-tuners get the panel with only what belongs to their DEVICE: audio,
   graphics, controls, account. Balance, effects, models and the config tree
   are authored globally — showing a player controls they cannot push is worse
   than not offering them. */
body.playerSettings #admHead span::after { content: ' — SETTINGS'; }
body.playerSettings #admHead span { font-size: 0; }
body.playerSettings #admHead span::after { font-size: 13px; }
body.playerSettings #admActions,
body.playerSettings #acConfig,
body.playerSettings #admPresets,
/* THE BALANCE TREE. Every section — world, ships, abilities, upgrades, AI —
   is rendered into #admBody, and nothing here hid it, so a player who opened
   Settings got the whole live-tuning panel. Editing it could not push to the
   server (that endpoint is admin-only) but it could wreck their own client and
   had no business being on screen. */
body.playerSettings #admBody,
body.playerSettings #admBackdrop { display: none; }
/* ...and the device settings take its place. */
/* Shown in BOTH modes: an admin needs these as much as anyone, and hiding them
   behind the non-admin path is why they could not be found. */
#admPlayer { display: block; padding: 4px 12px 14px; }
body.playerSettings #admPlayer::before {
  content: 'SETTINGS';
  display: block; margin: 2px 0 8px;
  font-size: 9px; font-weight: 700; letter-spacing: 1.6px; color: #6f8cae;
}
/* Folded away in the Control Room so it cannot bury the config tree. */
.admDeviceGroup { margin: 0 0 10px; }
.admDeviceGroup > summary { cursor: pointer; }
#admPlayerRows { padding-top: 4px; }
#admPlayer .profSetting, #admPlayerRows .profSetting {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 9px 2px;
  border-bottom: 1px solid rgba(110, 165, 230, .12);
  font-size: 12px; color: #b9d4ea;
}
#admPlayer .profSetting:last-child,
#admPlayerRows .profSetting:last-child { border-bottom: none; }
#admPlayer input[type="range"], #admPlayerRows input[type="range"] { width: 150px; }
/* Keep the account block and the graphics/audio rows, and let the tutorial
   replay through — it is a per-player thing, not a balance lever. */
body.playerSettings #admActions { display: flex; }
body.playerSettings #admActions > button { display: none; }
body.playerSettings #admActions > #replayTutorial { display: inline-block; }
body.inMatch.playerSettings #admActions > #quitMatch { display: inline-block; }
/* ...and out of a match it is not there for an admin either: the balance
   editor shows every action button, this one included. */
body:not(.inMatch) #quitMatch { display: none !important; }

/* Chat names by fleet, with your own in green. Only you see your own line as
   green — everyone else sees it in your team's colour, which is what makes it
   useful as "that one is me" rather than as a rank. */
#lobbyChatLog .chatBlue { color: #6fc2ff; }
#lobbyChatLog .chatRed  { color: #ff7a68; }
#lobbyChatLog .chatMe   { color: #7dffa8; }

/* ---- Lobby ------------------------------------------------------------- */
/* It was a plain list on a flat panel. This is the last thing a player looks
   at before a match, so it should feel like a launch bay: lit fleet columns,
   a live "waiting" pulse, and slots that read as seats to be filled. */
#lobbyTeams { gap: 14px; }
.lobbyCol {
  border: 1px solid rgba(90, 150, 220, 0.28);
  border-radius: 10px;
  padding: 10px;
  background: linear-gradient(180deg, rgba(12, 26, 45, 0.72), rgba(8, 16, 28, 0.72));
  box-shadow: inset 0 1px 0 rgba(140, 200, 255, 0.08);
}
.lobbyCol[data-team="0"] { border-color: rgba(80, 160, 240, 0.42); }
.lobbyCol[data-team="1"] { border-color: rgba(240, 110, 90, 0.42); }
.lobbyColHead {
  letter-spacing: 0.26em;
  font-weight: 700;
  font-size: 11px;
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 1px solid rgba(120, 170, 220, 0.18);
}
.lobbyList { min-height: 132px; display: flex; flex-direction: column; gap: 5px; }
.lobbyList > div {
  padding: 7px 9px;
  border-radius: 6px;
  background: rgba(20, 40, 66, 0.55);
  border: 1px solid rgba(120, 170, 220, 0.14);
  font-size: 12.5px;
}
.lobbySwitch {
  width: 100%;
  margin-top: 10px;
  letter-spacing: 0.16em;
  font-size: 11px;
}

/* Live status line: a slow pulse so a full lobby feels like it is about to go. */
#lobbyWait {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin: 12px 0 2px;
  font: 600 12px/1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.14em;
  color: #9fd0f0;
}
#lobbyWait .waitDot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #5ad0ff;
  box-shadow: 0 0 10px rgba(90, 208, 255, 0.9);
  animation: waitPulse 1.4s ease-in-out infinite;
}
@keyframes waitPulse {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50%      { opacity: 1;    transform: scale(1.15); }
}
#lobbyHint { opacity: 0.72; letter-spacing: 0.1em; }

/* A team size that training has not unlocked yet. Shown rather than hidden —
   knowing the bigger arenas exist, and why they are shut, beats a picker that
   silently has one option. */
#hgMode button.locked {
  opacity: 0.45;
  color: #7f93ab;
  cursor: not-allowed;
}
#hgMode button.locked::after { content: ' 🔒'; }
#hgMode button.locked:hover { opacity: 0.55; }

/* ── COACHING TIPS ────────────────────────────────────────────────────────
   The situational advice that follows training, in the same first match.

   Deliberately NOT shaped like the training box: that one is an instruction
   you are expected to carry out, this one is a remark about what just
   happened. Bottom-right, out of the way of the ship card and the minimap,
   and it leaves on its own. */
#coachTip {
  position: fixed;
  right: 14px;
  /* Top right, clear of the HUD buttons that end at ~42px.
     It used to sit bottom-right on a desktop and top-right on a handset, which
     is the wrong way round: the bottom of a desktop screen is where the
     console, the minimap and the ship card all are, so the tip landed in the
     busiest corner and read as part of the furniture. The phone rule below
     already did this; now both agree. */
  top: 52px;
  bottom: auto;
  z-index: 58;
  width: min(340px, calc(100vw - 28px));
  padding: 11px 34px 12px 13px;
  border: 1px solid rgba(255, 190, 90, 0.42);
  border-left: 3px solid #ffbe5a;
  border-radius: 9px;
  background: linear-gradient(180deg, rgba(30, 22, 10, 0.95), rgba(14, 11, 6, 0.95));
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55);
  animation: coachIn 0.22s ease-out;
  pointer-events: auto;
}
#coachTip.hidden { display: none; }
@keyframes coachIn {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}

#coachTip .coachHead {
  margin-bottom: 4px;
  font: 700 13px/1.2 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.03em;
  color: #ffd79a;
}
#coachTip .coachBody {
  font: 400 12.5px/1.45 'Chakra Petch', system-ui, sans-serif;
  color: #e3cfae;
}
#coachTip .coachClose {
  position: absolute;
  top: 5px; right: 6px;
  width: 22px; height: 22px;
  border: 0; border-radius: 5px;
  background: transparent;
  color: #9c8156;
  font-size: 12px;
  cursor: pointer;
}
#coachTip .coachClose:hover { background: rgba(255, 255, 255, 0.07); color: #ffd79a; }

/* On a handset it goes along the top instead: the bottom-right corner is
   where the ability drawer lives, and a tip that covers the buttons a player
   is being told to press is worse than no tip. */
@media (max-width: 900px), (pointer: coarse) {
  #coachTip {
    right: 8px;
    bottom: auto;
    top: 8px;
    width: min(300px, 56vw);
    padding: 8px 28px 9px 10px;
  }
  #coachTip .coachHead { font-size: 11.5px; }
  #coachTip .coachBody { font-size: 10.5px; line-height: 1.35; }
}

/* The <noscript> description. Only ever seen with JavaScript off, but it is
   real page content, so it should look like the rest of the site rather than
   like a browser default. */
#seoIntro {
  max-width: 720px; margin: 0 auto; padding: 48px 24px;
  font-family: 'Rajdhani', system-ui, sans-serif; color: #cfe3ff;
  line-height: 1.65; position: relative; z-index: 200;
}
#seoIntro h1 { font-size: 28px; letter-spacing: 2px; color: #eaf6ff; margin-bottom: 14px; }
#seoIntro h2 { font-size: 15px; letter-spacing: 2px; color: #7fc3ff; margin: 22px 0 8px; text-transform: uppercase; }
#seoIntro p { margin-bottom: 12px; }
#seoIntro a { color: #ffd65a; }

/* ── GRADUATION: the push from training into multiplayer ────────────────────
   Shown on the result screen after a solo match, once training is done and
   the player has still never met a real opponent. Amber, like the coaching
   tips, because it is the same voice — the game telling you what to do next
   rather than reporting what happened. */
.endGrad {
  width: min(560px, calc(100vw - 40px));
  margin: 6px auto 18px;
  padding: 14px 18px 15px;
  text-align: left;
  border: 1px solid rgba(255, 190, 90, 0.42);
  border-left: 3px solid #ffbe5a;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(30, 22, 10, 0.95), rgba(14, 11, 6, 0.95));
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.endGradHead {
  font: 700 15px/1.2 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.04em; color: #ffd79a; margin-bottom: 6px;
}
.endGradBody {
  font: 400 13px/1.5 'Chakra Petch', system-ui, sans-serif;
  color: #e3cfae; margin-bottom: 12px;
}
.endGradRow { display: flex; align-items: center; gap: 10px; }
.endGradGo {
  padding: 9px 20px;
  font: 700 12px/1 'Chakra Petch', system-ui, sans-serif; letter-spacing: 0.14em;
  color: #201603; background: linear-gradient(180deg, #ffd166, #f0a92e);
  border: 0; border-radius: 6px; cursor: pointer;
}
.endGradGo:hover { filter: brightness(1.08); }
.endGradLater {
  padding: 9px 14px;
  font: 500 11px/1 'Chakra Petch', system-ui, sans-serif; letter-spacing: 0.1em;
  color: #b9975f; background: transparent;
  border: 1px solid rgba(200, 160, 90, 0.38); border-radius: 6px; cursor: pointer;
}
.endGradLater:hover { color: #ffd79a; border-color: rgba(255, 200, 110, 0.6); }

/* Final tutorial hand-off. It uses the graduation card language, but is a
   modal over the live match so the player must make one clear choice. */
.tutorialCompleteChoice {
  position: fixed; inset: 0; margin: auto;
  box-sizing: border-box;
  width: min(520px, calc(100vw - 28px));
  max-height: calc(100dvh - 28px); overflow: auto;
  padding: 24px; z-index: 100;
  color: #ffe4ac;
}
.tutorialCompleteChoice::backdrop {
  background: rgba(2, 7, 17, 0.79);
  backdrop-filter: blur(4px);
}
.tutorialCompleteChoice .endGradRow { flex-wrap: wrap; }
.tutorialCompleteChoice button { min-height: 44px; padding: 12px 20px; }

/* The launch picker's MULTIPLAYER half, while it is the thing to do next.
   A slow pulse rather than a badge: it has to be noticeable in peripheral
   vision without competing with the LAUNCH button underneath it. */
#hgPlay button.mpNudge {
  border-color: rgba(255, 190, 90, 0.75) !important;
  animation: mpNudgePulse 2.1s ease-in-out infinite;
}
#hgPlay button.mpNudge em { color: #ffd79a; }
@keyframes mpNudgePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 190, 90, 0.34); }
  50%      { box-shadow: 0 0 16px 3px rgba(255, 190, 90, 0.30); }
}
@media (prefers-reduced-motion: reduce) {
  #hgPlay button.mpNudge { animation: none; box-shadow: 0 0 14px 2px rgba(255, 190, 90, 0.3); }
}

/* ── the control-scheme choice, inside the training box ─────────────────── */
.tutChoice { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.tutChoiceBtn {
  flex: 1 1 150px;
  display: flex; flex-direction: column; gap: 3px;
  padding: 9px 12px; text-align: left; cursor: pointer;
  border: 1px solid rgba(200, 160, 90, 0.38); border-radius: 7px;
  background: rgba(30, 22, 10, 0.5);
}
.tutChoiceBtn b {
  font: 700 12px/1.1 'Chakra Petch', system-ui, sans-serif;
  letter-spacing: 0.12em; color: #ffd79a;
}
.tutChoiceBtn em {
  font: 400 11px/1.35 'Chakra Petch', system-ui, sans-serif;
  font-style: normal; color: #c8b48c;
}
.tutChoiceBtn.on {
  border-color: #ffbe5a;
  background: rgba(60, 44, 16, 0.75);
  box-shadow: 0 0 12px rgba(255, 190, 90, 0.25);
}
.tutChoiceGo {
  flex: 0 0 auto; align-self: stretch;
  padding: 9px 18px; cursor: pointer;
  font: 700 11px/1 'Chakra Petch', system-ui, sans-serif; letter-spacing: 0.14em;
  color: #201603; background: linear-gradient(180deg, #ffd166, #f0a92e);
  border: 0; border-radius: 6px;
}
.tutChoiceGo:disabled { opacity: 0.4; cursor: default; }


/* A landscape handset has ~360px of height and the training box has to fit a
   title, a line of copy, two options and a confirm inside it. Everything here
   buys vertical room. */
@media (max-height: 460px) {
  #tutBox { padding: 10px 14px 12px; }
  #tutBox .tutTitle { font-size: 16px; margin: 4px 0 2px; }
  #tutBox .tutBody { font-size: 12.5px; line-height: 1.3; }
  .tutChoice { gap: 6px; margin-top: 8px; }
  .tutChoiceBtn { padding: 6px 10px; flex: 1 1 130px; }
  .tutChoiceBtn b { font-size: 11px; }
  .tutChoiceBtn em { font-size: 10px; line-height: 1.25; }
  .tutChoiceGo { padding: 7px 14px; }
  #tutBox .tutSkip { margin-top: 8px; padding: 5px 12px; }
}

/* TRAINING BOX, on a phone: top-left corner, over the map.
   Centred and 74px down, it sat in the middle of the battlefield and low
   enough to compete with the ship. The map is the thing it can afford to
   cover -- it is the one panel you are not being asked to use while a step is
   being read. */
body.touch #tutBox {
  left: 8px;
  top: 8px;
  transform: none;
  /* Shrink-to-fit, capped. Adjustable in the HUD editor. */
  width: max-content;
  max-width: min(var(--tut-w-touch, 300px), 46vw);
  max-height: calc(100vh - 76px);
}
/* Sign in with Apple.
   Apple's guidelines are specific: their mark, their wording, black or white,
   and no less prominent than any other sign-in button on the screen. Sized to
   match the Google button beside it. */
.appleNative {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  /* Matches the rendered width of the Google button beside it. Apple's
     guidelines require their button to be no less prominent than any other
     sign-in option on the screen, and a visibly narrower one fails that as
     well as looking careless. */
  width: min(362px, 100%); height: 44px; border-radius: 8px; cursor: pointer;
  border: 0; background: #000; color: #fff;
  font: 600 16px/1 -apple-system, system-ui, 'Segoe UI', sans-serif;
  letter-spacing: .2px;
}
.appleNative:hover { background: #141414; }
.appleNative:disabled { opacity: .55; cursor: default; }
.appleNative svg { width: 17px; height: 20px; flex: 0 0 auto; }
#appleBtn { display: flex; justify-content: center; margin-top: 8px; }
#appleBtn.hidden { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   AUTH SCREEN ON A SHORT / LANDSCAPE SCREEN

   THE BUG: .authCard is a flex item in a column, so it was allowed to SHRINK
   to fit the viewport — and it carries `overflow: hidden` to clip its own
   glow. The two together silently chop the bottom off the card instead of
   scrolling it. Measured on a 667x375 landscape phone: the card wanted 383px,
   flexbox squashed it to 363, and the missing 20px was the "Skip — play solo"
   link. With Sign in with Apple present (iOS Safari, where it is not hidden)
   that is a further 48px, so the Apple button went too.

   Never shrink it. If it genuinely cannot fit, #authScreen already carries
   overflow-y: auto and will scroll — which is reachable, where clipping is not.
   ══════════════════════════════════════════════════════════════════════════ */
.authCard { flex-shrink: 0; }

@media (max-height: 480px) {
  /* Room to scroll clear of the bottom edge, and the last control not flush
     against it. */
  #authScreen { padding: 6px 0 14px; overscroll-behavior: contain; }
  /* The social buttons are third-party widgets whose innards cannot be
     restyled, so the space comes out of what sits between them. */
  .authOr { margin: 6px 0 6px; }
  #appleBtn { margin-top: 5px; }
}

/* ─── Landscape phone: two columns, not a squashed one ────────────────────

   A phone on its side is the ONLY orientation this game runs in — portrait
   shows "rotate your device" — so this is not an edge case, it is the sign-in
   screen every mobile player sees. It has 375px of height and 700+ of width,
   which is the opposite shape to the card, so the card becomes two columns:
   the brand and the one-tap ways in on the left, the form on the right.

   Both wrappers are `display: contents` outside this query, so every other
   screen keeps the single column it always had.
   ──────────────────────────────────────────────────────────────────────── */
.authForm, .authAlt { display: contents; }

@media (max-height: 480px) and (min-aspect-ratio: 1/1) {
  #authScreen { justify-content: center; padding: 0; }
  .authCard {
    width: min(860px, 94vw);
    padding: 20px 30px;
    display: grid;
    grid-template-columns: 0.88fr 1.12fr;
    grid-template-rows: auto auto 1fr;
    column-gap: 34px;
    align-content: center;
  }

  /* LEFT — identity, then the one-tap ways in. */
  .authCard > .authBrand { grid-column: 1; grid-row: 1; }
  .authBrand .brandLogo { max-width: min(228px, 30vw); }
  .authCard > .authSub {
    grid-column: 1; grid-row: 2;
    font-size: 9.5px; line-height: 1.5; margin: 8px 0 16px;
    max-width: 30ch; margin-left: auto; margin-right: auto;
  }
  .authCard > .authAlt {
    grid-column: 1; grid-row: 3;
    display: flex; flex-direction: column; gap: 9px;
    align-self: start;
  }

  /* RIGHT — the form, centred against the whole left column. A hairline
     between them so the two halves read as one card rather than two. */
  .authCard > .authForm {
    grid-column: 2; grid-row: 1 / -1;
    display: flex; flex-direction: column; justify-content: center;
    padding-left: 34px;
    border-left: 1px solid rgba(120, 175, 240, .16);
  }

  /* Side by side, "or" is not dividing anything — the columns are. */
  .authOr { display: none !important; }
  #appleBtn { margin-top: 0; }
  .authGuest { margin-top: 2px; font-size: 10px; }

  /* Breathing room inside the form: it has the whole column height now, so
     it does not need to be squeezed the way the one-column version did. */
  .authTabs { margin-bottom: 10px; }
  /* At the narrow end of landscape (667px on an older phone) the right column
     is about 290px and "CREATE ACCOUNT" wrapped onto two lines, which shoved
     the tab row out of line with the other two. Never wrap a tab label. */
  .authTab { white-space: nowrap; font-size: 8px; letter-spacing: .04em; padding: 7px 4px; }
  .authField { margin-bottom: 7px; }
  .authField input { padding: 8px 11px; font-size: 12px; }
  .authField > span { font-size: 8px; margin-bottom: 3px; }
  .authHint { margin: -2px 0 6px; }
  .authGo { padding: 10px 0; font-size: 11px; }
  #authMsg { margin-top: 6px; }
}

/* An empty error line should not reserve 24px of card. It sits directly under
   the submit button now (errors belong with the thing that caused them), which
   put a visible hole between LAUNCH and the divider below it whenever there was
   nothing wrong — which is almost always. */
#authMsg:empty { min-height: 0; margin-top: 0; }

/* A coaching tip that highlights a control steps down out of the corner, so
   it never covers the button it is pointing at. The HUD toggle is at top:8px
   and is 32px tall, so 48px clears it with room. */
#coachTip.coachClear { top: 48px; }
@media (max-width: 900px), (pointer: coarse) {
  #coachTip.coachClear { top: 46px; right: 8px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   DAILY CHECK-IN — the framed version

   The old dialog was a plain clipped-corner box: flat tiles, a flat gold bar,
   nothing holding it together. This is the same information inside a proper
   bracketed frame — corner irons, a lit rule under the title, day tiles as
   individual panels, and a claim bar with bevelled ends that reads as a
   control rather than a rectangle.
   ══════════════════════════════════════════════════════════════════════════ */
#checkinBox {
  position: relative;
  width: min(760px, 94vw);
  padding: 30px 34px 22px;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(28, 66, 104, .55), transparent 70%),
    linear-gradient(178deg, rgba(10, 24, 42, .98), rgba(5, 12, 22, .99));
  border: 1px solid rgba(90, 180, 240, .55);
  border-radius: 10px;
  /* The clip-path notch is replaced by real corner irons below, which read as
     hardware rather than as a cut corner. */
  clip-path: none;
  box-shadow: 0 22px 70px rgba(0, 0, 0, .75), inset 0 1px 0 rgba(150, 215, 255, .18);
}
/* Corner irons: four L-brackets, drawn as two layered gradients per corner. */
#checkinBox::before,
#checkinBox::after {
  content: ''; position: absolute; pointer-events: none;
  width: 30px; height: 30px;
  border: 2px solid rgba(120, 205, 255, .85);
}
#checkinBox::before { top: 7px; left: 7px; border-right: 0; border-bottom: 0; border-radius: 6px 0 0 0; }
#checkinBox::after { bottom: 7px; right: 7px; border-left: 0; border-top: 0; border-radius: 0 0 6px 0; }
.ciFrame { position: absolute; inset: 0; pointer-events: none; }
.ciFrame::before,
.ciFrame::after {
  content: ''; position: absolute;
  width: 30px; height: 30px;
  border: 2px solid rgba(120, 205, 255, .85);
}
.ciFrame::before { top: 7px; right: 7px; border-left: 0; border-bottom: 0; border-radius: 0 6px 0 0; }
.ciFrame::after { bottom: 7px; left: 7px; border-right: 0; border-top: 0; border-radius: 0 0 0 6px; }
/* The diamond studs top and bottom centre, as in the reference. */
.ciStud {
  position: absolute; left: 50%; width: 12px; height: 12px;
  margin-left: -6px; transform: rotate(45deg);
  background: #7fd4ff; box-shadow: 0 0 12px rgba(127, 212, 255, .9);
}
.ciStud.top { top: -6px; }
.ciStud.bottom { bottom: -6px; }

.ciTitle {
  font-size: 30px; font-weight: 700; letter-spacing: 7px;
  color: #eaf6ff;
  text-shadow: 0 0 22px rgba(120, 200, 255, .55), 0 2px 0 rgba(0, 0, 0, .5);
}
.ciSub { margin: 10px 0 22px; font-size: 14px; color: #9fc4e2; letter-spacing: .2px; }

.ciLadder { display: flex; gap: 10px; justify-content: center; margin-bottom: 22px; }
.ciDay {
  flex: 1 1 0; min-width: 0; padding: 14px 6px 16px;
  border: 1px solid rgba(90, 165, 220, .38);
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(16, 38, 62, .9), rgba(9, 20, 36, .95));
}
.ciDay em {
  display: block; font-style: normal;
  font-size: 11px; letter-spacing: 1.4px; font-weight: 600; color: #8fb6d6;
}
.ciDay b {
  display: block; margin-top: 9px;
  font-size: 20px; font-weight: 700; color: #eaf6ff;
  white-space: nowrap;
}
/* The ship rung. Long word, so it sizes to fit rather than overflowing. */
.ciDay b.ciShip { font-size: 13px; letter-spacing: .5px; color: #9fe8ff; }
.ciDay.done { border-color: rgba(90, 200, 130, .5); background: linear-gradient(180deg, rgba(18, 50, 32, .9), rgba(9, 28, 18, .95)); }
.ciDay.done b { color: #7fe0a0; }
.ciDay.today {
  border-color: #ffcf5e;
  background: linear-gradient(180deg, rgba(70, 52, 12, .95), rgba(34, 24, 6, .97));
  box-shadow: 0 0 26px rgba(255, 200, 60, .45), inset 0 0 18px rgba(255, 190, 60, .12);
}
.ciDay.today b { color: #ffd77e; }
/* Marker above today's rung, the little caret in the reference. */
.ciDay.today::before {
  content: ''; position: absolute; margin-top: -26px; margin-left: -6px;
  border: 6px solid transparent; border-top-color: #ffcf5e;
}
.ciDay { position: relative; }

.ciClaim {
  width: 100%; padding: 17px 0;
  font-family: inherit; font-size: 20px; font-weight: 700; letter-spacing: 6px;
  color: #2a1a02; text-transform: uppercase;
  background: linear-gradient(180deg, #ffe08a 0%, #f7c23f 45%, #e0a021 62%, #f5cd60 100%);
  border: 1px solid #ffeeb4;
  border-radius: 4px;
  /* Bevelled ends, as in the reference — a control, not a rectangle. */
  clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 18px 100%, 0 50%);
  box-shadow: 0 0 30px rgba(255, 190, 60, .45), inset 0 -2px 0 rgba(0, 0, 0, .18);
  cursor: pointer;
}
.ciClaim:hover { filter: brightness(1.06); }
.ciLater { margin-top: 14px; font-size: 13px; letter-spacing: 1.5px; }

@media (max-width: 700px), (max-height: 480px) {
  #checkinBox { padding: 18px 16px 14px; }
  .ciTitle { font-size: 19px; letter-spacing: 4px; }
  .ciSub { font-size: 11px; margin: 6px 0 14px; }
  .ciLadder { gap: 5px; margin-bottom: 14px; }
  .ciDay { padding: 9px 3px 10px; }
  .ciDay em { font-size: 8.5px; letter-spacing: .8px; }
  .ciDay b { font-size: 14px; margin-top: 5px; }
  .ciDay b.ciShip { font-size: 9.5px; }
  .ciClaim { padding: 12px 0; font-size: 14px; letter-spacing: 4px; }
  .ciLater { margin-top: 8px; font-size: 11px; }
}

/* The turning hull on the day-8 rung. Sized in CSS; the preview reads the
   box's pixel size and renders to match, so it stays sharp on a phone. */
.ciShipArt {
  display: block; width: 100%; aspect-ratio: 1; margin: 4px 0 2px;
  border-radius: 6px;
  background: radial-gradient(circle at 50% 45%, rgba(40, 90, 140, .5), rgba(4, 10, 18, .85));
}
.ciShipArt canvas { display: block; width: 100%; height: 100%; }
/* Inside a tile it is decoration, not a control -- the drag-to-rotate the
   inspector brings with it would only steal the click meant for CLAIM. */
.ciShipArt canvas { pointer-events: none; }
.ciDay.prize b.ciShip { margin-top: 2px; }

/* iOS camera housing -- see the note beside #minimapPanel in hud.css. Left
   edge only, iOS only; every other platform keeps the plain 8px corner. */
body.touch.iosApp #tutBox { left: calc(8px + env(safe-area-inset-left, 0px)); }

/* THE CHECK-IN DIALOG ON A SHORT VIEWPORT.

   Everything above is sized for a desktop window: a 760px box, 30px title,
   30px of padding and 14px on every rung. A phone in landscape is 390px TALL,
   so the same dialog fills the screen edge to edge and reads as a wall --
   and day 8 makes it eight rungs, not seven.

   Keyed on height rather than width, because that is the axis that runs out:
   a landscape phone is wide and short, and a width query would miss it. */
@media (max-height: 560px) {
  #checkinBox { width: min(660px, 92vw); padding: 12px 16px 10px; border-radius: 8px; }
  .ciTitle { font-size: 17px; letter-spacing: 4px; }
  .ciSub { margin: 5px 0 10px; font-size: 11px; }
  .ciLadder { gap: 4px; margin-bottom: 10px; }
  .ciDay { padding: 6px 2px 7px; border-radius: 6px; }
  .ciDay em { font-size: 8px; letter-spacing: .6px; }
  .ciDay b { margin-top: 3px; font-size: 13px; }
  .ciDay b.ciShip { font-size: 9px; letter-spacing: .2px; }
  /* The caret above today rides on a margin, so it has to shrink with it. */
  .ciDay.today::before { margin-top: -17px; border-width: 5px; }
  .ciClaim { padding: 10px 0; font-size: 15px; letter-spacing: 4px; }
  .ciLater { margin-top: 6px; font-size: 11px; }
  .ciFrame::before, .ciFrame::after { width: 18px; height: 18px; }
  .ciStud { width: 9px; height: 9px; margin-left: -4.5px; }
  /* The spinning hull on the day-8 rung: a square tile is the tallest thing
     in the ladder, so it is what decides the dialog height. */
  .ciShipArt { max-height: 40px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   TRAINING MUST NOT COVER THE TRACKPAD

   #tutBox is pinned at top:56px and grows downward with its text; #moveStick
   is 132px tall, 14px off the bottom. On a short screen -- a landscape
   handset, or the steering step, which is the tallest card in the run because
   it carries two choice buttons -- the card grew far enough down to sit on
   top of the trackpad. The player was then asked to choose the trackpad
   through the panel covering it.

   Capped to the room above the stick instead, and scrolled if the text needs
   more. dvh, not vh: mobile Safari's vh is the tall unit that ignores its own
   toolbars, so a vh cap would still overlap once the bar is showing.
   ══════════════════════════════════════════════════════════════════════════ */
@media (pointer: coarse) {
  #tutBox {
    max-height: calc(100vh - 56px - 132px - 34px);
    max-height: calc(100dvh - 56px - 132px - 34px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}


}

/* Daily supply deck: eight real reward cards, with a single active claim. */
#checkinModal{background:linear-gradient(#02061088,#020610bb),url('backgrounds/bg4.jpg') center/cover;backdrop-filter:blur(5px);padding:20px;box-sizing:border-box}
#checkinBox{width:min(1340px,96vw);max-height:92dvh;overflow:auto;box-sizing:border-box;padding:38px 30px 25px;text-align:left;border-radius:2px;border:1px solid #5683a4;background:linear-gradient(125deg,#08131fed,#030912f5 65%,#0c1b2aed);box-shadow:0 25px 100px #000c,inset 0 0 65px #142e4733}
#checkinBox .ciEyebrow{font-size:10px;letter-spacing:4px;color:#648ba8;margin:0 0 12px}
#checkinBox .ciTitle{font-size:clamp(24px,3.2vw,46px);letter-spacing:7px;line-height:1.1;color:#e0f4ff;text-shadow:0 0 22px #4d9ac96b}
#checkinBox .ciSub{font-size:13px;letter-spacing:3px;text-transform:uppercase;color:#81abc8;margin:14px 0 36px}
#checkinBox .ciLater{position:absolute;right:14px;top:10px;margin:0;width:44px;height:44px;border:1px solid #50749366;background:#08131f;color:#adcce2;border-radius:3px;font-size:26px;line-height:1;cursor:pointer}
#checkinBox .ciLadder{display:grid;grid-template-columns:repeat(8,minmax(0,1fr));gap:12px;margin:0 0 26px;flex-wrap:nowrap}
#checkinBox .ciDay{display:flex;flex-direction:column;align-items:center;min-width:0;padding:20px 7px 0;border:1px solid #426782;border-radius:0;background:linear-gradient(145deg,#0c1e2d 0%,#030910 55%,#0b1824);text-align:center;box-shadow:inset 0 1px #abcfe222;clip-path:polygon(10px 0,calc(100% - 10px) 0,100% 10px,100% calc(100% - 10px),calc(100% - 10px) 100%,10px 100%,0 calc(100% - 10px),0 10px)}
#checkinBox .ciDay em{color:#9adfff;font-size:16px;letter-spacing:2px;font-weight:700}
#checkinBox .ciRewardArt{width:100%;height:auto;aspect-ratio:1;max-height:none;margin:14px 0 2px;display:block;border:0;background-color:transparent;pointer-events:none}
#checkinBox .ciLoot{background-image:url('icons/daily-rewards.png');background-size:300% 100%;background-repeat:no-repeat;transform:scale(var(--loot-scale,1));filter:drop-shadow(0 5px 9px #000)}
#checkinBox .ciLootCrystal{background-position:0 50%}#checkinBox .ciLootBlue{background-position:50% 50%}#checkinBox .ciLootGold{background-position:100% 50%}
#checkinBox .ciShipArt{background:radial-gradient(ellipse,#7542d52b,transparent 70%);overflow:hidden}
#checkinBox .ciShipArt img{width:100%;height:100%;object-fit:contain;transform:scale(1.45);filter:brightness(1.18)}
#checkinBox .ciDay b{font-size:25px;color:#9be2ff;line-height:1.2;margin:3px 0 0}
#checkinBox .ciDay b.ciShip{font-size:17px;letter-spacing:.3px}
#checkinBox .ciRewardKind{font-size:8px;letter-spacing:1px;color:#6994b1;min-height:24px;display:flex;align-items:center;justify-content:center}
#checkinBox .ciCardAction{width:calc(100% + 14px);height:49px;margin-top:12px;display:flex;align-items:center;justify-content:center;border-top:1px solid #284459;background:linear-gradient(#102131,#08121c);color:#557c9c;font-size:11px;font-weight:bold;letter-spacing:1.2px}
#checkinBox .ciDay.done{border-color:#3b5b73;background:linear-gradient(145deg,#112537,#050b13)}
#checkinBox .ciDay.done .ciCardAction{color:#6a9ab9}
#checkinBox .ciDay.today{border-color:#ffd575;background:radial-gradient(ellipse at 50% 40%,#65501a55,transparent 80%),linear-gradient(#302310,#0c0c0d);box-shadow:inset 0 0 22px #ffbb332b,0 0 22px #dfac4359}
#checkinBox .ciDay.today em,#checkinBox .ciDay.today b{color:#ffd780}
#checkinBox .ciDay.today::before{content:none}
#checkinBox .ciDay.today .ciRewardKind{color:#c6a56a}
#checkinBox .ciClaim{width:100%;height:100%;padding:0 4px;border:0;border-radius:0;clip-path:none;font-size:16px;letter-spacing:2px;color:#271800;background:linear-gradient(#ffe497,#eeb33c);box-shadow:inset 0 1px #fff2c3}
#checkinBox .ciClaim:disabled{opacity:.6;cursor:wait}
#checkinBox .ciClaim[hidden]{display:none}
#checkinBox .ciFooter{display:flex;align-items:center;justify-content:space-between;gap:24px;border-top:1px solid #3c62774d;padding-top:21px}
#checkinBox .ciStreakBadge{display:flex;align-items:center;gap:14px;color:#a5ceee}
#checkinBox .ciStreakBadge>span{font-size:34px;color:#77b6e1}
#checkinBox .ciStreakBadge strong{font-size:14px;letter-spacing:2px;display:block}
#checkinBox .ciStreakBadge small{display:block;color:#5f93b7;font-size:9px;letter-spacing:2px;margin-top:6px}
#checkinBox #ciStatus{max-width:340px;color:#8faec4;font-size:12px;line-height:1.6;margin:0;text-align:right}
#checkinBox #ciActions:empty{display:none}
@media(max-width:900px) and (min-height:601px){#checkinBox .ciLadder{grid-template-columns:repeat(4,minmax(0,1fr))}#checkinBox .ciRewardArt{max-height:125px}#checkinBox .ciSub{margin-bottom:24px}}
@media(max-height:600px){#checkinModal{padding:8px}#checkinBox{padding:18px 20px 12px;width:97vw;max-height:96dvh}#checkinBox .ciEyebrow{font-size:8px;margin-bottom:7px}#checkinBox .ciTitle{font-size:24px;letter-spacing:4px}#checkinBox .ciSub{font-size:10px;letter-spacing:1.5px;margin:8px 0 12px}#checkinBox .ciLadder{gap:7px;margin-bottom:13px}#checkinBox .ciDay{padding:12px 4px 0}#checkinBox .ciDay em{font-size:11px;letter-spacing:1px}#checkinBox .ciRewardArt{margin:5px 0 0;max-height:min(75px,18dvh)}#checkinBox .ciDay b{font-size:18px}#checkinBox .ciDay b.ciShip{font-size:11px}#checkinBox .ciRewardKind{font-size:6px;letter-spacing:.3px;min-height:19px}#checkinBox .ciCardAction{height:44px;margin-top:5px;width:calc(100% + 8px);font-size:8px;letter-spacing:.5px}#checkinBox .ciClaim{font-size:12px;letter-spacing:1px}#checkinBox .ciFooter{padding-top:9px;gap:12px}#checkinBox .ciStreakBadge strong{font-size:11px}#checkinBox .ciStreakBadge small{font-size:7px}#checkinBox #ciStatus{font-size:10px}#checkinBox .ciLater{top:8px}}
@media(max-width:480px) and (min-height:601px){#checkinBox{padding:25px 14px 18px}#checkinBox .ciTitle{font-size:23px;letter-spacing:3px}#checkinBox .ciEyebrow{font-size:7px;letter-spacing:2px}#checkinBox .ciSub{font-size:9px;letter-spacing:1px}#checkinBox .ciLadder{gap:7px}#checkinBox .ciDay{padding:12px 3px 0}#checkinBox .ciDay em{font-size:11px}#checkinBox .ciDay b{font-size:18px}#checkinBox .ciDay b.ciShip{font-size:10px}#checkinBox .ciRewardArt{margin-top:8px}#checkinBox .ciRewardKind{font-size:6px;letter-spacing:0}#checkinBox .ciCardAction{height:44px;font-size:8px;letter-spacing:0;width:calc(100% + 6px)}#checkinBox .ciClaim{font-size:11px}#checkinBox .ciFooter{display:block}#checkinBox #ciStatus{text-align:left;margin-top:12px;font-size:11px}}
/* Player settings: one viewport-bounded scroll surface at every screen size. */
body.playerSettings #adminPanel {
  display: block; left: auto; right: 0; top: 0; bottom: auto;
  width: min(520px, 100%); height: 100vh; height: 100dvh;
  box-sizing: border-box; overflow-y: auto; overflow-x: hidden;
  padding: 0 max(0px, env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) max(0px, env(safe-area-inset-left));
  background: #081321; box-shadow: -24px 0 80px #0009;
  overscroll-behavior: contain; touch-action: pan-y; -webkit-overflow-scrolling: touch;
  scrollbar-gutter: stable;
}
body.playerSettings #admHead {
  position: sticky; top: 0; z-index: 5; background: #0c1b2c;
  padding: calc(12px + env(safe-area-inset-top)) 20px 12px;
}
body.playerSettings #admHead span::after { content: 'SETTINGS'; font-size: 16px; }
body.playerSettings #admHead button { min-width: 44px; min-height: 44px; }
body.playerSettings #admActions { padding: 16px 20px; border: 0; }
body.playerSettings #admActions button, body.playerSettings #admAccount button { min-height: 44px; padding: 10px 16px; font-size: 14px; }
body.playerSettings #admAccount { margin: 0 20px 16px; padding: 16px; background: #101e30; border: 1px solid #29415a; border-radius: 12px; }
body.playerSettings #acctStatus:empty { display: none; }
body.playerSettings #admPlayer { padding: 0 20px; }
body.playerSettings #admPlayer::before { display: none; }
.settingsSection { margin: 0 0 12px; padding: 0 16px; background: #101e30; border: 1px solid #29415a; border-radius: 12px; }
.settingsSection > summary { min-height: 48px; padding: 15px 0; box-sizing: border-box; cursor: pointer; color: #87d7ff; font-size: 14px; font-weight: 700; letter-spacing: .5px; }
.settingsSection .profSetting, #admPlayer .settingsSection .profSetting, #admPlayerRows .settingsSection .profSetting {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: 56px; padding: 10px 0; box-sizing: border-box;
  font-size: 14px; line-height: 1.45; color: #d5e5f3; border-bottom: 1px solid #26394e;
}
.settingsSection .profSetting:last-child { border-bottom: 0 !important; }
.settingsSection .profSetting > span { flex: 1; min-width: 0; }
.settingsSection select { width: 48%; min-width: 0; max-width: 100%; min-height: 44px; padding: 8px; background: #071321; color: #e2f3ff; border: 1px solid #43627e; border-radius: 7px; font: inherit; }
.settingsSection input[type=range], #admPlayer .settingsSection input[type=range] { width: 48%; min-width: 0; height: 44px; accent-color: #52c6ff; }
.settingsSection input[type=checkbox] { flex: 0 0 44px; width: 44px; height: 28px; accent-color: #44bfff; cursor: pointer; }
.settingsSection .profSegment { flex-shrink: 0; }
.settingsSection .profSegment button { min-height: 44px; font-size: 13px; padding: 8px 12px; }
.settingsSection :focus-visible { outline: 2px solid #84dcff; outline-offset: 3px; }
#profileScreen .profCard { max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); touch-action: pan-y; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
@media (max-width: 540px) {
  body.playerSettings #adminPanel { width: 100%; }
  body.playerSettings #admPlayer { padding: 0 12px; }
  body.playerSettings #admAccount { margin-left: 12px; margin-right: 12px; }
  .settingsSection { padding: 0 12px; }
  .settingsSection .profSetting:has(select), .settingsSection .profSetting:has(.profSegment), #admPlayer .settingsSection .profSetting:has(select), #admPlayer .settingsSection .profSetting:has(.profSegment) { flex-wrap: wrap; gap: 8px; }
  .settingsSection .profSetting:has(select) > span, .settingsSection .profSetting:has(.profSegment) > span { flex-basis: 100%; }
  .settingsSection select { width: 100%; }
}

#sovereignGuide{position:fixed;z-index:950;top:max(76px,env(safe-area-inset-top));left:max(16px,env(safe-area-inset-left));width:min(340px,calc(100vw - 32px));box-sizing:border-box;max-height:calc(100dvh - 100px);overflow:auto;padding:18px;background:#081727;border:1px solid #42c9f4;border-radius:12px;color:#cceaff;box-shadow:0 8px 32px #0009;font:14px/1.5 system-ui}#sovereignGuide h3{font-size:15px;color:#69dcff;margin:0 0 10px}#sovereignGuide ul{padding-left:20px}#sovereignGuide li{margin:8px 0}#sovereignGuide button{min-height:44px;width:100%;border:1px solid #45bbdf;border-radius:7px;background:#16405b;color:white;font:inherit;cursor:pointer}

/* ── Lobby pilot card ─────────────────────────────────────────────────────
   Every roster seat opens a card on hover: portrait, rating, rank, record.
   Reuses .lbCard from the in-match leaderboard so the two read the same.
   The row is the positioning context; the card hangs off its right edge on
   desktop and drops below it on a phone, where there is no room beside. */
.lobP { position: relative; cursor: default; }
.lobP:hover .lobCard, .lobP.lbOpen .lobCard { display: block; }
.lobP .lobCard {
  /* Viewport-anchored, placed by bindLobbyCards -- see the comment there.
     The absolute/left:100% it inherits from .lbCard put it outside the
     scrolling fleet list, where it was clipped. */
  position: fixed;
  left: 0; top: 0; right: auto; margin: 0;
  min-width: 190px;
  max-width: 240px;
  z-index: 60;
  white-space: normal;
  pointer-events: auto;
  cursor: default;
}
.lobAvatar {
  display: block;
  width: 56px; height: 56px;
  margin-bottom: 8px;
  border-radius: 6px;
  object-fit: cover;
  background: rgba(20, 40, 66, .6);
  border: 1px solid rgba(120, 200, 255, .25);
}
/* No portrait uploaded, or not fetched yet: the slot still holds its shape so
   the card does not jump when the image lands. */
.lobAvatar:not([src]) { visibility: visible; }
.lobRenameForm {
  display: grid;
  grid-template-columns: 1fr;
  gap: 5px;
  margin-top: 9px;
  padding-top: 8px;
  border-top: 1px solid rgba(120, 200, 255, .18);
}
.lobRenameInput {
  min-width: 0;
  width: 100%;
  box-sizing: border-box;
  padding: 7px 8px;
  color: #eaf6ff;
  background: rgba(0, 0, 0, .38);
  border: 1px solid rgba(120, 200, 255, .32);
  border-radius: 5px;
  font: 11px/1.2 inherit;
}
.lobRenameGo {
  padding: 7px 8px;
  color: #bdeaff;
  background: rgba(32, 92, 135, .55);
  border: 1px solid rgba(120, 210, 255, .38);
  border-radius: 5px;
  font-size: 9px;
  letter-spacing: 1px;
}
.lobRenameGo:disabled { opacity: .55; }
.lobRenameMsg { min-height: 12px; color: #8ba6bd; font-size: 9px; }
.lobRenameMsg.good { color: #6aff8a; }
.lobRenameMsg.bad { color: #ff9a8a; }
/* Results must scroll from the top on short landscape screens. */
#endScreen{justify-content:flex-start;overflow-y:auto;overscroll-behavior:contain;box-sizing:border-box;padding:24px 12px max(24px,env(safe-area-inset-bottom));}
#endScreen>*{flex-shrink:0}#endScreen #endTitle{margin-top:0}
#endGrad{position:fixed;inset:0;margin:auto;box-sizing:border-box;width:min(580px,calc(100vw - 28px));max-height:calc(100dvh - 28px);overflow:auto;padding:24px;z-index:100;color:#ffe4ac}
#endGrad::backdrop{background:#020711c9;backdrop-filter:blur(4px)}
#endGrad .endGradRow{flex-wrap:wrap}#endGrad button{padding:12px 20px}
@media(max-height:500px){#endGrad{padding:16px}.endGradHead{font-size:22px}.endGradBody{font-size:14px;margin:10px 0}#endScreen{padding-top:14px}}
.founderName:before,.founderBadge{content:'';display:inline-block;width:24px;height:26px;vertical-align:middle;background:url('icons/founder-first-fleet.svg') center/contain no-repeat;margin-right:6px;filter:drop-shadow(0 0 4px #e3ac4255)}
.founderReveal{position:fixed;inset:0;margin:auto;width:min(680px,95vw);max-height:94dvh;overflow:auto;box-sizing:border-box;padding:26px;text-align:center;color:#f6e5be;border:1px solid #d6b774;border-radius:12px;background:radial-gradient(ellipse at top,#334052,#071322 65%);box-shadow:0 0 90px #dcad4a33;font-family:Rajdhani,sans-serif}.founderReveal::backdrop{background:#010811dd;backdrop-filter:blur(6px)}.founderCrest{width:120px;height:120px;filter:drop-shadow(0 0 24px #f8c65e77);animation:founderArrive 1s both}.founderReveal small{display:block;letter-spacing:3px;color:#bda877}.founderReveal h2{font-size:34px;line-height:1.1;letter-spacing:4px;margin:15px 0;text-shadow:0 0 24px #dda84155}.founderLoot{display:flex;gap:12px;margin:24px 0}.founderLoot b{flex:1;padding:16px 8px;background:#03101a88;border:1px solid #ad935b66;animation:founderArrive .7s .3s both}.founderLoot b:nth-child(2){animation-delay:.5s}.founderLoot b:nth-child(3){animation-delay:.7s}.founderLoot small{font-size:12px;letter-spacing:0;margin-top:6px}.founderReveal button{font:700 17px Rajdhani,sans-serif;padding:13px 24px;margin:5px;border:1px solid #eed28c;border-radius:5px;background:linear-gradient(#eac779,#a88138);color:#131820;cursor:pointer}.founderReveal [data-later]{background:#0c1b2a;color:#ddcfac}.founderStatus{font-size:13px}@keyframes founderArrive{from{opacity:0;transform:translateY(16px) scale(.8)}to{opacity:1;transform:none}}@media(max-height:500px){.founderReveal{padding:12px}.founderCrest{width:65px;height:65px}.founderReveal h2{font-size:23px;margin:8px}.founderLoot{margin:10px 0}.founderReveal p{margin:5px}}@media(prefers-reduced-motion:reduce){.founderReveal *{animation:none!important}}
