
/* ═══════════════════════════════════════════════════════════════════════════
   LA TAVOLOZZA DI STATO DEL PROGETTO — verde, arancio, rosso. Tre, una volta sola.
   ---------------------------------------------------------------------------
   PULSAR ha una palette SEMANTICA (`--n-bg-*`, `--n-tx-*`, `--n-ac`) e non ha i
   colori di STATO: non e' una dimenticanza della scatola, e' che «andato bene» e
   «andato male» sono concetti dell'applicazione, non del framework. Quindi li
   dichiara il foglio del progetto — ma UNA VOLTA, qui.

   ⚠️ Prima erano sparsi: #2e9e6b nel foglio permessi, lo stesso verde riscritto
   nei messaggi, #d64545 in tre punti piu' uno dentro un componente della
   scatola. Otto esadecimali per tre colori. Non da' un errore: da' due verdi che
   si somigliano abbastanza da non notarsi e abbastanza da non essere lo stesso,
   e il giorno in cui si cambia la tinta se ne cambia uno e mezzo.

   ⚠️ LE VARIANTI SOFT ESISTONO PERCHE' UN FONDO NON E' UN INCHIOSTRO. Lo stesso
   verde che si legge su un testo, steso su una cella, diventa una scacchiera.
     --v-ok / --v-warn / --v-err          il SEGNO: icone, bordi, barre
     --v-ok-ink / ...                     il TESTO su fondo soft — piu' scuro
     --v-ok-soft / ...                    il VELO: fondi di cella, riquadri
     --v-ok-bd / ...                      il bordo dei riquadri

   ⚠️ L'INCHIOSTRO E' UN GRADINO A PARTE, e non e' pignoleria tipografica:
   #2e9e6b su un velo verde chiaro da' 3,2:1, sotto il 4,5:1 che un testo di
   14px richiede. Lo stesso verde va benissimo per un'ICONA (che e' una forma, e
   il requisito e' 3:1) e non per una FRASE. Un solo valore per tutti e due
   costringe a scegliere fra un segno smorto e un testo che non si legge.

   ⚠️ E AL BUIO non si scuriscono: si ALZA l'inchiostro e si abbassa il velo. Un
   verde scuro su fondo scuro sparisce.

   ⚠️ I componenti della SCATOLA le leggono con un ripiego — `var(--v-ok,#2e9e6b)`
   — perche' non possono dipendere dal CSS di un progetto: senza questo foglio usano il
   valore scritto, con questo foglio seguono la tavolozza. Stessa forma dei `--n-*`.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
    --v-ok:        #2e9e6b;
    --v-ok-ink:    #196845;
    --v-ok-soft:   rgba(46, 158, 107, .07);
    --v-ok-bd:     #cfe9dd;
    --v-warn:      #c98a12;
    --v-warn-ink:  #7a5104;
    --v-warn-soft: rgba(201, 138, 18, .07);
    --v-warn-bd:   #efdfba;
    --v-err:       #d64545;
    --v-err-ink:   #9d2525;
    --v-err-soft:  rgba(214, 69, 69, .07);
    --v-err-bd:    #f2d2d2;
}
/* ⚠️ IL TEMA DELLA PAGINA, NON QUELLO DEL SISTEMA.
   `@media (prefers-color-scheme: dark)` da solo guarda il sistema operativo di
   chi guarda — e sbaglia ogni volta che i due non coincidono: con il sistema in
   scuro e la pagina in chiaro (l'interruttore del tema e' li' apposta) si
   prendeva l'inchiostro CHIARO su un fondo CHIARO, cioe' un testo verde pallido
   illeggibile. E' successo davvero, ed e' l'unico modo in cui questo difetto si
   manifesta: mai a chi ha sistema e pagina d'accordo.

   La forma giusta e' quella di PULSAR: la classe decide, e il media query vale
   SOLO per `auto`, che e' il caso in cui la pagina ha dichiarato di seguire il
   sistema. */
:where(.theme-dark) {
    --v-ok:        #4cc78d;
    --v-ok-ink:    #6fd7a6;
    --v-ok-soft:   rgba(46, 158, 107, .13);
    --v-ok-bd:     rgba(46, 158, 107, .32);
    --v-warn:      #e0ab3c;
    --v-warn-ink:  #edc061;
    --v-warn-soft: rgba(201, 138, 18, .14);
    --v-warn-bd:   rgba(201, 138, 18, .34);
    --v-err:       #ef7676;
    --v-err-ink:   #f79a9a;
    --v-err-soft:  rgba(214, 69, 69, .14);
    --v-err-bd:    rgba(214, 69, 69, .34);
}
@media (prefers-color-scheme: dark) {
    :where(.theme-auto) {
        --v-ok:        #4cc78d;
        --v-ok-ink:    #6fd7a6;
        --v-ok-soft:   rgba(46, 158, 107, .13);
        --v-ok-bd:     rgba(46, 158, 107, .32);
        --v-warn:      #e0ab3c;
        --v-warn-ink:  #edc061;
        --v-warn-soft: rgba(201, 138, 18, .14);
        --v-warn-bd:   rgba(201, 138, 18, .34);
        --v-err:       #ef7676;
        --v-err-ink:   #f79a9a;
        --v-err-soft:  rgba(214, 69, 69, .14);
        --v-err-bd:    rgba(214, 69, 69, .34);
    }
}
/* ===========================================================================
   LA PALETTE DEL PROGETTO
   ---------------------------------------------------------------------------
   ⚠️ I VALORI NON SI INVENTANO: sono misurati dalle due schermate di riferimento (schermate/new/screen_dark.png e
   screen_light.png). Il fatto che sorprende: l'accento e' #1362fc e NON cambia
   fra chiaro e scuro — qui va scritto lo stesso valore due volte.
   ---------------------------------------------------------------------------
   Qui NON si scrivono classi: si RIDICHIARANO le variabili della palette di
   PULSAR. È l'unica strada che funziona, e il motivo sta in PULSAR.md: le classi
   che PULSAR genera sono HASHATE (.n-x7k2a), quindi non sono un bersaglio che un
   foglio possa scrivere o indovinare. I colori invece passano tutti da
   var(--n-…), e quelle si possono ridichiarare.

   La conseguenza buona: una view scritta oggi con css="bg-1 tx-0" seguirà i
   colori del progetto DA SÉ, senza essere toccata. Anche fra due anni.

   ⚠️ NON si inventano token. `css="bg-sociale2"` non esiste: PULSAR non lo
   conosce, quindi finisce come commento nel foglio e la regola non c'è — senza
   un errore, senza un test rosso. Un colore del progetto vive solo in due modi:
     1. ridefinendo un RUOLO qui sotto  → tutte le view lo seguono;
     2. in una classe scritta a mano, usata con class="…" e non con css="…"
        → funziona, ma sta FUORI da PULSAR: niente slash responsive (cols-1/2),
          niente varianti di stato (hover:tx-ac).
   La 1 è quasi sempre quella giusta.

   I RUOLI, e cosa coprono davvero:

     --n-bg-0   il fondo della pagina
     --n-bg-1   le superfici sopra il fondo (card, riquadri, avvisi)
     --n-bg-2   il terzo livello (righe alternate, celle in evidenza)
     --n-bg-w   il bianco VOLUTO: resta bianco in entrambi i temi (una stampa)
     --n-tx-0   il testo normale
     --n-tx-1   il testo secondario
     --n-tx-2   il testo terziario (note, diciture)
     --n-tx-w   «massimo contrasto»: NON è bianco, è bianco sul buio e quasi-nero
                sul chiaro. Fissarlo a #fff lo fa sparire sul tema chiaro
     --n-ink    il testo SOPRA l'accento
     --n-ac     L'ACCENTO — link, bottoni, evidenze. Una variabile per tutti
     --n-bd     il bordo (bd bt bb bl br)

   SULLA TUA LISTA. È fatta per componenti (link, tasti); PULSAR ragiona per
   ruoli, e la traduzione toglie roba invece di aggiungerne:

     color link      ┐
     color tasti     ┴─→  --n-ac         una sola variabile, li copre entrambi
     color link hover ──→  NON è una variabile: in PULSAR lo stato è una
     color tasti hover     VARIANTE del token — hover:tx-ac, hover:op-80 — che
                           si scrive nella view, non qui
     sociale1        ──→  se è il colore guida del progetto, è --n-ac
     sociale2        ──→  questo sì è nuovo: vedi il blocco in fondo

   COME SI COMPILA. Quattro blocchi e non due, perché `auto` ha bisogno di
   entrambe le facce: la classe sul <body> la mette lo scheletro da DISPLAY_MODE
   (theme-light | theme-dark | theme-auto) e su `auto` è la media query a
   decidere — senza JavaScript, già alla prima visita.

   TOGLI IL COMMENTO a ciò che il progetto decide, e LASCIA COMMENTATO il resto: un
   valore ricopiato qui uguale a quello di NOVA non è neutro — il giorno che NOVA
   cambia i suoi default, questa copia li sovrascrive in silenzio.
   =========================================================================== */

/* ⚠️ NOVA e il riferimento ordinano le superfici in modo OPPOSTO nel chiaro.
   Nella palette di NOVA `--n-bg-0` (la pagina) e' BIANCO e `--n-bg-1` (le card)
   e' grigino. Nel riferimento e' il contrario, misurato dai due PNG: pagina
   #eeedef, card #ffffff — e si vede perche' funziona meglio, le schede
   "galleggiano" sul fondo invece di confondersi.
   Nel tema scuro invece i due ordini coincidono gia'. */

/* --- TEMA SCURO ---------------------------------------------------------- */
.theme-dark {
    --n-bg-0: #171622;   /* la pagina        (misurato) */
    --n-bg-1: #212130;   /* card, sidebar, topbar — un solo livello sopra */
    --n-bg-2: #2a2a3c;   /* righe alternate, campi in rilievo */
    --n-bd:   #2f2f42;
    /* Gli stati: nello SCURO i segni si leggono da sé, non serve l'inchiostro. */
    --n-ok:   var(--v-ok);
    --n-warn: var(--v-warn);
    --n-err:  var(--v-err);

    --v-titolo: #ccd4da;

    /* Il fondale del vetro, versione scura — vedi la nota nel blocco chiaro.
       ⚠️ Gli alpha sono PIU' BASSI, non piu' alti: su un fondo #212130 lo stesso
       42% del chiaro darebbe tre macchie luminose invece di un alone, e il testo
       delle voci ci finirebbe sopra. Il vetro scuro si fa togliendo, non
       aggiungendo. */
    /* Il filo del pannello, versione scura. ⚠️ Un bianco PIENO qui trasforma le
       schede in scatole contornate — l'occhio legge il contorno prima del
       contenuto. Provato, e si vede al primo sguardo.
       ⚠️ E non e' nemmeno bianco VELATO: un grigio medio al 14% invece del bianco
       al 14%. Sullo scuro il bianco, anche a bassa opacita', resta un bordo che
       si annuncia; il grigio si limita a staccare il pannello dal fondale, che e'
       tutto quello che deve fare. Il chiaro tiene il bianco pieno, perche' li'
       il filo ha il compito opposto — dare una forma a una scheda quasi bianca
       su un fondale chiaro. */
    --v-vetro-lettura-bd: rgba(106, 106, 106, .14);
    /* Il vetro di lettura, versione scura — vedi la nota nel blocco chiaro.
       ⚠️ NON e' il bianco del chiaro con un altro alpha: su un fondo scuro un
       velo bianco schiarisce il pannello invece di darle un fondo, e il testo
       chiaro ci finisce sopra con meno contrasto di prima. Qui il vetro e' la
       SUPERFICIE scura, un filo piu' chiara del fondo pagina perche' un pannello
       deve galleggiare. All'81 dal 09/10/2026: lo stesso passo del chiaro
       (52 → 75, +23), vedi la nota la'. */
    --v-vetro-lettura: rgba(38, 38, 56, .81);
    /* La tendina, versione scura — vedi la nota nel blocco chiaro.
       ⚠️ Qui e' `--n-bg-2` e non `--n-bg-1`: nello scuro `bg-1` e' la stessa
       tinta della sidebar e dei pannelli, e una tendina che si apre sopra la
       colonna sparirebbe dentro di lei. `bg-2` e' un gradino piu' chiara, che e'
       cio' che nel chiaro fa gia' il bianco contro il grigio della pagina. */
    --v-tendina: var(--n-bg-2);
    /* Il rilievo, versione scura — e qui e' un'OMBRA vera, nera. Il giro e'
       simmetrico: nel chiaro si stacca schiarendo attorno, nello scuro
       scurendo. Un alone bianco su un fondo #171622 sarebbe un bagliore, cioe'
       l'oggetto sembrerebbe acceso invece che sollevato. */
    --v-rilievo: 0 2px 8px -3px rgba(0, 0, 0, .60);
    /* Il rilievo del pannello, versione scura — vedi la nota nel blocco chiaro. */
    --v-rilievo-pannello: 0 2px 8px -3px rgba(0, 0, 0, .60);
    --v-vetro-a:    rgba( 70, 160, 225, .28);
    --v-vetro-b:    rgba(118, 104, 222, .26);
    --v-vetro-c:    rgba( 60, 190, 205, .23);  /* i titoli di blocco: vedi il blocco chiaro */
    /* Le stesse tre opacita', staccate dal colore: servono alle sezioni, che
       rifanno lo STESSO fondale con la propria tinta. Vedi «il fondale segue la
       sezione» piu' sotto. Qui e non li' perche' il valore e' del TEMA. */
    --v-vetro-qa: 28%;  --v-vetro-qb: 26%;  --v-vetro-qc: 23%;
    /* ⚠️ --n-ac e --n-ink NON si ridichiarano, ed e' una scelta voluta:
       il blu misurato nel riferimento (#1362fc) e' piu' carico di quello di
       NOVA, e a video risulta pesante su una pagina fitta di comandi. Restano
       quelli della scatola — #6abaea qui, #1a86bd nel chiaro.
       E se un giorno si riprende un accento carico, `--n-ink` va riportato a
       #fff INSIEME: nello scuro il default e' #111, che su un blu profondo e'
       illeggibile. Le due variabili si muovono in coppia, sempre. */
}

