:root {
  --bg: #0d1117;
  --bg2: #161d27;
  --card: #1b2430;
  --border: #2b3646;
  --text: #e6ebf2;
  --muted: #8b98ab;
  --green: #34d399;
  --green-dark: #059669;
  --accent: #4ade80;
  --red: #f87171;
  --yellow: #fbbf24;
  --blue: #60a5fa;
  --violet: #a78bfa;
}
/* Mobile-friendly UI, Fase 0 (richiesta prodotto, 09/08/2026, piano approvato
   nel Progetto — "Mobile-friendly UI - Documento di Progettazione.md"):
   convenzione di breakpoint condivisa da qui in avanti per ogni fase
   successiva (navigazione, tabelle, form), invece di inventarne uno diverso
   ogni volta. 600px = soglia "telefono": ogni regola sotto questa soglia va
   dentro un @media (max-width: 600px) dedicato, MAI come regola nuda, così
   il desktop (>600px) non cambia mai per costruzione. Le soglie "tablet" già
   esistenti (800/900px, sulle griglie che le usano già) restano invariate e
   convivono con questa senza conflitto, essendo entrambe max-width. */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  min-height: 100vh;
}
.loading { display: flex; justify-content: center; padding: 4rem; font-size: 3rem; animation: spin 1.2s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Layout */
.topbar {
  display: flex; align-items: center; gap: 1.5rem;
  padding: 0.7rem 1.5rem; background: var(--bg2);
  border-bottom: 2px solid var(--green-dark);
  /* z-index 21, non 10 (bug segnalato da un utente su mobile, 11/08/2026):
     `position: sticky` + z-index qui sopra rende .topbar un contesto di
     impilamento (stacking context) a sé — lo z-index:20 di `.topbar nav`
     (il cassetto di navigazione, sotto la soglia nav, vedi @media più sotto)
     vale quindi SOLO dentro .topbar, non a livello di pagina. .nav-overlay è
     invece un FRATELLO di .topbar nel markup (fuori da questo div, vedi
     layout() in app.js), quindi viene confrontato con .topbar nel suo
     insieme: col vecchio z-index:10 di .topbar, l'overlay (z-index:19)
     copriva tutto il cassetto aperto, intercettando ogni tocco sui link e
     lasciando solo la chiusura del pannello (click sull'overlay) — l'utente
     vedeva il menu aprirsi ma non riusciva mai a cambiare pagina. Con 21
     (> 19) l'intero sottoalbero di .topbar, cassetto incluso, torna sopra
     l'overlay. */
  position: sticky; top: 0; z-index: 21;
}
.topbar .logo { font-weight: 800; font-size: 1.15rem; color: var(--accent); text-decoration: none; letter-spacing: 0.5px; }
.topbar nav { display: flex; gap: 0.3rem; flex: 1; }
.topbar nav a {
  color: var(--muted); text-decoration: none; padding: 0.45rem 0.85rem;
  border-radius: 8px; font-size: 0.92rem; font-weight: 600;
}
.topbar nav a:hover { color: var(--text); background: var(--card); }
.topbar nav a.active { color: var(--accent); background: var(--card); }
/* Mobile-friendly UI, Fase 1 (richiesta prodotto, 09/08/2026, piano approvato
   nel Progetto — "Mobile-friendly UI - Documento di Progettazione.md"): sotto
   la soglia nav le 11 voci di `.topbar nav` diventano un pannello a scomparsa
   invece di restare in riga, dove non entrerebbero. Il pulsante ☰ e l'overlay
   restano nascosti di default (regole nude qui sotto, valide a OGNI
   larghezza) — si attivano solo dentro il blocco @media più sotto, così sopra
   la soglia il comportamento resta bit-per-bit quello di sempre. */
.nav-toggle {
  display: none; background: transparent; border: 1px solid var(--border);
  color: var(--text); font-size: 1.2rem; line-height: 1; padding: 0.5rem 0.7rem;
  border-radius: 8px; cursor: pointer;
}
.nav-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: 19; }
/* Bug pre-esistente scoperto durante la Fase 5 di verifica del Mobile-friendly
   UI (10/08/2026), corretto qui su richiesta esplicita dell'utente: le 11
   voci di `.topbar nav` NON entravano in riga già da larghezze desktop
   comuni, non solo sotto i 600px. Misurato con le etichette reali (incluso
   "Gloracy Italian Cup" e "Centro sportivo", le più lunghe fra IT/EN): la
   riga richiede ~1449px per stare senza andare a capo/tagliarsi, quindi a
   768-1440px (praticamente ogni laptop) la barra usciva dal bordo destro
   della pagina, nascondendo campanella/nome utente/Esci dietro uno scroll
   orizzontale mai suggerito visivamente. Soglia dedicata "soglia nav" a
   1500px (con margine sopra i ~1449px misurati), DISTINTA dalla "soglia
   telefono" (600px, convenzione Fase 0) — qui non è un adattamento per
   schermi piccoli, è la soglia minima sopra cui l'elenco intero entra
   davvero in una riga. Sotto 1500px si riusa lo stesso pannello a scomparsa
   già collaudato per il telefono (nessuna nuova UI): funziona identico anche
   come cassetto per tablet/laptop stretti. */
