/* =============================================================
   admin-theme.css — il vestito del pannello di amministrazione.
   Si carica DOPO hub-theme.css, da cui prende gettoni, font e fondo.
   Generato da build.sh — non modificare a mano: modifica
   theme-admin/*.css
   ============================================================= */

/* ---------- 01-guscio.css ---------- */
/* =========================================================================
   01 · IL GUSCIO DEL PANNELLO
   Testata, barra laterale, area di contenuto, porta di servizio.

   Differenza sostanziale rispetto a theme/02-guscio.css: là il guscio
   esisteva già e il tema lo ridipingeva. Qui no. Il pannello admin non
   carica styles.css e il suo blocco <style> di 392 righe viene rimosso:
   sotto questo foglio non c'è NIENTE, nemmeno il reset. Quindi qui non si
   ritocca un impianto, si costruisce l'impianto.

   Il disegno è la traduzione del prototipo (yoyohub-redesign/admin/) sui
   nomi di classe del pannello vero, che non si rinominano perché admin.js
   li usa come selettori. Le misure sono copiate da css/hub.css: dove ho
   cambiato un numero c'è scritto perché.

   Colori: solo gettoni di hub-theme.css. L'unica eccezione dichiarata è il
   riquadro del marchio (1.5): un marchio non si inverte in tema chiaro, ed
   è lo stesso motivo per cui hub-theme.css scrive quei valori alla lettera
   in .yh-logo-mark.

   1.1  Reset minimo            1.8  Corpo: barra + contenuto
   1.2  Le misure               1.9  Il menu verticale
   1.3  Il telaio               1.10 Piede della barra e uscita
   1.4  La testata (OPACA)      1.11 Contenuto e schermate
   1.5  Il marchio              1.12 La porta di servizio
   1.6  Le briciole             1.13 Lineette · schermo largo
   1.7  Pulsanti di sola icona  1.14 Lineette · schermo stretto

   IL PREFISSO DELLE CLASSI È `amm-` (amministrazione) E NON `ad-`. Non è
   gusto: `ad-` per un blocca-pubblicità significa "advertising", e le liste
   che usano tutti (EasyList) contengono regole GENERICHE — valide su
   qualunque sito — che nascondono con display:none `.ad-rail`, `.ad-body`,
   `.ad-main`, `.ad-tag`, `.ad-cat`, `.ad-on`, `.ad-hold`. Sette delle nostre.
   Il 2026-09-10 la barra laterale del pannello era invisibile per l'utente e
   perfettamente funzionante per chiunque non avesse un blocco installato: il
   difetto più difficile che questo lavoro abbia prodotto, e nel codice non
   c'era niente da vedere. Nessuna classe nuova comincia per `ad`; prima di
   scegliere un prefisso, cercarlo in easylist.txt.
   ========================================================================= */


/* =============================================== 1.1 · RESET MINIMO ======
   QUESTA È L'UNICA COPIA DEL RESET IN TUTTO IL PANNELLO. Non è un
   duplicato di niente: il vecchio blocco <style> apriva con
   `*{margin:0;padding:0;box-sizing:border-box}` ed è stato cancellato per
   intero, e hub-theme.css non lo rimpiazza — è uno strato di ritocco,
   scritto per stare SOPRA styles.css dell'applicazione, e il pannello
   admin styles.css non lo carica. Sotto questo foglio c'è solo il foglio
   di base del browser.

   Cosa succede senza queste righe, in concreto:
   · senza box-sizing:border-box ogni `width:100%` con un padding misura
     100% PIÙ il padding e sborda — è il guasto che fa sembrare sbagliato
     il lavoro di tutti, perché si vede su ogni campo e ogni scheda;
   · senza l'azzeramento dei margini i titoli tornano ai margini del
     browser, che sono grossi e disuguali fra un h3 e un h4 (nel pannello
     ce ne sono 1 h1, 7 h2, 10 h3, 6 h4 e un pre);
   · senza font:inherit i campi e i pulsanti tornano al corpo del browser.
     La famiglia la impone già hub-theme.css con !important, ma la MISURA
     no, e un <select> a 13px di sistema in mezzo a campi da 15 si vede.

   Due assenze volute, per non scrivere selettori di altri: `textarea`
   (assegnato a 02-controlli.css) e `table`/`border-collapse` (assegnato a
   03-contenuti.css). Il reset qui si fermano ai margini e alla scatola.  */
*,*::before,*::after{ box-sizing:border-box; }
body{ margin:0; }
h1,h2,h3,h4,h5,h6,p,pre,figure{ margin:0; }
button,input,select{ font:inherit; color:inherit; }
/* padding:0 sul pulsante è parte del reset vecchio che vale la pena
   tenere: il padding predefinito del browser cambia da browser a browser,
   e ogni pulsante del pannello la sua spaziatura la dichiara. */
button{ background:none; border:0; padding:0; cursor:pointer; }
/* Nel pannello i link sono comandi travestiti ("Torna a YoyoHub", i
   pulsanti-ancora della testata): la sottolineatura del browser li
   farebbe leggere come testo di un documento. */
a{ color:inherit; text-decoration:none; }
/* Le icone SVG: `max-width` le tiene dentro il loro posto se un giorno una
   arrivasse senza attributi di misura.
   `display:block` c'era e l'ho toltо: nei contenitori flex non cambiava
   niente (un figlio di flex viene comunque trattato come blocco), ma dove
   un'icona sta IN MEZZO AL TESTO la mandava a capo da sola. Si vedeva
   all'oggetto della mail di NewEden: "Oggetto:" su una riga, l'icona sola
   sulla riga dopo, e il testo dell'oggetto su una terza. Le misure le
   dichiara `.yh-i` (20x20), quindi il motivo per cui `display:block` era
   stato scritto non esisteva. */
svg{ max-width:100%; }


/* ==================================================== 1.2 · LE MISURE ====
   Il prototipo le tiene in :root come --header-h / --rail-w / --gutter, ma
   quei gettoni non esistono in hub-theme.css e non vanno inventati là:
   vivono qui, con il prefisso amm-, e stanno su .admin-container e non su
   :root perché sono misure di QUESTO guscio, non della tavolozza.

   --amm-rail-w è 280px e non i 250px del prototipo. La misura non la decide
   il menu (la voce più lunga, "Servizi & Permessi TL", ci sta in 250)
   ma il lockup della testata: il prototipo diceva "Admin", il pannello
   vero dice "Amministrazione", dieci lettere in più. Il blocco del marchio
   è largo quanto la barra perché i due filetti verticali devono essere lo
   stesso filetto: se il marchio non ci sta, si vede che sono due.         */
.admin-container{
  --amm-hdr-h:60px;
  --amm-rail-w:280px;
  --amm-gutter:26px;
  /* Larghezza della barra quando esce SOPRA il contenuto (≤900px). È una
     misura diversa perché lì la barra non divide lo spazio, lo copre. */
  --amm-rail-over:272px;
}


/* ===================================================== 1.3 · IL TELAIO ==
   .admin-container era un foglio A4 (max-width:1100px, margin:0 auto,
   padding:2rem): una pagina di documento dentro cui scorreva tutto.
   Diventa il telaio dell'applicazione, alto quanto la finestra, con la
   testata ferma in cima e il solo contenuto che scorre. È l'equivalente
   di .app nel prototipo.

   La doppia dichiarazione di height non è un errore: 100dvh tiene conto
   delle barre del browser mobile, che compaiono e spariscono, ma i
   browser che non la conoscono la scartano e tengono la riga prima.

   Il prototipo aggiunge z-index:1 perché là il fondo atmosferico è uno
   pseudo-elemento a z-index:0. In hub-theme.css il fondo sta direttamente
   sul body (§1.3, per non creare un contesto di impilamento), quindi qui
   lo z-index non serve e non lo mettiamo: un contesto di impilamento in
   meno è un posto in meno dove una tendina può finire sotto.              */
.admin-container{
  display:flex;
  flex-direction:column;
  height:100vh;
  height:100dvh;
  position:relative;
}


/* ================================================== 1.4 · LA TESTATA ====
   OPACA, non di vetro. Non è una preferenza: la testata galleggia sopra il
   contenuto che scorre, e una lastra all'8% di bianco lascia leggere
   attraverso le parole che le passano sotto. È la stessa regola per cui in
   hub-theme.css esiste --surface-menu, ed è la lezione della fase 8.

   Il selettore è `.admin-container > .amm-hdr` e non `.amm-hdr` per una
   ragione di specificità, non di stile: hub-theme.css §8.3 dichiara
   `body.light-mode header{ background:var(--glass-1); ... }` — peso
   (0,1,2) — e la nostra testata È un <header>. Un `.amm-hdr` nudo pesa
   (0,1,0) e in tema chiaro perderebbe: la testata tornerebbe di vetro
   proprio dove il fondo è chiaro e il problema si vede di più. Con due
   classi pesiamo (0,2,0) e vinciamo in entrambi i temi.                   */
.admin-container > .amm-hdr{
  height:var(--amm-hdr-h);
  flex:0 0 auto;
  display:flex;
  align-items:center;
  gap:18px;
  padding:0 22px 0 0;
  background:var(--surface-menu);
  border-bottom:1px solid var(--glass-edge);
  box-shadow:var(--shadow-1), inset 0 1px 0 var(--glass-spec);
  /* position+z-index servono qui e non su .admin-container: la testata deve
     stare sopra il contenuto che le scorre sotto. Resta sotto ai 100 dei
     tre modali, che devono coprire tutto. */
  position:relative;
  z-index:40;
}


/* ================================================== 1.5 · IL MARCHIO ====
   Il blocco a sinistra è largo quanto la barra laterale e chiude con lo
   stesso filetto: da lì l'occhio capisce che il menu appartiene a quella
   colonna. La transizione sulla larghezza è la stessa della barra (1.13),
   così quando la barra si comprime i due si muovono insieme.              */
.amm-brand{
  width:var(--amm-rail-w);
  flex:0 0 auto;
  height:100%;
  display:flex;
  align-items:center;
  gap:10px;
  padding-left:18px;
  min-width:0;
  border-right:1px solid var(--glass-edge);
  transition:width .26s var(--ease);
}

/* Il riquadro nero rialzato con la Y gialla. Qui — e solo qui — i colori
   sono scritti alla lettera: è un marchio, e un marchio non si inverte
   quando l'utente accende il tema chiaro. hub-theme.css fa la stessa cosa
   per lo stesso motivo in .yh-logo-mark (§11.2), e le due lastre devono
   essere la stessa lastra: il pannello e l'applicazione hanno un marchio
   solo. Il rilievo lo fanno tre cose insieme: gradiente diagonale sul
   corpo, filo di luce sul bordo alto, ombra scura sul bordo basso. */
.amm-brand-mark{
  width:30px; height:30px;
  flex:0 0 auto;
  border-radius:9px;
  display:grid;
  place-items:center;
  position:relative;
  /* overflow contiene il riflesso diagonale qui sotto, non un menu: nessuna
     tendina nasce dentro il marchio. */
  overflow:hidden;
  background:linear-gradient(158deg,#212227 0%,#0a0b0d 52%,#141519 100%);
  border:1px solid rgba(255,255,255,.12);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.26),
    inset 0 -1px 0 rgba(0,0,0,.75),
    0 4px 14px -4px rgba(0,0,0,.65),
    0 0 22px -6px var(--accent-glow);
}
/* Vetro liquido: la striscia di luce che attraversa una superficie lucida
   vista di lato. Senza, il riquadro sembra un rettangolo nero. */
.amm-brand-mark::before{
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(148deg,
    rgba(255,255,255,.24) 0%,
    rgba(255,255,255,.07) 32%,
    transparent 56%);
}
/* Alone caldo dietro il glifo: è il giallo che bagna il vetro dall'interno
   e stacca la Y dal nero. */
.amm-brand-mark::after{
  content:'';
  position:absolute;
  left:50%; top:56%;
  width:150%; height:150%;
  transform:translate(-50%,-50%);
  background:radial-gradient(circle, var(--accent-glow) 0%, transparent 58%);
  opacity:.5;
}
/* z-index:1 mette la Y sopra i due pseudo-elementi qui sopra, che
   altrimenti la coprirebbero. */
.amm-brand-mark .yh-i{
  width:19px; height:19px;
  position:relative;
  z-index:1;
  color:var(--accent);
  filter:drop-shadow(0 0 5px var(--accent-glow));
}

.amm-brand-name{
  font-size:15.5px;
  font-weight:700;
  letter-spacing:-.02em;
  white-space:nowrap;
}
/* Nel prototipo l'etichetta è una pastiglia bordata perché dentro c'era
   "Admin", cinque lettere. "Amministrazione" ne ha quindici: nella stessa
   pastiglia diventa una barra larga mezzo lockup, e mangia i pixel che
   servono al filetto. Resta l'etichetta minuta — corpo, peso e spaziatura
   della pastiglia del prototipo — senza il riquadro.
   L'ellissi è un'assicurazione, non il comportamento previsto: a 280px la
   parola ci sta intera, ma se un domani il testo cambia si accorcia invece
   di sfondare la testata.                                                 */
.amm-brand-tag{
  flex:0 1 auto;
  min-width:0;
  font-size:9.5px;
  font-weight:700;
  letter-spacing:.1em;
  color:var(--ink-3);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}


/* ================================================= 1.6 · LE BRICIOLE ====
   Dicono dove sei. Nel pannello vecchio non c'era nulla del genere: le
   sette linguette in cima erano insieme menu e indicatore di posizione, e
   spostando il menu di lato l'indicatore serve.

   Restano accese a ogni larghezza. In produzione (theme/12-fase3.css) le
   briciole si spengono sotto i 1025px, ma là convivono con un blocco
   utente e un selettore di periodo: qui la testata ha solo due comandi, e
   piuttosto che togliere parole le lascio comprimere — flex:1 con
   min-width:0 e l'ellissi sull'ultimo pezzo, che è quello che cambia.     */
.amm-crumbs{
  display:flex;
  align-items:center;
  gap:8px;
  flex:1;
  min-width:0;
}
.amm-crumb-up{
  font-size:13px;
  color:var(--ink-3);
  white-space:nowrap;
}
.amm-crumb-sep{
  color:var(--ink-3);
  opacity:.5;
}
.amm-crumb-now{
  font-size:14px;
  font-weight:600;
  letter-spacing:-.01em;
  color:var(--ink);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

/* Il gruppo di destra non si comprime: sono due comandi, e un comando
   mezzo tagliato non è un comando. È la colonna che cede (1.6). */
.amm-tools{
  display:flex;
  align-items:center;
  gap:8px;
  flex:0 0 auto;
}


/* ==================================== 1.7 · PULSANTI DI SOLA ICONA ======
   Le tre lineette e l'interruttore del tema. A riposo non hanno superficie:
   una testata con due riquadri sempre accesi accanto al marchio sposta
   l'attenzione dove non serve. Il bordo trasparente c'è da subito perché
   in hover non cambino di misura.
   display:grid con place-items:center serve anche all'interruttore del
   tema, che dentro ha DUE icone (sole e luna) di cui una con l'attributo
   hidden: la griglia centra quella che resta senza saperlo.               */
.amm-icon-btn{
  width:34px; height:34px;
  flex:0 0 auto;
  border-radius:10px;
  display:grid;
  place-items:center;
  color:var(--ink-2);
  border:1px solid transparent;
  transition:background var(--speed) var(--ease),
             color var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.amm-icon-btn:hover{
  background:var(--glass-2);
  color:var(--ink);
  border-color:var(--glass-edge);
}
/* Il clic deve arrivare al PULSANTE, non all'icona che ci sta dentro.
   Senza questa riga il bersaglio del clic e' l'elemento <use> dell'icona,
   che riempie tutto il pulsante: in Chrome l'evento risale comunque e
   l'onclick parte, ma dentro uno <svg> il rimbalzo passa per un albero
   d'ombra e non tutti i browser lo fanno risalire allo stesso modo. Con
   pointer-events:none l'icona diventa trasparente al puntatore e il clic
   non ha altro posto dove andare che il pulsante. Vale per il pulsante
   delle tre lineette e per quello del tema: sono gli unici due comandi del
   pannello fatti di sola icona, cioe' gli unici in cui l'icona copre il
   100% della superficie cliccabile.
   Le voci di menu non ne hanno bisogno: hanno anche la parola, e li' un
   clic sull'icona che non risalisse lascerebbe comunque il testo. */
.amm-icon-btn > svg,
.amm-icon-btn > svg *{
  pointer-events:none;
}
/* Le lineette stanno accanto al marchio, dove l'occhio le cerca, e sono
   appena più piccole degli altri comandi: aprono e chiudono una colonna,
   non eseguono un'azione. */
.amm-menu-btn{
  width:32px; height:32px;
  margin-right:2px;
}
/* L'interruttore del tema tiene in pancia sole e luna e ne spegne una con
   l'attributo `hidden` dell'HTML (lo mette adCambiaTema). Questa riga non
   è ridondante: il foglio di base del browser dichiara `[hidden]{display:
   none}` SOLO per gli elementi HTML, e un <svg> sta in un altro namespace.
   Senza, l'attributo non ha effetto e nel pulsante si vedono sole E luna
   una sopra l'altra — verificato a schermo, non dedotto. */
.amm-icon-btn .yh-i[hidden]{ display:none; }


/* ================================= 1.8 · CORPO: BARRA + CONTENUTO =======
   #adminPanel ha `style="display:none"` nel markup e admin.js lo riaccende
   con `style.display = ''` (riga 117), cioè TOGLIENDO la dichiarazione in
   linea e lasciando decidere al foglio di stile. Per questo qui il display
   si può — e si deve — dichiarare: è il valore che il JavaScript va a
   cercare. Senza, il pannello tornerebbe un blocco e la barra laterale non
   avrebbe un'altezza da cui partire.
   (Diverso dai tre modali, che il JavaScript accende con 'flex' scritto in
   linea: quelli il display NON devono averlo nel CSS.)                    */
#adminPanel{
  display:flex;
  flex-direction:column;
  flex:1;
  min-height:0;
}

/* min-height:0 è la riga che fa scorrere il contenuto invece di allungare
   la pagina: senza, un figlio flex non scende sotto la sua altezza
   naturale e l'overflow di .amm-main non si attiva mai. */
.amm-body{
  flex:1;
  display:flex;
  min-height:0;
}

/* La barra resta di VETRO, al contrario della testata: sta nel flusso,
   divide lo spazio col contenuto e ha dietro il fondo atmosferico, non
   del testo. Quando invece esce sopra il contenuto (≤900px, 1.14) diventa
   opaca — stesso motivo della testata. */
.amm-rail{
  width:var(--amm-rail-w);
  flex:0 0 auto;
  min-height:0;
  display:flex;
  flex-direction:column;
  background:var(--glass-1);
  backdrop-filter:blur(var(--blur)) saturate(1.6);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.6);
  border-right:1px solid var(--glass-edge);
  transition:width .26s var(--ease), opacity .2s var(--ease);
}
/* Se il browser non sa sfocare, la lastra diventa opaca invece di restare
   un velo grigio: il vetro è un miglioramento, non un requisito per
   leggere un menu. hub-theme.css non ha questo ripiego perché in
   produzione la barra ha un fondo pieno sotto. */
@supports not (backdrop-filter:blur(1px)){
  .amm-rail{ background:color-mix(in srgb, var(--ground) 86%, var(--ink) 6%); }
}


/* ========================================= 1.9 · IL MENU VERTICALE ======
   Il cambio strutturale più grosso del rifacimento. .admin-tabs era una
   fila di sette pastiglie in cima alla pagina con `overflow-x:auto`: a
   1024px le ultime due finivano fuori e si scoprivano scorrendo di lato,
   cioè non si scoprivano. Diventa il <nav> della barra laterale, con le
   sette voci in colonna e raggruppate in tre.
   Le classi restano .admin-tabs e .admin-tab perché admin.js cerca la
   linguetta attiva con querySelector("[onclick=\"switchTab('accounts')\"]")
   e spegne le altre con .admin-tab: rinominarle vorrebbe dire riscrivere
   il JavaScript.                                                          */