/* --- TEMA CHIARO --------------------------------------------------------- */
.theme-light {
    --n-bg-0: #eeedef;   /* la pagina        (misurato) */
    --n-bg-1: #ffffff;   /* le card: BIANCHE (misurato) */
    --n-bg-2: #f5f5f5;   /* righe alternate  (misurato) */
    --n-bd:   #e4e6ea;
    /* ⚠️ I TRE RUOLI DI STATO DELLA SCATOLA, mappati sulla tavolozza del progetto.
       `tx-err`, `bd-ok`, `tx-warn` di PULSAR passano tutti da queste tre
       variabili: dichiararle qui significa che OGNI campo del progetto — in
       qualunque componente, anche in uno che nascerà domani — dice «sbagliato»
       e «verificato» coi colori di casa, senza una riga in più.
       ⚠️ Nel CHIARO si usano gli INCHIOSTRI (`-ink`), non i segni: #2e9e6b su
       bianco è 3,4:1, sotto il 4,5:1 che un testo di 13px pretende. Nello scuro
       i segni bastano da soli (il peggiore è #ef7676 a 5,0:1). */
    --n-ok:   var(--v-ok-ink);
    --n-warn: var(--v-warn-ink);
    --n-err:  var(--v-err-ink);

    /* ⚠️ IL COLORE DEI TITOLI DI BLOCCO (h2), e sta qui perche' NON e' nessuno
       dei ruoli: `--n-tx-0` sul chiaro e' #14181a, cioe' nero praticamente
       pieno, e `--n-tx-1` (#5b6670) e' troppo tenue per un titolo. Serviva un
       nero SMORZATO, e un valore che non e' un ruolo vive qui.
       ⚠️ E vive in TUTTI E QUATTRO i blocchi: un #444 dichiarato solo nel chiaro
       renderebbe i titoli illeggibili sul fondo scuro, senza un errore. */
    --v-titolo: #444;

    /* ⚠️ IL FONDALE DEL VETRO — decorativo, e con variabili SUE.
       Non si appoggiano a `--n-ac` ne' a `--v-ok`: quelle dicono «il comando» e
       «riuscito». Legarci l'aspetto della sidebar vorrebbe dire che il giorno
       che si ritocca il verde del successo cambia anche il fondale, e nessuno
       collegherebbe le due cose. Un valore decorativo vive in una variabile
       decorativa.
       La base e' il colore della superficie: dove i blob non arrivano, il vetro
       deve leggersi come la sidebar di sempre. */
    /* ⚠️ IL FILO DEL PANNELLO — bianco nel chiaro: e' cio' che stacca una scheda
       quasi bianca da un fondale chiaro e colorato. Senza, il bordo sfuma nel
       nulla e la scheda perde la forma.
       ⚠️ Ma VELATO, non pieno: al 100% il filo diventava una cornice: si leggeva
       prima del contenuto, che e' lo stesso difetto per cui nello scuro il bianco
       e' stato sostituito da un grigio. Al 63% fa il suo lavoro e sta zitto. */
    --v-vetro-lettura-bd: rgba(255, 255, 255, .63);
    /* ⚠️ IL VETRO DI UN PANNELLO DI LETTURA — bianco al 75%.
       Era al 52, misurato sul gradiente tenue: su quel fondale
       sotto il 40% il testo lungo faticava e sopra il 65% il vetro spariva. Ma
       su un fondale forte (una trama, uno sfondo pieno) il 52 lascia passare
       troppo, e con la sfocatura scesa a 4px il vetro si riconosce dalla
       trasparenza dei bordi e del fondale, non dal latte: il 75 e' la misura
       in cui si legge anche li'. Il parallelo scuro sale dello stesso passo. */
    --v-vetro-lettura: rgba(255, 255, 255, .75);
    /* ⚠️ UNA TENDINA E' PIENA, NON DI VETRO. E' stata all'85% per qualche ora, ed
       era gia' il valore piu' carico di tutte le superfici — perche' una tendina
       galleggia sopra il CONTENUTO, non sul fondale: sotto ci passano righe di
       tabella e testo, e il minimo di trasparenza li lascia leggere attraverso.
       Due scritte sovrapposte sono il modo piu' rapido di rendere illeggibile un
       menu, e su un menu si legge per forza.
       Stessa postura della sidebar, tornata piena il 25/09: cio' su cui si deve
       leggere e agire sta su una superficie ferma. Il vetro resta ai pannelli. */
    --v-tendina: var(--n-bg-1);
    /* ⚠️ IL RILIEVO NEL CHIARO E' UN ALONE BIANCO, NON UN'OMBRA.
       E' la differenza fra le due meta' del tema, non un numero diverso: su un
       fondale chiaro e colorato un nero al 20% sporca: si legge come una macchia
       sotto l'oggetto, e piu' il fondale prende colore piu' si nota. Un alone di
       BIANCO fa il lavoro opposto e giusto — schiarisce il fondale attorno al
       bordo, come una luce che ci batte sopra, e l'oggetto si stacca senza che
       venga aggiunto sporco.
       ⚠️ Si vede solo dove il fondale e' COLORATO: su una zona gia' bianca un
       alone bianco non ha niente da schiarire. Non e' un difetto, e' la natura
       della cosa — ed e' anche perche' funziona solo da quando la pagina ha un
       fondale.
       E' una variabile e non un token perche' le ombre di PULSAR
       (`shadow-sm/md/lg`) hanno il nero FISSO a `rgba(0,0,0,.1)`: un elemento
       che su un tema si stacca e sull'altro no non da' nessun errore — da'
       un'interfaccia piatta a meta'. */
    --v-rilievo: 0 2px 10px -1px rgba(255, 255, 255, .25);
    /* ⚠️ Stessa ombra, un filo piu' carica: un PANNELLO e' grande e deve
       staccarsi da piu' lontano di una pastiglia. E' l'unica differenza — forma,
       raggio e tinta sono gli stessi, perche' due oggetti che galleggiano sulla
       stessa superficie devono galleggiare allo stesso MODO. Se qui ci finisse
       un'ombra di forma diversa i pannelli sembrerebbero illuminati da un'altra
       parte, ed e' il genere di stonatura che si sente senza saperla nominare. */
    --v-rilievo-pannello: 0 2px 10px -1px rgba(255, 255, 255, .35);
    --v-vetro-a:    rgba( 60, 170, 225, .18);
    --v-vetro-b:    rgba(120, 110, 225, .15);
    --v-vetro-c:    rgba( 70, 205, 220, .16);
    --v-vetro-qa: 18%;  --v-vetro-qb: 15%;  --v-vetro-qc: 16%;
    /* --n-ac e --n-ink: vedi la nota nel tema scuro */
}

/* --- AUTO: di base e' CHIARO... ------------------------------------------ */
.theme-auto {
    --n-bg-0: #eeedef;
    --n-bg-1: #ffffff;
    --n-bg-2: #f5f5f5;
    --n-bd:   #e4e6ea;
    /* ⚠️ I TRE RUOLI DI STATO DELLA SCATOLA, mappati sulla tavolozza del progetto.
       `tx-err`, `bd-ok`, `tx-warn` di PULSAR passano tutti da queste tre
       variabili: dichiararle qui significa che OGNI campo del progetto — in
       qualunque componente, anche in uno che nascerà domani — dice «sbagliato»
       e «verificato» coi colori di casa, senza una riga in più.
       ⚠️ Nel CHIARO si usano gli INCHIOSTRI (`-ink`), non i segni: #2e9e6b su
       bianco è 3,4:1, sotto il 4,5:1 che un testo di 13px pretende. Nello scuro
       i segni bastano da soli (il peggiore è #ef7676 a 5,0:1). */
    --n-ok:   var(--v-ok-ink);
    --n-warn: var(--v-warn-ink);
    --n-err:  var(--v-err-ink);

    --v-titolo: #444;

    /* ⚠️ IL FONDALE DEL VETRO — decorativo, e con variabili SUE.
       Non si appoggiano a `--n-ac` ne' a `--v-ok`: quelle dicono «il comando» e
       «riuscito». Legarci l'aspetto della sidebar vorrebbe dire che il giorno
       che si ritocca il verde del successo cambia anche il fondale, e nessuno
       collegherebbe le due cose. Un valore decorativo vive in una variabile
       decorativa.
       La base e' il colore della superficie: dove i blob non arrivano, il vetro
       deve leggersi come la sidebar di sempre. */
    /* ⚠️ IL FILO DEL PANNELLO — bianco nel chiaro: e' cio' che stacca una scheda
       quasi bianca da un fondale chiaro e colorato. Senza, il bordo sfuma nel
       nulla e la scheda perde la forma.
       ⚠️ Ma VELATO, non pieno: al 100% il filo diventava una cornice: si leggeva
       prima del contenuto, che e' lo stesso difetto per cui nello scuro il bianco
       e' stato sostituito da un grigio. Al 63% fa il suo lavoro e sta zitto. */
    --v-vetro-lettura-bd: rgba(255, 255, 255, .63);
    /* ⚠️ IL VETRO DI UN PANNELLO DI LETTURA — bianco al 75%.
       Era al 52, misurato sul gradiente tenue: su quel fondale
       sotto il 40% il testo lungo faticava e sopra il 65% il vetro spariva. Ma
       su un fondale forte (una trama, uno sfondo pieno) il 52 lascia passare
       troppo, e con la sfocatura scesa a 4px il vetro si riconosce dalla
       trasparenza dei bordi e del fondale, non dal latte: il 75 e' la misura
       in cui si legge anche li'. Il parallelo scuro sale dello stesso passo. */
    --v-vetro-lettura: rgba(255, 255, 255, .75);
    /* ⚠️ UNA TENDINA E' PIENA, NON DI VETRO. E' stata all'85% per qualche ora, ed
       era gia' il valore piu' carico di tutte le superfici — perche' una tendina
       galleggia sopra il CONTENUTO, non sul fondale: sotto ci passano righe di
       tabella e testo, e il minimo di trasparenza li lascia leggere attraverso.
       Due scritte sovrapposte sono il modo piu' rapido di rendere illeggibile un
       menu, e su un menu si legge per forza.
       Stessa postura della sidebar, tornata piena il 25/09: cio' su cui si deve
       leggere e agire sta su una superficie ferma. Il vetro resta ai pannelli. */
    --v-tendina: var(--n-bg-1);
    /* ⚠️ IL RILIEVO NEL CHIARO E' UN ALONE BIANCO, NON UN'OMBRA.
       E' la differenza fra le due meta' del tema, non un numero diverso: su un
       fondale chiaro e colorato un nero al 20% sporca: si legge come una macchia
       sotto l'oggetto, e piu' il fondale prende colore piu' si nota. Un alone di
       BIANCO fa il lavoro opposto e giusto — schiarisce il fondale attorno al
       bordo, come una luce che ci batte sopra, e l'oggetto si stacca senza che
       venga aggiunto sporco.
       ⚠️ Si vede solo dove il fondale e' COLORATO: su una zona gia' bianca un
       alone bianco non ha niente da schiarire. Non e' un difetto, e' la natura
       della cosa — ed e' anche perche' funziona solo da quando la pagina ha un
       fondale.
       E' una variabile e non un token perche' le ombre di PULSAR
       (`shadow-sm/md/lg`) hanno il nero FISSO a `rgba(0,0,0,.1)`: un elemento
       che su un tema si stacca e sull'altro no non da' nessun errore — da'
       un'interfaccia piatta a meta'. */
    --v-rilievo: 0 2px 10px -1px rgba(255, 255, 255, .25);
    /* ⚠️ Stessa ombra, un filo piu' carica: un PANNELLO e' grande e deve
       staccarsi da piu' lontano di una pastiglia. E' l'unica differenza — forma,
       raggio e tinta sono gli stessi, perche' due oggetti che galleggiano sulla
       stessa superficie devono galleggiare allo stesso MODO. Se qui ci finisse
       un'ombra di forma diversa i pannelli sembrerebbero illuminati da un'altra
       parte, ed e' il genere di stonatura che si sente senza saperla nominare. */
    --v-rilievo-pannello: 0 2px 10px -1px rgba(255, 255, 255, .35);
    --v-vetro-a:    rgba( 60, 170, 225, .18);
    --v-vetro-b:    rgba(120, 110, 225, .15);
    --v-vetro-c:    rgba( 70, 205, 220, .16);
    --v-vetro-qa: 18%;  --v-vetro-qb: 15%;  --v-vetro-qc: 16%;
}

/* --- ...e diventa scuro se il sistema di chi guarda lo e' ----------------- */
@media (prefers-color-scheme: dark) {
    .theme-auto {
        --n-bg-0: #171622;
        --n-bg-1: #212130;
        --n-bg-2: #2a2a3c;
        --n-bd:   #2f2f42;
        /* Gli stati: nello SCURO i segni si leggono da sé, non serve l'inchiostro. */
        --n-ok:   var(--v-ok);
        --n-warn: var(--v-warn);
        --n-err:  var(--v-err);

        --v-titolo: #ccd4da;

        /* Il fondale del vetro, versione scura — vedi la nota nel blocco chiaro. */
        /* Il filo del pannello, versione scura. ⚠️ Un bianco PIENO qui trasforma le
       schede in scatole contornate — l'occhio legge il contorno prima del
       contenuto. Provato, e si vede al primo sguardo.
       ⚠️ E non e' nemmeno bianco VELATO: un grigio medio al 14% invece del bianco
       al 14%. Sullo scuro il bianco, anche a bassa opacita', resta un bordo che
       si annuncia; il grigio si limita a staccare il pannello dal fondale, che e'
       tutto quello che deve fare. Il chiaro tiene il bianco pieno, perche' li'
       il filo ha il compito opposto — dare una forma a una scheda quasi bianca
       su un fondale chiaro. */
    --v-vetro-lettura-bd: rgba(106, 106, 106, .14);
    /* Il vetro di lettura, versione scura — vedi la nota nel blocco chiaro.
       ⚠️ NON e' il bianco del chiaro con un altro alpha: su un fondo scuro un
       velo bianco schiarisce il pannello invece di darle un fondo, e il testo
       chiaro ci finisce sopra con meno contrasto di prima. Qui il vetro e' la
       SUPERFICIE scura, un filo piu' chiara del fondo pagina perche' un pannello
       deve galleggiare. All'81 dal 09/10/2026: lo stesso passo del chiaro
       (52 → 75, +23), vedi la nota la'. */
    --v-vetro-lettura: rgba(38, 38, 56, .81);
    /* La tendina, versione scura — vedi la nota nel blocco chiaro.
       ⚠️ Qui e' `--n-bg-2` e non `--n-bg-1`: nello scuro `bg-1` e' la stessa
       tinta della sidebar e dei pannelli, e una tendina che si apre sopra la
       colonna sparirebbe dentro di lei. `bg-2` e' un gradino piu' chiara, che e'
       cio' che nel chiaro fa gia' il bianco contro il grigio della pagina. */
    --v-tendina: var(--n-bg-2);
    /* Il rilievo, versione scura — e qui e' un'OMBRA vera, nera. Il giro e'
       simmetrico: nel chiaro si stacca schiarendo attorno, nello scuro
       scurendo. Un alone bianco su un fondo #171622 sarebbe un bagliore, cioe'
       l'oggetto sembrerebbe acceso invece che sollevato. */
    --v-rilievo: 0 2px 8px -3px rgba(0, 0, 0, .60);
    /* Il rilievo del pannello, versione scura — vedi la nota nel blocco chiaro. */
    --v-rilievo-pannello: 0 2px 8px -3px rgba(0, 0, 0, .60);
        --v-vetro-a:    rgba( 70, 160, 225, .28);
        --v-vetro-b:    rgba(118, 104, 222, .26);
        --v-vetro-c:    rgba( 60, 190, 205, .23);
        --v-vetro-qa: 28%;  --v-vetro-qb: 26%;  --v-vetro-qc: 23%;
    }
}

