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

/* Fattore di scala UI globale (slider "Scala interfaccia" nel menu
   Impostazioni, vedi main.js applyUiScale): moltiplica, via calc()/
   composizione di transform scale(), la taglia di HUD/leaderboard/shop-panel/
   toast/kill-feed/torte a spicchi in OGNI modalità (N=1/2/3/4) — impostato
   su :root così ogni regola sotto (incluse quelle già esistenti per
   l'ingrandimento 1.5x/2x touch/mouse) lo eredita senza bisogno di
   ripeterlo. Il fallback "1" nei var(--ui-scale, 1) sotto copre il primissimo
   frame prima che main.js applichi la preferenza salvata. */
:root {
  --ui-scale: 1;
  /* Compensa la scala fissa 2x di #hud/#leaderboard-panel sui viewport touch
     piccoli (vedi updateTouchViewportScale in main.js): resta al default 1
     su desktop (mai scritto lì), quindi calc(2 * var(--ui-scale, 1) *
     var(--touch-viewport-scale, 1)) equivale esattamente a prima su
     desktop. */
  --touch-viewport-scale: 1;
  /* Oro/legno chiaro già usato in giro per l'UI su valori in risalto (DNA,
     Prestigio, podio Top 10, "Codice stanza:" in Impostazioni — tutti
     #ffd166 hardcoded sparsi nel file): prima variabile CSS ufficiale per
     questo accento, qui usata da #room-btn. --accent-gold-rgb affianca la
     tripletta r,g,b per comporre sfumature translucide via rgba(var(...))
     senza duplicare il valore esadecimale (stesso bisogno che ha già
     rgba(77, 159, 255, ...) per #info-btn, solo reso riusabile). */
  --accent-gold: #ffd166;
  --accent-gold-rgb: 255, 209, 102;
  /* Altezza NON scalata di #hud-card (contenuto di #hud, barra stat in alto
     centro): padding 10+10=20 + riga #hud-bar 22px (icona più alta della
     track 18px, le altre icone/track della riga si allineano a quella) =
     42px, calcolata sommando le regole sotto, non misurata a occhio. Serve a
     #important-banner (vedi sotto) per calcolare un top che segua la STESSA
     formula di scala di #hud (calc(2 * var(--ui-scale,1) *
     var(--touch-viewport-scale,1)), vedi #hud) invece di un offset fisso in
     px — altrimenti a scala UI alta (--ui-scale oltre ~114%, es. 130-150%)
     #hud cresce più in fretta di un top statico e il banner ci finisce
     sotto/sopra invece che restarci staccato. */
  --hud-card-natural-height: 42px;
}

/* Stesso --ui-scale (slider "Scala interfaccia" in Impostazioni) applicato
   anche a Home e ai popup raggiungibili da lì (Impostazioni/Codice
   stanza/Come si gioca) — finora era solo su HUD/leaderboard/shop-panel in
   game. Nessuna variabile parallela: applyUiScale (main.js) scrive solo
   :root { --ui-scale }, quindi lo slider — che vive proprio dentro
   #settings-box, raggiungibile da qui — si riflette qui in tempo reale via
   cascata CSS, nessuna gestione JS dedicata necessaria. Scala solo il
   contenitore di Home (#login-screen) e le card dei popup (*-box), non i
   loro overlay a tutto schermo (*-modal, position:fixed inset:0 — scalarli
   non avrebbe effetto visibile utile e comporrebbe la trasformazione con
   quella della card figlia). [data-role="settings-box"] (i cloni per gli
   slot extra dello split-screen in game) resta escluso apposta: quello
   scala già (o no) secondo la logica dedicata di applySplitScreenPositioning,
   fuori scope qui. */
#login-screen,
#settings-box,
#room-box,
#info-box {
  transform: scale(var(--ui-scale, 1));
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #0e1116;
  font-family: system-ui, "Noto Sans Devanagari", "Nirmala UI", "Kohinoor Devanagari", sans-serif;
  touch-action: none;
}

#game-canvas {
  display: block;
  width: 100vw;
  height: 100vh;
  cursor: crosshair;
  touch-action: none;
}

/* --- Split-screen locale (2-4 giocatori sullo stesso schermo) ---
   Costruito/rimosso dinamicamente da main.js (buildViewportGrid/
   teardownSplitScreen), MAI presente per il caso a un solo giocatore
   locale: #game-canvas e il resto del DOM per-giocatore restano allora
   diretti figli di <body>, e le regole sopra (100vw/100vh, position:fixed
   di #hud/#shop-panel/ecc. nelle regole più sotto) restano le uniche
   applicate, bit-per-bit come prima di questa milestone. */
#viewport-grid {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: grid;
  gap: 2px;
  background: #000;
}

#viewport-grid[data-layout="2"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr;
}

/* N=3: griglia 2x2, il 4° quadrante (basso-dx, auto-placement riga-per-riga)
   è occupato da #leaderboard-panel.leaderboard-quadrant invece che da un
   viewport di gioco — vedi placeLeaderboardForLayout in main.js. */
#viewport-grid[data-layout="3"],
#viewport-grid[data-layout="4"] {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.viewport-cell {
  position: relative;
  overflow: hidden;
  background: #04141c;
}

/* Il canvas riempie la propria cella (non più l'intero viewport): vince su
   #game-canvas{width:100vw} grazie alla combinazione #id+.class+elemento,
   senza dover duplicare la regola per ogni id suffissato (#game-canvas-1,
   #game-canvas-2, ...) dei cloni degli slot extra. */
#viewport-grid .viewport-cell canvas {
  width: 100%;
  height: 100%;
}

/* #leaderboard-panel è condiviso (un solo elemento, mai clonato): per N=3
   diventa il 4° quadrante della griglia, in-flow (non più un overlay
   fixed) — position:relative+.class ha specificità sufficiente per vincere
   su #leaderboard-panel{position:fixed}. */
#leaderboard-panel.leaderboard-quadrant {
  position: relative;
  inset: auto;
  width: 100%;
  height: 100%;
  border-radius: 0;
  z-index: 1;
  /* A differenza di HUD/shop-panel (dentro un .viewport-cell già
     overflow:hidden), qui il pannello È il figlio diretto della griglia:
     serve il proprio overflow:hidden per contenere lo scale(--ui-scale) del
     nuovo slider "Scala interfaccia" (fino a 1.5x) senza farlo traboccare
     nelle celle vicine — stesso identico contenimento che le altre celle
     ottengono gratis da .viewport-cell. */
  overflow: hidden;
}

/* Per N=2/4 resta un overlay centrato SOPRA tutti i quadranti, ma FUORI
   dalla griglia (vedi placeLeaderboardForLayout in main.js — bug 4 del
   report: come figlio della griglia con grid-column/row esplicito su
   entrambi gli assi rompeva l'auto-placement dei viewport-cell). position:
   fixed + transform di centratura invece dell'ancoraggio in alto a destra
   di #leaderboard-panel di base; il transform qui dichiarato vince per
   specificità (id+classe) sulla regola scale(2) fissa di #leaderboard-panel,
   senza bisogno di azzerarlo via JS come per .leaderboard-quadrant. */
#leaderboard-panel.leaderboard-overlay {
  position: fixed;
  top: 50%;
  left: 50%;
  right: auto;
  transform: translate(-50%, -50%) scale(var(--ui-scale, 1));
  z-index: 10;
  background: rgba(5, 10, 14, 0.85);
}

/* N=2 (split verticale a 2 giocatori): overlay centrata solo sull'asse
   ORIZZONTALE, ancorata in ALTO invece che al centro verticale — richiesta
   esplicita per lo split a 2, diversa da N=4 (che resta centrata su
   entrambi gli assi, regola sopra). Il selettore attributo [data-slots="2"]
   (impostato da placeLeaderboardForLayout in main.js) tiene questa regola
   scoped al solo caso N=2 senza toccare N=4, che condivide la stessa classe
   .leaderboard-overlay. Specificità (id+2classi+attributo) sufficiente a
   vincere sulla regola base sopra senza bisogno di !important. */
#leaderboard-panel.leaderboard-overlay[data-slots="2"] {
  top: 12px;
  transform: translateX(-50%) scale(var(--ui-scale, 1));
}

/* Invito a riagganciarsi (bug A): copre l'intera cella di uno slot
   "licenziato" mentre altri slot locali restano in gioco (vedi
   enterEmptySlotState in main.js) — sopra il frame di gioco ormai fermo,
   così non sembra un blocco/crash ma un'attesa esplicita. */
.empty-slot-invite {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 14px;
  background: rgba(5, 8, 11, 0.82);
  padding: 16px;
  text-align: center;
}

.empty-slot-invite-text {
  color: #f2f2f2;
  font-size: 15px;
  line-height: 1.4;
}

/* Mini-card di riaggancio: stesso aspetto di .lobby-slot in login, solo
   dentro il riquadro di gioco invece che in #lobby-extra-slots. Bug 1 del
   report: dimensione fissa (uguale per N=2/3/4) invece che proporzionata
   allo spazio nero disponibile in QUESTA cella — --empty-slot-card-scale
   è calcolato da sizeEmptySlotCard in main.js in base al lato corto reale
   della .viewport-cell dello slot (stesso principio del transform:scale
   già usato per #lobby-columns/--lobby-fit-scale). transform, non
   width/height, così l'intera card (canvas, frecce, testo, barra hold)
   cresce/rimpicciolisce in blocco mantenendo le proporzioni interne;
   .viewport-cell{overflow:hidden} resta il backstop se lo scale la
   spingesse oltre i bordi (stesso backstop già usato da HUD/shop-panel
   split-screen, vedi applySplitScreenPositioning). */
.empty-slot-reclaim-card {
  background: rgba(255,255,255,0.08);
  transform: scale(var(--empty-slot-card-scale, 1));
}