.admin-tabs{
  display:block;
  flex:1;
  min-height:0;
  overflow-y:auto;
  padding:14px 12px 24px;
}
.amm-nav-group + .amm-nav-group{ margin-top:16px; }
.amm-nav-label{
  font-size:9.5px;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.14em;
  color:var(--ink-3);
  padding:0 10px 7px;
}

/* La voce. width:100% e text-align:left non sono nel prototipo (là è una
   <a>): qui è un <button>, che di suo si stringe sul testo e lo centra. */
.admin-tab{
  width:100%;
  display:flex;
  align-items:center;
  gap:11px;
  height:36px;
  padding:0 10px;
  border-radius:10px;
  text-align:left;
  color:var(--ink-2);
  font-size:13.5px;
  font-weight:500;
  letter-spacing:-.005em;
  white-space:nowrap;
  position:relative;
  border:1px solid transparent;
  transition:background var(--speed) var(--ease),
             color var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
/* Il bordo trasparente qui sopra ha uno scopo preciso: lo stato attivo ne
   accende uno vero, e senza il segnaposto la voce si sposterebbe di un
   pixel al momento del clic. */
.admin-tab .yh-i{ color:var(--ink-3); }
.admin-tab:hover{
  background:var(--glass-2);
  color:var(--ink);
}
.admin-tab:hover .yh-i{ color:var(--ink-2); }

/* La voce attiva deve leggersi dall'altra parte della stanza, perché è
   l'unica cosa che dice in che schermata sei insieme alle briciole. Tre
   segnali che non dipendono l'uno dall'altro: lastra più chiara, icona
   gialla, barretta gialla a filo del bordo della barra.
   L'ombra non è nel prototipo: in tema chiaro --glass-3 è bianco pieno
   sopra una barra che è bianco all'80%, e la sola differenza di fondo
   quasi non si vede. L'ombra dà il rilievo che il colore lì non può dare. */
.admin-tab.active{
  background:var(--glass-3);
  color:var(--ink);
  font-weight:600;
  border-color:var(--glass-edge);
  box-shadow:var(--shadow-1), inset 0 1px 0 var(--glass-spec);
}
.admin-tab.active .yh-i{ color:var(--accent-text); }
/* left:-13px = i 12px di padding del <nav> più il bordo della voce: la
   barretta finisce a filo del bordo esterno della barra laterale e sporge
   appena, come una linguetta di archivio. */
.admin-tab.active::before{
  content:'';
  position:absolute;
  left:-13px;
  top:50%;
  transform:translateY(-50%);
  width:3px;
  height:18px;
  border-radius:0 3px 3px 0;
  background:var(--accent);
  box-shadow:0 0 12px var(--accent-glow);
}


/* ================================ 1.10 · PIEDE DELLA BARRA E USCITA =====
   .logout-btn era un pulsante rosso a tutta larghezza in fondo alla
   pagina: il comando più vistoso del pannello era quello che se ne va.
   Diventa un comando discreto nel piede della barra — rosso solo quando ci
   passi sopra, cioè quando stai per premerlo.                             */
.amm-rail-foot{
  flex:0 0 auto;
  border-top:1px solid var(--glass-edge);
  padding:11px 12px;
}
.logout-btn{
  width:100%;
  display:flex;
  align-items:center;
  gap:10px;
  height:34px;
  padding:0 10px;
  border-radius:10px;
  color:var(--ink-3);
  font-size:13px;
  font-weight:500;
  border:1px solid transparent;
  transition:background var(--speed) var(--ease),
             color var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.logout-btn .yh-i{ width:17px; height:17px; }
.logout-btn:hover{
  color:var(--lost);
  background:var(--lost-soft);
  /* Il bordo è il --lost diluito e non --lost-soft: quello è già il fondo,
     e un bordo dello stesso colore del fondo non è un bordo. */
  border-color:color-mix(in srgb, var(--lost) 34%, transparent);
}


/* ========================================= 1.11 · CONTENUTO E SCHERMATE =
   overflow:auto e non solo overflow-y: le matrici dei permessi sono più
   larghe di qualunque finestra, e se lo scorrimento orizzontale non lo
   prende quest'area lo prende la pagina intera — cioè scivola anche la
   testata, che deve stare ferma. Chi ha una tabella larga la fa scorrere
   nel suo contenitore (è il .matrix-scroll-wrap di 03-contenuti.css);
   questa riga è la rete sotto.
   scrollbar-gutter:stable tiene ferma la colonna quando si passa da una
   schermata che scorre a una che non scorre: senza, il contenuto salta di
   undici pixel a ogni cambio di linguetta.                                */
.amm-main{
  flex:1;
  min-width:0;
  overflow:auto;
  scrollbar-gutter:stable;
  scroll-behavior:smooth;
}

/* Una schermata per volta. È il meccanismo del pannello da sempre:
   switchTab() toglie .active a tutte e la rimette a una. Il display si
   dichiara qui e non si anima, perché display non si anima: la comparsa
   la fa un'animazione sulla sola opacità.                                 */
.tab-content{
  display:none;
  padding:var(--amm-gutter) var(--amm-gutter) 72px;
  /* Oltre questa misura una riga di tabella diventa un percorso per
     l'occhio invece di un dato: il contenuto si ferma, il fondo continua. */
  max-width:1560px;
}
.tab-content.active{
  display:block;
  animation:adSchermataIn .28s var(--ease) both;
}
/* Il prototipo accompagna la comparsa con un translateY di 8px. Qui è
   tolto di proposito: i tre modali (#permModal, #teamsManagerModal,
   #createTLModal) stanno DENTRO le .tab-content, e un transform su un
   antenato diventa il riquadro di riferimento di un position:fixed —
   per 280ms un modale aperto subito dopo un cambio di schermata si
   troverebbe incollato al contenuto e tagliato da .amm-main. La sola
   opacità non crea contesti di impilamento e non sposta niente. */
/* Parte da .4 e non da 0, e non e' un dettaglio estetico: un elemento a
   opacita' ZERO non ha superficie cliccabile: il browser non gli calcola
   nessun riquadro, e per tutta la durata dell'animazione la schermata e'
   gia' interattiva ma i suoi pulsanti non raccolgono i clic. Misurato col
   banco di prova, che cliccando "Aggiorna" 280ms dopo il cambio di
   schermata riceveva "Node is either not clickable or not an Element".
   Da .4 la comparsa si vede ancora, e non c'e' nessuna finestra morta. */
@keyframes adSchermataIn{
  from{ opacity:.4; }
  to  { opacity:1; }
}

/* La testata di ogni schermata. align-items:flex-end allinea i pulsanti di
   azione alla riga di base del titolo e non al suo bordo alto: con un
   titolo di 25px la differenza è di sei pixel e si vede. */
.amm-page-head{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:20px;
  flex-wrap:wrap;
  padding-bottom:16px;
  margin-bottom:18px;
  border-bottom:1px solid var(--glass-edge);
}
/* 56ch è la misura di riga oltre la quale l'occhio perde il capo della
   riga successiva. Senza questo blocco la descrizione si allargherebbe a
   tutti i 1560px del contenuto. */
.amm-lead{
  max-width:56ch;
  min-width:0;
}

/* .admin-header / .admin-title / .admin-subtitle restano nel markup ma
   cambiano posto: non sono più l'intestazione della pagina (una sola, in
   cima, che diceva "Admin Panel - YoyoHub V2" sette schermate su sette),
   sono il titolo di OGNI schermata dentro .amm-lead e il titolo della
   porta di servizio dentro .admin-login. Le regole di base valgono nei
   due posti; le differenze le fa il contesto, in 1.12.
   Il titolo era un gradiente giallo in clip sul testo: sparisce insieme al
   vecchio <style>, e non lo rifacciamo — il giallo è il marchio, e un
   titolo di schermata non è il marchio. */
.admin-title{
  font-size:25px;
  font-weight:700;
  letter-spacing:-.022em;
  line-height:1.15;
  color:var(--ink);
  margin-bottom:5px;
}
.admin-subtitle{
  font-size:14px;
  font-weight:400;
  line-height:1.45;
  color:var(--ink-2);
}
.admin-header{
  min-width:0;
}


/* ==================================== 1.12 · LA PORTA DI SERVIZIO =======
   Il modulo del codice di accesso. Era un blocco largo 400px appeso a
   4rem dall'alto sotto un'intestazione di pagina; diventa una scheda di
   vetro centrata nello spazio che resta sotto la testata.

   margin:auto in una colonna flex è ciò che la centra su ENTRAMBI gli
   assi: i margini automatici si mangiano lo spazio libero prima che
   justify-content e align-items possano dire la loro. Serve anche
   flex:0 1 auto, altrimenti la scheda si allungherebbe a riempire la
   colonna e "centrata" non vorrebbe dire niente.

   admin.js spegne questo blocco con style.display='none' (riga 116): il
   display in linea batte il foglio di stile, quindi qui non serve — e non
   si deve — dichiarare nulla per nasconderlo.                             */
.admin-login{
  flex:0 1 auto;
  margin:auto;
  width:100%;
  max-width:420px;
  padding:26px 24px;
  background:var(--glass-1);
  backdrop-filter:blur(var(--blur)) saturate(1.6);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.6);
  border:1px solid var(--glass-edge);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-2), inset 0 1px 0 var(--glass-spec);
  text-align:center;
}
/* Qui il titolo torna a essere il titolo di una scheda, non di una
   schermata: 25px in una scheda larga 420px riempirebbero due righe. */
.admin-login .admin-title{
  font-size:19px;
  letter-spacing:-.015em;
  margin-bottom:4px;
}
.admin-login .admin-subtitle{
  font-size:13px;
}
.admin-login .admin-header{
  margin-bottom:20px;
}
/* La frase "Inserisci il codice di accesso admin" è un <p> senza classe,
   figlio diretto del blocco: il selettore è > p per non pescare anche
   .admin-subtitle, che un <p> lo è pure ma sta dentro .admin-header. */
.admin-login > p{
  font-size:13.5px;
  color:var(--ink-2);
  margin-bottom:18px;
}
/* Il modulo è una griglia a una colonna per un motivo pratico: così il
   pulsante di invio si allarga da sé come faceva con il suo
   style="width:100%", e questo foglio non deve nominare .btn-primary, che
   è di 02-controlli.css. Il gap sostituisce i margini in linea che il
   markup nuovo non ha più. */
.admin-login form{
  display:grid;
  gap:12px;
}
.admin-login input{
  width:100%;
  height:46px;
  padding:0 14px;
  border-radius:var(--r-md);
  background:var(--glass-2);
  border:1px solid var(--glass-edge);
  color:var(--ink);
  font-size:15px;
  /* Il testo centrato resta: è un codice, non un nome — si scrive al
     centro e si controlla al centro. */
  text-align:center;
  letter-spacing:.08em;
  transition:border-color var(--speed) var(--ease),
             background var(--speed) var(--ease);
}
.admin-login input::placeholder{
  color:var(--ink-3);
  letter-spacing:normal;
}
.admin-login input:focus{
  outline:none;
  border-color:var(--accent);
  background:var(--glass-3);
}


/* ============================ 1.13 · LINEETTE · SCHERMO LARGO ===========
   Primo dei DUE comportamenti delle tre lineette, e quello che si sbaglia:
   sopra i 900px la barra non esce sopra il contenuto, si COMPRIME, e il
   contenuto si allarga nello spazio che lascia. La classe la mette
   adApriChiudiRail() su .admin-container (non sulla barra: la barra non è
   l'unica cosa che si muove — si muove anche il lockup della testata, che
   deve smettere di essere largo quanto una colonna che non c'è più).

   È confinato in min-width:901px perché sotto quella soglia la stessa
   classe deve poter restare addosso al contenitore senza fare nulla: chi
   chiude la barra su un monitor e poi restringe la finestra non deve
   ritrovarsi un menu inaccessibile.

   visibility:hidden sulla barra compressa è deliberato e ha la stessa
   motivazione di theme/11-fase2.css: a larghezza zero il contenuto è già
   invisibile, ma resterebbe nel giro del tasto TAB — sette bersagli che
   non si vedono. Il ritardo di .26s sulla visibility la fa sparire a
   compressione finita, non prima.                                          */
@media (min-width:901px){
  .admin-container.amm-rail-off .amm-rail{
    width:0;
    opacity:0;
    overflow:hidden;
    /* Il colore trasparente da solo non basta: con box-sizing:border-box un
       elemento a width:0 non scende sotto la larghezza dei suoi bordi, e
       restava un pixel che spostava il contenuto. Si azzera anche quello. */
    border-right-color:transparent;
    border-right-width:0;
    visibility:hidden;
    transition:width .26s var(--ease),
               opacity .2s var(--ease),
               visibility 0s .26s;
  }
  /* Il lockup smette di essere una colonna e diventa un blocco: senza
     questo resterebbe un filetto verticale in mezzo alla testata che non
     divide più niente. */
  .admin-container.amm-rail-off .amm-brand{
    width:auto;
    border-right:none;
    padding-right:18px;
  }
}


/* ========================== 1.14 · LINEETTE · SCHERMO STRETTO ===========
   Secondo comportamento. Sotto i 900px "restringere" non basta: 272px su
   una finestra da 700 sono più di un terzo dello spazio, e comprimerli
   lascia comunque una pagina inusabile. La barra ESCE SOPRA il contenuto,
   e la classe che la muove è `open` su .amm-rail — un elemento diverso e
   una classe diversa da quelle di 1.13, di proposito: sono due meccanismi,
   non due gradi dello stesso.

   Lo spostamento è su `left` e non su transform: un transform sulla barra
   ne farebbe il riquadro di riferimento di ogni position:fixed che sta
   dentro, e ne farebbe un contesto di impilamento nuovo — il velo qui
   sotto non riuscirebbe più a passarci sotto.                             */
@media (max-width:900px){
  /* Le briciole via, sotto i 900px. Non e' un capriccio: a schermo stretto
     la testata deve tenere marchio, tre lineette, "Torna a YoyoHub" e il
     tema, e le briciole finiscono stipate contro l'etichetta del marchio —
     che a quel punto dice "Amministrazione" due volte di fila. L'informazione
     non si perde: la voce accesa nel menu dice dove sei, e il titolo grande
     della schermata lo ripete. E' la stessa scelta che l'applicazione fa per
     le sue briciole (theme/12-fase3.css: accese solo da 1025px in su). */
  .amm-crumbs{ display:none; }

  .admin-container{
    --amm-gutter:16px;
  }
  /* Il lockup non è più la testa di una colonna: si stringe sul suo
     contenuto e lascia il resto della testata alle briciole. */
  .amm-brand{
    width:auto;
    flex:0 1 auto;
    overflow:hidden;
    border-right:none;
  }
  .amm-rail{
    position:fixed;
    top:var(--amm-hdr-h);
    bottom:0;
    left:-100%;
    width:var(--amm-rail-over);
    z-index:60;
    /* Opaca, non di vetro: qui la barra ha dietro il testo del contenuto,
       non il fondo atmosferico. È la stessa ragione della testata (1.4) e
       la stessa lezione della fase 8. */
    background:var(--surface-menu);
    /* La sfocatura va SPENTA, e non è solo perché su una lastra opaca non
       serve. Un backdrop-filter diverso da none rende l'elemento il
       riquadro di riferimento di ogni position:fixed che ha dentro: con la
       sfocatura accesa il velo qui sotto veniva misurato dentro la barra
       invece che sulla finestra e usciva larga zero — invisibile, e il
       difetto non si vedeva leggendo il CSS. Trovato a schermo. */
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
    border-right:1px solid var(--glass-edge);
    box-shadow:var(--shadow-3);
    transition:left .26s var(--ease);
  }
  .amm-rail.open{
    left:0;
  }
  /* Il velo dietro la barra aperta. È uno pseudo-elemento della barra
     stessa, e non un elemento a parte, perché il markup non ne prevede
     uno: la barra ha z-index 60 e il velo, essendo dentro, viene dipinto
     sopra il contenuto (che ne ha zero) e sotto la lastra della barra.
     Parte da sotto la testata e da dopo la barra: la testata deve restare
     leggibile e cliccabile, perché è lì che sta il comando per richiudere.
     Il colore è il fondo della pagina diluito: funziona in entrambi i temi
     perché in entrambi il fondo è la cosa più lontana dal contenuto. */
  .amm-rail.open::after{
    content:'';
    position:fixed;
    top:var(--amm-hdr-h);
    right:0;
    bottom:0;
    left:var(--amm-rail-over);
    /* Il velo scurisce con un filtro e non con un colore, e il motivo è
       che un colore qui non può funzionare in entrambi i temi: l'unico
       fondo scuro a disposizione è --ground, che in tema scuro È già il
       colore della pagina — coprire il nero col nero non vela niente.
       brightness() invece agisce su quello che c'è dietro, qualunque sia:
       toglie il 42% di luce in chiaro come in scuro. La velatura di
       --ground resta come ripiego per chi non sa filtrare lo sfondo, e
       come tinta di profondità per chi sa. */
    background:color-mix(in srgb, var(--ground) 45%, transparent);
    backdrop-filter:blur(6px) brightness(.58);
    -webkit-backdrop-filter:blur(6px) brightness(.58);
  }
  /* Sotto i 900px la barra si apre e si chiude con `open`: la classe
     `amm-rail-off` di 1.13 non è confinata per caso, ma se arriva qui
     addosso al contenitore (finestra rimpicciolita a barra chiusa) non
     deve avere alcun effetto. Il confinamento in min-width:901px lo
     garantisce da solo: questa nota è per chi legge e va a cercare la
     regola che rimette le cose a posto — non serve. */
}

/* Schermo del telefono. Non c'è nulla da impilare — il guscio è già una
   colonna — ma la testata ha quattro cose in fila su 360px di larghezza e
   deve restare intera. Si stringono le misure, non si toglie niente:
   ogni parola che l'utente legge oggi la legge anche qui.                 */
@media (max-width:640px){
  .admin-container{
    --amm-gutter:14px;
    --amm-rail-over:min(272px, 84vw);
  }
  .admin-container > .amm-hdr{
    gap:10px;
    padding-right:12px;
  }
  .amm-brand{
    gap:8px;
    padding-left:12px;
  }
  .amm-brand-tag{
    font-size:8.5px;
    letter-spacing:.06em;
  }
  .amm-crumb-up{ font-size:12px; }
  .amm-crumb-now{ font-size:13px; }
  .amm-icon-btn{ width:32px; height:32px; }
  .admin-login{
    padding:22px 18px;
    border-radius:var(--r-md);
  }
  /* La testata di schermata smette di essere una riga a due estremi:
     su 360px il titolo e i pulsanti di azione non ci stanno affiancati, e
     flex-wrap li manderebbe a capo lasciandoli allineati a destra. */
  .amm-page-head{
    align-items:flex-start;
    flex-direction:column;
    gap:14px;
  }
}

/* ---------- 02-controlli.css ---------- */
/* =========================================================================
   02 · CONTROLLI
   Tutto ciò che nel pannello si clicca o si compila, più i messaggi.

   Il pannello NON carica styles.css: qui non basta dare i colori, va dato
   l'impianto (misure, spaziature, bordi, stati di fuoco). Le 392 righe di
   CSS che stavano dentro la pagina sparivano insieme al <style>: da lì in
   poi un <button> tornerebbe un pulsante grigio di sistema.

   Nessun colore è scritto alla lettera: tutto passa dai gettoni di
   hub-theme.css. È questo che fa funzionare il tema chiaro senza scrivere
   un solo blocco `body.light-mode` — sotto quella classe i gettoni si
   ribaltano da soli, e ogni regola di questo file li segue.
   ========================================================================= */