/* ===========================================================================
   I COLORI CHE UN RUOLO NON CE L'HANNO
   ---------------------------------------------------------------------------
   Qui sotto va SOLO ciò che non è traducibile in un ruolo della palette: il
   secondo colore sociale, e soprattutto gli STATI — che in un gestionale
   contano più del «colore dei tasti»: un invio fallito, una scadenza, una
   conferma.

   ⚠️ Queste NON sono usabili in css="…". Si usano con class="…", oppure — ed è
   la strada che consiglierei — diventano una PROMOZIONE alla scatola: tre
   chiavi in bg_color/tx_color di PULSAR e tre variabili nelle due palette, e da
   quel momento si scrive css="bg-err tx-ink" come per tutto il resto.
   =========================================================================== */
:root {
    /* --v-sociale2: #……; */
    /* --v-ok:       #……; */   /* conferma, invio riuscito */
    /* --v-warn:     #……; */   /* in scadenza, da controllare */
    /* --v-err:      #……; */   /* invio fallito, errore, cancellazione */
}

/* ===========================================================================
   ELEMENTI GREZZI
   ---------------------------------------------------------------------------
   UNA regola su un ELEMENTO, non su una classe. Sta qui per un motivo preciso:
   `::-webkit-details-marker` e' uno PSEUDO-ELEMENTO, e le varianti di PULSAR
   sono STATI (`hover:`, `focus:`) — `Groups` ha tre fasce per quattro varianti,
   e aggiungerne una quinta sarebbe chirurgia sul compilatore per una stranezza
   di un browser solo.

   ⚠️ `list-style:none` invece NON e' piu' qui: il 15/09/2026 `list-none` e'
   entrato in PULSAR, perche' di quello beneficia ogni progetto che abbia un
   <ul> di navigazione. Resta fuori solo la riga di WebKit, che e' l'unica che
   la scatola non sa esprimere.
   =========================================================================== */

/* Il triangolino del <details> su WebKit datato. Chrome e Firefox moderni lo
   disegnano col `list-style`, quindi per loro basta il token `list-none` sul
   <summary>; Safari usa ancora il suo marcatore, e quello si toglie solo cosi'.
   Toglierla lascia il triangolino su un browser solo: il tipo di differenza che
   si scopre dal telefono di qualcun altro. */
summary::-webkit-details-marker { display: none; }

/* ===========================================================================
   LA GRIGLIA CON SELEZIONE
   ---------------------------------------------------------------------------
   Due regole, e stanno qui perche' PULSAR non le sa dire: chiedono di guardare
   i DISCENDENTI di un elemento, e le sue varianti agiscono sull'elemento stesso
   (o sul fratello immediato). Sono pero' generiche quanto un alias — valgono per
   ogni griglia del progetto, non per la pagina degli utenti.

   ⚠️ Niente JavaScript, ed e' il punto: la barra compare perche' il browser sa
   gia' se c'e' una casella spuntata. `:has()` e' sostenuto da tutti i browser
   moderni; dove non lo fosse, la barra resta VISIBILE — che e' il degrado giusto
   (si vede un comando in piu', non se ne perde uno).
   =========================================================================== */

/* La barra delle azioni: nascosta finche' non si spunta qualcosa. */
.griglia:has(input[name="ids"]:checked) .azioni-massa { display: flex; }
@supports selector(:has(*)) {
    .azioni-massa { display: none; }
}

/* Il popup di conferma: un <details> vestito da finestra. Il pannello si ancora
   sopra la barra, allineato a destra come il comando che lo apre. */
.conferma > summary { list-style: none; }
.conferma > summary::-webkit-details-marker { display: none; }

/* ===========================================================================
   IL TELAIO: sidebar, topbar, contenuto — e la riduzione a sole icone
   ---------------------------------------------------------------------------
   ⚠️ PERCHE' QUESTE TRE MISURE NON STANNO IN PULSAR. Perche' devono muoversi
   INSIEME: quando la sidebar si riduce a 64px, il margine della topbar e quello
   del contenuto devono ridursi con lei. PULSAR sa dire "230px"; non sa dire "la
   stessa misura che un'altra classe, altrove, cambia". Scritte con `ml-230px` e
   `w-230px` resterebbero tre numeri indipendenti, e il giorno che uno cambia gli
   altri due restano indietro — in silenzio. Qui sono un blocco solo.

   Tutto il RESTO (colori, respiro, ombre, la slash responsive) resta PULSAR: qui
   c'e' solo cio' che la scatola non sa esprimere, come per `.griglia` sopra.

   LA VIEW SCRIVE DUE ATTRIBUTI:  <div class="content" css="content">
   `css` da' il respiro, `class` da' il margine. Dimenticarne uno non e'
   silenzioso: senza `class` il contenuto finisce sotto la sidebar, senza `css`
   sbatte contro i bordi.
   =========================================================================== */

/* ⚠️ LA LARGHEZZA E' UNA VARIABILE, e non per eleganza: adesso la leggono in
   QUATTRO — la sidebar, il margine della topbar, quello del contenuto e la
   fascia del gradiente che le sta dietro. Scritta a numero, il 230 stava in due
   posti e il 64 in tre, ed e' esattamente il rischio che il commento qui sopra
   descrive: il giorno che uno cambia, gli altri restano indietro in silenzio.
   Sta su `html` perche' e' li' che finisce `.sidebar-closed`. */
:root {
    --v-sidebar-w: 230px;
}

.sidebar { width: var(--v-sidebar-w); }
.topbar, .content { margin-left: 0; }

/* ===========================================================================
   IL FONDALE — ed e' della PAGINA, non di un pezzo
   ---------------------------------------------------------------------------
   Tutto cio' che e' di vetro (la sidebar, la tendina, i riquadri) sfoca QUESTO.

   ⚠️ **SENZA, IL VETRO NON SI VEDE.** `backdrop-filter` sfoca cio' che sta
   DIETRO l'elemento: dietro una tinta unita c'e' quella tinta, e sfocarla
   restituisce la stessa tinta. Si spedirebbe l'effetto e non cambierebbe niente,
   senza un errore da nessuna parte. Il fondale non e' la decorazione
   dell'effetto: e' il suo presupposto.

   ⚠️ **E' `fixed`**, quindi non scorre col contenuto e non si muove quando la
   sidebar si apre o si chiude. E' anche la forma piu' semplice di una cosa che
   prima costava due meccanismi: finche' il fondale stava in una fascia larga
   quanto la colonna voleva un `background-size` ancorato per non schiacciarsi
   chiudendo il menu, PIU' una transizione sincronizzata per non restare scoperto
   durante l'apertura (misurato: 123px di gradiente nudo a 40ms). Legato al
   viewport, quei due problemi non sono risolti — non esistono.

   ⚠️ **Il fondo sta QUI e non piu' nel `@bodyclasses` delle view.** Ci stava in
   undici, e non e' una decisione per-pagina: bastava scrivere una view nuova
   dimenticandolo per avere una pagina col fondo piatto, senza nessun errore.

   I colori sono decorativi e hanno variabili LORO: appoggiarli su `--n-ac` o
   `--v-ok` legherebbe l'aspetto dell'applicazione al significato di «il comando»
   o «riuscito», e ritoccare l'uno cambierebbe l'altro senza volerlo. */
body {
    /* `--v-fondo` e' la base tinta delle sezioni con la trama (vedi «LO SFONDO DI SEZIONE»
       in fondo al foglio). Dove non c'e', la base resta quella del tema. */
    background-color: var(--v-fondo, var(--n-bg-0));
    background-image:
        radial-gradient(48% 38% at 12%  8%, var(--v-vetro-a) 0%, transparent 62%),
        radial-gradient(52% 40% at 88% 14%, var(--v-vetro-c) 0%, transparent 64%),
        /* ⚠️ La X di questo alone e' una VARIABILE perche' le sezioni lo vogliono
           piu' a destra del default (28/09). La geometria resta dichiarata qui, in
           un posto solo: le sezioni cambiano un numero, non ricopiano i quattro
           gradienti — una seconda `background-image` altrove sarebbe la copia che
           resta indietro al primo ritocco. */
        radial-gradient(60% 45% at var(--v-vetro-bx, 78%) 92%, var(--v-vetro-b) 0%, transparent 66%),
        radial-gradient(45% 35% at 22% 95%, var(--v-vetro-c) 0%, transparent 60%);
    background-attachment: fixed;
    background-repeat: no-repeat;
}

/* L'OMBRA A DESTRA, e solo a destra. La sidebar e' `fixed`: sta davvero sopra
   la pagina, ma senza un segno sembra soltanto una colonna piu' chiara incollata
   al bordo. Un filo d'ombra dice «questo galleggia», ed e' anche cio' che spiega
   perche' il contenuto le lascia il posto invece di passarci sotto.

   Appena percettibile sul chiaro; sullo scuro serve piu' nera, perche' un'ombra
   al 12% su un fondo #171622 non la vede nessuno. */
.sidebar { box-shadow: 2px 0 14px -4px rgba(9, 9, 16, .13); }
.theme-dark .sidebar { box-shadow: 2px 0 16px -4px rgba(0, 0, 0, .55); }
@media (prefers-color-scheme: dark) {
    .theme-auto .sidebar { box-shadow: 2px 0 16px -4px rgba(0, 0, 0, .55); }
}



/* ═══════════════════════════════════════════════════════════════════════════
   OGNI VOCE HA LA SUA TINTA — icona e filo dell'hover.
   ---------------------------------------------------------------------------
   Serve al RICONOSCIMENTO: cinque voci tutte grigie si distinguono solo
   leggendole, e chi usa il pannello otto ore al giorno impara la posizione ma
   non la parola. Un colore proprio si riconosce con la coda dell'occhio.

   ⚠️ Il meccanismo e' UNA VARIABILE per voce, non due regole per voce: le due
   regole (il filo e l'icona) leggono `--v-voce-tinta`, e ogni classe si limita a
   dichiararla. Una sezione nuova domani costa **una riga**, non tre — e se
   qualcuno la dimentica il ripiego e' la tinta di sempre, quindi la voce esce
   come prima invece che rotta.

   ⚠️ Le tinte stanno nel semicerchio FREDDO, piu' un caldo per Media, e nessuna
   e' verde-segnale, ambra o rossa: quelle tre dicono «riuscito», «attenzione» e
   «sbagliato» in tutto il progetto, e un'icona di navigazione che le indossa mente.

   ⚠️ E le due meta' del tema NON hanno gli stessi valori: una tinta scelta per
   leggersi su bianco, su un fondo #171622 diventa fango. Le scure sono le stesse
   schiarite e desaturate quel tanto che basta. */
/* Le cinque tinte, dichiarate UNA volta. Sotto le leggono in due: la voce del
   menu (icona e punto) e i titoli della pagina di quella sezione. Scriverle due
   volte vorrebbe dire che un giorno il menu e la pagina dicono due colori
   diversi per la stessa cosa. */
/* ⚠️ Lo schema e' quello degli altri blocchi di questo file, e l'ordine conta:
   il CHIARO e' il default (`:root`), lo scuro arriva con `.theme-dark`, e `auto`
   e' chiaro finche' il sistema non dice altro. Scritto al contrario — scuro di
   default e chiaro sotto `prefers-color-scheme: light` — una preferenza non
   dichiarata darebbe una pagina chiara con le tinte del tema scuro. */
:root {
    --tinta-dashboard: #1a86bd;   /* il blu di casa: e' la home */
    /* ⚠️ VIOLA a 280 gradi, e l'angolo non e' a gusto: indaco (Utenti) sta a 240
       e magenta (Canali) a 322, quindi 280 e' a 41 gradi da entrambi — la stessa
       distanza che separa gia' Cruscotto da Utenti. Cinque tinte che devono
       distinguersi si spaziano, non si scelgono una per una. */
    --tinta-utenti:    #5b5bd6;   /* indaco */
    --tinta-canali:    #b4478c;   /* magenta */
    --tinta-media:     #c2652a;   /* arancio bruciato: un magazzino */
    /* ⚠️ PROVVISORIA, da confermare:
       un verde oliva, lontano dal verde di «riuscito» (`--v-ok`) e dalle altre
       sei. 3,25:1 su bianco: basta a un segno, non a un testo piccolo — per
       quello c'e' l'inchiostro qui sotto. */
    --tinta-rubrica:   #7a9a30;

    /* ⚠️ E L'INCHIOSTRO DI CIASCUNA — piu' scuro del segno, e non e' una
       rifinitura: e' la soglia di leggibilita'. Il SEGNO (icona, punto, titolo)
       e' testo grande o non e' testo affatto, e gli bastano 3:1. Un
       COLLEGAMENTO o l'etichetta di un pulsante sono testo piccolo e ne
       pretendono 4,5 — e non tutti i segni ci arrivano su bianco
       (Dashboard 4,05, Media 4,05). Misurati, non stimati.
       E' lo stesso rapporto che c'e' gia' fra `--v-ok` e `--v-ok-ink`.
       ⚠️ Due dei cinque sono identici al segno perche' erano gia' sopra soglia:
       scurirli per simmetria avrebbe peggiorato il colore senza guadagnare
       niente. */
    --tinta-dashboard-ac: #187cb0;   /* 4,62:1 su bianco */
    --tinta-utenti-ac:    #5b5bd6;   /* 5,37 — il segno bastava */
    --tinta-canali-ac:    #b4478c;   /* 4,98 — il segno bastava */
    --tinta-media-ac:     #b35d27;   /* 4,65 */
    --tinta-rubrica-ac:   #5a7520;   /* 5,2 */
}
/* ⚠️ Le scure non sono le chiare con un filtro: sono le stesse tinte schiarite e
   smorzate, perche' un colore scelto per leggersi su bianco, su un fondo #171622
   diventa fango. */
.theme-dark {
    --tinta-dashboard: #6abaea;
    /* ⚠️ #c297d8 e non piu' #cc8aed: da quando l'accento
       copre superfici grandi — le pillole, i pulsanti —
       quel lilla saturo «gridava». Stessa luminosita', meno saturazione: i
       contrasti restano (anzi salgono di un filo), cambia solo la vivacita'. */
    --tinta-utenti:    #8f8ff0;
    --tinta-canali:    #e07fbd;
    --tinta-media:     #e59a5c;
    --tinta-rubrica:   #a9c95e;

    /* ⚠️ Nello scuro segno e inchiostro COINCIDONO, e il verso e' ribaltato:
       li' l'accento e' la tinta CHIARA e il testo che ci sta sopra e' scuro
       (`--n-ink: #111`). Misurate tutte e cinque: da 5,19:1 in su come testo sul
       pannello, da 6,61 in su per l'inchiostro scuro sopra il fondo pieno. Non
       serve una seconda variante perche' non c'e' niente da scurire — semmai il
       contrario. */
    --tinta-dashboard-ac: #6abaea;
    --tinta-utenti-ac:    #8f8ff0;
    --tinta-canali-ac:    #e07fbd;
    --tinta-media-ac:     #e59a5c;
    --tinta-rubrica-ac:   #a9c95e;
}
@media (prefers-color-scheme: dark) {
    .theme-auto {
        --tinta-dashboard: #6abaea;
        --tinta-utenti:    #8f8ff0;
        --tinta-canali:    #e07fbd;
        --tinta-media:     #e59a5c;
        --tinta-rubrica:   #a9c95e;
        --tinta-dashboard-ac: #6abaea;
        --tinta-utenti-ac:    #8f8ff0;
        --tinta-canali-ac:    #e07fbd;
        --tinta-media-ac:     #e59a5c;
        --tinta-rubrica-ac:   #a9c95e;
    }
}