/* Istruzione hold-Start (bug 2): a differenza delle mini-card di lobby (dove
   basta il bottone "Gioca" a dare contesto alla barra), qui va detto
   esplicitamente cosa fare — stessa dimensione/colore di .lobby-slot-label
   invece del più grande .empty-slot-invite-text ereditato, per restare
   leggibile nella card stretta senza andare a capo in modo scomodo. */
.empty-slot-reclaim-hint {
  font-size: 12px;
  line-height: 1.3;
}

/* Barra di progresso dell'hold Start (3s) PER QUESTO pad: stessa tecnica
   di #play-btn-progress (scaleX via --hold-progress), ma inline nella
   mini-card invece che sovrapposta a un bottone. */
.empty-slot-reclaim-progress {
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: rgba(255,255,255,0.15);
  overflow: hidden;
  position: relative;
}

.empty-slot-reclaim-progress::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(76, 175, 80, 0.9);
  transform: scaleX(var(--hold-progress, 0));
  transform-origin: left;
}

/* Mentre si usa il controller il mirino (cursore) non serve: si nasconde
   finché il mouse non si rimuove di nuovo (vedi Input.isUsingGamepad). */
#game-canvas.gamepad-cursor, [data-role="game-canvas"].gamepad-cursor {
  cursor: none;
}

/* Su touch, mentre si usa il controller il joystick virtuale di movimento
   non serve: si nasconde finché non si ritocca lo schermo (vedi
   Input.isUsingGamepad in renderer.js). I tasti azione touch (attacco/dash)
   restano visibili: la classe è applicata solo a #joystick-base.
   Stesso discorso per #backpack-btn: con gamepad attivo l'uso item passa
   al tasto X (slot 0), quindi il bottone touch diventa ridondante (vedi
   updateHeldItems in main.js) — Kill/Dash NON sono in questa lista, restano
   sempre visibili. display:none, non solo un fade: l'elemento nascosto non
   deve più ricevere tap accidentali. */
#joystick-base.gamepad-hidden,
#backpack-btn.gamepad-hidden {
  display: none;
}

/* #login-box resta l'UNICO elemento che #login-screen centra via
   justify-content:center — la versione precedente metteva #login-box e
   #login-leaderboard nella STESSA riga flex (flex-wrap), quindi la
   presenza/larghezza della classifica spostava la colonna host dal centro
   esatto del viewport (bug segnalato). #login-leaderboard è ora tolta dal
   flusso flex (position:absolute, vedi la sua regola più sotto) e ancorata a
   destra in modo indipendente: la sua larghezza non influenza più in alcun
   modo dove #login-box viene centrato. Le 3 colonne (sinistra/centro/destra)
   restano SEMPRE affiancate, anche su touch: se lo spazio reale non basta a
   contenerle alla loro dimensione naturale, updateLobbyFitScale in main.js
   restringe l'intero gruppo in blocco tramite --lobby-fit-scale (vedi
   .lobby-columns più sotto), mai un breakpoint che ne nasconde una — questo
   garantisce MATEMATICAMENTE (computeFitScale non supera mai 1) che il
   gruppo scalato entri nello spazio disponibile, quindi overflow-y resta
   hidden qui: con transform:scale() il browser calcola comunque lo
   scrollHeight del genitore sulla dimensione NATURALE pre-scala di
   .lobby-columns (non quella visiva già rimpicciolita) — con overflow-y:auto
   questo produceva uno scroll "fantasma" verificato empiricamente (contenuto
   già tutto visibile ma ancora scorribile, bug segnalato su mobile
   landscape). overflow-y:auto torna SOLO nel media query più sotto per
   touch+portrait, dove le colonne sono impilate SENZA fit-scale e possono
   eccedere l'altezza per design: lì lo scroll è reale e voluto. */
#login-screen {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow-y: hidden;
  padding: 24px 16px;
  /* Trasparente apposta: dietro c'è #game-canvas, che qui disegna dal vivo
     lo sfondo dell'hub (vedi renderer.homeBackgroundMode) invece di
     un'immagine statica. Ogni colonna/pannello si dà da sé lo sfondo
     "vetro smerigliato" necessario per restare leggibile sopra la mappa. */
  background: transparent;
  z-index: 10;
}

.lobby-columns {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  width: 100%;
  max-width: 1400px;
  /* --lobby-fit-scale: calcolato da updateLobbyFitScale in main.js in base
     allo spazio REALE disponibile in #login-screen (mai un breakpoint
     fisso) — restringe le 3 colonne in blocco, mantenendole affiancate e
     centrate, invece di nasconderne una su viewport touch stretti. */
  transform: scale(var(--lobby-fit-scale, 1));
  transform-origin: center center;
}

.lobby-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.lobby-col-left,
.lobby-col-right {
  flex: 0 0 220px;
}

/* Touch in portrait: le 3 colonne si IMPILANO verticalmente (centro in
   cima, poi sinistra, poi destra) invece di restringersi affiancate come in
   landscape — updateLobbyFitScale in main.js riconosce la stessa condizione
   (touch + orientation:portrait) e lascia --lobby-fit-scale a 1, quindi
   nessun doppio effetto con lo scale qui sopra. Ogni pannello resta alla
   sua larghezza naturale (fit-scale qui non serve: ogni colonna occupa
   ormai la propria riga da sola). Landscape touch e desktop restano
   invariati: nessuna di queste regole si applica fuori da questa
   combinazione hover/pointer/orientation. */
@media (hover: none) and (pointer: coarse) and (orientation: portrait) {
  #login-screen {
    /* Qui (a differenza della regola base, vedi sopra) le colonne impilate
       NON usano --lobby-fit-scale e possono davvero eccedere l'altezza
       disponibile — overflow-y torna auto apposta: a differenza del caso
       scalato via transform, qui lo scrollHeight riflette la dimensione
       LAYOUT reale (nessun transform sulle colonne, vedi updateLobbyFitScale
       in main.js), quindi niente scroll fantasma. */
    overflow-y: auto;
    /* Con le colonne impilate non dovrebbe più servire, ma resta una difesa
       in più per il pannello centrale (unico senza un cap di larghezza
       esplicito, vedi #login-box più sotto) su viewport strettissimi. */
    overflow-x: hidden;
    /* align-items:center (ereditato dalla regola base) intrappolerebbe la
       parte INIZIALE del contenuto quando eccede l'altezza disponibile con
       overflow-y:auto attivo — bug noto di flexbox: centrare un contenuto
       che trabocca lo rende irraggiungibile scorrendo, anche se si può
       scorrere oltre la fine. Qui le 3 colonne impilate eccedono l'altezza
       per design (lo scroll verticale è accettato ed esplicitamente voluto),
       quindi si ancora in cima invece di centrare. */
    align-items: flex-start;
  }

  .lobby-columns {
    flex-direction: column;
  }

  .lobby-col-center {
    order: 1;
  }

  .lobby-col-left {
    order: 2;
  }

  .lobby-col-right {
    order: 3;
  }

  /* flex:0 0 220px (landscape, sopra) fisserebbe l'ALTEZZA a 220px ora che
     l'asse principale di .lobby-columns è verticale — qui serve solo una
     larghezza "a carta", l'altezza resta auto (dipende dal contenuto). */
  .lobby-col-left,
  .lobby-col-right {
    flex: 0 0 auto;
    width: min(340px, 92vw);
  }

  /* Stesso ordine di grandezza dei pannelli sinistra/destra qui sopra: le 3
     "carte" impilate restano di larghezza coerente tra loro invece che
     ciascuna alla propria dimensione naturale (356px circa di suo). */
  #login-box {
    max-width: min(340px, 92vw);
  }
}

/* Pannello "vetro smerigliato" condiviso da #login-box e .lobby-col-left,
   così bordo/raggio/background restano un'UNICA fonte invece di due valori
   duplicati che potrebbero disallinearsi. */
.lobby-panel {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
}

.lobby-col-left {
  padding: 20px 10px;
}

.lobby-col-center {
  flex: 0 1 auto;
  position: relative;
}

#login-box {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
  color: #f2f2f2;
  padding: 24px 28px;
}

#login-box input {
  padding: 10px 14px;
  border-radius: 6px;
  border: none;
  font-size: 16px;
  width: 220px;
  text-align: center;
}

#login-box button {
  padding: 10px 24px;
  border-radius: 6px;
  border: none;
  background: #4caf50;
  color: white;
  font-size: 16px;
  cursor: pointer;
}

#login-box button:hover {
  background: #43a047;
}

#login-title {
  margin: 0;
  font-size: 48px;
}

#login-beaver-canvas {
  display: block;
}

/* Frecce sinistra/destra ai lati della preview stessa, sulla stessa riga:
   il colore selezionato si vede solo dal Beaver renderizzato nel canvas,
   niente più label o pallino separati. align-items:center centra le
   frecce (36px) rispetto all'altezza del canvas (170px) sull'asse
   trasversale della riga. */
#color-carousel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  border-radius: 12px;
  outline: 2px solid transparent;
  transition: outline-color 0.15s;
}

/* Il gamepad legato all'host sta guidando il carosello in questo momento
   (vedi hostUsingGamepad in main.js) — stesso concetto del cursore
   crosshair nascosto in partita quando si usa il controller, qui reso
   come un anello attorno al carosello invece che sparire qualcosa. */
#color-carousel.gamepad-active {
  outline-color: rgba(76, 175, 80, 0.6);
}

.color-arrow-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.1);
  color: #fff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

#login-box .color-arrow-btn {
  background: rgba(255,255,255,0.1);
}

#login-box .color-arrow-btn:hover {
  background: rgba(255,255,255,0.2);
}

/* Barra di caricamento durante l'hold di 3s del tasto Start su un
   gamepad in lobby: riempimento a sinistra->destra sopra lo sfondo verde
   del bottone, sotto la label testuale. --hold-progress va da 0 a 1,
   aggiornato ad ogni frame da pollLobbyGamepads in main.js — a 0 resta
   invisibile (scaleX(0)), niente da nascondere esplicitamente quando
   nessun controller sta tenendo premuto. */
