/* ==========================================================================
   Minimal System — Companion App
   Palette, tipografia e componenti derivati da style_guide_aggiornata.md
   (direzione "Interfaccia da Gioco"). Le regole di impaginazione A4 non si
   applicano qui: questa è un'interfaccia app, non una pagina stampata —
   restano fissi però palette, font, accento fisico/magico e stile dei box.
   ========================================================================== */

:root{
  --antracite-1:#14161A;
  --antracite-2:#1E2126;
  --bordo-scuro:#4A4F58;
  --bianco-artico:#F7F9FA;
  --testo-primario-dark:#F2F1ED;
  --testo-secondario-dark:#9CA0A8;
  --testo-secondario-dark-2:#C7CAD1;
  --testo-primario-light:#14161A;
  --testo-secondario-light:#6B7178;

  --fisico:#E8621F;
  --fisico-forte:#FF7A33;
  --magico:#1BB5C7;
  --magico-forte:#33D6E8;
  --incremento:#C9A227;
  --incremento-forte:#FFD873;
  --equip-momentaneo:#3DDC84;
  --equip-momentaneo-forte:#6BFFAF;

  --font-title:'Rajdhani',sans-serif;
  --font-body:'Inter',sans-serif;
  --font-mono:'JetBrains Mono',monospace;

  --radius:9px;
  --radius-sm:6px;
  --gap-min:16px;

  --safe-top:env(safe-area-inset-top,0);
  --safe-bottom:env(safe-area-inset-bottom,0);
}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
  background:var(--antracite-1);
  color:var(--testo-primario-dark);
  font-family:var(--font-body);
  -webkit-tap-highlight-color:transparent;
  overscroll-behavior-y:none;
}
h1,h2,h3,h4{font-family:var(--font-title);margin:0;}
p{margin:0 0 .8em;line-height:1.6;}
button{font-family:var(--font-body);}
input,select,textarea{font-family:var(--font-body);}
::selection{background:var(--fisico);color:var(--antracite-1);}

.hidden{display:none !important;}

/* ---------- App shell ---------- */
/* Tre livelli in cascata, dal meno al più preciso: 100vh (sempre valido),
   100dvh (più preciso dove supportato), --real-vh calcolato da JS in
   index.html sull'altezza DAVVERO visibile (window.innerHeight/
   visualViewport) — necessario perché su alcuni Android 100dvh non
   corrisponde all'area realmente visibile, lasciando lo sfondo scuro
   della pagina scoperto sotto il contenuto dell'app. */
#app{
  min-height:100vh;
  min-height:100dvh;
  min-height:calc(var(--real-vh, 1vh) * 100);
  display:flex;
  flex-direction:column;
}
.view{
  flex:1;
  display:flex;
  flex-direction:column;
  min-height:100vh;
  min-height:100dvh;
  min-height:calc(var(--real-vh, 1vh) * 100);
}

/* ---------- Copertina ---------- */
#view-cover{
  position:relative;
  background:#050608; /* stesso nero di fondo delle immagini di titolo/logo */
  /* niente più justify-content:flex-end + immagine flex:1 che si schiacciava
     con l'altezza della finestra: titolo e logo hanno una dimensione fissa
     (vedi sotto), quindi se lo spazio verticale non basta è la pagina a
     scorrere (esattamente come già succede con motto e bottoni sotto),
     non un rimpicciolimento dell'immagine. */
}
.cover-header{
  flex:none;
  display:flex;
  flex-direction:column;
  align-items:center;
  padding:calc(28px + var(--safe-top)) 24px 0;
}
.cover-title{
  flex:none;
  width:100%;
  max-width:320px;
  height:auto;
  display:block;
}
/* Nella copertina originale il cerchio ha praticamente la stessa larghezza
   del titolo (non un terzo, come restava qui prima): stessa larghezza
   massima di .cover-title per rispettarne le proporzioni. */
.cover-logo{
  flex:none;
  width:100%;
  max-width:300px;
  height:auto;
  margin-top:10px;
}
.cover-content{
  position:relative;
  z-index:2;
  flex:1;
  padding:24px 24px max(68px, calc(36px + var(--safe-bottom)));
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
  gap:18px;
}
.cover-actions{
  width:100%;
  max-width:360px;
  display:flex;
  flex-direction:column;
  gap:12px;
  margin-top:6px;
  text-align:left;
}
/* Motto ("da una semplice idea a infinite possibilità"): prima faceva parte
   dell'immagine di copertina, ora è testo vero. margin-top:auto lo spinge
   sempre in fondo alla pagina (.cover-content è flex:1) qualunque sia
   l'altezza del modulo di accesso sopra di lui, invece di seguirlo a ruota
   e finire a metà schermo quando quel modulo è basso. */
.cover-tagline{
  width:100%;
  max-width:360px;
  margin-top:auto;
  color:var(--testo-secondario-dark-2);
  font-size:13px;
  letter-spacing:.02em;
  text-align:center;
}
.cover-tagline-row{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:10px;
}
.cover-tagline-row .ct-line{
  flex:1 1 40px;
  max-width:70px;
  height:1px;
  background:var(--bordo-scuro);
}
/* Le due righe del motto sono un unico blocco: le lineette si centrano
   sull'intero blocco (align-items:center sulla riga), non solo sulla prima
   riga di testo come accadeva quando "a infinite possibilità" stava fuori
   da .cover-tagline-row, sotto, senza lineette accanto. */
.ct-text-block{
  flex:0 0 auto;
  display:flex;
  flex-direction:column;
  gap:2px;
}
.cover-tagline-row .ct-text{
  white-space:nowrap;
}

/* ---------- Avviso aggiornamento (solo app nativa) ---------- */
.update-banner{
  width:100%;
  max-width:360px;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:12px;
  background:var(--antracite-2);
  border:1px solid var(--fisico);
  border-radius:var(--radius);
  padding:10px 14px;
}
.update-banner .ub-text{
  flex:1;
  text-align:left;
  font-size:12.5px;
  color:var(--testo-secondario-dark-2);
  line-height:1.4;
}
.update-banner .btn{flex:none;}

/* ---------- Menù copertina (hamburger + indice) ---------- */
.cover-menu-btn{
  position:absolute;
  top:calc(16px + var(--safe-top));
  right:16px;
  z-index:10;
  width:44px;height:44px;
  display:flex;align-items:center;justify-content:center;
  background:rgba(30,33,38,.75);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius-sm);
  cursor:pointer;
  backdrop-filter:blur(4px);
  -webkit-backdrop-filter:blur(4px);
  transition:transform .12s ease, border-color .12s ease;
}
.cover-menu-btn:active{transform:scale(.94);}
.cover-menu-btn .menu-lines{
  display:flex;flex-direction:column;gap:5px;width:20px;
}
.cover-menu-btn .menu-lines span{
  display:block;height:2px;width:100%;
  background:var(--testo-primario-dark);
  border-radius:1px;
  transition:transform .18s ease, opacity .18s ease;
}
.cover-menu-btn[aria-expanded="true"]{border-color:var(--fisico-forte);}
.cover-menu-btn[aria-expanded="true"] .menu-lines span:nth-child(1){transform:translateY(7px) rotate(45deg);}
.cover-menu-btn[aria-expanded="true"] .menu-lines span:nth-child(2){opacity:0;}
.cover-menu-btn[aria-expanded="true"] .menu-lines span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}

.cover-menu{
  position:absolute;
  top:calc(66px + var(--safe-top));
  right:16px;
  z-index:9;
  min-width:230px;
  max-height:calc(100vh - 90px - var(--safe-top) - var(--safe-bottom));
  overflow-y:auto;
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:8px;
  display:flex;flex-direction:column;gap:2px;
  box-shadow:0 12px 32px rgba(0,0,0,.55);
  animation:cover-menu-in .16s ease;
}
@keyframes cover-menu-in{
  from{opacity:0;transform:translateY(-6px);}
  to{opacity:1;transform:translateY(0);}
}
.cover-menu .cm-label{
  font-family:var(--font-title);font-weight:600;font-size:10px;
  text-transform:uppercase;letter-spacing:.14em;
  color:var(--testo-secondario-dark);
  padding:8px 12px 4px;
}
.cover-menu .cm-sep{
  height:1px;background:var(--bordo-scuro);
  margin:6px 4px;
}
.cover-menu .cm-item{
  display:block;width:100%;text-align:left;
  background:transparent;border:none;cursor:pointer;
  font-family:var(--font-title);font-weight:600;font-size:13.5px;
  text-transform:uppercase;letter-spacing:.06em;
  color:var(--testo-primario-dark);
  padding:10px 12px;
  border-radius:var(--radius-sm);
  transition:background .12s ease, color .12s ease;
}
.cover-menu .cm-item:hover,.cover-menu .cm-item:focus-visible{
  background:rgba(255,255,255,.06);
  color:var(--fisico-forte);
  outline:none;
}
.cover-menu .cm-item:active{background:rgba(255,255,255,.1);}

/* ---------- Buttons ---------- */
.btn{
  font-family:var(--font-title);
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:.08em;
  font-size:13px;
  border-radius:var(--radius);
  border:1px solid var(--bordo-scuro);
  background:var(--antracite-2);
  color:var(--testo-primario-dark);
  padding:14px 18px;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:8px;
  cursor:pointer;
  transition:transform .12s ease, border-color .12s ease, background .12s ease;
}
.btn:active{transform:scale(.97);}
.btn-primary{
  background:var(--fisico);
  border-color:var(--fisico);
  color:var(--antracite-1);
}
.btn-magic{
  background:var(--magico);
  border-color:var(--magico);
  color:var(--antracite-1);
}
.btn-ghost{
  background:transparent;
  border-color:var(--bordo-scuro);
  color:var(--testo-secondario-dark-2);
}
.btn-sm{padding:8px 12px;font-size:11px;}
.btn-icon{
  width:40px;height:40px;padding:0;border-radius:var(--radius-sm);
  flex:none;
}
.btn:disabled{opacity:.35;cursor:not-allowed;transform:none;}

