/* ==========================================================================
   STAR RUMBLE — interface
   One chunky, high-contrast, unmistakably-a-party-game look.
   Everything is sized in clamp() so it survives a phone and a 4K TV.
   ========================================================================== */

/* Pixeloid Sans — GGBotNet, SIL OFL 1.1. Bitmap-clean at small sizes;
   legible down to a 520p internal buffer. See assets/fonts/PIXELOID-LICENSE.txt */
@font-face{
  font-family:'Pixeloid Sans';
  src:url('/assets/fonts/PixeloidSans.woff2') format('woff2'),
      url('/assets/fonts/PixeloidSans.woff') format('woff');
  font-weight:400; font-style:normal; font-display:block;
}
@font-face{
  font-family:'Pixeloid Sans';
  src:url('/assets/fonts/PixeloidSans-Bold.woff2') format('woff2'),
      url('/assets/fonts/PixeloidSans-Bold.woff') format('woff');
  font-weight:700; font-style:normal; font-display:block;
}

:root{
  --void0:#070b18; --void1:#0e1428; --void2:#161e3a;
  --panel:rgba(14,20,42,.86);
  --panel-2:rgba(22,30,60,.92);
  --line:#2b3a63;
  --line-hot:#7cc0ff;
  --text:#f2f6ff; --dim:#96a3c8; --dimmer:#5f6c90;
  --gold:#ffd34d; --gold-deep:#c78a12;
  --coin:#ffc02e; --danger:#ff4d5a; --good:#6ddf3c; --accent:#7cc0ff;
  --p0:#ff4d5a; --p1:#36a9ff; --p2:#6ddf3c; --p3:#ffc02e;
  --p4:#c46bff; --p5:#1fd6c4; --p6:#ff8a3d; --p7:#ff6fc3;
  --ui: 'Pixeloid Sans', ui-monospace, 'Courier New', monospace;
  --mono: 'Pixeloid Sans', ui-monospace, monospace;
  --r: 0px;
  --shadow: 6px 6px 0 rgba(0,0,0,.7);
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

*{ box-sizing:border-box; margin:0; padding:0; -webkit-tap-highlight-color:transparent; }
html,body{ height:100%; overflow:hidden; background:var(--void0); }
body{
  font-family:var(--ui); color:var(--text);
  font-synthesis-weight:none; text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
  touch-action:none; user-select:none;
}
#stage{ position:fixed; inset:0; width:100%; height:100%; display:block; }
.layer{ position:fixed; inset:0; pointer-events:none; z-index:10; }
.hidden{ display:none !important; }
button{ font:inherit; color:inherit; border:0; background:none; cursor:pointer; }

/* ---------------------------------------------------------------- fx layer */
#flash{ position:absolute; inset:0; opacity:0; background:#fff; mix-blend-mode:screen; }
#vignette{
  position:absolute; inset:0;
  background:rgba(3,6,16,.55);
}
#fog{
  position:absolute; inset:0; opacity:0; transition:opacity .4s;
  background:rgba(160,185,255,.86);
}
#fog.on{ opacity:1; }

/* ------------------------------------------------------------------ popups */
.popup{
  position:absolute; left:0; top:0; white-space:nowrap;
  font-weight:700; letter-spacing:.2px;
  text-shadow:0 2px 0 rgba(0,0,0,.65), 0 0 18px currentColor;
  will-change:transform,opacity;
}
.popup.big{ font-weight:700; letter-spacing:-.5px; }
.popup.coin{ color:var(--coin); }

/* --------------------------------------------------------------- wlabels */
/* Persistent world-anchored labels (names over a rig, banners). Hard offset
   shadow, never a glow: the bitmap font has to stay on the pixel grid. */
.wlabel{
  position:absolute; left:0; top:0; white-space:nowrap;
  font-weight:700; letter-spacing:.2px;
  text-shadow:2px 2px 0 rgba(0,0,0,.85);
  will-change:transform;
  pointer-events:none;
}
.wlabel.dim{ opacity:.72; }
.wlabel.big{ letter-spacing:-.5px; }