#play-btn {
  position: relative;
  overflow: hidden;
}

#play-btn span {
  position: relative;
  z-index: 1;
}

#play-btn-progress {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(255,255,255,0.4);
  transform: scaleX(var(--hold-progress, 0));
  transform-origin: left;
  pointer-events: none;
}

/* Fino a 3 mini-card, una per gamepad aggiuntivo unitosi in lobby (vedi
   addLobbySlot in main.js) — vuoto e senza alcun ingombro finché nessun
   secondo controller preme X. */
#lobby-extra-slots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.lobby-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.15);
}

.lobby-slot-label {
  font-size: 12px;
  color: rgba(255,255,255,0.7);
}

.lobby-slot-color-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.lobby-slot-canvas {
  display: block;
}

/* Frecce più piccole delle principali (36px): le mini-card devono restare
   compatte, stessa palette/hover di .color-arrow-btn (ereditati). */
.lobby-slot-arrow {
  width: 26px;
  height: 26px;
  font-size: 15px;
}

.lobby-slot-name {
  width: 120px;
  padding: 5px 8px;
  border-radius: 6px;
  border: none;
  font-size: 12px;
  text-align: center;
}

/* Nella colonna sinistra, insieme a #info-btn: stessa forma "pillola"
   icona+testo (non più un cerchio icon-only, che non avrebbe spazio per la
   label "Impostazioni"), stessa palette neutra già usata da #settings-btn
   in-game. */
#home-settings-btn {
  padding: 10px 24px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.1);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
}

#home-settings-btn:hover {
  background: rgba(255,255,255,0.2);
}

/* Bottone "Come si gioca", stessa colonna sinistra: riusa il font/padding
   generico dei bottoni di #login-box (non più applicabile via discendenza,
   dato che ora vive fuori da #login-box) più l'accento blu già usato prima. */
#info-btn {
  padding: 10px 24px;
  border-radius: 6px;
  border: 1px solid rgba(77, 159, 255, 0.6);
  background: rgba(77, 159, 255, 0.25);
  color: white;
  font-size: 16px;
  cursor: pointer;
}

#info-btn:hover {
  background: rgba(77, 159, 255, 0.4);
}

/* "Codice stanza": stessa forma "pillola" icona+testo di #home-settings-btn,
   ma tinta oro (--accent-gold, vedi :root) invece della palette neutra — la
   distingue visivamente come azione legata al codice Room, stesso
   trattamento "bordo/sfondo translucidi nell'accento" già usato da #info-btn
   con il blu. */
#room-btn {
  padding: 10px 24px;
  border-radius: 6px;
  border: 1px solid rgba(var(--accent-gold-rgb), 0.6);
  background: rgba(var(--accent-gold-rgb), 0.25);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
}

#room-btn:hover {
  background: rgba(var(--accent-gold-rgb), 0.4);
}

/* Nessuno dei tre ha una width propria: senza questa regola si
   dimensionano al proprio contenuto (icona+testo), e .lobby-col li centra
   (align-items:center) invece di stirarli — "Impostazioni" (testo più
   corto di "Codice stanza"/"Come si gioca") restava visibilmente più
   stretto e non arrivava al bordo del pannello. width:100% li fissa tutti
   alla stessa larghezza del pannello sinistro, indipendente dal testo. */
#home-settings-btn,
#info-btn,
#room-btn {
  width: 100%;
}

/* Conferma "Copiato!" nel popup #room-modal: nessuno spazio riservato quando
   nascosta (.hidden = display:none). */
#room-copy-confirm {
  color: #4caf50;
  font-size: 13px;
}

@media (max-width: 480px) {
  #home-settings-btn,
  #info-btn,
  #room-btn {
    padding: 8px 18px;
    font-size: 14px;
  }

  #login-title {
    font-size: 36px;
  }

  /* Freccia+canvas+freccia sono ora affiancati sulla stessa riga (invece
     che impilati): su schermi stretti restringiamo gap e canvas così la
     riga resti comoda anche sui viewport più piccoli, invece di rischiare
     di sfiorare i bordi. */
  #color-carousel {
    gap: 10px;
  }

  #login-beaver-canvas {
    width: 140px;
    height: 140px;
  }
}

#info-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(14, 17, 22, 0.95);
  z-index: 11;
}

/* max-width/max-height divisi per --ui-scale per compensare il
   transform:scale(--ui-scale) applicato a #info-box (vedi regola in cima al
   file): quel transform agisce DOPO il layout, con transform-origin al
   centro, quindi ingrandisce il box (e con esso #info-close-btn, che ne è
   figlio) simmetricamente in tutte le direzioni — a scale>1 il bordo
   superiore del box (e il tasto X vicino) finisce sopra y=0, fuori
   viewport e non cliccabile, perché html/body hanno overflow:hidden e
   #info-modal non ha uno scroll proprio. Dividendo qui il clamp per lo
   stesso --ui-scale che poi lo moltiplica in transform, il prodotto resta
   costante: la dimensione VISIVA del box non supera mai 640px x 82vh, per
   qualunque valore di --ui-scale (slider 80%-150%) — non un'euristica, è
   un invariante algebrico (max * scale / scale = max). */
#info-box {
  position: relative;
  background: #1b1f27;
  border-radius: 12px;
  padding: 32px 36px;
  color: #f2f2f2;
  max-width: calc(640px / var(--ui-scale, 1));
  max-height: calc(82vh / var(--ui-scale, 1));
  overflow-y: auto;
}

#info-box h1 {
  margin-bottom: 16px;
  font-size: 22px;
}

#info-box h2 {
  margin-top: 20px;
  margin-bottom: 6px;
  font-size: 16px;
  color: #ffd166;
}

#info-box p {
  font-size: 14px;
  line-height: 1.5;
  opacity: 0.92;
}

#info-box ul {
  margin: 6px 0 6px 20px;
  font-size: 14px;
  line-height: 1.6;
  opacity: 0.92;
}

#info-close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.1);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
}

#info-close-btn:hover {
  background: rgba(255,255,255,0.2);
}

#settings-modal, [data-role="settings-modal"],
#room-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(14, 17, 22, 0.85);
  z-index: 13;
}

#settings-box, [data-role="settings-box"],
#room-box {
  position: relative;
  background: #1b1f27;
  border-radius: 12px;
  padding: 28px 32px;
  color: #f2f2f2;
  min-width: 280px;
  max-width: 420px;
}

/* #room-modal, a differenza di #settings-modal, impila due sezioni centrate
   (codice attuale, entra con un codice) — stesso layout verticale già usato
   da #login-box, non un pannello di righe come le Impostazioni. */
#room-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  text-align: center;
}

/* Sezioni (a)/(b) di #room-box, separate da un filo sottile — stesso
   trattamento del border-bottom già usato per staccare #room-box h2 dal
   corpo. */
.room-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.room-section + .room-section {
  padding-top: 20px;
  border-top: 1px solid rgba(255,255,255,0.12);
}

.room-section-label {
  font-size: 13px;
  opacity: 0.75;
}

.room-code-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Codice attuale mascherato/rivelato: stessa tipografia monospace di
   #settings-room-code-value, per restare leggibile allo stesso modo
   indipendentemente da dove il codice compare in UI. */
#room-current-code-value {
  font-weight: 700;
  letter-spacing: 3px;
  font-family: 'Courier New', monospace;
  color: #ffd166;
  font-size: 18px;
  min-width: 90px;
}

/* Bottone occhiolino mostra/nascondi: stessa forma circolare "icon-only" di
   #settings-close-btn/#room-close-btn, ma di dimensione ridotta e non
   posizionata in absolute (vive dentro .room-code-row). */
.icon-toggle-btn {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.1);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.icon-toggle-btn:hover {
  background: rgba(255,255,255,0.2);
}

#room-join-error {
  color: #e35b4f;
  font-size: 13px;
}

/* Bottone/input del popup: stessa palette verde/pillola già usata dai
   bottoni di #login-box, ma come classi condivise (non selettori "#box
   button/input") per non alzare la specificità sopra il close-btn circolare
   qui sotto, che deve restare piccolo e in alto a destra. */
.room-modal-btn {
  padding: 10px 24px;
  border-radius: 6px;
  border: none;
  background: #4caf50;
  color: white;
  font-size: 15px;
  cursor: pointer;
}

.room-modal-btn:hover {
  background: #43a047;
}

.room-modal-input {
  padding: 10px 14px;
  border-radius: 6px;
  border: none;
  font-size: 16px;
  width: 220px;
  text-align: center;
  box-sizing: border-box;
}

/* Label "Codice stanza:" persistente nel pannello Impostazioni (vedi
   setRoomCode/refreshSettingsRoomCodeDisplay in main.js), sempre visibile —
   consultabile anche a partita iniziata. Mascherabile via
   #settings-room-code-eye-btn (.icon-toggle-btn, stessa classe/dimensione
   di #room-current-eye-btn) e copiabile via #settings-room-code-copy-btn
   (stessa copyRoomCodeToClipboard del pulsante "Copia codice" nel popup
   Home) — entrambi figli della riga flex qui sotto, nessun CSS dedicato
   necessario oltre a .icon-toggle-btn/.settings-copy-confirm. */
#settings-room-code {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 16px;
  font-size: 14px;
}

#settings-room-code-value {
  font-weight: 700;
  letter-spacing: 3px;
  font-family: 'Courier New', monospace;
  color: #ffd166;
}

/* Conferma "Copiato!" del pannello Impostazioni: stessa palette/dimensione
   di #room-copy-confirm (popup Home), ma per classe (non id) perché questo
   elemento vive dentro #settings-modal ed è quindi clonato/suffissato per
   slot in split-screen (vedi PLAYER_DOM_IDS/suffixIdsInSubtree in main.js) —
   una regola per id non farebbe più match sui cloni. */
.settings-copy-confirm {
  color: #4caf50;
  font-size: 13px;
}