/* ---------- Lista personaggi ---------- */
#view-list{background:var(--antracite-1);}
.topbar{
  display:flex;align-items:center;gap:12px;
  padding:calc(18px + var(--safe-top)) 20px 14px;
  border-bottom:1px solid var(--bordo-scuro);
}
.topbar h1{
  font-size:15px;text-transform:uppercase;letter-spacing:.12em;
  color:var(--testo-secondario-dark-2);flex:1;
}
.list-scroll{flex:1;overflow-y:auto;padding:16px 16px var(--safe-bottom);}
.char-card{
  display:flex;align-items:center;gap:14px;
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:14px 14px;
  margin-bottom:12px;
}
.char-card .avatar{
  width:44px;height:44px;border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-title);font-weight:700;font-size:16px;
  flex:none;
}
.avatar.physical{background:rgba(232,98,31,.16);color:var(--fisico-forte);border:1px solid var(--fisico);}
.avatar.magic{background:rgba(27,181,199,.16);color:var(--magico-forte);border:1px solid var(--magico);}
.avatar.bicolor{background:linear-gradient(135deg, rgba(232,98,31,.2), rgba(27,181,199,.2));color:var(--bianco-artico);border:1px solid var(--bordo-scuro);}
.char-card .info{flex:1;min-width:0;}
.char-card .name{font-family:var(--font-title);font-weight:600;font-size:16px;}
.char-card .meta{font-size:12px;color:var(--testo-secondario-dark);margin-top:2px;}
.empty-state{
  text-align:center;color:var(--testo-secondario-dark);
  padding:60px 20px;font-size:13px;line-height:1.7;
}

/* ---------- Scheda: layout ---------- */
#view-sheet{background:var(--antracite-1);}
.sheet-header{
  padding:calc(14px + var(--safe-top)) 16px 10px;
  border-bottom:1px solid var(--bordo-scuro);
  display:flex;align-items:center;gap:10px;
}
.sheet-header .who{flex:1;min-width:0;}
.sheet-header .name-input{
  background:transparent;border:none;color:var(--testo-primario-dark);
  font-family:var(--font-title);font-weight:700;font-size:18px;
  width:100%;padding:2px 0;
}
.sheet-header .sub{font-size:11px;color:var(--testo-secondario-dark);text-transform:uppercase;letter-spacing:.08em;}

.tabs{
  display:flex;overflow-x:auto;gap:4px;
  padding:8px 12px;
  border-bottom:1px solid var(--bordo-scuro);
  -webkit-overflow-scrolling:touch;
}
.tabs::-webkit-scrollbar{display:none;}
.tab-btn{
  flex:none;
  font-family:var(--font-title);font-weight:600;font-size:11.5px;
  text-transform:uppercase;letter-spacing:.06em;
  color:var(--testo-secondario-dark);
  background:transparent;border:1px solid transparent;
  border-radius:999px;padding:8px 14px;cursor:pointer;
}
.tab-btn.active{
  color:var(--antracite-1);
  background:var(--bianco-artico);
  border-color:var(--bianco-artico);
}

.sheet-body{flex:1;overflow-y:auto;padding:18px 16px var(--safe-bottom);}
.tab-panel{display:none;flex-direction:column;gap:18px;}
.tab-panel.active{display:flex;}

/* ---------- Section / Box ---------- */
.section-title{
  font-family:var(--font-title);font-weight:600;font-size:12.5px;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--testo-secondario-dark-2);
  display:flex;align-items:center;gap:8px;
}
.section-title .dot{width:6px;height:6px;border-radius:50%;background:var(--fisico-forte);}
.section-title .dot.magic{background:var(--magico-forte);}
.section-title .dot.neutral{background:var(--testo-secondario-dark);}

.box{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  overflow:hidden;
}
.box-bar{height:3px;width:100%;background:var(--testo-secondario-dark);}
.box-bar.physical{background:linear-gradient(90deg,var(--fisico),var(--fisico-forte));}
.box-bar.magic{background:linear-gradient(90deg,var(--magico),var(--magico-forte));}
.box-bar.bicolor{background:linear-gradient(90deg,var(--fisico-forte),var(--magico-forte));}
.box-pad{padding:14px 14px 16px;}

.box-lore{
  background:rgba(255,255,255,0.03);
  border-radius:var(--radius);
  padding:12px 14px;
  font-style:italic;
  color:var(--testo-secondario-dark-2);
  font-size:12.5px;
  line-height:1.6;
}

/* ---------- Build cards ---------- */
.build-grid{display:flex;flex-direction:column;gap:10px;}
.build-card{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:14px;
  display:flex;flex-direction:column;gap:8px;
  cursor:pointer;
  position:relative;
}
.build-card.selected{border-color:var(--fisico-forte);box-shadow:0 0 0 1px var(--fisico-forte) inset;}
.build-card.selected.magic-sel{border-color:var(--magico-forte);box-shadow:0 0 0 1px var(--magico-forte) inset;}
.build-card.selected.bicolor-sel{border-color:var(--bianco-artico);box-shadow:0 0 0 1px var(--bianco-artico) inset;}
.build-card.selected.bicolor-sel .bc-radio{border-color:var(--bianco-artico);}
.build-card.selected.bicolor-sel .bc-radio::after{background:var(--bianco-artico);}
.build-card .bc-top{display:flex;align-items:center;justify-content:space-between;}
.build-card .bc-name{font-family:var(--font-title);font-weight:700;font-size:16px;text-transform:uppercase;}
.build-card .bc-radio{width:18px;height:18px;border-radius:50%;border:2px solid var(--bordo-scuro);flex:none;position:relative;}
.build-card.selected .bc-radio{border-color:var(--fisico-forte);}
.build-card.selected .bc-radio::after{content:'';position:absolute;inset:3px;border-radius:50%;background:var(--fisico-forte);}
.build-card.selected.magic-sel .bc-radio{border-color:var(--magico-forte);}
.build-card.selected.magic-sel .bc-radio::after{background:var(--magico-forte);}
.build-card.locked{opacity:.35;pointer-events:none;}
.bc-stats{display:flex;gap:16px;font-family:var(--font-mono);font-size:12px;color:var(--testo-secondario-dark-2);}

/* Dialogo di conferma (classe, statistiche primarie...) */
.confirm-modal{
  position:fixed;inset:0;z-index:90;
  background:rgba(8,9,11,0.8);
  display:flex;align-items:center;justify-content:center;
  padding:24px;
}
.confirm-modal .cc-box{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:20px 18px;
  max-width:340px;width:100%;
  box-shadow:0 18px 50px rgba(0,0,0,.6);
}
.confirm-modal .cc-title{
  font-family:var(--font-title);font-weight:700;font-size:15px;
  text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px;
}
.confirm-modal p{font-size:13px;color:var(--testo-secondario-dark-2);line-height:1.55;margin:0 0 16px;}
.confirm-modal .cc-actions{display:flex;gap:10px;}
/* Voce del menu Tecniche/Abilità in combattimento (#combat-source-list),
   PRIMA di scegliere il bersaglio: nome a sinistra, dettaglio abbreviato
   (danno+statistica, effetto→tratto di salvezza) a destra — invece
   dell'unica etichetta centrata usata da armi/boost/oggetti. */
.cmb-source-btn{display:flex;justify-content:space-between;align-items:center;gap:10px;text-align:left;}
.cmb-source-label{flex:1;min-width:0;}
.cmb-source-desc{
  flex:none;font-family:var(--font-mono);font-size:11px;
  color:var(--testo-secondario-dark-2);white-space:nowrap;
}
.confirm-modal .cc-actions .btn{flex:1;}

/* Conflitto di sincronizzazione (vedi promptSyncConflict in app.js): due
   "carte" affiancate, una per versione, con volto + un riepilogo statistico
   invece di un'etichetta generica "questo dispositivo/cloud" — la scelta si
   fa guardando quale scheda è davvero più sviluppata, non a chi appartiene. */
.sync-conflict-versions{display:flex;gap:10px;}
.sync-conflict-version{
  flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:14px 8px;border:1px solid var(--bordo-scuro);border-radius:var(--radius);
  background:var(--antracite-1);cursor:pointer;text-align:center;
  font-family:var(--font-body);color:var(--testo-primario-dark);
  transition:border-color .15s;
}
.sync-conflict-version:hover,.sync-conflict-version:active{border-color:var(--fisico-forte);}
.scv-avatar{
  width:64px;height:64px;flex:none;border-radius:50%;
  background-color:var(--antracite-2);background-size:cover;background-position:center;
  border:1px solid var(--bordo-scuro);
}
.scv-label{font-size:11.5px;line-height:1.5;color:var(--testo-secondario-dark-2);}
.scv-label b{display:block;color:var(--testo-primario-dark);font-family:var(--font-title);font-size:13px;margin-bottom:2px;}
.bc-stats b{color:var(--testo-primario-dark);}
.bc-meta{font-size:11.5px;color:var(--testo-secondario-dark);}
.swap-row{display:flex;align-items:center;gap:10px;margin-top:4px;}
.swap-row .btn-sm{flex:none;}

/* ---------- Wizard di creazione personaggio (view-create) ---------- */
#view-create{background:var(--antracite-1);}
.wiz-header{
  padding:calc(14px + var(--safe-top)) 16px 10px;
  border-bottom:1px solid var(--bordo-scuro);
  display:flex;align-items:center;gap:10px;
}
.wiz-progress{flex:1;display:flex;justify-content:center;gap:6px;}
.wiz-dot{width:7px;height:7px;border-radius:50%;background:var(--bordo-scuro);flex:none;}
.wiz-dot.active{background:var(--fisico-forte);}
.wiz-dot.done{background:var(--testo-secondario-dark-2);}

.wiz-body{flex:1;overflow:hidden;display:flex;flex-direction:column;}
.wiz-step{display:none;flex:1;flex-direction:column;gap:18px;padding:18px 16px;overflow-y:auto;}
.wiz-step.active{display:flex;}

/* Il passo "narrative" (Identità/Ritratto + Background + Relazioni) non
   scorre verticalmente come gli altri step: è un carosello orizzontale a
   schede, ogni scheda occupa tutta la larghezza disponibile. */