/* --------------------------------------------------------------------- HUD */
#hud-top{
  position:absolute; top:calc(10px + var(--safe-t)); left:50%; transform:translateX(-50%);
  display:flex; align-items:center; gap:12px;
  padding:7px 9px 7px 7px;
  background:var(--panel); border:2px solid var(--line); border-radius:0;
  box-shadow:var(--shadow);
  max-width:min(94vw,760px);
}
/* Con round-pill, game-title y timer-wrap ocultos ingame, #hud-top quedaría
   como un panel vacío flotando arriba. Se oculta también. Escape hatch:
   #hud.legacy-hud lo vuelve a mostrar junto con sus hijos. */
#hud-top{ visibility:hidden; }
#hud.legacy-hud #hud-top{ visibility:visible; }
#round-pill{
  padding:6px 14px; border-radius:0; font-size:clamp(11px,1.5vw,13px);
  font-weight:600; letter-spacing:.10em; white-space:nowrap;
  background:rgba(124,192,255,.20);
  border:2px solid rgba(124,192,255,.65); color:#cfe6ff;
  /* Spanish round labels run ~20% longer than the English ones. Truncate
     rather than shove the game title and the timer out of the bar. */
  min-width:0; max-width:min(48vw,360px); overflow:hidden; text-overflow:ellipsis;
}
/* Julio no quiere la píldora de ronda ingame: se oculta con visibility (no
   display:none ni se saca del DOM) porque main.js sigue leyendo #round-label
   para telemetría. Escape hatch: #hud.legacy-hud la vuelve a mostrar. */
/* Vuelta a mostrar (Julio, 15-sep-2026: "siempre muestra en qué ronda estamos"). */
#round-pill{ visibility:visible; }
#hud.legacy-hud #round-pill{ visibility:visible; }
#round-pill.star{
  background:rgba(255,211,77,.28);
  border-color:rgba(255,211,77,.55); color:var(--gold);
  animation:pulseGold 1.6s ease-in-out infinite;
}
@keyframes pulseGold{ 50%{ box-shadow:0 0 22px rgba(255,211,77,.45);} }

#game-title{
  font-size:clamp(13px,1.9vw,17px); font-weight:600; letter-spacing:.01em; white-space:nowrap;
  min-width:0; overflow:hidden; text-overflow:ellipsis;
}
/* Julio no quiere el nombre del juego ingame: se oculta con visibility (no
   display:none ni se saca del DOM) porque main.js sigue leyendo #game-title
   para telemetría. Escape hatch: #hud.legacy-hud lo vuelve a mostrar. */
#game-title{ visibility:hidden; }
#hud.legacy-hud #game-title{ visibility:visible; }

#timer-wrap{ position:relative; width:44px; height:44px; flex:0 0 auto; }
#timer-ring{ width:44px; height:44px; transform:rotate(-90deg); }
#timer-ring circle{ fill:none; stroke-width:4; stroke-linecap:round; }
.tr-bg{ stroke:rgba(255,255,255,.10); }
.tr-fg{ stroke:var(--accent); stroke-dasharray:119.4; stroke-dashoffset:0; transition:stroke .3s; }
#timer-wrap.warn .tr-fg{ stroke:var(--danger); }
#timer-num{
  position:absolute; inset:0; display:grid; place-items:center;
  font-family:var(--mono); font-size:15px; font-weight:700;
}
#timer-wrap.warn #timer-num{ color:var(--danger); animation:tick .5s steps(2) infinite; }
@keyframes tick{ 50%{ transform:scale(1.14);} }
/* El HUD nuevo (ui/ingamehud.css) ya dibuja su propio anillo y su propio
   número: este timer viejo se oculta con visibility (no display:none ni se
   saca del DOM) para no romper los selectores que main.js sigue leyendo para
   telemetría. Escape hatch: #hud.legacy-hud lo vuelve a mostrar. */
#timer-wrap{ visibility:hidden; }
#hud.legacy-hud #timer-wrap{ visibility:visible; }