/* Gerarchia visiva vera (prima leggeva quasi come una riga del corpo:
   18px, nessun peso/colore distinto dalle label sottostanti a 14px) — stessa
   ricetta già usata dai titoli di altri modali (#info-box h1: dimensione
   marcatamente maggiore del corpo, più un divisore sotto per staccarlo dalle
   righe) invece di inventare una nuova tipografia. */
#settings-box h2, [data-role="settings-box"] h2,
#room-box h2 {
  margin-bottom: 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,0.12);
  font-size: 21px;
  font-weight: 700;
}

#settings-close-btn, [data-role="settings-close-btn"],
#room-close-btn {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.1);
  color: #fff;
  font-size: 15px;
  cursor: pointer;
}

#settings-close-btn:hover, [data-role="settings-close-btn"]:hover,
#room-close-btn:hover {
  background: rgba(255,255,255,0.2);
}

/* Riga base condivisa da TUTTE le voci del pannello, qualunque sia il tipo
   (vedi .settings-row--toggle/--slider/--stepper sotto — modificatori solo
   per le rifiniture specifiche del tipo, mai per il layout base): stessa
   altezza minima, stesso padding sinistra/destra, label sempre a sinistra e
   controllo sempre a destra (justify-content:space-between). Costruita da
   renderSettingsRows in main.js, non scritta a mano in index.html — vedi
   quella funzione per come ogni tipo popola il proprio "controllo".
   margin:0 -8px + padding orizzontale 8px è voluto (si cancellano a vicenda
   sul contenuto): serve solo a far "sanguinare" lo sfondo di
   .settings-row--focused un po' oltre il testo, il contenuto resta allineato
   al padding di #settings-box. Puramente basata su classi (nessun #id):
   sopravvive tale quale al cloneNode(true) di #settings-modal per gli slot
   extra dello split-screen — ma renderSettingsRows viene comunque richiamata
   da capo per OGNI slot (host e ogni extra), quindi le righe che finiscono
   davvero a schermo sono sempre ricostruite fresche per quello slot
   specifico, non quelle ereditate dal clone (che rifletterebbero lo stato
   dell'host). I18n.applyToDom/Icons.applyToDom non toccano mai queste classi
   (agiscono solo su testo/icone via [data-i18n]/[data-icon], non sul
   wrapper della riga). */
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 32px;
  border-radius: 8px;
  padding: 8px 8px;
  margin: 0 -8px;
}

/* Stesso ritmo verticale tra tutte le righe. */
.settings-row + .settings-row {
  margin-top: 10px;
}

/* Raggruppamento visivo: la lingua è concettualmente diversa dalle righe
   sopra (accessibilità/input, non localizzazione) — un sottile divisore +
   uno stacco leggermente più ampio del solito gap tra righe, senza nuove
   icone/categorie. Selettore per attributo (stessa specificità di una
   singola classe: MENO di ".settings-row + .settings-row" sopra, che ha 2
   classi) — va quindi dichiarato DOPO nel foglio per vincere il tie-break
   sul margin-top via ordine di cascata, non per specificità. Attributo
   invece di una classe dedicata: raggruppare/distinguere UNA riga specifica
   è una scelta di contenuto, non un nuovo "tipo" di riga (che riguarda solo
   il comportamento input, vedi .settings-row--toggle/--slider/--stepper). */
.settings-row[data-settings-row-id="language"] {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,0.12);
}

/* Unica fonte di evidenziazione del focus da controller, per QUALUNQUE tipo
   di riga (toggle/slider/stepper) — mai un trattamento hardcoded per un
   tipo specifico, vedi updateSettingsFocusVisual in main.js che applica
   questa stessa classe per indice, indipendentemente da row.config.type. */
.settings-row--focused {
  background: rgba(255,255,255,0.1);
  box-shadow: inset 0 0 0 1px rgba(255,214,102,0.6);
}

.settings-row-label {
  font-size: 14px;
}

/* Riga toggle: l'intera riga è cliccabile (vedi il listener delegato in
   renderSettingsRows), non solo il quadratino nativo. */
.settings-row--clickable {
  cursor: pointer;
}

.settings-toggle-input {
  width: 18px;
  height: 18px;
  cursor: pointer;
  flex: 0 0 auto;
}

/* Riga slider: il gruppo <input range>+percentuale è il "controllo"
   allineato a destra sulla stessa riga della label — flex:0 0 auto (non
   riempie lo spazio residuo, che justify-content:space-between della riga
   usa già come gap dalla label). */
.settings-slider-control {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

.settings-row--slider input[type="range"] {
  width: 130px;
  cursor: pointer;
}

/* Riga stepper (lingua): stesso schema "‹ valore ›" del carosello skin
   dell'host, stesse frecce (.color-arrow-btn, vedi sotto) — niente più
   <select> che promette un click-per-aprire quando l'interazione reale è
   solo sinistra/destra. */
.settings-stepper-control {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.settings-stepper-arrow {
  width: 26px;
  height: 26px;
  font-size: 15px;
}

/* Valore corrente: condivisa da slider (percentuale) e stepper (nome
   lingua) — stesso trattamento tipografico per il "numero/valore" di una
   riga, indipendentemente dal tipo. Larghezza minima generosa per nomi di
   lingua più lunghi di "Italiano"/"English" (es. future aggiunte a
   SUPPORTED_LANGUAGES). */
.settings-value {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  min-width: 70px;
  text-align: right;
  opacity: 0.85;
}

/* Nello stepper il valore sta TRA due frecce (non a fianco di uno slider):
   centrato invece che allineato a destra, per un "‹ valore ›" visivamente
   simmetrico come il carosello skin dell'host. */
.settings-stepper-control .settings-value {
  text-align: center;
}

/* HUD infografico dei controlli, angolo in basso a destra: mostrato solo
   su mouse/gamepad (mai su touch, dove i tasti sono già visibili) e solo
   se il toggle "Visualizza consigli tasti" nelle impostazioni è attivo.
   Stesso pattern "ancorato in un angolo" di #shop-panel (bottom left):
   transform:scale(--ui-scale) + transform-origin sull'angolo di ancoraggio
   invece di lasciarlo a dimensione fissa come prima — mancava qui mentre
   era già applicato a #hud/#shop-panel/#leaderboard-panel. */
#input-hints-hud, [data-role="input-hints-hud"] {
  position: fixed;
  right: 12px;
  bottom: 12px;
  background: rgba(0,0,0,0.45);
  border-radius: 10px;
  padding: 10px 14px;
  color: #f2f2f2;
  z-index: 5;
  pointer-events: none;
  max-width: min(480px, 92vw);
  line-height: 0; /* niente spazio extra sotto l'SVG (inline di default) */
  transform: scale(var(--ui-scale, 1));
  transform-origin: bottom right;
}

/* Diagramma a callout: silhouette del dispositivo (solo contorno) +
   puntini sui tasti + linee sottili verso label brevi — vedi
   buildMouseHintDiagram/buildGamepadHintDiagram in main.js. */
.input-hint-svg {
  display: block;
  width: 100%;
  height: auto; /* scala col contenitore (max-width: min(480px, 92vw)) invece di restare a larghezza fissa su viewport stretti */
  overflow: visible; /* le label non vengono mai tagliate se un po' più larghe del viewBox */
}

@media (hover: none) and (pointer: coarse) {
  #input-hints-hud {
    display: none !important;
  }
}

/* Normale figlio in flusso di .lobby-col-right (colonna destra delle 3
   colonne dell'hub, vedi index.html) — non più ancorata via
   position:absolute a #login-screen. Stessa palette scura a overlay bianco
   trasparente già usata da #settings-box/.lobby-slot/#shop-panel, niente
   colori nuovi. */
#login-leaderboard {
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px;
  padding: 14px 18px;
  width: 100%;
  max-width: 300px;
  color: #f2f2f2;
}

#login-leaderboard h3 {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 15px;
  margin-bottom: 10px;
  opacity: 0.9;
}

/* Vera classifica Top 10 (vedi updateLoginRetiredList in main.js): niente
   più marker decimal nativo dell'<ol>, il numero di posizione è ora un
   elemento disegnato a mano (.top10-rank) per poterlo allineare in colonna
   col resto della riga. */
#login-retired-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 340px;
  overflow-y: auto;
}

.top10-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 8px;
  border-radius: 6px;
  background: rgba(255,255,255,0.04);
  font-size: 13px;
}

.top10-rank {
  flex: 0 0 20px;
  text-align: center;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,0.6);
}