.voce-dashboard { --v-voce-tinta: var(--tinta-dashboard); }
.voce-utenti    { --v-voce-tinta: var(--tinta-utenti); }
.voce-canali    { --v-voce-tinta: var(--tinta-canali); }
.voce-media     { --v-voce-tinta: var(--tinta-media); }
.voce-rubrica   { --v-voce-tinta: var(--tinta-rubrica); }

/* ⚠️ I TITOLI DELLA PAGINA SEGUONO LA SEZIONE, E SENZA TOCCARE IL MARKUP.
   La pagina sa gia' qual e' la voce aperta — ce l'ha scritto nella sidebar — e
   `:has()` permette al documento intero di rispondere a un suo discendente.
   L'alternativa era una classe di sezione su ogni view: dieci punti da scrivere
   a mano, e uno dimenticato darebbe una pagina coi titoli del colore sbagliato
   senza nessun errore. Qui non c'e' niente da ricordarsi.

   ⚠️ Solo i TITOLI, per ora, e il motivo e' misurato: un titolo e' testo GRANDE
   (19-22px, grassetto) e gli basta 3:1 di contrasto — tutte e cinque le tinte ci
   arrivano. Il testo piccolo pretende 4,5:1 e non tutte ce la fanno
   (Dashboard 4,05, Media 4,05): per portare la sezione anche su
   collegamenti e pulsanti serve una seconda variante piu' scura di ciascuna —
   lo stesso rapporto che c'e' gia' fra `--v-ok` e `--v-ok-ink`. */
body:has(.voce-dashboard.attiva) { --v-titolo: var(--tinta-dashboard); --n-ac: var(--tinta-dashboard-ac); }
body:has(.voce-utenti.attiva)    { --v-titolo: var(--tinta-utenti);    --n-ac: var(--tinta-utenti-ac); }
body:has(.voce-canali.attiva)    { --v-titolo: var(--tinta-canali);    --n-ac: var(--tinta-canali-ac); }
body:has(.voce-media.attiva)     { --v-titolo: var(--tinta-media);     --n-ac: var(--tinta-media-ac); }
body:has(.voce-rubrica.attiva)   { --v-titolo: var(--tinta-rubrica);   --n-ac: var(--tinta-rubrica-ac); }

/* ⚠️ QUANTO PESA IL FONDALE DI SEZIONE — una manopola sola, apposta.
   Le tre opacita' di base (`--v-vetro-q*`) sono del TEMA e valgono anche per il
   default; le sezioni le scalano di questo fattore invece di avere numeri loro.
   Cosi' alleggerire o appesantire il fondale di TUTTE le sezioni e' un valore da
   cambiare, e il rapporto fra chiaro e scuro non si perde per strada. */
:root { --v-vetro-sez: .75; }

/* ⚠️ E IL FONDALE SEGUE LA SEZIONE — stessa trama, stessa trasparenza, una tinta
   sola.

   Il fondale di default nasce da TRE colori diversi (un blu, un viola, un
   ciano), e per il Cruscotto funzionava per caso: quel blu e' quasi la sua
   tinta. Sulle altre sezioni no — si apriva Canali e tutto diventava magenta
   tranne il fondo, che restava blu. Qui i quattro aloni prendono la tinta della
   sezione e **nient'altro cambia**: stesse posizioni, stessi raggi, stesse
   percentuali (`--v-vetro-q*`, che sono del TEMA — 28/26/23 nello scuro,
   18/15/16 nel chiaro).

   ⚠️ `color-mix(… <tinta> N%, transparent)` e non un rgba scritto a mano: la
   tinta e' un esadecimale che cambia col tema, e l'unico modo di darle
   un'opacita' senza ricopiare tre valori per sei sezioni per due temi —
   trentasei numeri — e' calcolarla. Ricopiarli sarebbe stato il posto dove uno
   resta indietro.

   ⚠️ E vale SOLO dove c'e' una voce di sidebar accesa: login, 403 e ogni pagina
   senza telaio non hanno nessun `.voce-*`, quindi `:has()` non combacia e si
   tengono il fondale di sempre. Era la richiesta: cambiano le sezioni, il resto
   resta com'e'. */
body:has(.voce-dashboard.attiva) {
    --v-vetro-a: color-mix(in srgb, var(--tinta-dashboard) calc(var(--v-vetro-qa) * var(--v-vetro-sez)), transparent);
    --v-vetro-b: color-mix(in srgb, var(--tinta-dashboard) calc(var(--v-vetro-qb) * var(--v-vetro-sez)), transparent);
    /* ⚠️ SPENTO, e non e' una dimenticanza: `--v-vetro-c` alimenta SOLO i due
       aloni in alto a destra e in basso a sinistra (verificato: non lo usa
       nient'altro nel foglio). Toglierli era la richiesta — restano i due in
       diagonale, che è il taglio che si vedeva bene. Sulle pagine senza voce di
       sidebar la variabile resta quella del tema, quindi il default ha ancora
       tutti e quattro. */
    --v-vetro-c: transparent;
    /* E l'alone rimasto in basso scivola verso il bordo destro: al 78% del
       default stava in mezzo allo spazio vuoto sotto la griglia, dove si legge
       come una macchia; al 94% e' un velo d'angolo. */
    --v-vetro-bx: 94%;
}


body:has(.voce-utenti.attiva) {
    --v-vetro-a: color-mix(in srgb, var(--tinta-utenti) calc(var(--v-vetro-qa) * var(--v-vetro-sez)), transparent);
    --v-vetro-b: color-mix(in srgb, var(--tinta-utenti) calc(var(--v-vetro-qb) * var(--v-vetro-sez)), transparent);
    /* ⚠️ SPENTO, e non e' una dimenticanza: `--v-vetro-c` alimenta SOLO i due
       aloni in alto a destra e in basso a sinistra (verificato: non lo usa
       nient'altro nel foglio). Toglierli era la richiesta — restano i due in
       diagonale, che è il taglio che si vedeva bene. Sulle pagine senza voce di
       sidebar la variabile resta quella del tema, quindi il default ha ancora
       tutti e quattro. */
    --v-vetro-c: transparent;
    /* E l'alone rimasto in basso scivola verso il bordo destro: al 78% del
       default stava in mezzo allo spazio vuoto sotto la griglia, dove si legge
       come una macchia; al 94% e' un velo d'angolo. */
    --v-vetro-bx: 94%;
}


body:has(.voce-canali.attiva) {
    --v-vetro-a: color-mix(in srgb, var(--tinta-canali) calc(var(--v-vetro-qa) * var(--v-vetro-sez)), transparent);
    --v-vetro-b: color-mix(in srgb, var(--tinta-canali) calc(var(--v-vetro-qb) * var(--v-vetro-sez)), transparent);
    /* ⚠️ SPENTO, e non e' una dimenticanza: `--v-vetro-c` alimenta SOLO i due
       aloni in alto a destra e in basso a sinistra (verificato: non lo usa
       nient'altro nel foglio). Toglierli era la richiesta — restano i due in
       diagonale, che è il taglio che si vedeva bene. Sulle pagine senza voce di
       sidebar la variabile resta quella del tema, quindi il default ha ancora
       tutti e quattro. */
    --v-vetro-c: transparent;
    /* E l'alone rimasto in basso scivola verso il bordo destro: al 78% del
       default stava in mezzo allo spazio vuoto sotto la griglia, dove si legge
       come una macchia; al 94% e' un velo d'angolo. */
    --v-vetro-bx: 94%;
}

body:has(.voce-rubrica.attiva) {
    --v-vetro-a: color-mix(in srgb, var(--tinta-rubrica) calc(var(--v-vetro-qa) * var(--v-vetro-sez)), transparent);
    --v-vetro-b: color-mix(in srgb, var(--tinta-rubrica) calc(var(--v-vetro-qb) * var(--v-vetro-sez)), transparent);
    /* Come le altre sezioni: due aloni in diagonale, quello in basso verso il bordo. */
    --v-vetro-c: transparent;
    --v-vetro-bx: 94%;
}

body:has(.voce-media.attiva) {
    --v-vetro-a: color-mix(in srgb, var(--tinta-media) calc(var(--v-vetro-qa) * var(--v-vetro-sez)), transparent);
    --v-vetro-b: color-mix(in srgb, var(--tinta-media) calc(var(--v-vetro-qb) * var(--v-vetro-sez)), transparent);
    /* ⚠️ SPENTO, e non e' una dimenticanza: `--v-vetro-c` alimenta SOLO i due
       aloni in alto a destra e in basso a sinistra (verificato: non lo usa
       nient'altro nel foglio). Toglierli era la richiesta — restano i due in
       diagonale, che è il taglio che si vedeva bene. Sulle pagine senza voce di
       sidebar la variabile resta quella del tema, quindi il default ha ancora
       tutti e quattro. */
    --v-vetro-c: transparent;
    /* E l'alone rimasto in basso scivola verso il bordo destro: al 78% del
       default stava in mezzo allo spazio vuoto sotto la griglia, dove si legge
       come una macchia; al 94% e' un velo d'angolo. */
    --v-vetro-bx: 94%;
}

/* ⚠️ RIDEFINIRE `--n-ac` TIRA DIETRO TUTTO, ed e' voluto: collegamenti (`tx-ac`),
   pulsanti pieni (`bg-ac`, quindi «Nuovo…» e «Salva»), bordi d'accento,
   l'anello di fuoco (`outline-ac`) e ogni componente della scatola che usa il
   ruolo. E' il punto: la sezione si riconosce senza leggerla.
   ⚠️ `--n-ink` — il testo SOPRA l'accento — resta quello della tavolozza (bianco
   nel chiaro, scuro nello scuro) e non va ritoccato: e' stato verificato contro
   tutte e cinque le tinte in entrambi i temi.
   ⚠️ E le pagine SENZA sidebar (accesso, conferma d'uscita) non hanno nessuna
   voce attiva, quindi nessuna di queste regole aggancia e l'accento resta il blu
   della tavolozza. E' il comportamento giusto, e viene gratis. */

/* L'icona prende la tinta; l'etichetta no — cinque testi colorati sarebbero una
   lista di collegamenti, non un menu. */
.sidebar-nav > a svg { color: var(--v-voce-tinta, inherit); }



/* ⚠️ IL PUNTO E' L'UNICO SEGNO DELLA VOCE, e vale per tutti e due gli stati.
   Prima c'era anche un filo — acceso all'hover, permanente sull'aperta — ed e'
   caduto: su una colonna di vetro ogni contorno e' una riga in piu' da leggere,
   e cinque voci con cinque filiformi facevano una griglia. Il punto dice la
   stessa cosa occupando sei pixel.

   ⚠️ Provata e SCARTATA anche una macchia di tinta che partiva da sinistra
   sfumando dopo l'icona: funzionava come segno, ma arrivava sotto l'ETICHETTA e
   il testo scuro sulla parte piena perdeva contrasto, tanto peggio quanto piu'
   lunga la parola. Il punto sta dove non c'e' niente da leggere.

   `::after` e non un elemento nel markup: e' un segno, non un contenuto, e chi
   legge a voce non deve sentirselo.

   ⚠️ E L'APERTA E LA PUNTATA NON SONO LA STESSA COSA. Con lo stesso punto
   sarebbero indistinguibili — «dove sono» e «dove sto passando» direbbero la
   stessa parola. Il punto della puntata e' piu' tenue: un segno che appare e
   sparisce col puntatore non deve pesare quanto uno che dice dove ti trovi. */
.sidebar-nav > a { position: relative; }

.sidebar-nav > a.attiva::after,
.sidebar-nav > a:hover::after {
    content: "";
    position: absolute;
    right: 12px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--v-voce-tinta, var(--n-ac));
}
/* La puntata: lo stesso punto, a mezza voce. Sull'aperta resta pieno anche
   mentre ci passi sopra — o «dove sono» si spegnerebbe proprio quando lo si
   sta per lasciare. */
.sidebar-nav > a:not(.attiva):hover::after { opacity: .45; }

/* ⚠️ IL VETRO DI UN PANNELLO DI LETTURA — UNA CLASSE, UNA DICHIARAZIONE.
   Vale per tutto cio' che contiene testo da leggere: le schede del cruscotto,
   i moduli delle impostazioni, i pannelli. Il `css="card"` accanto porta solo
   la forma (raggio, respiro, ombra); il materiale e' questo.

   ⚠️ E' QUI e non in PULSAR perche' la tinta cambia per tema, e un token non sa
   ramificare: nel chiaro il vetro e' bianco, nello scuro e' la superficie scura.
   Non sono lo stesso colore con due alpha — un velo bianco su fondo scuro
   schiarisce il pannello invece di dargli un fondo, e il testo chiaro ci va
   sopra con MENO contrasto.

   ⚠️ IL `body` DAVANTI E' UNA DIFESA, e va spiegato per cosa — perche' OGGI non
   serve. Il foglio di PULSAR e' caricato DOPO questo (vedi `partials/head.nbl`),
   quindi a parita' di specificita' vince lui: un `.vetro-lettura` secco varrebbe
   0-1-0 come una classe hashata. Adesso non fa differenza, perche' l'alias
   `card` dichiara solo forma e spazio e non contende ne' il fondo ne' il bordo.
   Il giorno che qualcuno ci aggiunge un `bg-…` o un `bd-…` — un gesto di due
   secondi, che sembra innocuo — quel token arriverebbe dopo e spegnerebbe questa
   regola **in silenzio**: il pannello resterebbe come l'ha lasciato PULSAR. Il
   `body` costa un carattere e toglie il caso.

   ⚠️ IL NOME DICE IL MATERIALE, NON L'OGGETTO — e non e' pedanteria: si e'
   chiamata `riquadro` per mezz'ora, e con quel nome una tendina o un modulo non
   se la sarebbero mai presa. Si mette su QUALUNQUE superficie che contiene testo
   da leggere: schede, moduli, pannelli, finestre. Cio' che porta un DATO — un
   numero, una pillola, un pulsante — resta invece PIENO: su vetro un dato non ci
   va mai. */
/* ⚠️ IL RILIEVO — CIO' CHE GALLEGGIA SUL VETRO.
   E' il rovescio di `.vetro-lettura`: quella e' la superficie su cui si LEGGE,
   questo e' l'oggetto PIENO che ci sta sopra — una linguetta, una pastiglia con
   un numero, un comando. La regola dell'interfaccia e' una riga: **cio' che
   porta un dato non sta mai su vetro**, sta su fondo pieno e si stacca con
   un'ombra.

   Da' SOLO l'ombra, e apposta: il fondo continua a darlo PULSAR (`bg-1` per una
   linguetta a riposo, `bg-ac` per quella aperta), che segue gia' il tema per suo
   conto. Qui c'e' la sola cosa che un token non sa fare — un'ombra la cui
   OPACITA' cambia col tema, perche' `shadow-md` ha il nero fisso a `.1` e su un
   fondo scuro sparisce.

   Si compone quindi con qualunque riempimento, ed e' il motivo per cui non si
   chiama `pastiglia` o `badge`: quelli sono oggetti, questo e' cio' che li fa
   galleggiare. Va bene su una linguetta come su un pulsante. */