/* ================================================== 2.1 · I PULSANTI =====
   Nel pannello di oggi ogni pulsante ha padding, font e raggio suoi:
   quattro pulsanti, quattro impianti diversi. Qui l'impianto è UNO e
   cambia soltanto il colore, così la gerarchia si legge dal colore e non
   dalla dimensione (che è quello che confonde).                            */
.btn-primary,
.btn-secondary,
.btn-danger,
.btn-success{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  height:34px; padding:0 14px; box-sizing:border-box;
  border-radius:var(--r-sm);
  font-size:13px; font-weight:600; letter-spacing:-.005em; line-height:1;
  white-space:nowrap; cursor:pointer;
  /* .btn-secondary veste anche un <a> ("Torna a YoyoHub"): senza queste due
     righe quel link resterebbe sottolineato e blu di sistema. */
  text-decoration:none;
  color:var(--ink);
  background:var(--glass-2);
  border:1px solid var(--glass-edge);
  box-shadow:inset 0 1px 0 var(--glass-spec);
  transition:background var(--speed) var(--ease),
             border-color var(--speed) var(--ease),
             box-shadow var(--speed) var(--ease),
             filter var(--speed) var(--ease);
}
.btn-secondary:hover,
.btn-primary:hover,
.btn-danger:hover,
.btn-success:hover{ border-color:var(--glass-edge-hi); }
.btn-secondary:hover{ background:var(--glass-3); }

/* Il fuoco da tastiera: nel pannello di oggi non esiste per nessun
   pulsante (`outline` non è mai dichiarato e il browser lo disegna dove
   capita). `:focus-visible` e non `:focus` perché altrimenti l'anello
   comparirebbe anche al clic del mouse, dove nessuno lo chiede. */
.btn-primary:focus-visible,
.btn-secondary:focus-visible,
.btn-danger:focus-visible,
.btn-success:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
}

/* Il giallo pieno è l'unico di una schermata: se ce ne fossero due,
   nessuno dei due sarebbe il principale.
   Il testo è --on-accent, non bianco: bianco su giallo non si legge. */
.btn-primary{
  background:linear-gradient(160deg,var(--accent-2),var(--accent));
  color:var(--on-accent);
  border-color:transparent;
  font-weight:700;
  box-shadow:0 4px 16px -6px var(--accent-glow),
             inset 0 1px 0 var(--glass-spec);
}
.btn-primary:hover{
  filter:brightness(1.06);
  border-color:transparent;
  box-shadow:0 6px 22px -6px var(--accent-glow),
             inset 0 1px 0 var(--glass-spec);
}

/* Rosso e verde TENUI, con bordo, non pieni. Stanno nelle righe di una
   tabella accanto ad altri comandi: un rosso pieno per riga urlerebbe più
   del pulsante principale della schermata, e la gerarchia si invertirebbe. */
.btn-danger{
  color:var(--lost);
  background:var(--lost-soft);
  border-color:color-mix(in srgb,var(--lost) 34%,transparent);
  box-shadow:none;
}
.btn-danger:hover{
  border-color:var(--lost);
  background:color-mix(in srgb,var(--lost) 22%,transparent);
}
.btn-success{
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 34%,transparent);
  box-shadow:none;
}
.btn-success:hover{
  border-color:var(--won);
  background:color-mix(in srgb,var(--won) 22%,transparent);
}

/* I pulsanti disabilitati: il pannello ne accende e spegne diversi con
   `disabled` da JavaScript, e oggi restano identici a quelli attivi. */
.btn-primary[disabled],
.btn-secondary[disabled],
.btn-danger[disabled],
.btn-success[disabled]{
  opacity:.45; cursor:not-allowed; filter:none; box-shadow:none;
}

/* ----------------------------------- 2.2 · I pulsantini dentro le schede --
   Nelle schede dei team leader i comandi stanno in fondo, due o tre in
   fila su una scheda larga 316px: all'altezza piena non ci starebbero.
   In produzione questo si otteneva con `!important` sopra .btn-danger;
   qui basta la specificità di due classi.                                  */
.btn-primary.tl-card-btn,
.btn-secondary.tl-card-btn,
.btn-danger.tl-card-btn,
.btn-success.tl-card-btn,
.tl-card-btn{
  flex:1 1 0; min-width:0;
  height:28px; padding:0 9px;
  font-size:12px;
}

/* "+ Aggiungi team": non è un pulsante vero, è un invito a riempire un
   posto vuoto accanto alle pastiglie delle squadre. Tratteggiato perché
   quel posto è ancora da riempire, come la zona di caricamento file. */
.add-team-btn{
  display:inline-flex; align-items:center; gap:5px;
  padding:4px 10px; border-radius:var(--r-pill);
  border:1px dashed var(--glass-edge-hi);
  background:none; color:var(--ink-3);
  font-size:11.5px; font-weight:600; cursor:pointer;
  transition:border-color var(--speed) var(--ease), color var(--speed) var(--ease);
}
.add-team-btn:hover{ border-color:var(--accent-line); color:var(--accent-text); }
.add-team-btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }


/* ============================================ 2.3 · I RIQUADRI DEI MODULI =
   `.create-form` era un rettangolo scuro col bordo giallo: il bordo giallo
   diceva "sono importante" su una cosa che è solo un contenitore. Diventa
   una lastra di vetro come le altre schede, e il giallo resta al pulsante
   che conclude il modulo.
   Il contratto mi assegnava anche `.add-rule-form`, che però nel markup
   non ha mai vestito niente: esisteva solo dentro il <style> cancellato,
   accanto a .create-form. Il modulo "Nuova Regola Permesso" sta dentro
   #permModal, cioè in un `.amm-modal`. Non la scrivo per non lasciare una
   regola che il prossimo terrebbe in vita per paura di romperla.           */
.create-form{
  padding:18px 20px; margin-bottom:22px;
  border-radius:var(--r-md);
  background:var(--glass-1);
  backdrop-filter:blur(var(--blur)) saturate(1.6);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(1.6);
  border:1px solid var(--glass-edge);
  box-shadow:var(--shadow-1), inset 0 1px 0 var(--glass-spec);
}
/* Il titolo del modulo: piccolo e in maiuscoletto spaziato, come le altre
   intestazioni di gruppo dell'applicazione. Non è un titolo di pagina. */
.create-form h3{
  font-size:10.5px; font-weight:700;
  text-transform:uppercase; letter-spacing:.14em;
  color:var(--ink-3);
  padding-bottom:9px; margin:0 0 14px;
  border-bottom:1px solid var(--glass-edge);
}

.form-row{
  display:flex; gap:14px; margin-bottom:12px; flex-wrap:wrap;
  align-items:flex-end; /* i campi si allineano in basso: se un'etichetta va
                           a capo, i campi restano su una riga sola */
}
.form-row .form-group{ flex:1 1 200px; min-width:0; margin-bottom:0; }

/* Etichetta SOPRA il campo, non a fianco: regge le etichette lunghe senza
   sfalsare l'altezza della riga, ed è la forma usata in tutta l'app. */
.form-group{ display:flex; flex-direction:column; gap:6px; margin-bottom:12px; min-width:0; }
.form-group:last-child{ margin-bottom:0; }
.form-group label{
  display:block;
  font-size:11.5px; font-weight:600; letter-spacing:-.005em;
  color:var(--ink-2);
}


/* =================================================== 2.4 · I CAMPI ======
   Un solo aspetto per tutto ciò che si compila, qualunque classe abbia in
   pagina: nel pannello lo stesso `<select>` compare a volte come
   `.filter-select` e a volte dentro un `.form-group`, e oggi i due hanno
   misure diverse.                                                          */
/* `:not([type=radio]):not([type=checkbox])` non e' pignoleria: senza,
   questa regola prende anche i pallini di scelta e le caselle, che nel
   pannello stanno DENTRO un .form-group (la "Modalita' operazione" della
   schermata Template). Un radio con width:100% e height:38px il browser lo
   disegna gigante — un cerchio da 40px con l'anello giallo dell'accento — e
   l'etichetta accanto si spezza su tre righe. Visto su schermata prima di
   correggere. Radio e caselle prendono la loro misura da se': l'unica cosa
   che serve loro e' `accent-color`, piu' sotto. */
.form-group input:not([type="radio"]):not([type="checkbox"]),
.form-group select,
.form-group textarea,
.filter-select,
textarea{
  width:100%; min-width:0; box-sizing:border-box;
  height:38px; padding:0 12px;
  border-radius:var(--r-sm);
  font-size:13.5px; color:var(--ink);
  background-color:var(--glass-2);
  border:1px solid var(--glass-edge);
  box-shadow:inset 0 1px 0 var(--glass-spec);
  outline:none;
  transition:border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
/* Il `<select>` di filtro sta in una barra di comandi accanto ad altri:
   a larghezza piena mangerebbe la riga. Gli altri, dentro un modulo,
   restano al 100% della loro colonna. */
select.filter-select,
input.filter-select:not([type="file"]):not([type="text"]):not([type="email"]){
  width:auto; max-width:100%;
}

/* Un'area di testo non ha altezza fissa, ed è l'unico campo in cui il
   testo parte dall'alto: senza queste righe eredita `height:38px` e mostra
   una riga sola. */
textarea,
.form-group textarea,
textarea.filter-select{
  height:auto; min-height:64px; padding:10px 12px;
  line-height:1.5; resize:vertical;
}

/* La freccia del `<select>`: due gradienti che disegnano un triangolino.
   ⚠️ Sono dichiarati con `background-image` + posizione/misura/ripetizione
   SEPARATE, e mai con la forma abbreviata `background:`: la forma
   abbreviata riazzera position, size e repeat, ed è esattamente il difetto
   che in produzione ha già fatto sparire un'icona in tema chiaro. Scritte
   così, le tre proprietà sopravvivono a qualunque cambio di colore. */
.form-group select,
select.filter-select{
  appearance:none; -webkit-appearance:none;
  padding-right:30px; cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),
                   linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
  background-position:calc(100% - 16px) 17px, calc(100% - 12px) 17px;
  background-size:4px 4px, 4px 4px;
  background-repeat:no-repeat, no-repeat;
}
/* Il menù a tendina nativo di un `<select>` non eredita il vetro: il
   sistema operativo lo disegna da sé. `--surface-menu` è il gettone della
   superficie OPACA (nero in tema scuro, bianco in chiaro), e serve proprio
   qui: senza, su alcuni sistemi esce bianco su bianco. */
.form-group select option,
select.filter-select option{
  background:var(--surface-menu);
  color:var(--ink);
}

/* Lo stesso :not() torna sulle tre regole di stato: passaggio del mouse,
   fuoco e testo del segnaposto. Un pallino di scelta non ha un segnaposto,
   e un bordo o un alone su di lui non li disegna il foglio di stile ma il
   sistema operativo — l'anello di fuoco glielo da' gia' il tema, sulla
   regola `input:focus-visible`. */
.form-group input:not([type="radio"]):not([type="checkbox"])::placeholder,
.form-group textarea::placeholder,
.filter-select::placeholder,
textarea::placeholder{ color:var(--ink-3); }

.form-group input:not([type="radio"]):not([type="checkbox"]):hover,
.form-group select:hover,
.form-group textarea:hover,
.filter-select:hover,
textarea:hover{ border-color:var(--glass-edge-hi); }

/* Sui campi di testo si usa `:focus` e non `:focus-visible`: l'anello di
   fuoco di un campo serve anche quando ci si è cliccati dentro, perché
   dice dove finirà quello che si scrive. */
.form-group input:not([type="radio"]):not([type="checkbox"]):focus,
.form-group select:focus,
.form-group textarea:focus,
.filter-select:focus,
textarea:focus{
  border-color:var(--accent-line);
  box-shadow:0 0 0 3px var(--accent-soft), inset 0 1px 0 var(--glass-spec);
}

/* Il campo file "nudo", per i punti dove non sta dentro una .amm-drop.
   Il pulsante interno è l'unico pezzo di un <input type=file> che si può
   vestire: senza, resta il pulsante grigio di sistema in mezzo al vetro. */
input[type="file"]{
  width:100%; box-sizing:border-box;
  height:auto; padding:8px 10px;
  border-radius:var(--r-sm);
  font-size:12.5px; color:var(--ink-2);
  background-color:var(--glass-2);
  border:1px dashed var(--glass-edge-hi);
  cursor:pointer;
}
input[type="file"]::file-selector-button{
  margin-right:11px; padding:0 12px; height:28px;
  border:1px solid var(--glass-edge); border-radius:var(--r-sm);
  background:var(--glass-2); color:var(--ink);
  font-size:12px; font-weight:600; cursor:pointer;
}
input[type="file"]::file-selector-button:hover{
  border-color:var(--accent-line); color:var(--accent-text);
}
input[type="file"]:focus-visible{
  border-color:var(--accent-line);
  box-shadow:0 0 0 3px var(--accent-soft);
}

/* ---------------------------------- 2.5 · Pallini e caselle di sistema ----
   UNA riga, e vale una schermata: senza `accent-color` i radio e le
   caselle restano BLU, l'unico blu di sistema in una tavolozza dove
   l'accento è giallo. Non è una rifinitura: è la cosa che si nota per
   prima nella scelta "sostituzione totale / parziale" e nell'elenco dei
   ruoli di ogni team leader.                                               */
input[type="radio"],
input[type="checkbox"]{
  accent-color:var(--accent);
  cursor:pointer;
}
input[type="radio"]:focus-visible,
input[type="checkbox"]:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
}

/* La casella con la sua etichetta accanto (`<label class="amm-check">`):
   nel pannello serve per scegliere le squadre di un team leader, e il
   JavaScript ne stampa una per squadra.
   Sta in una pastiglia e non nuda in mezzo al testo per un motivo
   pratico: nude, dieci caselle in fila diventano un elenco dove non si
   capisce quale etichetta appartenga a quale quadratino. La pastiglia
   rende cliccabile tutta la parola, non solo i 15px del quadratino.       */
.amm-check{
  display:inline-flex; align-items:center; gap:7px;
  padding:5px 11px; border-radius:var(--r-pill);
  background:var(--glass-1); border:1px solid var(--glass-edge);
  font-size:12px; color:var(--ink-2);
  cursor:pointer; user-select:none; white-space:nowrap;
  transition:border-color var(--speed) var(--ease), color var(--speed) var(--ease);
}
.amm-check:hover{ border-color:var(--accent-line); color:var(--ink); }
/* L'anello va sulla pastiglia, non sul quadratino: è la pastiglia intera
   che il TAB seleziona a occhio. */
.amm-check:focus-within{
  border-color:var(--accent-line);
  box-shadow:0 0 0 3px var(--accent-soft);
}
.amm-check input[type="checkbox"],
.amm-check input[type="radio"]{ margin:0; flex:0 0 auto; }
.amm-check input:focus-visible{ outline:none; } /* l'anello ce l'ha la pastiglia */


/* ======================================= 2.6 · GLI INTERRUTTORI ==========
   Il pannello ha DUE markup diversi per la stessa cosa, e li avrà ancora
   dopo il rifacimento perché sono generati da funzioni JavaScript diverse:

     a) `<label class="perm-toggle"><input type=checkbox><span class=pt-slider>`
        e `<label class="toggle-switch"><input type=checkbox><span class=toggle-slider>`
     b) `<span class="amm-sw on|off|dflt">`  — nessun <input> dentro

   Sono DUE, non tre: l'interruttore di NewEden aveva una classe propria e
   una misura propria, e il rifacimento del markup l'ha riportato sul primo
   gruppo (`toggle-switch` + `toggle-slider`). Non ha più righe sue, e non
   c'è un terzo interruttore da nessuna parte. Lo <span id="newedenToggleKnob">
   che gli resta dentro è vuoto e non si vede: il pallino lo disegna il
   `::before` dello slider come per tutti gli altri, e la sua corsa la
   comanda `input:checked`.

   La forma sta in UNA regola sola, condivisa. Se la scrivessi due volte,
   il giorno che qualcuno cambia una misura la stessa cosa avrebbe due
   facce nella stessa pagina — ed è precisamente ciò che il pannello aveva
   prima: 36×20 nella matrice, 40×22 altrove, 54×28 in NewEden, tre misure
   per un unico oggetto.                                                    */

/* Il contenitore: solo geometria e posizione, nessun colore. */
.perm-toggle,
.toggle-switch{
  position:relative; display:inline-block;
  width:38px; height:21px;
  vertical-align:middle; cursor:pointer; flex:0 0 auto;
}

/* La casella vera si nasconde ma NON si spegne: `display:none` (che è ciò
   che il pannello usa oggi) la tira fuori dal giro del tasto TAB, e
   l'interruttore diventa raggiungibile solo col mouse. Ridotta a 1px e
   trasparente, resta focalizzabile e l'anello di fuoco lo disegniamo noi
   sul cursore, qui sotto. */
.perm-toggle input,
.toggle-switch input{
  position:absolute; top:0; left:0;
  width:1px; height:1px; margin:0; padding:0;
  opacity:0;
  clip-path:inset(50%);
}

/* --- L'aspetto, condiviso dai tre markup ---------------------------------
   Lo stato di BASE è "spento esplicito": rosso, pallino a sinistra. È lo
   stato che si vede quando nessuna classe e nessun `checked` dicono altro,
   e vale sia per la cella della matrice sia per uno `.amm-sw` nudo.          */