.top10-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.top10-score {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #ffd166;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Primi 3 posti leggermente in risalto — stessa tinta oro (#ffd166) già
   usata altrove per DNA/prestigio/costi, più due varianti neutre per
   argento/bronzo, nessuna palette nuova introdotta. */
.top10-row-rank1 { background: rgba(255,214,102,0.14); }
.top10-row-rank1 .top10-rank { color: #ffd166; }
.top10-row-rank2 { background: rgba(255,255,255,0.08); }
.top10-row-rank2 .top10-rank { color: #d8d8d8; }
.top10-row-rank3 { background: rgba(205,127,50,0.12); }
.top10-row-rank3 .top10-rank { color: #cd7f32; }

/* [data-role="x"] affianca ogni #x qui sotto: gli slot extra dello
   split-screen locale clonano questo intero sottoalbero rinominando gli id
   (per evitare duplicati nel documento, vedi suffixIdsInSubtree in main.js)
   — un id suffissato (es. "hud-1") non fa più match con "#hud", quindi
   senza questa aggiunta il clone esisterebbe nel DOM ma senza ALCUNO stile
   (posizione, colori, sfondo, z-index...). data-role invece NON viene mai
   rinominato dal clone (main.js lo imposta una volta sola a page-load,
   PRIMA di ogni clonazione, via tagDataRoles — cloneNode(true) lo copia
   inalterato). Per il caso N=1 (nessun clone) #hud continua a fare match
   da solo, esattamente come prima di questa aggiunta: zero rischio di
   regressione. */
/* Base 2x identica su desktop e su touch (stessa formula), ma su touch
   --touch-viewport-scale (impostato da updateTouchViewportScale in main.js,
   default 1 su desktop dove non viene mai scritto) la restringe in
   proporzione al viewport reale: la STESSA 2x assoluta occuperebbe una
   frazione di schermo molto maggiore su un telefono che su un monitor
   desktop, a parità di moltiplicatore numerico. Il fattore utente --ui-scale
   (slider "Scala interfaccia") resta comunque l'unico moltiplicatore
   regolabile sopra questa base. */
#hud, [data-role="hud"] {
  position: fixed;
  top: 12px;
  left: 50%;
  color: #f2f2f2;
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: max-content;
  max-width: 320px;
  /* Stesso pattern "ancorato in alto, centrato in orizzontale" già usato da
     #important-banner/#kill-feed: left:50% + translateX(-50%). */
  transform: translateX(-50%) scale(calc(2 * var(--ui-scale, 1) * var(--touch-viewport-scale, 1)));
  transform-origin: top center;
}

/* Card delle statistiche: riga 1 = barra unica a 3 segmenti (Stick/Vita/
   DNA), riga 2 = solo Prestigio (icona tier + numero). Niente più
   etichette testuali: il valore "attuale/max" dentro ogni segmento basta. */
#hud-card, [data-role="hud-card"] {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: rgba(0,0,0,0.4);
  border-radius: 10px;
  padding: 10px 14px;
  pointer-events: none;
}

.hud-icon {
  font-size: 20px;
  line-height: 1;
}

.hud-bar-icon {
  flex: 0 0 auto;
  line-height: 1;
}

/* Icone procedurali (icons.js/Icons.createIconElement): un <canvas> inline,
   dimensionato via style.width/height dal chiamante — qui serve solo
   allinearlo verticalmente al testo circostante come faceva prima il
   glifo emoji. Usata sia dagli slot statici (.icon-inline, aggiunti a
   mano nell'HTML per titoli/etichette senza wrapper dedicato) sia dentro
   classi preesistenti come .hud-icon/.shop-stat-icon una volta popolate
   da Icons.applyToDom/I18n.applyToDom. */
.icon-inline,
.inline-icon {
  display: inline-block;
  vertical-align: middle;
}

/* Riga unica: chip Prestigio (icona+numero, larghezza al proprio contenuto
   — un valore discreto, FUORI dai segmenti a barra, niente riempimento) +
   2 segmenti di uguale larghezza (Stick/Vita). Ogni segmento è icona +
   track scuro con riempimento proporzionale a valore/max, col numero
   ESATTO "attuale/max" sopra (stesso pattern già validato dalla vecchia
   #hp-bar: riquadro scuro, riempimento colorato, testo bianco con ombra
   per restare leggibile sia sulla zona piena che su quella vuota). Il DNA
   (terzo segmento originario) è stato spostato come header della UI
   verticale upgrade, vedi .shop-dna-bar più sotto. */
#hud-bar, [data-role="hud-bar"] {
  display: flex;
  gap: 6px;
  /* Larghezza fissa: #hud/#hud-card sono width:max-content (si stringono
     al contenuto, vedi #hud sopra), quindi senza un'ancora esplicita qui i
     segmenti flex:1 non avrebbero spazio reale da dividersi in parti
     uguali — collasserebbero al solo contenuto (icona), coi track a
     larghezza zero. */
  width: 280px;
}

#hud-prestige-chip, [data-role="hud-prestige-chip"] {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
}

.hud-bar-seg {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 1 1 0;
  min-width: 0;
}

.hud-bar-track {
  position: relative;
  display: block;
  flex: 1 1 auto;
  min-width: 0;
  height: 18px;
  border-radius: 4px;
  background: rgba(0,0,0,0.5);
  border: 1px solid rgba(255,255,255,0.3);
  overflow: hidden;
}

.hud-bar-fill {
  position: absolute;
  inset: 0;
  width: 0%;
  transition: width 0.2s ease-out;
}

/* Colore di riempimento per segmento: nessuna tinta nuova, tutte già in
   palette per quello stat — legno dell'icona Stick (icons.js WOOD_TAN),
   rosso già usato dalla vecchia #hp-bar-fill. */
#stick-bar-fill, [data-role="stick-bar-fill"] { background: #C68642; }
#hp-bar-fill, [data-role="hp-bar-fill"] { background: #e53935; }

/* Trattini soglie DNA sulla barra Stick: un trattino per ogni soglia DNA
   (n * DNA_STICKS_PER_POINT Stick lifetime, vedi Player.earnedDnaPoints())
   che cade nel ciclo di prestigio corrente — ricalcolati in JS ad ogni
   cambio di prestigio (vedi renderStickDnaTicks in main.js), mai in CSS.
   inset:0 + pointer-events:none: overlay puramente visivo. Nessuno
   z-index esplicito qui né su #stick-bar-fill: DEVONO restare PRIMA del
   fill nel markup (vedi index.html) così il riempimento solido lo copre
   man mano che avanza — visibili solo nella parte ancora vuota, mai sopra
   il colore già riempito. #stick-bar-text ha z-index:1 esplicito, quindi
   resta sopra a entrambi indipendentemente dall'ordine nel DOM. */
.hud-bar-dna-ticks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hud-bar-dna-tick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  /* stesso viola DNA di ACCENT_PURPLE (icons.js) / #shop-dna-spent-fill sopra */
  background: #8a5fd1;
  transform: translateX(-50%);
}

.hud-bar-text {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 1px rgba(0,0,0,0.8);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

#prestige-value, [data-role="prestige-value"] {
  font-size: 17px;
  font-weight: 700;
  color: #ffd166;
  font-variant-numeric: tabular-nums;
}

/* Contenitore FRATELLO di #hud (non più figlio): #hud si è spostato al
   centro, questo resta ancorato in alto a sinistra (la posizione liberata),
   con la stessa base 2x + --ui-scale + --touch-viewport-scale che aveva
   prima ereditandola da #hud. Ordine pulsanti invertito nel markup
   (ingranaggio Impostazioni, poi Licenziati).
   --hud-btn-height: stesso approccio di --shop-row-height-* su #shop-panel
   sopra (custom property sul contenitore condiviso, ereditata anche dai
   cloni [data-role] dello split-screen) — altezza calcolata, non stimata a
   occhio: #settings-btn (il più alto dei due) è padding 6+6=12 + icona 16px
   (supera il suo stesso line-height:1 * font-size 15px = 15px) + bordo
   1+1=2 = 30px; #quit-btn nativamente arriva a ~29.6px (padding 12 +
   line-height testo 13px*~1.2=15.6, la sua icona 14px è più piccola del
   testo, quindi non la determina + bordo 2) — differenza sub-pixel che
   prima rendeva le due altezze leggermente diverse. Applicata esplicitamente
   a entrambi sotto invece di lasciarli auto-dimensionarsi. */
#hud-bottom-row, [data-role="hud-bottom-row"] {
  --hud-btn-height: 30px;
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 8px;
  transform: scale(calc(2 * var(--ui-scale, 1) * var(--touch-viewport-scale, 1)));
  transform-origin: top left;
}

#quit-btn, [data-role="quit-btn"] {
  height: var(--hud-btn-height);
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(255,82,82,0.25);
  color: #fff;
  font-size: 13px;
  cursor: pointer;
  pointer-events: auto; /* l'HUD è pointer-events:none, ma il bottone deve restare cliccabile */
}

#quit-btn:hover, [data-role="quit-btn"]:hover {
  background: rgba(255,82,82,0.45);
}

#settings-btn, [data-role="settings-btn"] {
  height: var(--hud-btn-height);
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(255,255,255,0.12);
  color: #fff;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  pointer-events: auto;
}

#settings-btn:hover, [data-role="settings-btn"]:hover {
  background: rgba(255,255,255,0.22);
}

.hidden { display: none !important; }

/* Come .hidden ma RISERVA lo spazio nel layout: usata per Kill/Dash/OK
   nel flex row delle azioni touch, così passare dall'uno all'altro non fa
   ridimensionare la fila (che altrimenti spostava anche Shop/zaino, dato
   che il contenitore è ancorato a destra e la sua larghezza dipende da
   quanti figli sono visibili). */
.invisible-btn { visibility: hidden; }

/* Pannello Shop della Dam ("DNA Beaver"): SOLA VISUALIZZAZIONE — i
   potenziamenti si comprano solo dalla DNA Wheel (torta a spicchi,
   invariata), mai da qui. Ancorato all'angolo basso-sinistra del proprio
   container in entrambe le varianti. SOLO desktop/mouse: su touch il
   pannello è del tutto assente (display:none, vedi la media query più
   sotto) — nessun listener tap da gestire qui. Due varianti, commutate da
   main.js (mouseenter/mouseleave — vedi shopPanelExpanded/
   refreshShopPanelMode in createGameSlot):
   - default (nessuna classe extra) = Ristretta: solo le 7 coppie
     icona+livello (impilate in colonna, vedi #shop-stats-list sotto),
     niente titolo/contatori/nome — width:auto, si stringe al
     contenuto.
   - .shop-panel--full = Completa: il layout "a lista" (icona, nome,
     livello, titolo, contatori — costo rimosso, era sempre 1 DNA per
     tutte le stat quindi ridondante), width fissa 220px. */