body .rilievo { box-shadow: var(--v-rilievo); }

/* ⚠️ LA TENDINA — UNA CLASSE, UNA DICHIARAZIONE, per tutto cio' che compare
   sopra il contenuto: il menu utente, la scelta delle righe per pagina, gli
   elenchi a discesa. Prima erano tre pezzi di markup che si vestivano ognuno per
   conto suo (`bd bg-1 shadow` due, vetro il terzo), e divergevano di un
   dettaglio per volta: la piu' vecchia era ancora bianca piena mentre l'ultima
   era gia' di vetro.
   Fa fede il menu utente in basso a sinistra.

   Qui c'e' il MATERIALE; posizione, misura, respiro e raggio restano nel markup,
   perche' sono di quella tendina e non della famiglia.

   ⚠️ Il filo e' `--n-bd`, il bordo neutro, e non quello dei pannelli: una
   tendina deve staccarsi da cio' che ha SOTTO (contenuto, non fondale), e li' un
   filo velato non basta a dire dove finisce.
   ⚠️ Niente ombra: era `shadow` di PULSAR, il nero fisso a `rgba(0,0,0,.1)` —
   sporca sul chiaro e sparisce sullo scuro. */
body .tendina {
    background: var(--v-tendina);
    /* ⚠️ Niente `backdrop-filter`: sotto un fondo opaco non sfoca niente — e
       costerebbe comunque un livello di composizione per tendina aperta. Era
       rimasto dalla versione di vetro. */
    border: 1px solid var(--n-bd);
}

/* ⚠️ UN PANNELLO DI VETRO TRATTIENE I `fixed`. `backdrop-filter` fa del pannello
   il riferimento di ogni discendente `position: fixed`: un livello che deve
   stare SOPRA la pagina — il velo che chiude cliccando fuori, il pannello della
   ricerca — resta chiuso dentro la colonna, e il velo copre solo lei. Misurato con
   la lente di un elenco: l'unico antenato che tratteneva il pannello era
   l'elenco, per la sua sfocatura.
   Finche' dentro c'e' qualcosa di APERTO (`aria-expanded="true"`: la lente, una
   tendina, i suggerimenti di un campo) il pannello rinuncia alla sfocatura:
   sopra un fondale fermo non si vede, e i livelli tornano liberi. */