.wiz-step[data-wizstep="narrative"]{overflow:hidden;padding:0;}
.wiz-narrative-track{
  flex:1;display:flex;
  transition:transform .25s ease;
  will-change:transform;
}
.wiz-narrative-card{
  flex:0 0 100%;
  min-width:0;
  overflow-y:auto;
  padding:18px 16px;
  display:flex;flex-direction:column;gap:18px;
}
.wiz-nav{
  flex:none;
  position:sticky;bottom:0;
  display:flex;gap:10px;
  padding:12px 16px calc(12px + var(--safe-bottom));
  border-top:1px solid var(--bordo-scuro);
  background:var(--antracite-1);
}
.wiz-nav .btn{flex:1;}
.wiz-nav .btn:disabled{opacity:.35;pointer-events:none;}

/* ---------- Le regole: indice per capitoli + pagina di capitolo ---------- */
/* Voce dell'indice (un "raccoglitore"/capitolo): stesso stile scuro dei
   bottoni di navigazione già in uso altrove nell'app, la freccia indica che
   si entra in una pagina, non che si espande sul posto. */
.rule-title{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:10px;
  background:var(--antracite-2);border:1px solid var(--bordo-scuro);border-radius:var(--radius);
  color:var(--testo-primario-dark);
  font-family:var(--font-title);font-weight:700;font-size:14px;
  text-transform:uppercase;letter-spacing:.06em;
  padding:13px 14px;cursor:pointer;text-align:left;
}
.rules-index-item{margin-bottom:10px;}
.rule-title .arrow{color:var(--testo-secondario-dark);}
/* Capitolo aperto: pop-up a schermo intero sopra l'indice, stessa
   struttura del lettore PDF della premessa (head fisso + corpo scorrevole). */
#rules-popup{
  position:fixed;inset:0;z-index:95;
  background:#0b0c10;
  display:flex;flex-direction:column;
}
/* Libreria "Ambientazioni" della campagna (Gestisci > Ambientazioni):
   stesso guscio a schermo intero di #rules-popup/#pdf-viewer, ma il corpo
   è una griglia in stile galleria foto invece di testo scorrevole. */
#campaign-assets-popup{
  position:fixed;inset:0;z-index:95;
  background:#0b0c10;
  display:flex;flex-direction:column;
}
.asset-gallery-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(96px,1fr));
  gap:20px 12px;
  padding:14px 16px calc(14px + var(--safe-bottom));
}
.asset-gallery-tile{display:flex;flex-direction:column;gap:6px;}
.asset-gallery-name{
  font-size:10.5px;font-weight:600;text-align:center;line-height:1.3;
  color:var(--testo-secondario-dark-2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;text-overflow:ellipsis;
  min-height:2.6em;
}
.asset-gallery-thumb{
  position:relative;aspect-ratio:1;
  border-radius:var(--radius-sm);border:1px solid var(--bordo-scuro);
  background:var(--antracite-1) center/cover no-repeat;
  overflow:hidden;cursor:pointer;
}
.asset-gallery-thumb .ag-del{
  position:absolute;top:4px;right:4px;z-index:1;
  width:22px;height:22px;border-radius:50%;border:none;
  background:rgba(8,9,11,.65);color:#fff;font-size:12px;
  display:flex;align-items:center;justify-content:center;
}
.asset-gallery-add{
  aspect-ratio:1;border-radius:var(--radius-sm);
  border:1px dashed var(--bordo-scuro);background:transparent;
  display:flex;align-items:center;justify-content:center;
  font-size:26px;color:var(--testo-secondario-dark);
}
.asset-gallery-add:active{background:rgba(255,255,255,.05);}
/* Copertina illustrata di una sezione (quando esiste in
   RULES_SECTION_COVERS): a piena larghezza, prima del titolo. */
.rule-cover{
  width:100%;height:auto;display:block;
  border-radius:var(--radius);
  margin:14px 0;
}
.rule-cover:first-child{margin-top:0;}
/* Corpo testuale di una sezione dentro la pagina di un capitolo: stesso
   .box usato in tutta l'app, sempre leggibile per intero (niente accordion
   da espandere: sei già entrato nel capitolo apposta per leggerlo). */
.rule-text{
  font-size:13px;line-height:1.65;color:var(--testo-secondario-dark-2);
  white-space:pre-wrap;
  overflow-wrap:break-word;
  text-align:justify;text-align-last:left;
  hyphens:auto;word-spacing:normal;
}
.rule-text strong{color:var(--testo-primario-dark);font-weight:700;}
/* Introduzione dell'intero capitolo (RULES_CHAPTER_INTROS): fuori dai box
   delle sotto-sezioni, corsivo per distinguerla dal resto del testo. */
.rule-intro{
  margin:14px 0 4px;
  font-style:italic;
  color:var(--testo-primario-dark);
}

/* ---------- Premesse di gioco ---------- */
.prem-row{
  display:flex;align-items:flex-start;gap:10px;
  padding:9px 10px;background:var(--antracite-1);
  border:1px solid var(--bordo-scuro);border-radius:var(--radius-sm);
  margin-bottom:8px;
}
.prem-row input[type=checkbox]{width:18px;height:18px;margin-top:1px;accent-color:var(--fisico-forte);flex:none;}
.prem-row .pr-main{flex:1;min-width:0;}
.prem-row .pr-title{font-family:var(--font-title);font-weight:600;font-size:13.5px;}
.prem-row .pr-text{font-size:12.5px;color:var(--testo-secondario-dark-2);line-height:1.55;margin-top:4px;white-space:pre-wrap;}
.prem-row .btn-del{flex:none;opacity:.6;}
#prem-popup{
  position:fixed;inset:0;z-index:85;
  background:rgba(8,9,11,0.85);
  display:flex;align-items:center;justify-content:center;
  padding:20px 14px;
}
#prem-popup .pp-box{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:16px;
  width:100%;max-width:420px;
  max-height:86vh;overflow-y:auto;
  display:flex;flex-direction:column;gap:10px;
}
#prem-popup .pp-head{display:flex;align-items:center;justify-content:space-between;gap:10px;}
#prem-popup .pp-list{display:flex;flex-direction:column;}

/* ---------- Volto del personaggio ---------- */
.portrait-pad{display:flex;align-items:flex-start;gap:14px;}
.portrait-frame{
  width:150px;height:150px;flex:none;
  border-radius:var(--radius);
  border:1px solid var(--bordo-scuro);
  background:var(--antracite-1) center/cover no-repeat;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
  cursor:pointer;
}
.portrait-placeholder{font-size:10px;color:var(--testo-secondario-dark);text-align:center;padding:4px;line-height:1.5;}
.portrait-actions{display:flex;flex-direction:column;gap:10px;align-items:stretch;flex:1;min-width:0;}

/* Lightbox di ingrandimento del volto */
#portrait-lightbox{
  position:fixed;inset:0;z-index:80;
  background:rgba(8,9,11,0.92);
  display:flex;align-items:center;justify-content:center;
  padding:56px 16px 24px;
}
/* ---------- Visualizzatore PDF (premesse di gioco) ---------- */
body.pdf-lock-scroll{overflow:hidden;}
#pdf-viewer{
  position:fixed;inset:0;z-index:95;
  background:#0b0c10;
  display:flex;flex-direction:column;
}
.pdfv-head{
  display:flex;align-items:center;gap:10px;flex:none;
  padding:calc(10px + var(--safe-top)) 12px 10px;
  border-bottom:1px solid var(--bordo-scuro);
  background:var(--antracite-2);
}
.pdfv-title{
  font-family:var(--font-title);font-weight:700;font-size:14px;
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--testo-primario-dark);
}
.pdfv-status{font-size:11px;color:var(--testo-secondario-dark);flex:none;}
.pdfv-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;position:relative;}
.pdfv-pages{
  position:relative;z-index:1;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  padding:12px 12px max(56px, calc(12px + var(--safe-bottom)));
  user-select:none;-webkit-user-select:none;
}
.pdf-page-canvas{max-width:100%;border-radius:2px;box-shadow:0 2px 12px rgba(0,0,0,.45);}
.pdfv-watermark{
  position:absolute;top:0;left:0;right:0;
  pointer-events:none;z-index:2;
  background-repeat:repeat;
}

/* ---------- Premesse di gioco (info file) ---------- */
#premises-file-info .pr-title,
#acc-new-campaign-premise-info .pr-title,
.cm-campaign-detail .pr-title{font-family:var(--font-title);font-weight:600;font-size:13.5px;}
#premises-file-info .pr-text,
#acc-new-campaign-premise-info .pr-text,
.cm-campaign-detail .pr-text{font-size:12.5px;color:var(--testo-secondario-dark-2);margin-top:2px;}

#portrait-lightbox img{
  max-width:94vw;
  max-height:80vh;
  border-radius:var(--radius);
  border:1px solid var(--bordo-scuro);
  box-shadow:0 18px 50px rgba(0,0,0,.6);
}
#pl-close{
  position:absolute;
  top:calc(12px + var(--safe-top));
  right:14px;
  width:44px;height:44px;
  border-radius:50%;
  border:1px solid var(--bordo-scuro);
  background:var(--antracite-2);
  color:var(--testo-primario-dark);
  font-size:18px;
  cursor:pointer;
}
.header-avatar{
  width:38px;height:38px;flex:none;border-radius:var(--radius-sm);
  border:1px solid var(--bordo-scuro);
  background:var(--antracite-1) center/cover no-repeat;
}
.char-card .avatar.has-portrait{background-size:cover;background-position:center;color:transparent;}

/* ---------- Diagramma scheda (fronte) ---------- */
.diagram-wrap{
  position:relative;
  width:100%;
  max-width:400px;
  margin:0 auto;
}
.diagram-wrap svg{width:100%;height:auto;display:block;}
.dg-rect{fill:var(--antracite-1);stroke:var(--bordo-scuro);stroke-width:2;}
.dg-c{fill:var(--antracite-1);stroke:var(--bianco-artico);stroke-width:2;}
.dg-c-t{stroke:var(--testo-secondario-dark);}
.dg-c-hp{stroke:var(--fisico);stroke-width:2.6;}
.dg-c-mp{stroke:var(--magico);stroke-width:2.6;}
.dg-c-sm{stroke:var(--bordo-scuro);}
.dg-lab{
  font-family:var(--font-title);
  font-size:8px;
  font-weight:600;
  letter-spacing:.5px;
  text-transform:uppercase;
  fill:var(--testo-secondario-dark);
  text-anchor:middle;
}
.dg-inputs{position:absolute;inset:0;}
.dg-input{
  position:absolute;
  transform:translate(-50%,-50%);
  background:transparent;
  border:none;
  color:var(--testo-primario-dark);
  font-family:var(--font-mono);
  font-size:14px;
  text-align:center;
  padding:0;
  -moz-appearance:textfield;
}
.dg-input::-webkit-outer-spin-button,.dg-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.dg-input:focus{outline:none;color:var(--fisico-forte);}
.dg-input.dg-ro{color:var(--testo-secondario-dark-2);pointer-events:none;}
.dg-input.dg-buffed{color:var(--incremento-forte) !important;}
@media (max-width:379px){.dg-input{font-size:12px;}}