.perm-toggle .pt-slider,
.toggle-switch .toggle-slider,
.amm-sw{
  box-sizing:border-box;
  width:38px; height:21px;
  border-radius:var(--r-pill);
  border:1px solid var(--lost);
  background:var(--lost-soft);
  transition:background var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.perm-toggle .pt-slider,
.toggle-switch .toggle-slider{ position:absolute; inset:0; cursor:pointer; }
.amm-sw{
  position:relative; display:inline-block;
  vertical-align:middle; cursor:pointer; flex:0 0 auto;
}

/* Il cursore. Il pallino prende il colore dello stato invece di essere
   sempre bianco: da lontano si legge la riga, non il singolo interruttore. */
.perm-toggle .pt-slider::before,
.toggle-switch .toggle-slider::before,
.amm-sw::before{
  content:''; position:absolute; top:2px; left:2px;
  width:15px; height:15px; border-radius:50%;
  background:var(--lost);
  transition:transform var(--speed) var(--ease),
             background var(--speed) var(--ease),
             opacity var(--speed) var(--ease);
}

/* --- Primo stato: ACCESO ESPLICITO — verde, pallino a destra ------------- */
.perm-toggle input:checked + .pt-slider,
.toggle-switch input:checked + .toggle-slider,
.amm-sw.on{
  background:var(--won-soft);
  border-color:var(--won);
}
.perm-toggle input:checked + .pt-slider::before,
.toggle-switch input:checked + .toggle-slider::before,
.amm-sw.on::before{
  transform:translateX(17px);
  background:var(--won);
}

/* --- Secondo stato: SPENTO ESPLICITO — rosso, pallino a sinistra ---------
   Coincide con lo stato di base; lo riscrivo solo per `.amm-sw.off`, perché
   quella classe può arrivare su un elemento che prima aveva `.on`. */
.amm-sw.off{ background:var(--lost-soft); border-color:var(--lost); }
.amm-sw.off::before{ transform:none; background:var(--lost); }

/* --- Terzo stato: NESSUNA REGOLA SCRITTA --------------------------------
   È il motivo per cui questa schermata esiste. Vale "acceso", ma nessuno
   l'ha deciso: è un permesso che il consulente ha perché nessuno gliel'ha
   mai negato, non perché qualcuno gliel'ha dato.

   Nel pannello di oggi era grigio con il pallino verde spostato a destra:
   a occhio, indistinguibile da "acceso esplicito". Chi guardava la matrice
   non poteva sapere quali celle erano state decise e quali no — e quella
   distinzione è tutta l'informazione della schermata.

   Qui diventa: bordo TRATTEGGIATO (il tratteggio è il segno del "non
   ancora deciso", lo stesso di .add-team-btn e .amm-drop), fondo
   TRASPARENTE (non c'è nessun colore di stato da mostrare, perché non c'è
   nessuno stato) e pallino A METÀ STRADA e attenuato (non a destra, che
   direbbe "acceso"; non a sinistra, che direbbe "spento").

   ⚠️ Trappola di specificità, non toglierla: la cella "nessuna regola"
   contiene un <input> con `checked` (renderPermissions parte dal
   presupposto che senza regola il servizio è abilitato). Il selettore
   `.perm-toggle input:checked + .pt-slider` pesa (0,3,1) e batterebbe
   `.perm-toggle.no-rule .pt-slider`, che pesa (0,3,0): il verde vincerebbe
   e il terzo stato non si vedrebbe mai. Per questo la variante `:checked`
   è elencata a parte, con la sua (0,4,1).                                  */
.perm-toggle.no-rule .pt-slider,
.perm-toggle.no-rule input:checked + .pt-slider,
.amm-sw.dflt{
  background:transparent;
  border-style:dashed;
  border-color:var(--glass-edge-hi);
}
.perm-toggle.no-rule .pt-slider::before,
.perm-toggle.no-rule input:checked + .pt-slider::before,
.amm-sw.dflt::before{
  transform:translateX(8.5px);
  background:var(--ink-3);
  opacity:.45;
}

/* Passaggio del mouse: schiarisco, non ricoloro. Se cambiassi il colore
   di fondo perderei l'informazione dello stato proprio nell'istante in cui
   la persona ci sta puntando sopra. */
.perm-toggle:hover .pt-slider,
.toggle-switch:hover .toggle-slider,
.amm-sw:hover{ filter:brightness(1.18); }

/* Fuoco da tastiera. Oggi non ce l'ha nessuno dei tre: l'anello va sul
   cursore visibile, perché la casella che riceve il fuoco è larga 1px e
   un anello lì sarebbe un puntino nell'angolo.
   `.amm-sw` non ha un <input> dentro: riceve il fuoco solo se il markup gli
   dà `tabindex`. La regola è pronta comunque — così il giorno che lo
   riceve funziona, invece di essere un difetto da scoprire. */
.perm-toggle input:focus-visible + .pt-slider,
.toggle-switch input:focus-visible + .toggle-slider,
.amm-sw:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
}
.amm-sw:focus{ outline:none; } /* niente anello al clic: lo dà :focus-visible */

/* ------------------------------------------------- 2.7 · La legenda ------
   I tre stati vanno spiegati una volta sopra la matrice. Il quadratino
   della legenda usa gli stessi tre segni delle celle — pieno verde, pieno
   rosso, tratteggiato vuoto — altrimenti la legenda spiega un'altra cosa. */
.amm-legenda{
  display:flex; gap:18px; flex-wrap:wrap; align-items:center;
  margin:12px 0;
}
.amm-legenda span{
  display:inline-flex; align-items:center; gap:7px;
  font-size:12px; color:var(--ink-3);
}
.amm-legenda i{
  width:9px; height:9px; border-radius:50%;
  flex:0 0 auto; font-style:normal;
}
.amm-legenda i.ok{ background:var(--won); }
.amm-legenda i.ko{ background:var(--lost); }
.amm-legenda i.dflt{ background:transparent; border:1px dashed var(--glass-edge-hi); }


/* ================================== 2.8 · ETICHETTE, NOTE, RICERCA ======
   L'etichetta piccola che mancava: il nome di una squadra, un conteggio.
   NON è una pastiglia di stato (quelle hanno il pallino davanti e un
   colore che significa qualcosa) e non è un numero grosso. È la cosa
   piccola e neutra in mezzo, e nel pannello serve in dieci punti.          */
.amm-tag{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px; border-radius:var(--r-pill);
  background:var(--glass-2); border:1px solid var(--glass-edge);
  font-size:11.5px; font-weight:500; color:var(--ink-2);
  white-space:nowrap;
}
/* Variante per i conteggi: cifre incolonnate, così una fila di etichette
   con numeri non "balla" quando i numeri cambiano. */
.amm-tag--n{ font-variant-numeric:tabular-nums; color:var(--ink-3); }

/* La nota: un avviso che spiega una regola del pannello (per esempio che
   una casella spenta non cancella niente). Fondo accento tenue e non
   rosso o arancio: informa, non allarma. */
.amm-nota{
  display:flex; align-items:flex-start; gap:10px;
  padding:12px 15px; border-radius:var(--r-md);
  background:var(--accent-soft); border:1px solid var(--accent-line);
  font-size:12.5px; line-height:1.5; color:var(--ink-2);
}
/* In tema chiaro il giallo pieno come TESTO non si legge: --accent-text è
   il gettone che si scurisce da sé sotto body.light-mode. È il motivo per
   cui esiste, e per cui qui non serve un blocco per il tema chiaro. */
.amm-nota .yh-i{
  flex:0 0 auto; margin-top:1px;
  width:16px; height:16px;
  color:var(--accent-text);
}

/* --- Il campo di ricerca ------------------------------------------------
   La lente sta DENTRO il campo: icona in posizione assoluta e il campo che
   le fa spazio a sinistra.

   La lente è un <svg> vero (`<svg class="yh-i"><use href="#yh-ic-search">`),
   non un'immagine di sfondo. Due motivi: prende il colore del testo e
   quindi segue il tema da sola, e soprattutto non entra in conflitto con
   il `background-image` della freccia del <select> né con la forma
   abbreviata `background:` — il difetto che in produzione ha già fatto
   sparire un'icona quando si è passati al tema chiaro.

   E la lente non è sovrapposta al campo in posizione assoluta: è la
   LASTRA che si sposta dal campo al contenitore, e dentro ci stanno lente
   e campo in fila. Costa tre righe in più e ne risparmia tre difetti: non
   serve `position:absolute`, non serve un `padding-left` che qualcuno
   domani può riazzerare con una forma abbreviata, e non serve spegnere i
   clic sull'icona per non farle rubare il fuoco al campo. Il fuoco lo
   disegna il contenitore con `:focus-within`, quindi l'anello circonda
   tutto il campo, lente compresa.                                          */
.amm-cerca{
  display:flex; align-items:center; gap:8px;
  box-sizing:border-box;
  flex:1 1 220px; min-width:200px; max-width:380px;
  height:38px; padding:0 12px;
  border-radius:var(--r-sm);
  background-color:var(--glass-2);
  border:1px solid var(--glass-edge);
  box-shadow:inset 0 1px 0 var(--glass-spec);
  transition:border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
.amm-cerca:hover{ border-color:var(--glass-edge-hi); }
.amm-cerca:focus-within{
  border-color:var(--accent-line);
  box-shadow:0 0 0 3px var(--accent-soft), inset 0 1px 0 var(--glass-spec);
}
.amm-cerca .yh-i{
  flex:0 0 auto;
  width:16px; height:16px;
  color:var(--ink-3);
}
/* Il campo dentro perde la propria lastra: se la tenesse, si vedrebbero
   due bordi uno dentro l'altro. (0,1,1) batte `.filter-select`, che questi
   campi hanno addosso nel markup di oggi. */
.amm-cerca input{
  flex:1 1 auto; min-width:0;
  height:auto; padding:0;
  background:none; border:0; box-shadow:none; outline:none;
}
.amm-cerca input:focus,
.amm-cerca input:hover{ border:0; box-shadow:none; }

/* --- La zona di caricamento file ---------------------------------------
   Un `<input type=file>` non si può vestire: si nasconde e si veste la
   `<label>` che lo contiene.
   Nascosto con la tecnica del ritaglio e NON con `display:none`, che lo
   toglierebbe dal giro del tasto TAB: la label resterebbe cliccabile col
   mouse e irraggiungibile da tastiera.
   Il tratteggio dice "qui manca qualcosa, mettilo tu". */
.amm-drop{
  position:relative;
  display:flex; flex-direction:column; align-items:center; gap:7px;
  padding:22px 18px; text-align:center; cursor:pointer;
  border:1px dashed var(--glass-edge-hi); border-radius:var(--r-md);
  background:var(--glass-1);
  transition:border-color var(--speed) var(--ease),
             background var(--speed) var(--ease),
             box-shadow var(--speed) var(--ease);
}
.amm-drop input[type="file"]{
  position:absolute; top:0; left:0;
  width:1px; height:1px; padding:0; margin:0; border:0;
  opacity:0;
  clip-path:inset(50%);
}
.amm-drop:hover{ border-color:var(--accent-line); background:var(--accent-soft); }
/* Il fuoco si vede SULLA LABEL, non sulla casella nascosta: `:focus-within`
   è l'unico modo di portarlo dove la persona lo sta guardando. */
.amm-drop:focus-within{
  border-color:var(--accent-line);
  background:var(--accent-soft);
  box-shadow:0 0 0 3px var(--accent-soft);
}
.amm-drop .yh-i{ width:22px; height:22px; color:var(--ink-3); }
.amm-drop b{ font-size:13px; font-weight:600; color:var(--ink); }
.amm-drop span{ font-size:11.5px; line-height:1.45; color:var(--ink-3); }


/* ==================================================== 2.9 · I MESSAGGI ===
   `display` qui è comportamento, non decorazione: il modulo di accesso
   accende l'errore aggiungendo `.show`, ed è la pagina a deciderlo. Se
   togliessi il `display:none` l'errore sarebbe visibile a pagina aperta,
   prima che qualcuno abbia sbagliato qualcosa.                             */
.error-message{
  display:none;
  color:var(--lost);
  font-size:12.5px; line-height:1.45;
}
.error-message.show{ display:block; }

/* Il messaggio che compare in basso a destra.
   Superficie OPACA (--surface-menu) e non vetro: galleggia sopra il
   contenuto e sopra il velo dei modali, e all'8% di bianco si leggerebbe
   attraverso quello che c'è dietro.
   z-index 9999 — lo stesso di prima, e resta il numero più alto del
   pannello: il velo dei modali sta a 400. Un messaggio che compare DIETRO
   un velo scuro non si legge, e nel pannello i messaggi arrivano proprio
   quando un modale è aperto (salvataggi, errori di rete). */
.toast{
  position:fixed; bottom:24px; right:24px; z-index:9999;
  max-width:min(420px,calc(100vw - 48px));
  padding:13px 18px;
  border-radius:var(--r-md);
  font-size:13px; font-weight:500; line-height:1.45;
  color:var(--ink);
  background:var(--surface-menu);
  border:1px solid var(--glass-edge-hi);
  box-shadow:var(--shadow-2);
  /* Spento, scivola INTERAMENTE fuori dalla finestra (100% della propria
     altezza più i 24px di distacco dal fondo), non solo di 20px come
     nell'animazione di comparsa. Non è un vezzo: a opacità zero ma dentro
     la finestra resterebbe un rettangolo invisibile di 420×50px appoggiato
     sull'angolo in basso a destra, e si mangerebbe i clic di quello che
     c'è sotto. Fuori dalla finestra non intercetta niente, e non serve
     spegnergli i clic. */
  transform:translateY(calc(100% + 24px)); opacity:0;
  transition:transform var(--speed) var(--ease), opacity var(--speed) var(--ease);
}
.toast.show{ transform:none; opacity:1; }
/* La riga di colore è una barra sul bordo sinistro, non il fondo intero:
   il testo resta sull'opaco (quindi leggibile in entrambi i temi) e il
   colore dice comunque com'è andata. */
.toast.success{
  border-color:color-mix(in srgb,var(--won) 45%,transparent);
  box-shadow:var(--shadow-2), inset 3px 0 0 var(--won);
}
.toast.error{
  border-color:color-mix(in srgb,var(--lost) 45%,transparent);
  box-shadow:var(--shadow-2), inset 3px 0 0 var(--lost);
}

/* La rotellina di attesa della schermata Template. Il nome dell'animazione
   resta `templ-spin`: era già così e nessun altro foglio lo usa.
   La traccia usa --track e non il vetro, perché in tema chiaro il vetro è
   quasi bianco e un cerchio "vetro su vetro" sparirebbe. */
.templ-spinner{
  width:28px; height:28px; margin:0 auto 10px;
  border:3px solid var(--track);
  border-top-color:var(--accent);
  border-radius:50%;
  animation:templ-spin .8s linear infinite;
}
@keyframes templ-spin{ to{ transform:rotate(360deg); } }


/* =================================================== 2.10 · I MODALI ====
   ⚠️ QUESTA REGOLA NON DICHIARA `display`, ED È VOLUTO.
   Il JavaScript del pannello accende e spegne i tre modali con
   `style.display='flex'` / `'none'` (e `addTeamToTL` ne crea uno al volo
   allo stesso modo). Se dichiarassi `display:flex` qui, l'attributo in
   linea vincerebbe comunque e oggi funzionerebbe — ma il giorno che
   qualcuno togliesse quel `style="display:none"` dal markup, credendo di
   fare pulizia, i tre modali resterebbero accesi sopra la pagina per
   sempre. Lo stato aperto/chiuso appartiene al JavaScript; il CSS dà solo
   l'aspetto di quando è aperto.
   `align-items` e `justify-content` sono dichiarati qui: su un elemento
   non-flex non fanno niente, e appena il JavaScript mette `display:flex`
   la scheda si trova già centrata.                                         */
.amm-modal{
  position:fixed; inset:0; z-index:400;
  align-items:center; justify-content:center;
  padding:24px;
  background:color-mix(in srgb,var(--ground) 62%,transparent);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
}

/* La scheda dentro il velo. Opaca come i menu, per lo stesso motivo:
   dietro non c'è il fondo della pagina, c'è del testo. */
.amm-modal-box{
  width:min(560px,100%);
  max-height:min(86vh,100%);
  overflow:auto;
  padding:22px 24px;
  border-radius:var(--r-lg);
  background:var(--surface-menu);
  border:1px solid var(--glass-edge-hi);
  box-shadow:var(--shadow-3), inset 0 1px 0 var(--glass-spec);
}
/* Nei tre modali il contenuto sta direttamente dentro la scheda, senza un
   <div> di corpo: la spaziatura la mette la scheda. L'intestazione però
   deve arrivare fino ai bordi, perché la sua linea di chiusura separa
   l'intero riquadro — quindi esce dal padding con dei margini negativi,
   invece di chiedere all'HTML un contenitore in più. */
.amm-modal-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  margin:-22px -24px 18px;
  padding:18px 24px 14px;
  border-bottom:1px solid var(--glass-edge);
}
.amm-modal-head h3{
  margin:0;
  font-size:14.5px; font-weight:600; letter-spacing:-.01em; color:var(--ink);
}
/* La × che chiude il modale è un `.amm-icon-btn`, e quello sta in
   01-guscio.css: non lo vesto io. Unica cosa che manca e che vale la pena
   aggiungere là: dentro l'intestazione di un modale quella × butta via
   quello che si stava scrivendo, e al passaggio del mouse dovrebbe dirlo
   (rosso `--lost`) invece di restare grigia come le icone della testata. */

/* Su schermo stretto il velo non ha 24px da regalare ai lati, e una scheda
   con dentro un modulo diventa più alta della finestra. */
@media (max-width:640px){
  .amm-modal{ padding:12px; }
  .amm-modal-box{ padding:18px; max-height:calc(100vh - 24px); }
  .amm-modal-head{ margin:-18px -18px 14px; padding:16px 18px 12px; }
  .toast{ left:16px; right:16px; bottom:16px; max-width:none; }
}

/* ---------- 03-contenuti.css ---------- */
/* =========================================================================
   03 · CONTENUTI — tabelle, matrici, schede, NewEden, Template

   Il file piu' lungo dei tre: e' ordinato per SCHERMATA, non per tipo di
   regola, perche' chi lo apre di solito arriva da un difetto visto in una
   schermata precisa e cerca quella. I separatori grossi sono le schermate,
   quelli sottili i componenti dentro.

   Due cose da sapere prima di leggere:

   1. `hub-theme.css` si carica PRIMA di questo foglio e da' solo colori e
      decorazione alle classi condivise (`.table-card`, `.data-table`): il
      pannello non carica `styles.css`, quindi l'IMPIANTO (larghezze,
      `border-collapse`, padding, display) lo deve dare questo file.
   2. `body .table-card` in `hub-theme.css` ha specificita' (0,1,1) e batte
      un `.table-card` scritto qui. Dove serve cambiarla si scrive
      `body .table-card`. E' segnalato caso per caso.

   Nessun colore scritto a mano: solo i gettoni di `hub-theme.css`.
   acceso/ok --won · spento/errore --lost · attenzione --wait ·
   informazione --live · viola --hold · grigio --off · marchio --accent.
   ========================================================================= */


/* #########################################################################
   A · FONDAMENTA CONDIVISE — la scheda-tabella e la tabella dati
   Le usano cinque schermate su sette, quindi stanno in cima e una volta sola.
   ######################################################################### */

/* ------------------------------------------------- A.1 · La scheda ------
   `body .table-card` (e non `.table-card`) perche' hub-theme.css dichiara
   proprio quel selettore: con la stessa specificita' vincerebbe lui, essendo
   caricato dopo... no, prima — ma a pari specificita' vince l'ULTIMO letto,
   e per una classe (0,1,0) contro (0,1,1) vince comunque lui. Quindi qui si
   scrive (0,1,1) o piu'.
   Vetro, bordo e ombra arrivano già da hub-theme.css: qui si aggiunge solo
   cio' che manca, cioe' l'impianto (padding e scorrimento).                */
body .table-card{
  padding:18px;
  /* La tabella dentro puo' essere piu' larga della scheda (la tabella
     Account ha 6 colonne, su telefono non ci sta): scorre QUI, dentro la
     scheda, e non trascina la pagina in orizzontale. */
  overflow-x:auto;
}

/* La scheda che contiene una matrice fa da sola cornice al contenitore che
   scorre: un padding pieno le metterebbe una fascia di vetro attorno e la
   matrice sembrerebbe piu' piccola di quello che e'. Oggi lo faceva un
   `style="padding:0.6rem"` in linea. */
body .table-card:has(.matrix-scroll-wrap){
  padding:7px;
}

body .table-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  flex-wrap:wrap;
  margin-bottom:14px;
}
/* Il titolo e' un <h3>: senza `margin:0` esplicito resta il margine del
   browser e la barra dell'intestazione si sbilancia verso il basso. */
body .table-title{
  margin:0;
  font-size:15.5px;
  letter-spacing:-.012em;
}

/* --------------------------------------------- A.2 · La tabella dati ---
   hub-theme.css veste `.data-table th/td` (colori, maiuscoletto,
   intestazione ferma in alto) ma non le da' ne' larghezza ne'
   `border-collapse`: senza queste due righe la tabella si stringe sul
   contenuto e le righe non si separano.                                   */
.data-table{
  width:100%;
  border-collapse:collapse;
  font-size:13px;
}
/* Padding e allineamento: sono impianto, non colore, quindi non arrivano
   dal tema. L'aspetto dell'intestazione (minuscola + maiuscoletto) invece
   SI', ed e' voluto: e' l'aspetto delle tabelle dell'applicazione e tenerlo
   e' coerenza, non pigrizia. */
.data-table th{
  padding:10px 14px;
  text-align:left;
  white-space:nowrap;
}
.data-table td{
  padding:11px 14px;
  vertical-align:middle;
}
/* L'ultima riga non ha bisogno del filo sotto: sotto c'e' il bordo della
   scheda, e i due insieme fanno una doppia linea. */