@media (max-width: 1500px) {
  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; }
  .topbar nav {
    position: fixed; top: 0; right: 0; z-index: 20;
    height: 100vh; width: min(78vw, 320px);
    background: var(--bg2); border-left: 1px solid var(--border);
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 4rem 1rem 1.5rem; overflow-y: auto;
    transform: translateX(100%); transition: transform 0.25s ease;
  }
  .topbar nav.open { transform: translateX(0); }
  .topbar nav a { padding: 0.9rem 0.85rem; font-size: 1rem; border-radius: 8px; }
  .nav-overlay.open { display: block; }
}
.topbar .user { color: var(--muted); font-size: 0.88rem; display: flex; align-items: center; gap: 0.6rem; }
/* Limite residuo segnalato durante le due correzioni di overflow qui sotto
   (10/08/2026): lo username non ha un limite di lunghezza in registrazione,
   quindi un nome molto più lungo del solito poteva ancora rompere la barra
   a qualunque larghezza, anche dopo i due fix. Corretto qui alla radice: lo
   username vive nel proprio `<span class="username">` (non più un nodo di
   testo nudo dentro `.topbar .user`, vedi app.js) e viene troncato con
   ellissi invece di spingere fuori il resto della barra. `title` sull'elemento
   mostra il nome completo al passaggio del mouse.
   `max-width` in due parti, misurate con Playwright usando uno username
   volutamente enorme (80+ caratteri larghi senza spazi, il caso peggiore
   possibile) per trovare il tetto sicuro ad ogni larghezza:
   - min(15vw, 150px) di base: sicuro con margine da 300px in su (misurato:
     spazio realmente disponibile 57px a 300px, 77px a 320px... fino a
     "tanto quanto vuole" da ~600px, quindi il tetto fisso di 150px non è
     mai stretto lì) — QUESTA regola vale anche sotto la soglia nav
     (1500px, vedi sopra), dove il pannello ☰ è a scomparsa e lascia
     spazio in abbondanza.
   - sopra i 1500px (soglia nav) invece la nav completa (11 voci) torna in
     riga e occupa quasi tutta la larghezza: appena sopra la soglia
     (1501-1520px circa) lo spazio libero per lo username crolla a ~106px
     misurati, per poi riaprirsi salendo di larghezza — un tetto fisso più
     stretto (100px, con margine sotto ai 106px misurati nel punto più
     stretto) evita di dover scegliere una soglia dedicata in più solo per
     questo, sacrificando qualche carattere in più visibile quando la
     finestra è molto larga (scelta di leggibilità/robustezza, non un
     vincolo reale a quelle larghezze).
   Limite noto, non affrontato qui: le misure sopra assumono un utente non
   admin (nessun badge). Con badge admin lo spazio disponibile è ancora più
   stretto (badge = testo in più nella stessa riga) — un admin con uno
   username molto lungo su un telefono molto stretto (misurato: sotto i
   ~360px) può ancora vedere un overflow residuo di pochi px. Segnalato
   all'utente, non corretto qui: andrebbe gestito rendendo `.badge` capace
   di andare a capo o riducendone la dimensione sotto la soglia telefono,
   un intervento distinto da questo. */
.topbar .user .username {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: inline-block; max-width: min(15vw, 150px); vertical-align: bottom;
}
@media (min-width: 1501px) {
  .topbar .user .username { max-width: 100px; }
}
.bell { position: relative; cursor: pointer; font-size: 1.1rem; text-decoration: none; }
.bell .dot {
  position: absolute; top: -4px; right: -7px;
  background: var(--red); color: #fff; font-size: 0.62rem; font-weight: 700;
  border-radius: 999px; padding: 1px 5px;
}
/* Bug pre-esistente scoperto verificando la correzione dell'overflow nav
   (10/08/2026), corretto qui su richiesta esplicita dell'utente: a schermi
   telefono molto stretti (misurato: 300-344px, es. iPhone SE 1ª/2ª gen) la
   barra logo+pulsante ☰+blocco utente (campanella/nome/Esci) — indipendente
   dal pannello di navigazione, già a scomparsa dalla Fase 1 — usciva di
   circa 24px dal bordo destro della pagina. Non è il contenuto a dover
   sparire, solo gli spazi vuoti attorno: `.topbar` e `.topbar .user` sono
   solo un po' più compatti sotto la soglia telefono (gap/padding ridotti,
   mai il contenuto). Verificato con Playwright: nessun overflow fino a un
   minimo intrinseco di 297px, ben sotto qualunque telefono reale in uso
   (320px il più stretto comune). Sopra i 600px questa regola non si applica
   mai, quindi il desktop resta invariato per costruzione. */