.dg-pm-overlay{position:absolute;inset:0;pointer-events:none;}
.dg-pm-btn{
  position:absolute;
  transform:translate(-50%,-50%);
  width:14px;height:14px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-title);font-weight:700;font-size:10px;line-height:1;
  border:1.2px solid var(--bianco-artico);
  background:var(--antracite-2);color:var(--bianco-artico);
  pointer-events:auto;cursor:pointer;padding:0;
  box-shadow:0 0 0 1.5px var(--antracite-1);
}
.dg-pm-btn:active{transform:translate(-50%,-50%) scale(.9);}
.dg-pm-plus{background:var(--fisico);border-color:var(--fisico);color:var(--antracite-1);}
.dg-pm-minus{background:var(--antracite-2);border-color:var(--testo-secondario-dark);}
@media (max-width:379px){.dg-pm-btn{width:13px;height:13px;font-size:9px;}}

/* Contatore degli esiti + / - accumulati verso il traguardo (3, o 4 in
   compresenza) di Carisma/Stile/Fortuna: compare accanto alla cifra
   dell'anello (sinistra per i "-", destra per i "+"), non più sui bottoni
   (rovinava la leggibilità) — sparisce da solo quando il traguardo scatta e
   la statistica cambia (vedi renderTertiaryPlusMinus). */
.dg-pm-num{
  position:absolute;transform:translate(-50%,-50%);
  font-family:var(--font-title);font-weight:700;font-size:9px;line-height:1;
  pointer-events:none;white-space:nowrap;
  text-shadow:0 0 2px var(--antracite-1),0 0 2px var(--antracite-1);
}
.dg-pm-num-plus{color:var(--incremento-forte);}
.dg-pm-num-minus{color:var(--fisico-forte);}
@media (max-width:379px){.dg-pm-num{font-size:8px;}}

/* ---------- Point buy ---------- */
.pointbuy-header{
  display:flex;align-items:baseline;justify-content:space-between;
  padding:2px 2px 10px;
}
.pointbuy-header .remaining{
  font-family:var(--font-mono);font-size:20px;color:var(--fisico-forte);
}
.pointbuy-header .remaining.zero{color:var(--testo-secondario-dark-2);}
.pointbuy-header .remaining.neg{color:#FF5C5C;}
.pointbuy-header .label{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--testo-secondario-dark);}

.stat-row{
  display:flex;align-items:center;flex-wrap:wrap;gap:10px;
  padding:9px 2px;
  border-bottom:1px solid rgba(255,255,255,0.05);
}
.stat-row:last-child{border-bottom:none;}
.stat-row .stat-label{width:104px;flex:none;}
.stat-row .stat-label .abbr{font-family:var(--font-title);font-weight:700;font-size:13px;}
.stat-row .stat-label .full{
  display:block;font-size:9px;color:var(--testo-secondario-dark);
  text-transform:uppercase;letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.stat-label.physical .abbr{color:var(--fisico-forte);}
.stat-label.magic .abbr{color:var(--magico-forte);}
.stat-label.neutral .abbr{color:var(--bianco-artico);}
.stat-label.buffed .abbr{color:var(--incremento-forte) !important;}
.buff-chip{
  border-color:var(--incremento);color:var(--incremento-forte);
  font-family:var(--font-mono);flex:none;
}
/* Bonus da arma/scudo equipaggiati: verde, a indicare che statistica o
   tratto sono momentanei (durano finché il pezzo resta equipaggiato),
   a differenza del giallo/ambra usato per gli incrementi da consumabile. */
.buff-chip-equip{
  border-color:var(--equip-momentaneo);color:var(--equip-momentaneo-forte);
  font-family:var(--font-mono);flex:none;
}
.stepper{display:flex;align-items:center;gap:0;flex:1;justify-content:flex-end;}
.stepper button{
  width:30px;height:30px;border-radius:var(--radius-sm);
  border:1px solid var(--bordo-scuro);background:var(--antracite-1);
  color:var(--testo-primario-dark);font-size:16px;line-height:1;
  display:flex;align-items:center;justify-content:center;cursor:pointer;
}
.stepper button:disabled{opacity:.35;cursor:not-allowed;}
.stepper input{
  width:42px;text-align:center;background:transparent;border:none;
  font-family:var(--font-mono);font-size:15px;color:var(--testo-primario-dark);
  -moz-appearance:textfield;
}
.stepper input:disabled{opacity:.5;}
.stepper input::-webkit-outer-spin-button,.stepper input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}

/* ---------- Stat readouts (derived values, HUD-style) ---------- */
.hud-grid{display:flex;flex-wrap:wrap;gap:10px;}
.hud-tile{
  flex:1 1 calc(50% - 10px);
  min-width:120px;
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:12px 14px;
}
.hud-tile .ht-label{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--testo-secondario-dark);}
.hud-tile .ht-value{font-family:var(--font-mono);font-size:22px;color:var(--testo-primario-dark);margin-top:2px;}
.hud-tile.physical .ht-value{color:var(--fisico-forte);}
.hud-tile.magic .ht-value{color:var(--magico-forte);}
.hud-tile .ht-sub{font-size:10.5px;color:var(--testo-secondario-dark);margin-top:2px;}

/* Barre HP/MP/PP in gioco */
.bar-row{display:flex;flex-direction:column;gap:6px;margin-bottom:14px;}
.bar-row:last-child{margin-bottom:0;}
.bar-row .bar-top{display:flex;justify-content:space-between;align-items:baseline;}
.bar-row .bar-name{font-family:var(--font-title);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.08em;}
.bar-row .bar-name.buffed{color:var(--incremento-forte) !important;}
.bar-row .bar-val{font-family:var(--font-mono);font-size:14px;color:var(--testo-secondario-dark-2);}
.bar-track{height:14px;border-radius:7px;background:var(--antracite-1);border:1px solid var(--bordo-scuro);overflow:hidden;}
.bar-fill{height:100%;border-radius:7px;transition:width .2s ease;}
.bar-fill.physical{background:linear-gradient(90deg,var(--fisico),var(--fisico-forte));}
.bar-fill.magic{background:linear-gradient(90deg,var(--magico),var(--magico-forte));}
.bar-fill.neutral{background:linear-gradient(90deg,#7C828C,var(--testo-secondario-dark-2));}
.bar-controls{display:flex;justify-content:flex-end;align-items:center;gap:6px;margin-top:2px;flex-wrap:wrap;}
.bar-controls input[type=number]{
  width:64px;background:var(--antracite-1);border:1px solid var(--bordo-scuro);
  border-radius:var(--radius-sm);color:var(--testo-primario-dark);
  font-family:var(--font-mono);font-size:12px;text-align:center;padding:7px 4px;
}
.bar-controls select{
  flex:1 1 auto;min-width:0;max-width:220px;
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);
  border-radius:var(--radius-sm);color:var(--testo-primario-dark);
  font-size:12px;padding:7px 8px;
}

.inline-max-input{
  width:52px;background:transparent;border:none;border-bottom:1px dashed var(--bordo-scuro);
  color:var(--testo-secondario-dark-2);font-family:var(--font-mono);font-size:14px;
  text-align:center;padding:0 2px;
  -moz-appearance:textfield;
}
.inline-max-input-sm{width:38px;font-size:12px;}
.inline-max-input::-webkit-outer-spin-button,.inline-max-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.inline-max-input:focus{outline:none;border-bottom-color:var(--fisico-forte);}

/* ---------- Roll widget ---------- */
.roll-row{display:flex;align-items:center;gap:12px;}
.roll-result{
  font-family:var(--font-mono);font-size:24px;color:var(--bianco-artico);
  min-width:52px;text-align:center;
}
.roll-result.success{color:var(--magico-forte);}
.roll-result.fail{color:#FF5C5C;}
.roll-detail{font-size:10.5px;color:var(--testo-secondario-dark);white-space:pre-wrap;}
.roll-detail .success-note{color:var(--magico-forte);font-weight:600;}
.roll-detail .fail-note{color:#FF5C5C;font-weight:600;}

/* ---------- Form fields generic ---------- */
.field{display:flex;flex-direction:column;gap:6px;min-width:0;}
.field label{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--testo-secondario-dark);}
.field input[type=text],.field input[type=number],.field input[type=password],.field textarea,.field select{
  background:var(--antracite-1);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius-sm);
  padding:10px 12px;
  color:var(--testo-primario-dark);
  font-size:14px;
  width:100%;
  min-width:0;
}
.field textarea{resize:vertical;min-height:70px;line-height:1.5;font-family:var(--font-body);}
.field-row{display:flex;gap:10px;flex-wrap:wrap;}
.field-row .field{flex:1 1 120px;min-width:0;}

/* ---------- Background: contenitori (uno alla volta, scelti dal menu #bg-nav-select) + sola lettura/modifica ---------- */
.bg-section{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  overflow:hidden;
}
.bg-section-head{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:12px 12px;
}
.bg-section-head .bg-section-title{
  font-family:var(--font-title);font-weight:600;font-size:12.5px;
  text-transform:uppercase;letter-spacing:.1em;
  color:var(--testo-secondario-dark-2);
  margin-right:auto;
}
.bg-section-body{padding:0 12px 14px;}
/* campo di sola lettura: niente bordo/sfondo a rilievo, testo comunque
   interamente leggibile (auto-altezza via JS, mai troncato o a scorrimento) */
.field textarea[data-bg][readonly],.field input[data-bg][readonly]{
  background:transparent;border-color:transparent;padding-left:0;padding-right:0;
  color:var(--testo-primario-dark);cursor:default;
}
.field textarea[data-bg]{resize:none;overflow:hidden;}
/* campi "corti" (data di nascita, altezza...): niente min-height da 70px,
   l'altezza reale la decide comunque l'auto-resize via JS */
.field textarea[data-bg][rows="1"]{min-height:0;}

/* ---------- Tratti ---------- */
.trait-group{display:flex;flex-direction:column;gap:6px;}
.trait-row{
  display:flex;align-items:center;gap:10px;
  padding:8px 10px;
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius-sm);
}
.trait-row .t-name{flex:1;font-size:13px;min-width:0;}
.trait-row .t-name input{
  width:100%;background:transparent;border:none;color:var(--testo-primario-dark);font-size:13px;
}
.trait-row .t-dice{
  font-family:var(--font-mono);font-size:11px;color:var(--testo-secondario-dark-2);
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);
  border-radius:5px;padding:3px 7px;min-width:44px;text-align:center;flex:none;
}
.trait-row input[type=number]{
  width:46px;background:var(--antracite-1);border:1px solid var(--bordo-scuro);
  border-radius:5px;color:var(--testo-primario-dark);font-family:var(--font-mono);
  text-align:center;padding:6px 2px;flex:none;
}
.trait-row input[type=number]:disabled{opacity:.5;}
.trait-row .btn-roll{flex:none;}
.trait-row .btn-del{flex:none;opacity:.5;}
.trait-add-select:disabled{opacity:.4;cursor:not-allowed;}
.trait-add-select{
  appearance:none;
  -webkit-appearance:none;
  align-self:flex-start;
  margin-bottom:4px;
  background:transparent;
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  color:var(--testo-secondario-dark-2);
  font-family:var(--font-title);
  font-weight:600;
  font-size:11px;
  text-transform:uppercase;
  letter-spacing:.08em;
  padding:8px 12px;
  cursor:pointer;
  max-width:100%;
}