.data-table tbody tr:last-child td{
  border-bottom:none;
}

/* ------------------------------------------- A.3 · Tabella senza righe --
   Nel prototipo (`.vuoto`) e' un'icona attenuata piu' una frase, non una
   riga di testo grigio: una tabella vuota deve dire "non c'e' niente",
   non sembrare rotta.
   NIENTE larghezze qui: `.empty-state` compare quasi sempre dentro un
   `<td colspan>`, dove una larghezza fissa combatterebbe col colspan; e in
   tre punti compare come `<div>` dentro un contenitore qualunque. Deve
   funzionare in entrambi i casi, quindi si limita a centrare e respirare. */
.empty-state{
  padding:36px 20px;
  text-align:center;
  color:var(--ink-3);
  font-size:13px;
}
/* In tre punti `.empty-state` sta su uno <span>, che essendo in linea
   ignorerebbe metà del padding. Si dichiara `display:block` SOLO sui tag
   dove e' giusto: metterlo su `.empty-state` da sola lo darebbe anche al
   <td colspan>, e un <td> reso `block` fa uscire la cella dalla tabella. */
span.empty-state,
div.empty-state{
  display:block;
}
/* Dentro una tabella serve piu' specificita' del `.data-table td` che le
   da' il padding di cella (0,1,2 contro 0,1,0): senza, la riga vuota
   resterebbe alta come una riga normale. In produzione questa era la
   ragione di un `!important`, che qui non serve piu'. */
.data-table td.empty-state{
  padding:40px 20px;
  text-align:center;
  color:var(--ink-3);
}
.empty-state .yh-i{
  width:26px;
  height:26px;
  margin-bottom:9px;
  color:var(--ink-3);
  opacity:.6;
}
.empty-state p{
  margin:0;
}

/* --------------------------------------------- A.4 · Colonna dei comandi
   I pulsanti stanno in fila e vanno a capo su schermo stretto invece di
   allargare la cella e con essa tutta la tabella.                        */
.actions-cell{
  display:flex;
  align-items:center;
  gap:7px;
  flex-wrap:wrap;
}

/* ------------------------------------------------ A.5 · Stato conto ----
   Pastiglia col pallino davanti, come tutte le pastiglie di stato
   dell'applicazione: il pallino e' cio' che rende lo stato leggibile a
   colpo d'occhio in una colonna lunga, il colore da solo no.             */
.account-status{
  display:inline-flex;
  align-items:center;
  gap:6px;
  height:22px;
  padding:0 9px;
  border-radius:var(--r-pill);
  font-size:11px;
  font-weight:600;
  white-space:nowrap;
  border:1px solid transparent;
  color:var(--off);
  background:var(--off-soft);
}
.account-status::before{
  content:'';
  width:5px;
  height:5px;
  border-radius:50%;
  background:currentColor;
  flex:0 0 auto;
}
.account-status.active{
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 28%,transparent);
}
.account-status.inactive{
  color:var(--lost);
  background:var(--lost-soft);
  border-color:color-mix(in srgb,var(--lost) 28%,transparent);
}


/* #########################################################################
   B · CLASSI DI STATO CHE EMETTE IL JAVASCRIPT
   Sono le classi con cui `admin.js` sostituisce i colori che oggi scrive a
   mano (`style.color = '#22c55e'` e simili). Stanno tutte qui, in un blocco
   solo, perche' sono un CONTRATTO fra due file: chi cambia il nome di una di
   queste in admin.js deve venire a cambiarlo anche qui, e trovarle sparse
   per il foglio renderebbe la cosa un tiro alla cieca.
   ######################################################################### */

/* -------------------------------- B.1 · Colonna "Attivita'" degli account
   Quattro distanze nel tempo che erano quattro esadecimali dentro
   `renderAccountsTable`. Qui c'e' SOLO il colore: la forma comune (`.amm-visto`)
   e il pallino (`.amm-pallino`) sono utilita' sparse per tutto il pannello e
   stanno nel foglio delle utilita', non qui. Il perche' della divisione: la
   forma la usano tre schermate, il significato di queste quattro una sola. */

/* Connesso adesso: verde pieno e in grassetto. E' l'unico dei quattro che
   descrive una cosa che sta succedendo, e l'unico che merita un colore
   forte — nella colonna e' cio' che si cerca. */
.amm-vivo{ color:var(--won); font-weight:600; }
/* Meno di un'ora: arancio d'attenzione, non giallo — il giallo e' il
   marchio e non deve voler dire anche "poco fa". */
.amm-recente{ color:var(--wait); }
/* Ore: informazione di servizio, colore terziario. */
.amm-lontano{ color:var(--ink-3); }
/* Giorni o mai: grigio dichiarato, il piu' spento dei quattro. */
.amm-mai{ color:var(--off); }

/* -------------------------------------- B.2 · Acceso / spento di NewEden
   Due elementi diversi ricevono le STESSE due classi da
   `updateNewedenToggleUI`: la parola («Attiva» / «Disattivata») e il binario
   dell'interruttore accanto. Sono due oggetti, non uno, e le due
   combinazioni si scrivono separate ed esplicite — altrimenti la pastiglia
   della parola imporrebbe al binario padding e raggio e lo deformerebbe.

   La forma del binario (misura, posizione, cursore) resta in
   02-controlli.css: qui il binario riceve solo il colore dello stato, che
   prima era uno `style.background` scritto nel JavaScript e che quindi in
   tema chiaro non sapeva cambiare.                                        */

/* a) la parola. Vale anche per `#permEnabledLabel` nel modale delle regole,
      che riceve la stessa coppia di classi dalla stessa logica. */
.amm-on:not(.toggle-slider),
.amm-off:not(.toggle-slider){
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:5px 12px;
  border-radius:var(--r-pill);
  font-size:12.5px;
  font-weight:700;
  white-space:nowrap;
  border:1px solid transparent;
}
#newedenStatusLabel.amm-on,
.amm-on:not(.toggle-slider){
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 30%,transparent);
}
#newedenStatusLabel.amm-off,
.amm-off:not(.toggle-slider){
  color:var(--lost);
  background:var(--lost-soft);
  border-color:color-mix(in srgb,var(--lost) 30%,transparent);
}

/* b) il binario. Il fondo tenue e il bordo pieno, e non il colore pieno di
      prima (#22c55e): il pomello e' bianco e su verde pieno si legge, ma su
      un binario di 21px il colore pieno grida piu' della cosa che accende. */
.toggle-slider.amm-on{
  background:var(--won-soft);
  border-color:var(--won);
}
.toggle-slider.amm-off{
  background:var(--lost-soft);
  border-color:var(--lost);
}

/* --------------------------------------------- B.3 · Identificativo doppio
   `renderTemplFieldsTable`: due campi generati con lo stesso id sono un
   difetto del PDF di partenza, e al commit uno dei due vincerebbe in
   silenzio. Rosso + un filo a sinistra, perche' il solo colore del testo in
   una tabella di cento righe non si nota.                                 */
.data-table td.amm-dupl{
  color:var(--lost);
  font-weight:600;
  box-shadow:inset 2px 0 0 var(--lost);
}

/* ------------------------------------------ B.4 · Categorie di servizio -
   `renderPermissions` teneva i colori delle categorie in un array
   JavaScript (`cat.color`, esadecimali a mano). Adesso la funzione mette
   una classe e il colore lo decide il CSS.

   La tavolozza NON e' inventata qui: e' quella che il pannello usa gia'
   nelle schede (`.perm-card-title .page` e compagnia), che e' l'unica delle
   due famiglie a comparire in tutte le schermate. Le intestazioni di
   matrice avevano una loro terna diversa (pagine blu, esterni viola,
   giochi arancio) e adesso si allineano a questa: due tavolozze per le
   stesse quattro categorie erano il difetto, non una scelta.

     pagine    viola   --hold   (era #8A2BE2)
     esterni   arancio --wait   (era #FFC107: il giallo resta al marchio)
     giochi    verde   --won    (era #22c55e)
     dashboard blu     --live   (era #3b82f6)

   Ogni classe si limita a impostare due gettoni locali, cosi' la stessa
   classe funziona sia su un <th> di matrice sia su una pastiglia.         */
   Sono TRE e non quattro: `renderPermissions` ha tre categorie
   (`page`, `external`, `game`) e la quarta, «dashboard», non e' nel suo
   array. Aggiungerla avrebbe cambiato il comportamento della funzione, non
   il suo aspetto, quindi non si e' fatto: una quarta classe scritta
   qui non dipingerebbe niente. Il blu di `--live` resta assegnato alla
   categoria dashboard nelle SCHEDE (C.6), dove la classe esiste davvero.  */
.amm-cat-pagine{  --amm-cat:var(--hold); --amm-cat-soft:var(--hold-soft); }
.amm-cat-esterni{ --amm-cat:var(--wait); --amm-cat-soft:var(--wait-soft); }
.amm-cat-giochi{  --amm-cat:var(--won);  --amm-cat-soft:var(--won-soft); }


/* #########################################################################
   C · SCHERMATA «SERVIZI & PERMESSI» e «SERVIZI & PERMESSI TL»
   LA MATRICE. E' la schermata piu' importante del pannello e oggi la piu'
   confusa: due matrici (`#permMatrix`, `#tlPermMatrix`) con la stessa
   struttura, dentro `.matrix-scroll-wrap`, dentro una `.table-card`.
   ######################################################################### */

/* --------------------------------------- C.1 · Il contenitore che scorre
   La matrice scorre nelle DUE direzioni dentro questo riquadro, e mai la
   pagina: e' l'unico modo per tenere ferme insieme l'intestazione in alto e
   la prima colonna a sinistra, perche' `position:sticky` si aggancia al piu'
   vicino antenato che scorre. Se lo scorrimento fosse della pagina,
   l'intestazione si fermerebbe rispetto alla finestra e uscirebbe dal
   riquadro.
   `max-height` in unita' di finestra e non in pixel: la matrice deve
   arrivare fin dove arriva lo schermo, che sia un portatile o un monitor. */
.matrix-scroll-wrap{
  overflow:auto;
  border-radius:var(--r-md);
  border:1px solid var(--glass-edge);
  /* Fondo appena piu' scuro del vetro della scheda: da' al riquadro un
     dentro e un fuori, cosi' si capisce che e' lui a scorrere. */
  background:var(--glass-1);
  /* Barra di scorrimento in tono col vetro invece di quella di sistema:
     la matrice ne mostra due, e due barre grigie in una lastra di vetro si
     vedono piu' del contenuto. */
  scrollbar-width:thin;
}
/* L'altezza in unita' di finestra vale per le DUE matrici vere, non per
   ogni contenitore che scorre: `selectPermConsultant` riusa
   `.matrix-scroll-wrap` per una tabella di tre righe, e un `min-height` di
   320px le lascerebbe sotto un buco di vetro alto mezzo schermo. */
.matrix-scroll-wrap:has(#permMatrix),
.matrix-scroll-wrap:has(#tlPermMatrix){
  max-height:calc(100vh - 300px);
  min-height:320px;
}
.matrix-scroll-wrap::-webkit-scrollbar{ width:10px; height:10px; }
.matrix-scroll-wrap::-webkit-scrollbar-track{ background:transparent; }
.matrix-scroll-wrap::-webkit-scrollbar-thumb{
  background:var(--glass-3);
  border-radius:var(--r-pill);
}
.matrix-scroll-wrap::-webkit-scrollbar-thumb:hover{ background:var(--glass-edge-hi); }

/* ------------------------------------------------ C.2 · Impianto tabella
   `border-collapse:separate` e non `collapse`: con le celle collassate i
   bordi appartengono alla tabella e non alla cella, e una cella
   `position:sticky` perde i suoi bordi mentre scorre. E' il motivo per cui
   queste due tabelle derogano dall'impianto di A.2.
   `min-width:max-content` fa scorrere il contenitore invece di comprimere
   le colonne: venti servizi schiacciati in 900px sono illeggibili.        */
#permMatrix,
#tlPermMatrix{
  width:100%;
  min-width:max-content;
  border-collapse:separate;
  border-spacing:0;
  font-size:12.5px;
}

/* ----------------------------------- C.3 · Intestazione ferma in alto ---
   ⚠️ Il pezzo delicato di tutto il foglio.

   `hub-theme.css` da' gia' a `.data-table th` `position:sticky;top:0` piu'
   minuscola+maiuscoletto: quell'aspetto e' quello delle tabelle
   dell'applicazione e resta. Qui si aggiungono tre cose che lui non puo'
   sapere:

   a) le intestazioni sono su DUE righe (categoria sopra, servizio sotto), e
      la seconda deve fermarsi SOTTO la prima, non a `top:0` dove finirebbe
      coperta. Da qui `--amm-mx-h1`: e' l'altezza misurata della prima riga
      (padding 9+9 piu' la riga di testo), non un numero a caso. Se si
      cambia il padding della prima riga va cambiato anche questo.
   b) il fondo deve essere OPACO. Non `--glass-3` da solo: sotto scorrono le
      righe, e una lastra traslucida lascerebbe leggere il testo che passa.
      Due strati di sfondo sullo stesso elemento (un velo di vetro sopra il
      fondo pieno `--ground`) danno un opaco senza scrivere un colore a
      mano, e funzionano tali e quali in tema chiaro, dove `--ground`
      diventa avorio. E' la stessa ricetta di hub-theme.css per le
      intestazioni ferme.
   c) i nomi dei servizi sono lunghi e le colonne strette: `white-space:
      nowrap` e la matrice scorre. NIENTE testo ruotato di 90°: si legge di
      lato, obbliga a inclinare la testa, e per starci dentro servirebbe
      un'altezza di riga di 150px che manda l'intestazione fuori schermo.  */
#permMatrix,
#tlPermMatrix{
  --amm-mx-h1:33px;
}
#permMatrix thead th,
#tlPermMatrix thead th{
  position:sticky;
  top:0;
  z-index:4;
  padding:9px 10px;
  text-align:center;
  white-space:nowrap;
  background:linear-gradient(var(--glass-3),var(--glass-3)),var(--ground);
  border-bottom:1px solid var(--glass-edge-hi);
}
/* La PRIMA riga porta l'altezza dichiarata, e non e' un vezzo: `--amm-mx-h1`
   e' il valore a cui si ferma la seconda riga, e finche' era solo
   l'altezza «che viene» dal padding piu' la riga di testo, bastava un
   ritocco al corpo del carattere per farle scollare — con il risultato di
   una fessura fra le due intestazioni ferme, o di una che copre l'altra.
   Fissandola qui, il numero non e' piu' una misura sperata: e' la stessa
   grandezza usata dalle due parti.
   `.perm-matrix-group-row` e' la riga in `#tlPermMatrix`; in `#permMatrix`
   la riga delle categorie non porta quella classe, quindi la si prende per
   posizione. */
.perm-matrix-group-row,
#permMatrix thead tr:first-child,
#tlPermMatrix thead tr:first-child{
  height:var(--amm-mx-h1);
}

/* Seconda riga: si ferma appena sotto la prima e le passa SOTTO (z-index
   minore), altrimenti scorrendo si accavallerebbero al contrario. */
#permMatrix thead tr:nth-child(2) th,
#tlPermMatrix thead tr:nth-child(2) th{
  top:var(--amm-mx-h1);
  z-index:3;
}

/* Riga delle categorie: fascia colorata sotto, dal gettone locale posato
   dalle classi `.amm-cat-*` (B.4). `box-shadow` inset e non `border-bottom`
   perche' il bordo inferiore e' gia' occupato dalla riga sopra e i due si
   sommerebbero in una doppia linea. */
#permMatrix thead th.amm-cat-pagine,
#permMatrix thead th.amm-cat-esterni,
#permMatrix thead th.amm-cat-giochi{
  color:var(--amm-cat);
  background:linear-gradient(var(--amm-cat-soft),var(--amm-cat-soft)),var(--ground);
  box-shadow:inset 0 -2px 0 var(--amm-cat);
}

/* La riga delle categorie e' piu' piccola della riga dei servizi: e' un
   livello sopra, e un titolo di gruppo grande come le sue voci non si legge
   come un titolo. L'aggancio e' la CELLA e non la riga, perche' in
   `#permMatrix` la riga delle categorie non porta
   `.perm-matrix-group-row` — ce l'ha solo `#tlPermMatrix`. */
#permMatrix thead th.perm-matrix-group-cell,
#tlPermMatrix thead th.perm-matrix-group-cell{
  font-size:10.5px;
}

/* Il viola di `#tlPermMatrix`: le sue categorie arrivano da
   `TL_CAT_GROUPS`, che non porta un colore per categoria, quindi e' un
   colore di LIVELLO (un titolo di gruppo) e non di significato — uno solo
   per tutte. In `#permMatrix` invece ogni categoria ha il suo, e lo posano
   le `.amm-cat-*` qui sopra, che essendo (1,1,2) come questa e scritte prima
   perderebbero: per questo questa regola e' scoperta su `#tlPermMatrix` e
   non generica. */
#tlPermMatrix thead th.perm-matrix-group-cell{
  color:var(--hold);
  background:linear-gradient(var(--hold-soft),var(--hold-soft)),var(--ground);
  box-shadow:inset 0 -2px 0 color-mix(in srgb,var(--hold) 55%,transparent);
}

/* Le colonne di servizio: strette ma non tanto da tagliare l'interruttore
   che ci sta dentro (38px piu' il padding). */
.perm-matrix-svc-cell{
  min-width:78px;
}

/* ------------------------------------ C.4 · Prima colonna ferma a sinistra
   Senza questa, dopo tre colonne non si sa piu' di chi sia la riga che si
   sta leggendo — ed e' esattamente cio' che si sta decidendo, un permesso
   per un team o per una persona.

   Il fondo e' lo stesso opaco a due strati dell'intestazione, e per lo
   stesso motivo: se fosse traslucido, le colonne che le scorrono SOTTO si
   vedrebbero attraverso e la colonna diventerebbe illeggibile proprio
   mentre serve. Il filo a destra (`box-shadow:1px 0 0`) dice che la colonna
   e' ferma e il resto passa: senza, sembra un difetto di allineamento.

   ⚠️ Le due matrici hanno l'angolo in due posti diversi, e non e' un
   dettaglio da cui si puo' prescindere:
   · `#permMatrix` ha DUE celle d'angolo, una per riga d'intestazione
     (`<th></th>` sopra, `<th class="perm-matrix-col-label">Team</th>` sotto);
   · `#tlPermMatrix` ne ha UNA sola, con `rowspan="2"`, nella prima riga.
   Per questo l'aggancio e' la coppia «`th:first-child` + la classe
   `.perm-matrix-col-label`»: la classe prende la cella dell'etichetta in
   entrambe, `:first-child` prende anche la cella vuota di `#permMatrix`.
   Cio' che NON si puo' fare e' usare `thead tr:nth-child(2) th:first-child`
   come regola generale: nella seconda riga di `#tlPermMatrix` la prima
   cella e' una colonna di SERVIZI, e finirebbe incollata a sinistra sopra
   l'etichetta.                                                            */
#permMatrix thead th:first-child,
#permMatrix thead .perm-matrix-col-label,
#tlPermMatrix thead .perm-matrix-col-label,
#permMatrix tbody td:first-child,
#tlPermMatrix tbody td:first-child{
  position:sticky;
  left:0;
  box-shadow:1px 0 0 var(--glass-edge);
}
#permMatrix tbody td:first-child,
#tlPermMatrix tbody td:first-child{
  /* Sopra le celle che le passano sotto (che non hanno z-index), e sotto
     l'intestazione. */
  z-index:2;
  background:linear-gradient(var(--glass-2),var(--glass-2)),var(--ground);
  text-align:left;
  min-width:200px;
}