/* ---------------------------------------------------------------- leaderboard
   TOP-LEFT, and compact enough that eight rows never reach the middle of the
   frame. It tucks under the round pill on narrow viewports and rides up beside
   it once there is room, so it never collides with the pill or the game title. */
#rail{
  position:absolute; left:10px; top:calc(58px + var(--safe-t));
  display:flex; flex-direction:column; gap:4px;
  width:clamp(138px,15vw,188px);
}
@media (min-width:1240px){ #rail{ top:calc(10px + var(--safe-t)); } }
/* El HUD nuevo (ui/ingamehud.css) ya pinta la fila de retratos con puntos:
   este rail viejo se oculta con visibility (no display:none ni se saca del
   DOM) para no romper los selectores que main.js sigue leyendo para
   telemetría. Escape hatch: #hud.legacy-hud lo vuelve a mostrar. */
#rail{ visibility:hidden; }
#hud.legacy-hud #rail{ visibility:visible; }
.rail-row{
  display:grid; grid-template-columns:11px 13px 1fr auto; align-items:center; gap:6px;
  padding:4px 8px 4px 7px; border-radius:0;
  background:var(--panel); border:2px solid var(--line);
  border-left:3px solid var(--pc);
  transition:transform .35s cubic-bezier(.2,1.4,.4,1), background .3s, box-shadow .3s;
}
.rail-row.you{
  background:var(--panel-2); border-color:rgba(255,255,255,.34);
  box-shadow:0 0 0 1.5px rgba(255,255,255,.26), 4px 4px 0 rgba(0,0,0,.5);
}
.rail-row.you .rail-name{ font-weight:700; color:#fff; }
.rail-row.you .rail-rank{ color:var(--text); }
.rail-row.lead{ box-shadow:0 0 0 1px rgba(255,211,77,.4), 0 0 22px rgba(255,211,77,.18); }
.rail-row.you.lead{ box-shadow:0 0 0 1.5px rgba(255,211,77,.65), 0 0 26px rgba(255,211,77,.26); }
.rail-row.dead{ opacity:.42; filter:saturate(.35); }
.rail-row.bump{ animation:bump .5s cubic-bezier(.2,1.6,.4,1); }
@keyframes bump{ 0%{transform:scale(1)} 35%{transform:scale(1.075)} 100%{transform:scale(1)} }
.rail-rank{
  font-size:10px; font-weight:700; color:var(--dimmer); text-align:center;
  font-variant-numeric:tabular-nums;
}
.rail-pip{ width:13px; height:13px; border-radius:0; background:var(--pc); box-shadow:0 1px 0 rgba(0,0,0,.35) inset, 0 0 10px var(--pc); }
.rail-name{ font-size:12px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rail-name .bot{ color:var(--dimmer); font-size:9px; margin-left:4px; letter-spacing:.06em; }
.rail-stat{ display:flex; gap:6px; font-size:11px; font-weight:700; font-variant-numeric:tabular-nums; }
.rail-stat .st{ color:var(--gold); }
.rail-stat .co{ color:var(--coin); }
.rail-hex{ position:absolute; }
/* A full table of eight tightens itself instead of growing down the screen. */
#rail[data-n="7"] .rail-row, #rail[data-n="8"] .rail-row{ padding:3px 7px 3px 6px; }
#rail[data-n="7"], #rail[data-n="8"]{ gap:3px; width:clamp(130px,14vw,176px); }
#rail[data-n="7"] .rail-name, #rail[data-n="8"] .rail-name{ font-size:11.5px; }

/* Score pod (own score, big) */
#score-pod{
  position:absolute; right:14px; top:50%; transform:translateY(-50%);
  text-align:right; pointer-events:none;
}
#score-primary{
  font-size:clamp(40px,7vw,74px); font-weight:700; line-height:.92;
  font-variant-numeric:tabular-nums; letter-spacing:-.03em;
  text-shadow:0 4px 0 rgba(0,0,0,.4), 0 0 40px rgba(124,192,255,.35);
}
#score-primary.pop{ animation:scorePop .38s cubic-bezier(.2,1.7,.4,1); }
@keyframes scorePop{ 0%{transform:scale(1)} 40%{transform:scale(1.22)} 100%{transform:scale(1)} }
#score-label{ font-size:12px; letter-spacing:.20em; color:var(--dim); text-transform:uppercase; margin-top:2px; }
#lives{ display:flex; gap:5px; justify-content:flex-end; margin-top:9px; }
.life{ width:15px; height:15px; border-radius:0; background:var(--danger); box-shadow:0 0 12px var(--danger); transition:.3s; }
.life.gone{ background:rgba(255,255,255,.10); box-shadow:none; transform:scale(.72); }

/* Energy / nitro tank — only present when the minigame reports `bar` */
#energy{ margin:10px 0 0 auto; width:clamp(88px,10vw,136px); }
#energy-track{
  height:8px; border-radius:0; overflow:hidden;
  background:rgba(255,255,255,.09); border:2px solid var(--line);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.5);
}
#energy-fill{
  display:block; height:100%; width:0%; border-radius:0;
  background:linear-gradient(90deg,#36a9ff 0%,#36a9ff 55%,#ffd34d 55%,#ffd34d 100%);
  transition:width .1s linear, background .25s, box-shadow .25s;
}
#energy-label{
  margin-top:3px; font-size:9.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--dim); text-align:right;
}
#energy.full #energy-fill{ background:#ffd34d; box-shadow:0 0 14px rgba(255,211,77,.75); }
#energy.full #energy-label{ color:var(--gold); }
#energy.low #energy-fill{ background:#ff4d5a; }