/* ---------- Tabelle ---------- */
table.data-table{width:100%;border-collapse:collapse;font-size:12px;}
table.data-table thead th{
  background:var(--bianco-artico);color:var(--antracite-1);
  font-family:var(--font-title);font-weight:600;text-transform:uppercase;
  font-size:10.5px;letter-spacing:.04em;
  padding:8px 8px;text-align:left;
}
table.data-table tbody td{
  padding:8px 8px;border-bottom:1px solid rgba(255,255,255,0.06);
  color:var(--testo-secondario-dark-2);
}
table.data-table tbody tr:nth-child(even){background:rgba(255,255,255,0.02);}
table.data-table tbody tr.current-row{outline:1px solid var(--fisico-forte);outline-offset:-1px;}
table.data-table td.num,table.data-table th.num{font-family:var(--font-mono);}
.table-scroll{overflow-x:auto;border:1px solid var(--bordo-scuro);border-radius:var(--radius);}
.table-scroll table{border:none;}

/* Tabella editabile (Tecniche/Abilità/Boost) */
table.edit-table input{
  width:100%;background:transparent;border:none;color:var(--testo-primario-dark);
  font-size:12px;padding:2px;
}
table.edit-table textarea{
  width:100%;min-width:150px;background:transparent;border:none;color:var(--testo-primario-dark);
  font-size:12px;padding:2px;resize:vertical;font-family:inherit;line-height:1.4;
}
table.edit-table td{padding:4px 6px;}
table.edit-table td.col-wide{min-width:120px;}
table.edit-table td.col-narrow{min-width:64px;}
table.edit-table thead th{white-space:nowrap;}
/* Cella Bonus/Malus (traitBonusCellHtml): ospita un piccolo form per riga
   (select tratto + eventuale nome personalizzato + valore + rimuovi), non un
   singolo campo — .col-wide (120px, pensato per un input di solo testo) è
   troppo stretto e tronca l'etichetta del select ("Nuovo tratto (Capacità
   Combattive)…" diventava "Nuovo tratto (C"), costringendo ogni controllo
   sulla propria riga. */
table.edit-table td.col-bonus{min-width:240px;}
table.edit-table .equip-bonus-row select{min-width:150px;flex:1 1 150px;}

/* Bonus/malus: uno o più per riga, ciascuno un pallino "acceso" */
.bm-list{list-style:none;padding:0;margin:4px 0 0;display:flex;flex-direction:column;gap:3px;}
.bm-item{display:flex;align-items:flex-start;gap:6px;font-size:11.5px;line-height:1.4;color:var(--testo-secondario-dark-2);}
.bm-dot{width:6px;height:6px;border-radius:50%;margin-top:4px;flex-shrink:0;background:var(--fisico-forte);box-shadow:0 0 4px 1px var(--fisico-forte);}
.bm-item.malus .bm-dot{background:#FF5C5C;box-shadow:0 0 4px 1px #FF5C5C;}

/* ---------- Retro scheda: locazioni ---------- */
.slot-grid{display:flex;flex-direction:column;gap:10px;}
/* Griglia Zaino 5x4 (20 slot): una cella per oggetto non equipaggiato
   (consumabile, arma/scudo, oggetto chiave), vuota/tratteggiata se libera. */
.zaino-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:10px;}
.zaino-slot{
  aspect-ratio:1;border:1px dashed var(--bordo-scuro);border-radius:var(--radius-sm);
  display:flex;align-items:center;justify-content:center;font-size:22px;
  background:var(--antracite-2);
  padding:0;font-family:inherit;
}
.zaino-slot.filled{border-style:solid;cursor:pointer;}
.zaino-icon-hp{color:var(--fisico-forte);}
.zaino-icon-mp{color:var(--magico-forte);}
.zaino-icon-buff{color:var(--incremento-forte);}
/* Popup di dettaglio equip (tap su un'icona dello Zaino): sola lettura,
   stessa struttura .confirm-modal/.cc-box già in uso (chiuso anche dal
   tasto indietro Android via closeTopOverlay). */
.equip-detail-stats .row-between{margin-bottom:6px;}
.equip-detail-bonuses{margin-top:8px;display:flex;flex-direction:column;gap:4px;}
.slot-card{
  background:var(--antracite-2);border:1px solid var(--bordo-scuro);border-radius:var(--radius);
  padding:10px 12px;
}
.slot-card .slot-name{
  width:100%;background:transparent;border:none;border-bottom:1px dashed var(--bordo-scuro);
  color:var(--testo-primario-dark);font-family:var(--font-title);font-weight:600;
  font-size:13px;padding:2px 0 6px;margin-bottom:8px;text-transform:uppercase;letter-spacing:.04em;
}
.slot-picker{margin-bottom:8px;}
.slot-picker .sp-label{
  display:block;font-size:8.5px;text-transform:uppercase;color:var(--testo-secondario-dark);
  letter-spacing:.04em;margin-bottom:4px;
}
.slot-picker .sp-row{display:flex;flex-wrap:wrap;gap:6px;}
.slot-picker .sp-row .btn-sm{flex:1;min-width:64px;padding:7px 8px;}
.slot-fields{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.slot-fields .sf{display:flex;flex-direction:column;gap:3px;min-width:0;}
.slot-fields label{font-size:8.5px;text-transform:uppercase;color:var(--testo-secondario-dark);letter-spacing:.04em;}
.slot-fields label .sf-range{text-transform:none;letter-spacing:0;font-family:var(--font-mono);}
.slot-card .slot-bonus{margin-top:10px;}
.equip-bonuses{margin-top:10px;}
.equip-bonus-row{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  padding:6px 0;border-top:1px solid var(--bordo-scuro);
}
.equip-bonus-row select{
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:5px;
  color:var(--testo-primario-dark);font-size:12px;padding:5px 6px;min-width:0;
}
.equip-bonus-row input[type="number"]{
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:5px;
  color:var(--testo-primario-dark);font-family:var(--font-mono);text-align:center;padding:5px 2px;font-size:13px;
}
.equip-bonus-row input[type="text"]{
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:5px;
  color:var(--testo-primario-dark);font-size:12px;padding:5px 6px;min-width:0;flex:1 1 100px;
}
.equip-bonus-trait{display:flex;flex-wrap:wrap;gap:6px;flex:1 1 auto;}
/* Effetto opzionale (Rompere/Tramortire/nome libero) di una riga Tecnica/
   Abilità a Danno: <details> collassato di default, così il controllo resta
   "non sempre visibile" senza nascondere un effetto già configurato (si
   apre da solo se la riga ne ha già uno, vedi dannoConfigHtml). */
.tec-effetto-details{margin-top:6px;}
.tec-effetto-summary{
  font-size:11px;color:var(--testo-secondario-dark-2);cursor:pointer;
  list-style:none;user-select:none;
}
.tec-effetto-summary::-webkit-details-marker{display:none;}
.tec-effetto-summary::before{content:'▸ ';}
.tec-effetto-details[open] .tec-effetto-summary::before{content:'▾ ';}
.slot-fields input{
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:5px;
  color:var(--testo-primario-dark);font-family:var(--font-mono);text-align:center;padding:6px 2px;font-size:13px;
  width:100%;min-width:0;
}
.slot-fields input[readonly]{opacity:.6;cursor:default;}
.slot-fields .sf-dur-readout{
  font-family:var(--font-mono);text-align:center;padding:6px 2px;font-size:13px;
  color:var(--testo-primario-dark);background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:5px;
}
.slot-fields .badge-broken{display:inline-block;margin-top:3px;font-size:10px;color:#FF5C5C;font-weight:600;}
.slot-confirm-row{display:flex;justify-content:flex-end;}

/* ---------- Scudo/armi: equipaggiato vs inventario, tipo, caratteristiche ---------- */
.slot-equip-toggle{display:flex;gap:8px;margin-bottom:8px;}
.slot-equip-toggle .btn{flex:1;}
.slot-card-inventory{opacity:.6;}
.slot-card-inventory .slot-name{color:var(--testo-secondario-dark);}
.chk-inline{
  display:flex;align-items:center;gap:5px;font-size:12px;color:var(--testo-secondario-dark-2);
  background:var(--antracite-1);border:1px solid var(--bordo-scuro);border-radius:var(--radius-sm);
  padding:6px 9px;cursor:pointer;flex:1;min-width:64px;justify-content:center;
}
.chk-inline input{accent-color:var(--fisico-forte);}
.weapon-stat-flags{flex-wrap:wrap;}
.attack-weapon-list{display:flex;flex-direction:column;gap:8px;}
.attack-weapon-row{justify-content:flex-start;gap:8px;}
.attack-results{display:flex;flex-direction:column;gap:6px;}
.attack-result-row{display:flex;align-items:center;justify-content:space-between;gap:10px;}

/* Ritaglio fisso sul fondo, sempre visibile fin da subito: copre esattamente
   l'altezza reale riportata dal sistema (--safe-bottom, nessun valore
   calcolato/indovinato) così il testo che scorre sotto "emerge" da questo
   bordo invece di poter mai toccare davvero i tasti del telefono. */
#bottom-safe-mask{
  position:fixed;left:0;right:0;bottom:0;
  height:var(--safe-bottom);
  background:var(--antracite-1);
  z-index:40;
  pointer-events:none;
}

/* ---------- Note toast ---------- */
#toast{
  position:fixed;left:50%;bottom:calc(20px + var(--safe-bottom));
  transform:translateX(-50%) translateY(120%);
  background:var(--bianco-artico);color:var(--antracite-1);
  font-family:var(--font-title);font-weight:600;font-size:12.5px;
  padding:10px 18px;border-radius:999px;
  z-index:50;transition:transform .25s ease;
  box-shadow:0 6px 20px rgba(0,0,0,.4);
}
#toast.show{transform:translateX(-50%) translateY(0);}