/* L'ANGOLO. E' la cella ferma in due direzioni insieme, quindi deve stare
   sopra a tutto: sopra le altre celle d'intestazione (che le scorrono
   sotto in orizzontale) e sopra la prima colonna (che le scorre sotto in
   verticale). Ha il valore piu' alto della scala:
      1  celle normali del corpo (implicito)
      2  prima colonna del corpo
      3  seconda riga d'intestazione
      4  prima riga d'intestazione
      5  angolo della seconda riga
      6  angolo della prima riga
   Il valore 5 esiste solo per `#permMatrix`, che di angoli ne ha due (uno
   per riga d'intestazione). La regola porta `tr:nth-child(2)` esplicito
   perche' altrimenti la regola di C.3 sulla seconda riga, che ha un
   elemento in piu' nel selettore, gli riabbasserebbe lo z-index a 3.      */
#permMatrix thead th:first-child,
#tlPermMatrix thead .perm-matrix-col-label{
  z-index:6;
}
#permMatrix thead tr:nth-child(2) th:first-child{
  z-index:5;
}

/* La colonna dell'etichetta: allineata a sinistra e larga abbastanza da
   contenere un nome e cognome senza andare a capo. `text-align:left` va
   ridichiarato qui perche' C.3 centra tutte le intestazioni, e con l'`id`
   nel selettore quella regola batte una classe da sola. */
#permMatrix thead th:first-child,
#tlPermMatrix thead .perm-matrix-col-label{
  text-align:left;
  padding-left:14px;
  min-width:200px;
}

/* --------------------------------------------------- C.5 · Corpo e righe
   La riga sotto il puntatore si evidenzia PER INTERO (`tbody tr:hover td`,
   non `tbody tr:hover`): in una matrice larga venti colonne, senza la riga
   accesa da un bordo all'altro si perde il filo fra il nome a sinistra e la
   cella che si sta per cliccare, e si spegne il permesso sbagliato.       */
#permMatrix tbody td,
#tlPermMatrix tbody td{
  padding:7px 10px;
  text-align:center;
  vertical-align:middle;
  border-bottom:1px solid var(--glass-edge);
}
#permMatrix tbody tr:hover td,
#tlPermMatrix tbody tr:hover td{
  background:var(--glass-2);
}
/* La prima colonna deve accendersi con la riga come tutte le altre celle,
   altrimenti resta l'unico pezzo spento della riga evidenziata. Il fondo
   opaco va rifatto sopra il velo di hover, non sostituito. */
#permMatrix tbody tr:hover td:first-child,
#tlPermMatrix tbody tr:hover td:first-child{
  background:linear-gradient(var(--glass-3),var(--glass-3)),var(--ground);
}

/* L'etichetta di riga. In `#permMatrix` e' il nome del team, in
   `#tlPermMatrix` un nome di persona con sotto i suoi team.
   Il nome NON e' giallo (oggi `.perm-matrix-team` e' #FFC107): il giallo e'
   il marchio, e una colonna di venti nomi gialli se lo mangia. Inchiostro
   pieno: in una tabella di testo attenuato, il nero e' gia' l'evidenza. */
.perm-matrix-team{
  color:var(--ink);
  font-weight:600;
  font-size:13px;
}
.perm-matrix-row-label{
  text-align:left;
  padding-left:14px;
  font-size:13px;
  color:var(--ink);
  line-height:1.3;
}
.perm-matrix-row-label strong{
  font-weight:600;
}
.perm-matrix-row-sub{
  margin-top:2px;
  font-size:11px;
  font-weight:400;
  color:var(--ink-3);
}
/* La cella dell'interruttore: qui si veste la CELLA, non l'interruttore
   dentro (`.perm-toggle`/`.pt-slider`/`.toggle-switch` sono di
   02-controlli.css). Serve solo che l'interruttore stia in mezzo e che la
   cella non collassi in altezza. */
.perm-matrix-cell{
  text-align:center;
  vertical-align:middle;
  line-height:0;
}


/* ------------------------------------------------------------------------
   C.6 · Il pannello del singolo consulente
   Sotto la matrice: si cerca una persona e si vede cosa le arriva dal team,
   cosa le e' stato scritto addosso, e cosa ne risulta.
   ------------------------------------------------------------------------ */

/* ---------------------------- C.6.1 · Il menu dei risultati di ricerca --
   `#permConsResults`, riempito da `filterPermConsultants`. Sta dentro il
   campo `.amm-cerca` (di 02-controlli.css), che gli fa da riferimento.

   ⚠️ Superficie OPACA (`--surface-menu`), NON vetro. E' la lezione della
   fase 8 di questo progetto: un pannello che galleggia SOPRA il contenuto
   ha dietro del testo, non il fondo della pagina, e all'8% di bianco lo si
   legge attraverso — quindici nomi di consulente sovrapposti al testo della
   schermata non sono un effetto, sono un pannello inservibile. Il vetro va
   bene per un contenitore che sta nel flusso; questo no.                  */
#permConsResults{
  position:absolute;
  top:calc(100% + 5px);
  left:0;
  right:0;
  z-index:60;
  max-height:320px;
  overflow-y:auto;
  padding:5px;
  border-radius:var(--r-md);
  background:var(--surface-menu);
  border:1px solid var(--glass-edge-hi);
  box-shadow:var(--shadow-2);
}
/* Una riga di risultato: nome e email a sinistra, squadra a destra.
   Lo stato al passaggio del mouse e' obbligatorio, non decorativo: in un
   elenco di quindici righe cliccabili identiche, senza riga accesa non si
   sa quale si sta per scegliere — e la scelta cambia tutta la schermata
   sotto. */
.amm-sugg-riga{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  padding:8px 10px;
  border-radius:var(--r-sm);
  cursor:pointer;
  transition:background var(--speed) var(--ease);
}
.amm-sugg-riga:hover{
  background:var(--glass-2);
}
.amm-sugg-nome{
  font-size:13px;
  font-weight:600;
  color:var(--ink);
}
.amm-sugg-mail{
  font-size:11px;
  color:var(--ink-3);
  overflow-wrap:anywhere;
}
/* "Nessun consulente trovato" dentro un menu alto 320px: il padding da
   tabella (36px) lo farebbe sembrare un errore di caricamento. */
#permConsResults .empty-state{
  padding:18px 12px;
}

/* ------------------------------ C.6.2 · La testata di chi si e' scelto --
   Bordo blu tenue (`--live`) perche' qui non si decide niente: si sta
   LEGGENDO chi si e' scelto. Il blu e' il colore dell'informazione in
   questa tavolozza.                                                      */
.perm-cons-info{
  display:flex;
  align-items:center;
  gap:13px;
  padding:14px 16px;
  margin-bottom:14px;
  border-radius:var(--r-md);
  background:var(--live-soft);
  border:1px solid color-mix(in srgb,var(--live) 26%,transparent);
}
.amm-cons-ico{
  flex:0 0 auto;
  display:grid;
  place-items:center;
  width:38px;
  height:38px;
  border-radius:50%;
  background:var(--track);
  border:1px solid var(--glass-edge);
  color:var(--live);
  font-size:19px;
  line-height:1;
}
.amm-cons-ico .yh-i{
  width:20px;
  height:20px;
}
/* `min-width:0` e' cio' che permette all'email lunga di troncarsi invece di
   spingere la squadra fuori dal riquadro. */
.amm-cons-chi{
  flex:1;
  min-width:0;
}
.amm-cons-nome{
  font-size:15px;
  font-weight:600;
  color:var(--ink);
  letter-spacing:-.01em;
}
.amm-cons-mail{
  font-size:12px;
  color:var(--ink-3);
  overflow-wrap:anywhere;
}
/* Squadra sopra, numero di eccezioni sotto, allineati a destra: sono i due
   dati che dicono "da dove arrivano i suoi permessi", e stanno insieme
   all'estremo opposto del nome. */
.amm-cons-meta{
  flex:0 0 auto;
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:5px;
  text-align:right;
}
.amm-cons-over{
  font-size:11px;
}

/* ------------------- C.6.3 · Le tre righe: team, eccezione, risultato ---
   La tabella del pannello ha tre righe che si leggono dall'alto in basso
   come un calcolo: cosa dice il team, cosa e' stato scritto sulla persona,
   cosa ne esce. L'etichetta di riga e' il nome del passaggio.             */
.amm-cons-riga{
  font-size:12px;
  color:var(--ink-3);
  white-space:nowrap;
}
/* La riga del risultato e' la conclusione: fondo appena staccato e un filo
   piu' marcato sopra, per leggerla come somma e non come un terzo dato
   qualunque. Stessa idea della riga dei totali nelle tabelle
   dell'applicazione. */
.amm-cons-esito td{
  background:var(--glass-2);
  border-top:2px solid var(--glass-edge-hi);
}
.amm-cons-tot{
  font-size:12.5px;
  font-weight:700;
  color:var(--ink);
  white-space:nowrap;
}
/* L'asterisco che marca "questo valore viene da un'eccezione, non dal
   team". Viola come tutto cio' che e' eccezione (`.amm-hold`), e piccolo:
   e' una nota a margine dentro una cella, non un dato. */
.amm-cons-star{
  color:var(--hold);
  font-size:10px;
  font-weight:700;
  vertical-align:super;
}

/* Le schede per servizio: una griglia che si riempie da sé.
   `auto-fill` e non `auto-fit`: con `auto-fit`, tre schede su un monitor
   largo si allargherebbero a 500px l'una: una scheda con dentro tre righe
   di elenco non ha niente da farci, con quello spazio. Sulle 5 schede di
   NewEden (F.1) la scelta e' l'opposta, e la' e' spiegata perche'. */
.perm-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(272px,1fr));
  gap:13px;
  margin-top:14px;
}
.perm-card{
  padding:15px 16px;
  border-radius:var(--r-md);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  box-shadow:var(--shadow-1),inset 0 1px 0 var(--glass-spec);
}
.perm-card-title{
  display:flex;
  align-items:center;
  gap:8px;
  flex-wrap:wrap;
  margin-bottom:11px;
  font-size:14px;
  font-weight:600;
  color:var(--ink);
  letter-spacing:-.01em;
}

/* L'etichetta di categoria dentro il titolo. Stessa tavolozza di B.4:
   quattro categorie, quattro gettoni, e nessun colore a mano. */
.service-type{
  display:inline-flex;
  align-items:center;
  padding:2px 8px;
  border-radius:var(--r-pill);
  font-size:10.5px;
  font-weight:600;
  text-transform:lowercase;
  font-variant:small-caps;
  letter-spacing:.06em;
  white-space:nowrap;
  color:var(--off);
  background:var(--off-soft);
  border:1px solid transparent;
}
.service-type.page{
  color:var(--hold);
  background:var(--hold-soft);
  border-color:color-mix(in srgb,var(--hold) 26%,transparent);
}
.service-type.external{
  color:var(--wait);
  background:var(--wait-soft);
  border-color:color-mix(in srgb,var(--wait) 26%,transparent);
}
.service-type.game{
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 26%,transparent);
}
.service-type.dashboard{
  color:var(--live);
  background:var(--live-soft);
  border-color:color-mix(in srgb,var(--live) 26%,transparent);
}

/* I titoli che dividono le schede per categoria. Stessa tavolozza, ma qui
   il colore sta sulla riga di separazione: un titolo tutto colorato in
   quattro colori diversi, ripetuto quattro volte in una pagina, diventa un
   arcobaleno. Il testo resta inchiostro, il colore fa da segnalibro. */
.perm-section{
  margin-bottom:26px;
}
.perm-section-title{
  display:flex;
  align-items:center;
  gap:9px;
  padding-bottom:8px;
  margin-bottom:13px;
  font-size:12px;
  font-weight:700;
  text-transform:lowercase;
  font-variant:small-caps;
  letter-spacing:.09em;
  color:var(--ink-2);
  border-bottom:1px solid var(--glass-edge);
}
.perm-section-title .yh-i{
  width:17px;
  height:17px;
  flex:0 0 auto;
}
.perm-section-title.pages{      color:var(--hold); border-bottom-color:color-mix(in srgb,var(--hold) 34%,transparent); }
.perm-section-title.externals{  color:var(--wait); border-bottom-color:color-mix(in srgb,var(--wait) 34%,transparent); }
.perm-section-title.games{      color:var(--won);  border-bottom-color:color-mix(in srgb,var(--won) 34%,transparent); }
.perm-section-title.dashboards{ color:var(--live); border-bottom-color:color-mix(in srgb,var(--live) 34%,transparent); }

/* L'elenco delle regole scritte dentro una scheda. */
.perm-rules{
  list-style:none;
  padding:0;
  margin:0;
}
.perm-rule{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  padding:6px 0;
  font-size:12.5px;
  border-bottom:1px solid var(--glass-edge);
}
.perm-rule:last-child{
  border-bottom:none;
}
.rule-scope{
  color:var(--ink-2);
  min-width:0;
  overflow-wrap:anywhere;
}
/* Acceso e spento non si distinguono per il solo colore: hanno anche il
   peso e un pallino. Chi non distingue il verde dal rosso — una persona su
   dodici fra gli uomini — su questa schermata deciderebbe alla cieca. */
.rule-status{
  display:inline-flex;
  align-items:center;
  gap:5px;
  font-size:11.5px;
  font-weight:600;
  white-space:nowrap;
  color:var(--ink-3);
}
.rule-status::before{
  content:'';
  width:6px;
  height:6px;
  border-radius:50%;
  background:currentColor;
  flex:0 0 auto;
}
.rule-status.enabled{ color:var(--won); }
.rule-status.disabled{ color:var(--lost); }
/* "Nessuna regola" non e' "spento": e' un non-deciso, e vale acceso.
   Corsivo e terziario, come una nota, non come uno stato. */
.perm-no-rules{
  font-size:12px;
  font-style:italic;
  color:var(--ink-3);
}

/* ------------------------- C.7 · Segmentato «per TL / per squadra» ------
   Due modi di guardare la stessa matrice. E' un segmentato: la voce scelta
   e' piena, l'altra e' solo testo. Giallo pieno sulla voce attiva perche'
   qui il segmentato E' la cosa principale della schermata — cambia cosa
   dicono tutte le righe sotto.
   `inline-flex` con margine e non `flex` sul genitore: il contenitore di
   queste due voci non ha una classe assegnata dal contratto, quindi la
   pastiglia deve stare in piedi anche in un genitore che non le dispone. */
.tl-scope-tab{
  display:inline-flex;
  align-items:center;
  gap:7px;
  height:30px;
  margin:0 6px 6px 0;
  padding:0 13px;
  border-radius:var(--r-pill);
  font-size:12.5px;
  font-weight:600;
  color:var(--ink-3);
  background:var(--glass-2);
  border:1px solid var(--glass-edge);
  cursor:pointer;
  white-space:nowrap;
  user-select:none;
  transition:color var(--speed) var(--ease),
             background var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.tl-scope-tab:hover:not(.active){
  color:var(--ink);
  border-color:var(--glass-edge-hi);
}
.tl-scope-tab.active{
  background:var(--accent);
  color:var(--on-accent);
  border-color:transparent;
  box-shadow:0 2px 10px -4px var(--accent-glow);
}
.tl-scope-tab .yh-i{
  width:16px;
  height:16px;
}


/* #########################################################################
   D · SCHERMATA «ASSEGNAZIONE TEAM» — le schede dei Team Leader
   ######################################################################### */

/* ------------------------------------------------------ D.1 · La griglia
   Oggi e' uno `style="display:grid…"` in linea su `#tlCardGrid`.
   `auto-fill` (non `auto-fit`) per il motivo detto in C.6: un solo team
   leader non deve produrre una scheda larga come lo schermo.              */
.amm-tl-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(316px,1fr));
  gap:14px;
  align-items:start;
}
/* Il messaggio di "nessun risultato" e' l'unico figlio che deve prendersi
   tutte le colonne: era un `grid-column:1/-1` scritto in linea, e senza si
   accuccia nella prima colonna, stretto e storto accanto a due terzi di
   riga vuota. */
.amm-tl-grid .empty-state{
  grid-column:1 / -1;
}

/* --------------------------------------------------------- D.2 · La scheda */
.tl-card-v2{
  padding:16px 17px;
  border-radius:var(--r-md);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  box-shadow:var(--shadow-1),inset 0 1px 0 var(--glass-spec);
  transition:border-color var(--speed) var(--ease),
             box-shadow var(--speed) var(--ease),
             transform var(--speed) var(--ease);
}
.tl-card-v2:hover{
  border-color:var(--glass-edge-hi);
  box-shadow:var(--shadow-2),inset 0 1px 0 var(--glass-spec);
  transform:translateY(-1px);
}

.tl-card-head{
  display:flex;
  align-items:flex-start;
  gap:11px;
}
/* Il blocco di mezzo: nome, email, distintivi. `min-width:0` e' cio' che
   permette all'email lunga di troncarsi invece di allargare la scheda e con
   essa tutta la colonna della griglia. */
.amm-tl-info{
  flex:1;
  min-width:0;
}
/* Mercato e stato stanno in fila sotto l'email e vanno a capo insieme: sono
   due distintivi, non una riga di testo. */
.amm-tl-badges{
  display:flex;
  flex-wrap:wrap;
  gap:6px;
  margin-top:6px;
}
/* Il menu del mercato prende tutta la larghezza della scheda: e' l'unico
   controllo pieno che ci sta dentro, e a larghezza automatica cambierebbe
   misura da una scheda all'altra secondo il nome del paese. La veste
   (vetro, bordo, fuoco) arriva da `.filter-select` in 02-controlli.css. */
.amm-tl-mercato{
  width:100%;
}

/* Le iniziali. NON gialle: una scheda per team leader vuol dire venti
   pastiglie gialle in una schermata, e il giallo che si ripete venti volte
   non e' piu' un accento. Neutre come l'`.ava` del prototipo: l'identita'
   la porta il nome accanto, non il colore del cerchio. */
.tl-avatar-v2{
  width:40px;
  height:40px;
  border-radius:50%;
  flex:0 0 auto;
  display:grid;
  place-items:center;
  font-size:13px;
  font-weight:700;
  letter-spacing:-.02em;
  color:var(--ink-2);
  background:var(--track);
  border:1px solid var(--glass-edge);
}
.tl-card-name{
  font-size:14.5px;
  font-weight:600;
  letter-spacing:-.01em;
  color:var(--ink);
}
/* L'email si tronca con i puntini invece di andare a capo: e' un dato da
   riconoscere, non da leggere, e su tre righe sfonderebbe la scheda. Il
   `title` nel markup la mostra intera al passaggio del mouse. */
.tl-card-email{
  font-size:11.5px;
  color:var(--ink-3);
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

/* -------------------------------------- D.3 · I distintivi della scheda -
   Tre varianti: mercato, attivo, disattivo.                              */
.tl-card-badge{
  display:inline-flex;
  align-items:center;
  gap:5px;
  padding:3px 9px;
  border-radius:var(--r-pill);
  font-size:11px;
  font-weight:600;
  white-space:nowrap;
  color:var(--ink-2);
  background:var(--glass-2);
  border:1px solid var(--glass-edge);
}
/* Il mercato: neutro perche' il colore ce l'ha ora la bandiera dentro.
   Prima era una pastiglia gialla con dentro un'emoji-bandiera. */
.tl-card-badge.market{
  color:var(--ink-2);
}
.tl-card-badge.success{
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 28%,transparent);
}
.tl-card-badge.danger{
  color:var(--lost);
  background:var(--lost-soft);
  border-color:color-mix(in srgb,var(--lost) 28%,transparent);
}