/* Altezza riga condivisa fra .shop-stat-row e .shop-dna-bar, una per
   modalità. Ristretta = icona 48px (nessun padding/border in questa
   modalità) — .shop-dna-bar ci si allinea perché lì l'header è una SOLA
   riga (icona+testo), stessa altezza naturale di una riga stat.
   Completa invece l'header è DUE righe impilate (.shop-dna-bar: icona+
   barra 30px, poi #shop-panel-header: label "DNA Beaver" 16px di
   line-height esplicita, vedi sotto) quindi la sua altezza naturale
   supera quella di una singola riga stat — 30 (barra) + 6 (margin-bottom
   di .shop-dna-bar) + 16 (label) = 52px. Invece di comprimere l'header a
   forza per farlo combaciare con una riga stat piccola (errore del fix
   precedente), si è ingrandita la riga stat per raggiungere l'altezza
   naturale dell'header: icona 30->40px, font 12->16px, padding
   verticale 4->5px (vedi .shop-stat-row sotto), scala ~1.3x = 52/40.
   Custom property qui (non su .shop-stat-row stessa) così è ereditata da
   entrambe le classi ed è visibile anche ai cloni [data-role] dello
   split-screen, senza doverla ridichiarare. */
#shop-panel, [data-role="shop-panel"] {
  --shop-row-height-compact: 48px;
  --shop-row-height-full: 52px;
  position: fixed;
  left: 16px;
  bottom: 16px;
  width: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  color: #f2f2f2;
  font-size: 13px;
  text-shadow: 0 1px 2px rgba(0,0,0,0.6);
  z-index: 5;
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,214,102,0.5);
  border-radius: 8px;
  padding: 8px 10px;
  transform: scale(var(--ui-scale, 1));
  transform-origin: bottom left;
}

#shop-panel.shop-panel--full, [data-role="shop-panel"].shop-panel--full {
  width: 220px;
  padding: 10px 12px;
}

/* Ristretta: titolo nascosto, torna solo in Completa. #shop-dna-points e
   #shop-total-levels (testo "DNA utilizzabili: N" / "Livelli: N/30",
   entrambi visibili solo in Completa) sono stati rimossi: ridondanti con
   .shop-dna-bar sotto, ora sempre visibile in ENTRAMBE le varianti e che
   incorpora entrambi i valori (disponibile nel livello giallo, speso nel
   livello viola + nel testo). */
#shop-panel-header, [data-role="shop-panel-header"] {
  display: none;
}

#shop-panel.shop-panel--full #shop-panel-header,
[data-role="shop-panel"].shop-panel--full [data-role="shop-panel-header"] {
  display: block;
  font-weight: bold;
  color: #ffd166;
  margin-bottom: 4px;
  /* line-height esplicita (era "normal", dipendente dal font del
     browser): rende deterministica l'altezza di questa riga (13px *
     ~1.2, arrotondato) invece di stimarla — serve per calcolare
     l'altezza totale dell'header impilato usata da
     --shop-row-height-full sopra. */
  line-height: 16px;
}

/* Header DNA fisso: SEMPRE visibile (Ristretta e Completa), a differenza
   di #shop-panel-header sopra — icona (dimensioni coerenti con le altre
   righe stat, vedi .shop-stat-icon--compact/--full) + valore DNA, in due
   presentazioni diverse per modalità (vedi .shop-dna-level--compact/--full
   sotto). font-size allineato a .shop-stat-row per modalità, così il testo
   Ristretta ha la stessa altezza/dimensione delle righe "N/5" sotto (prima
   il vecchio track a 18px sembrava schiacciato accanto all'icona 48px). */
.shop-dna-bar {
  position: relative; /* ancora .dna-earned-popup, vedi sotto */
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 4px;
  font-size: 19px;
  height: var(--shop-row-height-compact);
}

/* Popup "Hai ottenuto N DNA": nodo creato/rimosso da JS ad ogni guadagno
   (showDnaEarnedPopup in main.js), MAI solo nascosto — niente accumulo se
   il player guadagna DNA spesso. Ancorato al centro di .shop-dna-bar
   (icona + numero DNA, sempre visibile in entrambe le modalità Ristretta/
   Completa), sale e sfuma con un'unica @keyframes — durata qui e il
   timeout JS di rimozione DEVONO restare allineati (1.8s). */
.dna-earned-popup {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  white-space: nowrap;
  pointer-events: none;
  font-size: 13px;
  font-weight: 700;
  color: #ffd166;
  text-shadow: 0 1px 2px rgba(0,0,0,0.85);
  animation: dna-earned-popup-rise 1.8s ease-out forwards;
  z-index: 2;
}

@keyframes dna-earned-popup-rise {
  0% { opacity: 0; transform: translate(-50%, 6px); }
  15% { opacity: 1; transform: translate(-50%, 0); }
  70% { opacity: 1; transform: translate(-50%, -10px); }
  100% { opacity: 0; transform: translate(-50%, -18px); }
}

/* Altezza NON legata a --shop-row-height-full qui: .shop-dna-bar è solo
   metà dell'header impilato (l'altra metà è #shop-panel-header sotto),
   quindi resta alla propria altezza naturale — l'icona--full, 30px, è il
   figlio più alto (la barra hud-bar-track è fissa a 18px), niente
   padding/border su questo elemento. È la riga stat che si allarga per
   raggiungere il totale delle due, non il contrario (vedi commento sulla
   custom property sopra). */
#shop-panel.shop-panel--full .shop-dna-bar,
[data-role="shop-panel"].shop-panel--full .shop-dna-bar {
  margin-bottom: 6px;
  font-size: 12px;
  height: 30px;
}

/* Ristretta: solo testo "N/30" (N = speso), stesso .shop-stat-level delle
   righe sotto — niente track/box. Lampeggia in oro (.shop-dna-level--available,
   aggiunta/rimossa da main.js in base a dnaPoints>0) SOLO quando c'è DNA
   disponibile da spendere; altrimenti resta nel colore normale del pannello,
   statico. */
.shop-dna-level--available {
  color: #ffd166;
  animation: hud-blink 1.1s ease-in-out infinite;
}

/* Completa: INVARIATA, barra a 2 livelli sovrapposti nello stesso track.
   Livello base: giallo lampeggiante, DNA speso+disponibile insieme (capped
   a 30) — "quanto hai guadagnato finora che conta per il tetto", lampeggia
   per segnalare che una parte potrebbe essere ancora spendibile. Livello
   sopra (dopo nel markup, quindi disegnato sopra): viola statico, SOLO lo
   speso — sempre ≤ del giallo per costruzione (speso ≤ speso+disponibile),
   quindi la fetta di giallo oltre il bordo viola resta sempre visibile ed è
   esattamente il DNA disponibile non ancora speso. Nessun colore nuovo:
   oro #ffd166 già associato a DNA/Prestigio in questo stesso file, viola
   #8a5fd1 già usato dall'icona DNA stessa (icons.js ACCENT_PURPLE). */
#shop-dna-total-fill, [data-role="shop-dna-total-fill"] { background: #ffd166; }
#shop-dna-spent-fill, [data-role="shop-dna-spent-fill"] { background: #8a5fd1; }

/* Switch Ristretta/Completa per il valore DNA, stesso pattern display:none
   di .shop-stat-icon--compact/--full sopra (non una nuova convenzione). */
.shop-dna-level--full {
  display: none;
}

#shop-panel.shop-panel--full .shop-dna-level--compact,
[data-role="shop-panel"].shop-panel--full .shop-dna-level--compact {
  display: none;
}

#shop-panel.shop-panel--full .shop-dna-level--full,
[data-role="shop-panel"].shop-panel--full .shop-dna-level--full {
  display: block;
}

/* Lampeggio riusato dal periodo (1.1s) già validato dal glow pulsante che
   renderer.js disegna sul proprio castoro quando ci sono DNA spendibili
   (stessa curva "a battito", vedi drawIcon/showDnaGlow in renderer.js) —
   nessuna nuova cadenza inventata, solo espressa in CSS invece che canvas.
   Keyframe generico (non specifico al DNA): riusato sia dal livello giallo
   della barra Completa (.hud-blink) sia dal testo Ristretta
   (.shop-dna-level--available sopra). */
@keyframes hud-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

.hud-blink {
  animation: hud-blink 1.1s ease-in-out infinite;
}

/* Ristretta e Completa: entrambe in colonna verticale (le 7 coppie
   icona+livello impilate, stesso ordine di sempre) — la sola differenza tra
   le due varianti è quali dettagli per riga sono visibili (nome, vedi
   .shop-panel--full .shop-stat-name sotto), non la
   direzione della lista. Gap di lista ~+60% in Ristretta (5px -> 8px) per
   restare in proporzione con icona/testo ingranditi sotto — la Completa
   resta invariata (3px). */
#shop-stats-list, [data-role="shop-stats-list"] {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 8px;
}

#shop-panel.shop-panel--full #shop-stats-list,
[data-role="shop-panel"].shop-panel--full [data-role="shop-stats-list"] {
  gap: 3px;
}

/* Gap icona<->testo e font-size del livello ~+60% in Ristretta (gap 3px ->
   5px, font-size 12px -> 19px, stessa proporzione ~1.6x di icona/gap-lista
   sopra) — la Completa riporta esplicitamente entrambi ai valori originali
   (gap 6px, font-size 12px), dato che non eredita più il 12px di default. */
.shop-stat-row {
  display: flex;
  align-items: center;
  gap: 5px;
  color: #f2f2f2;
  font-size: 19px;
  text-align: left;
  height: var(--shop-row-height-compact);
}

/* Ingrandita ~1.3x (52/40) per raggiungere l'altezza naturale
   dell'header DNA impilato (barra+label, vedi --shop-row-height-full
   sopra) invece di comprimere l'header a 40px: gap 6->8px, font 12->16px
   (eredita anche .shop-stat-name/.shop-stat-level, che non hanno un
   proprio font-size), padding verticale 4->5px. L'icona passa a 40px via
   data-icon-size in index.html (non qui: è cotta nel canvas, vedi
   .shop-stat-icon--full sotto). */
#shop-panel.shop-panel--full .shop-stat-row,
[data-role="shop-panel"].shop-panel--full .shop-stat-row {
  gap: 8px;
  font-size: 16px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 6px;
  padding: 5px 10px;
  height: var(--shop-row-height-full);
}