/* ---------- Misc ---------- */
.helper-text{font-size:11px;color:var(--testo-secondario-dark);line-height:1.5;}
.row-between{display:flex;align-items:center;justify-content:space-between;gap:10px;}
.chip{
  font-size:10px;text-transform:uppercase;letter-spacing:.05em;
  padding:4px 9px;border-radius:999px;border:1px solid var(--bordo-scuro);
  color:var(--testo-secondario-dark-2);
}
.chip.physical{border-color:var(--fisico);color:var(--fisico-forte);}
.chip.magic{border-color:var(--magico);color:var(--magico-forte);}

/* ---------- Consumo oggetti / incrementi attivi ---------- */
table.edit-table select{
  width:100%;background:var(--antracite-1);border:1px solid var(--bordo-scuro);
  border-radius:5px;color:var(--testo-primario-dark);font-size:11.5px;padding:5px 2px;
}
.buff-row{padding:6px 0;border-bottom:1px solid rgba(255,255,255,0.05);}
.buff-row:last-child{border-bottom:none;}
.buff-amt{color:var(--incremento-forte);}

/* ---------- Tabellone di combattimento (view-combat) ---------- */
/* Unica parte dell'app in tema chiaro: schermata bianca con la mappa in
   stile "carta invecchiata" ben visibile, invece della palette antracite
   usata ovunque nel resto dell'app. Sovrascrivendo qui le stesse variabili
   che ogni componente condiviso già usa (box, bottoni, chip, campi, modali)
   si ottiene il re-theme automatico di tutto ciò che vive nel tabellone e
   nelle sue finestre modali — dichiarate a parte perché nel markup sono
   fuori da #view-combat (append diretto al body). */
#view-combat,
#combat-scene-modal,
#combat-environmental-modal,
#combat-own-actions-menu,
#combat-target-picker,
#combat-source-picker,
#combat-flags-modal,
#combat-reveal-picker{
  --antracite-1:#FFFFFF;
  --antracite-2:#F4EEDD;
  --bordo-scuro:#CBB994;
  --testo-primario-dark:#2B2417;
  --testo-secondario-dark:#7A6F52;
  /* "color" va ridichiarato qui (non solo la custom property): altrimenti
     un testo semplice senza regola propria (es. .cc-title, un <p> senza
     classe) continua a ereditare il colore già calcolato su <body> — chiaro,
     pensato per la palette scura dell'app — invece di ricalcolarsi con la
     variabile appena sovrascritta in questo sotto-albero. */
  color:#2B2417;
  --testo-secondario-dark-2:#4A4330;
}
/* Layout a 3 righe (topbar / mappa / barra personaggi) su CSS Grid invece
   che sul flex:1 + min-height:100vh condiviso da .view: quel meccanismo
   lascia che l'altezza della riga centrale dipenda dal contenuto quando la
   mappa è "corta" (poche righe di griglia), facendo slittare la barra dei
   personaggi verso l'alto invece di restare ancorata al fondo reale dello
   schermo. minmax(0,1fr) sulla riga della mappa la forza sempre a occupare
   esattamente lo spazio residuo (mai di più, mai di meno), qualunque sia
   l'altezza reale della griglia esagonale al suo interno. */
#view-combat{
  background:var(--antracite-1);
  display:grid;
  /* Riga in più rispetto a prima: il pannello comandi (#combat-command-panel)
     è ora sempre presente sotto la barra ritratti, non più un popup a
     comparsa legato al tocco su una faccia — vedi renderCombatCommandPanel. */
  grid-template-rows:auto auto minmax(0,1fr) auto auto;
  height:100vh;height:100dvh;height:calc(var(--real-vh, 1vh) * 100);
}

/* Banner "di chi è il turno": una sola riga fissa fra la topbar e la mappa,
   sempre visibile mentre l'iniziativa è rivelata — mostra il personaggio
   attivo (chiunque lo stia guardando, la sequenza è condivisa) e, solo per
   chi può agire ora (il suo proprietario o il Narratore), il bottone per
   passare. */
.combat-turn-banner{
  flex:none;
  display:flex;align-items:center;gap:8px;
  padding:8px 14px;
  background:var(--antracite-2);
  border-bottom:1px solid var(--bordo-scuro);
  font-size:13px;
}
.combat-turn-banner .ctb-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.combat-turn-banner .ctb-name{font-weight:700;}
.combat-turn-banner .ctb-budget{color:var(--testo-secondario-dark);font-size:11.5px;}

/* Board: area RETTANGOLARE (segue il rapporto d'aspetto dell'immagine
   caricata, o il riquadro del fallback) — sono le singole caselle della
   griglia dentro a tassellarsi in esagoni, non il contorno della board. */
.combat-map-wrap{
  min-height:220px;position:relative;
  overflow:auto;
  border-bottom:1px solid var(--bordo-scuro);
  /* Stesso bianco del resto della vista (--antracite-1 qui sopra) invece di
     un beige diverso: la board (immagine o riquadro carta invecchiata) ha
     quasi sempre un rapporto d'aspetto diverso dallo spazio disponibile,
     quindi resta sempre un margine sopra/sotto o ai lati — deve leggersi
     come lo sfondo dell'app, non come una terza campitura di colore a sé. */
  background:var(--antracite-1);
  display:flex;align-items:center;justify-content:center;
}
.combat-map{
  /* content-box, non il border-box globale (vedi *{box-sizing:border-box}):
     map.style.width/height (js/app.js, renderCombatMap) e il viewBox
     dell'SVG della griglia sono entrambi calcolati come CONTENUTO puro, in
     "unità cella" (cellW/cellH) — con border-box i 3px di bordo per lato
     mangerebbero spazio dal contenuto, l'SVG (width/height:100%) si
     ritroverebbe leggermente più piccolo della griglia "vera" in pixel
     usata per posizionare le pedine (che non passano da questo scalamento,
     essendo posizionate in px assoluti), disallineando i due sempre di più
     man mano che ci si allontana dall'angolo in alto a sinistra. */
  box-sizing:content-box;
  position:relative;
  margin:auto;
  background-size:cover;background-position:center;background-repeat:no-repeat;
  /* Cornice come sulla plancia stampata di riferimento */
  border:3px solid #8B4A2E;
  border-radius:4px;
  box-shadow:inset 0 0 0 1px rgba(255,246,224,.5);
}
/* Preset "carta invecchiata + logo": nessun asset caricato dal Narratore
   ancora scelto per questo encounter (map_asset_id null) — un unico colore
   piatto più il logo al centro, niente altro (niente macchie/vignette a
   gradiente radiale: si confondevano con il bagliore delle celle attorno
   al personaggio selezionato). */
.combat-map.combat-map-fallback{
  background-color:#E9D9A8;
}
.combat-map-fallback-logo{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:35%;max-width:220px;opacity:.28;pointer-events:none;
}
/* Frecce ▲/▼ per cambiare il livello mostrato (Combattimenti multi-livello):
   nell'angolo in alto dello spazio vuoto attorno alla mappa (.combat-map-wrap
   è più grande della mappa centrata quando i rapporti d'aspetto non
   combaciano, vedi sopra) — mai sopra la griglia stessa, mai un ostacolo al
   tocco delle celle. */