/* LA BANDIERA. Su Windows le emoji-bandiera non esistono: il sistema stampa
   le due lettere del codice paese (IT, ES) — e' una scelta di Microsoft, non
   un font mancante, e non si aggira installando niente. Per questo le
   bandiere sono disegnate, e per questo la classe e' `yh-flag` e non
   `yh-i`: `yh-i` impone `fill:none` e `stroke:currentColor`, che su una
   bandiera vuol dire cancellarla.
   Misura e raggio arrivano da hub-theme.css; qui si accorda solo la scala
   alla pastiglia, che e' piu' piccola di una riga di tabella. */
.tl-card-badge .yh-flag{
  width:17px;
  height:12px;
  border-radius:2px;
}

/* ----------------------------------- D.4 · Etichette e squadre nella scheda */
.tl-card-section-label{
  margin:13px 0 6px;
  font-size:10.5px;
  font-weight:700;
  text-transform:lowercase;
  font-variant:small-caps;
  letter-spacing:.1em;
  color:var(--ink-3);
}
.tl-card-teams-list{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:6px;
  /* Altezza minima: senza, una scheda senza squadre si accorcia e la
     griglia diventa un dente di sega. */
  min-height:30px;
}
/* Una squadra assegnata. Viola `--hold`, che sostituisce il #a855f7 di
   oggi: e' l'unico colore della tavolozza che non vuol dire ne' "ok" ne'
   "errore" ne' "attenzione", e una squadra non e' nessuna delle tre. */
.team-pill{
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:3px 6px 3px 10px;
  border-radius:var(--r-pill);
  font-size:11.5px;
  font-weight:600;
  white-space:nowrap;
  color:var(--hold);
  background:var(--hold-soft);
  border:1px solid color-mix(in srgb,var(--hold) 30%,transparent);
}
/* La × che rimuove la squadra. Attenuata a riposo perche' e' un'azione
   distruttiva che non deve invitare; area di clic di 16px, che e' il minimo
   per centrarla col dito senza cancellare la squadra sbagliata. */
.team-pill .x{
  display:inline-grid;
  place-items:center;
  width:16px;
  height:16px;
  border-radius:50%;
  opacity:.55;
  cursor:pointer;
  transition:opacity var(--speed) var(--ease),
             color var(--speed) var(--ease),
             background var(--speed) var(--ease);
}
.team-pill .x:hover{
  opacity:1;
  color:var(--lost);
  background:var(--lost-soft);
}
.team-pill .x .yh-i{
  width:11px;
  height:11px;
}

/* ---------------------------------------------- D.5 · Ruoli e piede ----
   I ruoli sono caselle di spunta con una parola accanto: la casella resta
   quella vera (accessibile, raggiungibile col TAB), l'etichetta le fa da
   bersaglio grande.

   ⚠️ Misure, raggio, gap, hover e anello di fuoco sono gli STESSI di
   `.amm-check` in 02-controlli.css, e non per caso: `.amm-check` (i team nei
   modali) e queste (i ruoli nelle schede) sono visivamente lo stesso
   oggetto, e nella stessa pagina. Se qui si scrivessero misure proprie, la
   stessa cosa avrebbe due facce a due centimetri di distanza. Le classi
   restano due perche' il markup le tiene separate (una e' `<label>` figlia
   di `.tl-card-roles-list`, l'altra porta la classe addosso), ma l'aspetto
   e' uno: chi cambia una delle due deve venire a cambiare l'altra.        */
.tl-card-roles-list{
  display:flex;
  flex-wrap:wrap;
  gap:7px;
}
.tl-card-roles-list label{
  display:inline-flex;
  align-items:center;
  gap:7px;
  padding:5px 11px;
  border-radius:var(--r-pill);
  font-size:12px;
  color:var(--ink-2);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  cursor:pointer;
  user-select:none;
  white-space:nowrap;
  transition:border-color var(--speed) var(--ease),
             color var(--speed) var(--ease),
             background var(--speed) var(--ease);
}
.tl-card-roles-list label:hover{
  border-color:var(--accent-line);
  color:var(--ink);
}
/* L'anello di fuoco va sulla pastiglia, non sul quadratino: e' la pastiglia
   intera che il TAB seleziona a occhio. Identico a `.amm-check:focus-within`. */
.tl-card-roles-list label:focus-within{
  border-color:var(--accent-line);
  box-shadow:0 0 0 3px var(--accent-soft);
}
.tl-card-roles-list label input[type="checkbox"]{
  margin:0;
  flex:0 0 auto;
}
.tl-card-roles-list label input:focus-visible{
  outline:none; /* l'anello ce l'ha la pastiglia */
}
/* Ruolo attivo: la pastiglia si accende insieme alla casella, senza una
   riga di JavaScript. Serve perche' in una fila di tre pastiglie identiche
   la sola spunta di 13px non si legge da lontano. */
.tl-card-roles-list label:has(input:checked){
  color:var(--accent-text);
  background:var(--accent-soft);
  border-color:var(--accent-line);
}

.tl-card-footer{
  display:flex;
  align-items:center;
  gap:7px;
  margin-top:14px;
  padding-top:12px;
  border-top:1px solid var(--glass-edge);
}


/* #########################################################################
   E · SCHERMATA «GRUPPI ADMIN» — i gruppi richiudibili
   Un gruppo e' un elenco di servizi acceso/spento piu' le persone che lo
   usano. Chiuso dice quanti servizi e quante persone, aperto mostra tutto.
   Oggi e' tutto in linea dentro renderGruppoCard/renderGruppoExpanded.
   ######################################################################### */

/* ⚠️ `body .table-card.amm-grp` e non `.amm-grp`: nel markup generato la
   scheda del gruppo porta ENTRAMBE le classi
   (`<div class="table-card amm-grp">`), e `body .table-card` di
   hub-theme.css pesa (0,1,1) — un `.amm-grp` da solo (0,1,0) non le
   toglierebbe il padding. Qui il padding deve essere zero perche'
   l'intestazione va da bordo a bordo: e' lei il bersaglio del clic, e un
   bersaglio con 18px di vetro morto attorno e' 18px di clic che non fanno
   niente.                                                                */
body .table-card.amm-grp{
  padding:0;
  border-radius:var(--r-md);
  margin-bottom:11px;
  /* Serve a far tagliare gli angoli tondi al fondo dell'intestazione, che
     e' a tutta larghezza: senza, il rettangolo dell'hover sborda dai
     quattro angoli della scheda. Nessun contenuto viene nascosto — la
     scheda cresce in altezza a piacere. */
  overflow:hidden;
}
/* Gruppo aperto: bordo acceso (prima era un `border-color` giallo scritto a
   mano dentro il JavaScript). E' l'unico segnale che dice "quello che stai
   leggendo sotto appartiene a QUESTA scheda", quando ce ne sono sei in
   colonna e una sola e' aperta. */
body .table-card.amm-grp.aperto{
  border-color:var(--accent-line);
}

/* L'intestazione e' una riga cliccabile a tutta larghezza. Le righe di
   azzeramento (`background`, `border`, `font`, `text-align`) servono per il
   caso in cui diventi un <button>: un <button> arriva col suo carattere,
   il suo fondo grigio e il testo centrato, e senza azzeramento non
   sembrerebbe una riga di elenco. Oggi e' un <div onclick>, e su un <div>
   sono innocue.
   Area di clic generosa (15px sopra e sotto): e' il bersaglio che si prende
   piu' volte in questa schermata.                                        */
.amm-grp-head{
  display:flex;
  width:100%;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  flex-wrap:wrap;
  padding:15px 18px;
  text-align:left;
  background:none;
  border:0;
  color:inherit;
  font:inherit;
  cursor:pointer;
  transition:background var(--speed) var(--ease);
}
.amm-grp-head:hover{
  background:var(--glass-2);
}
/* Il fuoco da tastiera dentro un contenitore con `overflow:hidden` non puo'
   uscire fuori: contorno interno, non esterno. */
.amm-grp-head:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:-3px;
}
/* `min-width:0` perche' una descrizione lunga deve andare a capo dentro il
   blocco, non spingere i due pulsanti fuori dalla scheda. */
.amm-grp-info{
  flex:1;
  min-width:220px;
}
.amm-grp-titolo{
  display:flex;
  align-items:center;
  gap:9px;
  flex-wrap:wrap;
}
.amm-grp-nome{
  font-size:14px;
  font-weight:600;
  color:var(--ink);
  letter-spacing:-.01em;
}
.amm-grp-desc{
  margin-top:3px;
  font-size:11.5px;
  color:var(--ink-3);
  line-height:1.45;
}
/* Il riepilogo «3 abilitate · 1 disabilitate»: e' il dato che serve a
   scheda chiusa, quindi non e' una nota — sta staccato e leggibile. Il
   colore delle due parole lo portano le utilita' acceso/spento del
   foglio delle utilita', non questo file. */
.amm-grp-sunto{
  margin-top:6px;
  font-size:11.5px;
}
/* I due pulsanti a destra: non si allargano e non vanno a capo dentro se
   stessi. Il `event.stopPropagation()` che impedisce loro di aprire il
   gruppo e' nel markup e non si tocca. */
.amm-grp-azioni{
  display:flex;
  align-items:center;
  gap:7px;
  flex:0 0 auto;
}

/* La freccetta. ⚠️ NON le si mette una rotazione al volo: il JavaScript
   scambiava due caratteri diversi (▸ chiuso, ▾ aperto): ma Sofia Pro non ha
   quei due glifi e a schermo si vedeva un puntino, cioe' il comando
   principale della schermata restava senza segno. Dal 2026-09-10 il
   JavaScript emette sempre la stessa icona disegnata ed e' questa regola a
   girarla — una sola forma che ruota, che e' il modo giusto di dirlo. */
.amm-grp-caret{
  display:inline-block;
  flex:0 0 auto;
  color:var(--ink-3);
  font-size:11px;
  line-height:1;
  transition:transform var(--speed) var(--ease),
             color var(--speed) var(--ease);
}
.amm-grp-head:hover .amm-grp-caret{
  color:var(--ink-2);
}
.amm-grp.aperto .amm-grp-caret{
  color:var(--accent-text);
}
/* 90 gradi, non 180. La freccetta ora e' `yh-ic-chevron-right`, cioe' punta
   a DESTRA quando il gruppo e' chiuso: ruotata di 180° punterebbe a sinistra,
   che non vuol dire niente. A 90° punta in giu', che e' il verso in cui il
   gruppo si apre — ed e' quello che diceva il carattere ▾ di prima.
   Il `:has(svg)` resta: se un domani tornasse un carattere al posto
   dell'icona, la rotazione si spegne da se' invece di girarlo a caso. */
.amm-grp.aperto .amm-grp-caret:has(svg){
  transform:rotate(90deg);
}

/* ------------------------------------------- E.2 · Il gruppo aperto ---- */
.amm-grp-body{
  padding:16px 18px 18px;
  border-top:1px solid var(--glass-edge);
  /* Fondo appena piu' fondo dell'intestazione: dice che questo pezzo sta
     DENTRO la scheda e non e' una scheda nuova appoggiata sotto. */
  background:var(--glass-1);
}
.amm-grp-sez + .amm-grp-sez{
  margin-top:22px;
}
.amm-grp-sez-tit{
  margin:0 0 5px;
  font-size:12.5px;
  font-weight:700;
  color:var(--ink);
}
/* Le istruzioni del ciclo a tre stati. Sono una frase lunga e vanno lette
   una volta sola: testo terziario, interlinea larga, e le parole in
   grassetto (che sono i tre stati) restano l'unica evidenza. */
.amm-grp-sez-nota{
  margin:0 0 12px;
  font-size:11.5px;
  color:var(--ink-3);
  line-height:1.55;
  max-width:78ch;
}
.amm-grp-sez-nota strong{
  color:var(--ink-2);
  font-weight:600;
}

/* Le categorie di servizi dentro il gruppo. */
.amm-grp-cat{
  margin-bottom:15px;
}
.amm-grp-cat-tit{
  margin-bottom:7px;
  font-size:11px;
  font-weight:700;
  text-transform:lowercase;
  font-variant:small-caps;
  letter-spacing:.1em;
  /* Viola dei gettoni: sostituisce il #a78bfa scritto a mano. Le categorie
     qui non hanno un colore proprio (arrivano da `TL_CAT_GROUPS`, che non
     ne porta uno), quindi e' un colore di livello — "questo e' un titolo di
     gruppo" — non un colore di significato. */
  color:var(--hold);
}

/* I servizi del gruppo: griglia che si riempie, `auto-fill` per la ragione
   di sempre (due servizi non devono diventare due riquadri larghi mezzo
   schermo). */
.amm-grp-srv{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(232px,1fr));
  gap:8px;
}
/* Una riga servizio: nome a sinistra, stato a destra. Tutta la riga e'
   cliccabile (`onclick` sul contenitore) e fa girare i tre stati, quindi ha
   il cursore e uno stato al passaggio del mouse — un bersaglio grande che
   non si vede e' un bersaglio che nessuno prende. */
.amm-grp-riga{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  padding:9px 12px;
  border-radius:var(--r-sm);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  font-size:12.5px;
  cursor:pointer;
  transition:border-color var(--speed) var(--ease),
             background var(--speed) var(--ease);
}
.amm-grp-riga:hover{
  background:var(--glass-2);
  border-color:var(--glass-edge-hi);
}
.amm-grp-riga-nome{
  color:var(--ink-2);
  min-width:0;
  overflow-wrap:anywhere;
}
/* I tre stati anche sul BORDO della riga, non solo sull'etichetta dentro
   (che e' `.amm-sw`, di 02-controlli.css): con venti servizi in griglia, e'
   il bordo colorato a far vedere da lontano quali sono stati toccati e
   quali sono rimasti al valore ereditato. */
.amm-grp-riga.on{
  border-color:color-mix(in srgb,var(--won) 34%,transparent);
}
.amm-grp-riga.off{
  border-color:color-mix(in srgb,var(--lost) 34%,transparent);
}
/* "dflt" (nessuna regola scritta: vale abilitato, ma non e' stato deciso)
   NON prende un colore. E' dichiarata comunque, e non lasciata al caso, per
   una ragione precisa: e' il terzo stato, e il suo aspetto — bordo neutro,
   tratteggiato — e' una scelta di design, non un'assenza di regola. Chi
   legge questo file deve trovarla scritta, altrimenti la prossima volta
   qualcuno le dara' un colore "perche' mancava".
   Il tratteggio e' la stessa grammatica dell'interruttore a tre stati della
   matrice: tratteggiato = non deciso. */
.amm-grp-riga.dflt{
  border-style:dashed;
  border-color:var(--glass-edge);
}

/* --------------------------------------------- E.3 · I membri del gruppo
   Un elenco di caselle di spunta che puo' essere lungo: scorre dentro il
   proprio riquadro invece di allungare la scheda a due schermi.           */
.amm-grp-membri{
  max-height:280px;
  overflow-y:auto;
  padding:5px;
  border-radius:var(--r-sm);
  border:1px solid var(--glass-edge);
  background:var(--glass-1);
}
/* Una riga di membro: NON una pastiglia come i ruoli (D.5) — quelle sono
   tre e stanno in fila, queste sono cinquanta e stanno in colonna, e in
   colonna una riga a tutta larghezza e' un bersaglio molto piu' facile da
   prendere di una pastiglia stretta quanto il nome. */
.amm-grp-membro{
  display:flex;
  align-items:center;
  gap:8px;
  padding:6px 8px;
  border-radius:var(--r-sm);
  font-size:12.5px;
  color:var(--ink-2);
  cursor:pointer;
  user-select:none;
  transition:background var(--speed) var(--ease);
}
.amm-grp-membro:hover{
  background:var(--glass-2);
}
.amm-grp-membro:focus-within{
  background:var(--glass-2);
  box-shadow:inset 0 0 0 1px var(--accent-line);
}
.amm-grp-membro input[type="checkbox"]{
  margin:0;
  flex:0 0 auto;
}
.amm-grp-membro input:focus-visible{
  outline:none; /* l'anello ce l'ha la riga */
}


/* #########################################################################
   F · SCHERMATA «NEWEDEN FESTIVAL»
   ######################################################################### */

/* ------------------------------------------------- F.1 · I cinque numeri
   ⚠️ `auto-fit`, NON `auto-fill`. Con `auto-fill` la griglia crea tutte le
   colonne che ci stanno anche se sono vuote: su un monitor largo si apre
   una sesta colonna fantasma e le cinque schede restano strette sulla
   sinistra con un buco a destra. `auto-fit` richiude le colonne vuote e le
   cinque schede si dividono la riga. Qui, al contrario delle griglie di
   schede (C.6, D.1, E), riempire la riga E' cio' che si vuole: sono
   sempre cinque, sono una fila di numeri, e devono leggersi come una fila. */
.amm-stats{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:12px;
  margin-bottom:18px;
  align-items:start;
}

/* La scheda. E' una griglia a colonna con le righe DICHIARATE, non un
   semplice blocco: cosi' l'etichetta finisce sopra e il numero sotto
   qualunque sia l'ordine in cui arrivano nel markup, e nessuno deve
   ricordarsi di tenerli nell'ordine giusto. Stessa tecnica usata in fase 9
   per le `.stat-card` dell'applicazione. */
.amm-stat{
  display:grid;
  align-content:start;
  padding:15px 16px;
  border-radius:var(--r-md);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  box-shadow:var(--shadow-1),inset 0 1px 0 var(--glass-spec);
  transition:border-color var(--speed) var(--ease),
             box-shadow var(--speed) var(--ease),
             transform var(--speed) var(--ease);
}
.amm-stat:hover{
  border-color:var(--glass-edge-hi);
  box-shadow:var(--shadow-2),inset 0 1px 0 var(--glass-spec);
  transform:translateY(-1px);
}

/* ETICHETTA SOPRA, NUMERO GROSSO SOTTO. Decisione presa e misurata nella
   fase 9 di questo progetto: il numero e' il motivo per cui la scheda
   esiste, e si legge come risposta a una domanda — prima la domanda
   ("Totale"), poi la risposta. Invertiti, si legge un numero senza sapere
   di cosa, e si torna su a cercare l'etichetta. */
.amm-stat-lbl{
  grid-row:1;
  font-size:10.5px;
  font-weight:700;
  text-transform:lowercase;
  font-variant:small-caps;
  letter-spacing:.1em;
  color:var(--ink-3);
}
.amm-stat-val{
  grid-row:2;
  margin-top:7px;
  font-size:29px;
  font-weight:800;
  line-height:1.05;
  letter-spacing:-.035em;
  color:var(--ink);
  /* Cifre a larghezza fissa: i cinque numeri stanno in fila e senza questo
     si disallineano ogni volta che un 1 prende il posto di un 8. */
  font-variant-numeric:tabular-nums;
}
/* La riga di dettaglio sotto il numero (il nome dell'artista della serata)
   e' una `.amm-tag`, che e' di 02-controlli.css. Qui le si da' solo il POSTO
   — terza riga, allineata a sinistra — e nient'altro: se questa regola le
   scrivesse anche corpo e colore, batterebbe `.amm-tag` per specificita' e
   la stessa etichetta avrebbe due facce a seconda di dove sta. */
.amm-stat > *:not(.amm-stat-lbl):not(.amm-stat-val){
  grid-column:1 / -1;
  margin-top:7px;
  justify-self:start;
}

/* I due numeri che oggi hanno un colore proprio lo conservano, ma preso
   per posizione e non con una classe nuova: il contratto non me ne assegna
   nessuna per questo, e la posizione nel markup e' stabile (sono cinque
   schede fisse scritte nel documento, non una lista generata).
   · la prima e' il TOTALE: e' la cosa principale della schermata, ed e'
     l'unico posto di questa schermata in cui il giallo di marchio ha diritto
     di comparire;
   · l'ultima e' "multi-giorno", che oggi e' viola (#a78bfa) → `--hold`.  */
.amm-stats > .amm-stat:first-child .amm-stat-val{
  color:var(--accent-text);
}
.amm-stats > .amm-stat:last-child .amm-stat-val{
  color:var(--hold);
}