body .vetro-lettura:has([aria-expanded="true"]) {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
body .vetro-lettura {
    background: var(--v-vetro-lettura);
    /* 4px e non 18 (dopo una prova a 2): a 18 cio' che
       sta sotto si scioglie del tutto e il pannello sembra latte — il vetro non
       si riconosce. A 4px il fondale si intuisce, ed e' quello che dice
       «vetro». Va letto insieme al fondo del pannello, salito al 75%. */
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    border: 1px solid var(--v-vetro-lettura-bd);
    /* ⚠️ L'ombra sta QUI e non piu' nell'alias `card`. Quella di PULSAR
       (`shadow`) ha il nero FISSO a `rgba(0,0,0,.1)`: su un fondale chiaro e
       colorato sporca — una macchia sotto il pannello — e su fondo scuro non si
       vede affatto. Un pannello deve galleggiare come galleggia una pastiglia:
       stessa forma, stessa tinta, solo un filo piu' carica. */
    box-shadow: var(--v-rilievo-pannello);
}

/* Il logo intero da aperta, il solo segno da ridotta. Escono ENTRAMBI nel
   markup e il CSS ne spegne uno: nessun JavaScript che scambia un `src`, quindi
   nessun secondo scaricamento e nessun lampo nel mezzo. */
/* ⚠️ IL LOGO NON SI DEFORMA MAI, QUALUNQUE PROPORZIONE ABBIA.
   La scatola e' fissa (`w-150px h-52px` sul markup, per non far crescere il logo
   in altezza mentre la colonna si anima); `contain` ci incastra dentro
   l'immagine rispettandone il rapporto, e `left center` la tiene ancorata al
   bordo sinistro — cosi' restringendo la sidebar il logo si COPRE da destra
   invece di scivolare verso il centro.
   Senza `contain`, un logo caricato dal cliente con proporzioni diverse dalle
   nostre verrebbe stirato dentro la scatola: nessun errore, il marchio di
   qualcun altro storto sulla sua stessa applicazione. */
.logo-full { object-fit: contain; object-position: left center; }

.logo-mini { display: none; }

@media (min-width: 768px) {

    .topbar, .content { margin-left: var(--v-sidebar-w); }

    /* ——— RIDOTTA: restano le icone ——————————————————————————————— */
    html.sidebar-closed { --v-sidebar-w: 64px; }
    /* ⚠️ Niente `margin-left: 64px` qui: i margini leggono gia'
       `--v-sidebar-w`, che la riga sopra ha appena cambiato. Riscriverlo
       sarebbe il quarto numero indipendente. */

    /* Le etichette spariscono. ⚠️ Non e' `visibility`: `display:none` le toglie
       anche al calcolo della larghezza, o la voce resterebbe larga 230px dentro
       una sidebar di 64 e il testo uscirebbe dal bordo. */
    html.sidebar-closed .sidebar-label { display: none; }

    /* ...e cio' che resta si centra. Senza queste righe l'icona resterebbe
       appoggiata a sinistra, con 14px di padding ereditato dall'alias. */
    html.sidebar-closed .sidebar-nav { padding-left: 8px; padding-right: 8px; }
    html.sidebar-closed .sidebar-nav > a,
    html.sidebar-closed .user-chip,
    html.sidebar-closed .sidebar-brand {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    /* ⚠️ DA RIDOTTA IL PUNTO SI SPOSTA VERSO IL BORDO. Resta di fianco all'icona
       — sotto non ci sta, in 40px d'altezza finirebbe appiccicato al testo che
       non c'e' e al bordo che c'e' — ma i 12px dell'aperta, su una colonna di
       64, lo portano quasi addosso al segno: l'icona e' centrata, quindi lo
       spazio a destra e' meta' di quello che c'era. Spostandolo a 5px il punto
       torna a respirare, e si legge come un'annotazione al margine invece che
       come un pezzo dell'icona. */
    html.sidebar-closed .sidebar-nav > a.attiva::after,
    html.sidebar-closed .sidebar-nav > a:hover::after { right: 5px; }

    /* Da ridotta il comando sparisce — in 64px non ci sta accanto al segno — e
       a riaprire ci pensa il logo, che diventa cliccabile. */
    html.sidebar-closed .sidebar-toggle { display: none; }
    /* ⚠️ `flex-grow: 0` QUI, e senza non si centra niente: da aperta il bottone
       del logo CRESCE per prendersi lo spazio libero (è il rimedio all'SVG che
       collassa a zero), e un elemento che cresce riempie la riga — quindi il
       `justify-content: center` della riga non ha piu' niente da distribuire, e
       il logo resta appoggiato a sinistra. Tolto il `grow`, il bottone torna
       largo quanto il suo contenuto e la riga lo mette in mezzo. */
    html.sidebar-closed .logo-apri {
        pointer-events: auto;
        cursor: pointer;
        flex-grow: 0;
        justify-content: center;
    }
    /* ⚠️ LA FRECCIA ESCE DAL FLUSSO, e il motivo è tutto qui: se resta un
       elemento in riga, a essere centrata è la COPPIA logo+freccia, e il logo
       finisce spostato a sinistra di mezza freccia. Assoluta rispetto alla riga,
       invece, non partecipa alla centratura: il logo si centra da solo e lei si
       appoggia al bordo destro. */
    html.sidebar-closed .sidebar-brand { position: relative; }
    html.sidebar-closed .logo-freccia {
        display: inline-flex;
        position: absolute;
        /* ⚠️ `right: 0` è il massimo utile, e il disegno arriva comunque un po'
           prima del bordo: il chevron occupa la fascia centrale del suo riquadro
           24×24, quindi a 15px si porta dietro ~5px di aria per lato che nessun
           `right` può togliere. Spingere oltre con un valore negativo farebbe
           uscire la freccia dalla sidebar, sopra il contenuto. */
        right: 0;
        top: 50%;
        transform: translateY(-50%);
    }
    /* Al passaggio del mouse la freccia si accende e fa un passo a destra: il
       verso del gesto detto col movimento, che si capisce prima di una parola.
       ⚠️ La `translate` porta ANCHE la centratura verticale: scriverla come sola
       `translateX` la annullerebbe, e la freccia salterebbe in alto. */
    html.sidebar-closed .logo-apri:hover .logo-freccia {
        color: var(--n-ac, #1a86bd);
        transform: translate(2px, -50%);
    }
    html.sidebar-closed .logo-full { display: none; }
    html.sidebar-closed .logo-mini { display: block; }

    /* Il menu utente non ci sta in 64px: si stacca e si allarga. */
    html.sidebar-closed .sidebar-menu { width: 210px; }
}

/* Il movimento. `width` e `margin-left` insieme, o la sidebar scivolerebbe via
   mentre il contenuto la insegue con un istante di ritardo.

   ⚠️ Il FONDALE non e' in questa lista, e non e' una dimenticanza: da quando sta
   sulla pagina ed e' `fixed` non ha nessuna larghezza da animare. Finche' era una
   fascia larga quanto la colonna doveva muoversi insieme a lei, o aprendo la
   sidebar restava scoperta una striscia di gradiente nudo — 123px a 40ms,
   misurati. Quel difetto adesso non e' risolto: non esiste. */
.sidebar, .topbar, .content { transition: width .18s ease, margin-left .18s ease; }
@media (prefers-reduced-motion: reduce) {
    .sidebar, .topbar, .content { transition: none; }
}

/* Un'icona dentro una riga flex non si schiaccia: in una voce stretta il
   browser preferirebbe restringere l'SVG invece di tagliare il testo. */
.sidebar svg, .topbar svg, .azione-riga svg { flex: 0 0 auto; }

/* ===========================================================================
   LE GRIGLIE: righe alternate, e le due colonne che non scorrono via
   ---------------------------------------------------------------------------
   L'alternanza sta QUI e non nel template (`{{ @if loop.even }}`) per una
   ragione pratica: le celle incollate ai bordi devono avere lo STESSO fondo
   della loro riga, e `background: inherit` lo prende dal <tr> — cosa che
   funziona solo se il fondo del <tr> e' una regola CSS, non una classe messa a
   righe alterne dal template.

   ⚠️ SUL TELEFONO le griglie scorrono in orizzontale, ed e' giusto: sei colonne
   non si spezzano in modo sensato. Ma i comandi di riga finirebbero fuori
   schermo, e per premere la matita bisognerebbe trascinare la tabella ogni
   volta. `position: sticky` tiene la casella a sinistra e matita/cestino a
   destra mentre il resto scorre sotto.
   =========================================================================== */

/* ⚠️ `border-spacing: 0`. Una tabella nasce `separate` con 2px di gioco fra le
   celle, e su una riga a fondo alternato quel gioco si VEDE: la riga esce a
   strisce, con un filo di bianco fra una colonna e l'altra. Non e' `collapse`
   perche' con i bordi fusi i browser perdono il bordo delle celle `sticky`. */
.griglia table { border-collapse: separate; border-spacing: 0; }

/* ⚠️ LA GRIGLIA PARLA LA LINGUA DELLE SELECT. Le due misure stanno qui, in un
   posto solo, perche' le usano DUE regole lontane (la riga a zebra e il fondo
   dell'etichetta della casella flottante) e devono restare la stessa cosa: se
   divergono, il dischetto si vede come una macchia di un altro colore.
   I numeri non sono inventati — sono gli stessi che usa `<#Select/>`
   (core/components/render/select.rs): 7% per il velo di una voce popolata,
   18% per i separatori fra le voci. Un'interfaccia sola, due componenti.
   Il mix e' su `--n-ac` e `--n-bg-1`, che sono variabili di TEMA: chiaro e
   scuro vengono da se', senza un secondo blocco da tenere allineato. */
.griglia, .permessi {
    /* ⚠️ LA ZEBRA E' UN VELO, NON UNA CAMPITURA. Dentro un pannello di vetro un
       fondo di riga pieno rimetterebbe una superficie opaca esattamente dove il
       pannello e' trasparente, e il fondale sparirebbe sotto la tabella — era
       cosi', ed e' il difetto che si vedeva.
       ⚠️ E una sola espressione serve TUTTI E DUE i temi: `--n-bg-1` e' bianco
       nel chiaro e scuro nello scuro, quindi la riga pari schiarisce di la' e
       scurisce di qua senza doverlo dire due volte. Il verso giusto lo porta
       gia' la tavolozza. */
    --v-riga-velo: color-mix(in srgb, var(--n-bg-1) 45%, transparent);

    /* ⚠️ E IL VELO SI SPEGNE AI DUE CAPI. Una banda che finisce di netto contro
       il bordo del pannello disegna due linee verticali che nessuno ha voluto —
       si leggono come i lati di una tabella che non c'e'. Sfumando, la riga resta
       un'ombreggiatura e non diventa un rettangolo.
       ⚠️ In PIXEL e non in percentuale: la sfumatura e' una rifinitura di BORDO,
       e deve valere 40px tanto su una tabella stretta quanto su una larga. A
       percentuale, su una griglia a tutta pagina diventerebbe una dissolvenza da
       mezzo schermo. */
    --v-riga-alt: linear-gradient(to right,
        transparent 0,
        var(--v-riga-velo) 40px,
        var(--v-riga-velo) calc(100% - 40px),
        transparent 100%);
    --v-riga-bd:  color-mix(in srgb, var(--n-ac) 18%, transparent);
}

/* La riga di separazione sta sulle CELLE e non sul <tr>: in modalita'
   `separate` il bordo di una riga non viene disegnato affatto.
   ⚠️ Il filo e' del colore sociale, non del grigio neutro `--n-bd`: sulla
   riga e' l'unico segno che separa due record, e prenderlo dall'accento lo
   rende una scelta invece che un residuo. Piu' marcato del fondo (18 contro
   7) perche' deve LEGGERSI sopra la zebra, non confondersi con lei. */
.griglia tbody td { border-top: 1px solid var(--v-riga-bd); }

/* ⚠️ LE RIGHE NON HANNO FONDO — e la zebra, per ora, non c'e'.
   Dentro un pannello di vetro un fondo di riga e' un COPRENTE: la zebra
   rimetteva una superficie piena esattamente dove il pannello e' trasparente, e
   il fondale spariva sotto la tabella. A tenere il ritmo resta il FILO fra le
   righe (`--v-riga-bd`), che e' un segno e non una campitura.

   ⚠️ IL PREZZO, dichiarato invece che scoperto dopo: le celle `sticky` prendono
   `background: inherit`, quindi adesso sono trasparenti anche loro — e dove la
   tabella scorre in orizzontale (schermo stretto) il testo delle altre colonne
   si vede passare sotto la colonna incollata. Su desktop non si manifesta,
   perche' non c'e' scorrimento. Se il caso stretto va chiuso, la strada e' dare
   alle sole celle incollate un `backdrop-filter` loro — al prezzo di un livello
   di composizione per riga. */
.griglia tbody tr:nth-child(even) { background: var(--v-riga-alt); }

/* ⚠️ NIENTE RESPIRO AI DUE ESTREMI DELLA RIGA — e prima ce n'erano 16px, messi
   apposta. Vale la pena dire perche' erano giusti allora e sbagliati adesso.
   Le celle nelle view portano `py-*` e `pr-16px`: verso l'interno la spaziatura
   c'e', ai due bordi no, e quando la tabella stava attaccata al bordo di una
   card la prima dicitura e l'ultima icona finivano appoggiate al filo. I 16px
   erano il rimedio.
   Da quando la tabella vive dentro un PANNELLO che ha gia' il suo respiro
   (`p-20px/24px` sull'alias `card`), quei 16 non sostituiscono piu' niente: si
   SOMMANO. La prima colonna rientrava di 40px dal bordo del pannello, e la riga
   sembrava indentata rispetto al titolo che la sorveglia.
   A zero, la colonna si allinea al contenuto del pannello — che e' il
   riferimento vero.

   ⚠️ I selettori restano quelli di prima, e uno spiega l'altro: la prima cella
   VISIBILE non e' sempre `:first-child`, perche' dove c'e' la multiselezione la
   precede `.cella-fissa-sx`, larga zero e senza padding (e' l'ancora della
   casella flottante). Si esclude lei e si prende la cella che le sta accanto,
   cosi' la regola vale con e senza selezione. */
.griglia th:first-child:not(.cella-fissa-sx),
.griglia td:first-child:not(.cella-fissa-sx),
.griglia .cella-fissa-sx + th,
.griglia .cella-fissa-sx + td { padding-left: 0; }

.griglia th:last-child,
.griglia td:last-child { padding-right: 0; }

/* ⚠️ NIENTE `z-index` QUI. Un elemento `sticky` con uno z-index diventa un
   CONTESTO DI IMPILAMENTO, e la finestra di conferma — che e' `fixed` dentro
   una di queste celle — resterebbe prigioniera di quel contesto: le celle
   incollate delle ALTRE righe le finirebbero sopra, bianche, a coprire il velo.
   Senza z-index il contesto non nasce, e una cella `sticky` copre lo stesso le
   colonne che le scorrono sotto — perche' e' POSIZIONATA e loro no. */
/* ⚠️ `transparent` e NON `inherit`, da quando il fondo della riga e' un VELO.
   `inherit` copia il valore calcolato del genitore e lo ridipinge: su un colore
   pieno dava lo stesso risultato, su un velo lo applica DUE VOLTE — e la colonna
   incollata usciva come un rettangolo piu' chiaro sulle sole righe pari. E' il
   difetto che si vedeva in cima a destra nella griglia utenti.
   Trasparente, la cella lascia semplicemente vedere il velo della sua riga, una
   volta sola. */
.griglia .cella-fissa,
.griglia .cella-fissa-sx { position: sticky; background: transparent; }
.griglia .cella-fissa    { right: 0; padding-left: 10px; }
.griglia .cella-fissa-sx { left: 0; }

/* La testata non eredita nulla (il <tr> del <thead> non ha fondo): glielo si
   da', o le due celle incollate diventerebbero trasparenti e sotto ci
   scorrerebbe il testo delle altre colonne. */
/* ⚠️ Niente fondo nemmeno sulla testata incollata: era un rettangolo bianco
   PIENO in cima a destra, e su un pannello di vetro si leggeva come una toppa
   — piu' chiaro di tutto il resto, senza un motivo visibile. */
.griglia thead .cella-fissa,
.griglia thead .cella-fissa-sx { background: transparent; }

/* ⚠️ E QUI STA LA TRAPPOLA VERA, pagata a video: `position: sticky` crea un
   CONTESTO DI IMPILAMENTO SEMPRE, anche senza z-index — al contrario di
   `relative` e `absolute`, che lo creano solo se glielo si da'. La finestra di
   conferma vive dentro l'ultima cella della riga, quindi resta prigioniera di
   quel contesto: il velo copriva la pagina ma NON le celle incollate delle
   altre righe, che restavano bianche a mezz'aria sopra di lui.
   Togliere lo z-index non bastava. Si alza la CELLA che ha la finestra aperta:
   il velo e' dentro di lei, e sale con lei. */
.griglia .cella-fissa:has(details[open]),
.griglia .cella-fissa-sx:has(details[open]) { z-index: 70; }

/* ⚠️ NESSUNA OMBRA sulle colonne incollate, e ci si e' arrivati provando.
   L'idea era dire «li' sotto scorre qualcosa», ma il CSS non sa se la tabella
   stia scorrendo DAVVERO: su uno schermo largo, dove ci sta tutta — cioe' quasi
   sempre — l'ombra restava comunque, e si leggeva come una riga verticale fra
   Stato e i comandi. Un segno che dice una cosa falsa nel caso piu' frequente
   vale meno di nessun segno. */

/* ═══ LE CASELLE COMPAIONO SENZA SPOSTARE NIENTE ═══
   La colonna della selezione c'e' SEMPRE, ma e' larga ZERO: accendere
   «Seleziona» non allarga la tabella e non fa saltare le altre colonne di un
   centimetro a destra. Le caselle escono fuori dalla colonna, nella fascia del
   PADDING del riquadro — quello spazio a sinistra c'e' gia' e non serve a
   nient'altro.

   ⚠️ E QUI STA L'OSTACOLO, che vale la pena scrivere: il contenitore della
   tabella ha `overflow-x: auto` per far scorrere le griglie larghe, e un
   contenitore che scorre TAGLIA cio' che gli esce a sinistra. Una casella a
   `left: -26px` sarebbe semplicemente invisibile. Il rimedio e' la coppia
   `margin-left` negativo + `padding-left` uguale e contrario: la tabella resta
   dov'era (i due si annullano), ma il contenitore guadagna 28px di area
   DIPINGIBILE alla sua sinistra — perche' l'overflow taglia al bordo del
   padding, non a quello del contenuto. */
/* ⚠️ 40 e non piu' 28: da quando la casella si ACCAVALLA sul bordo del riquadro
   (invece di stare dentro la fascia del padding) le serve piu' area dipingibile
   a sinistra, o il contenitore che scorre la taglia a meta'. I due valori si
   annullano, quindi la tabella non si muove di un pixel. */
.griglia .tabella-scorre { margin-left: -40px; padding-left: 40px; }

.griglia .cella-fissa-sx { width: 0; padding: 0; }

/* La casella galleggia: e' posizionata rispetto alla cella `sticky`, quindi
   resta al suo posto anche mentre la tabella scorre in orizzontale. */
.griglia .check-flottante {
    position: absolute;
    /* ⚠️ LA CASELLA STA A CAVALLO DEL BORDO, non dentro il riquadro.
       Prima stava nella fascia del padding (-17/-20) per non farsi tagliare dal
       bordo della card. Ora ci sta SOPRA: il segno di selezione appartiene alla
       riga, non al contenitore, e appoggiato sul filo si legge come una cosa che
       sporge invece che come una colonna in piu'.
       ⚠️ Sporge di POCO — e' un segno di multiselezione, non una colonna che
       si e' spostata fuori.
       ⚠️ Perche' funzioni serve l'ETICHETTA dietro (vedi qui sotto): senza, il
       bordo del riquadro le passerebbe attraverso. */
    left: -26px;
    top: 50%;
    /* ⚠️ `-50% + 2px` e non `-50%`: il centro GEOMETRICO della riga non e' il
       centro OTTICO. La riga ha il bordo in alto e niente in basso, e il testo
       ha l'ascendente piu' alto della discendente: una casella centrata sul
       calcolo sembra montata due pixel troppo in su. Scritto qui perche' e'
       esattamente il genere di numero che qualcuno un giorno «corregge». */
    transform: translateY(calc(-50% + 4px));
    opacity: 0;
    visibility: hidden;
    transition: opacity .15s ease;
}
/* ⚠️ IL DISCO CHE FINGE LO SFONDO. La casella e' TRASPARENTE per costruzione —
   ovunque, ed e' giusto: cosi' sta bene su qualunque superficie, chiara o scura,
   senza che nessuno debba dirle su cosa e' appoggiata (vedi `<#Check/>`). Ma a
   cavallo di un bordo quella trasparenza lascia passare la linea del riquadro
   proprio in mezzo al quadratino.
   Il rimedio NON e' dare uno sfondo alla casella — perderebbe la sua qualita'
   ovunque — ma metterne uno a chi la AVVOLGE, e solo dentro le griglie: un
   ritaglio del colore della superficie, che interrompe il bordo dietro di lei.
   Il `padding` e' cio' che gli da' corpo: senza, sarebbe grande quanto la
   casella e il bordo spunterebbe comunque agli angoli. */
.griglia .check-flottante {
    padding: 3px 3px 0px 3px;
    /* ⚠️ Raggio piccolo e SOLO a sinistra. Un cerchio sarebbe una bolla appoggiata
       sopra il bordo; smussando i due angoli che sporgono e lasciando vivi i due
       che entrano nella card, la stessa macchia si legge come un'ETICHETTINA che
       esce dal riquadro — che e' quello che la riga sta facendo davvero. */
    border-radius: 5px 0 0 5px;
    /* ⚠️ IL FONDO PIENO SERVE, ed era stato tolto per sbaglio insieme a quello
       delle righe. La casella sta FUORI dal pannello — sporge sul bordo, sopra
       la pagina — quindi non ha sotto nessuna superficie da cui staccarsi: senza
       un fondo suo galleggia direttamente sul fondale a gradiente e la spunta si
       legge appena.
       ⚠️ E non insegue piu' la zebra della riga, come faceva prima: da quando le
       righe sono veli sfumati non c'e' nessuna superficie alternata da
       pareggiare, e quel fondo alternato era proprio il residuo che si vedeva
       come una toppa. Un fondo solo, pieno, che segue il tema. */
    background: var(--n-bg-1);
    left: -35px; 
}
/* ⚠️ E il disco del flottante non ha piu' bisogno di inseguire la zebra: da
   quando le righe non hanno fondo non c'e' nessuna superficie alternata da
   pareggiare. Restava, dava una macchia piena su un pannello trasparente. */

.griglia.selezione-attiva .check-flottante { opacity: 1; visibility: visible; }

@media (max-width: 1230px) {
    .griglia .check-flottante { left: -30px; }
}
@media (max-width: 768px) {
    .griglia .check-flottante { left: -25px; }
}
@media (prefers-reduced-motion: reduce) {
    .griglia .check-flottante { transition: none; }
}

/* Il comando acceso si vede: pillola d'accento, come la voce attiva della
   sidebar. `aria-pressed` e' gia' lo stato — non serve una seconda classe, e
   cosi' quel che si vede e quel che viene annunciato non possono divergere. */
.sel-toggle[aria-pressed="true"] {
    background: var(--n-ac, #1a86bd);
    color: var(--n-ink, #fff);
    border-color: transparent;
}

/* ===========================================================================
   LA FINESTRA DI CONFERMA DI RIGA
   ---------------------------------------------------------------------------
   `position: fixed` e non `absolute`, ed e' l'unica scelta che funziona: il
   cestino sta dentro un contenitore che scorre (`overx-a`), e un pannello
   ancorato alla riga verrebbe TAGLIATO dal suo bordo — sull'ultima riga non si
   vedrebbe affatto. Fissa al viewport, invece, e' sempre intera e sempre al
   centro.

   La riga `:not([open])` e' una cintura: i browser nascondono da soli il
   contenuto di un <details> chiuso, ma lo fanno con meccanismi diversi
   (`content-visibility` su Chrome), e un elemento `fixed` e' esattamente il caso
   in cui le differenze si vedono.
   =========================================================================== */

details:not([open]) > .modale { display: none; }

.modale {
    position: fixed;
    inset: 0;
    z-index: 60;
    /* La finestra nasce dentro l'ultima cella della riga, che e' allineata a
       DESTRA: senza questa riga il testo della domanda eredita quell'allineamento
       e la finestra esce storta. */
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(9, 9, 16, .5);
}

/* ===========================================================================
   IL ROSSO — l'unico colore fisso, e il motivo per cui e' fisso
   ---------------------------------------------------------------------------
   ⚠️ NON si puo' usare `tx-w`: quello e' il ruolo «massimo contrasto», che sul
   tema CHIARO vale quasi-nero — testo scuro su fondo rosso.

   ⚠️ E IL FONDO DEVE ESSERE DAVVERO FISSO. Questo commento diceva «il bianco su
   rosso e' bianco in entrambi i temi, perche' il fondo e' fisso anche lui», ma
   il fondo era `var(--v-err)` — che il blocco del tema scuro RIDICHIARA. Il
   risultato, misurato il 16/09/2026: bianco su #d64545 (chiaro) = 4,38:1, sotto
   il 4,5:1 che un testo normale pretende; bianco su #ef7676 (scuro) = 2,79:1,
   sotto perfino il 3:1 di una forma. Il tasto piu' pericoloso del pannello era
   il meno leggibile, e solo al passaggio del mouse (#c23a3a, 5,30:1) tornava a
   posto.

   Adesso il fondo e' un esadecimale VERO e uguale nei due temi — il commento
   descrive di nuovo il file — e il bianco ci sta sopra a 5,30:1.

   ⚠️ NON si usa `--n-err`: quello e' l'INCHIOSTRO dello stato (il colore con cui
   si SCRIVE «sbagliato»), e nel tema scuro e' un rosso schiarito, fatto per
   essere letto su un fondo scuro. Come fondo di un tasto pretenderebbe un
   inchiostro scuro sopra, cioe' un secondo ruolo che PULSAR non ha: e finche'
   nessuno lo chiede, un colore fisso e misurato e' piu' onesto di una coppia
   inventata.
   =========================================================================== */

.pericolo        { background: #c23a3a; color: #fff; }
.pericolo:hover  { background: #a93030; }

/* Il cestino di riga si accende di rosso, non di grigio: e' l'unico comando
   della riga che non si annulla. Il selettore e' piu' lungo del necessario
   perche' deve battere l'`hover:tx-0` dell'alias `azione-riga`, e app.css si
   carica PRIMA del foglio di PULSAR. */
.griglia .azione-pericolo:hover { color: var(--v-err); }

/* ===========================================================================
   LA CASELLA GLOBALE A META': il trattino
   ---------------------------------------------------------------------------
   `<#Check>` disegna la spunta come un SVG acceso da `peer-checked`, e lo stato
   `indeterminate` — «alcune si', altre no» — non e' ne' spuntato ne' vuoto:
   senza questa regola la casella in testata sembrerebbe VUOTA mentre tre righe
   sono selezionate. E' esattamente il fallimento silenzioso che questo progetto
   evita: nessun errore, solo un comando che dice il falso.

   Sta nel PROGETTO e non in PULSAR perche' oggi ha un consumatore solo. Il
   giorno che un secondo progetto lo chiede, la promozione e' gia' scritta: una
   variante `peer-indeterminate` accanto a `peer-checked` in css.rs, e queste
   righe spariscono.

   ⚠️ `:has()` e non un fratello: il trattino sta sullo ::after del CONTENITORE
   (l'unico elemento con `position: relative` gia' addosso), e un ::after non e'
   fratello di niente.
   =========================================================================== */

.check-tutti label > span:has(input:indeterminate)::after {
    content: "";
    position: absolute;
    left: 25%;
    right: 25%;
    top: 50%;
    height: 2px;
    margin-top: -1px;
    border-radius: 1px;
    background: var(--n-ac, #1a86bd);
}

/* ===========================================================================
   IL TITOLO DI PAGINA — un gradiente, non un colore
   ---------------------------------------------------------------------------
   Dall'accento a un blu leggermente piu' scuro. Il colore di partenza NON
   e' scritto: e' `--n-ac`, cioe' l'accento del tema. Cosi' il titolo segue la
   palette da se' — se un giorno l'accento cambia, cambia anche questo, e nessuno
   deve ricordarsi di venire qui.

   ⚠️ `color-mix` e non due colori a mano: scurire l'accento CALCOLANDOLO tiene i
   due estremi legati. Scritti a mano sarebbero due valori che divergono al primo
   ritocco della palette, e la sfumatura diventerebbe da un blu a un blu che non
   c'entra.

   ⚠️ **`@supports`, e non e' prudenza teorica.** `background-clip: text` vuole
   `color: transparent` per funzionare: dove non e' sostenuto, il testo resta
   trasparente — cioe' il titolo SPARISCE. Un fallimento silenzioso completo, su
   ogni pagina. Dentro la guardia, chi non lo sostiene tiene il colore pieno che
   fonts.css gli ha gia' dato.

   ⚠️ Solo `.topbar h1`, cioe' il TITOLO DELLA PAGINA. Un h1 dentro una card o
   sulla pagina d'accesso resta inchiostro normale: un gradiente su ogni titolo
   della pagina smette di dire "questa e' la pagina in cui sei" e diventa una
   decorazione che si ignora.
   =========================================================================== */

/* ⚠️ IL GRADIENTE E' PASSATO DAL TESTO ALLA BARRA.
   Era il riempimento dell'h1 (`background-clip: text`): la stessa formula, letta
   sullo stesso `--n-ac`, adesso riempie la topbar intera e la scritta ci sta
   sopra piena. Due ragioni per cui e' meglio qui:
   · un gradiente su una scritta lo si vede se la si cerca; su una fascia alta
     sessanta pixel lo si vede e basta;
   · e da quando l'accento segue la SEZIONE, la barra diventa il segno piu'
     grande di «dove sei» — prima lo era una riga di testo.
   ⚠️ Niente piu' `background-clip: text` ne' `-webkit-text-fill-color`: erano li'
   per riempire le lettere, e con loro sparisce anche la regola su `::selection`
   che serviva a non far diventare invisibile il testo evidenziato.

   ⚠️ IL `body` DAVANTI: il foglio di PULSAR e' caricato dopo questo, e la barra
   porta dei token nel markup. Senza l'antenato, a parita' di specificita' vince
   lui e il fondo resta quello dei token — in silenzio. */
body .topbar {
    /* ⚠️ 260 e non 100: e' lo stesso gradiente RIFLESSO in orizzontale. Lo
       specchio manda l'angolo θ in 360−θ, quindi 100 → 260 — non in 280 come
       verrebbe da fare sommando 180, che invece lo ribalta in VERTICALE e
       scambia anche l'inclinazione. La tinta piena resta a destra, il fondo
       scurito passa a sinistra. */
    background-image: linear-gradient(
        260deg,
        var(--n-ac, #1a86bd) 0%,
        color-mix(in srgb, var(--n-ac, #1a86bd) 78%, #000) 100%
    );
}

/* ⚠️ La scritta e tutto cio' che le sta accanto prendono `--n-ink`, che E' il
   ruolo «il testo sopra l'accento»: bianco nel chiaro, scuro nello scuro. Non e'
   un bianco scritto a mano — sul tema scuro l'accento e' chiaro, e un bianco
   fisso lascerebbe il titolo a 1,7:1, cioe' illeggibile.
   ⚠️ Vale anche per il comando dell'hamburger, che stava a `tx-2` (un grigio
   smorzato): su una fascia colorata sparirebbe. */
body .topbar h1,
body .topbar > button { color: var(--n-ink, #fff); }
body .topbar > button svg { color: inherit; }

/* Sul tema scuro l'accento e' gia' chiaro: si scurisce di meno, o il secondo
   estremo perde contrasto contro il fondo. */
body.theme-dark .topbar {
    background-image: linear-gradient(260deg, var(--n-ac, #6abaea) 0%,
        color-mix(in srgb, var(--n-ac, #6abaea) 84%, #000) 100%);
}
@media (prefers-color-scheme: dark) {
    body.theme-auto .topbar {
        background-image: linear-gradient(260deg, var(--n-ac, #6abaea) 0%,
            color-mix(in srgb, var(--n-ac, #6abaea) 84%, #000) 100%);
    }
}

/* Il logo è un bottone solo quando serve: da sidebar aperta non risponde al
   puntatore, così un clic distratto non collassa il menu. */
.logo-apri { pointer-events: none; cursor: default; }

/* La freccia del logo: non c'è finché la sidebar è aperta — lì il comando ce
   l'ha gia', e un secondo segno per lo stesso gesto e' rumore. */
.logo-freccia { display: none; transition: transform .15s ease, color .15s ease; }
@media (prefers-reduced-motion: reduce) { .logo-freccia { transition: none; } }

/* Il comando di riduzione sale di 5px.
   ⚠️ Non e' un capriccio di allineamento: la riga li centra tutti e due sul
   loro riquadro, ma il marchio predefinito porta sotto una dicitura
   — quindi la PAROLA sta nella meta' alta del suo box, e un bottone
   centrato sul box sembra montato basso. Si allinea a cio' che si legge, non a
   cio' che si misura. `transform` e non `top`: non sposta il layout, quindi la
   riga non cambia altezza. */
.sidebar-toggle { transform: translateY(-5px); }

/* ===========================================================================
   IL FOGLIO DEI PERMESSI — il comando a tre stati
   ---------------------------------------------------------------------------
   Tre segmenti attaccati: `–` eredita · `✓` consente · `✕` nega. Sono RADIO,
   non bottoni: il gruppo e' uno stato solo, e la tastiera li percorre come un
   gruppo — cosa che tre bottoni non farebbero.

   ⚠️ Il radio e' invisibile ma NON `display:none`: quello lo toglierebbe dal
   giro della tastiera, e un foglio di decine di celle che si puo' compilare solo col
   mouse non e' compilabile. Sta li', largo un pixel, e a disegnare e' il
   fratello (`peer-checked` di PULSAR).
   =========================================================================== */

.perm-cella { display: inline-flex; gap: 2px; }
.perm-cella > label { position: relative; display: inline-flex; }

.perm-seg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 24px;
    border: 0;
    border-radius: 6px;
    background: var(--n-bg-2, #f5f5f5);
    color: var(--n-tx-2, #8a949c);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    transition: background .12s ease, color .12s ease, box-shadow .12s ease;
}
.perm-cella > label:hover .perm-seg,
button.perm-seg:hover { color: var(--n-tx-0, #14181a); }

/* Il segmento SCELTO. Il verde e il rosso non sono ruoli della palette (PULSAR
   non ha ancora ok/warn/err), quindi vivono qui — ed e' lo stesso posto dove
   sta il rosso del cestino, che aspetta la stessa promozione. */
/* ⚠️ IL SEGNO SELEZIONATO TIENE IL SUO COLORE. Prima la pastiglia si riempiva
   di verde (o di rosso) e l'icona passava a bianco: il segno spariva proprio
   nell'istante in cui lo si era appena scelto, e a distanza di un metro dallo
   schermo restava un rettangolo colorato senza piu' dentro il disegno che dice
   COSA si e' scelto. Ora l'inchiostro non cambia mai — grigio la freccia, verde
   la spunta, rosso la croce — e a dire quale e' attivo e' un ANELLO del suo
   stesso colore. Vedi anche la nota sulla pastiglia, sopra. */
.perm-cella input:checked + .perm-seg {
    box-shadow: inset 0 0 0 1px currentColor;
    font-weight: 600;
}

/* ⚠️ SPENTA vuol dire CHIUSA PIU' IN ALTO, non «guasta»: si vede che c'e' e non
   si preme. Il fumetto (title) dice perche', ed e' la risposta alla domanda che
   fa l'assistenza — «perche' questo non puo'?» — data nel punto in cui si
   guarda, invece che da ricostruire. */
.perm-cella input:disabled + .perm-seg { opacity: .35; cursor: not-allowed; }
.perm-cella:has(input:disabled) { opacity: .7; }

/* ⚠️ Anche qui la zebra e' un velo sfumato, e la variabile e' LA STESSA: due
   tabelle vestite con lo stesso tessuto devono leggerlo dallo stesso posto, o il
   giorno che si ritocca una l'altra resta indietro. */
.permessi tbody tr:nth-child(even) { background: var(--v-riga-alt); }
.permessi tbody td { border-top: 1px solid var(--n-bd, #e4e6ea); }
.permessi table { border-collapse: separate; border-spacing: 0; }

@media (prefers-reduced-motion: reduce) { .perm-seg { transition: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   LA SCALA DEI RUOLI — il pannello permessi, colonna a sinistra
   ---------------------------------------------------------------------------
   Erano schede in cima, e le schede dicono «due cose pari». I ruoli non sono
   pari: sono una scala, e tutto il pannello si regge su quella («si cambia solo
   verso il basso»). In colonna e rientrati, la gerarchia SI VEDE invece di
   doverla leggere in un paragrafo.
   ═══════════════════════════════════════════════════════════════════════════ */

.perm-scala { display: block; }
/* ⚠️ Fondo, filo e ombra NON sono qui: li da' `class="vetro-lettura"` sul
   markup, come a ogni altro pannello. Erano scritti a mano (`background:
   var(--n-bg-1)` piu' un bordo grigio) e il riquadro RUOLI restava l'unica
   superficie PIENA in mezzo a pannelli di vetro — si notava subito.
   Qui resta solo cio' che e' suo: il raggio e la disposizione. Il raggio sta
   fuori dalla media query perche' il vetro c'e' a ogni larghezza, e un fondo con
   gli angoli vivi in mezzo a pannelli arrotondati e' peggio di nessun fondo. */
.perm-ruoli { margin-bottom: 16px; border-radius: 12px; }

/* ⚠️ SOTTO i 768px la colonna NON esiste: una barra laterale da 200px su un
   telefono lascia al foglio 120px, e il foglio è una tabella di decine di celle.
   Sopra, diventa colonna — ed è l'unico punto in cui cambia qualcosa. */
@media (min-width: 768px) {
    .perm-scala  { display: flex; align-items: flex-start; gap: 20px; }
    .perm-ruoli  {
        flex: 0 0 210px;
        margin-bottom: 0;
        position: sticky;
        top: 20px;
        padding: 14px 12px;
    }
    /* ⚠️ `min-width: 0` sul FOGLIO, non solo `flex: 1`: un figlio flex ha
       `min-width: auto`, cioè non si stringe sotto il proprio contenuto. Senza,
       la tabella larga sfonda il contenitore invece di far comparire la propria
       barra di scorrimento, e a scorrere diventa tutta la pagina. */
    .perm-foglio { flex: 1 1 auto; min-width: 0; }
}

.perm-ruoli-titolo {
    margin: 0 0 8px;
    font-size: 12px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--n-tx-2, #6b7280);
}
.perm-ruoli ul { list-style: none; margin: 0; padding: 0; }
.perm-ruoli li { margin: 0; }

/* IL RIENTRO È IL LIVELLO. Un dato, non una decorazione: il bordo a sinistra
   disegna il filo della discendenza, come l'albero dei gruppi di Joomla. */
.ruolo-liv0 { padding-left: 0; }
.ruolo-liv1 { padding-left: 14px; }
.ruolo-liv2 { padding-left: 28px; }
.ruolo-liv1, .ruolo-liv2 { border-left: 1px solid var(--n-bd, #e4e6ea); margin-left: 6px; }

.ruolo-voce {
    display: block;
    padding: 7px 10px;
    margin: 2px 0;
    border-radius: 8px;
    font-size: 14px;
    line-height: 1.2;
    text-decoration: none;
    color: var(--n-tx-1, #374151);
}
/* ⚠️ `--n-hov` e non `--n-bg-2`: il primo e' il RUOLO «superficie sotto il
   puntatore» ed e' un velo, il secondo e' il grigio pieno delle righe alternate.
   Su un pannello di vetro un fondo pieno rimette una campitura opaca. */
a.ruolo-voce:hover { background: var(--n-hov, rgba(17,24,39,.07)); color: var(--n-tx-0, #14181a); }

.ruolo-attivo,
a.ruolo-attivo:hover {
    background: var(--n-ac, #1f7ae0);
    color: var(--n-ink, #fff);
    font-weight: 600;
}

/* ⚠️ Spento ma PRESENTE, e con il cursore che lo dice. Toglierlo dall'elenco
   avrebbe nascosto dove si sta — che è l'informazione più importante qui. */
.ruolo-spento {
    color: var(--n-tx-2, #6b7280);
    opacity: .6;
    cursor: help;
}


/* ═══════════════════════════════════════════════════════════════════════════
   IL COLORE DEL FOGLIO PERMESSI — cosa il ruolo puo' fare ADESSO
   ---------------------------------------------------------------------------
   Il foglio ha decine di celle e quasi tutte stanno su «ereditato»: senza colore e'
   una distesa grigia, e per sapere se il Manager puo' cancellare un canale
   bisogna passarci sopra col mouse, una cella per volta. La tinta dice il
   valore EFFETTIVO — la stessa cosa che il badge rosso «Non consentita
   (Predefinito)» dice in Joomla, senza mettere un badge per cella.

   ⚠️ TINTE MOLTO TENUI (4-6%). Con decine di celle una saturazione normale diventa
   una scacchiera che stanca dopo dieci secondi, e il segno che conta davvero —
   lo SCOSTAMENTO scelto, pieno e in negativo — non si distinguerebbe piu' dal
   fondo. Il fondo racconta, il segno pieno decide.
   ═══════════════════════════════════════════════════════════════════════════ */

.permessi td.perm-eff-si { background: var(--v-ok-soft); }
.permessi td.perm-eff-no { background: var(--v-err-soft); }

/* Chiusa piu' in alto: non e' «negata qui», e' «non c'e' niente da decidere».
   Grigia e a righe, cosi' si legge come una cella fuori gioco invece che come
   un rifiuto scelto da qualcuno in questa pagina. */
.permessi td.perm-cap {
    background: repeating-linear-gradient(
        135deg,
        transparent 0 5px,
        rgba(127, 127, 127, .10) 5px 10px
    );
}

/* ⚠️ LA SCELTA ESPLICITA VINCE SULLA TINTA EREDITATA, e dal vivo: `:has()`
   guarda il radio dentro la cella, quindi il fondo cambia al click senza una
   riga di JavaScript e senza ricaricare. La tinta del server resta quella
   giusta per il caso «ereditato», che e' l'unico che il CSS non puo' sapere.
   La specificita' basta da se': `td:has(input[...]:checked)` batte `.perm-eff-*`. */
.permessi td:has(input[value="allow"]:checked) { background: color-mix(in srgb, var(--v-ok) 14%, transparent); }
.permessi td:has(input[value="deny"]:checked)  { background: color-mix(in srgb, var(--v-err) 14%, transparent); }

/* I due segni portano il proprio colore anche DA SPENTI, smorzato: cosi' il
   comando si legge come un semaforo invece che come tre glifi grigi, e quando
   si sceglie non cambia colore — si accende. */
/* ⚠️ NON legate a `.perm-cella`: il segno deve avere il suo colore ovunque
   compaia — nella cella, nel comando di riga e soprattutto nella LEGENDA, che
   sta fuori da quel contenitore. Legandole, la legenda usciva grigia: cioe'
   proprio la riga che spiega i tre segni non li mostrava come sono. */
.perm-si { color: var(--v-ok); }
.perm-no { color: var(--v-err); }
.perm-cella input:not(:checked) + .perm-si,
.perm-cella input:not(:checked) + .perm-no { opacity: .5; }
.perm-cella > label:hover .perm-si,
.perm-cella > label:hover .perm-no { opacity: 1; }


/* LA LEGENDA dei tre comandi. Una riga, e toglie la domanda «cosa vuol dire
   quel segno?» a chiunque apra il pannello per la prima volta. */
.perm-legenda {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 16px;
    margin: 0 0 16px;
    font-size: 13px;
    color: var(--n-tx-2, #6b7280);
}
.perm-legenda > span { display: inline-flex; align-items: center; gap: 6px; }
/* ⚠️ I segni della legenda NON sono comandi: niente cursore a manina e niente
   reazione al passaggio, o si prova a cliccarli. */
.perm-legenda .perm-seg { cursor: default; }
.perm-legenda-nota { color: var(--n-tx-2, #6b7280); opacity: .85; }
@media (max-width: 767px) { .perm-legenda-nota { flex-basis: 100%; } }

/* ═══════════════════════════════════════════════════════════════════════════
   LA SELEZIONE STA NELLA PASTIGLIA, NON NEL COLORE DEL SEGNO
   ---------------------------------------------------------------------------
   La freccia dell'ereditato, nella griglia, usciva PIU' SCURA che nell'ultima
   colonna: nelle celle e' selezionata e prendeva `tx-0`, nei comandi di riga
   non c'e' nessuno stato e restava grigia. Due grigi diversi per lo stesso
   segno, a quattro colonne di distanza.

   Ora il segno ha SEMPRE il suo colore — grigio la freccia, verde la spunta,
   rosso la croce — e a dire quale e' scelto e' il FONDO. E' anche il motivo per
   cui prima il colore scuro serviva: la pastiglia c'era sotto tutti e tre, e non
   distingueva niente.

   ⚠️ `.perm-cella > label` e non `.perm-cella`: cosi' tocca SOLO i tre radio di
   una cella. I comandi di riga (`button.perm-seg`, senza label attorno) restano
   come sono — sono comandi, non stati, e sono il riferimento a cui la griglia si
   sta allineando.
   ═══════════════════════════════════════════════════════════════════════════ */

.perm-cella > label .perm-seg { background: transparent; }
/* ⚠️ `--n-bg-1` (la superficie) e non `--n-bg-2`: la cella sotto ha gia' la sua
   tinta di stato (verde o rossa tenue), e una pastiglia grigia su quella si
   confonderebbe. La superficie e' l'unico fondo che si stacca da tutt'e due. */
.perm-cella input:checked + .perm-seg { background: var(--n-bg-1, #fff); }

/* ⚠️ Nella legenda si colora il SEGNO, non la parola. `#2e9e6b` su fondo chiaro
   dà un contrasto di 3:1 — sotto il 4,5:1 che serve a un testo di 13px — quindi
   "Consenti" in verde sarebbe più difficile da leggere proprio per chi ha già
   difficoltà. Il colore lo porta il disegno, il significato la parola. */
.perm-legenda > span { color: var(--n-tx-2, #6b7280); }
.perm-legenda .perm-seg { flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   IL FOGLIO CALCOLATO nella scheda di una persona — SOLA LETTURA
   ---------------------------------------------------------------------------
   Stesso vocabolario del pannello permessi, e non e' pigrizia: due alfabeti
   diversi per la stessa cosa a due pannelli di distanza sarebbero due cose da
   imparare invece di una. Verde/rosso = cosa puo'; ANELLO = deciso su questa
   persona invece che ereditato dal ruolo.
   ═══════════════════════════════════════════════════════════════════════════ */

.perm-letto {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 24px;
    border-radius: 6px;
    /* ⚠️ Niente `cursor: pointer` e niente reazione al passaggio: qui non si
       clicca niente, e un segno che si illumina invita a provarci. */
    cursor: default;
}
.perm-deciso {
    background: var(--n-bg-1, #fff);
    box-shadow: inset 0 0 0 2px currentColor;
}
.perm-letto .perm-si,
.perm-letto .perm-no { display: inline-flex; }

/* Un'azione che NON ESISTE: un trattino spento, non una croce rossa. Non e'
   "negata" — nessuno l'ha tolta a nessuno — ed e' il motivo per cui la cella
   sotto porta la stessa trama grigia di una chiusa piu' in alto: in tutti e due
   i casi non c'e' niente da decidere. */
.perm-nulla { color: var(--n-tx-2, #8a949c); opacity: .5; }

/* LA FRECCIA DELL'EREDITATO porta l'ACCENTO, cioe' il colore sociale del progetto
   (`--n-ac`: vedi la mappa in cima a questo file — «sociale1 -> se e' il colore
   guida del progetto, e' --n-ac»). Segue il tema da se', chiaro e scuro.

   ⚠️ Non e' decorazione: dei tre segni l'ereditato e' quello NORMALE — la
   stragrande maggioranza delle celle sta li'. Lasciarlo grigio lo faceva
   leggere come «spento», cioe' come la meno importante delle tre scelte, mentre
   e' quella che regge tutto il pannello: e' il foglio del ruolo che decide.
   Verde e rosso restano gli stati di eccezione, e si distinguono da soli.

   ⚠️ E l'anello della selezione usa `currentColor`, quindi diventa blu con lei
   senza una riga in piu': una sola variabile, due segni che non possono
   divergere. */
.perm-er { color: var(--n-ac, #1a86bd); }

/* ═══════════════════════════════════════════════════════════════════════════
   I MESSAGGI — una classe, quattro stati, e un colore che dice qualcosa
   ---------------------------------------------------------------------------
   Prima c'era un solo alias `alert`: bordo grigio, fondo bianco, nessuna
   differenza fra «salvato» e «non ho potuto salvare». Il colore in
   un'interfaccia gestionale non e' decorazione — e' la sola cosa che si legge
   scorrendo, e un messaggio senza stato costringe a leggerlo per sapere se e'
   una buona notizia.

   ⚠️ GLI STATI SONO QUATTRO E NON DIECI. Ogni stato in piu' e' una sfumatura
   che chi scrive deve scegliere e chi legge deve imparare; sopra i quattro si
   smette di distinguerli e si guarda solo il testo — cioe' si torna al punto di
   partenza, con piu' CSS.

     successo    e' andata
     attesa      sta succedendo, o dipende da qualcun altro
     allarme     non e' andata, e serve fare qualcosa
     incompleto  manca un pezzo, ma niente e' rotto

   ⚠️ IL COLORE NON E' L'UNICO SEGNO. Ogni stato porta un'ICONA e un ruolo ARIA:
   chi non distingue il verde dal rosso — una persona su dodici fra gli uomini —
   leggerebbe quattro riquadri identici. E la barra a sinistra da' un secondo
   appiglio anche in bianco e nero, o su uno schermo sbiadito dal sole (una
   scrivania con la finestra alle spalle e' il caso normale, non quello raro).
   ═══════════════════════════════════════════════════════════════════════════ */

.msg {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0 0 16px;
    padding: 11px 14px;
    /* Il bordo tutt'intorno è dello STESSO colore della barra a sinistra
       (chiesto il 05/10/2026): la barra resta più spessa, il resto lo chiude. */
    border: 1px solid var(--msg-ac);
    border-left: 4px solid var(--msg-ac);
    border-radius: 10px;
    background: var(--msg-bg);
    /* ⚠️ `--msg-ink` e non `--msg-ac`: il segno e il testo hanno due requisiti di
       contrasto diversi (3:1 per una forma, 4,5:1 per una frase di 14px). Vedi
       la nota sulla tavolozza. */
    color: var(--msg-ink);
    font-size: 14px;
    line-height: 1.45;
}
.msg svg { flex: 0 0 auto; margin-top: 1px; color: var(--msg-ac); }
.msg-testo { min-width: 0; }
.msg-titolo { display: block; font-weight: 600; margin-bottom: 2px; }

.msg-successo   { --msg-ink: var(--v-ok-ink); --msg-ac: var(--v-ok);   --msg-bg: var(--v-ok-soft); }
.msg-attesa     { --msg-ink: var(--n-ac); --msg-ac: var(--n-ac);   --msg-bg: rgba(26,134,189,.07); }
.msg-allarme    { --msg-ink: var(--v-err-ink); --msg-ac: var(--v-err);  --msg-bg: var(--v-err-soft); }
.msg-incompleto { --msg-ink: var(--v-warn-ink); --msg-ac: var(--v-warn); --msg-bg: var(--v-warn-soft); }



/* ═══════════════════════════════════════════════════════════════════════════
   UNA RIGA CHE SCORRE DI LATO — ovunque (dal 06/10/2026)
   ---------------------------------------------------------------------------
   Un contenitore con `data-nova-orizzontale` (scrollbar.js della scatola, vedi
   PULSAR) sta su una riga sola e scorre di lato, con la rotella anche; i suoi
   elementi non si stringono, e sfuma dal lato dove c'e' ancora qualcosa da
   vedere — lo dicono `data-nova-sx` e `data-nova-dx`, che la scatola tiene
   aggiornati. Oggi la barra degli elenchi; domani ogni fila di badge. Chi
   la usa aggiunge solo la sua misura (padding, bordo): prima ogni fila ripeteva
   queste righe. */
[data-nova-orizzontale] { display: flex; flex-wrap: nowrap; overflow-x: auto; gap: 6px; }
[data-nova-orizzontale] > * { flex: none; }
[data-nova-orizzontale][data-nova-dx] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent);
}
[data-nova-orizzontale][data-nova-sx] {
    -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 36px), transparent);
            mask-image: linear-gradient(to left, #000 calc(100% - 36px), transparent);
}
[data-nova-orizzontale][data-nova-sx][data-nova-dx] {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent);
            mask-image: linear-gradient(to right, transparent, #000 36px, #000 calc(100% - 36px), transparent);
}

/* ═══════════════════════════════════════════════════════════════════════════
   APRIBILE — una riga che si apre, dentro un pannello (12/10/2026)
   ---------------------------------------------------------------------------
   Il markup è sempre lo stesso, e si scrive nella view:

       <details class="apribile"[ open]>
           <summary>…la riga…</summary>
           <div|form class="apribile-corpo">…ciò che si apre…</div|form>
       </details>

   ⚠️ NON è un componente, e non per scelta: un componente di NOVA non ha un
   «dentro» (le sue prop sono dati, non markup), e qui dentro ci vanno moduli
   interi. `<details>` apre e chiude da sé, senza JavaScript, e si chiude da
   tastiera come un bottone. Nasce per i mittenti di un canale; serve a ogni
   elenco di cose da aprire una alla volta.

   Ogni riga è un PANNELLO con la tinta tenue della sezione (una cosa
   dell'elenco), e un «aggiungi» che si apre è un TASTO pieno d'accento
   (`apribile apribile-comando`): la regola della veste, tenue per ciò che è
   scelto e pieno per i comandi. La freccia è quella della tendina dei
   discorsi: in giù chiusa, in su aperta. */
.apribile {
    margin-top: 8px;
    padding: 0 14px;
    border-radius: 12px;
    /* UN PANNELLO, non una riga col filo (pannello e tasto vanno
       distinti): la tinta TENUE della sezione, che
       nella veste vuol dire «una cosa dell'elenco»; il comando che aggiunge è
       pieno (`apribile-comando`, qui sotto). */
    background: color-mix(in srgb, var(--n-ac) 6%, transparent);
}
.apribile > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    /* Il margine negativo porta il velo del passaggio fino al bordo del
       pannello, senza spostare il testo. */
    margin: 0 -14px;
    padding: 11px 14px;
    border-radius: 12px;
    /* LA RIGA È UN COMANDO, e si veste da comando: l'accento della sezione,
       un filo di peso. Il colore sta QUI e non sulle singole righe della view,
       così ogni `apribile` nuova nasce già giusta. */
    color: var(--n-ac);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}
.apribile > summary:hover { background: color-mix(in srgb, var(--n-ac) 7%, transparent); }
.apribile[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.apribile > summary::-webkit-details-marker { display: none; }
.apribile > summary::after {
    content: "";
    width: 6px;
    height: 6px;
    margin: -3px 4px 0 auto;
    border-right: 1.6px solid currentColor;
    border-bottom: 1.6px solid currentColor;
    transform: rotate(45deg);
    flex: none;
}
.apribile[open] > summary::after { transform: rotate(-135deg); margin-top: 3px; }
.apribile > summary:focus-visible { outline: 2px solid var(--n-ac); outline-offset: 2px; }
.apribile-corpo { display: block; padding: 4px 0 18px; }

/* IL COMANDO CHE SI APRE — «Aggiungi un mittente», e ogni «aggiungi» che verrà:
   lo stesso <details>, vestito da TASTO pieno d'accento con l'inchiostro
   sopra (`--n-ink`: bianco nel chiaro, scuro nello scuro). Niente pannello
   attorno finché è chiuso: un comando non è una cosa dell'elenco. */
.apribile-comando { margin-top: 14px; padding: 0; background: none; }
.apribile-comando > summary {
    display: inline-flex;
    margin: 0;
    padding: 8px 14px;
    border-radius: 10px;
    background: var(--n-ac);
    color: var(--n-ink, #fff);
    font-size: 13.5px;
}
.apribile-comando > summary::before { content: "+"; font-weight: 700; }
.apribile-comando > summary:hover { background: color-mix(in srgb, var(--n-ac) 86%, #000); }
.apribile-comando[open] > summary { border-radius: 10px; }
.apribile-comando > summary::after { margin-left: 4px; }
.apribile-comando > .apribile-corpo { padding: 14px 0 4px; }