.combat-level-arrows{
  position:absolute;top:8px;right:8px;z-index:5;
  display:flex;align-items:center;gap:6px;
  background:rgba(20,22,26,.75);
  border-radius:999px;
  padding:2px 8px;
}
.combat-level-arrows .btn-icon{width:26px;height:26px;min-height:0;font-size:13px;color:#fff;}
.combat-level-arrows-label{
  font-size:10.5px;color:#fff;font-weight:600;
  max-width:90px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Banner temporaneo di piazzamento passaggi/ostacoli (Gestisci scena >
   Aggiungi passaggio / Modifica ostacoli), solo per il Narratore (unico
   che può entrare in questa modalità, vedi renderCombatMapManager): riga
   fissa del layout appena sopra la mappa, stesso spirito del turno banner
   — MAI sovrapposta alla griglia (un overlay assoluto finiva per coprire
   le prime file di celle proprio mentre si deve toccarle per piazzare). */
.combat-placement-banner{
  flex:none;
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:8px 14px;
  background:var(--antracite-2);
  border-bottom:1px solid var(--bordo-scuro);
  color:#fff;
  font-size:13px;
}
.combat-placement-banner #combat-placement-banner-done{color:#fff;border-color:rgba(255,255,255,.4);}
/* Strumenti del Narratore (passaggio/ostacoli/danno ambientale/effetto
   libero) sempre visibili fra mappa e barra personaggi, non più solo
   raggiungibili aprendo "⚙ Gestisci scena": riga fissa come il resto dei
   banner qui sopra, mai ai giocatori (toggle su callerIsMaster in
   renderCombatBoard). */
.combat-narrator-toolbar{
  flex:none;
  display:flex;align-items:center;gap:6px;
  padding:3px 14px;
  /* Colore scuro esplicito (non var(--antracite-2)): dentro #view-combat
     quella variabile è sovrascritta al crema del tema chiaro del tabellone
     (vedi sopra), ma questa barra resta l'unico pannello di controllo che
     deve leggersi come una toolbar scura — stesso valore antracite di
     default della palette globale, indipendente dal re-theme locale. */
  background:#1E2126;
  border-bottom:1px solid #4A4F58;
}
.combat-narrator-toolbar .btn{color:#fff;border-color:rgba(255,255,255,.25);}
.combat-narrator-toolbar-tools{
  flex:1;min-width:0;
  display:flex;flex-wrap:nowrap;gap:6px;
  overflow-x:auto;
}
/* Padding verticale dimezzato rispetto a .btn-sm (8px, il valore che vince
   in cascata su questi bottoni — non i 14px di .btn base): dimezza
   l'altezza della barra insieme al padding del contenitore qui sopra, resta
   invariato solo l'orizzontale. I bottoni restano centrati verticalmente
   grazie ad align-items:center sul contenitore padre, invariato. */
.combat-narrator-toolbar-tools .btn{flex:none;white-space:nowrap;padding:3px 12px;}
/* Il tasto "▲" (comprimi barra) è un .btn-icon fisso a 40×40px: senza
   dimezzarlo anche lui resta lui il vincolo che tiene alta l'intera barra,
   vanificando il dimezzamento sopra sui bottoni degli strumenti. */
.combat-narrator-toolbar .btn-icon{width:20px;height:20px;min-height:0;font-size:11px;}
/* Barra ripiegata (tasto "Nascondi barra"): resta solo la freccetta per
   riaprirla, mai completamente sparita — così il Narratore la ritrova
   sempre nello stesso punto invece di doverla "ricordare". */
.combat-narrator-toolbar.collapsed .combat-narrator-toolbar-tools{display:none;}
.combat-narrator-toolbar.collapsed{padding:4px 14px;}
/* Griglia esagonale come SVG (vedi renderCombatMap in app.js): un
   <polygon> con stroke disegna il contorno su tutti e sei i lati, cosa
   che un <div> con clip-path non può fare (il bordo di un box rettangolare
   resta visibile solo dove il ritaglio combacia con un lato originale del
   rettangolo — qui i due lati piatti orizzontali, da cui le sole
   "trattine" della versione precedente). */
.combat-hex-grid{
  position:absolute;top:0;left:0;
  pointer-events:none; /* i singoli poligoni sotto riabilitano gli eventi */
}
/* Campitura bianca piena: unico <rect> a piena dimensione "bucato" da una
   <mask> con un poligono nero per ogni esagono (vedi renderCombatMap) —
   copre sia i vuoti fra le celle (nati dal rimpicciolimento) sia il bordo
   esterno alla griglia, sempre sopra l'immagine della mappa. Gli esagoni
   stessi restano fori trasparenti: solo il loro contorno (.combat-hex-cell
   sotto) resta visibile, mai una fill piena sopra l'immagine del singolo
   esagono. */
.combat-hex-void-frame{
  fill:#FFFFFF;
  opacity:1;
  pointer-events:none;
}
.combat-hex-cell{
  /* Solo il contorno è disegnato: l'interno dell'esagono è un vuoto che
     lascia vedere l'immagine sotto per intero, mai una fill visibile. Il
     gradiente di opacità per distanza (inline, vedi renderCombatMap) si
     accende sul contorno stesso solo mentre una pedina è selezionata per
     lo spostamento — a riposo il contorno resta comunque visibile a bassa
     opacità (definita qui).
     ATTENZIONE hit-test: fill deve restare "transparent" (mai "none"). Con
     fill:none l'interno del <polygon> non riceve eventi pointer/tap anche
     con pointer-events:auto (solo lo stroke sottile risponde) — il tocco
     reale su una cella quasi mai cade esattamente sul bordo, quindi
     "Ostacoli"/"Passaggio" risultavano silenziosamente senza effetto.
     fill:transparent è visivamente identico (nessun colore disegnato) ma
     conta come "painted" per l'hit-test SVG, rendendo tappabile l'intero
     esagono. */
  fill:transparent;
  stroke:#FFFFFF;
  stroke-width:.3125;
  vector-effect:non-scaling-stroke;
  pointer-events:auto;
  opacity:.55;
  transition:opacity .2s;
}
.combat-hex-cell.combat-hex-selectable{cursor:pointer;}
.combat-hex-cell.combat-hex-selectable:active,
.combat-hex-cell.combat-hex-hover{fill:rgba(255,122,51,0.32);}
.combat-hex-cell.combat-hex-occupied{fill:rgba(255,255,255,0.18);}
/* Ostacolo invalicabile piazzato dal Narratore (Gestisci scena > Modifica
   ostacoli): overlay scuro sotto il contorno interattivo della cella
   (disegnato prima nel markup, vedi renderCombatMap) — mai un segreto,
   visibile a tutti allo stesso modo. */
.combat-hex-obstacle{
  fill:#000000;
  fill-opacity:.8;
  pointer-events:none;
}
/* Icona 🪜 sulla casella adibita a passaggio/scala fra livelli (piazzata
   dal Narratore, vedi setCombatLevelStaircase/setCombatLevelTransition):
   senza, la cella era invisibile in mappa e nessuno poteva sapere dove
   fosse il passaggio. paint-order+stroke danno un alone scuro che la
   rende leggibile sopra qualunque immagine di sfondo. */
.combat-hex-transition-icon{
  text-anchor:middle;
  dominant-baseline:central;
  paint-order:stroke;
  stroke:#000000;
  stroke-width:2px;
  stroke-opacity:.55;
  pointer-events:none;
}
/* La pedina riempie per intero l'esagono della cella (stesso poligono
   "flat-top" dei contorni disegnati in renderCombatMap: lato piatto sopra/
   sotto, punta a sinistra/destra — vedi rawPts/HEX_GAP_SCALE), non più un
   cerchio più piccolo centrato sopra di esso. clip-path taglia sfondo,
   bordo e ombre "verso l'interno": un box-shadow verso l'esterno (usato
   prima per l'anello di selezione) sparirebbe perché ricade fuori dal
   poligono di ritaglio, per questo qui sotto si passa a filter:drop-shadow,
   che invece segue la sagoma esagonale già tagliata. */
.combat-token{
  position:absolute;
  display:flex;align-items:center;justify-content:center;
  clip-path:polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  background:var(--antracite-2);
  border:2px solid var(--bordo-scuro);
  font-family:var(--font-title);font-weight:700;
  color:var(--testo-primario-dark);
  background-size:cover;background-position:center;
  cursor:pointer;
  transition:filter .15s, border-color .15s;
}
.combat-token.combat-token-mine{border-color:var(--fisico-forte);}
.combat-token.combat-token-master-owned{border-color:var(--magico-forte);}
.combat-token.combat-token-selected{filter:drop-shadow(0 0 4px rgba(255,122,51,.85));}
/* Trascinamento diretto (vedi setupCombatTokenDrag): pointer-events:none
   così elementFromPoint al rilascio raggiunge la cella esagonale sotto la
   pedina invece di ritrovare la pedina stessa. */
.combat-token.combat-token-dragging{
  z-index:20;opacity:.85;cursor:grabbing;
  pointer-events:none;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.5));
  transition:none;
}
/* Trascinata fuori dai bordi della board (solo Narratore): rilasciandola
   qui la pedina viene espulsa dalla scena, vedi isOutsideMap in
   setupCombatTokenDrag — bordo rosso d'avviso invece del solito arancione. */
.combat-token.combat-token-eject-armed{
  border-color:#E24A4A;
  opacity:.6;
  filter:drop-shadow(0 3px 6px rgba(226,74,74,.7));
}
.combat-token-label{
  position:absolute;left:50%;bottom:100%;transform:translateX(-50%);
  margin-bottom:3px;
  white-space:nowrap;
  font-size:10px;font-weight:600;
  /* Etichetta sempre scura con testo chiaro, indipendente dal tema: deve
     restare leggibile sopra qualunque mappa (foto caricata o parchment),
     non solo sulla card chiara del resto del tabellone. */
  background:rgba(8,9,11,.82);
  color:#F2F1ED;
  padding:1px 6px;border-radius:999px;
  pointer-events:none;
}
/* Barra di movimento (caselle percorse/budget da Velocità, vedi
   combatMovementBudget): sotto il token, speculare all'etichetta nome
   sopra — sempre scura per restare leggibile su qualunque mappa. */
.combat-token-move-bar{
  position:absolute;left:15%;top:100%;transform:translateY(3px);
  width:70%;height:3px;border-radius:999px;
  background:rgba(8,9,11,.55);
  overflow:hidden;
  pointer-events:none;
}
.combat-token-move-fill{height:100%;background:#F2D34D;}

/* Overlay di risoluzione attacco: appare solo quando c'è un attacco in
   corso, sopra la mappa invece di occupare spazio fisso in pagina. */
.combat-attack-overlay{
  position:absolute;left:8px;right:8px;bottom:8px;
  max-height:60%;overflow-y:auto;
  z-index:5;
}

/* Barra "Personaggi in gioco": card compatte, scroll orizzontale, sempre
   ancorata in fondo. */
.combat-roster-bar{
  flex:none;
  display:flex;gap:10px;overflow-x:auto;
  padding:10px 14px;
  -webkit-overflow-scrolling:touch;
}
.combat-roster-bar::-webkit-scrollbar{display:none;}
/* Pannello comandi (Attacca/Tecniche/Abilità/Boost/Oggetti): sempre
   presente sotto la barra ritratti (non più un popup a comparsa legato al
   tocco su una faccia, vedi renderCombatCommandPanel), quindi è lui ora ad
   avere il padding di sicurezza in fondo (prima toccava alla barra
   ritratti, che era l'ultimo elemento). Testo/bottoni allineati a sinistra
   ("a bandiera"), non centrati come i pulsanti a pillola del resto
   dell'app. */
.combat-command-panel{
  flex:none;
  display:flex;flex-direction:column;gap:6px;
  padding:10px 14px calc(10px + var(--safe-bottom));
  border-top:1px solid var(--bordo-scuro);
  background:var(--antracite-2);
}
.combat-command-panel .cmdpanel-title{
  font-family:var(--font-title);font-weight:700;font-size:13px;
  color:var(--testo-secondario-dark-2);
  margin:0 0 2px;
}
.combat-command-panel .cmdpanel-btn{
  display:block;width:100%;text-align:left;
  padding:9px 12px;
  border-radius:6px;
  border:1px solid var(--bordo-scuro);
  background:transparent;
  color:var(--testo-primario-dark);
  font-family:var(--font-body);font-size:14px;
  cursor:pointer;
}
.combat-command-panel .cmdpanel-btn:active{background:rgba(255,255,255,.08);}
.combat-roster-card{
  flex:none;width:88px;
  display:flex;flex-direction:column;align-items:center;gap:4px;
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:8px 6px;
  cursor:pointer;
}
.combat-roster-card.combat-roster-card-mine{border-color:var(--fisico-forte);}
/* Personaggio "di turno" ora (vedi combatIsCurrentTurn): un alone visibile
   a tutti, indipendente dal colore del bordo di proprietà sopra. */
.combat-roster-card.combat-roster-card-turn{box-shadow:0 0 0 2px #F2D34D, 0 4px 12px rgba(242,211,77,.35);}
/* Card "sollevata" mentre la si trascina verso la board (vedi
   setupCombatRosterDrag): resta al suo posto nella barra ma si vede che
   qualcosa si sta spostando, la vera pedina trascinata è il ghost qui sotto. */
.combat-roster-card.combat-roster-card-lifted{opacity:.4;}
/* Ghost trascinato: position:fixed così segue il puntatore ovunque sullo
   schermo, fuori dai confini scrollabili della barra roster e sopra la
   mappa. Stesso aspetto circolare di un token, senza le interazioni. */
.combat-roster-drag-ghost{
  position:fixed;top:0;left:0;
  width:44px;height:44px;margin:-22px 0 0 -22px;
  border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:var(--antracite-2);
  background-size:cover;background-position:center;
  border:2px solid var(--fisico-forte);
  font-family:var(--font-title);font-weight:700;font-size:17px;
  color:var(--testo-primario-dark);
  box-shadow:0 6px 18px rgba(0,0,0,.4);
  pointer-events:none;
  z-index:1000;
}
.combat-roster-drag-ghost.combat-roster-drag-ghost-armed{
  border-color:#3DDC84;
  box-shadow:0 0 0 4px rgba(61,220,132,.35),0 6px 18px rgba(0,0,0,.4);
}
/* Ordine di iniziativa: impostato qui sulla card, nella barra in basso —
   non più in una fascia separata sopra la mappa. */
.combat-roster-card .cr-initiative{
  font-family:var(--font-mono);font-size:9.5px;font-weight:600;
  color:var(--testo-secondario-dark);
}
.combat-roster-card .avatar{
  width:40px;height:40px;border-radius:50%;flex:none;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-title);font-weight:700;font-size:15px;
  /* Il ritratto (background-image inline) va ridimensionato per riempire
     il cerchio, non mostrato alla sua risoluzione naturale: senza questa
     regola l'immagine appariva "non scalata", un ritaglio casuale invece
     del volto intero rimpicciolito. */
  background-size:cover;background-position:center;
}
.combat-roster-card .avatar.has-portrait{color:transparent;}
.combat-roster-card .cr-name{font-size:11px;font-weight:600;text-align:center;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;}
.combat-roster-card .cr-hp{width:100%;height:4px;border-radius:999px;background:rgba(80,60,25,.12);overflow:hidden;}
.combat-roster-card .cr-hp-fill{height:100%;background:var(--fisico-forte);}
/* Effetti attivi (buff/regen/danno nel tempo, vedi combat_active_effects):
   un'etichetta compatta per riga di card, il countdown scende solo con
   "Avanza turno" (mai qui, solo lettura del valore corrente). */
.combat-roster-card .cr-effects{display:flex;flex-wrap:wrap;gap:3px;justify-content:center;margin-top:2px;}
.combat-roster-card .cr-effect-badge{
  display:inline-flex;align-items:center;gap:2px;
  font-size:8.5px;line-height:1;font-family:var(--font-mono);
  padding:2px 4px;border-radius:999px;
  background:rgba(80,60,25,.14);color:var(--testo-secondario-dark);
  white-space:nowrap;
}
.combat-roster-card .cr-effect-buff{background:rgba(90,140,255,.18);}
.combat-roster-card .cr-effect-regen{background:rgba(70,180,110,.2);}
.combat-roster-card .cr-effect-danno{background:rgba(200,60,60,.2);}
.combat-roster-card .cr-effect-remove{
  border:none;background:none;padding:0;margin-left:1px;
  font-size:8.5px;line-height:1;color:inherit;cursor:pointer;opacity:.7;
}
.combat-roster-card .cr-effect-remove:hover{opacity:1;}
/* Tentativo di liberazione da Tramortire (🎲): stesso trattamento minimale
   di "Sospendi" (✕) qui accanto, distinto solo dall'icona. */
.combat-roster-card .cr-effect-escape{
  border:none;background:none;padding:0;margin-left:1px;
  font-size:8.5px;line-height:1;color:inherit;cursor:pointer;opacity:.85;
}
.combat-roster-card .cr-effect-escape:hover{opacity:1;}

/* Card di dettaglio (usata nel pannello attacco per nominare attaccante/
   bersaglio, e come stile condiviso per eventuali elenchi di dettaglio) */
.combat-card{
  background:var(--antracite-2);
  border:1px solid var(--bordo-scuro);
  border-radius:var(--radius);
  padding:12px 14px;
  display:flex;gap:12px;align-items:flex-start;
  position:relative;
}
.combat-card .avatar{width:52px;height:52px;border-radius:var(--radius-sm);flex:none;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-title);font-weight:700;font-size:18px;}
.combat-card .cc-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;}
.combat-card .cc-name-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.combat-card .cc-name{font-family:var(--font-title);font-weight:600;font-size:15px;}
.combat-card .cc-init{
  font-family:var(--font-mono);font-size:11px;color:var(--testo-secondario-dark);
  border:1px solid var(--bordo-scuro);border-radius:999px;padding:2px 8px;flex:none;
}
.combat-card .cc-stats{display:flex;flex-wrap:wrap;gap:6px 10px;font-size:11.5px;color:var(--testo-secondario-dark-2);}
.combat-card .cc-stat-hidden{color:var(--testo-secondario-dark);font-style:italic;}
.combat-card .cc-reveal-btn{align-self:flex-start;}