/* #########################################################################
   G · SCHERMATA «TEMPLATE CONTRATTI»
   ######################################################################### */

/* ----------------------------------------- G.1 · I riquadri di esito ----
   Tre varianti: avviso, errore, riuscito. `display:block` e NON flex: la
   funzione `renderTemplPartialBanner` appende tre <div> dentro lo stesso
   riquadro, e in flex-row finirebbero uno accanto all'altro su una riga.
   L'icona si allinea da sé al testo con `vertical-align`.                 */
.templ-alert{
  padding:11px 14px;
  margin-bottom:10px;
  border-radius:var(--r-sm);
  font-size:12.5px;
  line-height:1.5;
  border:1px solid transparent;
  color:var(--ink-2);
  background:var(--glass-1);
}
.templ-alert .yh-i{
  width:16px;
  height:16px;
  margin-right:7px;
  vertical-align:-3px;
}
/* Il collegamento a GitHub dentro un riquadro riuscito: eredita il colore
   del riquadro invece di essere il blu di sistema, che dentro una fascia
   verde stona e sembra un errore. */
.templ-alert a{
  color:inherit;
  font-weight:700;
  text-decoration:underline;
  text-underline-offset:2px;
}
.templ-alert.warn{
  color:var(--wait);
  background:var(--wait-soft);
  border-color:color-mix(in srgb,var(--wait) 32%,transparent);
}
.templ-alert.danger{
  color:var(--lost);
  background:var(--lost-soft);
  border-color:color-mix(in srgb,var(--lost) 32%,transparent);
}
.templ-alert.ok{
  color:var(--won);
  background:var(--won-soft);
  border-color:color-mix(in srgb,var(--won) 32%,transparent);
}

/* --------------------------------------- G.2 · I collegamenti ai PDF ----
   Stanno in fila e vanno a capo: sono fino a cinque e hanno nomi di file
   lunghi.                                                                 */
.templ-pdf-link{
  display:inline-flex;
  align-items:center;
  gap:7px;
  margin:0 7px 7px 0;
  padding:6px 11px;
  border-radius:var(--r-sm);
  background:var(--glass-2);
  border:1px solid var(--glass-edge);
  color:var(--ink);
  font-size:12px;
  text-decoration:none;
  transition:background var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.templ-pdf-link:hover{
  background:var(--accent-soft);
  border-color:var(--accent-line);
}
.templ-pdf-link .yh-i{
  width:15px;
  height:15px;
  color:var(--ink-3);
}

/* -------------------------------------- G.3 · Il riquadro del codice ----
   Qui dentro c'e' codice JavaScript generato, da rileggere e da copiare in
   `documents-config.js`.

   ⚠️ Il carattere a spaziatura fissa e' l'unica eccezione motivata a
   `font-family:var(--font)!important`, che hub-theme.css impone su `body *`.
   Serve un `!important` per batterlo, e serve perche' qui la spaziatura
   fissa non e' un vezzo tipografico: e' quello che tiene incolonnate le
   rientranze e le coordinate x,y del codice. Ovunque altro
   nell'applicazione il monospaziato e' stato sostituito da Sofia Pro con
   `tabular-nums`, che per delle cifre basta — per del codice no.

   `overflow:auto` sul RIQUADRO: una riga lunga scorre qui dentro e non
   allarga la pagina. `max-height` perche' lo snippet puo' essere di
   duecento righe e non deve seppellire la tabella dei campi che sta sotto.
   Il padding e' uniforme: il pulsante «Copia» non e' piu' appoggiato
   sopra il riquadro (era in posizione assoluta con un padding di 2.6rem a
   fargli posto), adesso sta nella riga di titolo — quindi quel posto
   riservato in alto sarebbe una fascia vuota e basta.                     */
#templSnippetPre{
  margin:0;
  padding:16px;
  max-height:400px;
  overflow:auto;
  border-radius:var(--r-sm);
  background:linear-gradient(var(--glass-2),var(--glass-2)),var(--ground);
  border:1px solid var(--glass-edge);
  color:var(--ink-2);
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono',monospace!important;
  font-size:11.5px;
  line-height:1.65;
  /* Le righe lunghe vanno a capo invece di far scorrere in orizzontale:
     leggere del codice muovendosi di lato e' scomodo, e qui lo si rilegge
     per controllarlo. Lo scorrimento resta per il caso limite (una stringa
     unica senza spazi piu' larga del riquadro). */
  white-space:pre-wrap;
  word-break:break-word;
  tab-size:2;
}
#templSnippetPre::-webkit-scrollbar{ width:10px; height:10px; }
#templSnippetPre::-webkit-scrollbar-track{ background:transparent; }
#templSnippetPre::-webkit-scrollbar-thumb{
  background:var(--glass-3);
  border-radius:var(--r-pill);
}

/* ------------------------------- G.4 · «sostituzione totale / parziale» -
   Due caselle radio che decidono cose molto diverse: rifare un contratto da
   zero o cambiarne un PDF. Vestite da pastiglie selezionabili, non lasciate
   come due pallini in fila: la scelta sbagliata qui riscrive la
   configurazione di un contratto intero.                                  */
.amm-radio-riga{
  display:flex;
  align-items:center;
  gap:9px;
  flex-wrap:wrap;
}
.amm-radio-riga label{
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:8px 13px;
  border-radius:var(--r-sm);
  font-size:12.5px;
  color:var(--ink-2);
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  cursor:pointer;
  transition:color var(--speed) var(--ease),
             background var(--speed) var(--ease),
             border-color var(--speed) var(--ease);
}
.amm-radio-riga label:hover{
  color:var(--ink);
  border-color:var(--glass-edge-hi);
}
/* La scelta attiva si accende da sé: senza, in una fila di due pastiglie
   identiche l'unico segno e' il pallino da 13px. */
.amm-radio-riga label:has(input:checked){
  color:var(--ink);
  background:var(--accent-soft);
  border-color:var(--accent-line);
}
.amm-radio-riga .yh-i{
  width:16px;
  height:16px;
  color:var(--ink-3);
}
.amm-radio-riga label:has(input:checked) .yh-i{
  color:var(--accent-text);
}


/* #########################################################################
   H · MINUZIE CONDIVISE
   ######################################################################### */

/* Riga con due estremi: un titolo (o un testo) a sinistra, un comando o un
   interruttore a destra. Compare in cinque punti, dove oggi c'e' un
   `style="display:flex; justify-content:space-between…"` in linea.
   `flex-wrap` non e' decorazione: su schermo stretto il comando va sotto
   invece di schiacciare il titolo a una parola per riga. */
.amm-riga-tra{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  flex-wrap:wrap;
}


/* #########################################################################
   I · SCHERMO STRETTO
   Solo i selettori di questo foglio. Il comportamento della barra laterale e
   l'impilamento del guscio stanno in 01-guscio.css.
   ######################################################################### */

@media (max-width:640px){

  /* La scheda perde un po' di respiro laterale: su 360px, 18px per parte
     sono un decimo della larghezza utile. */
  body .table-card{
    padding:13px;
  }

  /* La matrice si prende piu' altezza: su un telefono la finestra e' alta e
     stretta, ed e' l'altezza l'unica dimensione che avanza. */
  .matrix-scroll-wrap{
    max-height:calc(100vh - 220px);
    min-height:240px;
  }
  /* La prima colonna si stringe: 200px su uno schermo da 360 lascerebbero
     due colonne di servizi visibili in tutto. */
  #permMatrix tbody td:first-child,
  #tlPermMatrix tbody td:first-child,
  #permMatrix thead th:first-child,
  #tlPermMatrix thead .perm-matrix-col-label{
    min-width:140px;
  }

  /* Una colonna sola: 316px di scheda non ci stanno, e una griglia che non
     ci sta produce lo sbordamento orizzontale della pagina. */
  .amm-tl-grid,
  .perm-grid,
  .amm-grp-srv{
    grid-template-columns:1fr;
  }

  /* I numeri di NewEden restano una fila di due o tre, non una colonna di
     cinque schede alte: una colonna di cinque numeri non si legge piu' come
     una fila di confronto. */
  .amm-stats{
    grid-template-columns:repeat(auto-fit,minmax(112px,1fr));
    gap:9px;
  }
  .amm-stat{
    padding:12px 13px;
  }
  .amm-stat-val{
    font-size:24px;
  }

  /* I comandi di riga a tutta larghezza: due pulsantini affiancati in una
     cella da 100px diventano due bersagli da 45px, sotto il minimo per un
     dito. */
  .actions-cell{
    flex-direction:column;
    align-items:stretch;
  }

  .amm-grp-head{
    padding:13px 14px;
  }
  .amm-grp-body{
    padding:0 14px 14px;
  }
}

/* ---------- 04-rifiniture.css ---------- */
/* =========================================================================
   04 · RIFINITURE — le utilità sparse e i contenitori rimasti senza padrone

   I tre fogli precedenti hanno un tema ciascuno: il guscio, i controlli, i
   contenuti. Questo no: qui stanno le briciole che non appartengono a nessuna
   schermata in particolare, e che il JavaScript emette in mezzo al testo.

   Sono nate tutte dallo stesso lavoro: nel pannello vecchio ognuna di queste
   cose era un colore scritto a mano dentro `admin.js` — `color:#22c55e` per un
   esito buono, `color:#888` per un testo secondario, un cerchietto di 8px
   composto a mano dentro una stringa. Il JavaScript ora emette un nome, e il
   colore lo decide qui: così lo stesso stato ha la stessa faccia in tutte e
   sette le schermate, e in tema chiaro cambia da sé.

   REGOLA DI QUESTO FILE: nessuna di queste classi deve occuparsi di
   posizionamento o di misure di contenitore. Sono aggettivi, non scatole: si
   appiccicano a un elemento che qualcun altro ha già messo al suo posto. Se
   una di queste regole comincia a dichiarare `position` o `width`, è il segno
   che quel pezzo apparteneva a uno degli altri tre fogli.
   ========================================================================= */


/* ------------------------------------------------- 4.1 · Gli esiti --------
   Le tre risposte che il pannello dà dopo un'azione: è andata, non è andata,
   guarda che stai per fare una cosa grossa. Un gettone ciascuna, e mai il
   verde e il rosso scritti a mano: in tema chiaro `--won` e `--lost` si
   scuriscono da soli per restare leggibili sul bianco (contrasto ≥ 4,5:1),
   cosa che `#22c55e` non fa. */
.amm-ok{
  color:var(--won);
  font-weight:600;
}
.amm-ko{
  color:var(--lost);
  font-weight:600;
}
.amm-avviso{
  color:var(--wait);
  font-weight:600;
}

/* L'attesa non è un esito: è un "sto lavorando". Percio' non prende un
   colore di stato — dire "in corso" in verde o in rosso sarebbe una risposta
   che ancora non c'è. Resta testo secondario. */
.amm-attesa{
  color:var(--ink-2);
  font-weight:500;
}

/* L'elenco degli indirizzi a cui la mail non è arrivata. Va sotto il
   messaggio, piu' piccolo, e deve poter andare a capo dentro un indirizzo:
   una fila di email lunghe altrimenti allarga il riquadro e sborda.
   `display:block` perche' nel markup lo precede un <br>: senza, la prima
   riga resterebbe attaccata al messaggio. */
.amm-ko-elenco{
  display:block;
  margin-top:5px;
  color:var(--lost);
  font-size:12px;
  line-height:1.5;
  word-break:break-word;
}

/* La spunta delle adesioni. È l'unica cosa in tutta la tabella che dice
   "sì": va vista in mezzo a una colonna di trattini, quindi piena. */
.amm-si{
  color:var(--won);
  font-weight:700;
}


/* ------------------------------------------- 4.2 · Il testo di secondo piano
   `--ink-3` è il grigio dei gettoni: quello che nel pannello vecchio era
   `#888` in ventisei punti e `#666` in altri otto, con la conseguenza che due
   testi con lo stesso ruolo avevano due grigi diversi.

   `.amm-muto` conserva il corsivo dove il markup usa un <i>: lì il corsivo ha
   un senso preciso — sta al posto di un nome che manca, e si legge come "non
   è un nome, è un codice". Non lo raddrizzo. */
.amm-muto{
  color:var(--ink-3);
}

/* Il trattino che sta al posto di un dato assente. Cifre a larghezza fissa
   perche' in una colonna di numeri il trattino deve stare incolonnato con
   loro, non piu' stretto. */
.amm-vuoto{
  color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}

/* Il viola dei gettoni: nel pannello sta per "eccezione", cioè un permesso
   deciso sulla singola persona che scavalca la regola della squadra. Era
   `#a855f7` e `#8A2BE2` — due viola diversi per la stessa idea. */
.amm-hold{
  color:var(--hold);
  font-weight:600;
}


/* -------------------------------------- 4.3 · Il pallino e l'incolonnamento
   `.amm-pallino` prende il colore da chi lo contiene (`currentColor`): è il
   motivo per cui una sola regola basta per tutti i suoi usi. Nel badge
   dell'ultimo accesso vive dentro `.amm-visto.amm-vivo` e viene verde da solo;
   nella matrice del consulente ha bisogno di dirlo per conto suo, e allora
   arriva con `.ok` o `.ko`.

   Senza `flex:0 0 auto` il pallino si schiaccia quando l'etichetta accanto è
   lunga, e da tondo diventa un ovale. */
.amm-pallino{
  display:inline-block;
  flex:0 0 auto;
  width:8px;
  height:8px;
  border-radius:50%;
  background:currentColor;
}
.amm-pallino.ok{ color:var(--won); }
.amm-pallino.ko{ color:var(--lost); }

/* Il badge dell'ultimo accesso: "Online", "12 min fa", "3 ore fa", "Mai
   connesso". Qui c'è solo la disposizione — pallino e testo sulla stessa
   riga, senza andare a capo. Il COLORE lo danno le quattro classi del tempo
   (`amm-vivo`, `amm-recente`, `amm-lontano`, `amm-mai`), che stanno nel foglio dei
   contenuti insieme agli altri stati delle tabelle. */
.amm-visto{
  display:inline-flex;
  align-items:center;
  gap:6px;
  white-space:nowrap;
  font-variant-numeric:tabular-nums;
}

/* Centratura. Serve un selettore piu' specifico per le celle, perche'
   `hub-theme.css` allinea a sinistra `.data-table th` e `.data-table td` con
   specificita' (0,1,1): un `.amm-ctr` nudo (0,1,0) perderebbe, e le colonne
   "19/20/21 Giu" delle adesioni resterebbero a sinistra sopra numeri
   centrati. */
.amm-ctr{ text-align:center; }
.data-table th.amm-ctr,
.data-table td.amm-ctr,
.mx th.amm-ctr,
.mx td.amm-ctr{ text-align:center; }


/* ------------------------------------------- 4.4 · Il piede delle finestre
   La riga dei pulsanti in fondo a un modale. Vale per il modale che il
   JavaScript costruisce da zero ("Aggiungi Team"), l'unico che non esiste
   nel markup della pagina.
   I pulsanti stanno a DESTRA, e in quest'ordine: prima "Annulla", poi
   l'azione. È l'ordine che hanno già le tre finestre scritte nella pagina —
   se qui fosse rovesciato, il pannello avrebbe due convenzioni. */
.amm-modal-azioni{
  display:flex;
  justify-content:flex-end;
  gap:9px;
  margin-top:18px;
  padding-top:15px;
  border-top:1px solid var(--glass-edge);
}
/* Su schermo stretto i due pulsanti in fila non ci stanno e si stringono
   fino a spezzare la parola: meglio uno sopra l'altro, con l'azione in cima
   perche' è quella che si cerca. */
@media (max-width:520px){
  .amm-modal-azioni{
    flex-direction:column-reverse;
  }
  .amm-modal-azioni > button{ width:100%; }
}


/* ------------------------------------ 4.5 · Tre contenitori senza padrone
   Non appartengono a nessuna delle tre famiglie: sono scatole che il
   JavaScript riempie e che nel pannello vecchio avevano il loro aspetto
   scritto nell'attributo `style` del markup. Togliendo quegli attributi
   sarebbero rimaste senza niente. */

/* Il pannello dei permessi di un singolo consulente: appare sotto la ricerca
   quando se ne scegle uno, e sparisce quando non c'è nessuno scelto (è il
   JavaScript a mostrarlo con `style.display`, quindi qui NON si dichiara
   display: se lo dichiarassi vincerebbe l'attributo in linea e andrebbe
   bene, ma il giorno che qualcuno lo togliesse resterebbe acceso per sempre). */
#permConsPanel{
  margin-top:16px;
}

/* Il riquadro delle caselle "a quali squadre appartiene": una lista che puo'
   diventare lunga, quindi scorre per conto suo invece di allungare la
   finestra. Le caselle dentro sono `.amm-check`, vestite nel foglio dei
   controlli: qui c'è solo la scatola che le contiene. */
#tlTeamCheckboxes{
  display:flex;
  flex-wrap:wrap;
  gap:7px;
  padding:11px;
  min-height:52px;
  max-height:200px;
  overflow-y:auto;
  background:var(--glass-1);
  border:1px solid var(--glass-edge);
  border-radius:var(--r-md);
}
/* Quando è vuoto non deve sembrare rotto: il riquadro vuoto con l'altezza
   minima si legge come "qui ci andranno delle cose", che è la verita'. */

/* L'elenco delle squadre nella finestra "Gestisci Team". Le pastiglie dentro
   sono `.team-pill`, vestite nel foglio dei contenuti. */
#teamsList{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
}


/* --------------------------------- 4.6 · Tre briciole della schermata Template
   Stanno qui e non nel foglio dei contenuti per una ragione sola: non
   descrivono un pezzo di quella schermata, sono tre aggettivi che il
   JavaScript appiccica a elementi costruiti al volo. */

/* Il titolo dentro un riquadro di esito ("Sostituzione parziale",
   "Inserimento manuale richiesto"). Non prende un colore: lo EREDITA dal
   riquadro che lo contiene, che sa già se è un avviso o un errore. Dargliene
   uno qui vorrebbe dire ripetere in due posti la stessa decisione. */
.amm-templ-tit{
  display:block;
  margin-bottom:5px;
  font-weight:700;
  font-size:13px;
}

/* Il collegamento a un file appena caricato o al commit. Stessa idea:
   `color:inherit` perche' vive dentro un riquadro verde o rosso e deve
   essere di quel colore. La sottolineatura staccata dal testo si legge
   meglio su fondo colorato di quella attaccata. */
.amm-templ-link{
  color:inherit;
  font-weight:700;
  text-decoration:underline;
  text-underline-offset:2px;
}
.amm-templ-link:hover{
  text-decoration-thickness:2px;
}

/* Lo stacco fra due blocchi di esito impilati. Era `marginTop` scritto in
   linea in tre punti, con tre valori diversi. */
.amm-stacco{
  margin-top:16px;
}


/* ------------------------------- 4.7 · La parola accanto a un interruttore
   Nelle righe servizio dei gruppi la riga dice tre cose: il nome del
   servizio a sinistra, poi la parola dello stato, poi l'interruttore.
   `.amm-grp-riga` (foglio dei contenuti) li distribuisce con space-between, e
   con tre figli la parola finirebbe a meta' strada, staccata dall'
   interruttore che sta descrivendo. `margin-left:auto` la incolla al suo
   interruttore e lascia il nome del servizio da solo a sinistra.

   E' l'unico punto in cui questo file nomina una classe di un altro foglio,
   e lo fa solo per dire dove va una cosa SUA (`.amm-muto`) quando si trova
   dentro quella. */
.amm-grp-riga > .amm-muto{
  margin-left:auto;
  margin-right:9px;
  font-size:11.5px;
  white-space:nowrap;
}