/* Bottom bar */
#hud-bottom{
  position:absolute; left:50%; bottom:calc(10px + var(--safe-b)); transform:translateX(-50%);
  display:flex; flex-direction:column; align-items:center; gap:8px;
}
#loadout{ display:flex; gap:7px; }
.chip{
  display:flex; align-items:center; gap:6px; padding:5px 11px; border-radius:0;
  font-size:12px; font-weight:600; background:var(--panel); border:2px solid var(--line);
}
.chip.boost{ border-color:rgba(109,223,60,.45); color:#bff5a0; }
.chip.hex{ border-color:rgba(255,77,90,.45); color:#ffb3b9; }
/* Ayuda de controles: ARRIBA y centrada, no en el footer (calibrado por Julio
   en el lab /ui/ingame). Se ancla bajo el header y el `right` la mantiene a la
   izquierda del #timer-wrap, que vive pegado al borde derecho: así no se le
   monta encima ni con muchas entradas. El rail ocupa la franja izquierda desde
   los ~58px, por eso el `left` le deja ese ancho libre. */
#controls-hint{
  position:absolute; top:calc(20px + var(--safe-t));
  left:clamp(150px,16vw,200px); right:clamp(150px,16vw,200px);
  display:flex; gap:26px; row-gap:6px; flex-wrap:wrap; justify-content:center;
  font-size:15px; color:var(--text); opacity:.85;
  text-shadow:0 2px 0 #000,0 -2px 0 #000,2px 0 0 #000,-2px 0 0 #000;
}
#controls-hint kbd{
  display:inline-block; min-width:20px; padding:3px 7px; margin-right:4px;
  font-family:var(--ui); font-size:14px; font-weight:700; text-align:center;
  background:rgba(0,0,0,.45); border:2px solid rgba(255,255,255,.75);
  border-bottom-width:2px; border-radius:0; color:#fff; text-shadow:none;
}

/* ----------------------------------------------------------------- overlay */
#overlay{ display:grid; place-items:center; z-index:20; }
#overlay > *{ pointer-events:auto; }
/* El .scrim es absolute; un hermano sin position se pinta DEBAJO de él y el
   scrim se come sus clics (pasó con .pick y .finale). Todo lo que no es scrim
   queda posicionado para pintarse encima en orden de DOM. */
#overlay > :not(.scrim){ position:relative; }