/* Stat già al livello massimo: attenuazione puramente informativa (il
   pannello è sola visualizzazione, non c'è più un :disabled da gestire). */
.shop-stat-row--maxed {
  opacity: 0.5;
}

.shop-stat-icon {
  font-size: 15px;
}

/* Due canvas icona per riga (stesso Icons.createIconElement, due
   data-icon-size statici — 48px Ristretta/40px Completa nelle righe stat,
   30px Completa nell'header DNA che non è stato ingrandito): mai
   ridisegnati/scalati via CSS (resterebbe sfocato, la risoluzione fisica è
   cotta dentro al canvas alla creazione, vedi createIconElement in
   icons.js), si alterna solo quale dei due è display:none. */
.shop-stat-icon--full {
  display: none;
}

#shop-panel.shop-panel--full .shop-stat-icon--compact,
[data-role="shop-panel"].shop-panel--full .shop-stat-icon--compact {
  display: none;
}

#shop-panel.shop-panel--full .shop-stat-icon--full,
[data-role="shop-panel"].shop-panel--full .shop-stat-icon--full {
  display: inline;
}

.shop-stat-name {
  display: none;
}

#shop-panel.shop-panel--full .shop-stat-name,
[data-role="shop-panel"].shop-panel--full .shop-stat-name {
  display: inline;
  flex: 1;
}

/* Costo (icona DNA + "1") rimosso dalla riga: era sempre 1 DNA per ogni
   stat, quindi ridondante. .shop-stat-name resta flex:1 (invariato) —
   era già il meccanismo che allineava il costo al bordo destro della
   riga (assorbe tutto lo spazio libero, spingendo l'ultimo figlio
   visibile contro il padding destro); ora che il costo non c'è più,
   .shop-stat-level (l'ultimo figlio rimasto) eredita questo stesso
   allineamento senza bisogno di nessuna regola nuova — esattamente
   quello che succede già oggi in Ristretta, dove il costo è sempre
   stato display:none e il livello è sempre stato l'ultimo figlio. */
.shop-stat-level {
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}

/* Base 2x + --touch-viewport-scale, come #hud sopra: stessa proporzione di
   schermo su desktop e su touch (non lo stesso valore assoluto), invariata
   indipendentemente dalla wheel aperta. Condivisa da tutti gli slot;
   in split-screen (.leaderboard-quadrant/.leaderboard-overlay) la posizione è
   strutturalmente diversa e questa regola viene vinta per specificità. */
#leaderboard-panel {
  position: fixed;
  top: 12px;
  right: 12px;
  color: #f2f2f2;
  background: rgba(0,0,0,0.35);
  border-radius: 8px;
  padding: 10px 14px;
  min-width: 160px;
  z-index: 5;
  font-size: 14px;
  pointer-events: none;
  transform: scale(calc(2 * var(--ui-scale, 1) * var(--touch-viewport-scale, 1)));
  transform-origin: top right;
}

#leaderboard-panel h3 {
  margin-bottom: 6px;
  font-size: 14px;
  opacity: 0.8;
}

/* list-style-position:inside (non il default "outside"): con "outside" Chrome
   riserva per il marker numerico nativo uno spazio SEPARATO, ulteriore
   rispetto a padding-left, prima che il contenuto della riga inizi — il
   numero digitato a mano nelle righe pinnate (.leaderboard-self-rank, che
   non ha alcun marker nativo) parte invece esattamente al bordo di
   padding-left, quindi appariva spostato a destra rispetto ai numeri "1./2./
   ..." della top N (righe visibilmente disallineate a sinistra). Con
   "inside" il marker nativo diventa il primo contenuto in-flow della riga,
   allo stesso punto di partenza di un numero digitato a mano: le due
   numerazioni si allineano perfettamente. */
#leaderboard-list {
  list-style: decimal;
  list-style-position: inside;
  padding-left: 18px;
}

.leaderboard-self-divider {
  list-style: none;
  margin: 4px 0;
  border-top: 1px dashed rgba(255,255,255,0.3);
}

/* Bug del doppio numero: #leaderboard-list è un <ol> con list-style:decimal,
   quindi il browser numera OGNI <li> per posizione nel DOM, non solo le righe
   della top N. Il divisore sopra sopprime già il proprio marker, ma il
   contatore dell'ol avanza comunque per gli elementi successivi (list-style
   nasconde solo il glifo, non ferma il counter) — la riga pinnata mostrava
   quindi il rank vero (già scritto da JS in updateLeaderboard) PIÙ il numero
   di posizione assegnato dal browser (es. "7. 41. nome"). Va soppresso qui. */
.leaderboard-self-rank {
  list-style: none;
}

#killed-toast, [data-role="killed-toast"] {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(var(--ui-scale, 1));
  background: rgba(0,0,0,0.75);
  color: #fff;
  padding: 16px 28px;
  border-radius: 8px;
  font-size: 20px;
  z-index: 8;
  pointer-events: none;
}

/* Stesso stile del toast kill, ma un po' più in basso (non centrato),
   per non sovrapporsi visivamente ad altri messaggi centrali. */
#item-toast, [data-role="item-toast"] {
  position: fixed;
  top: 64%;
  left: 50%;
  transform: translate(-50%, -50%) scale(var(--ui-scale, 1));
  background: rgba(0,0,0,0.75);
  color: #b388ff;
  padding: 12px 22px;
  border-radius: 8px;
  font-size: 16px;
  z-index: 8;
  pointer-events: none;
}

/* Banner centrale per annunci importanti: più grande e vistoso di un
   toast normale, resta un paio di secondi poi sfuma. */
#center-banner, [data-role="center-banner"] {
  position: fixed;
  top: 30%;
  left: 50%;
  transform: translate(-50%, -50%) scale(var(--ui-scale, 1));
  background: rgba(120, 20, 20, 0.85);
  border: 2px solid rgba(255,82,82,0.7);
  color: #fff;
  padding: 18px 32px;
  border-radius: 10px;
  font-size: 26px;
  font-weight: bold;
  text-align: center;
  z-index: 9;
  pointer-events: none;
}

/* Banner "importante" screen-space, fisso in alto (distinto dal popup sotto
   il player #item-toast e dal #center-banner centrato): coda one-time-per-vita
   per evento (Primo Giorno, scontro alla Dam, soglia 500 Stick — soppressi
   dopo la prima volta da un flag lato server, vedi player.hasSeenXWarning in
   Room.js/Player.js), 6s poi fade-out via opacity (vedi showImportantBanner
   in main.js). Stesso componente riusato anche dal popup Stick "Fermo
   troppo a lungo" (variante .important-banner-danger sotto), che però
   NON è mai soppresso dopo la prima volta — ricompare ogni volta che la
   condizione si ripete. */
#important-banner, [data-role="important-banner"] {
  position: fixed;
  /* Abbassato rispetto a prima (era 18px fisso): #hud (barra stat) si è
     spostato da alto-sinistra ad alto-centro (vedi #hud sopra), quindi
     questo banner — anch'esso centrato in orizzontale — ora gli sta
     esattamente sotto invece che affiancato. Il top è un calc() che
     RIPRODUCE la stessa formula di scala di #hud (12px di offset +
     --hud-card-natural-height scalata da calc(2 * --ui-scale *
     --touch-viewport-scale), vedi :root) più un margine fisso di 12px —
     non un px statico: un fisso andava bene solo a --ui-scale=100% (12 +
     42*2 + 12 = 108px), ma #hud cresce col FATTORE 2x mentre un top statico
     no, quindi da --ui-scale ~114%+ (verificato: 84*scale supera i 96px di
     margine implicito nel vecchio 108px fisso) il banner ci finiva sotto —
     bug visibile già ben prima della soglia 130% ipotizzata, conclamato a
     150%. Split-screen: #hud usa questa STESSA formula piena anche lì
     (applySplitScreenPositioning in main.js non la sovrascrive più, vedi
     bug del report — #hud non si rimpicciolisce più in base a N), quindi
     il calc() resta esatto in ogni modalità, non solo a schermo intero. */
  top: calc(12px + (var(--hud-card-natural-height) * 2 * var(--ui-scale, 1) * var(--touch-viewport-scale, 1)) + 12px);
  left: 50%;
  transform: translateX(-50%) scale(var(--ui-scale, 1));
  background: rgba(90, 62, 30, 0.92);
  border: 2px solid rgba(222, 184, 135, 0.8);
  color: #fff;
  padding: 14px 26px;
  border-radius: 12px;
  font-size: 18px;
  font-weight: bold;
  text-align: center;
  max-width: 80vw;
  z-index: 11;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.4s ease;
}

#important-banner.important-banner-fade-out, [data-role="important-banner"].important-banner-fade-out {
  opacity: 0;
}

/* Variante rossa (stessi colori "pericolo" di #center-banner/#idle-warning
   originale: #ff5252 / rgba(120,20,20,...)) — stessa forma/font/animazione
   del banner marrone-oro sopra, solo la palette cambia. */
#important-banner.important-banner-danger, [data-role="important-banner"].important-banner-danger {
  background: rgba(120, 20, 20, 0.85);
  border-color: rgba(255, 82, 82, 0.7);
}

/* Variante countdown "licenziamento per pigrizia" (main.js,
   afkFireCountdownActive): stesso sfondo/bordo del banner-danger sopra, ma
   testo rosso pieno invece di bianco — l'ultimo avviso prima della morte
   AFK, deve leggersi a colpo d'occhio come il più urgente dei banner. */
#important-banner.important-banner-fire-warning, [data-role="important-banner"].important-banner-fire-warning {
  background: rgba(120, 20, 20, 0.85);
  border-color: rgba(255, 82, 82, 0.7);
  color: #ff5252;
}

#kill-feed {
  position: fixed;
  top: 90px;
  left: 68%;
  transform: translateX(-50%) scale(var(--ui-scale, 1));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  z-index: 7;
  pointer-events: none;
}