@media (max-width: 600px) {
  .topbar { padding: 0.6rem 0.85rem; gap: 0.6rem; }
  .topbar .user { gap: 0.35rem; }
}
main { max-width: 1100px; margin: 0 auto; padding: 1.5rem; }
/* Mobile-friendly UI, Fase 0: 1,5rem fissi su un telefono da 360-390px si
   mangiano ~48px di larghezza utile senza motivo — ridotto solo sotto la
   soglia telefono, il desktop (>600px) resta 1,5rem come oggi. */
@media (max-width: 600px) { main { padding: 1rem 0.75rem; } }
footer { text-align: center; color: var(--muted); font-size: 0.8rem; padding: 2rem 0 1.2rem; }

/* Cards & grids */
.grid { display: grid; gap: 1.2rem; }
.grid.cols-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 800px) { .grid.cols-2 { grid-template-columns: 1fr; } }
.grid.sector-grid { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .grid.sector-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 500px) { .grid.sector-grid { grid-template-columns: 1fr; } }
/* Calendario: elenco partite + finestra arbitri a destra (richiesta prodotto, 18/07/2026) */
.grid.cols-fixtures { grid-template-columns: 1fr 320px; align-items: start; }
@media (max-width: 900px) { .grid.cols-fixtures { grid-template-columns: 1fr; } }
.referees-panel { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow-y: auto; }
.referee-row { padding: 0.7rem 0; border-bottom: 1px solid rgba(43,54,70,0.5); }
.referee-row:last-child { border-bottom: none; }
.referee-row .mt { margin-top: 0.3rem; }
.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 14px; padding: 1.2rem;
}
.card h2 { font-size: 1.02rem; margin-bottom: 0.9rem; color: var(--accent); text-transform: uppercase; letter-spacing: 0.8px; }
.card h3 { font-size: 0.95rem; margin: 0.8rem 0 0.5rem; color: var(--muted); }

/* Annuncio campione (richiesta prodotto, 25/07/2026): nel Cruscotto, quando
   il campionato si è appena concluso (finestra di mercato aperta), il nome
   della squadra prima in classifica compare qui in grande — ben distinto dal
   resto del banner "mercato aperto", che sotto resta di dimensione normale. */
.champion-banner { font-size: 1.7rem; font-weight: 800; color: var(--yellow); text-align: center; margin: 0.7rem 0; }

/* Tables */
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
/* Tabelle molto larghe (es. Rosa, con tutte le colonne di statistiche +
   cella contratto con etichetta "Ultima stagione!", tendina durata rinnovo
   e pulsanti): senza questo wrapper la tabella supera la larghezza della
   card e trabocca fuori dal layout principale invece di scorrere al suo
   interno (bug segnalato, corretto il 25/07/2026). Lo scroll orizzontale
   resta invisibile quando la tabella entra comunque nello spazio disponibile. */
/* Mobile-friendly UI, Fase 2 (richiesta prodotto, 09/08/2026, piano approvato
   nel Progetto — "Mobile-friendly UI - Documento di Progettazione.md"):
   `.table-scroll` estesa da 4 a tutte le 18 tabelle dell'app (stesso
   wrapper di sempre, solo applicato ovunque mancasse) più due aggiunte
   valide per tutte, senza distinzione fra tabelle larghe o strette:
   un'ombra persistente sul bordo destro come indizio che c'è altro da
   scorrere (funziona con qualunque sfondo dietro, non serve indovinare un
   colore preciso — a differenza di un dissolvenza a gradiente, che invece
   andrebbe intonata sfondo per sfondo), e la prima colonna "agganciata" a
   sinistra mentre si scorrono le altre, così l'identità della riga (nome,
   squadra, #) resta sempre visibile. Su una tabella che non trabocca (la
   maggioranza) queste regole restano semplicemente inerti — nessun effetto
   visibile, nessun rischio. */
/* Intestazione agganciata in alto (richiesta prodotto, 11/08/2026, esempio
   guida: Rosa, dove scorrendo verso gli attaccanti si perdeva di vista quale
   colonna fosse quale skill): `overflow-x: auto` da solo rende comunque
   questo contenitore un "contenitore di scroll" anche sull'asse verticale
   (regola della spec CSS Overflow: se un asse è auto/scroll e l'altro è
   visible, il visible diventa implicitamente auto) — quindi un'intestazione
   sticky qui dentro si sarebbe agganciata al contenitore stesso, non alla
   pagina, e senza un'altezza propria il contenitore non scorre mai da solo
   (motivo per cui prima non bastava aggiungere solo `position: sticky`
   all'intestazione). La soluzione è dargli un'altezza massima: sotto quella
   soglia il contenitore semplicemente non scorre (nessun effetto sulle
   tabelle corte, identiche a prima), sopra quella soglia scorre al suo
   interno sia in verticale che in orizzontale, con intestazione e prima
   colonna entrambe agganciate — come un foglio di calcolo con riga e colonna
   congelate. 65vh è un primo valore ragionevole, da ritarare a occhio. */