.scrim{ position:absolute; inset:0; background:rgba(4,7,18,.86); }
.card{
  position:relative; width:min(92vw,560px); padding:clamp(20px,3.4vw,34px);
  background:rgba(12,17,36,.98);
  border:2px solid var(--line-hot); border-radius:0; box-shadow:var(--shadow);
  animation:cardIn .5s cubic-bezier(.2,1.3,.3,1) both;
}
@keyframes cardIn{ from{ opacity:0; transform:translateY(26px) scale(.94);} }
.card h1{ font-size:clamp(26px,4.6vw,42px); font-weight:700; line-height:1.04; letter-spacing:-.02em; }
.card h2{ font-size:clamp(17px,2.4vw,22px); font-weight:600; }
.card p{ color:var(--dim); line-height:1.55; font-size:clamp(13px,1.7vw,15px); }
.eyebrow{ font-size:12px; letter-spacing:.24em; text-transform:uppercase; color:var(--accent); font-weight:600; margin-bottom:8px; }

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:13px 26px; border-radius:0; font-size:15px; font-weight:600;
  background:#2749c8;
  box-shadow:0 5px 0 #17307f;
  transition:transform .09s, box-shadow .09s, filter .15s;
}
.btn:hover{ filter:brightness(1.1); }
.btn:active{ transform:translateY(4px); box-shadow:0 1px 0 #17307f; }
.btn.gold{ background:#e2a013; color:#3a2500; box-shadow:0 5px 0 #96650a; }
.btn.gold:active{ box-shadow:0 1px 0 #96650a; }
.btn.ghost{ background:rgba(255,255,255,.07); border:2px solid var(--line); box-shadow:none; }
.btn.ghost:active{ transform:translateY(2px); }
.btn[disabled]{ opacity:.4; pointer-events:none; filter:grayscale(.7); }

/* -------------------------------------------------------------- toasts */
#toasts{
  position:fixed; top:calc(70px + var(--safe-t)); left:50%; transform:translateX(-50%);
  display:flex; flex-direction:column; gap:6px; align-items:center; z-index:30; pointer-events:none;
}
.toast{
  padding:8px 16px; border-radius:0; font-size:13px; font-weight:600;
  background:var(--panel-2); border:2px solid var(--line);
  animation:toastIn .35s cubic-bezier(.2,1.4,.4,1) both;
  box-shadow:var(--shadow);
}
.toast.star{ border-color:rgba(255,211,77,.55); color:var(--gold); }
.toast.hex{ border-color:rgba(255,77,90,.5); color:#ffb3b9; }
@keyframes toastIn{ from{ opacity:0; transform:translateY(-12px) scale(.9);} }
.toast.out{ animation:toastOut .3s ease-in forwards; }
@keyframes toastOut{ to{ opacity:0; transform:translateY(-8px) scale(.94);} }

/* ------------------------------------------------------------- netstat */
#netstat{
  position:fixed; right:10px; top:calc(10px + var(--safe-t)); z-index:30;
  display:flex; gap:8px;
  font-family:var(--mono); font-size:11px; color:var(--dimmer);
  padding:4px 9px; border-radius:0; background:rgba(10,14,30,.6);
  pointer-events:none;
}
#netstat.bad{ color:var(--danger); }
#netstat #fps{ color:var(--dim); }
/* En partida (mientras #hud está visible: fase de juego o cuenta regresiva,
   ver hud.js show()) se ven solo los fps: Julio los pidió ingame el 6-oct-2026;
   el ping sigue solo en el lobby y el menú. Escape hatch: #hud.legacy-hud
   muestra también el ping en partida. Va debajo del timer redondo de arriba a
   la derecha (ingamehud.css: 20 px de margen + 96 px, escalados por alto/1080),
   que si no lo tapa. Encima del panel de /style (#stylelab, z-index 300). */
body:has(#hud:not(.hidden)) #netstat #ping{ display:none; }
body:has(#hud:not(.hidden):not(.legacy-hud)) #netstat{
  top:calc(var(--safe-t) + 124 * 100vh / 1080); right:calc(20 * 100vh / 1080); z-index:301;
}
body:has(#hud.legacy-hud) #netstat #ping{ display:inline; }

/* ------------------------------------------------------------ language switch
   Two states of one control: the compact EN|ES pill that lives under the ping
   readout (reachable on the title screen, in the lobby and mid-match), and the
   labelled pair of buttons on the title card. */
#langbar{ position:fixed; right:10px; top:calc(34px + var(--safe-t)); z-index:31; }
/* Julio no quiere el selector de idioma ingame, pero sigue haciendo falta en
   el lobby y el menú: se oculta solo mientras #hud está visible (fase de
   juego o cuenta regresiva, ver hud.js show()). Escape hatch: #hud.legacy-hud
   lo vuelve a mostrar también en partida. */
body:has(#hud:not(.hidden)) #langbar{ visibility:hidden; }
body:has(#hud.legacy-hud) #langbar{ visibility:visible; }
.langsw-btns{
  display:inline-flex; gap:2px; padding:2px; border-radius:0;
  background:rgba(10,14,30,.86); border:2px solid var(--line);
}
.langsw-b{
  padding:3px 9px; border-radius:0; font-family:var(--mono);
  font-size:10.5px; font-weight:700; letter-spacing:.06em; color:var(--dimmer);
  transition:color .15s, background .15s;
}
.langsw-b:hover{ color:var(--text); }
.langsw-b.on{ background:rgba(124,192,255,.22); color:#dcecff; box-shadow:inset 0 0 0 1px rgba(124,192,255,.42); }
.langsw.compact{ display:flex; }
/* The title-card variant sits inside a .field, so it inherits the column flow */
#titleLang .langsw-btns{ display:grid; grid-template-columns:1fr 1fr; gap:6px; padding:4px; border-radius:0; }
#titleLang .langsw-b{ padding:9px 8px; font-family:var(--ui); font-size:13px; letter-spacing:.02em; border-radius:0; }

.noscript{ position:fixed; inset:0; display:grid; place-items:center; font-family:var(--ui); text-align:center; }

/* ---------------------------------------------------------------- mobile */
@media (max-width: 860px){
  #rail{ left:6px; top:calc(56px + var(--safe-t)); width:clamp(104px,32vw,148px); gap:3px; }
  .rail-row{ padding:3px 6px 3px 5px; gap:4px; grid-template-columns:10px 11px 1fr auto; }
  .rail-pip{ width:11px; height:11px; border-radius:0; }
  .rail-name{ font-size:10.5px; }
  .rail-stat{ font-size:10px; gap:4px; }
  #score-pod{ right:10px; top:auto; bottom:calc(96px + var(--safe-b)); transform:none; }
  #score-primary{ font-size:clamp(30px,9vw,44px); }
  #controls-hint{ display:none; }
}
@media (max-width: 560px){
  #rail{ width:auto; }
  .rail-name, .rail-stat .co{ display:none; }
  .rail-row{ grid-template-columns:10px 11px auto; }
}

/* ------------------------------------------------------------- minimapa
   Esquina superior izquierda, libre en partida: #netstat y #langbar se ocultan
   solos mientras el HUD está visible. Sin pointer-events — es información,
   no un control. Lo monta client/src/ui/minimap.js desde la vista del juego. */
.minimap{
  position:fixed; left:10px; top:calc(10px + var(--safe-t)); z-index:20;
  padding:3px; background:rgba(8,12,26,.82);
  border:2px solid rgba(150,175,225,.34); border-radius:0;
  box-shadow:0 2px 14px rgba(0,0,0,.45);
  pointer-events:none; line-height:0;
  animation:cardIn .35s both;
}
.minimap.round{ border-radius:50%; padding:4px; }
.minimap canvas{ display:block; border-radius:0; }
.minimap.round canvas{ border-radius:50%; }
@media (max-width:820px){
  .minimap{ transform:scale(.74); transform-origin:top left; }
}