.kill-feed-entry {
  background: rgba(0,0,0,0.6);
  color: #fff;
  padding: 6px 14px;
  border-radius: 6px;
  font-size: 13px;
  white-space: nowrap;
  animation: kill-feed-rise 2.5s ease-out forwards;
}

@keyframes kill-feed-rise {
  0%   { opacity: 0; transform: translateY(10px); }
  10%  { opacity: 1; transform: translateY(0); }
  75%  { opacity: 1; transform: translateY(-10px); }
  100% { opacity: 0; transform: translateY(-40px); }
}

/* Barra di scelta non invasiva: niente overlay a schermo intero che
   blocca la visuale e le azioni di gioco. Resta compatta, in alto, semi-
   trasparente — puoi continuare a muoverti e combattere mentre scegli. */
#quit-confirm-modal, [data-role="quit-confirm-modal"] {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%) scale(var(--ui-scale, 1));
  background: rgba(20, 24, 32, 0.75);
  border-radius: 10px;
  padding: 10px 18px;
  z-index: 9;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.4);
  max-width: min(680px, 94vw);
  max-height: 80vh;
  overflow-y: auto;
  box-sizing: border-box;
}

.top-bar-label {
  color: #f2f2f2;
  font-size: 14px;
  white-space: normal;
  text-align: center;
}

#retired-overlay, [data-role="retired-overlay"] {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(14, 17, 22, 0.9);
  z-index: 10;
}

#retired-box, [data-role="retired-box"] {
  background: #1b1f27;
  border-radius: 12px;
  padding: 28px 32px;
  text-align: center;
  color: #f2f2f2;
}

#gameover-overlay, [data-role="gameover-overlay"] {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 8, 8, 0.92);
  z-index: 11;
}

#gameover-box, [data-role="gameover-box"] {
  background: #271b1b;
  border: 1px solid rgba(255,82,82,0.4);
  border-radius: 12px;
  padding: 28px 32px;
  text-align: center;
  color: #f2f2f2;
  max-width: 360px;
}

#gameover-box button, [data-role="gameover-box"] button {
  margin-top: 16px;
  padding: 10px 24px;
  border-radius: 6px;
  border: none;
  background: #ff5252;
  color: white;
  font-size: 16px;
  cursor: pointer;
}

.powerup-option {
  padding: 8px 14px;
  border-radius: 8px;
  border: 2px solid transparent;
  background: #2a2f3a;
  color: #fff;
  cursor: pointer;
  font-size: 13px;
  white-space: normal;
  max-width: 240px;
  text-align: center;
}

.powerup-option:hover {
  border-color: #4caf50;
}

#retired-box button, [data-role="retired-box"] button {
  margin-top: 16px;
  padding: 10px 24px;
  border-radius: 6px;
  border: none;
  background: #4caf50;
  color: white;
  font-size: 16px;
  cursor: pointer;
}

/* Controlli touch: nascosti di default, mostrati solo su dispositivi a
   puntamento "grezzo" (dita) senza hover — cioè telefoni/tablet, non mouse. */
#touch-controls {
  display: none;
}

@media (hover: none) and (pointer: coarse) {
  #touch-controls {
    display: block;
  }
  /* Su touch il pannello DNA Beaver (in ENTRAMBE le varianti, Ristretta e
     Completa) resta assente — sostituito dal tasto Shop + torta a spicchi.
     Rimosso di nuovo dopo un tentativo di mostrarlo anche qui (era
     display:none anche prima del rework sola-visualizzazione): l'idea è
     rimandata, non scartata — se tornerà, richiederà comunque di
     riprendere il riposizionamento sopra il joystick già sperimentato qui. */
  #shop-panel, [data-role="shop-panel"] {
    display: none !important;
  }
}

/* Sfondo live dell'hub di login: sull'hub non c'è nessun Player reale da
   controllare, quindi i controlli touch (altrimenti mostrati dalla media
   query sopra a prescindere dallo stato di partita) vanno nascosti finché
   non si preme "Gioca" — vedi la classe sul <body> impostata/rimossa in
   main.js. */
body.on-login-screen #touch-controls {
  display: none !important;
}

/* Su schermi touch grandi, tutto è ingrandito del 50% — soglia alzata da
   600 a 720px: con zaino e Shop ora SEMPRE visibili (prima sparivano
   quando non servivano), la fila di bottoni è più larga stabilmente, e
   sotto i 720px l'ingrandimento la faceva sovrapporre al joystick. */
@media (hover: none) and (pointer: coarse) and (min-width: 720px) {
  #joystick-base {
    width: 165px;
    height: 165px;
  }
  #joystick-knob {
    width: 69px;
    height: 69px;
    margin-left: -34.5px;
    margin-top: -34.5px;
  }
  #action-buttons {
    gap: 21px;
    right: 36px;
  }
  #kill-btn, #dash-btn, #shop-btn, .item-slot-btn {
    width: 105px;
    height: 105px;
    font-size: 18px;
  }
  .item-slot-btn {
    font-size: 33px;
  }
}

#joystick-base {
  position: fixed;
  left: 30px;
  bottom: 30px;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  border: 2px solid rgba(255,255,255,0.25);
  z-index: 6;
  touch-action: none;
}

#joystick-knob {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 46px;
  margin-left: -23px;
  margin-top: -23px;
  border-radius: 50%;
  background: rgba(255,255,255,0.4);
  pointer-events: none;
  transition: transform 0.05s linear;
}

#action-buttons {
  position: fixed;
  right: 24px;
  bottom: 30px;
  display: flex;
  gap: 14px;
  z-index: 6;
}

/* Su telefoni stretti, 4 bottoni sempre visibili (zaino+Shop+Kill+Dash) in
   una sola fila si sovrappongono al joystick. Sotto i 520px si impilano su
   2 righe (zaino+Shop sopra, Kill+Dash sotto, dove sono sempre stati) —
   il bottone OK resta ancorato all'angolo in basso a destra del
   contenitore (posizionamento assoluto), quindi copre comunque Kill+Dash. */
@media (hover: none) and (pointer: coarse) and (max-width: 520px) {
  #action-buttons {
    flex-wrap: wrap;
    justify-content: flex-end;
    width: 160px;
  }
}

#kill-btn, #dash-btn, #shop-btn {
  position: relative;
  width: 70px;
  height: 70px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.3);
  color: #fff;
  font-size: 12px;
  line-height: 1.3;
  touch-action: none;
  user-select: none;
  overflow: hidden;
}

#kill-btn span, #dash-btn span {
  position: relative;
  z-index: 2;
}

/* Spicchio scuro che si restringe mano a mano che l'abilità ricarica:
   parte pieno (appena usata) e si svuota fino a sparire (pronta). */
.cd-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: conic-gradient(rgba(0,0,0,0.6) var(--cd-deg, 0deg), transparent var(--cd-deg, 0deg));
  pointer-events: none;
}

#kill-btn {
  background: rgba(255, 82, 82, 0.35);
}

/* Stato di scontro (hai attaccato o sei stato colpito negli ultimi 5s):
   stesso tasto Kill, solo più rosso/saturo — nessuna icona in più. */
#kill-btn.in-combat {
  background: rgba(255, 0, 0, 0.65);
  border-color: rgba(255, 0, 0, 0.9);
}

#dash-btn {
  background: rgba(77, 159, 255, 0.35);
}

#shop-btn {
  background: rgba(255, 214, 102, 0.3);
  border-color: rgba(255, 214, 102, 0.6);
}

/* Slot abilità (0 e 1): stesso stile del bottone item di prima, ma sono
   due e mostrano l'icona dell'abilità tenuta in quello slot (impostata via
   JS). Nascosti (.hidden) quando lo slot è vuoto. */
.item-slot-btn {
  position: relative;
  width: 70px;
  height: 70px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.3);
  background: rgba(179, 136, 255, 0.35);
  color: #fff;
  font-size: 26px;
  touch-action: none;
  user-select: none;
  overflow: hidden;
}

/* Tenendo premuto (invece di un tap secco), l'item si "scarica" e droppa a
   terra da solo, senza aspettare il rilascio: questa barra rossa che
   cresce da sinistra è il feedback visivo di quel countdown. La durata
   DEVE combaciare con HOLD_TO_DROP_MS in input.js (450ms). */
.item-slot-btn.discharging::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 50, 50, 0.55);
  transform-origin: left center;
  transform: scaleX(0);
  animation: item-discharge 0.45s linear forwards;
  pointer-events: none;
}

@keyframes item-discharge {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* Bottone OK gigante: appare al posto di Kill+Dash durante la scelta DNA
   sulla torta a spicchi (li sostituisce visivamente, non gli si affianca).
   Posizionamento ASSOLUTO (non un fratello flex): copre esattamente l'area
   di Kill+Dash senza mai contare nella larghezza della fila — altrimenti,
   riservando sempre il suo spazio, allargava la fila abbastanza da farla
   sovrapporre al joystick su schermi di media larghezza. */
#powerup-ok-btn {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,0.6);
  background: rgba(76, 175, 80, 0.6);
  color: #fff;
  font-size: 16px;
  font-weight: bold;
  line-height: 1.3;
  touch-action: none;
  user-select: none;
}

/* Solo su desktop (mouse, non touch): il pannello DNA resta LO STESSO
   pannello (in comune con la sua taglia base), solo un po' più leggibile
   (1.3x: a piena taglia diventava ingombrante, con 8 righe di stat). HUD e
   leaderboard hanno invece la stessa scala fissa 2x su ogni dispositivo
   (vedi #hud/#leaderboard-panel più sopra), quindi non compaiono qui.
   transform-origin ancorato allo stesso angolo del posizionamento fixed del
   pannello, così cresce "verso l'interno" dello schermo invece che uscire
   dal bordo. */
@media (hover: hover) and (pointer: fine) {
  #shop-panel {
    transform: scale(calc(1.3 * var(--ui-scale, 1)));
    transform-origin: bottom left;
  }
}