.table-scroll { overflow-x: auto; overflow-y: auto; max-height: 65vh; -webkit-overflow-scrolling: touch; box-shadow: inset -14px 0 10px -10px rgba(0,0,0,0.4); }
th { text-align: left; color: var(--muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--border); }
td { padding: 0.5rem; border-bottom: 1px solid rgba(43, 54, 70, 0.5); }
tr:last-child td { border-bottom: none; }
tr.mine td { background: rgba(52, 211, 153, 0.07); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Colonna agganciata: sfondo pieno necessario per non far trasparire le
   celle che scorrono sotto mentre resta ferma; ridichiarata per le righe
   "mine" (la propria squadra, evidenziata sopra) componendo la stessa tinta
   verde già usata su uno sfondo opaco, così la colonna agganciata non perde
   l'evidenziazione quando si scorre. z-index esplicito (1): senza, un
   elemento sticky senza z-index dichiarato segue l'ordine del DOM invece
   dell'impilamento voluto, e qui il thead (che deve sempre vincere sul
   tbody quando i due si sovrappongono scorrendo in verticale) viene prima
   nel markup — quindi perderebbe altrimenti contro la colonna del tbody. */
.table-scroll table th:first-child, .table-scroll table td:first-child { position: sticky; left: 0; z-index: 1; background: var(--card); }
.table-scroll table tr.mine td:first-child { background: linear-gradient(rgba(52, 211, 153, 0.07), rgba(52, 211, 153, 0.07)), var(--card); }
/* Riga di intestazione agganciata in alto, oltre che (per la prima cella,
   già sticky a sinistra dalla regola sopra) a sinistra: la cella d'angolo
   deve vincere l'impilamento su ENTRAMBI i vicini — sulle altre celle
   dell'intestazione quando si scorre in orizzontale (passano sotto di lei),
   e sulla colonna agganciata del corpo quando si scorre in verticale — da
   qui lo z-index più alto (3) rispetto al resto della riga (2) e alla
   colonna del corpo (1, sopra). */
.table-scroll table thead th { position: sticky; top: 0; z-index: 2; background: var(--card); }
.table-scroll table thead th:first-child { z-index: 3; }

/* Nome giocatore in Rosa, richiesta prodotto 12/08/2026: è l'unico punto di
   tutta l'app dove il nome è un vero link (apre la scheda giocatore, vedi
   squadTable in app.js) — senza questa regola il browser gli applica il blu
   di default per i link non visitati, poco leggibile sullo sfondo scuro.
   Stesso "quasi bianco" già usato per tutto il resto del testo (var(--text),
   non un bianco puro a sé) così il nome torna identico, come tono, a come
   appare ovunque altrove nell'app — vale su mobile e desktop, la causa non
   era mai stata specifica del mobile. Resta cliccabile esattamente come
   prima: cambia solo il colore, non il comportamento del link. */
.player-link { color: var(--text); text-decoration: none; }
.player-link:hover { color: var(--accent); }

/* Nomi squadra cliccabili in classifica (Storico Scontri Diretti, richiesta
   prodotto, 15/08/2026): stessa identica correzione di .player-link sopra —
   senza questa regola i link ereditano il blu di default del browser,
   illeggibile sullo sfondo scuro dell'app. */
.team-link { color: var(--text); text-decoration: none; }
.team-link:hover { color: var(--accent); }

/* Forms & buttons */
input, select, textarea {
  width: 100%; padding: 0.6rem 0.8rem; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg2); color: var(--text);
  font-size: 0.95rem; margin-bottom: 0.8rem; font-family: inherit;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--green-dark); border-color: transparent; }
/* Forum (richiesta prodotto, 13/08/2026): textarea introdotta per la prima
   volta (nuovo thread / risposta / motivazione cartellino) — resize solo
   verticale per non rompere il layout della card che la contiene. */