/* Libreria mappe nel pannello "Gestisci scena" */
.combat-asset-row{
  display:flex;align-items:center;gap:10px;
  padding:6px 0;border-bottom:1px solid rgba(80,60,25,0.12);
}
.combat-asset-row:last-child{border-bottom:none;}
.combat-asset-thumb{width:44px;height:32px;border-radius:4px;background-size:cover;background-position:center;
  background-color:var(--antracite-1);flex:none;border:1px solid var(--bordo-scuro);}
.combat-asset-label{flex:1;min-width:0;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* Anteprima trascinabile dell'inquadratura mappa (vedi setupMapFocusDrag):
   stessa proporzione della griglia vera (aspect-ratio impostato inline),
   background-size:cover così il ritaglio che si vede qui è lo stesso che
   comparirà sulla board reale. */
.combat-map-focus-preview{
  width:100%;max-width:260px;margin:0 auto;
  background-size:cover;background-repeat:no-repeat;
  background-color:var(--antracite-1);
  border:1px solid var(--bordo-scuro);border-radius:var(--radius);
  cursor:grab;touch-action:none;
  overflow:hidden;
}
.combat-map-focus-preview:active{cursor:grabbing;}

@media (min-width:600px){
  .sheet-body{padding-left:32px;padding-right:32px;}
}

/* La "cornice telefono" scalata (sotto) è pensata SOLO per browser desktop
   veri. Prima la decisione era in CSS puro (min-width + hover:hover +
   pointer:fine), ma alcuni WebView Android dichiarano hover:hover vero
   anche su schermi puramente touch (difetto noto di alcune build) — un
   media query "che dovrebbe" riconoscere solo un mouse reale non basta se
   il dispositivo mente sulla propria capacità. La decisione ora si prende
   in JS (vedi script inline in cima a index.html: navigator.maxTouchPoints,
   un segnale diretto sul dispositivo invece di un'euristica sul
   rendering), che aggiunge o toglie .ms-desktop-frame su <html> — il CSS
   qui sotto si limita a leggere quella classe, mai un media query. */
html.ms-desktop-frame{height:100%;}
html.ms-desktop-frame body{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  height:100vh;
  overflow:hidden;
  background:#0a0b0d;
}
html.ms-desktop-frame #app{
  /* Sul web/desktop la "cornice telefono" (430×860) si scala per riempire
     lo schermo mantenendo le proporzioni — mai deformata, come
     background-size:contain per un'immagine (vedi lo script inline in
     cima a index.html che calcola --app-scale) — invece di restare a
     dimensione fissa con la pagina che scorre. transform non cambia le
     dimensioni di layout dell'elemento, quindi #app resta 430×860 "sulla
     carta": è per questo che centrarlo con align-items+justify-content
     (il centro visivo della trasformazione coincide col centro del box
     originale) basta, senza margini calcolati a mano. */
  position:relative;
  width:430px;
  height:860px;
  flex:none;
  min-height:0;
  border-radius:26px;
  overflow:hidden;
  box-shadow:0 24px 70px rgba(0,0,0,.55),0 0 0 1px var(--bordo-scuro);
  transform:scale(var(--app-scale, 1));
}
html.ms-desktop-frame #app .view{
  min-height:0;
}
/* i popup a schermo intero (e il toast) restano dentro la "cornice" del
   telefono invece di coprire tutta la finestra del browser */
html.ms-desktop-frame .confirm-modal,
html.ms-desktop-frame #prem-popup,
html.ms-desktop-frame #portrait-lightbox,
html.ms-desktop-frame #pdf-viewer,
html.ms-desktop-frame #rules-popup,
html.ms-desktop-frame #campaign-assets-popup,
html.ms-desktop-frame #toast{
  position:absolute;
}