textarea { resize: vertical; min-height: 4.5rem; }
label { display: block; font-size: 0.8rem; color: var(--muted); margin-bottom: 0.3rem; font-weight: 600; }
button, .btn {
  display: inline-block; padding: 0.6rem 1.3rem; border-radius: 8px; border: none;
  background: var(--green-dark); color: #fff; font-weight: 700; font-size: 0.95rem;
  cursor: pointer; text-decoration: none; transition: filter 0.15s;
}
button:hover, .btn:hover { filter: brightness(1.15); }
button.secondary, .btn.secondary { background: var(--bg2); border: 1px solid var(--border); color: var(--text); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
/* Mobile-friendly UI, Fase 0: altezza minima di tocco ~44px (linea guida
   accessibilità), oggi non garantita (bottoni/campi coi soli padding sopra
   restano sotto quella soglia). `min-height` invece di alzare i padding
   perché resta valido anche per i bottoni con padding ridotto via style
   inline (es. il pulsante "Esci" nella topbar) senza doverli toccare uno per
   uno. Solo sotto la soglia telefono: sopra i 600px bottoni/campi restano
   dimensionati come oggi. */
@media (max-width: 600px) {
  button, .btn, input, select { min-height: 44px; }
}

/* Auth */
.auth-wrap { max-width: 420px; margin: 3rem auto; }
.auth-wrap .logo-big { text-align: center; font-size: 2rem; font-weight: 800; color: var(--accent); margin-bottom: 1.5rem; }
.auth-tabs { display: flex; gap: 0.5rem; margin-bottom: 1.2rem; }
.auth-tabs button { flex: 1; background: var(--bg2); border: 1px solid var(--border); color: var(--muted); }
.auth-tabs button.active { background: var(--green-dark); color: #fff; border-color: transparent; }
.hint { color: var(--muted); font-size: 0.82rem; margin: 0.6rem 0; line-height: 1.4; }
/* Link nella schermata di login (richiesta prodotto, 13/08/2026): stessa
   correzione già applicata a .player-link — senza questa regola i link
   ("Password dimenticata", "Torna al login") ereditano il blu di default del
   browser per i link non visitati, poco leggibile sullo sfondo scuro. */
.hint a { color: var(--text); }
/* Percorso di Avvio Guidato "Primi passi" (richiesta prodotto, 17/08/2026):
   card dismissibile in Cruscotto, vedi renderDashboard/onboardingCardHtml. */
.onboarding-list { list-style: none; margin: 0.7rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.onboarding-item { display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem; }
.onboarding-item label { display: flex; align-items: center; gap: 0.5rem; cursor: pointer; }
.onboarding-item input[disabled] { cursor: default; }
.onboarding-item label.done span { color: var(--muted); text-decoration: line-through; }
.onboarding-hint { flex-basis: 100%; margin: 0; color: var(--muted); font-size: 0.8rem; line-height: 1.4; }
.onboarding-hint a { color: var(--text); }
/* Obiettivi di Stagione (richiesta prodotto, 17/08/2026): card fissa nel
   Cruscotto, vedi renderDashboard/objectiveCardHtml. */
.objective-row { margin-top: 0.6rem; }
.objective-row:first-of-type { margin-top: 0.7rem; }
.objective-row p { margin: 0.3rem 0 0; }
.error-box { background: rgba(248, 113, 113, 0.12); border: 1px solid var(--red); color: var(--red); border-radius: 8px; padding: 0.6rem 0.9rem; font-size: 0.88rem; margin-bottom: 0.9rem; }
.ok-box { background: rgba(52, 211, 153, 0.12); border: 1px solid var(--green); color: var(--green); border-radius: 8px; padding: 0.6rem 0.9rem; font-size: 0.88rem; margin-bottom: 0.9rem; }

/* Badges */
.badge { display: inline-block; font-size: 0.68rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.4px; }
.badge.green { background: rgba(52, 211, 153, 0.15); color: var(--green); }
.badge.red { background: rgba(248, 113, 113, 0.15); color: var(--red); }
.badge.yellow { background: rgba(251, 191, 36, 0.15); color: var(--yellow); }
.badge.blue { background: rgba(96, 165, 250, 0.15); color: var(--blue); }
.badge.gray { background: rgba(139, 152, 171, 0.15); color: var(--muted); }

/* Match report */
.score-header { text-align: center; padding: 1rem 0 0.4rem; }
.score-header .teams { font-size: 1.25rem; font-weight: 700; }
.score-header .score { font-size: 2.6rem; font-weight: 800; color: var(--accent); margin: 0.3rem 0; font-variant-numeric: tabular-nums; }
.score-header .meta { color: var(--muted); font-size: 0.85rem; }
.report-line { padding: 0.45rem 0.7rem; border-left: 3px solid var(--border); margin: 0.35rem 0; font-size: 0.93rem; line-height: 1.45; border-radius: 0 8px 8px 0; }
.report-line.goal { border-color: var(--green); background: rgba(52, 211, 153, 0.08); font-weight: 600; }
.report-line.yellow { border-color: var(--yellow); }
.report-line.red { border-color: var(--red); background: rgba(248, 113, 113, 0.07); }
.report-line.injury { border-color: var(--blue); }
.report-line.system { color: var(--muted); font-style: italic; border-color: transparent; }
.report-line.tech { border-color: var(--violet); background: rgba(167, 139, 250, 0.08); font-style: italic; }
.stats-bar { display: grid; grid-template-columns: 60px 1fr 60px; align-items: center; gap: 0.6rem; margin: 0.4rem 0; font-size: 0.85rem; }
.stats-bar .label { text-align: center; color: var(--muted); grid-column: 1 / 4; font-size: 0.72rem; text-transform: uppercase; }
.bar { height: 7px; border-radius: 4px; background: var(--bg2); overflow: hidden; display: flex; }
.bar > div { background: var(--green-dark); }
.bar > div.away { background: var(--blue); margin-left: auto; }

/* Lineup editor */
.slot-row { display: grid; grid-template-columns: 200px 1fr auto; gap: 0.6rem; align-items: center; margin-bottom: 0.4rem; }
.slot-row .pos { font-size: 0.72rem; font-weight: 700; color: var(--muted); text-transform: uppercase; line-height: 1.25; }
.slot-row .badge { white-space: nowrap; }
.slot-row .badges { display: flex; flex-direction: column; gap: 0.25rem; align-items: flex-start; }
@media (max-width: 800px) { .slot-row { grid-template-columns: 120px 1fr auto; } }
.slot-row select { margin-bottom: 0; }
.pill-group { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.pill-group button { background: var(--bg2); border: 1px solid var(--border); color: var(--muted); padding: 0.4rem 0.9rem; font-size: 0.85rem; }
.pill-group button.active { background: var(--green-dark); color: #fff; border-color: transparent; }
.bench-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 0.3rem; }
.bench-list label { display: flex; align-items: center; gap: 0.45rem; font-size: 0.85rem; color: var(--text); font-weight: 400; background: var(--bg2); border-radius: 7px; padding: 0.4rem 0.6rem; cursor: pointer; }
.bench-list input { width: auto; margin: 0; }

/* Mobile-friendly UI, Fase 3 (richiesta prodotto, 10/08/2026, piano approvato
   nel Progetto — "Mobile-friendly UI - Documento di Progettazione.md"): il
   form Formazione (renderLineup) è il più lungo dell'app su un telefono
   (modulo + 11 tendine + panchina + capitano, tutto in una sola colonna sotto
   gli 800px per via di .grid.cols-2 già esistente). Due interventi, entrambi
   attivi SOLO sotto la soglia telefono (600px):
   1) le 4 sezioni (Titolari/Modulo/Capitano/Panchina) diventano richiudibili
      — Titolari resta aperta di default (è il compito principale), le altre
      tre partono chiuse per accorciare lo scroll iniziale. Il markup
      (.collapsible/.collapsible-toggle/.collapsible-body) è lo STESSO a ogni
      larghezza (nessuna diramazione per viewport in JS, stessa disciplina di
      Fase 1/2): sopra i 600px il pulsante diventa non interattivo
      (cursor/pointer-events) e .collapsible-body non ha MAI una regola
      display:none fuori dal blocco @media qui sotto, quindi il corpo resta
      sempre visibile sul desktop qualunque sia lo stato "collapsed" —
      desktop bit-per-bit invariato per costruzione, non per convenzione.
   2) il pulsante "Salva formazione" (già presente, invariato per il
      desktop) diventa una barra agganciata in fondo allo schermo, sempre
      raggiungibile senza dover riscorrere il form fino in cima dopo una
      modifica in fondo alla pagina. */
.collapsible-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  width: 100%; background: none; border: none; padding: 0; margin-bottom: 0.9rem;
  text-align: left; font: inherit; color: inherit; cursor: default; pointer-events: none;
}
.collapsible-toggle h2 { margin-bottom: 0; }
.collapsible-toggle .chevron { display: none; flex: none; color: var(--muted); font-size: 0.8rem; transition: transform 0.2s ease; }
@media (max-width: 600px) {
  .collapsible-toggle { cursor: pointer; pointer-events: auto; }
  .collapsible-toggle .chevron { display: inline-block; }
  .collapsible.collapsed .collapsible-toggle { margin-bottom: 0; }
  .collapsible.collapsed .chevron { transform: rotate(-90deg); }
  .collapsible.collapsed .collapsible-body { display: none; }

  .lineup-page { padding-bottom: 4.75rem; }
  .lineup-page .save-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 15;
    margin: 0; padding: 0.7rem 1rem; background: var(--bg2);
    border-top: 1px solid var(--border);
  }
  .lineup-page .save-bar button { width: 100%; }
}

/* Mobile-friendly UI, Fase 4 (richiesta prodotto, 10/08/2026, piano approvato
   nel Progetto — "Mobile-friendly UI - Documento di Progettazione.md"):
   rifinitura delle pagine restanti (Cruscotto, Calendario, Coppa, Mercato,
   Bilancio, Stadio, Centro, Partita live, Forum). Le griglie a due
   colonne esistenti (.grid.cols-2 e simili) collassavano già sotto gli
   800/900/500px — qui si sistemano 3 griglie a TRE colonne fisse che finora
   avevano la larghezza scritta inline in app.js (quindi non gestibile da
   nessun breakpoint) e la riga stadio nome+pulsante, anch'essa un flex
   inline senza wrap. Nel farlo è emerso anche un bug pre-esistente: la
   griglia del vivaio in Allenamenti aveva class="grid cols-2" MA uno style
   inline grid-template-columns che sovrascriveva sempre la regola
   responsive di .cols-2 (lo style inline vince sempre su un @media di un
   foglio esterno) — restava quindi bloccata a 3 colonne a qualunque
   larghezza. Le classi qui sotto sostituiscono quegli style inline. */
.friendly-form-grid { grid-template-columns: 1fr 1fr 1fr; gap: 0.6rem; }
.camp-tiers-grid { grid-template-columns: 1fr 1fr 1fr; gap: 0.8rem; }
.youth-cards-grid { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 600px) {
  .friendly-form-grid { grid-template-columns: 1fr; }
  .camp-tiers-grid { grid-template-columns: 1fr; }
  .youth-cards-grid { grid-template-columns: 1fr; }
}

.stadium-rename-row { display: flex; gap: 0.6rem; align-items: center; margin-top: 0.8rem; }
@media (max-width: 600px) {
  .stadium-rename-row { flex-direction: column; align-items: stretch; }
  .stadium-rename-row button { width: 100%; }
}

/* Notifications */
.notif { padding: 0.6rem 0.8rem; border-radius: 8px; margin-bottom: 0.4rem; background: var(--bg2); font-size: 0.88rem; display: flex; gap: 0.6rem; align-items: baseline; }
.notif.unread { border-left: 3px solid var(--accent); }
.notif time { color: var(--muted); font-size: 0.75rem; white-space: nowrap; }

.fixture-row { display: grid; grid-template-columns: 1fr auto 1fr auto; gap: 0.8rem; align-items: center; padding: 0.55rem 0.4rem; border-bottom: 1px solid rgba(43,54,70,0.5); font-size: 0.92rem; }
.fixture-row:last-child { border-bottom: none; }
.fixture-row .h { text-align: right; }
.fixture-row .s { font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 600px) {
  /* Mobile-friendly UI, Fase 4 (10/08/2026): sotto i 600px la 4a colonna
     (.small, data/orario + azione) non entra più affiancata alle prime tre
     senza schiacciarsi — passa a riga propria a tutta larghezza. */
  .fixture-row { grid-template-columns: 1fr auto 1fr; row-gap: 0.35rem; }
  .fixture-row .small { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; }
}
.muted { color: var(--muted); }
.small { font-size: 0.8rem; }
h1.page-title { font-size: 1.35rem; margin-bottom: 1.2rem; }
.mb { margin-bottom: 1.2rem; }
.mt { margin-top: 1.2rem; }
.right { text-align: right; }

/* Cruscotto: statistiche all time del club (richiesta prodotto, 18/07/2026) */
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.9rem; margin-top: 0.6rem; }
@media (max-width: 500px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
.stat-tile { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0.6rem 0.4rem; background: var(--bg2); border-radius: 8px; }
.stat-tile .stat-value { font-size: 1.15rem; font-weight: 800; color: var(--accent); font-variant-numeric: tabular-nums; }
.stat-tile .stat-label { font-size: 0.72rem; color: var(--muted); margin-top: 0.2rem; }

/* Partita LIVE */
.live-badge { display: inline-block; background: #dc2626; color: #fff; font-size: 0.68rem; font-weight: 800; letter-spacing: 0.08em; padding: 0.15rem 0.5rem; border-radius: 5px; animation: livepulse 1.6s ease-in-out infinite; vertical-align: middle; }
@keyframes livepulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.live-card { border: 1px solid rgba(220, 38, 38, 0.45); }
.live-panel select { width: 100%; }
/* In campo: elenco giocatori con condizione live (richiesta prodotto, 22/07/2026) */
.pitch-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.24rem 0; font-size: 0.88rem; border-bottom: 1px solid var(--border); }
.pitch-row:last-child { border-bottom: none; }
/* Ruolo preciso (richiesta prodotto, 23/07/2026): colonna allargata per
   ospitare etichette come "Centrocampista centrale sinistro" invece del
   solo reparto generico (GK/DF/MF/FW) — con ellissi + title come rete di
   sicurezza sugli schermi più stretti. */
.pitch-row .pos { width: 13.5rem; flex: none; color: var(--muted); font-size: 0.72rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pitch-row .pname { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pitch-row.tired .pname { color: var(--red); font-weight: 600; }
@media (max-width: 800px) { .pitch-row .pos { width: 7.5rem; font-size: 0.66rem; } }
.form-bar { width: 64px; height: 8px; flex: none; border-radius: 4px; background: var(--border); overflow: hidden; }
.form-bar i { display: block; height: 100%; border-radius: 4px; transition: width 0.6s ease; }
.form-bar.good i { background: var(--green); }
.form-bar.mid i { background: var(--yellow); }
.form-bar.low i { background: var(--red); }
.form-num { width: 2.2rem; flex: none; text-align: right; font-variant-numeric: tabular-nums; font-size: 0.8rem; color: var(--muted); }
.opp-formation { font-size: 1.05rem; }

/* Interruttore (slider) sostituzioni automatiche */
.switch-row { display: flex; align-items: center; gap: 0.6rem; cursor: pointer; font-weight: 600; }
.switch { position: relative; display: inline-block; width: 42px; height: 24px; flex: none; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; inset: 0; background: var(--bg2); border: 1px solid var(--border); border-radius: 999px; transition: background 0.2s; }
.switch .slider::before { content: ''; position: absolute; width: 18px; height: 18px; left: 2px; top: 2px; background: var(--muted); border-radius: 50%; transition: transform 0.2s, background 0.2s; }
.switch input:checked + .slider { background: var(--green-dark); border-color: transparent; }
.switch input:checked + .slider::before { transform: translateX(18px); background: #fff; }

/* Tour Guidato "Imposta la formazione" (richiesta prodotto, 22/08/2026): un
   pannello fluttuante, appeso a document.body (non a $app: sopravvive ai
   ridisegni della pagina fra una tappa e l'altra, vedi app.js). Non è un
   overlay a schermo intero apposta — il Manager deve continuare a vedere la
   pagina di cui il pannello sta parlando. z-index sopra la topbar (21) e il
   pannello di navigazione mobile (20), ma sotto il popup di contrattazione
   (1000, l'unico vero overlay modale del sito) per lasciargli sempre la
   precedenza se mai dovessero capitare insieme. */
.tour-panel {
  position: fixed; left: 50%; bottom: 1rem; transform: translateX(-50%);
  z-index: 950; width: calc(100% - 2rem); max-width: 30rem;
  background: var(--card); border: 2px solid var(--accent); border-radius: 10px;
  padding: 1rem 1.1rem; box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
}
.tour-panel .tour-progress { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.3rem; }
.tour-panel h3 { margin: 0 0 0.5rem; color: var(--accent); font-size: 1rem; }
.tour-panel .tour-body { font-size: 0.88rem; line-height: 1.45; margin-bottom: 0.9rem; }
.tour-panel .tour-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.tour-panel .tour-nav { display: flex; gap: 0.5rem; }
@media (max-width: 600px) { .tour-panel { bottom: 0.5rem; padding: 0.85rem; } }

/* Elemento evidenziato dalla tappa corrente del tour — stesso --accent del
   pannello, per riconoscerli come collegati a colpo d'occhio. */
.tour-highlight { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 8px; }

/* Regolamento di Lega (richiesta prodotto, 23/08/2026): i 18 capitoli sono
   elementi <details> nativi — niente JS per aprire/chiudere, lo gestisce il
   browser. Qui solo l'aspetto: il <summary> di default del browser (con la
   sua freccetta nativa, diversa per browser) viene sostituito dalla stessa
   idea di freccia di .collapsible-toggle più sopra, così il capitolo
   chiuso/aperto si riconosce allo stesso modo del resto dell'app. */
.rules-chapter summary {
  cursor: pointer; list-style: none; font-weight: 700; color: var(--accent);
  font-size: 0.98rem; display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
}
.rules-chapter summary::-webkit-details-marker { display: none; }
.rules-chapter summary .chevron { color: var(--muted); font-size: 0.75rem; flex: none; transition: transform 0.15s ease; }
.rules-chapter[open] summary .chevron { transform: rotate(90deg); }
.rules-chapter[open] summary { margin-bottom: 0.9rem; }
.rules-chapter .rules-body h4 { font-size: 0.9rem; color: var(--muted); margin: 0.8rem 0 0.4rem; }
.rules-chapter .rules-body h4:first-child { margin-top: 0; }
.rules-chapter .rules-body p { margin-bottom: 0.6rem; line-height: 1.5; }
.rules-chapter .rules-body ul { margin: 0 0 0.6rem 1.1rem; }
.rules-chapter .rules-body li { margin-bottom: 0.35rem; line-height: 1.45; }
.rules-chapter .rules-body p:last-child, .rules-chapter .rules-body ul:last-child { margin-bottom: 0; }
