/* ── Reset & Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Qui c'era "color-scheme: only light". Il motivo era vero: con l'iPhone in
     scuro, senza, WebKit dipingeva di nero la fascia dietro la Dynamic Island
     mentre la pagina restava chiara, e si vedeva una banda nera in cima.
     Il motivo resta, la soluzione no: dichiarare "so fare solo il chiaro"
     impediva per sempre di avere un tema scuro. Adesso si dichiara quello che
     l'app sa fare davvero, e la fascia torna coerente da sola perche' i due
     temi esistono entrambi. */
  color-scheme: light dark;
  /* ── I COLORI DI STATO ────────────────────────────────────────────────────
     Erano quelli di sistema di iOS 7, e sono nati per essere usati DA iOS: su
     fondi suoi, col suo rendering. Qui facevano due mestieri per cui non erano
     fatti — testo su bianco (il verde a 2,22, l'arancio a 2,20) e fondo pieno
     col bianco sopra (stessi numeri) — e non ne passavano nessuno dei due.

     Questi sono gli stessi colori portati dove si leggono: stessa famiglia,
     stesso significato, tono piu' cupo. Verde 6,07 · arancio 5,74 · rosso 6,54
     · azzurro 5,96, sia come testo sia col bianco sopra.

     Il tono VIVO non sparisce: resta nei veli qui sotto, dove serve un fondo
     colorato senza doverci leggere niente. */
  --blue:   #1a63b8; --green:  #16713b; --orange: #965700;
  --red:    #b3261e; --purple: #4b49b8; --pink:   #c4234a; --teal: #186a7b;
  /* Colori fissi dei post-it: non seguono il tema di proposito (sono carta,
     non una superficie), ma passano da un token invece che da un esadecimale
     scritto nella regola. */
  --sticky-yellow: #FFF3A0;
  --sticky-pink:   #FFD3E6;
  --sticky-green:  #CFF3C8;
  --sticky-blue:   #CDEBFB;
  /* Colori fissi dell'editor PDF ortopedico (crocette/testo sulla scansione di
     un modulo cartaceo): non seguono il tema di proposito, ma passano da un
     token invece che da un esadecimale scritto nella regola. */
  --ortho-ann-red: #E01E1E;
  --ortho-ann-ink: #141414;
  --ortho-ann-hl:  rgba(255,255,80,.55);
  --ortho-toolbar-bg: #3a3a3c;
  --ortho-toolbar-fg: #ffffff;

  /* I veli: fondo appena tinto per i contrassegni. Un contrassegno con il fondo
     pieno e la scritta bianca urla, e messo dieci volte su una schermata la fa
     sembrare un gioco. Con un velo e la scritta cupa dice la stessa cosa senza
     alzare la voce — e si legge (5,42 · 5,12 · 5,43 · 4,96). */
  --velo-ok:      #e3f7e8;
  --velo-attesa:  #fff0db;
  --velo-errore:  #ffe4e2;
  --velo-info:    #dbecff;
  --gray1:  #8E8E93; --gray2:  #AEAEB2; --gray3:  #C7C7CC;
  --gray4:  #D1D1D6; --gray5:  #E5E5EA; --gray6:  #F2F2F7;
  /* Il fondo ha un filo di azzurro invece di essere un grigio perfettamente
     neutro: un neutro puro legge come "non scelto", questo legge come scelto.
     E' il valore del ridisegno del Piano Ferie, portato a tutta l'app perche'
     e' lo stesso ruolo. */
  --bg:     #f4f6f8; --card:   #FFFFFF;
  --text:   #15181c; --text2:  #4d545c; --text3:  #6e757d;
  /* --accent NON e' un colore scritto qui: e' derivato da --accento-grezzo,
     che scrive il codice all'avvio (vedi applySettings). Cosi' il tema puo'
     ricamarci sopra — nel chiaro si usa tale e quale, nello scuro si schiarisce.
     Se il grezzo non c'e' ancora, si ripiega sull'azzurro. */
  --accent: var(--accento-grezzo, var(--blue));
  /* Cosa si scrive SOPRA l'accento. Nel chiaro l'accento e' cupo e ci va il
     bianco; nello scuro diventa chiaro e ci vuole l'inchiostro. */
  --su-accento: #ffffff;
  /* Cosa si scrive sopra un colore di STATO pieno (i contrassegni). Stessa
     storia: nel chiaro i colori sono cupi e prendono il bianco, nello scuro
     sono chiari e il bianco ci sparisce sopra — misurato fra 1,78 e 2,74. */
  --su-colore: #ffffff;
  /* Il fondo dei riquadri di nota. Era usato cinque volte come
     var(--bg2, #f5f5f7) senza essere MAI definito: cadeva sempre sul grigio
     chiaro scritto a mano, che in tema scuro diventa un riquadro bianco con
     sopra del testo chiaro (1,56 misurati). */
  --bg2: #f5f5f7;
  /* ── GLI ARROTONDAMENTI ────────────────────────────────────────────────
     Cinque gradini, assegnati per RUOLO e non a occhio. Prima erano 19 valori
     diversi: le schede stavano fra 12 e 20 a seconda di quando erano nate, e i
     contrassegni erano meta' pillole e meta' rettangolini. Nessuno di questi
     scarti si nota da solo — si nota tutto insieme, ed e' quello che fa
     sembrare un'interfaccia messa insieme invece che disegnata. */
  --r-xs:   8px;   /* comandi bassi, contrassegni squadrati, caselle */
  --r-sm:  10px;   /* bottoni, campi, righe selezionabili */
  --r-md:  14px;   /* schede */
  --r-lg:  18px;   /* pannelli, finestre, tendine */
  --r-full: 999px; /* pallini, pillole, avatar, pulsante fluttuante */
  /* I nomi vecchi restano come alias finche' tutto il foglio non e' passato ai
     nuovi: toglierli di colpo lascerebbe meta' app senza arrotondamenti. */
  --r-pill: var(--r-full);
  --r-xl:   var(--r-lg);

  /* ── I CORPI DEL TESTO ────────────────────────────────────────────────────
     Sette, non ventidue. Prima c'erano anche i mezzi pixel (10.5, 11.5, 12.5,
     13.5, 14.5), che non fanno gerarchia: fanno solo sporco. */
  --fs-micro: 11px;  /* etichette di gruppo maiuscolette, unita' */
  --fs-xs:    12px;  /* meta, orari, contrassegni, didascalie */
  --fs-sm:    13px;  /* celle di tabella, righe dense */
  --fs-base:  14px;  /* il default del documento */
  --fs-md:    16px;  /* titolo di scheda, testo enfatico */
  --fs-lg:    20px;  /* titolo di sezione, titolo di finestra */
  --fs-xl:    28px;  /* titolo di pagina, il numero di un dato */

  /* ── LE SPAZIATURE ───────────────────────────────────────────────────────
     Griglia a 4. Prima erano 26 valori diversi, con dispari (3, 5, 7, 9, 11,
     13, 15) che nascevano da aggiustamenti a occhio e non tornavano mai. */
  --sp-1:   2px;  --sp-2:   4px;  --sp-3:   8px;  --sp-4:  12px;
  --sp-5:  16px;  --sp-6:  20px;  --sp-7:  24px;  --sp-8:  32px;
  --sp-9:  40px;  --sp-10: 48px;

  /* Il tempo delle transizioni: due, non dieci. */
  --t-stato:  .12s cubic-bezier(.2,0,0,1);   /* passaggio del mouse, premuto */
  --t-appare: .2s  cubic-bezier(.2,0,0,1);   /* comparse */
  --radius: var(--r-md);
  /* ── LE OMBRE: due, e basta ──────────────────────────────────────────────
     Una scheda ferma non ha ombra: ha un bordo. L'ombra dice "questa cosa sta
     SOPRA il resto", e se ce l'hanno tutti non lo dice piu' nessuno.
       --shadow-1  cose sollevate ma non modali: tendine, popover, fluttuante
       --shadow-2  finestre e fogli
     I nomi vecchi restano come alias finche' il foglio non e' tutto passato. */
  /* Due strati e non uno: il primo, quasi invisibile, e' il contatto con la
     superficie; il secondo e' la distanza. Con un solo strato l'ombra si legge
     come un alone appiccicato sotto invece che come un rilievo. */
  --shadow-1: 0 1px 2px rgba(16,24,40,.05), 0 4px 12px rgba(16,24,40,.06);
  --shadow-2: 0 4px 8px rgba(16,24,40,.06), 0 12px 32px rgba(16,24,40,.14);
  --shadow:    var(--shadow-1);
  --shadow-sm: var(--shadow-1);
  --transition: .18s cubic-bezier(.4,0,.2,1);
  /* Il margine orizzontale della pagina, uno solo. Prima erano quattro valori
     diversi a seconda della sezione, e cambiando modulo il contenuto scivolava
     a destra e a sinistra. */
  --gutter: 24px;
  /* Il velo sfocato dietro a tutto cio' che si apre al centro dello schermo:
     modal, conferme, visualizzatore di foto e PDF. Un valore solo, cosi' non
     possono diventare due veli diversi. */
  --velo-sfondo: rgba(12,15,18,.44);
  --velo-sfocatura: blur(8px) saturate(115%);
  /* Quanto puo' allargarsi una colonna di contenuto prima di diventare scomoda
     da leggere. Su uno schermo largo un elenco che va da bordo a bordo obbliga
     l'occhio a percorrere tutta la scrivania per ogni riga, e le due estremita'
     di una stessa scheda finiscono lontanissime.
     Il numero era gia' nel foglio, scritto a mano nella Dashboard: qui diventa
     un valore solo, cosi' le schermate non possono divergere di cento pixel
     senza che nessuno se ne accorga. */
  --larghezza-lettura: 1100px;
  /* Il rientro che centra un contenuto entro quella larghezza: quando lo schermo
     e' piu' stretto vale il margine normale, quando e' piu' largo cresce da solo
     per tenere il contenuto in mezzo. */
  --rientro-lettura: max(var(--gutter), calc((100% - var(--larghezza-lettura)) / 2));
  /* ── LE DUE LARGHEZZE DELL'APP ─────────────────────────────────────────────
     Una regola sola, dicibile in una riga: gli ELENCHI stanno nella colonna di
     lettura, i MODULI DI CAMPI in quella stretta. Tutto il resto e' la stessa
     pagina vista da lontano.
       · 1100 — elenchi e tavole da scorrere: task, ferie, ortopedia, clienti,
         noleggi, prenotazioni, timbratura, cruscotto, file, paghe.
       · 640  — i CAMPI dei moduli da compilare: profilo, schermi in negozio, e
         i campi dentro le impostazioni. Un campo largo mille pixel obbliga
         l'occhio ad attraversare la scrivania.
         Le PAGINE delle impostazioni invece no: ogni scheda occupa tutta la
         larghezza del contenuto, uguale per tutte (deciso il 14/09/2026, vedi
         .settings-tab-panel). Schede di larghezze diverse saltano a ogni clic.
       · tutta larghezza — solo il planner e la chat, che sono griglie e
         pannelli, non pagine.
     Prima ce n'erano quattro (640, 760, 1000, 1100) e nessuna scritta da
     qualche parte: si sceglieva a occhio, pagina per pagina. */
  --larghezza-modulo: 640px;
  --rientro-modulo: max(var(--gutter), calc((100% - var(--larghezza-modulo)) / 2));
  /* Alias usati nel codice JS-generato */
  --border:  var(--gray5);
  /* Il contorno di un CAMPO non e' decorazione: e' cio' che dice dove si puo'
     scrivere, e per le regole vale 3, non 1,26 come faceva --gray5. Separato
     apposta: i bordi delle schede restano leggeri come sono. */
  --bordo-campo: #8c939b;
  /* Il bordo di una SCHEDA e' decorativo: separa due superfici, non dice dove
     si scrive. Puo' quindi stare sotto il 3:1 richiesto ai comandi — e deve,
     se no diventa una gabbia. Sono due mestieri diversi, due token diversi. */
  --bordo-scheda: #e3e4e8;

  /* ── I COLORI DI STATO DEI BLOCCHI APPUNTAMENTO ──────────────────────────
     Fissi in tutti e due i temi, e apposta: un operatore riconosce lo stato di
     un appuntamento con la coda dell'occhio mentre parla con un cliente, e quel
     riconoscimento non deve cambiare fra chiaro e scuro. Sono superfici piene
     con sopra il bianco, quindi non dipendono dal fondo della pagina.
     I valori sono quelli di prima portati dove il bianco si legge (4,53 · 5,25
     · 4,61 · 4,58): stessa tinta, tono piu' cupo. */
  --stato-attesa:    #ad6500;  --stato-attesa-bordo:    #7d4900;
  --stato-condiviso: #7b5ea7;  --stato-condiviso-bordo: #5a3f80;
  --stato-fatto:     #25863b;  --stato-fatto-bordo:     #1a6029;
  --stato-ferie:     #71767c;  --stato-ferie-bordo:     #565a5f;
  --text1:   var(--text);
  --danger:  var(--red);
  --surface: var(--card);
}

/* Background esplicito su html: è ciò che iOS mostra dietro la status bar
   in overscroll e al ripristino della PWA dal background */
html { background: var(--bg); }
body {
  font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', system-ui, sans-serif;
  background: var(--bg); color: var(--text);
  height: 100vh; height: 100dvh; overflow: hidden;
  /* Era 16px. Il documento parte da 14: e' la misura del corpo di questa app,
     e tutto cio' che non dichiara un corpo proprio deve ereditare quella, non
     una piu' grande che poi ogni regola si ritrova a dover correggere. */
  font-size: var(--fs-base); -webkit-font-smoothing: antialiased;
  /* Mancava del tutto: senza, tutta l'app ereditava l'interlinea di sistema
     (~1.15) e il testo stava stretto nella propria riga. Le dodici interlinee
     sparse nel foglio erano toppe su questo buco. */
  line-height: 1.45;
}

/* ── Material Icons — allineamento universale icona+testo ── */
.material-icons-outlined {
  font-size: 20px; line-height: 1;
  /* inline-flex garantisce l'allineamento verticale centrato con il testo adiacente */
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle; flex-shrink: 0;
}
.mi-sm    { font-size: 16px; }
.mi-chip  { font-size: 16px; }
.mi-badge { font-size: 13px; }

/* Qualsiasi elemento con icona + testo deve usare flex per allineamento perfetto */
.task-badge      { display: inline-flex; align-items: center; gap: 2px; }

.btn-icon .material-icons-outlined { font-size: 18px; }
.btn-sm .material-icons-outlined   { font-size: 16px; }
.sidebar-item .material-icons-outlined { font-size: 19px; }
.modal-header h3 { display: flex; align-items: center; gap: 6px; }
.modal-header h3 .material-icons-outlined { font-size: 20px; }

/* ── Icon picker ── */
.icon-opt .material-icons-outlined { font-size: 22px; }



/* ═══════════════════════════════════════════════════════════════════════════
   IL TEMA SCURO
   ═══════════════════════════════════════════════════════════════════════════
   Gli stessi token di sopra, altri valori. Tre stati, come nella console: chi
   non sceglie segue il computer, chi sceglie vince sul computer in tutte e due
   le direzioni.

   Non serve ridefinire --accent, --border, --text1, --danger e --surface:
   sono alias (var(--blue), var(--gray5)...) e si ricalcolano da soli appena
   cambia la base. Ridefinirli qui vorrebbe dire tenerli allineati a mano per
   sempre.

   I grigi si ROVESCIANO per funzione, non per numero: in chiaro --gray1 e' il
   piu' scuro (testo smorzato) e --gray6 il piu' chiaro (fondo appena accennato).
   Qui --gray1 diventa il piu' CHIARO e --gray6 il piu' scuro, cosi' ogni token
   continua a fare il mestiere che faceva.

   I numeri sono misurati, non scelti a occhio:
     testo 13,3 · testo2 9,17 · testo3 5,35 sulla scheda
     i sette colori di stato fra 5,69 e 8,75
     contorno dei campi 3,24 (ne servono 3)
     la scheda si stacca dal fondo di 1,22 — in chiaro fa 1,12
     le righe di separazione 1,44: si vedono senza tagliare

   ATTENZIONE, scritto perche' non si scopra per caso: questo blocco governa i
   TOKEN, cioe' tutto cio' che nel foglio passa da var(--...). Altrove restano
   colori scritti a mano — bianchi, grigi, ombre — che il tema scuro non
   raggiunge finche' restano tali. Quanti siano lo dice verifica-css.js a ogni
   giro: finche' quel numero non e' zero, il tema scuro e' giusto sulle
   superfici principali e va rifinito nel resto.

   I due blocchi qui sotto sono gemelli e devono restare tali. Sono due perche'
   uno sta dentro una media query e l'altro no, e il CSS non permette di
   scriverli una volta sola. Se divergono, il tema scuro scelto a mano e quello
   automatico diventano due temi diversi senza che nulla dia errore. Lo
   controlla verifica-css.js. */

@media (prefers-color-scheme: dark) {
  :root:not([data-tema="chiaro"]) {
    --blue:   #479fff; --green:  #6dd787; --orange: #ffb347;
    --red:    #ff726a; --purple: #9b98ff; --pink:   #ff7a99; --teal: #5cc4d8;

    --velo-ok:      #203a2b;
    --velo-attesa:  #40321d;
    --velo-errore:  #402324;
    --velo-info:    #182e45;

    /* L'accento del marchio schiarito al 65%: il verde tarato sul bianco fa
       4,03 su fondo quasi nero, sotto il minimo. Schiarito fa 5,79. */
    --accent: color-mix(in srgb, var(--accento-grezzo, var(--blue)) 65%, #ffffff);
    --su-accento: #0d1614;
    --su-colore:  #14171a;
    --bg2: #191d21;

    --gray1:  #9aa2ab; --gray2:  #7d858e; --gray3:  #5a636d;
    --gray4:  #454d56; --gray5:  #373e46; --gray6:  #191d21;
    --bg:     #0e1113; --card:   #20242a;
    --text:   #eef1f4; --text2:  #b3bcc6; --text3:  #8f99a3;
    --bordo-campo: #6b737b;
    --bordo-scheda: #2e343b;

    /* ── I COLORI DI STATO NEL BUIO ────────────────────────────────────────────
       Restavano quelli del tema chiaro: due tinte scure (#ad6500, #7b5ea7)
       usate come FONDO pieno di una scheda, dentro un'app dove nel buio il
       testo su colore diventa quasi nero (--su-colore #14171a). Risultato
       misurato: 3,97 sull'attesa e 3,43 sul condiviso — sotto la soglia.
       Prima non si vedeva perche' il testo era scritto #fff a mano, e un bianco
       fisso su un fondo scuro il contrasto ce l'ha; ma allora quei blocchi
       restavano macchie scure su un fondo scuro, e nel buio non si leggevano
       comunque come schede.
       Si schiariscono con lo stesso giro di --accent (65% di tinta e il resto
       bianco): nel buio TUTTI i fondi pieni sono chiari e portano testo scuro.
       Il bordo scuro di ognuna diventa la tinta piena di partenza, che sopra il
       fondo schiarito e' un contorno che si vede. */
    --stato-attesa:    color-mix(in srgb, #ad6500 62%, #ffffff);
    --stato-attesa-bordo:    #ad6500;
    --stato-condiviso: color-mix(in srgb, #7b5ea7 62%, #ffffff);
    --stato-condiviso-bordo: #7b5ea7;
    --stato-fatto:     color-mix(in srgb, #25863b 62%, #ffffff);
    --stato-fatto-bordo:     #25863b;
    --stato-ferie:     color-mix(in srgb, #71767c 62%, #ffffff);
    --stato-ferie-bordo:     #71767c;

    /* Nel buio un'ombra chiara non esiste: la profondita' la fa il nero, e piu'
       marcato, se no la scheda sta appiccicata al fondo. */
    /* Nel buio la profondita' la fa il nero, e piu' marcato. */

    --shadow-1: 0 1px 2px rgba(0,0,0,.4), 0 4px 12px rgba(0,0,0,.34);

    --shadow-2: 0 4px 8px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.5);

    --shadow: var(--shadow-1); --shadow-sm: var(--shadow-1);
  }
}

:root[data-tema="scuro"] {
  --blue:   #479fff; --green:  #6dd787; --orange: #ffb347;
  --red:    #ff726a; --purple: #9b98ff; --pink:   #ff7a99; --teal: #5cc4d8;

  --velo-ok:      #203a2b;
  --velo-attesa:  #40321d;
  --velo-errore:  #402324;
  --velo-info:    #182e45;

  /* L'accento del marchio schiarito al 65%: il verde tarato sul bianco fa
     4,03 su fondo quasi nero, sotto il minimo. Schiarito fa 5,79. */
  --accent: color-mix(in srgb, var(--accento-grezzo, var(--blue)) 65%, #ffffff);
  --su-accento: #0d1614;
  --su-colore:  #14171a;
  --bg2: #191d21;

  --gray1:  #9aa2ab; --gray2:  #7d858e; --gray3:  #5a636d;
  --gray4:  #454d56; --gray5:  #373e46; --gray6:  #191d21;
  --bg:     #0e1113; --card:   #20242a;
  --text:   #eef1f4; --text2:  #b3bcc6; --text3:  #8f99a3;
  --bordo-campo: #6b737b;
  --bordo-scheda: #2e343b;

  /* ── I COLORI DI STATO NEL BUIO ────────────────────────────────────────────
     Restavano quelli del tema chiaro: due tinte scure (#ad6500, #7b5ea7)
     usate come FONDO pieno di una scheda, dentro un'app dove nel buio il
     testo su colore diventa quasi nero (--su-colore #14171a). Risultato
     misurato: 3,97 sull'attesa e 3,43 sul condiviso — sotto la soglia.
     Prima non si vedeva perche' il testo era scritto #fff a mano, e un bianco
     fisso su un fondo scuro il contrasto ce l'ha; ma allora quei blocchi
     restavano macchie scure su un fondo scuro, e nel buio non si leggevano
     comunque come schede.
     Si schiariscono con lo stesso giro di --accent (65% di tinta e il resto
     bianco): nel buio TUTTI i fondi pieni sono chiari e portano testo scuro.
     Il bordo scuro di ognuna diventa la tinta piena di partenza, che sopra il
     fondo schiarito e' un contorno che si vede. */
  --stato-attesa:    color-mix(in srgb, #ad6500 62%, #ffffff);
  --stato-attesa-bordo:    #ad6500;
  --stato-condiviso: color-mix(in srgb, #7b5ea7 62%, #ffffff);
  --stato-condiviso-bordo: #7b5ea7;
  --stato-fatto:     color-mix(in srgb, #25863b 62%, #ffffff);
  --stato-fatto-bordo:     #25863b;
  --stato-ferie:     color-mix(in srgb, #71767c 62%, #ffffff);
  --stato-ferie-bordo:     #71767c;

  /* Nel buio la profondita' la fa il nero, e piu' marcato. */


  --shadow-1: 0 1px 2px rgba(0,0,0,.4), 0 4px 12px rgba(0,0,0,.34);


  --shadow-2: 0 4px 8px rgba(0,0,0,.4), 0 12px 32px rgba(0,0,0,.5);


  --shadow: var(--shadow-1); --shadow-sm: var(--shadow-1);
}

/* ── Auth ── */
#auth-screen {
  display: flex; align-items: center; justify-content: center;
  height: 100vh; height: 100dvh; background: linear-gradient(135deg,#f5f7fa 0%,#e8edf3 100%);
}
.auth-card {
  background: var(--card); border-radius: var(--r-lg); padding: 40px 36px;
  width: 100%; max-width: 400px; box-shadow: var(--shadow-2);
}
.auth-logo { text-align: center; margin-bottom: 32px; }
.auth-logo .app-icon {
  width: 72px; height: 72px; border-radius: var(--r-xl);
  background: var(--accent); display: flex; align-items: center; justify-content: center;
  font-size: 36px; margin: 0 auto 12px; box-shadow: 0 4px 20px color-mix(in srgb, var(--accent) 30%, transparent);
}
.auth-logo h1 { font-size: var(--fs-lg); font-weight: 600; }
.auth-logo p  { font-size: 14px; color: var(--text3); margin-top: 4px; }

/* ── Forms ── */
.form-group { margin-bottom: 16px; }
/* Due o tre campi affiancati (Servizio | Sede, Cognome | Nome, CAP | Città | Prov.).
   La classe era usata in una ventina di moduli ma non era definita da nessuna
   parte: i campi finivano sempre uno sotto l'altro, anche su uno schermo largo.
   Sul telefono restano in colonna, come prima. */
.form-row { display: flex; gap: 12px; align-items: flex-start; }
.form-row > .form-group { flex: 1; min-width: 0; }
@media (max-width: 600px) {
  .form-row { flex-direction: column; align-items: stretch; gap: 0; }
  .form-row > .form-group { flex: none !important; width: 100%; }
}
/* Erano 12px MAIUSCOLE e spaziate. Il maiuscolo toglie alla parola la sua
   forma — la sagoma con le lettere alte e basse e' il primo appiglio per
   riconoscerla senza leggerla — e su un modulo di dieci campi si finisce per
   compitarle tutte. Adesso e' testo normale, un filo piu' grande e piu' scuro:
   resta chiaro che e' un'etichetta perche' e' in grassetto e sta sopra il
   campo, non perche' grida. */
.form-group label, .field-label {
  display: block; font-size: 13px; font-weight: 500; color: var(--text2);
  margin-bottom: 6px; letter-spacing: 0;
}
.form-group input:not([type=checkbox]):not([type=radio]), .form-group select, .form-group textarea {
  width: 100%; padding: 12px 14px;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm);
  font-size: var(--fs-base); font-family: inherit; background: var(--card); color: var(--text);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.form-group input:not([type=checkbox]):not([type=radio]):focus, .form-group select:focus, .form-group textarea:focus {
  border-color: var(--accent);
}
/* UN solo segnale. Prima ce n'erano due sovrapposti: il bordo del campo che
   diventava accento (regola qui sopra) e l'anello di :focus-visible due pixel
   piu' in fuori — due cornici verdi concentriche attorno alla stessa casella.
   Nei campi di testo il browser accende :focus-visible anche col mouse, quindi
   capitava a ogni click, non solo a chi si muove da tastiera.
   L'anello si spegne SOLO qui, dove il bordo del campo fa gia' quel mestiere e
   si vede benissimo; su pulsanti, link e tutto il resto resta dov'era. */
.form-group input:not([type=checkbox]):not([type=radio]):focus-visible,
.form-group select:focus-visible,
.form-group textarea:focus-visible {
  outline: none;
  border-color: var(--accent);
}
.form-group textarea { resize: vertical; min-height: 80px; }

/* ── Toggle section (optional fields) ── */
.toggle-section {
  background: var(--gray6); border-radius: 12px; padding: 12px 14px;
  margin-bottom: 12px;
}
.toggle-row {
  display: flex; align-items: center; justify-content: space-between;
  cursor: pointer; user-select: none; font-size: 14px; font-weight: 500;
}
.toggle-switch {
  width: 44px; height: 26px; border-radius: var(--r-full); background: var(--gray4);
  position: relative; transition: background var(--transition); flex-shrink: 0;
}
.toggle-switch::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,.2);
  transition: transform var(--transition);
}
.toggle-switch.on { background: var(--accent); }
.toggle-switch.on::after { transform: translateX(18px); }

/* Variante compatta, usata negli header (es. toggle "solo mia agenda" del planner) */
.header-toggle {
  display: flex; align-items: center; gap: 6px; cursor: pointer; user-select: none;
}
.header-toggle-label { font-size: 13px; font-weight: 500; color: var(--text2); white-space: nowrap; }
.toggle-switch-sm { width: 34px; height: 20px; border-radius: var(--r-full); }
.toggle-switch-sm::after { width: 14px; height: 14px; top: 3px; left: 3px; }
.toggle-switch-sm.on::after { transform: translateX(14px); }

/* ── Buttons ── */
/* ── Buttons (§7) ──
   Altezza fissa (40 standard, 32 compatto) al posto del padding verticale:
   con un solo corpo testo (14, fs-base) il bottone non cambia più altezza a
   seconda del contenuto. Raggio 10 (r-sm), non 14 (r-md, quello delle
   schede) — un bottone non è una scheda in miniatura. Larghezza minima 96px
   per tutti i ruoli. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 40px; padding: 0 16px; min-width: 96px; border-radius: var(--r-sm);
  font-size: var(--fs-base); font-weight: 600; font-family: inherit;
  border: none; cursor: pointer; transition: all var(--transition);
}
/* Primario resta pieno, senza bordo. La larghezza piena non è più il default:
   prima era così OVUNQUE comparisse un bottone primario, anche dentro una
   card di pagina dove la specifica la vieta esplicitamente (§7, "no nelle
   pagine e dentro le schede") — è la causa, fra l'altro, per cui
   ".apt-admin-form .btn { align-self: flex-start }" non aveva mai avuto
   effetto: un width:100% esplicito vince sempre su align-self. Resta piena
   solo dove la specifica la ammette davvero. */
.btn-primary { background: var(--accent); color: var(--su-accento); }
.btn-primary:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 30%, transparent); }
.btn-primary:active { transform: translateY(0); }
.auth-card .btn-primary { width: 100%; margin-top: 8px; }
@media (max-width: 480px) { .btn-primary { width: 100%; } }
/* Secondario era un riquadro grigio pieno: esattamente lo stile che la
   specifica toglie di mezzo ("il grigio pieno come stile di bottone
   sparisce"). Trasparente + bordo, come un campo; hover/premuto sul testo
   invece che su un altro grigio pieno diverso. */
.btn-secondary { background: transparent; border: 1px solid var(--bordo-campo); color: var(--text); font-weight: 500; }
.btn-secondary:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--text) 8%, transparent); }
/* Distruttivo era pieno rosso sempre, anche sulle tante "Rifiuta" dentro le
   righe di lista (ferie, noleggi, utenti in attesa) — non dentro nessuna
   finestra di conferma. La specifica lo vieta fuori da lì. Il pieno resta
   SOLO sul "Conferma" del dialogo dedicato: vedi la regola su #confirm-yes
   più sotto, che restituisce esattamente l'aspetto di prima in quell'unico
   punto. */
.btn-danger { background: transparent; color: var(--danger); font-weight: 400; }
.btn-danger:hover { background: color-mix(in srgb, var(--danger) 8%, transparent); }
/* Terziario era già senza fondo né bordo, giusto — mancava solo il peso 500
   ("distinzione dentro un blocco", §3): ereditava il 600 del bottone base. */
.btn-ghost { background: transparent; color: var(--accent); font-weight: 500; }
.btn-ghost:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.btn-sm { height: 32px; padding: 0 12px; font-size: var(--fs-base); border-radius: var(--r-sm); width: auto; margin-top: 0; }
.btn-icon {
  min-width: 44px; min-height: 44px; padding: 10px; border-radius: var(--r-sm);
  background: transparent; border: none; cursor: pointer;
  color: var(--text3); transition: all var(--transition);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px;
}
.btn-icon:hover { background: var(--gray5); color: var(--text); }
/* L'unico punto dove il distruttivo torna pieno: il "Conferma" del dialogo
   di conferma dedicato (confirmDialog / aptConfirmDeleteSingle). Selettore
   sull'id già presente nel markup, non una classe nuova: nessuna struttura
   cambia. Stesso id è usato anche per conferme NON distruttive con
   btn-primary — questa regola si applica solo quando è anche .btn-danger. */
#confirm-yes.btn-danger { background: var(--danger); color: var(--su-colore); font-weight: 600; }
#confirm-yes.btn-danger:hover { background: var(--danger); filter: brightness(1.08); }

.error-msg {
  background: #FFF0F0; color: var(--red); border-radius: 8px;
  padding: 10px 14px; font-size: 14px; margin-bottom: 12px; display: none;
}
.error-msg.visible { display: block; }

.auth-toggle { text-align: center; margin-top: 20px; font-size: 14px; color: var(--text3); }
.auth-toggle a { color: var(--accent); text-decoration: none; font-weight: 600; cursor: pointer; }

/* ── App Layout ── */
#app { display: flex; height: 100vh; height: 100dvh; }

/* ── Sidebar ── */
.sidebar {
  width: 268px; min-width: 268px;
  background: var(--card); border-right: 1px solid var(--gray5);
  display: flex; flex-direction: column; overflow: hidden; z-index: 100;
}
.sidebar-header {
  padding: 20px 16px 8px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--gray5);
}
.sidebar-logo { display: flex; align-items: center; gap: 10px; }
/* 28px di lato è una miniatura, non un bottone: raggio 25% dell'altezza -> r-xs. */
.sidebar-logo img { height: 28px; border-radius: var(--r-xs); object-fit: contain; }
/* 17px non è uno dei sette corpi; 16 (--fs-md) è il gradino più vicino. Il
   peso 700 è riservato a pallini/contrassegni ≤11px: un titolo si ferma a 600. */
.sidebar-logo .app-name { font-size: var(--fs-md); font-weight: 600; }
/* Stessa logica del logo immagine qui sopra: 28px -> r-xs, non r-sm. */
.sidebar-logo .app-icon-sm {
  width: 28px; height: 28px; border-radius: var(--r-xs);
  background: var(--accent); display: flex; align-items: center; justify-content: center; font-size: 15px;
}
/* Il titolino di un gruppo di impostazioni. Non e' una voce: non si clicca,
   non si illumina, e sta piu' vicino a quello che introduce che a quello che
   lo precede — o divide il gruppo sbagliato. */
.sidebar-gruppo {
  margin: 14px 0 4px; padding: 0 10px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text3);
}
.sidebar-module-body > .sidebar-gruppo:first-child { margin-top: 2px; }

.sidebar-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--r-md); cursor: pointer;
  transition: background var(--transition); color: var(--text2); font-size: 14px;
}
/* Solo su dispositivi con un vero mouse — su touch screen (iPad compreso) l'hover
   simulato dal browser dopo un tocco può restare "appiccicato" fino al tocco
   successivo altrove, facendo sembrare una voce sempre selezionata in grigio */
@media (hover: hover) { .sidebar-item:hover { background: var(--gray6); } }
.sidebar-item.active { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); font-weight: 600; }
.sidebar-item .item-icon { font-size: 17px; width: 22px; text-align: center; flex-shrink: 0; }
.sidebar-item .item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* --gray1 su --gray5 e' circa 2.6:1: sotto il minimo di 4.5:1 per un testo,
   in entrambi i temi. --text2 (secondario) su questo fondo tiene oltre 6:1. */
.sidebar-item .item-count {
  background: var(--gray5); color: var(--text2);
  font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: var(--r-pill);
}
.sidebar-item.active .item-count { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
.sidebar-item .item-icon .material-icons-outlined { font-size: 19px; }
.sidebar-item .edit-btn {
  opacity: 0; transition: opacity var(--transition); flex-shrink: 0;
  /* .btn-icon impone un'area di tocco 44x44 (giusta per un bottone normale);
     qui resta invisibile finché non c'è hover, ma occuperebbe comunque quello
     spazio e allargherebbe la riga — la restringiamo alla dimensione dell'icona */
  min-width: 22px; min-height: 22px; padding: 2px;
}
@media (hover: hover) {
  .sidebar-item:hover .edit-btn { opacity: .6; }
}
@media (hover: none) {
  .sidebar-item .edit-btn { display: none; }
}

/* Task groups (all-tasks view) */
/* ── IL GRUPPO E' UNA SCHEDA, LE RIGHE RESTANO RIGHE ─────────────────────────
   Qui NON si fa quello che si e' fatto con le Prenotazioni, e il motivo e' che
   sono due cose diverse. Una prenotazione da approvare chiede una decisione, una
   per volta: e' un oggetto a se' e sta bene da sola su una scheda. Un elenco di
   task si scorre: staccare venti schede una dall'altra allungherebbe la pagina
   del doppio per non dire niente di piu'.
   Quindi la scheda e' il GRUPPO — "Direzione", "Fornitori", "Condivisi con me" —
   e i task restano righe dentro di lei, separate da un filo. E' la stessa forma
   della tavola del Piano Ferie: un riquadro con dentro delle righe.
   Le righe (.task-card) non sono state toccate: le usano anche Ferie e altri
   elenchi, e li' vanno bene come sono. */
.task-group { margin-bottom: 22px; }
.task-group-riquadro {
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  /* Ritaglia: la barretta rossa dei task scaduti e il pannello rosso dello
     swipe-to-delete arrivano fino al bordo, e senza questo spunterebbero fuori
     dagli angoli arrotondati. */
  overflow: hidden;
  animation: apt-entra var(--t-appare) both;
  animation-delay: var(--apt-ritardo, 0ms);
}
/* L'ultima riga non ha bisogno del filo: sotto c'e' gia' il bordo della scheda. */
.task-group-riquadro > .task-swipe-wrap:last-child > .task-card,
.task-group-riquadro > .task-card:last-child { border-bottom: none; }

/* L'intestazione del gruppo sta FUORI dalla scheda, sul grigio: e' un'etichetta
   di sezione, non il cappello del riquadro. Era una fascia con un filo sotto e
   il peso 700; il filo lo fa adesso il bordo della scheda, e 700 nel progetto e'
   riservato ai contrassegni piccoli. */
.task-group-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 2px 10px; font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em; color: var(--text3);
}
.task-group-count {
  background: var(--gray6); color: var(--text3);
  font-size: var(--fs-micro); font-weight: 600; padding: 2px 8px; border-radius: var(--r-full);
}
.sidebar-lists { flex: 1; overflow-y: auto; padding: 8px 0 8px; }
.sidebar-lists::-webkit-scrollbar { width: 4px; }
.sidebar-lists::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 2px; }

/* ── Sidebar Moduli (accordion) ── */
.sidebar-module {
  margin: 0 8px 4px; border-radius: var(--r-lg); overflow: hidden;
  transition: background .2s;
}
.sidebar-module.module-active {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.sidebar-module-header {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px; cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--text2);
  transition: background var(--transition);
  border-radius: var(--r-lg);
}
.sidebar-module:not(.module-active) .sidebar-module-header:hover { background: var(--gray6); }
.sidebar-module.module-active > .sidebar-module-header { color: var(--accent); border-radius: var(--r-lg) 14px 0 0; }
.module-icon { width: 22px; text-align: center; flex-shrink: 0; }
.module-icon .material-icons-outlined { font-size: 20px; color: var(--accent); }
.module-label { flex: 1; }
/* Era --gray2, che su bianco fa 2,21: sotto anche il minimo di 3 previsto per
   un semplice segno di comando, non solo per il testo. Questa freccetta dice se
   il gruppo e' aperto o chiuso — se non si vede, non lo dice a nessuno. */
.module-chevron .material-icons-outlined { font-size: 18px; color: var(--text3); }

/* Corpo espanso del modulo */
.sidebar-module-body { padding: 0 0 8px; }
.sidebar-sub-section { padding: 0 4px; margin-top: 2px; }
.sidebar-sub-title {
  font-size: 10px; font-weight: 700; color: var(--gray2);
  text-transform: uppercase; letter-spacing: .07em; padding: 4px 8px 2px;
}
/* Dentro un modulo attivo, gli item hover sono più scuri per risaltare sullo sfondo tenue */
@media (hover: hover) { .sidebar-module.module-active .sidebar-item:hover { background: rgba(0,0,0,.05); } }
.sidebar-module.module-active .sidebar-item.active { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.sidebar-sep {
  height: 1px; background: var(--gray5); margin: 6px 16px;
}

/* ── Timbratura: stato del giorno (vista admin "Oggi") ── */
/* ── LA PASTIGLIA DI STATO ────────────────────────────────────────────────────
   Una sola, per tutti i moduli: chi la usa le passa la tinta con --tinta-stato.
   Il testo NON e' la tinta pura ma la tinta mescolata verso il colore del testo:
   i colori di stato sono pensati per essere un FONDO pieno col bianco sopra, e
   usati come testo su un velo di se stessi non arrivano alla soglia (misurato
   3,79 sull'arancione). Mescolando verso --text si scuriscono nel tema chiaro e
   si schiariscono nel buio, quindi funziona in tutt'e due senza scrivere due
   valori a mano. */
.pastiglia-stato {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-micro); font-weight: 600;
  padding: 3px 9px; border-radius: var(--r-full);
  /* Il ripiego non e' formalita': la tinta la scrive chi usa la pastiglia, in
     linea sull'elemento. Senza ripiego, un chiamante che se ne dimentica ottiene
     un color-mix che non risolve — cioe' una pastiglia trasparente con dentro
     del testo invisibile, e nessun errore da nessuna parte. */
  background: color-mix(in srgb, var(--tinta-stato, var(--text3)) 14%, var(--card));
  color: color-mix(in srgb, var(--tinta-stato, var(--text3)) 70%, var(--text));
  white-space: nowrap;
}

/* ── IL SELETTORE A SCHEDE ───────────────────────────────────────────────────
   Lo usano dodici punti, e le sue misure stavano ripetute in un attributo style
   dentro il disegno. Qui una volta sola, sui valori del progetto. */
.seg-tab-bar {
  display: flex; gap: 4px; margin-bottom: 20px;
  background: var(--gray6); border-radius: var(--r-md); padding: 4px;
}
.seg-tab {
  position: relative; flex: 1;
  padding: 9px 10px; font-weight: 600; font-family: inherit;
  border: none; border-radius: var(--r-sm); cursor: pointer;
  background: transparent; color: var(--text2);
  transition: background var(--t-stato), color var(--t-stato);
}
.seg-tab:hover:not(.attiva) { background: color-mix(in srgb, var(--text) 5%, transparent); }
/* La scheda scelta e' una pastiglia BIANCA su fondo grigio, non un blocco pieno
   d'accento: cosi' si legge come "sono qui" invece che come un pulsante da
   premere, e le due voci restano leggibili tutt'e due. */
.seg-tab.attiva {
  background: var(--card); color: var(--text);
  box-shadow: var(--shadow-1);
}

/* ── TIMBRATURA ──────────────────────────────────────────────────────────────
   La tabella stava nuda sul fondo della pagina, con le misure scritte
   nell'attributo style di ogni cella. Adesso e' dentro una scheda come le
   tavole degli altri moduli. */
.tbr-scheda {
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: 6px 18px 14px;
}
.tbr-scorri { overflow-x: auto; }
.tbr-scorri::-webkit-scrollbar { height: 10px; }
.tbr-scorri::-webkit-scrollbar-track { background: transparent; }
.tbr-scorri::-webkit-scrollbar-thumb {
  background: var(--gray2); border-radius: var(--r-full);
  border: 3px solid transparent; background-clip: content-box;
}
.tbr-scorri::-webkit-scrollbar-button { display: none; width: 0; height: 0; }

.tbr-tabella { width: 100%; border-collapse: collapse; }
/* L'intestazione era MAIUSCOLA scritta nel testo ("DIPENDENTE"): scritta cosi'
   non si puo' piu' leggere in minuscolo se un giorno si cambia idea, e chi usa
   un lettore di schermo se la sente sillabare. Le maiuscole le fa il foglio. */
.tbr-tabella th {
  text-align: left; padding: 12px 8px 10px;
  font-size: var(--fs-micro); font-weight: 600; color: var(--text3);
  text-transform: uppercase; letter-spacing: .06em;
  border-bottom: 1px solid var(--bordo-scheda);
}
.tbr-tabella td { padding: 12px 8px; border-bottom: 1px solid var(--bordo-scheda); }
.tbr-tabella tbody tr:last-child td { border-bottom: none; }
.tbr-tabella tbody tr { transition: background var(--t-stato); }
.tbr-tabella tbody tr:hover { background: color-mix(in srgb, var(--text) 3%, transparent); }

.tbr-dipendente { display: flex; align-items: center; gap: 10px; }
.tbr-avatar {
  width: 34px; height: 34px; border-radius: var(--r-full);
  display: flex; align-items: center; justify-content: center;
  color: var(--su-colore); font-size: var(--fs-sm); font-weight: 600; flex-shrink: 0;
}
.tbr-nome { font-weight: 500; font-size: var(--fs-sm); }
.tbr-ora  { font-size: var(--fs-sm); color: var(--text2); font-variant-numeric: tabular-nums; }
.tbr-ore  { font-size: var(--fs-sm); color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbr-vuoto { color: var(--text3); }
.tbr-nota-ritardo { font-size: var(--fs-micro); color: var(--danger); font-weight: 600; margin-top: 3px; }
.tbr-aggiornato { margin: 12px 0 0; font-size: var(--fs-xs); color: var(--text3); text-align: right; }

/* La schermata era limitata a 740px scritti in linea, e con sei colonne la
   tabella non ci stava: restava una finestrella con lo scorrimento laterale
   dentro una pagina mezza vuota. Adesso la centra il rientro di lettura, che
   .task-list-container porta gia' con se'.
   NIENTE max-width qui: sarebbe un SECONDO modo di fare la stessa cosa, e i due
   si combattono. Il rientro e' una percentuale, e una percentuale di padding si
   calcola sulla larghezza del GENITORE, non dell'elemento: allargando la finestra
   il rientro cresceva — 450px per lato a 2000 di finestra — mentre il max-width
   teneva la scatola a 1100. Dentro 1100 di scatola con 900 di rientro restavano
   200 pixel di contenuto: piu' si allargava la pagina, piu' il campo si
   stringeva. Un meccanismo solo, e il problema non esiste. */

/* ── IL LATO DI CHI TIMBRA ───────────────────────────────────────────────────
   Era tutto scritto nell'attributo style: bordi da 2px, angoli a 16, il rosso
   #FF3B30 a mano, il peso 700 sui titoli. Qui prende le misure del progetto. */
.tbr-oggi-data {
  text-align: center; margin-bottom: 6px;
  color: var(--text3); font-size: var(--fs-sm); text-transform: capitalize;
}
/* L'orologio: era 52px di peso 700. Un numero grande non ha bisogno di essere
   anche grasso per farsi vedere — la dimensione basta, e 700 nel progetto e'
   riservato ai contrassegni piccoli. Le cifre tabulari perche' altrimenti
   l'orologio "balla" a ogni secondo che cambia larghezza. */
.tbr-orologio {
  font-size: 56px; font-weight: 500; text-align: center;
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
  line-height: 1; margin-bottom: 24px; color: var(--text);
}
.tbr-scheda-blocco { padding: 20px; margin-bottom: 16px; }
.tbr-etichetta {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text3); margin-bottom: 12px;
}
.tbr-timbri { display: flex; flex-wrap: wrap; gap: 8px; }
.tbr-vuoto-testo { color: var(--text3); font-size: var(--fs-sm); }
.tbr-ore-lavorate { margin-top: 12px; font-size: var(--fs-sm); color: var(--text3); }
.tbr-ore-lavorate strong { color: var(--text); font-weight: 600; }
.tbr-annulla-riga { margin-top: 14px; border-top: 1px solid var(--bordo-scheda); padding-top: 12px; }
/* Distruttiva come link piccolo, mai come pulsante accanto a quello che salva. */
.tbr-annulla {
  background: none; border: none; padding: 0; cursor: pointer;
  font-family: inherit; font-size: var(--fs-sm);
  color: var(--danger); text-decoration: underline;
}
.tbr-annulla:hover { color: color-mix(in srgb, var(--danger) 80%, var(--text)); }

/* I campi: pieni e senza bordo, come le note dell'Agenda. Avevano due pixel di
   bordo grigio dentro una scheda gia' bordata — due cornici a pochi pixel
   l'una dall'altra. L'anello a fuoco e' un'ombra INTERNA, cosi' comparendo non
   sposta il testo. */
.tbr-campo {
  width: 100%; box-sizing: border-box; text-align: center;
  background: var(--gray6); border: none; border-radius: var(--r-sm);
  color: var(--text); font-family: inherit;
  transition: background var(--t-stato), box-shadow var(--t-stato);
}
.tbr-campo:focus {
  outline: none; background: var(--card);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}
/* I 16px minimi non sono estetica: sotto quella misura iOS ingrandisce da solo
   la pagina appena si tocca il campo. Qui siamo abbondantemente sopra. */
.tbr-campo-pin { font-size: 28px; font-weight: 600; letter-spacing: .2em; padding: 16px; }
.tbr-campo-ora { font-size: 20px; font-weight: 600; padding: 14px; -webkit-appearance: none; }
.tbr-nota { font-size: var(--fs-xs); color: var(--text3); margin: 10px 0 0; }
.tbr-errore {
  color: var(--danger); font-size: var(--fs-sm); text-align: center;
  min-height: 20px; margin-bottom: 8px;
}

/* Il report: le stesse misure della tabella di "Oggi". L'elenco dei dipendenti
   stava nudo sul grigio mentre la barra degli strumenti sopra era gia' in una
   scheda — due meta' della stessa schermata trattate in due modi. */
.tbr-strumenti { padding: 16px 18px; margin-bottom: 16px; }
.tbr-separatore { width: 1px; align-self: stretch; background: var(--bordo-scheda); margin: 0 6px; }
.tbr-riga-apribile { cursor: pointer; }
/* Le ore totali sono il numero che si cerca in questa tabella: restano in
   accento, ma a peso 600 — 700 nel progetto e' riservato ai contrassegni
   piccoli, e un numero di quindici pixel non ha bisogno di essere grasso. */
.tbr-ore-totali {
  font-size: var(--fs-base); font-weight: 600; color: var(--accent);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tbr-freccia { color: var(--text3); width: 40px; }
.tbr-col-freccia { width: 40px; }
.tbr-riga-dettaglio > td { padding: 0 0 14px 52px; border-bottom: 1px solid var(--bordo-scheda); }

/* La tabella di dettaglio che si apre cliccando un dipendente. Era l'ultimo
   pezzo del modulo scritto per intero nell'attributo style: novecentotrenta
   celle, una misura ripetuta per ognuna. */
.tbr-dettaglio { border-collapse: collapse; min-width: 420px; }
.tbr-dettaglio th {
  text-align: left; padding: 6px 8px;
  font-size: var(--fs-micro); font-weight: 600; color: var(--text3);
  text-transform: uppercase; letter-spacing: .05em;
  border-bottom: 1px solid var(--bordo-scheda);
}
.tbr-dettaglio td {
  padding: 7px 8px; font-size: var(--fs-xs);
  border-bottom: 1px solid var(--bordo-scheda);
  font-variant-numeric: tabular-nums;
}
.tbr-dettaglio tbody tr:last-child td { border-bottom: none; }
/* Sabato e domenica sbiaditi: erano a opacita' 0,6 sull'intera riga, che sbiadisce
   anche i contrassegni delle assenze. Qui si tocca solo il colore del testo, e un
   badge colorato in un weekend resta leggibile. */
.tbr-dt-weekend td { color: var(--text3); }
.tbr-dt-giorno { white-space: nowrap; }
.tbr-dt-tenue { color: var(--text3); }
.tbr-dt-ore { font-weight: 600; }
.tbr-dt-ore-num { color: var(--accent); }
.tbr-dt-vuoto { font-size: var(--fs-sm); color: var(--text3); padding: 8px 0; }
.tbr-dt-azioni { display: flex; justify-content: flex-end; margin: 6px 0 8px; }
.tbr-dt-csv { font-size: var(--fs-xs); padding: 6px 12px; margin-top: 0; }

.tbr-status-cell { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.tbr-late-badge {
  display: inline-flex; align-items: center; gap: 3px;
  background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red);
  font-size: 11px; font-weight: 700;
  padding: 3px 8px; border-radius: var(--r-pill); white-space: nowrap;
}
.tbr-late-badge .material-icons-outlined { font-size: 13px; }
.sidebar-mod-badge {
  display: flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  background: var(--red); color: var(--su-colore);
  font-size: 10px; font-weight: 700; border-radius: var(--r-pill);
}

/* Pallino di conteggio su una tab di segTabBar (es. "Duelli" nel Quizzettone) — stesso
   ambra/oro del badge sidebar duelli, per coerenza visiva lungo tutto il percorso.
   Il contenitore della tab-bar ha overflow:hidden (per arrotondare bene gli angoli dei
   pulsanti): un top negativo che sporge sopra il pulsante veniva tagliato via, quasi
   invisibile — resta DENTRO i confini del pulsante (top positivo), mai fuori. */
.seg-tab-badge {
  position: absolute; top: 3px; right: 3px;
  display: flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: color-mix(in srgb, var(--orange) 14%, transparent);
  color: var(--orange); font-size: 10px; font-weight: 700; border-radius: var(--r-pill);
}

/* Toggle switch per i moduli utente */
.toggle-track {
  position: absolute; inset: 0; border-radius: var(--r-full);
  background: var(--gray4); transition: background .2s;
  cursor: pointer;
}
.toggle-track::after {
  content: ''; position: absolute;
  width: 20px; height: 20px; border-radius: 50%; background: #fff;
  top: 3px; left: 3px; transition: transform .2s;
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.toggle-track.on { background: var(--accent); }
.toggle-track.on::after { transform: translateX(18px); }
.sidebar-footer {
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom)); border-top: 1px solid var(--gray5);
  display: flex; align-items: center; gap: 6px;
}
.avatar-btn {
  background: none; border: none; padding: 2px; border-radius: var(--r-full); cursor: pointer;
  transition: background .15s; position: relative;
}
/* Un alone colorato al passaggio del mouse e' esattamente cio' che la nuova
   direzione vieta. L'hover cambia il fondo, mai l'elevazione: stessa formula
   generica di ogni altro stato hover del progetto. */
.avatar-btn:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.avatar {
  width: 32px; height: 32px; border-radius: var(--r-full);
  display: flex; align-items: center; justify-content: center;
  /* 700 qui non rientra nell'eccezione (e' testo a 13px, non un contrassegno
     <=11px): il tetto per un'iniziale in un cerchio e' 600. Il bianco fisso
     resta: il fondo e' un colore scelto dall'utente in anagrafica, non un
     colore di tema, e non deve inseguire chiaro/scuro. */
  font-size: 13px; font-weight: 600; color: #fff; flex-shrink: 0;
}
.avatar-xs { width: 28px; height: 28px; font-size: 11px; flex-shrink: 0; }
.avatar-lg { width: 40px; height: 40px; font-size: 16px; }
.user-info { flex: 1; min-width: 0; }
.user-info .user-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-info .user-role { font-size: 11px; color: var(--text3); }

/* ── Main Content ── */
.main-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: var(--bg); }
.main-header {
  padding: 20px var(--gutter) 16px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--bg);
  flex-shrink: 0;
}
/* 26px non e' un corpo previsto: e' un titolo di pagina, cioe' esattamente
   --fs-xl (28px). Il peso scende a 600: nessun titolo supera il 600. */
.main-header h2 { font-size: var(--fs-xl); font-weight: 600; }

/* ── LE RIGHE DEI SUONI (Impostazioni → Notifiche) ───────────────────────────
   Stessa forma delle righe delle preferenze che stanno subito sotto nella
   stessa schermata: padding e una riga di separazione, niente pillola con lo
   sfondo. Due componenti diversi a dieci centimetri di distanza si notano.
   Titolo e spiegazione hanno pesi e corpi diversi — vedi IL DIALOGO DI
   CONFERMA qui sotto per la stessa logica. */
.notif-suono-riga {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 12px 0;
}
.notif-suono-testo { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.notif-suono-testo strong { font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.notif-suono-testo span { font-size: 12.5px; font-weight: 400; color: var(--text3); line-height: 1.5; }

/* ── IL DIALOGO DI CONFERMA ──────────────────────────────────────────────────
   Tre livelli di testo, con tre pesi e tre corpi diversi: la domanda, il fatto
   che fa decidere, le condizioni. Prima era una frase sola tutta in grassetto —
   e quando tutto e' in grassetto niente lo e'.
   Il segno in cima e' rosso quando si sta per rompere qualcosa, del colore
   dell'app quando si sta per fare una cosa voluta. */
.conferma { padding: 24px 24px 20px; text-align: center; }
.conferma-segno { font-size: 40px; display: block; margin-bottom: 12px; }
.conferma-segno.segno-pericolo { color: var(--danger); }
.conferma-segno.segno-azione   { color: var(--accent); }
.conferma-domanda {
  margin: 0; font-size: var(--fs-lg); font-weight: 600; line-height: 1.3;
  color: var(--text); text-wrap: balance;
}
/* Il numero che decide la risposta: il pezzo piu' pesante della finestra, e
   l'unico che si legge a colpo d'occhio senza aver letto niente altro. */
.conferma-evidenza {
  margin: 12px 0 0; font-size: var(--fs-md); font-weight: 600;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.conferma-dettaglio {
  margin: 8px auto 0; max-width: 42ch;
  font-size: var(--fs-sm); font-weight: 400; line-height: 1.55; color: var(--text3);
}

/* ── LE ICONE IN ALTO A DESTRA: DUE GRUPPI, NON UNA FILA ─────────────────────
   A destra ci sono due cose diverse e vanno lette come due cose diverse:
     · le azioni della PAGINA — "Solo mia" e la stampa in agenda, il credito
       messaggi, quello che serve li' e solo li';
     · le tre FISSE di tutta l'app — ricerca, post-it, notifiche.
   Le fisse stanno all'estremo destro, attaccate fra loro e sempre nello stesso
   punto: e' quello che permette di arrivarci senza guardare. Le azioni di
   pagina stanno prima, e possono comparire e sparire senza spostare niente.

   Lo stacco fra i due gruppi e' uno spazio, non una lineetta: bastano dodici
   pixel a dire "questi tre sono un'altra cosa", e una riga verticale in una
   testata gia' piena sarebbe un segno in piu' da guardare. */
.header-icone { display: flex; align-items: center; gap: 20px; }
.header-azioni-pagina { display: flex; align-items: center; gap: 4px; }
/* Senza azioni di pagina non deve restare lo spazio del gruppo vuoto, o le
   fisse sembrano staccate dal bordo in certe pagine e non in altre. */
.header-azioni-pagina:empty { display: none; }
.header-fisse { display: flex; align-items: center; gap: 2px; }
/* ── LA RIGA DELL'AZIONE ─────────────────────────────────────────────────────
   Il pulsante che crea sta da solo, allineato a destra, fra i filtri e le
   schede. Non dentro la barra dei filtri — la' sarebbe una pastiglia fra
   pastiglie, e i filtri restringono mentre lui crea — e non accanto al titolo,
   dove si mangia la testata della pagina.
   Il rientro e' quello delle schede: cosi' il pulsante finisce esattamente sul
   loro bordo destro, che e' la linea che l'occhio segue scendendo. */
.riga-azione {
  display: flex; justify-content: flex-end;
  padding: 0 var(--rientro-lettura) 12px;
}
.mobile-menu-btn { display: none; font-size: 22px; min-width: 44px; min-height: 44px; }

/* ── IL TITOLO STA SOPRA IL SUO CONTENUTO ────────────────────────────────────
   Il titolo del modulo stava al bordo estremo sinistro mentre filtri, azione e
   schede vivevano nella colonna di lettura: su uno schermo largo restava
   orfano in alto a sinistra, staccato da tutto quello che nominava.

   Il rientro si applica DA SOLO alle viste che usano la colonna (:has), e non
   tocca quelle a tutta larghezza — planner, chat, schermi — dove il contenuto
   parte dal bordo e li' deve partire anche il titolo. Cosi' non c'e' niente da
   ricordarsi quando si scrive una vista nuova: e' la vista a dichiarare come e'
   fatta, e la testata si adegua.
   Fra la testata e #main-content c'e' un .content-wrapper, quindi il
   contenuto non e' un figlio diretto: si guarda per discendenza.
   Se il browser non conosce :has(), resta il comportamento di prima. */
:is(div):has(#main-content > .vista-scorrevole) > #app-header,
:is(div):has(#main-content > .dash-wrap) > #app-header {
  padding-left: var(--rientro-lettura); padding-right: var(--rientro-lettura);
}
:is(div):has(#main-content > .colonna-stretta) > #app-header {
  padding-left: var(--rientro-modulo); padding-right: var(--rientro-modulo);
}
/* Le impostazioni stanno nella colonna di lettura come ogni altra pagina. */
:is(div):has(#main-content > .settings-content) > #app-header {
  padding-left: var(--rientro-lettura); padding-right: var(--rientro-lettura);
}

.filter-bar { padding: 0 var(--gutter) 12px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

/* Riquadri residuo ferie/permessi/ROL sopra i filtri di "Ferie & Permessi" —
   stesso rientro della barra dei filtri e dell'elenco qui sotto, altrimenti i
   bordi sinistri dei riquadri e quelli dei filtri non stanno sulla stessa linea
   verticale. Era 28px fisso e valeva finche' anche i filtri stavano li': da
   quando l'elenco vive nella colonna di lettura, il rientro giusto e' quello. */
.leave-budget-cards {
  display: flex; gap: 10px; flex-wrap: wrap;
  padding: 16px var(--rientro-lettura) 20px;
}

/* ── L'AZIONE PRINCIPALE DELLA PAGINA ────────────────────────────────────────
   Sta accanto al titolo, in tutti i moduli, sempre nello stesso posto.

   Prima stava dentro la barra dei filtri, prima pastiglia di sette. I filtri
   sono un insieme di PARI — tutti dicono "restringi" — e l'unico che invece
   CREA qualcosa, messo in mezzo a loro, si trova scandagliando la fila invece
   di saperlo gia'. Il verde lo faceva notare, ma notare non e' prevedere.

   Non nel gruppo di icone in alto a destra: la' vivono gli strumenti
   dell'applicazione (ricerca, post-it, notifiche), che non cambiano mai da una
   pagina all'altra. Questa cambia, e appartiene alla pagina: quindi sta col suo
   titolo. */
.azione-pagina {
  display: inline-flex; align-items: center; gap: 4px;
  height: 32px; padding: 0 14px; border-radius: var(--r-full); font-size: 13px; font-weight: 700;
  background: var(--accent); color: var(--su-accento); border: none; cursor: pointer;
  font-family: inherit; transition: all var(--transition); white-space: nowrap;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 30%, transparent);
}
.azione-pagina:hover { filter: brightness(1.08); transform: translateY(-1px); box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent); }
.azione-pagina:active { transform: translateY(0); }
/* Il contorno e' quello DECORATIVO (--bordo-scheda, 1px), non quello dei campi
   (--bordo-campo, 1.5px). La differenza non e' estetica: il contorno forte
   esiste per dire "qui dentro si scrive", e un chip non e' un campo — e' un
   comando. Indossando il tratto dei campi la barra dei filtri pesava come un
   modulo da compilare. E' anche quello che prescrive Material 3, la stessa
   lingua da cui arrivano le icone: i chip usano il contorno leggero.
   Lo stato SELEZIONATO non perde niente — a distinguerlo e' il velo d'accento
   qui sotto, che vale molto piu' di mezzo pixel di bordo. */
.filter-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  height: 32px; padding: 0 14px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
  cursor: pointer; border: 1px solid var(--bordo-scheda); background: var(--card);
  color: var(--text3); transition: all var(--transition); white-space: nowrap;
}
/* Compensa il whitespace interno del glyph Material Icons nei chip */
.filter-chip .material-icons-outlined { margin-left: -2px; }
/* Il passaggio del mouse NON usa l'accento. Prima faceva esattamente quello che
   fa il selezionato — bordo accento, testo accento — e cosi' l'unico segnale che
   distingueva "il filtro attivo" da "il filtro sotto il mouse" era... nessuno.
   Adesso il mouse alza un velo neutro, come le schede di .seg-tab, e l'accento
   resta a significare una cosa sola: sono qui. */
.filter-chip:hover { background: color-mix(in srgb, var(--text) 5%, var(--card)); color: var(--text2); }
/* Selezionato: velo d'accento + contorno + scritta, non riempimento pieno.
   Il solo contorno colorato non bastava: su una barra di sette chip tutti della
   stessa forma, un bordo di un pixel e mezzo che cambia tinta non si vede — e
   infatti non si vedeva. Il velo dice "questo" da un metro di distanza, e resta
   distinguibile dall'azione della pagina (.azione-pagina), che e' l'unica piena.
   Mescolato su --card e non su transparent: la barra sta a volte su scheda
   bianca e a volte sul fondo grigio della pagina, e il velo deve rendere uguale
   nei due posti invece di lasciar passare quello che ha sotto. */
.filter-chip.active {
  /* 18 e non 14 come le pastiglie: in tema scuro un velo del 14% alzava la
     casella di soli 19 livelli sul fondo della scheda — misurato — e a fianco
     di un chip sotto il mouse la differenza si assottigliava a 9. Le pastiglie
     stanno su una riga da leggere, questi sono comandi da colpire: qui il
     segnale deve arrivare prima della lettura. */
  background: color-mix(in srgb, var(--accent) 18%, var(--card));
  border-color: var(--accent);
  /* Non l'accento puro: sopra il suo stesso velo scendeva a 4,42 in tema chiaro,
     sotto la soglia di leggibilita'. E' la ricetta gia' usata dalle pastiglie
     (.pastiglia-stato): l'accento tirato verso il colore del testo, che in
     chiaro lo scurisce e in scuro lo schiarisce — un valore solo, giusto nei due
     temi, invece di due colori scritti a mano che prima o poi divergono. */
  color: color-mix(in srgb, var(--accent) 70%, var(--text));
  font-weight: 600;
}
.fc-active    .material-icons-outlined { color: var(--accent); }
.fc-urgent    .material-icons-outlined { color: var(--red); }
.fc-today     .material-icons-outlined { color: var(--teal); }
.fc-overdue   .material-icons-outlined { color: var(--red); }
.fc-completed .material-icons-outlined { color: var(--green); }
.filter-chip.active .material-icons-outlined { color: var(--accent); }

/* Centrata entro la larghezza di lettura, come Dashboard e Prenotazioni: un
   elenco che va da bordo a bordo su uno schermo largo obbliga l'occhio a
   percorrere tutta la scrivania per ogni riga, e il titolo di un task finisce a
   mezzo metro dalla sua data. */
.task-list-container { flex: 1; overflow-y: auto; padding: 16px var(--rientro-lettura) 28px; }

/* ── LA COLONNA STRETTA ──────────────────────────────────────────────────────
   Le pagine che sono un modulo da compilare, non un elenco da scorrere: il
   profilo, le impostazioni, gli schermi in negozio. File condivisi e paghe
   stanno invece fra gli elenchi, nella colonna di lettura.

   PERCHE' NON BASTA .task-list-container CON UN max-width ADDOSSO
   Era cosi' che erano scritte, e da li' veniva il difetto: piu' si allargava la
   finestra, piu' la colonna si stringeva, fino a strozzare il contenuto. Il
   motivo e' che --rientro-lettura contiene un 100%, e una percentuale dentro un
   padding non si misura sull'elemento ma sul suo CONTENITORE: dentro una
   scatola da 760px il rientro cresceva con la finestra — su uno schermo da 2000
   diventavano 450px per lato dentro una scatola da 760, e restava una fessura.

   Qui il rientro sta sul contenitore, che e' largo quanto la pagina, e il
   limite di larghezza sta sul corpo dentro. Cosi' il bordo sinistro e' lo
   stesso di tutti gli altri moduli e la colonna non si muove piu'. */
.colonna-stretta { flex: 1; overflow-y: auto; padding: 16px var(--rientro-modulo) 28px; }
/* L'azione della pagina, qui dentro, e' gia' rientrata dal contenitore — e
   larga quanto il corpo, cosi' il pulsante cade sul bordo destro delle schede
   come in tutti gli altri moduli, non a mezza pagina di distanza. */
.colonna-stretta > .riga-azione { padding-left: 0; padding-right: 0; }
/* (il rientro della barra dei task arriva da .vista-scorrevole) */
/* Ferie: card riepilogo + filtri + storico scorrono INSIEME. Con lo scroll solo
   sullo storico, i caratteri di sistema ingranditi facevano occupare alle card
   l'intero schermo del telefono, rendendo irraggiungibile tutto il resto. */
/* (.leaves-scroll e' stata tolta: era una copia a mano di .vista-scorrevole,
   con la stessa regola sull'elenco che non scorre piu' da solo, ma senza la
   barra dei filtri che resta in cima. Adesso Ferie usa quella condivisa.) */
.task-list-container::-webkit-scrollbar { width: 5px; }
.task-list-container::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 3px; }

.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 300px; color: var(--text3);
}
.empty-state .empty-icon { margin-bottom: 16px; opacity: .4; }
.empty-state .empty-icon .material-icons-outlined { font-size: 56px; }
.empty-state p { font-size: 16px; font-weight: 500; }
.empty-state small { font-size: 13px; margin-top: 6px; }

/* ── Task Card (riga di elenco, non piu' scheda staccata — par.9) ── */
.task-card {
  background: var(--card); border-radius: 0; padding: 14px 16px; margin-bottom: 0;
  border-bottom: 1px solid var(--bordo-scheda); cursor: pointer;
  transition: background var(--t-stato);
}
.task-card:hover { background: color-mix(in srgb, var(--text) 4%, var(--card)); }
.task-card-main { display: flex; align-items: center; gap: 8px; }
/* Attenuazione sul contenuto, non sulla card: l'involucro esterno deve
   restare sempre pienamente opaco per non lasciar trasparire il pannello
   rosso dello swipe-to-delete posizionato dietro (stesso bug della v.precedente) */
.task-card.completed .task-card-top { opacity: .6; }
.task-card.overdue { border-left: 3px solid var(--red) !important; }
.task-card.shared-card { border-left: 3px solid var(--purple); }
.task-card.priority-high { border-left: 3px solid var(--red); }
.task-card-top { display: flex; align-items: center; gap: 12px; }
.task-delete-btn {
  flex-shrink: 0; margin-left: auto;
  background: none; border: none; cursor: pointer;
  color: var(--gray3); padding: 4px; border-radius: var(--r-sm);
  display: flex; align-items: center; opacity: 0; transition: opacity .15s, color .15s;
}
.task-card:hover .task-delete-btn { opacity: 1; }
.task-delete-btn:hover { color: var(--red); }
/* Su touch l'eliminazione è già lo swipe: il cestino in card sarebbe ridondante */
@media (hover: none) { .task-delete-btn { display: none; } }
/* Swipe-to-delete mobile (stile Mail/WhatsApp iOS) */
.task-swipe-wrap {
  position: relative; margin-bottom: 0; border-radius: 0; overflow: hidden;
  touch-action: pan-y;
}
.task-swipe-wrap .task-card { margin-bottom: 0; position: relative; z-index: 1; }
.task-swipe-bg {
  position: absolute; inset: 0; background: var(--red);
  display: flex; align-items: stretch; justify-content: flex-end;
}
.task-swipe-trash {
  width: 80px; border: none; background: transparent; color: var(--su-colore);
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
  transition: transform .15s ease;
}
.task-swipe-trash .material-icons-outlined { font-size: 22px; }

.task-checkboxes { display: flex; gap: 8px; flex-shrink: 0; align-self: center; }
.task-checkbox {
  width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--bordo-campo); background: transparent;
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
  transition: all var(--transition); position: relative;
}
.task-checkbox:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, transparent); }
.task-checkbox.taken { border-color: var(--orange); background: var(--orange); }
.task-checkbox.taken::after { content: ''; width: 10px; height: 10px; background: var(--su-colore); border-radius: 50%; }
.task-checkbox.completed-cb { border-color: var(--green); background: var(--green); }
.task-checkbox.completed-cb::after { content: '✓'; color: var(--su-colore); font-size: 14px; font-weight: 600; }
.checkbox-tooltip {
  /* Ancorato al bordo sinistro (non centrato): il primo pallino è vicino al bordo
     della card e un tooltip centrato sborda a sinistra, venendo tagliato dal
     contenitore che clippa l'overflow per lo swipe-elimina.
     Sotto e non sopra il pallino: i pallini sono nella riga in cima alla card,
     quindi "sopra" sborda oltre il bordo superiore di .task-swipe-wrap (anch'esso
     overflow:hidden) e viene tagliato lì */
  position: absolute; top: calc(100% + 4px); left: 0;
  background: rgba(0,0,0,.75); color: #fff; font-size: 11px; padding: 3px 7px;
  border-radius: var(--r-sm); white-space: nowrap; pointer-events: none; opacity: 0;
  transition: opacity .15s; z-index: 10;
}
@media (hover: hover) {
  .task-checkbox:hover .checkbox-tooltip { opacity: 1; }
}
.task-content { flex: 1; min-width: 0; }
.task-title { font-size: var(--fs-md); font-weight: 500; color: var(--text); line-height: 1.4; word-break: break-word; }
.task-card.completed .task-title { text-decoration: line-through; color: var(--text3); }
.task-desc { font-size: 13px; color: var(--text3); margin-top: 4px; line-height: 1.4; }
/* Contatto strutturato sui task da webhook (richieste dal sito): nome + pulsanti
   chiama/scrivi, non più sepolti nel testo libero della descrizione. */
.task-contact-pills { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.task-contact-name { font-size: 13px; font-weight: 600; color: var(--text2); }
.task-meta { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.task-badge {
  display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); font-weight: 600;
  padding: 2px 8px; border-radius: var(--r-pill); white-space: nowrap;
}
.badge-due     { background: color-mix(in srgb, var(--accent) 10%, transparent);   color: var(--accent); }
.badge-due.overdue { background: color-mix(in srgb, var(--red) 10%, transparent);  color: var(--red); }
.badge-due.today   { background: color-mix(in srgb, var(--orange) 10%, transparent);  color: var(--orange); }
.badge-shared  { background: color-mix(in srgb, var(--purple) 10%, transparent);   color: var(--purple); }
.badge-taken   { background: color-mix(in srgb, var(--orange) 10%, transparent);   color: var(--orange); }
.badge-completed { background: color-mix(in srgb, var(--green) 10%, transparent); color: var(--green); }
.badge-recurring { background: color-mix(in srgb, var(--teal) 10%, transparent); color: var(--teal); }
.badge-sticky  { background: color-mix(in srgb, var(--orange) 10%, transparent);   color: var(--orange); }
.badge-unread  {
  background: color-mix(in srgb, var(--red) 10%, transparent); color: var(--red);
  animation: badge-pop .25s ease;
}
.badge-chat    { background: var(--gray5); color: var(--text2); }
@keyframes badge-pop { from { transform: scale(.7); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ── Modal ── */
.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  /* Il velo era nero piatto al 35%: la finestra restava appiccicata a un fondo
     ancora perfettamente leggibile, e l'occhio continuava a tornarci.
     Con la sfocatura il contenuto dietro diventa tessitura invece che testo, e
     la finestra si stacca senza bisogno di annerire di piu'. */
  background: var(--velo-sfondo);
  backdrop-filter: var(--velo-sfocatura);
  -webkit-backdrop-filter: var(--velo-sfocatura);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
.modal-overlay.open { opacity: 1; pointer-events: all; }
/* Conferma aperta SOPRA un modal (confirmDialogSopra): stesso velo sfocato,
   un gradino piu' in alto. */
.modal-overlay.modal-overlay-sopra { z-index: 1100; }
.modal {
  background: var(--card); border-radius: var(--r-lg); width: 100%; max-width: 540px; max-height: 90vh;
  overflow-y: auto; overflow-x: hidden; box-shadow: var(--shadow-2);
  transform: translateY(20px) scale(.97); transition: transform .2s;
}
.modal-overlay.open .modal { transform: translateY(0) scale(1); }
.modal::-webkit-scrollbar { width: 4px; }
.modal::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 2px; }
.modal.modal-wide { max-width: 820px; }
/* Matrice residui ferie/permessi/ROL: 11 colonne, con modal-wide (820px) la maggior
   parte finiva tagliata fuori dal bordo destro senza che si notasse lo scroll interno
   della tabella — qui semplicemente si allarga il modal invece di doverci scrollare. */
.modal.modal-xwide { max-width: 1100px; }
.modal-header {
  padding: 20px; display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--gray5); position: sticky; top: 0;
  background: var(--card); z-index: 1; border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.modal-header h3 { font-size: var(--fs-lg); font-weight: 600; }
.modal-body { padding: 20px; }
.modal-footer {
  padding: 16px 20px 20px; border-top: 1px solid var(--gray5);
  display: flex; gap: 10px;
}
.modal-footer .btn {
  flex: 1; margin-top: 0;
}

/* Detail modal — un solo scorrimento verticale per tutto il contenuto (campi +
   storico messaggi): prima corpo e chat avevano ciascuno la propria scrollbar
   indipendente, ritagliate a metà dello spazio residuo — con descrizioni/note
   lunghe si finiva a scorrere un'area minuscola alla volta. Header e barra di
   invio restano ancorati (sticky) sopra e sotto un unico scroller. */
.detail-modal {
  width: min(480px, 95vw);
  max-height: 90vh;
  display: flex; flex-direction: column;
  padding: 0; overflow-y: auto; overflow-x: hidden;
}
/* Nessun figlio deve comprimersi per far stare tutto nei 90vh (31/07/2026):
   in un contenitore flex-column con overflow, corpo e chat sono flex item e
   Safari/iOS può schiacciarli ciascuno nella propria porzione (di fatto due
   aree separate) invece di lasciarli alla loro altezza naturale e far scorrere
   il contenitore — che è l'unico scroll voluto qui. */
.detail-modal > * { flex-shrink: 0; }
/* Da desktop i dettagli (pratica, task, cliente, medico) e il modulo
   dell'appuntamento hanno la stessa larghezza. 480 e 540px sono misure da
   telefono: su uno schermo largo il contenuto finiva in una colonnina, con
   i codici N.T. a capo e i campi uno sotto l'altro. I duelli restano come sono. */
@media (min-width: 769px) {
  .modal.detail-modal:not(.quiz-duel-modal) { width: min(720px, 92vw); max-width: 720px; }
  .modal.apt-form-modal { width: min(720px, 92vw); max-width: 720px; }
}
.detail-modal::-webkit-scrollbar { width: 4px; }
.detail-modal::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 2px; }
.detail-modal-header {
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 1;
  background: var(--card);
}
.detail-modal-title-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 8px;
}
.detail-modal-header .detail-title-input {
  font-size: var(--fs-lg); font-weight: 600; padding: 0; border: none; background: none;
  width: 100%; color: var(--text1);
}
.detail-modal-body {
  padding: 16px 20px;
}
.detail-modal-chat {
  display: flex; flex-direction: column;
  border-top: 1px solid var(--border);
}
.detail-modal-chat .chat-messages {
  overflow-y: visible;
  max-height: none !important;
}
.detail-modal-chat .chat-input-bar {
  position: sticky; bottom: 0; z-index: 1;
}

/* Modal dei duelli: centrato e "grande" anche su telefono, non un foglio dal basso
   come gli altri pannelli di dettaglio — due classi di specificità per vincere sia
   sulla regola generica bottom-sheet dei telefoni (riga ~957) sia su .detail-modal. */
.modal.quiz-duel-modal {
  align-self: center;
  transform: translateY(20px) scale(.97);
  width: min(94vw, 480px); max-width: min(94vw, 480px);
  max-height: 88dvh;
  border-radius: var(--r-lg);
}
.modal-overlay.open .modal.quiz-duel-modal { transform: translateY(0) scale(1); }

@media (max-width: 600px) {
  .modal-overlay { align-items: flex-end; }
  .detail-modal {
    width: 100vw; max-height: 92dvh; border-radius: 20px 20px 0 0;
  }
  /* Correzione timbrature: pop-up in alto invece del foglio dal basso — dentro c'è
     un date picker e input orari, in alto restano visibili anche a tastiera aperta */
  .modal.tbr-edit-modal { margin-bottom: auto; margin-top: 5vh; border-radius: 20px; }
}

.detail-section { margin-bottom: 20px; }
/* Erano 11px maiuscole in --gray2, che su bianco fa 2,21: sotto la meta' di
   quello che serve. Un titoletto illeggibile non e' discreto, e' invisibile. */
.detail-section-label {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0;
  color: var(--text3); margin-bottom: 8px; display: flex; align-items: center;
}
.detail-checkboxes { display: flex; gap: 10px; }
.detail-check-item {
  flex: 1; border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); padding: 12px 14px;
  cursor: pointer; transition: all var(--transition);
  display: flex; align-items: center; gap: 8px;
}
.detail-check-item:hover { border-color: var(--accent); }
.detail-check-item.active-taken { border-color: var(--orange); background: color-mix(in srgb, var(--orange) 6%, transparent); }
.detail-check-item.active-done  { border-color: var(--green);  background: color-mix(in srgb, var(--green) 6%, transparent); }
.detail-check-icon {
  width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--bordo-campo);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 13px;
}
.active-taken .detail-check-icon { border-color: var(--orange); background: var(--orange); color: var(--su-colore); }
.active-done  .detail-check-icon { border-color: var(--green);  background: var(--green);  color: var(--su-colore); }
.detail-check-text strong { display: block; font-size: 13px; font-weight: 600; }
.detail-check-text span   { font-size: 11px; color: var(--text2); }
.share-user-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--gray5); }
.share-user-row:last-child { border-bottom: none; }
.share-user-info { flex: 1; }
.share-user-info strong { font-size: 13px; display: block; }
.detail-title-input {
  font-size: var(--fs-lg); font-weight: 600; border: none; outline: none;
  background: transparent; width: 100%; color: var(--text); padding: 0; font-family: inherit;
}
/* Qui il segnale e' la riga sotto al titolo: l'outline ci disegnava attorno
   anche un rettangolo intero, che su un titolo grande e' vistosissimo. */
.detail-title-input:focus, .detail-title-input:focus-visible {
  outline: none; border-bottom: 2px solid var(--accent);
}
.due-indicator { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text3); }
.due-indicator.overdue { color: var(--red); }
.due-indicator.today   { color: var(--orange); }
.due-indicator.soon    { color: var(--accent); }


/* ── PRENOTAZIONI ONLINE ─────────────────────────────────────────────────────
   Le schede da approvare erano righe piatte a tutta larghezza (.task-card, la
   riga dei Task): incollate una all'altra, senza angoli ne' ombra, dentro un
   riquadro bianco unico. Ognuna di queste e' una cosa che ti chiede una
   decisione — approva o rifiuta — quindi e' un oggetto a se', e come tale si
   stacca dalle altre e galleggia sul grigio della pagina.
   .task-card non e' stata toccata: la usano quindici punti, e nei Task la lista
   senza stacchi e' voluta. */
/* (la tinta leggibile la calcola .pastiglia-stato, componente condiviso) */

/* A scorrere e' la vista intera — filtri compresi — e non l'elenco per conto
   suo. E' la stessa scelta fatta in Agenda, e serve a due cose insieme: le
   schede passano SOTTO la barra dei filtri invece di essere tagliate contro il
   suo bordo, e la barra puo' restare in cima velata e sfocata mentre gli passano
   sotto. Con l'elenco che scorreva da solo non c'era niente da sfocare: sopra il
   suo bordo non passava niente, si interrompeva e basta. */
/* ── LA BARRA DEI FILTRI CHE RESTA IN CIMA ───────────────────────────────────
   Vale per tutti i moduli, quindi sta scritta una volta sola.
   Perche' serve una VISTA che scorre invece del solo elenco: se a scorrere e'
   l'elenco, il suo contenuto viene TAGLIATO contro il bordo della barra invece
   di passarci sotto — e allora non c'e' niente da sfocare, la barra si
   interromperebbe di netto sul nulla. E' la vista intera a scorrere, la barra
   resta ferma, e il contenuto le passa dietro.
   Il velo con la sfocatura non e' un vezzo: a meta' di una scheda il taglio
   secco fa sembrare la scheda mozzata; sfocata si intravede che continua.
   Il rientro segue la larghezza di lettura, ma il velo resta a TUTTA larghezza:
   e' il rientro a spostare il contenuto, non la barra a stringersi, o ai lati
   resterebbero due strisce non sfocate. */
.vista-scorrevole { flex: 1; min-height: 0; overflow-y: auto; }
/* La barra di scorrimento sottile che aveva la vista delle Ferie: adesso ce
   l'hanno tutti i moduli, visto che la vista e' la stessa. */
.vista-scorrevole::-webkit-scrollbar { width: 5px; }
.vista-scorrevole::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 3px; }
.vista-scorrevole > .filter-bar {
  position: sticky; top: 0; z-index: 10;
  padding: 14px var(--rientro-lettura);
  background: var(--bg);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .vista-scorrevole > .filter-bar {
    background: color-mix(in srgb, var(--bg) 80%, transparent);
    backdrop-filter: blur(14px) saturate(130%);
    -webkit-backdrop-filter: blur(14px) saturate(130%);
  }
}
/* Dentro una vista che scorre, l'elenco non scorre piu' per conto suo. */
.vista-scorrevole > .task-list-container { flex: none; overflow: visible; padding-top: 4px; }

.apt-pren-vista { flex: 1; min-height: 0; overflow-y: auto; }

/* I filtri restano in cima. Il rientro e' lo stesso delle schede — prima era
   scritto in linea nel disegno a 16px contro i 24 delle schede, e si vedeva:
   le schede sporgevano di otto pixel a sinistra. */
/* (l'appiccicatura, il velo e il rientro arrivano da .vista-scorrevole) */

.apt-pren-elenco {
  /* Stessa larghezza della Dashboard: le schede andavano da bordo a bordo, e su
     uno schermo largo il pulsante "Rifiuta" finiva a quasi due metri dal nome del
     cliente a cui si riferisce. */
  padding: 4px var(--rientro-lettura) 28px;
  display: flex; flex-direction: column; gap: 12px;
}
.apt-pren-card {
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: 16px 18px;
  cursor: pointer;
  transition: box-shadow var(--t-stato), transform var(--t-stato);
  animation: apt-entra var(--t-appare) both;
  animation-delay: var(--apt-ritardo, 0ms);
}
/* Qui il sollevamento ha lo spazio per leggersi — sono schede staccate, non
   incastrate in una griglia come gli appuntamenti. */
.apt-pren-card:hover { box-shadow: var(--shadow-2); transform: translateY(-1px); }

.apt-pren-testa { display: flex; align-items: flex-start; gap: 12px; }
/* Il quadratino dell'icona: era #FF950018 con dentro #FF9500 — un'arancione
   fisso che non segue il tema e che, testo su velo, sta sotto la soglia. I token
   di stato ci sono gia' e sono stati scelti apposta per reggere il contrasto. */
.apt-pren-icona {
  width: 38px; height: 38px; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--stato-attesa) 12%, var(--card));
  color: color-mix(in srgb, var(--stato-attesa) 70%, var(--text));
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.apt-pren-riga1 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.apt-pren-riga1 strong { font-size: var(--fs-base); font-weight: 600; }
/* Stessa formula di .pastiglia-stato, con la tinta dell'attesa. */
.apt-pren-stato {
  font-size: var(--fs-micro); font-weight: 600;
  padding: 3px 9px; border-radius: var(--r-full);
  background: color-mix(in srgb, var(--stato-attesa) 14%, var(--card));
  color: color-mix(in srgb, var(--stato-attesa) 70%, var(--text));
  display: inline-flex; align-items: center; gap: 4px;
}
.apt-pren-riga {
  font-size: var(--fs-sm); color: var(--text2); margin-top: 5px;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
}
.apt-pren-riga-nuova { color: var(--accent); font-weight: 600; }
.apt-pren-recapito { font-size: var(--fs-xs); color: var(--text3); }
.apt-pren-azioni {
  display: flex; align-items: center; gap: 10px;
  margin-top: 16px; padding-left: 50px;
}
.apt-pren-azioni .btn {
  flex: 1; justify-content: center; margin-top: 0;
  font-size: var(--fs-sm); padding: 9px 12px;
}
.apt-pren-suggerimento {
  font-size: var(--fs-xs); color: var(--text3);
  margin-top: 10px; padding-left: 50px;
  display: flex; align-items: center; gap: 5px;
}
/* Su schermo stretto i due pulsanti stanno larghi uno sopra l'altro, e il rientro
   di cinquanta pixel sotto l'icona diventa spazio sprecato. */
@media (max-width: 560px) {
  .apt-pren-azioni { padding-left: 0; }
  .apt-pren-suggerimento { padding-left: 0; }
}

/* Il cliente collegato a un task: velo dell'accento, come gli altri
   contrassegni informativi. */
.badge-cliente {
  background: color-mix(in srgb, var(--accent) 12%, var(--card));
  color: color-mix(in srgb, var(--accent) 70%, var(--text));
}
/* L'etichetta che dice "questo campo non serve per forza": accanto al nome del
   campo, non al posto suo. Senza, un campo in mezzo a un modulo si legge come
   uno degli obbligatori. */
.etichetta-facoltativa {
  font-size: var(--fs-micro); font-weight: 400; color: var(--text3);
  text-transform: none; letter-spacing: 0; margin-left: 6px;
}

/* L'avviso di pratica chiusa: non un errore — non e' andato storto niente — ma
   una porta chiusa con accanto la chiave. Grigia, non rossa. */
.ortho-pratica-chiusa {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-top: 8px; padding: 12px 14px;
  background: var(--gray6); border-radius: var(--r-md);
  font-size: var(--fs-sm); color: var(--text2);
}
.ortho-pratica-chiusa > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ortho-pratica-chiusa span { font-size: var(--fs-xs); color: var(--text3); }
.ortho-pratica-chiusa .btn { margin-top: 0; flex-shrink: 0; }

/* ── Ferie & Permessi ─────────────────────────────────────────────────────────
   Questo modulo era rimasto all'aspetto di prima: riquadri con una spranga
   colorata in cima, corpi scritti a mano (26, 13, 11), maiuscolette a 12px e i
   colori di iOS 7 concatenati a mano nel JS ("#FF9500" + "18" per il velo). Due
   conseguenze, non una: si vedeva che era un pezzo di un'altra epoca, e i
   contrassegni non si leggevano (l'arancio come TESTO faceva 2,2).

   Adesso il colore entra da --tinta-stato e il foglio ne ricava velo e scritta, come
   in tutto il resto dell'app. Il tipo di assenza usa i colori di stato del tema
   (che nel buio si schiariscono da soli), non piu' esadecimali fissi. */
.leave-status-badge, .stato-badge {
  font-size: var(--fs-xs); font-weight: 500; padding: 2px 8px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--tinta-stato, var(--text3)) 14%, transparent);
  color: var(--tinta-stato, var(--text3));
}

/* "Ex festivita'" nel form di modifica: una riga tappabile tutta, velo del permesso
   quando e' spuntata. Titolo e spiegazione su due livelli, mai piatti. */
.lv-ex {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 0 0 16px; padding: 12px 16px;
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-md);
  background: var(--card); cursor: pointer;
}
.lv-ex:has(input:checked) {
  border-color: color-mix(in srgb, #0e7c56 45%, transparent);
  background: color-mix(in srgb, #0e7c56 8%, var(--card));
}
.lv-ex input { accent-color: #0e7c56; width: 18px; height: 18px; margin: 2px 0 0; flex: none; }
.lv-ex span { display: flex; flex-direction: column; gap: 2px; }
.lv-ex b { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.lv-ex small { font-size: var(--fs-xs); color: var(--text2); line-height: 1.4; }

/* I quattro riquadri del residuo. La spranga colorata in cima non c'e' piu': il
   colore sta nel velo dell'icona e nel numero, che e' anche il dato. */
.leave-riquadro {
  flex: 1; min-width: 160px;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md); padding: 16px;
}
.leave-riquadro-testata { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.leave-riquadro-icona {
  width: 28px; height: 28px; border-radius: var(--r-xs); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--tinta-stato); background: color-mix(in srgb, var(--tinta-stato) 12%, transparent);
}
.leave-riquadro-icona .material-icons-outlined { font-size: 18px; }
.leave-riquadro-etichetta {
  font-size: var(--fs-micro); letter-spacing: .06em; text-transform: uppercase;
  font-weight: 500; color: var(--text3);
}
.leave-riquadro-valore { font-size: var(--fs-lg); font-weight: 600; color: var(--tinta-stato); }
.leave-riquadro-valore.in-rosso { color: var(--red); }
/* Il saldo totale non e' di nessuna categoria: sta nel colore del testo. */
.leave-riquadro-valore.neutro { color: var(--text); }
.leave-riquadro-valore span { font-size: var(--fs-xs); font-weight: 400; color: var(--text3); }
.leave-riquadro-nota { margin-top: 8px; font-size: var(--fs-xs); color: var(--text3); }
.leave-riquadro-nota strong { color: var(--text2); font-weight: 500; }

/* Le righe dell'elenco. */
.leave-riga-corpo { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
.leave-riga-icona {
  width: 36px; height: 36px; border-radius: var(--r-sm); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--tinta-stato); background: color-mix(in srgb, var(--tinta-stato) 12%, transparent);
}
.leave-riga-testo { flex: 1; min-width: 0; }
.leave-riga-testa { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.leave-riga-titolo { font-weight: 500; }
.leave-riga-chi { font-size: var(--fs-xs); color: var(--text3); }
.leave-riga-quando {
  display: flex; align-items: center; gap: 4px; margin-top: 4px;
  font-size: var(--fs-xs); color: var(--text2);
}
.leave-riga-quando .material-icons-outlined { font-size: 16px; }
.leave-riga-quando em { font-style: normal; color: var(--text3); }
.leave-riga-nota {
  margin-top: 4px; font-size: var(--fs-xs); color: var(--text3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.leave-riga-motivo {
  margin-top: 4px; font-size: var(--fs-xs); color: var(--red);
  display: flex; align-items: center; gap: 4px;
}
.leave-riga-motivo .material-icons-outlined { font-size: 16px; }
.leave-riga-azioni { position: relative; flex-shrink: 0; align-self: center; }
/* Una chiusura aziendale sta nell'elenco ma non si apre: non e' una richiesta di
   nessuno. Senza questo la riga prometteva un clic che non succedeva. */
.task-card.senza-clic { cursor: default; }
.task-card.senza-clic:hover { background: var(--card); }

/* Le tre intestazioni della vista personale (In attesa / Programmate / Godute)
   non hanno un aspetto loro: sono .task-group-header, la stessa etichetta di
   gruppo dei task e delle attrezzature, con le righe dentro
   .task-group-riquadro. Un elenco che ha un involucro tutto suo e' esattamente
   il modo in cui due schermate della stessa app diventano due app. */

/* Il menu della riga: e' una cosa SOLLEVATA, quindi ombra 1 e nient'altro. */
.leave-menu {
  position: absolute; right: 0; top: 36px; min-width: 160px; z-index: 50;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-sm); box-shadow: var(--shadow-1); overflow: hidden;
}
.leave-menu-voce {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 8px 12px; background: none; border: none; cursor: pointer;
  font-size: var(--fs-base); color: var(--text);
}
.leave-menu-voce:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.leave-menu-voce.pericolo { color: var(--red); }

/* Il contrassegno del tipo, usato anche in Timbratura. */
.leave-tipo-badge {
  display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
  font-size: var(--fs-xs); font-weight: 500; padding: 2px 8px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--tinta-stato) 14%, transparent);
  color: var(--tinta-stato);
  border: 1px solid color-mix(in srgb, var(--tinta-stato) 30%, transparent);
}
.leave-tipo-badge.piccolo { font-size: var(--fs-micro); padding: 2px 8px; }

/* Gli appuntamenti che bloccano un'approvazione. */
.leave-conflitti {
  background: color-mix(in srgb, var(--red) 10%, transparent);
  border-left: 4px solid var(--red);
  border-radius: var(--r-xs); padding: 12px; margin-bottom: 12px;
}
.leave-conflitti strong { color: var(--red); font-weight: 500; }
/* Lo stesso riquadro, ma per una cosa che aspetta una decisione e non per un
   ostacolo: cambia solo la tinta. */
.leave-conflitti.in-attesa {
  background: color-mix(in srgb, var(--orange) 10%, transparent);
  border-left-color: var(--orange);
}
.leave-conflitti.in-attesa strong { color: var(--orange); }
.leave-conflitti p { font-size: var(--fs-sm); margin: 8px 0; color: var(--text2); }
.leave-conflitti-riga {
  font-size: var(--fs-xs); color: var(--text2);
  padding: 4px 0; border-top: 1px solid var(--bordo-scheda);
}
/* Le pillole per scegliere il tipo. L'aspetto stava scritto nell'attributo style
   di tre punti diversi di app.js — tre copie che nessuno avrebbe piu' aggiornato
   insieme. Qui una volta sola, sulle misure del progetto: il raggio dei campi, il
   bordo dei campi, i tempi del progetto. Restano in linea solo spaziatura e corpo
   del testo, che nei tre punti sono davvero diversi. */
.leave-type-btn {
  cursor: pointer;
  border: 1.5px solid var(--bordo-campo);
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--text3);
  transition: border-color var(--t-stato), background var(--t-stato), color var(--t-stato);
}
/* Niente !important: serviva a scavalcare il bordo scritto in linea, che ora non
   c'e' piu'. Tolto, la pillola scelta non perde piu' il suo colore quando ci si
   passa sopra col mouse. */
.leave-type-btn:hover { border-color: var(--accent); }
/* La pillola scelta: velo tinto e scritta del colore, non fondo pieno col bianco
   sopra — e' la stessa regola dei contrassegni, e qui evita anche il salto di
   contrasto fra un tipo e l'altro. Lo stato lo mette e lo toglie una classe,
   non tre assegnazioni a style dal JS. */
.leave-type-btn.attivo {
  background: color-mix(in srgb, var(--tinta-stato) 12%, transparent);
  border-color: var(--tinta-stato);
  color: var(--tinta-stato);
}

/* ── La scheda del tipo, dentro la finestra di un giorno ─────────────────────
   Era un rettangolo grigio con una spranga colorata da quattro pixel sul fianco
   sinistro: il colore del tipo — l'unica cosa che quella scheda deve dire —
   finiva relegato su un bordo, e con i tipi scuri sembrava una barra nera.
   Adesso il colore tinge tutta la scheda e un pallino lo ripete in pieno:
   stessa lingua della barra nella griglia dietro. */
.pf-scheda-tipo {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; margin-bottom: 16px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--pf-tinta) 10%, var(--card));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pf-tinta) 26%, transparent);
}
.pf-scheda-pallino {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--pf-tinta); flex-shrink: 0; margin-top: 5px;
}
.pf-scheda-tipo strong { font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.pf-scheda-stato { font-size: var(--fs-xs); color: var(--text3); margin-left: 5px; }
.pf-scheda-tipo p { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text2); }

/* La nota gia' scritta, quando non si puo' modificare: un blocco citato, non una
   riga di testo con un'emoji davanti. */
.pf-nota-letta {
  margin: 4px 0 0; padding: 10px 12px;
  border-radius: var(--r-sm); background: var(--gray6);
  font-size: var(--fs-sm); color: var(--text2); white-space: pre-wrap;
}

/* ── Admin ── */
/* Rientro sul contenitore, non max-width sulla scatola: e' lo stesso modo di
   tutte le altre pagine, e cosi' il titolo qui sopra cade sulla stessa linea
   verticale del primo campo. */
.settings-content {
  flex: 1; overflow-y: auto; overflow-x: hidden; width: 100%; box-sizing: border-box;
  padding: 24px var(--rientro-lettura);
}
/* I CAMPI restano stretti, la PAGINA no.
   Le impostazioni stavano in una colonna da 640: giusta per leggere una riga di
   modulo, ma larga la meta' di ogni altra pagina dell'app — e una pagina larga
   la meta' delle altre e' semplicemente una pagina diversa, per chi la guarda.
   Adesso la pagina sta nella colonna di tutti e a restare corti sono solo i
   campi, che e' quello che serviva davvero: un campo di testo lungo mille pixel
   non si legge, una scheda che lo contiene si'. */
.settings-content input:not([type=checkbox]):not([type=radio]):not([type=color]),
.settings-content select,
.settings-content textarea {
  max-width: var(--larghezza-modulo);
}
.settings-content .apt-tpl-card { min-width: 0; }
@media (max-width: 640px) {
  /* La riga token cron va a capo invece di sbordare */
  .apt-tpl-card-body .form-group > div { flex-wrap: wrap; }
}
/* ── Notifications ── */
.notif-bell-wrap { position: relative; }
.notif-bell { position: relative; }
.notif-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 16px; height: 16px; border-radius: var(--r-pill);
  background: var(--red); color: var(--su-colore);
  /* 10px non e' uno dei sette corpi: e' il pallino di conteggio, il piu'
     piccolo disponibile e' fs-micro. Il 700 resta: e' un glifo piccolo su
     fondo pieno, l'eccezione prevista dal §3. Padding 3px era fuori griglia. */
  font-size: var(--fs-micro); font-weight: 700;
  display: flex; align-items: center; justify-content: center; padding: 0 4px;
  pointer-events: none;
}
.notif-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 320px; max-height: 420px; overflow-y: auto;
  /* E' un menu a tendina: L2 per il §5, quindi bordo + --shadow-1 e stop,
     niente ombra letterale ne' un raggio inventato. */
  background: var(--card); border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  border: 1px solid var(--border);
  display: none; flex-direction: column;
  z-index: 200;
}
.notif-dropdown.open { display: flex; }
.notif-empty { padding: 24px; text-align: center; font-size: 14px; color: var(--text3); display: flex; align-items: center; justify-content: center; gap: 8px; }
.notif-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 16px; cursor: pointer; border-bottom: 1px solid var(--border);
  transition: background var(--t-stato);
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: var(--gray6); }
.notif-item.unread { background: color-mix(in srgb, var(--accent) 5%, transparent); }
/* Il non letto si distingue col COLORE, non col peso (§3): il titolo pieno
   contro un titolo attenuato, mai un grassetto in piu'. */
.notif-item.unread .notif-title { color: var(--text); }
.notif-icon { color: var(--accent); flex-shrink: 0; margin-top: 2px; }
.notif-content { flex: 1; min-width: 0; }
/* Letto/non letto adesso e' solo colore: di base il titolo e' secondario
   (letta), l'unread sopra lo riporta a primario. */
.notif-title { font-size: var(--fs-sm); color: var(--text2); }
.notif-msg   { font-size: 12px; color: var(--text3); margin-top: 2px; overflow: hidden; }
/* 700 tolto: non e' un pallino di conteggio, e' testo dentro la riga — il
   colore accento basta a farlo notare. Margine 3px portato in griglia. */
.notif-note  { display: block; margin-top: 4px; font-weight: 500; color: var(--accent); }
/* --gray3 su bianco/scuro non arriva a 4.5:1: qui il testo diventava quasi
   illeggibile. --text3 e' il terziario tarato apposta, ma sotto i 12px e'
   vietato dal §2 — quindi anche la dimensione sale a fs-xs (che e' pure il
   corpo giusto per un orario, per tabella). 3px di margine era fuori griglia. */
.notif-time  { font-size: var(--fs-xs); color: var(--text3); margin-top: 4px; }
/* .notif-del rimossa (30/07/2026): la X "Elimina" per singola notifica compariva
   solo all'hover — su mobile il primo tap simulava l'hover invece di aprire la
   destinazione, obbligando a un secondo tap. Le notifiche si auto-puliscono dopo
   7 giorni lato server, la cancellazione manuale non serviva. */
/* ── Notifiche duello del Quizzettone: colorate/fancy, mai il rosso/blu standard
   delle notifiche di lavoro — stesso gradiente del pulsante Quiz in sidebar, per
   riconoscerle a colpo d'occhio come "gioco", non "lavoro". ── */
/* Il gradiente qui violava il divieto generale (§10.10: solo lo sfondo di
   login puo' averne uno). Un velo pieno di --purple mantiene la stessa idea
   — "colorata, si riconosce come gioco" — senza il gradiente: a percentuali
   cosi' basse la differenza dei due toni del gradiente originale era comunque
   impercettibile. L'icona passa da un viola scritto a mano a --purple, lo
   stesso token gia' usato qui sopra: non c'e' piu' bisogno di inseguire
   esattamente il viola del pulsante Quiz in sidebar (che resta suo, non mio). */
.notif-item.notif-quiz { background: color-mix(in srgb, var(--purple) 8%, transparent); }
.notif-item.notif-quiz.unread { background: color-mix(in srgb, var(--purple) 13%, transparent); }
.notif-item.notif-quiz .notif-icon { color: var(--purple); }
.notif-item.notif-quiz .notif-title { color: var(--text); }
/* ── Ricerca globale — stesso pannello delle notifiche (.notif-dropdown), solo
   larghezza maggiore per ospitare risultati multi-categoria ── */
.gsearch-wrap { position: relative; }
.gsearch-dropdown { width: 360px; }
.gsearch-section-label {
  padding: 8px 14px 4px; font-size: 11px; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--text3);
}
@media (max-width: 600px) {
  .gsearch-dropdown { width: auto; }
}
@media (max-width: 600px) {
  .notif-dropdown {
    position: fixed;
    top: 56px; left: 8px; right: 8px;
    width: auto;
    max-height: 60vh;
    border-radius: var(--r-xl);
  }
}

/* ── Campanella: Nuove / Precedenti ────────────────────────────────────────
   Aprendo la campanella il pallino si azzera subito, ma dentro il pannello
   quello che era nuovo resta separato (intestazione + punto) finche' il pannello
   e' aperto. L'etichetta e' la stessa della ricerca globale, che vive nello
   stesso pannello; qui resta attaccata in alto scorrendo, come nelle notifiche
   del telefono. Dopo .gsearch-section-label apposta: vince sul suo padding. */
.notif-sezione {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; gap: 6px;
  padding: 12px 16px 6px; background: var(--card);
}
.notif-sezione-conta {
  display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-full); font-size: 11px; font-weight: 700; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent);
}
.notif-title { display: flex; align-items: flex-start; gap: 8px; }
.notif-title-testo { flex: 1; min-width: 0; }
/* Il punto sta a destra del titolo, centrato sulla sua PRIMA riga anche quando
   il titolo va a capo. */
.notif-punto {
  flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
  margin-top: 5px; margin-top: calc((1lh - 8px) / 2);
}
.notif-item.notif-quiz .notif-punto { background: var(--purple); }

/* ── Pop-up della campanella (notifShowToast) ──────────────────────────────
   Esce dalla campanella quando arriva una notifica, come il fumetto dei
   messaggi esce dal pulsante della chat: stessa scheda (card, bordo,
   --shadow-1, r-md), stessa molla in entrata, stessi corpi del testo. Un
   beccuccio lo lega alla campanella, da cui parte anche l'ingrandimento. */
.notif-toast {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 210;
  width: 300px; max-width: calc(100vw - 24px);
  display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow-1); cursor: pointer; text-align: left;
  transform-origin: calc(100% - 22px) 0;
  animation: notifToastIn .45s cubic-bezier(.34,1.56,.64,1);
}
.notif-toast::before {
  content: ''; position: absolute; top: -6px; right: 17px; width: 10px; height: 10px;
  background: var(--card); border-left: 1px solid var(--border); border-top: 1px solid var(--border);
  transform: rotate(45deg);
}
.notif-toast.hide { animation: notifToastOut .22s ease-in forwards; }
@keyframes notifToastIn {
  0%   { transform: translateY(-8px) scale(.8); opacity: 0; }
  60%  { transform: translateY(2px) scale(1.03); opacity: 1; }
  100% { transform: none; opacity: 1; }
}
@keyframes notifToastOut { to { transform: translateY(-6px) scale(.9); opacity: 0; } }
.notif-toast-icona {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent);
}
.notif-toast-icona .material-icons-outlined { font-size: 18px; }
.notif-toast-quiz .notif-toast-icona { background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); }
.notif-toast-corpo { flex: 1; min-width: 0; }
.notif-toast-titolo { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.notif-toast-testo {
  font-size: 13px; color: var(--text2); overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.notif-toast-altre { margin-top: 6px; font-size: 12px; font-weight: 500; color: var(--text3); }
/* La campanella oscilla e il pallino fa "pop": come il pulsante della chat. */
.notif-bell.suona .material-icons-outlined { animation: campanellaSuona .8s ease; transform-origin: 50% 3px; }
@keyframes campanellaSuona {
  0%, 100% { transform: rotate(0); }
  15% { transform: rotate(14deg); }  30% { transform: rotate(-12deg); }
  45% { transform: rotate(8deg); }   60% { transform: rotate(-5deg); }  75% { transform: rotate(2deg); }
}
.notif-badge.pop { animation: chatBadgePop .4s cubic-bezier(.34,1.56,.64,1); }
@media (prefers-reduced-motion: reduce) {
  .notif-toast, .notif-toast.hide, .notif-bell.suona .material-icons-outlined, .notif-badge.pop { animation: none; }
}
/* Sul telefono sotto la testata, largo quanto lo schermo (come l'elenco). */
@media (max-width: 600px) {
  .notif-toast {
    position: fixed; top: calc(62px + env(safe-area-inset-top)); left: 12px; right: 12px;
    width: auto; max-width: none; transform-origin: calc(100% - 30px) 0;
  }
  .notif-toast::before { display: none; }
}
.user-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 10px 0; border-bottom: 1px solid var(--gray5); }
.user-row:last-child { border-bottom: none; }
.user-row-info { flex: 1 1 140px; min-width: 0; overflow: hidden; }
.user-row-info strong { font-size: 14px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-row-info span   { font-size: 12px; color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.user-row .btn { flex-shrink: 0; }
.user-row .role-badge { flex-shrink: 0; white-space: nowrap; }
.user-row-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; margin-left: auto; }
/* native title tooltip is used for user emails — no custom CSS needed */
.role-badge { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); }
.role-badge.admin { background: color-mix(in srgb, var(--purple) 10%, transparent); color: var(--purple); }
.user-row-pending { background: color-mix(in srgb, var(--orange) 6%, transparent); border-radius: 8px; padding: 10px 10px; margin: 0 -10px; }

/* ── Matrice moduli utenti (Impostazioni → Utenti → Matrice moduli) ── */
.mod-matrix-wrap {
  overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card);
}
.mod-matrix-table { border-collapse: collapse; width: 100%; min-width: 480px; }
.mod-matrix-table th, .mod-matrix-table td {
  padding: 10px 12px; border-bottom: 1px solid var(--border); text-align: center;
}
.mod-matrix-table tr:last-child td { border-bottom: none; }
.mod-matrix-table th {
  font-size: 12px; color: var(--text3); font-weight: 600; white-space: nowrap;
  background: var(--gray6);
}
.mod-matrix-table th .material-icons-outlined { font-size: 18px; vertical-align: middle; }
.mod-matrix-user-col {
  text-align: left; position: sticky; left: 0; background: var(--card);
  min-width: 150px; max-width: 190px; z-index: 1;
}
.mod-matrix-table th.mod-matrix-user-col { background: var(--gray6); }
.users-pending-label { font-size: 12px; font-weight: 700; color: var(--orange); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 8px; display: flex; align-items: center; gap: 4px; }

/* ── Color / Icon pickers ── */
.color-picker { display: flex; gap: 8px; flex-wrap: wrap; }
.color-dot {
  width: 28px; height: 28px; border-radius: 50%; cursor: pointer;
  border: 2px solid transparent; transition: transform var(--transition);
  display: flex; align-items: center; justify-content: center;
}
.color-dot:hover { transform: scale(1.15); }
.color-dot.selected { border-color: var(--text); transform: scale(1.1); }
.color-dot.selected::after { content: '✓'; font-size: 12px; color: #fff; font-weight: 700; }
/* ── IL COLORE DELL'AZIENDA: SU MISURA E ANTEPRIMA ──────────────────────────
   La tavolozza qui sopra e' la scorciatoia; queste due righe sono la liberta'
   vera — il selettore del sistema e l'esadecimale scritto a mano, che e' quello
   che ha in mano chi arriva col manuale del proprio marchio. */
.colore-su-misura {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; font-size: 13px; color: var(--text3);
}
/* Senza .form-group davanti: la pagina Aspetto (aspettoBlocco) non ce l'ha, e
   con quel prefisso queste regole non valevano mai — i due campi uscivano
   nativi, bianchi sul tema scuro, e il selettore rettangolare sotto una fila di
   pastiglie tonde. Ora il colore su misura e' TONDO e grande come le pastiglie,
   e l'esadecimale e' un campo dell'app, con i suoi colori. */
.colore-su-misura input[type=color] {
  -webkit-appearance: none; appearance: none;
  width: 28px; height: 28px; padding: 0; margin: 0; flex: none; cursor: pointer;
  border: none; border-radius: 50%; background: none;
  /* Un anello sottile staccato di 2px: dice "si tocca" senza sembrare un'altra
     pastiglia della tavolozza. */
  box-shadow: 0 0 0 2px var(--card), 0 0 0 3.5px var(--bordo-campo);
}
.colore-su-misura input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
.colore-su-misura input[type=color]::-webkit-color-swatch { border: none; border-radius: 50%; }
.colore-su-misura input[type=color]::-moz-color-swatch { border: none; border-radius: 50%; }
.colore-su-misura input[type=color]:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.colore-su-misura input[type=text] {
  width: 108px; height: 34px; padding: 0 10px; margin: 0; flex: none;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm);
  background: var(--card); color: var(--text);
  font: 500 13px ui-monospace, Menlo, Consolas, monospace; letter-spacing: .02em; text-transform: uppercase;
  transition: border-color var(--transition);
}
.colore-su-misura input[type=text]:focus { outline: none; border-color: var(--accent); }

/* L'anteprima: questo colore non tinge il gestionale, tinge quello che vedono i
   clienti. Senza vederlo su qualcosa, si sceglie alla cieca. */
.colore-anteprima {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 14px; padding: 14px 16px;
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card);
}
.colore-anteprima-eti { font-size: 12px; color: var(--text3); margin-right: 2px; }
.colore-anteprima-chip {
  font-size: 12.5px; font-weight: 600; padding: 4px 11px; border-radius: var(--r-full);
  color: var(--tinta-stato, var(--accent));
  background: color-mix(in srgb, var(--tinta-stato, var(--accent)) 14%, var(--card));
}
.colore-anteprima-btn {
  font-size: 13px; font-weight: 700; padding: 8px 18px; border-radius: var(--r-full);
  background: var(--tinta-stato, var(--accent)); color: #fff;
}

/* ── IL LOGO ─────────────────────────────────────────────────────────────────
   Il logo caricato E' il riquadro: prima era una miniatura da 40px sotto un
   campo "scegli file", e sembrava che non ci fosse niente. */
/* ── I BLOCCHI DI IMPOSTAZIONI → ASPETTO ─────────────────────────────────────
   Quattro riquadri uguali: a sinistra il titolo con sotto una riga piu' piccola
   e grigia che spiega, a destra il comando. Se serve altro (la tavolozza, il
   logo, una nota) sta nel corpo sotto, staccato da un filo.

   La forma e' UNA SOLA per tutti e quattro. Prima ogni pezzo aveva la sua —
   un campo nudo, un riquadro tratteggiato, un altro riquadro con l'interruttore
   di fianco — e la pagina sembrava montata con quello che c'era. */
.imp-blocco {
  padding: 16px 20px; border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md); background: var(--card);
}
.imp-blocco + .imp-blocco { margin-top: 12px; }
.imp-testa {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  flex-wrap: wrap;
}
.imp-testo { flex: 1; min-width: 220px; }
.imp-testo h3 { margin: 0; font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.imp-testo p  { margin: 3px 0 0; font-size: 12.5px; font-weight: 400; line-height: 1.5; color: var(--text3); }
.imp-comando { display: flex; align-items: center; gap: 8px; flex: none; }
.imp-corpo { margin-top: 14px; }

/* Il dato, quando si legge e non si scrive: e' il pezzo importante del riquadro
   e ha il corpo per dirlo. */
.imp-valore { margin: 0; font-size: var(--fs-md); font-weight: 500; color: var(--text); }
.imp-vuoto { color: var(--text3); font-style: normal; }
.imp-nota { margin: 0; font-size: 12.5px; font-weight: 400; line-height: 1.5; color: var(--text3); }
.imp-nota strong { font-weight: 600; color: var(--text2); }
.imp-nota-serve { color: var(--stato-attesa); }
.imp-nota-serve strong { color: var(--stato-attesa); }
.imp-nota .material-icons-outlined { vertical-align: -3px; }

/* Il nome in modifica: campo e due pulsanti su una riga sola. */
.imp-modifica { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.imp-modifica input { flex: 1; min-width: 200px; }

/* Lo stato a parole, accanto all'interruttore. Serve perche' un interruttore da
   solo dice "acceso/spento" ma non dice acceso COSA — e con la firma era
   proprio quella la domanda. */
.stato-pillola {
  padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600; line-height: 1.5;
}
.stato-pillola.stato-attiva {
  color: var(--stato-fatto);
  background: color-mix(in srgb, var(--stato-fatto) 14%, transparent);
}
.stato-pillola.stato-spenta { color: var(--text3); background: var(--gray6); }
.firma-comando { display: flex; align-items: center; gap: 10px; }

/* Il pulsante che toglie: stessa forma degli altri, colore diverso. Il gesto
   distruttivo resta il piu' quieto — lo fa il colore, non una forma a parte. */
.btn.btn-quieto-pericolo { color: var(--danger); }
.btn.btn-quieto-pericolo:hover {
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}

/* Sta dentro un .imp-blocco, che il bordo ce l'ha gia': qui basta il fondo piu'
   scuro a dire "questo e' il posto del logo". Due cornici una dentro l'altra
   sono il segno che due componenti sono stati incastrati senza guardarli. */
.logo-riquadro {
  display: flex; align-items: center; justify-content: center; min-height: 96px;
  padding: 14px 18px; border-radius: var(--r-md); background: var(--gray6);
}
.logo-riquadro.vuoto { border: 1px dashed var(--bordo-campo); }
.logo-anteprima {
  max-height: 72px; max-width: 260px; object-fit: contain;
  /* Una scacchiera leggera dietro: meta' dei loghi ha lo sfondo trasparente, e
     su bianco non si distingue un PNG ritagliato bene da uno ritagliato male. */
  background-image:
    linear-gradient(45deg, var(--gray6) 25%, transparent 25%, transparent 75%, var(--gray6) 75%),
    linear-gradient(45deg, var(--gray6) 25%, transparent 25%, transparent 75%, var(--gray6) 75%);
  background-size: 14px 14px; background-position: 0 0, 7px 7px;
  border-radius: var(--r-sm); padding: 6px;
}
/* Le azioni del logo stanno nella testata del blocco (.imp-comando) insieme a
   tutte le altre: qui resta solo come si dichiara il vuoto. */
.logo-vuoto-testo {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 400; color: var(--text3);
}
.logo-vuoto-testo .material-icons-outlined { font-size: 20px; }
.btn-link-pericolo {
  background: none; border: 0; padding: 4px 2px; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--danger); text-decoration: underline;
}
.btn-link-pericolo:hover { filter: brightness(.9); }

.icon-picker { display: flex; gap: 6px; flex-wrap: wrap; }
.icon-opt {
  width: 36px; height: 36px; border-radius: 8px; font-size: 18px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; background: var(--gray6); border: 2px solid transparent; transition: all var(--transition);
}
.icon-opt:hover { background: var(--gray5); transform: scale(1.1); }
.icon-opt.selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* ── User select list (sharing) ── */
.user-select-list { max-height: 220px; overflow-y: auto; overflow-x: hidden; border: 1.5px solid var(--bordo-campo); border-radius: var(--r-md); }
.user-select-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer; transition: background var(--transition); }
.user-select-item > div { min-width: 0; }
.user-select-item strong, .user-select-item span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-select-item:hover { background: var(--gray6); }
.user-select-item.selected { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.user-select-item input[type=checkbox] { accent-color: var(--accent); width: 16px; height: 16px; }

/* ── Toast ── */
.toast-container { position: fixed; top: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 8px; max-width: 320px; }
/* color:#fff era sbagliato in tema scuro: il toast di default ha fondo
   var(--text), che al buio e' quasi bianco — testo bianco su quasi bianco,
   invisibile. --su-colore e' fatto apposta per questo capovolgimento e vale
   anche sulle varianti colorate qui sotto. Raggio e ombra portati a token
   (nessuno dei due era un valore ammesso), animazione allineata al tempo di
   comparsa di sistema (200ms, la stessa curva). */
.toast {
  background: var(--text); color: var(--su-colore); border-radius: var(--r-md); padding: 12px 16px;
  font-size: 14px; font-weight: 500; box-shadow: var(--shadow-1);
  animation: slideIn var(--t-appare); display: flex; align-items: flex-start; gap: 10px;
}
.toast.success  { background: var(--green); }
.toast.error    { background: var(--red); }
.toast.warning  { background: var(--orange); }
.toast.reminder { background: var(--purple); }
.toast-content { flex: 1; }
.toast-title { font-weight: 600; }
.toast-msg   { font-size: 13px; opacity: .85; margin-top: 2px; }
@keyframes slideIn { from { transform: translateX(110%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes fadeOut { to { opacity: 0; transform: translateX(30px); } }

/* ── Loading ── */
.spinner { width: 22px; height: 22px; border: 2px solid var(--gray4); border-top-color: var(--accent); border-radius: 50%; animation: spin .6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.loading-state { display: flex; align-items: center; justify-content: center; gap: 12px; height: 200px; color: var(--text3); }

/* Spinner compatto per dentro un bottone (es. "Analizza…", "Salvataggio…").
   Non e' legato a .btn: serve identico nei bottoni a sola icona (.btn-icon) e
   in quelli del visualizzatore a schermo intero, dove prima restava un <div>
   senza dimensioni ne' animazione — il bottone si svuotava e non girava
   niente. Le varianti qui sotto vincono per specificita'. */
.spinner-sm {
  width: 15px; height: 15px; border: 2px solid color-mix(in srgb, var(--su-accento) 35%, transparent); border-top-color: var(--su-accento);
  border-radius: 50%; animation: spin .6s linear infinite; flex-shrink: 0;
}
.btn-secondary .spinner-sm { border-color: var(--gray4); border-top-color: var(--accent); }
.btn-danger .spinner-sm { border-color: color-mix(in srgb, var(--danger) 35%, transparent); border-top-color: var(--danger); }
/* Bottone a sola icona: sta su scheda chiara e l'icona e' gia' grigia, quindi
   anche la rotellina resta grigia invece di accendersi con la tinta. */
.btn-icon .spinner-sm { border-color: var(--gray4); border-top-color: var(--text2); }
.btn:disabled { opacity: .45; cursor: default; }

/* ── SMTP Settings ── */
.smtp-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px;
}
@media (max-width: 600px) { .smtp-grid { grid-template-columns: 1fr; } }

/* ── Chat / Comments ── */
.chat-messages {
  display: flex; flex-direction: column; gap: 10px;
  max-height: 320px; overflow-y: auto;
  padding: 8px 0 4px;
}
.chat-loading { font-size: 13px; color: var(--text3); text-align: center; padding: 12px 0; }

.chat-msg { display: flex; align-items: flex-end; gap: 8px; }
/* ── Le spunte, in tre stati come su WhatsApp ─────────────────────────────
   Una grigia: inviato. Due grigie: recapitato, cioe' arrivato sul dispositivo
   di tutti. Due blu: letto da tutti.
   Prima gli stati erano due, e per una ragione onesta: non esisteva un segnale
   di consegna distinto dalla lettura, e un terzo stato senza un dato vero dietro
   sarebbe stato inventato. Adesso il dato c'e': lo scrive il dispositivo del
   destinatario quando riceve la push o interroga i badge
   (api/chat_recapito_helper.php).
   Il letto e' BLU e non nel colore dell'accento: e' un segnale che tutti
   conoscono gia', e nel colore dell'app si confonderebbe col resto
   dell'interfaccia proprio dove deve distinguersi dal grigio.
   Si vedono solo sui PROPRI messaggi. */
.chat-receipt { display: inline-flex; cursor: pointer; }
.chat-receipt .material-icons-outlined { font-size: 14px; color: var(--text3); }
.chat-receipt.chat-receipt-read .material-icons-outlined { color: var(--blue); }

.chat-mine  { flex-direction: row-reverse; }
.chat-theirs { flex-direction: row; }

.chat-bubble-wrap { display: flex; flex-direction: column; max-width: 78%; }
.chat-mine .chat-bubble-wrap { align-items: flex-end; }
.chat-theirs .chat-bubble-wrap { align-items: flex-start; }

.chat-sender { font-size: var(--fs-xs); color: var(--text2); margin-bottom: 2px; padding: 0 4px; }

.chat-bubble {
  display: flex; align-items: flex-end; gap: 6px;
  padding: 8px 12px; border-radius: var(--r-xl);
  font-size: 14px; line-height: 1.5; word-break: break-word;
}
.chat-mine .chat-bubble {
  background: var(--accent); color: var(--su-accento);
  border-bottom-right-radius: 4px;
}
/* Era var(--gray6): la scheda a riempimento grigio che il §5 vuole sparita,
   qui era una bolla dentro il pannello bianco — scheda dentro scheda in
   miniatura. Appiattita su fondo/bordo come richiesto, contenuto intatto. */
.chat-theirs .chat-bubble {
  background: var(--card); border: 1px solid var(--border); color: var(--text1);
  border-bottom-left-radius: 4px;
}

.chat-text { flex: 1; }

/* rgba(255,255,255,.7) era bianco fisso: in tema scuro la bolla propria ha
   fondo accento chiaro (pastello) e testo/icone scure — un'icona bianca ci
   sarebbe quasi sparita sopra. --su-accento e' il colore giusto in entrambi
   i temi, qui solo attenuato. */
.chat-delete {
  background: none; border: none; cursor: pointer; padding: 0; line-height: 1;
  opacity: 0; transition: opacity var(--t-stato); flex-shrink: 0;
  color: color-mix(in srgb, var(--su-accento) 70%, transparent);
}
.chat-bubble:hover .chat-delete { opacity: 1; }
.chat-delete .material-icons-outlined { font-size: 14px; }

/* Il colore era gia' stato alzato da --text3 a --text2 (il terziario e' vietato
   sotto i 12px). Restava l'altra meta' del problema: il corpo, che a 11px stava
   sotto quella stessa soglia. E il margine di 3px non e' un gradino. */
.chat-time { font-size: var(--fs-xs); color: var(--text2); margin-top: 4px; padding: 0 4px; }

.chat-input-bar {
  display: flex; align-items: flex-end; gap: 8px;
  padding: 10px 16px 12px; border-top: 1px solid var(--border);
  background: var(--surface); flex-shrink: 0;
}
/* --border (grigio decorativo da scheda) su un campo di testo non arriva al
   3:1 richiesto per i bordi dei comandi: qui serve --bordo-campo, lo stesso
   usato da ogni altro input dell'app, con lo stesso spessore 1.5px. */
.chat-input {
  flex: 1; resize: none; border: 1.5px solid var(--bordo-campo); border-radius: var(--r-xl);
  padding: 8px 14px; font-size: 16px; font-family: inherit;
  background: var(--gray6); color: var(--text1);
  outline: none; line-height: 1.4; max-height: 120px; overflow-y: auto;
  transition: border-color var(--t-stato);
}
/* UN solo segnale, come nei campi dei form (vedi .form-group ... :focus-visible
   piu' su): il bordo che diventa accento E l'anello di :focus-visible due pixel
   piu' in fuori facevano due cornici verdi concentriche attorno allo stesso
   campo. Nei campi di testo il browser accende :focus-visible anche col mouse,
   quindi capitava a ogni clic. Vale per la chat interna e per quella
   dell'assistenza: e' lo stesso campo. */
.chat-input:focus { border-color: var(--accent); }
.chat-input:focus-visible { outline: none; border-color: var(--accent); }
.chat-send-btn {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent); color: var(--su-accento); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background var(--t-stato);
  /* Il bordo lo azzera QUI, non solo .btn-icon: il pulsante della chat a
     pannello non aveva .btn-icon e si portava dietro il bordo di serie del
     browser — un anello grigio in rilievo attorno al cerchio, il "riflesso". */
  -webkit-appearance: none; appearance: none; border: none; padding: 0; cursor: pointer;
}
.chat-send-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* L'hover cambia il fondo, non l'opacita': stessa formula di scurimento gia'
   in uso per .btn-primary:hover. */
.chat-send-btn:hover { background: color-mix(in srgb, var(--accent) 88%, #000); }

.install-step {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--gray5); font-size: 14px; line-height: 1.5;
}
.install-step:last-of-type { border-bottom: none; }
.install-step-num {
  min-width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: var(--su-accento);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600; flex-shrink: 0;
}

.install-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; background: var(--gray6); border-radius: var(--r-md); margin-top: 12px;
}
.install-row .material-icons-outlined { color: var(--accent); }
.install-status {
  display: flex; align-items: center; gap: 6px;
  padding: 10px 16px; background: color-mix(in srgb, var(--green) 10%, transparent); border-radius: var(--r-md);
  margin-top: 12px; font-size: 14px; color: var(--green);
}

#install-banner {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  background: var(--accent); color: var(--su-accento);
  border-radius: var(--r-xl); padding: 14px 16px;
  box-shadow: var(--shadow-2);
  z-index: 9000; width: calc(100% - 40px); max-width: 460px;
  animation: slideUp .3s ease-out;
}
@keyframes slideUp { from { transform: translateX(-50%) translateY(20px); opacity:0; } to { transform: translateX(-50%) translateY(0); opacity:1; } }

/* ── Helpers ── */
* { scrollbar-width: thin; scrollbar-color: var(--gray4) transparent; }
/* scrollbar-width è ignorata da Chrome/Edge/Safari: senza questa, un contenitore che
   scrolla di traverso senza una regola ::-webkit-scrollbar dedicata mostra la barra
   grigia spessa di sistema invece di quella sottile usata ovunque nell'app */
html::-webkit-scrollbar, body::-webkit-scrollbar { width: 5px; }
html::-webkit-scrollbar-thumb, body::-webkit-scrollbar-thumb { background: var(--gray4); border-radius: 3px; }

/* ══════════════════════════════════════════════
   MOBILE RESPONSIVE
══════════════════════════════════════════════ */

/* Content wrapper: contiene overlay + main-content; l'overlay non può mai uscire da qui */
#content-wrapper {
  position: relative;
  flex: 1;
  overflow: hidden;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* Overlay sidebar: position:absolute = fisicamente sotto l'header, mai nella safe-area zone */
#sidebar-overlay {
  display: none;
  position: absolute;
  inset: 0;
  /* Stesso velo tinto usato per il modale (.modal-overlay), non un nero secco
     scelto qui per conto suo. */
  background: var(--velo-sfondo);
  z-index: 99;
  pointer-events: none;
}
#sidebar-overlay.active { display: block; pointer-events: auto; }

@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) and (pointer: coarse) {
  /* Sidebar: slide in from left.
     La seconda condizione (OR) intercetta lo smartphone ruotato in orizzontale: la
     larghezza in quel caso spesso supera già 768px (es. iPhone ~850px), ma l'altezza
     resta bassa (~390-430px) e il touch è "coarse" — a differenza di iPad orizzontale
     (altezza ~768-1024px), che deve restare nel layout desktop com'è oggi. */
  .sidebar {
    position: fixed; left: 0; top: 0; height: 100%; z-index: 101;
    transform: translateX(-100%); transition: transform var(--transition);
    box-shadow: none; width: 280px; min-width: 280px;
    padding-top: env(safe-area-inset-top);
  }
  .sidebar.mobile-open {
    /* La barra laterale in sovrapposizione su mobile e' L2: bordo (gia' c'e',
       eredita border-right dalla regola base) + shadow-1, non un valore a mano. */
    transform: translateX(0); box-shadow: var(--shadow-1);
  }

  /* Show hamburger button */
  .mobile-menu-btn { display: flex !important; }

  #app { padding-top: 0; }

  /* Header: padding-top assorbe la safe-area (Dynamic Island/notch).
     L'overlay sta SOTTO questo elemento (è nel content-wrapper), quindi non può mai
     toccare questa zona né la status bar sopra. Nessuno z-index trick necessario. */
  #app-header {
    padding: calc(env(safe-area-inset-top) + 10px) 16px 10px;
  }
  /* Un gradino sotto il titolo desktop (28), non un valore fuori scala: --fs-lg. */
  .main-header h2 { font-size: var(--fs-lg); }
  /* Sul telefono lo stacco fra azioni di pagina e icone fisse si stringe: la
     testata ha meno di quattrocento pixel e dodici sono un lusso. */
  .header-icone { gap: 7px; }

  /* Filter bar: wrap to multiple rows on mobile */
  .filter-bar { padding: 0 12px 10px; flex-wrap: wrap; gap: 6px; }
  .dash-wrap { padding: 4px 12px 32px; }
  /* Su una riga sua c'e' posto anche sul telefono: l'etichetta resta. Il
     rientro NON si riscrive qui: --rientro-lettura scende gia' a --gutter sotto
     i 768px, ed e' lo stesso valore di testata, filtri ed elenco. Scriverne uno
     a mano (erano 12px) metteva il pulsante su una verticale tutta sua. */
  .filter-chip { flex: 1 1 auto; text-align: center; }
  .leave-budget-cards { padding: 12px 12px 16px; }

  /* Task list: less padding */
  .task-list-container { padding: 0 12px 100px; }

  /* Modal: full screen bottom sheet.
     top: env(safe-area-inset-top) invece di inset:0 — stesso principio già usato per
     l'overlay della sidebar: un elemento position:fixed non deve MAI estendersi nella
     zona della Dynamic Island/notch. Con inset:0 + 100dvh, quando si apre un campo di
     testo del modal (tastiera che compare/scompare — l'editor appuntamento ne ha molti)
     il ricalcolo di 100dvh su iOS in PWA standalone a volte non ridipinge quella striscia
     in cima, che resta "sporca" (grigio scuro) finché non si forza la chiusura dell'app.
     Tenendo l'overlay strutturalmente fuori da quella zona, non può mai succedere: quella
     striscia resta sempre di competenza dell'header sottostante, che ridipinge normalmente. */
  .modal-overlay { padding: 0; align-items: flex-end; top: env(safe-area-inset-top); }
  .modal {
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    width: 100vw; max-width: 100vw; box-sizing: border-box;
    overflow-x: hidden;
    max-height: calc(100dvh - env(safe-area-inset-top) - 16px);
    transform: translateY(100%);
  }
  .modal-overlay.open .modal { transform: translateY(0); }
  /* Prevent iOS auto-zoom on input focus (threshold: font-size >= 16px) */
  input, select, textarea, .detail-title-input, .chat-input { font-size: 16px !important; }
  /* Eccezione: controlli inline della barra contesto appuntamento — compatti e allineati.
     Lo zoom iOS è comunque disattivato dal viewport (user-scalable=no). */
  .apt-f-time-inline {
    font-size: 13px !important; width: auto !important; max-width: 45vw !important;
    min-height: 0 !important; height: auto !important; line-height: 1.3;
    padding: 4px !important; display: inline-block;
  }
  .apt-f-context { row-gap: 8px; }
  .apt-f-ctx-item { flex: 0 0 auto; }

  .modal-body { padding: 16px; overflow-x: hidden; box-sizing: border-box; width: 100%; }
  .modal-body * { box-sizing: border-box; max-width: 100%; }
  .modal-body input:not(.apt-f-time-inline):not([type="checkbox"]):not([type="radio"]), .modal-body select:not(.apt-f-time-inline), .modal-body textarea { width: 100%; max-width: 100%; }
  .modal-body .form-group { overflow: hidden; }
  .modal-body .form-group:has(.apt-client-dropdown) { overflow: visible; }
  .modal-body input[type="date"], .modal-body input[type="time"] {
    -webkit-appearance: none; appearance: none; display: block; width: 100%; min-height: 44px;
  }
  .modal-body .leave-type-btn { min-width: 0; flex: 1; }
  .modal-footer { padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); gap: 8px; }
  .modal-footer .btn { flex: 1; justify-content: center; }

  /* Toast: full width top */
  .toast-container { left: 12px; right: 12px; max-width: unset; top: 12px; }

  /* Auth card: full width */
  .auth-card { border-radius: var(--r-lg); padding: 32px 24px; margin: 16px; }
}

/* ══════════════════════════════════════
   PIANO FERIE
══════════════════════════════════════ */
/* ── I comandi sopra la tavola ────────────────────────────────────────────────
   Il passo del mese era tre elementi sciolti su una riga con un filo sotto: due
   frecce e una scritta che non stavano insieme. Adesso e' un comando solo —
   un riquadro con bordo e ombra, come il filtro delle sedi accanto — cosi' si
   legge come una cosa sola invece che come tre. */
/* Le tre misure del Piano Ferie in un posto solo. La larghezza della colonna
   dei nomi la usano sia la colonna sia lo strato delle barre: scritta due volte,
   prima o poi divergono e le barre si spostano rispetto ai giorni. */
/* Le misure della tavola stanno tutte qui. La larghezza del giorno la usano la
   cella, la sua intestazione E il calcolo delle barre in app.js (che legge questo
   token invece di ripetere il numero): scritta in piu' posti, prima o poi le copie
   divergono e le barre si spostano rispetto ai giorni. */
:root { --pf-col-nome: 236px; --pf-col-giorno: 42px; --pf-alt-riga: 48px; --pf-alt-barra: 30px; }

/* Il sottotitolo sotto il titolo di pagina: quante persone, quanti giorni via,
   quanti di chiusura. E' il riassunto che si cerca per primo aprendo la
   schermata, e prima bisognava contare le barre a occhio. */
.pf-sottotitolo { font-size: 13px; color: var(--text3); margin-top: 1px; }

.pf-comandi {
  display: flex; align-items: center; gap: 10px;
  padding: 4px var(--gutter) 14px;
}
.pf-mese {
  display: flex; align-items: center; gap: 2px;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-sm); padding: 3px; box-shadow: var(--shadow-1);
}
.pf-mese button {
  appearance: none; border: 0; background: none; cursor: pointer;
  width: 30px; height: 30px; border-radius: var(--r-xs); color: var(--text2);
  display: grid; place-items: center;
  transition: background var(--t-stato), color var(--t-stato);
}
.pf-mese button:hover { background: var(--gray6); color: var(--text); }
.pf-mese button .material-icons-outlined { font-size: 19px; }
.pf-mese #pf-title {
  min-width: 138px; text-align: center;
  font-size: var(--fs-base); font-weight: 600; color: var(--text);
}
/* Il filtro delle sedi prende lo stesso trattamento, cosi' i due comandi
   affiancati sembrano della stessa famiglia invece che presi da due posti. */
/* Le misure sono quelle del ridisegno, prese dal file: alto 36, spazio interno
   12, corpo 13,5, peso normale. Prima era piu' alto, piu' grasso e col bordo
   piu' marcato — pesava piu' del comando del mese che ha accanto, e i due non
   si leggevano come una coppia. */
.pf-comandi .filter-chip {
  display: inline-flex; align-items: center; gap: 7px;
  height: 36px; padding: 0 12px;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-sm); box-shadow: var(--shadow-1);
  color: var(--text2); font-size: 13.5px; font-weight: 400;
}
.pf-comandi .filter-chip .material-icons-outlined { font-size: 18px; }
.pf-comandi .filter-chip:hover { border-color: var(--bordo-campo); background: var(--card); }

/* La tavola e' una scheda: fondo proprio, bordo, angoli, e un'ombra sola.
   Prima galleggiava sul fondo della pagina senza contorni, e non si capiva dove
   cominciasse e dove finisse. */
/* La scheda NON scorre: scorre solo la griglia dentro di lei (#pf-scorri).
   Cosi' la barra di scorrimento orizzontale sta dove deve — fra i giorni e la
   legenda — invece che in fondo alla scheda, sotto la legenda e a cavallo
   dell'angolo arrotondato. E la legenda smette di scorrere di lato insieme ai
   giorni, cosa che non aveva senso visto che parla di tutto il mese.
   ── La barra di scorrimento ──────────────────────────────────────────────
   Due tentativi andati storti prima di questo: rifatta a mano era un filo di
   due pixel che non si capiva fosse trascinabile; lasciata a quella di sistema
   restava comunque sottile (la regola generale del foglio mette
   scrollbar-width:thin su TUTTO) e schiacciata contro il filo della legenda,
   senza un dito di spazio intorno.
   Adesso la fascia e' alta 18px e il pollice ne occupa 8, centrato: i 5px di
   bordo trasparente sopra e sotto sono il margine che mancava, e la fascia
   stessa diventa il respiro fra l'ultima riga di persone e la legenda.
   Il bordo e' trasparente e non colorato apposta: cosi' il margine prende il
   colore della scheda qualunque esso sia, tema chiaro o scuro.
   Il grigio e' --gray2 e non --gray4: quest'ultimo, su una scheda bianca, sta a
   1,6 di contrasto — su otto pixel di spessore sarebbe stato di nuovo un filo
   che non si vede. --gray2 si legge su entrambi i temi. */
#pf-scorri {
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-x pan-y; overscroll-behavior-x: contain;
  /* Le due proprieta' standard vanno riportate a "auto", non impostate:
     Chrome IGNORA le regole ::-webkit-scrollbar qui sotto se sull'elemento c'e'
     uno scrollbar-color diverso da auto — e il foglio ne mette uno su TUTTO con
     la regola "*". Misurato: con scrollbar-color valorizzato la fascia restava
     ai 15px di sistema; riportandolo ad auto passa ai 18 dichiarati.
     Firefox non ha le pseudo-classi e prende la sua barra normale: piu' spessa
     di quella "thin" di prima, che era il problema. */
  scrollbar-width: auto;
  scrollbar-color: auto;
}
#pf-scorri::-webkit-scrollbar { height: 18px; }
#pf-scorri::-webkit-scrollbar-track { background: transparent; }
#pf-scorri::-webkit-scrollbar-thumb {
  background: var(--gray2);
  border-radius: var(--r-full);
  border: 5px solid transparent;
  background-clip: content-box;
}
#pf-scorri::-webkit-scrollbar-thumb:hover {
  background: var(--gray1); background-clip: content-box;
}
/* Le frecce agli estremi appartengono a un'altra epoca di interfacce: dentro una
   scheda sembrano una cornice di finestra finita li' per sbaglio. */
#pf-scorri::-webkit-scrollbar-button { display: none; width: 0; height: 0; }

#pf-wrap {
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  margin: 0 var(--gutter) 16px;
}
.pf-grid { display: inline-block; min-width: 100%; }

/* ── La fascia sopra i giorni ─────────────────────────────────────────────────
   Ci vanno le etichette di cio' che vale per tutti: festivita' e chiusure. Una
   chiusura aziendale non e' l'assenza di qualcuno — ripeterla come blocco su
   ogni riga direbbe otto volte la stessa cosa, e la farebbe sembrare
   un'assenza personale. */
.pf-bande { display: flex; align-items: stretch; }
.pf-bande-nome {
  min-width: var(--pf-col-nome); max-width: var(--pf-col-nome);
  position: sticky; left: 0; z-index: 5; background: var(--card);
  border-right: 1px solid var(--bordo-scheda);
}
.pf-bande-pista { position: relative; flex: 1; height: 28px; }
.pf-banda {
  position: absolute; top: 6px; height: 20px;
  margin: 0 3px; box-sizing: border-box;
  border-radius: 5px; padding: 0 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 600; letter-spacing: .01em;
  white-space: nowrap; overflow: hidden; color: var(--su-colore);
}
.pf-banda-festivo  { background: var(--danger); }
.pf-banda-chiusura { background: var(--purple); }

.pf-header-row,
.pf-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--gray5);
  transition: background .1s;
}
.pf-row { cursor: default; position: relative; }
.pf-row:hover { background: var(--gray6); }
/* Click sul tecnico: evidenzia l'intera riga, per non perdere lo sguardo
   scorrendo verso il giorno cercato.
   Prima erano due binari accent da due pixel sopra e sotto: un segno pesante,
   che tagliava la riga in orizzontale e non somigliava a niente altro nella
   schermata rifatta. Il segno sta ora dove si guarda davvero — nella colonna
   dei nomi, che resta ferma mentre si scorre di lato: una barretta accent sul
   bordo sinistro, il nome in accento. Sui giorni resta una velatura chiusa da
   due fili sottili, che regge anche sopra le celle colorate senza gridare. */
.pf-row-highlighted { position: relative; background: color-mix(in srgb, var(--accent) 8%, transparent); }
.pf-row-highlighted::after {
  content: ''; position: absolute; inset: 0;
  box-shadow: inset 0  1px 0 color-mix(in srgb, var(--accent) 30%, transparent),
              inset 0 -1px 0 color-mix(in srgb, var(--accent) 30%, transparent);
  pointer-events: none; z-index: 3;
}
.pf-row-highlighted .pf-name-cell {
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
  /* La barretta e' un'ombra interna e non un bordo: un bordo sposterebbe di tre
     pixel il contenuto della cella, e i nomi salterebbero di lato a ogni click. */
  box-shadow: inset 3px 0 0 var(--accent);
}
.pf-row-highlighted .pf-name { color: var(--accent); font-weight: 600; } /* Testo di riga normale, non un contrassegno: il tetto e 600 anche da evidenziato. */
.pf-row-highlighted .pf-giorni { border-color: color-mix(in srgb, var(--accent) 35%, transparent); }

/* Trascinando fuori dalla propria sede il fantasma si spegne: si capisce che
   li' non si puo' lasciare, senza bisogno di un messaggio. */
.pf-ghost-fuori-sede { opacity: .45 !important; filter: grayscale(.7); }
.pf-drag-handle {
  /* Piu' discreta: e' un attrezzo, non un'informazione. Prima pesava quanto
     l'avatar accanto. */
  font-size: 16px; opacity: .45;
  transition: opacity var(--t-stato);
  color: var(--gray3);
  cursor: grab;
  flex-shrink: 0;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  padding: 2px 0;
}
.pf-drag-handle:hover { color: var(--text3); opacity: 1; }
.pf-row:hover .pf-drag-handle { opacity: .8; }

/* Il separatore di sede: una riga bassa e chiara, giusto un respiro fra un
   gruppo e l'altro. Il nome resta appiccicato a sinistra mentre si scorre di
   lato — se scorresse via insieme ai giorni, il gruppo diventerebbe di nuovo
   anonimo proprio quando si sta guardando la fine del mese. */
.pf-sede {
  height: 26px; display: flex; align-items: center;
  background: var(--gray6);
  border-top: 1px solid var(--bordo-scheda);
  border-bottom: 1px solid var(--bordo-scheda);
}
.pf-sede:first-child { border-top: none; }
.pf-sede span {
  position: sticky; left: 0;
  padding: 0 14px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text3);
  white-space: nowrap;
}

.pf-name-cell {
  /* La larghezza sta in un token perche' la usa anche lo strato delle barre:
     scritta due volte, prima o poi le due misure divergono e le barre si
     spostano di qualche pixel rispetto ai giorni. */
  min-width: var(--pf-col-nome); max-width: var(--pf-col-nome);
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px;
  position: sticky; left: 0;
  /* Era var(--bg), il colore della PAGINA: una colonna larga 236 pixel dipinta
     del colore del fondo dentro una scheda bianca faceva sembrare grigia tutta
     la tavola. Sta sulla scheda, quindi prende il colore della scheda. */
  background: var(--card);
  border-right: 1px solid var(--bordo-scheda);
  z-index: 3;
  font-size: 13.5px; font-weight: 500;
  /* Tutta la colonna risponde al click, quindi tutta la colonna lo dichiara. */
  cursor: pointer;
}
.pf-header-cell.pf-name-cell { z-index: 5; background: var(--card); cursor: default; }
/* Stesso trattamento delle lettere dei giorni accanto: maiuscoletto piccolo e
   spaziato. E' un'etichetta di colonna, non un titolo. */
.pf-intestazione-nomi {
  /* Un gradino sopra la lettera del giorno: e' l'intestazione di una colonna
     larga sei volte le altre, e a 10px si perdeva nel bianco. */
  font-size: 11.5px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text3);
}
.pf-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; cursor: pointer; }
/* La legenda: solo i tipi presenti in questo mese, con quanti giorni. Tredici
   pallini fissi tutto l'anno sono vocabolario buttato addosso a chi guarda —
   meta' di quelle voci si usa tre volte l'anno. */
/* La legenda sta DENTRO la scheda, in fondo, separata da un filo: e il piede
   della tavola, non un elenco che galleggia sotto. */
.pf-legend-titolo {
  font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text3); margin-right: 2px;
}
.pf-legend-voce {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; color: var(--text2);
  padding: 3px 10px 3px 6px; border-radius: var(--r-full); background: var(--gray6);
}
.pf-legend-voce i {
  width: 17px; height: 17px; border-radius: 5px; flex: none; font-style: normal;
  display: grid; place-items: center;
  font-size: 9.5px; font-weight: 700; color: var(--su-colore);
  background: var(--pf-tinta);
}
.pf-legend-voce b { font-weight: 600; font-size: 11.5px; color: var(--text3); }
.pf-legend-sep { width: 1px; height: 20px; background: var(--bordo-scheda); margin: 0 2px; }
/* La voce che spiega il contorno usa lo stesso aspetto delle barre in attesa:
   quello che si legge nella legenda deve essere la stessa cosa che si vede
   nella griglia. */
.pf-legend-attesa i {
  background: color-mix(in srgb, var(--pf-tinta) 10%, var(--card));
  color: var(--pf-tinta); box-shadow: inset 0 0 0 2px var(--pf-tinta);
}
.pf-legend-altre {
  font-size: 12.5px; color: var(--text3);
  padding: 3px 10px; border-radius: var(--r-full);
  border: 1px solid var(--bordo-campo); background: none;
}
/* Quanti giorni di assenza ha questa persona nel mese. E' la prima cosa che si
   cerca in un piano ferie, e la griglia non la dava affatto: bisognava contare
   le caselle a occhio. */
.pf-giorni {
  flex: none; font-size: 11px; font-weight: 600; color: var(--text3);
  background: var(--gray6); padding: 2px 7px; border-radius: var(--r-full);
}

.pf-day-cell {
  min-width: var(--pf-col-giorno); max-width: var(--pf-col-giorno);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  /* Un paio di pixel in piu' sopra e sotto: le date stavano strette fra il bordo
     alto della scheda e la linea della testata. */
  padding: 8px 2px 9px;
  /* Nessun bordo verticale nell'intestazione: nel ridisegno le date respirano e
     l'unica linea e' quella sotto, che separa la testata dalla griglia.
     I bordi fra le colonne restano dove servono davvero — nelle celle, per
     capire su che giorno cade una barra. */
  font-size: 11px;
}
.pf-header-cell { background: var(--card); position: sticky; top: 0; z-index: 4; font-weight: 500; } /* Intestazione di colonna: la tabella pesi (paragrafo 3) assegna 500, non 700. */
/* Il giorno non lavorativo nell'intestazione: appena accennato. Il rosso acceso
   sui numeri faceva saltare all'occhio la cosa meno importante della schermata. */
.pf-day-off { background: var(--gray6); }
.pf-day-off .pf-dow, .pf-day-off .pf-dnum { color: var(--text3); }
/* Le misure del ridisegno: la lettera del giorno piccola, maiuscoletta e
   spaziata; il numero un filo piu' grande e di peso medio. Prima erano due
   testi quasi uguali e la settimana non si leggeva a colpo d'occhio. */
.pf-dow { font-size: 10px; font-weight: 600; line-height: 1;
          letter-spacing: .05em; text-transform: uppercase; color: var(--text3); }
.pf-dnum { font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--text2); }

.pf-cell {
  min-width: var(--pf-col-giorno); max-width: var(--pf-col-giorno); height: var(--pf-alt-riga);
  display: flex; align-items: center; justify-content: center;
  border-right: 1px solid var(--gray6);
  cursor: pointer;
  position: relative;
  transition: filter .15s;
}
.pf-cell:hover { filter: brightness(.92); }
/* La cella di un'assenza non si dipinge piu' da sola: il colore lo porta la
   barra continua qui sotto. Resta cliccabile e con i suoi dati — cambia solo
   chi disegna. Il passaggio del mouse pero' deve continuare a vedersi, quindi
   schiarisce la barra invece di scurire una cella ormai trasparente. */
.pf-cell-sotto-barra { background: transparent; }
.pf-cell-sotto-barra:hover { filter: none; }
/* ── LO STRATO DELLE BARRE ───────────────────────────────────────────────────
   Sta sopra le celle e NON intercetta i tocchi: sotto restano le celle di
   sempre, con i loro click, i loro dati e le loro classi. Cambia chi dipinge,
   non chi risponde.
   Comincia dopo la colonna dei nomi (240px, la stessa misura di .pf-name-cell)
   e sta sotto di lei nell'impilamento, cosi' scorrendo di lato le barre le
   passano sotto invece che sopra. */
.pf-barre {
  position: absolute; left: var(--pf-col-nome); right: 0; top: 0; bottom: 0;
  pointer-events: none; z-index: 1;
}
.pf-barra {
  position: absolute;
  /* La posizione verticale e' scritta per esteso invece che con "50% piu'
     transform": con le mezze giornate quel giro chiedeva di sommare tre
     spostamenti (meta' riga, meno meta' barra, meno meta' altezza) e il conto
     non tornava mai. Cosi' e' una sottrazione sola e si legge:
     (altezza riga - altezza barra) / 2 = lo spazio sopra e sotto. */
  top: calc((var(--pf-alt-riga) - var(--pf-alt-barra)) / 2);
  height: var(--pf-alt-barra); border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 6px; font-size: 11px; font-weight: 600;
  white-space: nowrap; overflow: hidden;
  background: var(--pf-tinta); color: #fff;
  /* NIENTE margine orizzontale. Su un elemento posizionato in modo assoluto con
     una larghezza esplicita il margine non stringe: SPOSTA. Ogni barra finiva
     due pixel a destra della propria colonna, e sporgeva di due a destra.
     Il filo d'aria fra due periodi consecutivi si toglie dalla misura, quando
     si calcola dove va la barra (vedi pfRenderGrid). */
  box-sizing: border-box;
}
/* In attesa di approvazione: contorno e velo, mai tratteggiata — il tratteggio
   nel linguaggio di oggi vuol dire "segnaposto", non "da approvare". */
/* In attesa di approvazione: velo e contorno. Il contorno e' spesso 2px e il
   velo abbastanza carico da leggersi come "una cosa c'e'": nel primo tentativo
   era cosi' pallido che la barra sembrava un rettangolo vuoto. Il 10% tiene il
   testo sopra i 4,5 di contrasto. */
/* Mezza giornata (DOPO .pf-barra: a parita di specificita vince chi e scritto
   dopo, e messa prima veniva scavalcata su altezza e raggio). una barra alta la meta', spostata su o giu' di meta' altezza.
   Nel ridisegno era cosi'; lasciandola alla cella diventava un rettangolo
   squadrato largo tutta la casella, che non somiglia a niente altro nella
   schermata. Sopra se e' mattina, sotto se e' pomeriggio: dentro la colonna di
   un giorno il tempo scorre dall'alto in basso. */
/* Su un giorno solo "→ VF" ha poco piu' di trenta pixel: margine interno
   stretto, come per le altre sigle corte. */
.pf-barra-trasferta { padding: 0 4px; }

.pf-barra-mezza { height: calc(var(--pf-alt-barra) / 2); padding: 0 5px;
                  font-size: 10px; border-radius: 6px; }
/* La meta' di sopra comincia dove comincerebbe una barra intera; quella di sotto
   mezza barra piu' in giu'. Scritto cosi' si verifica a mente: una barra intera
   va da 9 a 39, la mattina da 9 a 24, il pomeriggio da 24 a 39. */
.pf-barra-mezza.pf-barra-mattina {
  top: calc((var(--pf-alt-riga) - var(--pf-alt-barra)) / 2);
}
.pf-barra-mezza.pf-barra-pomeriggio {
  top: calc((var(--pf-alt-riga) - var(--pf-alt-barra)) / 2 + var(--pf-alt-barra) / 2);
}

.pf-barra-attesa {
  background: color-mix(in srgb, var(--pf-tinta) 10%, var(--card));
  color: var(--pf-tinta);
  box-shadow: inset 0 0 0 2px var(--pf-tinta);
}
/* Mezza giornata: il pieno occupa meta' altezza, sopra se e' mattina e sotto se
   e' pomeriggio. Dentro la colonna di un giorno il tempo scorre dall'alto in
   basso, quindi la posizione dice l'ora senza doverla scrivere. */

.pf-cell-off { background: var(--gray6); cursor: default; }
.pf-cell-off:hover { filter: none; }
/* Il weekend deve farsi notare MENO di tutto il resto: e' la cosa meno
   importante della schermata, e un blocco grigio abbastanza scuro da leggersi
   e' anche abbastanza scuro da rubare l'occhio. Il messaggio "qui non si
   lavora" lo porta la tessitura, non la tinta.
   Sta SOPRA le barre (z-index 2 contro 1) perche' un periodo di ferie
   attraversa il fine settimana per intero — e' giusto vedere il periodo
   continuo, e insieme quali giorni dentro non si contano. */
/* Il weekend e' la cosa MENO importante della schermata, e nel primo tentativo
   era la piu' visibile: fondo grigio pieno piu' tratteggio marcato, colonne
   intere che dominavano tutto. Adesso niente fondo e un tratteggio appena
   percettibile — dice "qui non si lavora" senza gridarlo.
   Sta sopra le barre (z-index 2 contro 1) perche' un periodo di ferie attraversa
   il fine settimana per intero: si vede il periodo continuo e insieme quali
   giorni dentro non si contano. */
/* Il tratteggio sta SOTTO le barre, non sopra. Nel ridisegno un periodo di
   ferie attraversa il fine settimana come una barra intera e ininterrotta: il
   periodo e' quello, e spezzarlo visivamente con una fascia che ci passa sopra
   lo fa sembrare due assenze separate.
   Il tratteggio resta ben visibile nei giorni in cui non c'e' niente sopra,
   che e' dove serve. */
.pf-cell-off { position: relative; background: transparent; }
/* Festivita' e chiusura aziendale sono informazioni che valgono per TUTTI:
   si leggono come colonne tinte, non come una casella ripetuta su ogni riga. */
.pf-col-festivo  { background: color-mix(in srgb, var(--danger) 7%, transparent); }
.pf-col-chiusura { background: color-mix(in srgb, var(--purple) 8%, transparent); }
.pf-col-festivo::after  { --riga-tratteggio: color-mix(in srgb, var(--danger) 15%, transparent); }
.pf-col-chiusura::after { --riga-tratteggio: color-mix(in srgb, var(--purple) 16%, transparent); }
.pf-header-cell.pf-col-festivo  { background: color-mix(in srgb, var(--danger) 7%, var(--card)); }
.pf-header-cell.pf-col-chiusura { background: color-mix(in srgb, var(--purple) 8%, var(--card)); }
.pf-cell-off::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(-45deg, transparent 0 6px,
    var(--riga-tratteggio, color-mix(in srgb, var(--text) 8%, transparent)) 6px 7px);
}
.pf-off-mark { display: none; }
/* La chiusura aziendale non e' piu' una cella rossa piena ripetuta su ogni riga:
   e' una colonna tinta con l'etichetta in cima. Resta il segno dentro la cella. */
.pf-cell-closure .pf-badge { color: var(--purple); text-shadow: none; }
/* La trasferta non e' piu' una cella: la disegna la barra. Qui non resta niente
   da dipingere. */ /* Colore letterale non ammesso: la copertura turno non e uno dei quattro tipi protetti (ferie/permesso/malattia/ROL), puo appoggiarsi al token viola di famiglia. */
/* Mezza giornata (permesso o trasferta solo mattina/pomeriggio): metà cella colorata
   e metà "normale", invece del pieno — il colore lo passa il JS via --pf-half-bg.
   La scritta si sposta nella metà colorata (non resta centrata a cavallo delle due
   metà) e si rimpicciolisce leggermente per stare più comoda nello spazio dimezzato. */
/* Le mezze giornate di ASSENZA le disegna la barra: qui resta solo il caso
   della trasferta di copertura, che non ha una barra propria. */
.pf-cell-half-top    { background: linear-gradient(to bottom, var(--pf-half-bg) 50%, transparent 50%); align-items: flex-start; padding-top: 3px; }
.pf-cell-half-bottom { background: linear-gradient(to bottom, transparent 50%, var(--pf-half-bg) 50%); align-items: flex-end; padding-bottom: 3px; }
.pf-cell-sotto-barra.pf-cell-half-top,
.pf-cell-sotto-barra.pf-cell-half-bottom { background: none; padding: 0; align-items: center; }
/* Evidenzia la cella "un attimo" quando si arriva dal dettaglio richiesta (pfJumpToDate)
   — un contorno pulsante che si nota anche sopra sfondi colorati, poi il JS rimuove la
   classe da solo dopo l'animazione. */
@keyframes pf-cell-jump-pulse {
  0%, 100% { box-shadow: inset 0 0 0 2px var(--accent); }
  50%      { box-shadow: inset 0 0 0 2px var(--accent), 0 0 0 4px color-mix(in srgb, var(--accent) 35%, transparent); }
}
.pf-cell-jump-highlight { animation: pf-cell-jump-pulse .55s ease-in-out 3; z-index: 2; }
/* Colonna di oggi: velo leggero e continuo su tutta la colonna (stile Google
   Calendar) invece del contorno cella per cella — le celle già colorate (ferie,
   chiusure, trasferte, mezze giornate) mantengono il loro colore, il weekend il
   suo grigio; l'intestazione porta il peso visivo con sfondo accent e numero bold. */
/* Oggi. Il numero sta dentro un cerchio pieno d'accento: e' un segno che si
   riconosce subito e non ha bisogno di spiegazioni.
   Prima c'era una riga verde spessa sotto l'intestazione della colonna, e
   capitando il primo del mese proprio sul bordo sinistro della griglia sembrava
   una bordatura della tavola messa li' per sbaglio invece che il segno di oggi.
   La colonna resta appena tinta, che basta a seguirla in verticale. */
.pf-header-cell.pf-col-today { background: color-mix(in srgb, var(--accent) 10%, var(--card)); }
.pf-header-cell.pf-col-today .pf-dow { color: var(--accent); font-weight: 600; }
.pf-header-cell.pf-col-today .pf-dnum {
  color: var(--su-accento); background: var(--accent);
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 600; margin-top: 1px;
}
.pf-cell.pf-col-today:not(.pf-cell-leave):not(.pf-cell-closure):not(.pf-cell-cover):not(.pf-cell-half-top):not(.pf-cell-half-bottom):not(.pf-cell-off) {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
/* Stesso pulse, generico: usato per "atterrare" su una riga aperta dalla ricerca globale */
.search-jump-highlight { animation: pf-cell-jump-pulse .55s ease-in-out 3; border-radius: 12px; }
.pf-cell-half-top .pf-badge, .pf-cell-half-bottom .pf-badge { font-size: 9px; }
.pf-badge { font-size: 11px; font-weight: 700; color: var(--su-colore); text-shadow: 0 1px 2px rgba(0,0,0,.25); } /* Bianco fisso spariva sopra i colori pastello del tema scuro: su-colore e gia il token per testo su fondo colorato, usato ovunque nel progetto. */
.pf-note-dot {
  position: absolute; top: 3px; right: 3px;
  width: 6px; height: 6px; border-radius: 50%;
  /* Colore letterale ed ombra sul pallino non ammessi (paragrafi 0.4 e 5: niente ombra sui pallini). */
  background: var(--orange);
}
/* Il pallino da solo si perde in una griglia densa di quadratini colorati — il
   contorno arancione (sempre presente, non solo su hover) si vede anche a distanza
   e non aggiunge altro elemento visivo oltre a quello già lì. */
/* La nota era un anello arancione attorno all'INTERA cella: un quadratone che
   pesava quanto un giorno di assenza, per un promemoria. Adesso e' un pallino
   pieno, come nel resto dell'app — piccolo, sopra a tutto, e agganciato al bordo
   alto della barra quando cade dentro un periodo, cosi' non copre la scritta. */
/* Spegneva l'anello arancione che una volta circondava l'intera cella con una
   nota. Quell'anello non esiste piu' da quando la nota e' un pallino, e la cella
   non prende il fuoco da tastiera: la regola non spegneva piu' niente. */
/* ── GLI STRATI DELLA TAVOLA, dal basso in alto ──────────────────────────────
   1 le barre  ·  2 i pallini delle note  ·  3 la colonna dei nomi (e la riga
   selezionata)  ·  4 la riga delle date  ·  5 gli angoli fermi in alto a
   sinistra  ·  6 il piede.
   Il pallino della nota stava a 3, cioe' SOPRA la colonna dei nomi appiccicata:
   scorrendo di lato le note passavano davanti agli avatar invece che sotto —
   evidentissimo su telefono, dove la colonna e' larga quanto un avatar. Deve
   stare in mezzo: sopra la barra, che altrimenti la coprirebbe, e sotto i nomi,
   che sono uno strato fermo. */
.pf-note-dot {
  position: absolute; z-index: 2;
  /* Centrata nella cella quando il giorno e' libero: e' l'unica cosa che c'e',
     quindi sta al centro come qualunque altro contenuto di cella. */
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--orange); color: var(--su-colore);
  display: grid; place-items: center;
  font-size: 10px; font-weight: 700; line-height: 1;
  box-shadow: 0 0 0 2px var(--card);
}
/* Se il giorno e' gia' coperto da un'assenza, la nota sale sul bordo alto della
   barra — a cavallo, come una puntina — e si rimpicciolisce: al centro coprirebbe
   la scritta della barra. */
.pf-cell-sotto-barra .pf-note-dot {
  top: 11px; width: 15px; height: 15px; font-size: 8.5px;
  transform: translate(-50%, -50%);
}
.pf-note-dot::before { content: 'N'; } /* Stesso anello di prima ma senza box-shadow letterale (paragrafo 10.5) e con il token arancio. */

/* Il piede della tavola. Il fondo e' quello della SCHEDA e non della pagina:
   dichiarato var(--bg) faceva una fascia grigia in fondo a un riquadro bianco.
   Le pastiglie dentro restano grigie, ed e' quel contrasto a farle leggere come
   pastiglie.
   Lo z-index resta in cima alla scala (6) per il motivo di prima: deve stare
   SOPRA la colonna dei nomi appiccicata quando lo scorrimento verticale arriva in
   fondo, o le ultime righe le passano sopra e il testo si mescola agli avatar. */
.pf-legend {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  /* Un filo piu' alta di prima: sopra c'e' ora la fascia da 16px della barra di
     scorrimento, e con 11px il piede sembrava schiacciato in confronto. */
  padding: 13px 16px; border-top: 1px solid var(--bordo-scheda);
  background: var(--card); position: sticky; bottom: 0; left: 0;
  z-index: 6;
}
/* .pf-legend-item, -dot e -pending non li genera piu' nessuno: la legenda ora
   e' contestuale e usa .pf-legend-voce. Tolti invece di lasciarli a occupare
   spazio nel foglio in attesa di confondere qualcuno fra un anno. */

/* Una riga di "Controlli ripetuti" non e' piu' un nome con un numero a destra:
   e' un caso da leggere — chi, su cosa, da quando, e chi l'ha visto. Impilata,
   perche' il riquadro della dashboard e' stretto e affiancare cinque
   informazioni le taglierebbe tutte. */
.dash-controllo { flex-direction: column; align-items: stretch; gap: 4px; }
.dash-controllo-testa { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dash-controllo-chi { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.dash-controllo-presidio {
  display: flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); color: var(--text3);
}
.dash-controllo-presidio .material-icons-outlined { font-size: 14px; }
/* Le date dei controlli: una lista vera, non righe finte separate da punti —
   sono l'elenco delle volte che quella persona e' tornata, e si contano con
   l'occhio. */
.dash-controllo-date { list-style: none; margin: 4px 0 0; padding: 0 0 0 4px; }
.dash-controllo-date li {
  display: flex; align-items: baseline; gap: 8px;
  font-size: var(--fs-xs); color: var(--text2);
  padding: 2px 0;
}
.dash-controllo-date li span {
  min-width: 44px; font-variant-numeric: tabular-nums;
  color: var(--text); font-weight: 600;
}

/* Un caso con dieci ritorni riempirebbe il riquadro da solo: si mostrano gli
   ultimi sei, e quanti ce n'erano prima si DICE — un elenco tagliato in
   silenzio si legge come "sono tutti qui". */
.dash-controllo-altri { color: var(--text3); font-style: italic; padding-left: 4px; }

/* ════════════════════════════════════════════════════════════════════════════
   AUTOMAZIONI EMAIL POST-CONSEGNA
   ════════════════════════════════════════════════════════════════════════════
   Tre schermate, un prefisso: .autom-.
   L'elenco (Impostazioni > Agenda) non ha classi proprie: riusa .apt-admin-card
   e .apt-admin-row della scheda Servizi, che sta due schede piu' in la'. Qui
   sotto c'e' solo cio' che nel foglio non esisteva. */

/* ── LA COLONNA DEI PASSI ────────────────────────────────────────────────────
   Una sola colonna, dall'alto in basso, perche' e' l'ordine in cui le cose
   accadono: il tempo scende e non si dirama. Brevo e ActiveCampaign disegnano
   rami perche' hanno le condizioni; qui non ci sono, e un impianto a rami per
   quattro passi sarebbe piu' disegno che informazione.
   520 e non --larghezza-lettura: quella e' la misura di un elenco che si legge
   riga per riga, questa e' una fila di quattro schede che si guardano insieme —
   piu' larga, l'occhio dovrebbe percorrere la scrivania per ogni passo. */
.autom-tela {
  max-width: 720px; margin: 0 auto;
  padding: 48px 24px;
  background: var(--gray6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='2' cy='2' r='1' fill='%23000' fill-opacity='0.07'/%3E%3C/svg%3E");
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
}
/* I pallini della tela sono neri al 7%: sul grigio chiaro si vedono appena, che
   e' quello che deve fare una texture. Sul tema scuro la tela e' quasi nera e
   sparirebbero del tutto, quindi li' diventano bianchi.
   Due blocchi e non uno: il tema scuro di questo progetto ha tre stati — scelta
   esplicita "scuro", scelta esplicita "chiaro", e nessuna scelta (che segue il
   sistema). Dichiararlo solo in uno dei due lascerebbe meta' degli utenti con i
   pallini invisibili. */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="chiaro"]) .autom-tela {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='2' cy='2' r='1' fill='%23fff' fill-opacity='0.10'/%3E%3C/svg%3E");
  }
}
:root[data-tema="scuro"] .autom-tela {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='2' cy='2' r='1' fill='%23fff' fill-opacity='0.10'/%3E%3C/svg%3E");
}

.autom-flusso {
  max-width: 520px; margin: 0 auto;
  display: flex; flex-direction: column;
}

/* Il passo: la scheda delle Prenotazioni (bordo + --r-md + --shadow-1), non un
   blocco pieno. NON si solleva al passaggio del mouse: in una colonna fitta un
   pixel di alzata fa comparire sotto un'ombra larga e squadrata, ed e' solo
   sporco — e' la lezione della voce 20 del registro Agenda, dove lo stesso
   gesto e' stato tolto agli appuntamenti. */
.autom-passo {
  display: flex; align-items: center; gap: 12px;
  min-height: 64px; padding: 12px 16px;
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: background var(--t-stato);
}
.autom-passo:hover { background: color-mix(in srgb, var(--text) 4%, var(--card)); }

/* Il quadratino della tinta: stessa ricetta di .apt-pren-icona e di
   .pastiglia-stato. Il velo si mescola su --card e non su transparent, cosi' il
   colore e' calcolato invece che composto: viene lo stesso qui e in qualunque
   altro posto lo si metta, e il contrasto misurato una volta vale sempre.
   Il ripiego su --accent non e' formalita': senza --tinta-stato il color-mix non
   risolve, e si ottiene un quadratino trasparente con dentro un'icona
   invisibile, senza nessun errore da nessuna parte. */
.autom-passo-icona {
  width: 40px; height: 40px; flex-shrink: 0;
  border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--tinta-stato, var(--accent)) 16%, var(--card));
  color: color-mix(in srgb, var(--tinta-stato, var(--accent)) 78%, var(--text));
}

.autom-passo-corpo { flex: 1; min-width: 0; }
.autom-passo-titolo {
  font-size: var(--fs-base); font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.autom-passo-meta {
  font-size: var(--fs-xs); color: var(--text3); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* I comandi di riga restano grigi finche' non li si tocca. Con il cestino rosso
   fisso, la cosa piu' colorata della schermata era il modo di distruggerla —
   e la regola di questo progetto e' che l'eliminazione non urla mai. */
.autom-passo-azioni { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* Due classi contro due classi: .btn-icon.danger sta piu' in basso nel foglio
   e vinceva a parita' di specificita' (il cestino restava rosso). Si nomina
   anche .danger qui, cosi' fanno tre classi e l'ordine non conta piu'. */
.autom-passo-azioni .btn-icon,
.autom-passo-azioni .btn-icon.danger { color: var(--text3); }
.autom-passo-azioni .btn-icon:hover { color: var(--text); }
.autom-passo-azioni .btn-icon.danger:hover { color: var(--danger); }
.autom-passo-azioni .btn-icon:disabled { opacity: .3; cursor: default; }

/* L'ATTESA e' lo stesso passo, ma basso e di una riga sola. La differenza si
   legge dalla SAGOMA prima che dall'icona — 48 contro 64 — e scorrendo la
   colonna le attese sono le barre corte, senza bisogno di leggere niente.
   Tre segnali indipendenti e nessuno e' il grassetto (la gerarchia fatta di
   peso e' proprio cio' che DESIGN.md par.2 vieta): sagoma, tinta (--tinta-stato vale
   --stato-attesa qui e --accent sull'email, passata in linea dal disegno) e
   icona (orologio contro busta).
   Il quadratino scende a 28, e a 28 il raggio per il par.4 e' --r-xs, non
   --r-sm: e' il criterio scritto (raggio ~25% dell'altezza), non un'occhiata. */
.autom-passo.autom-attesa { min-height: 48px; padding: 8px 16px; }
.autom-attesa .autom-passo-icona { width: 28px; height: 28px; border-radius: var(--r-xs); }
.autom-attesa .autom-passo-titolo { font-size: var(--fs-sm); font-weight: 500; }

/* L'innesco: non e' un passo, e' la condizione da cui parte tutto. Non si
   modifica e non si elimina, quindi non deve nemmeno sembrare cliccabile:
   niente ombra, niente puntatore, fondo pieno del grigio di pagina.
   Il nome della classe non contiene "card"/"scheda"/"panel" apposta: con quei
   nomi, un fondo --gray6 fa scattare la voce 6 di verifica-design.js. */
.autom-innesco {
  display: flex; align-items: center; gap: 12px;
  min-height: 48px; padding: 8px 16px;
  background: var(--card);
  border: 1px dashed var(--gray4);
  border-radius: var(--r-md);
  font-size: var(--fs-sm); color: var(--text2);
}

/* ── IL CONNETTORE ───────────────────────────────────────────────────────────
   32px di filo fra un passo e l'altro, con la punta in fondo. La punta non e'
   decorazione: senza, la colonna si legge come un elenco puntato invece che
   come una sequenza, e il verso lo deve dire qualcosa.
   --gray4 e non --bordo-scheda: il bordo delle schede e' apposta quasi
   invisibile (e' decorativo), mentre questo filo e' l'unica cosa che tiene
   insieme i passi. Misurato in tutt'e due i temi: #D1D1D6 sul chiaro, #454d56
   sullo scuro, si vede in entrambi.
   La punta e' fatta coi bordi: i bordi non entrano nel conto delle spaziature
   dispari (verifica-design.js righe 62-66 guarda solo padding/margin/gap). */
.autom-freccia { position: relative; height: 48px; flex-shrink: 0; }
.autom-freccia::before {
  content: ''; position: absolute; left: 50%; top: 0; bottom: 0;
  width: 2px; transform: translateX(-50%);
  background: var(--gray4);
}
.autom-freccia::after {
  content: ''; position: absolute; left: 50%; bottom: 0;
  transform: translateX(-50%);
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--gray4);
}

/* Il "+": SEMPRE VISIBILE, non al passaggio del mouse.
   In Agenda il "+" degli slot liberi si nasconde, e li' e' giusto: sono
   centoventi caselle e passandoci sopra ne partivano decine di animazioni al
   secondo (registro Agenda, voci 6 e 19). Qui i connettori sono tre o quattro,
   e un comando che si scopre solo passandoci sopra e' un comando che meta'
   delle persone non trova. Della lezione resta la parte che vale: nessuna
   transizione di DIMENSIONE, il "+" non cresce.
   Tratteggiato e non pieno: e' la stessa grammatica della zona di trascinamento
   dei preventivi (.ortho-quote-drop) — tratteggiato vuol dire "qui ci puo'
   andare qualcosa".
   Il fondo --bg serve a tagliare il filo che gli passa dietro: vale finche' il
   costruttore sta sul fondo della pagina. Se un giorno finisse dentro una
   scheda, qui va --card. */
.autom-piu {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--gray4); border-radius: var(--r-full);
  background: var(--bg); color: var(--text3);
  cursor: pointer; font-family: inherit;
  transition: border-color var(--t-stato), color var(--t-stato), background var(--t-stato);
}
.autom-piu:hover {
  border-style: solid; border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--bg));
}
.autom-piu .material-icons-outlined { font-size: 16px; }
/* Il segno e' 24, il bersaglio di tocco resta 40x40: area estesa con lo
   pseudo-elemento e MAI con un margine (par.9), che sposterebbe il filo. */
.autom-piu::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 40px; height: 40px; transform: translate(-50%, -50%);
}

/* La pagina del costruttore. Lo spazio in fondo non e' generosita': sotto c'e'
   la barra di salvataggio appiccicata, e senza quello spazio l'ultimo passo le
   finirebbe sotto. */
/* flex:1 + overflow-y:auto NON sono decorazione: .main-content e'
   overflow:hidden e ogni sotto-pagina si porta il proprio scorrimento (come fa
   .apt-admin-page). Senza, il contenuto piu' alto dello schermo restava
   semplicemente irraggiungibile — e con una foto dentro una mail si supera
   l'altezza dello schermo subito. */
.autom-pagina { flex: 1; overflow-y: auto; padding: 28px var(--gutter) 104px; }

/* Una foto da tremila pixel dentro un mattoncino riempie da sola tre schermate
   e il resto del messaggio sparisce sotto. Nell'editor si guarda alta al
   massimo 320: le proporzioni vere si vedono nell'anteprima accanto, che e'
   larga quanto la mail vera. */
.autom-mat img { max-height: 320px; width: auto; }
/* Le distanze fra i tre blocchi della pagina: testata, spiegazione, tela.
   Erano tutte incollate, e tre cose incollate si leggono come una cosa sola. */
.autom-pagina > .autom-testata { margin-bottom: 20px; }
.autom-pagina > .apt-tpl-hint  { margin: 0 auto 24px; }

/* La testata della sequenza: nome, innesco e interruttore in una scheda sola,
   sopra il flusso. Prima nome e "accendi" stavano IN FONDO, sotto la sequenza:
   sembravano l'ultimo passo invece dell'intestazione, e l'occhio arrivava alla
   cosa piu' importante per ultima. Adesso stanno sopra, ma piccoli: sono la
   targa della sequenza, non la sequenza. */
.autom-testata {
  /* Stessa larghezza della tela: due blocchi incolonnati che non condividono i
     bordi si leggono come due cose sfalsate, non come una pagina. */
  max-width: 720px; margin: 0 auto 8px;
  display: flex; align-items: center; gap: 16px;
  padding: 16px 20px;
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.autom-testata-corpo { flex: 1; min-width: 0; }
/* Il nome si modifica dove si legge: niente etichetta, niente riquadro, il
   bordo compare solo quando ci si scrive dentro. Un campo di testo con la sua
   etichetta pesava quanto il titolo della pagina, e non lo vale. */
.autom-testata-nome {
  width: 100%; padding: 2px 6px; margin-left: -6px;
  font-family: inherit; font-size: var(--fs-lg); font-weight: 600; color: var(--text);
  background: none; border: 1px solid transparent; border-radius: var(--r-xs);
}
.autom-testata-nome:hover { border-color: var(--bordo-scheda); }
.autom-testata-nome:focus { outline: none; border-color: var(--accent); background: var(--card); }
.autom-testata-sotto {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 4px; font-size: var(--fs-xs); color: var(--text3);
}

/* La barra di salvataggio: appiccicata in fondo, e compare SOLO quando c'e'
   qualcosa da salvare. Prima il pulsante stava nell'intestazione dell'app, in
   mezzo alla lente e alla campanella — fra i comandi di sistema, dove nessuno
   cerca il salvataggio di quello che sta scrivendo. */
.autom-salva-barra {
  position: sticky; bottom: 0; z-index: 5;
  max-width: 720px; margin: 24px auto 0;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px;
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
}
.autom-salva-barra span { font-size: var(--fs-sm); color: var(--text2); }

/* La fine della sequenza. Serve: senza, l'ultimo "+" sembra sospeso nel vuoto e
   non si capisce se manchi qualcosa o se sia finita. */
.autom-freccia.aperta { height: 120px; }
.autom-scelta {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 8px;
  padding: 8px; white-space: nowrap;
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-full);
  box-shadow: var(--shadow-1);
}

.autom-vuoto {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 24px 16px;
  border: 2px dashed var(--gray4); border-radius: var(--r-md);
  color: var(--text3); font-size: var(--fs-sm);
}
.autom-vuoto-scelte { display: flex; gap: 8px; }

.autom-fine {
  display: flex; align-items: center; justify-content: center;
  height: 40px; margin-top: 8px;
  font-size: var(--fs-xs); color: var(--text3);
}

/* ── IL COSTRUTTORE SU TELEFONO ──────────────────────────────────────────────
   Tre bersagli da 44 in una riga alta 48 non ci stanno senza mangiare il
   titolo: i due bottoni di riga diventano uno solo che apre l'elenco delle
   azioni, come fa l'Agenda (.apt-azioni-elenco). */
@media (max-width: 600px) {
  .autom-flusso { max-width: none; }
  .autom-passo, .autom-innesco { gap: 8px; padding: 12px; }
  .autom-solo-desktop { display: none; }
}
@media (min-width: 601px) {
  .autom-solo-telefono { display: none; }
}

/* ── LA BARRA DELL'EDITOR MAIL ───────────────────────────────────────────────
   Il contenitore porta DUE classi: "sig-toolbar autom-barra". Cosi' eredita le
   misure dei bottoni gia' esistenti (34px, bordo --bordo-campo) invece di
   riscriverle, e qui si aggiunge solo cio' che alle firme non serviva: andare a
   capo, i gruppi, e uno stato acceso.
   Nell'editor delle firme quello stato non c'e' proprio: si scrive in grassetto
   e il bottone non lo dice. Con dieci comandi invece di tre diventa necessario. */
.autom-barra { flex-wrap: wrap; row-gap: 4px; }

/* Il separatore fra gruppi e' un filo, non uno spazio piu' largo: lo spazio
   funziona finche' i gruppi stanno sulla stessa riga, e appena la barra va a
   capo sparisce. */
.autom-barra-sep {
  width: 1px; height: 24px; margin: 0 4px;
  background: var(--bordo-scheda); flex-shrink: 0;
}

/* Il comando acceso: stessa ricetta di .filter-chip.active — velo al 18% su
   --card, bordo accento, testo mescolato al 70% verso --text.
   Il 18 e non il 14 delle pastiglie ha una ragione misurata (app.css 994-998):
   una pastiglia sta su una riga da leggere, questo e' un comando da colpire, e
   il segnale deve arrivare prima della lettura. Il testo non e' l'accento puro
   perche' sopra il suo stesso velo scende a 4,42 in tema chiaro. */
.autom-barra button.attivo {
  background: color-mix(in srgb, var(--accent) 18%, var(--card));
  border-color: var(--accent);
  color: color-mix(in srgb, var(--accent) 70%, var(--text));
}

/* Le tendine della barra (corpo del testo, colore) hanno l'altezza dei BOTTONI,
   non quella dei campi di modulo: stanno in una barra di strumenti, non in un
   modulo, e a 48px di altezza spezzerebbero la riga. */
/* I colori: quadratini, non una tendina. Sei tinte si vedono tutte insieme e si
   colpiscono in un colpo; dentro una tendina servirebbero due gesti per una cosa
   che si sceglie a occhio. Il selettore libero resta accanto per gli altri casi. */
/* La riga sopra l elenco: a sinistra cosa e, a destra come se ne aggiunge una.
   Il bottone sta qui e non in fondo alla pagina perche il gesto appartiene
   all elenco, non a un modulo staccato che gli sta sotto. */
.autom-elenco-testa {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 0 0 8px;
}

/* .autom-barra davanti non e' una formalita': ".sig-toolbar button" e' due
   selettori (0,1,1) e batteva ".autom-colore" (0,1,0) su fondo e larghezza —
   i quadratini uscivano bianchi e larghi 34, cioe' sei riquadri vuoti al posto
   dei colori. Con due classi davanti la partita si vince a prescindere
   dall'ordine nel foglio. */
.autom-barra .autom-colore {
  width: 24px; height: 24px; min-width: 24px; padding: 0;
  border: 1px solid var(--bordo-campo); border-radius: var(--r-xs);
  background: var(--c); cursor: pointer;
}
.autom-barra .autom-colore:hover { border-color: var(--accent); transform: scale(1.1); }
.autom-barra input[type=color] {
  width: 34px; height: 34px; padding: 2px;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-xs);
  background: var(--card); cursor: pointer;
}

.autom-barra select {
  height: 34px; padding: 0 8px;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm);
  background: var(--card); color: var(--text2);
  font-family: inherit; font-size: var(--fs-sm); cursor: pointer;
}

/* ── I MATTONCINI ────────────────────────────────────────────────────────────
   Un mattoncino non e' una scheda: e' un pezzo di documento. Quindi a riposo
   non ha ne' bordo ne' fondo — si vede solo il contenuto, che e' esattamente
   cio' che finira' nella mail. Se ogni blocco avesse il suo riquadro, l'editor
   smetterebbe di somigliare al risultato, e un editor che non somiglia al
   risultato e' un'anteprima in meno.
   Il velo del mattoncino scelto e' al 6 e non al 18 del chip: qui sotto c'e'
   del testo da leggere, non un comando da colpire. */
.autom-mattoni {
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md);
  padding: 16px;
  display: flex; flex-direction: column; gap: 4px;
}
.autom-mat {
  position: relative;
  padding: 8px 12px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color var(--t-stato), background var(--t-stato);
}
.autom-mat:hover { border-color: var(--bordo-scheda); }
.autom-mat.scelto {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--card));
}

/* I comandi del mattoncino: su, giu', duplica, elimina. Compaiono solo su
   quello sotto il mouse o scelto — sei mattoncini con la barretta sempre accesa
   vorrebbero dire ventiquattro bottoni su una schermata.
   visibility e non display: cosi' comparendo non sposta di un pixel il testo
   che sta sotto.
   La barretta e' uno strato L2 (par.5): bordo piu' --shadow-1, che e' il
   trattamento di tendine e popover — sta sopra al contenuto, e lo dice. */
.autom-mat-comandi {
  position: absolute; top: 4px; right: 4px;
  display: flex; gap: 2px; padding: 2px;
  background: var(--card);
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-xs);
  box-shadow: var(--shadow-1);
  visibility: hidden;
}
.autom-mat:hover > .autom-mat-comandi,
.autom-mat.scelto > .autom-mat-comandi { visibility: visible; }
.autom-mat-comandi button {
  width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--r-xs);
  background: none; color: var(--text3); cursor: pointer;
}
.autom-mat-comandi button:hover {
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text);
}
.autom-mat-comandi .material-icons-outlined { font-size: 16px; }
/* Sul tocco il passaggio del mouse non esiste: nasconderla vorrebbe dire
   renderla irraggiungibile. Resta sul mattoncino scelto, che li' e' il modo di
   dire "sto lavorando su questo". */
@media (hover: none) {
  .autom-mat.scelto > .autom-mat-comandi { visibility: visible; }
  .autom-mat-comandi button { width: 32px; height: 32px; }
}

/* La riga di chi aggiunge: pastiglie (.filter-chip), non una tendina. Sono sei
   voci con un'icona ciascuna, e vederle tutte insieme costa una riga sola. */
/* La barra di formattazione compare solo nel blocco scelto. Fuori di li' non
   serve, e sei barre accese insieme sarebbero sessanta bottoni su una
   schermata. */
.autom-mat .autom-barra { display: none; }
/* Il filo sotto i comandi separa gli attrezzi dal foglio. Senza, i bottoni
   sembravano la prima riga del messaggio: appoggiati sul testo, senza niente a
   dire dove finiva la barra e dove cominciava quello che si scrive. */
.autom-mat.scelto .autom-barra {
  display: flex; gap: 6px;
  margin: 0 0 12px; padding: 0 0 12px;
  border-bottom: 1px solid var(--bordo-scheda);
}
/* Il testo respira dentro il suo blocco invece di partire incollato al filo. */
.autom-mat .sig-editor { border: none; background: none; padding: 4px 2px; }

/* Il doppio contorno: il blocco scelto ha gia' il suo bordo d'accento, e
   l'editor dentro ci aggiungeva il proprio anello di messa a fuoco. Due
   contorni concentrici attorno alla stessa cosa non dicono niente in piu' e
   rendono meno leggibile quello che c'e' dentro. */
.autom-mat .sig-editor:focus { box-shadow: none; border-color: transparent; }

.autom-mat-nuovi { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

/* ── L'ANTEPRIMA ─────────────────────────────────────────────────────────────
   Non e' un riquadro dell'app: e' il FOGLIO della mail. Il grigio intorno e'
   quello del client di posta, e la colonna bianca e' larga 560 — la stessa
   misura di mailTemplate() in app/api/mail.php (riga 95). Se fosse larga
   diversamente, l'anteprima mentirebbe.
   Bianco e #3a3a3c fissi, e apposta: NON seguono il tema dell'app, per lo
   stesso motivo dei post-it (--sticky-yellow e compagni) — chi guarda vuole
   vedere cosa vede il cliente, non cosa vede lui.
   Interlinea 1.6 e non 1.5: e' il valore della mail, non quello dell'editor.
   Fra .sig-editor (1.5) e la mail vera (1.35 in ortho.php) c'e' gia' oggi una
   divergenza; qui almeno l'anteprima sta dalla parte della mail. */
.autom-anteprima {
  background: var(--gray6);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md);
  padding: 24px 16px;
  overflow-x: auto;
}
.autom-anteprima-foglio {
  width: 560px; max-width: 100%; margin: 0 auto;
  background: #ffffff; color: #3a3a3c;
  border-radius: var(--r-md);
  font-size: 15px; line-height: 1.6; text-align: left;
}

/* Editor e anteprima affiancati. Sotto i 900 non ci stanno: l'anteprima
   diventa la seconda voce di una .seg-tab-bar (Contenuto / Anteprima), che e'
   il selettore a schede gia' in uso in dodici punti. */
.autom-mail-due {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start;
}
@media (max-width: 900px) {
  .autom-mail-due { grid-template-columns: 1fr; }
}

/* Su telefono il conteggio dei passi esce dalla riga dell'elenco: il nome
   dell'automazione e' cio' che serve, i passi si vedono aprendola. */
@media (max-width: 600px) {
  .autom-riga .apt-admin-row-meta { display: none; }
}

/* Timbratura */
.tbr-stamp {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  background: var(--bg);
  border: 1.5px solid var(--c, var(--border));
  border-radius: var(--r-md);
  font-size: 14px;
}

/* Print */
@media print {
  .sidebar, .mobile-menu-btn, #pf-header button, .pf-legend { display: none !important; }
  .main-content { overflow: visible !important; }
  #pf-wrap { overflow: visible !important; }
  .pf-name-cell { position: static !important; }
  .pf-header-cell { position: static !important; }
  body { background: white !important; }
}

@media (max-width: 480px) {
  /* Ancora un gradino sotto (20 -> 16): --fs-md, non un 18 inventato qui. */
  .main-header h2 { font-size: var(--fs-md); }
  .task-title { font-size: 14px; }
  .detail-checkboxes { flex-direction: column; }
  /* Con solo l'avatar visibile (nome/drag-handle nascosti sotto), il confine di 2px
     tra colonna sticky e griglia che le scorre sotto non bastava a leggerla come uno
     strato separato — l'avatar sembrava "galleggiare" sopra la tabella. Un'ombra
     leggera sul bordo destro la fa leggere subito come una colonna fissa distinta.
     ATTENZIONE larghezze: .avatar-sm è 36px fissi (app.css ~1814) — con 8px di
     padding per lato qui restavano solo 28px di spazio utile, 8px meno del
     necessario: l'avatar sborda SEMPRE nella colonna del giorno 1, indipendentemente
     dall'ombra (che aiuta a leggerla come strato separato ma non impedisce la
     sovrapposizione). Padding ridotto per lasciare davvero posto ai 36px dell'avatar. */
  /* Si stringe il TOKEN, non la sola cella: la stessa misura la usano anche lo
     strato delle barre (che parte da li') e l'angolo delle bande. Cambiando solo
     la cella, barre e bande restavano larghe 236px e finivano spostate di quasi
     duecento pixel rispetto ai giorni. */
  :root { --pf-col-nome: 44px; }
  .pf-name-cell { padding: 6px 4px; gap: 0; box-shadow: 2px 0 4px rgba(0,0,0,.08); }
  /* In 44 pixel "PERSONA" non ci sta, e l'avatar dice gia' cosa c'e' in colonna. */
  .pf-intestazione-nomi { display: none; }
  /* CAUSA VERA dell'avatar che copriva il giorno 1 (verificata sperimentalmente):
     il drag-handle ha anche la classe .material-icons-outlined, e il foglio di
     Google Material Icons (caricato DOPO app.css in index.php) dichiara
     display:inline-block a pari specificità — in cascata "riaccendeva" l'icona
     nonostante il display:none qui sotto. La manina visibile spingeva l'avatar
     24px a destra, facendolo sbordare sopra la cella del giorno 1 (la colonna è
     sticky con z-index 2, quindi la parte sbordante si dipinge SOPRA la griglia).
     Il selettore con due classi (0,2,0) batte quello del font (0,1,0) a
     prescindere dall'ordine di caricamento dei fogli. */
  /* Il conteggio dei giorni ("5g") sparisce con loro. In 44 pixel ci sta un
     avatar da 28 e basta: il contrassegno finiva 15 pixel OLTRE il bordo della
     colonna (misurato), e siccome la colonna e' appiccicata sopra la griglia,
     la parte che sborda si dipinge sopra il giorno 1.
     Il numero non si perde: toccando l'avatar compare col nome. Allargare la
     colonna per farcelo stare sarebbe stato peggio — su 375 pixel di schermo
     ogni pixel dato ai nomi e' un pixel tolto ai giorni, che sono la ragione
     per cui si guarda un planner. */
  .pf-name-cell .pf-name, .pf-name-cell .pf-drag-handle, .pf-name-cell .pf-giorni { display: none; }
  .pf-avatar-tap { cursor: pointer; }

  /* La colonna avatar è sticky: scorrendo in orizzontale le celle-giorno le passano
     SOTTO, e se lo scroll si ferma a metà cella il primo giorno visibile resta mezzo
     nascosto dietro gli avatar ("l'avatar copre il giorno 1"). Lo snap riallinea
     sempre lo scroll a inizio colonna-giorno, subito dopo il bordo degli avatar
     (scroll-padding = 44px cella + 2px bordo), così nessun giorno resta mai a metà. */
  #pf-wrap { scroll-snap-type: x proximity; scroll-padding-left: 46px; }
  .pf-day-cell { scroll-snap-align: start; }

  /* La legenda non sta piu' incollata in fondo: e' alta 182 pixel su 812 —
     misurata — cioe' un quinto abbondante dello schermo tolto per sempre alla
     griglia, su un telefono dove di righe se ne vedono gia' poche. Adesso e'
     in coda al calendario: si scorre tutto e la si trova la' sotto.
     Resta pero' appiccicata a SINISTRA (sticky con left ma senza bottom):
     scorrendo di lato il calendario le passa sotto e la legenda non se ne va
     per i fatti suoi fuori schermo.
     Nascosterla del tutto no: da telefono le assenze sono una lettera sola —
     F, P, M, R, 104, C — ed e' proprio li' che serve qualcosa che le spieghi. */
  .pf-legend { bottom: auto; }
}

/* ── Agenda / Planner ── */
/* ── CHI SCORRE ──────────────────────────────────────────────────────────────
   Questa e' LA modifica strutturale, e senza di lei tutte le altre sono una mano
   di vernice.
   Prima scorreva la PAGINA: la tavola era alta millecinquecento pixel dentro una
   finestra da settecento, quindi della "scheda" si vedevano solo il bordo di
   sopra e i due fianchi — mai il fondo. Un rettangolo bianco che esce dallo
   schermo non e' una scheda, e infatti non si leggeva come tale.
   Adesso scorre la TAVOLA dentro la scheda, come nel Piano Ferie: la scheda ha
   un'altezza sua, sta tutta dentro la finestra, e si vede che comincia e finisce.
   In piu' questo semplifica il pasticcio di prima: la striscia dei nomi non ha
   piu' bisogno di essere appiccicata, perche' sta FUORI dall'area che scorre e
   quindi resta ferma da sola. */
.apt-container {
  display: flex; flex-direction: column;
  height: 100%; min-height: 0;
  /* In verticale scorre QUESTO, cioe' la pagina del modulo — e la scheda qui
     dentro si estende per tutta la sua altezza invece di scorrere al proprio
     interno. Cambia parecchio l'impressione: non si guarda dentro una
     finestrella, si scorre un foglio su cui c'e' la tavola e, sotto, i pannelli
     del giorno. Resta comunque UNA sola barra verticale.
     Di lato non scorre niente: quello lo fa la scheda, con le frecce. */
  overflow-y: auto; overflow-x: hidden;
}

/* ── LA SCHEDA ───────────────────────────────────────────────────────────────
   Contiene la tavola E i pannelli del giorno, e scorre LEI: una barra sola, in
   tutt'e due i versi. E' anche il motivo per cui la testata e la colonna delle
   ore possono restare ferme davvero — si appiccicano al bordo di questo
   riquadro, che e' l'unico che si muove. */
.apt-scheda {
  /* Alta quanto il suo contenuto: niente flex:1, niente min-height. E' questo
     che la fa "estendere" invece di diventare una finestrella su una tavola piu'
     grande. */
  flex: 0 0 auto;
  /* RITAGLIA, non scorre — ed e' la differenza che permette ai nomi dei tecnici
     di restare fermi.
     Un riquadro che scorre "cattura" gli elementi appiccicati che ha dentro: la
     testata della tavola si sarebbe agganciata a LUI, che in verticale non si
     muove, quindi in pratica non si sarebbe agganciata a niente e scorrendo la
     pagina i nomi sarebbero spariti. "clip" ritaglia senza diventare un
     contenitore di scorrimento, cosi' la testata si aggancia alla PAGINA, che e'
     quella che si muove davvero.
     Di lato ci si sposta spostando la tavola (transform), non scorrendo: vedi
     .apt-planner-scroll qui sotto. */
  overflow: clip;
  /* NIENTE scroll-behavior:smooth qui. Scritto sull'elemento rende morbido OGNI
     spostamento, compreso il ripristino della posizione dopo un ridisegno — che
     deve essere istantaneo, o a ogni cambio giorno si vede la tavola scivolare
     da sola. Il movimento morbido lo chiede la freccia, che e' l'unico caso in
     cui e' un gesto voluto. */
  /* La larghezza e' un numero INTERO di colonne: le colonne mezze tagliate dal
     bordo del riquadro erano la ragione per cui il riquadro non si leggeva come
     un contenitore ma come una finestra su qualcosa di piu' grande. Quante ce ne
     stanno lo dice il disegno (aptColonneIntere), perche' dipende dallo spazio
     disponibile che il foglio di stile non conosce. */
  /* --apt-barra-v e' gia' offsetWidth-clientWidth, cioe' bordi PIU' barra:
     aggiungere altri 2px per i bordi li contava due volte, e avanzavano due
     pixel che rendevano la scheda larga quanto tre colonne piu' un filo. */
  width: calc(var(--apt-colonne, 4) * var(--apt-unita, 252px)
              + var(--apt-barra-v, 0px));
  max-width: calc(100% - 2 * var(--gutter));
  /* Lo stacco dai comandi sta QUI, dentro la scorciatoia: scritto sopra come
     margin-top separato veniva cancellato da questa riga, che riscrive tutti e
     quattro i lati (misurato: aria 0px). Attaccata, la scatola della data
     sembrava il coperchio della scheda invece che un comando a se'. */
  margin: 10px auto 16px;
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  scrollbar-width: auto; scrollbar-color: auto;
}
.apt-scheda::-webkit-scrollbar { width: 18px; height: 0; }
.apt-scheda::-webkit-scrollbar-track { background: transparent; }
.apt-scheda::-webkit-scrollbar-thumb {
  background: var(--gray2); border-radius: var(--r-full);
  border: 5px solid transparent; background-clip: content-box;
}
.apt-scheda::-webkit-scrollbar-thumb:hover { background: var(--gray1); background-clip: content-box; }
.apt-scheda::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
.apt-scheda::-webkit-scrollbar-corner { background: transparent; }

/* Navigazione settimana */
/* ── LA BARRA DEI COMANDI ────────────────────────────────────────────────────
   Era una fascia bianca a tutta larghezza chiusa da un filo, cioe' un'altra
   lingua rispetto al Piano Ferie: li' i comandi stanno SUL grigio della pagina,
   come pastiglie bianche con bordo e ombra, e la fascia bianca non esiste.
   Due moduli che si aprono uno dopo l'altro non possono avere due testate
   diverse: qui il fondo diventa quello della pagina, il filo sparisce, e i
   comandi si raccolgono in scatole bianche — le stesse misure di .pf-mese e
   .pf-comandi .filter-chip, prese di li' e non reinventate. */
.apt-week-nav {
  display: flex; flex-direction: column; align-items: center;
  /* Sopra quasi niente — c'e' gia' il titolo della schermata e in mezzo restava
     una fascia vuota che non diceva niente; sotto e ai lati piu' aria, perche'
     era tutto schiacciato. */
  padding: 0 var(--gutter) 18px;
  flex-shrink: 0; background: transparent; gap: 10px;
}
.apt-nav-month-row {
  width: 100%; text-align: center;
}
/* Il mese sta sul grigio, sopra la scatola: e' un'etichetta, non un comando.
   Stesso corpo e stesso peso del sottotitolo del Piano Ferie. */
.apt-month-label {
  font-size: 13px; font-weight: 500; color: var(--text3);
  text-transform: capitalize; letter-spacing: .01em;
}
.apt-nav-days-row-wrap {
  display: flex; align-items: center; justify-content: center;
  width: 100%;
}
/* La scatola bianca che raccoglie "Oggi", le frecce, i giorni e il calendario:
   stesse misure della scatola del mese nel Piano Ferie. */
.apt-nav-center {
  display: flex; align-items: center; gap: 6px; position: relative;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-sm); padding: 5px 8px; box-shadow: var(--shadow-1);
}
.apt-days-row { display: flex; align-items: center; gap: 4px; }
/* La "zona calda" nativa dell'icona calendario di un <input type="date"> è un
   pseudo-elemento posizionato a un offset fisso dentro il controllo — non si allarga
   da solo per riempire tutto lo spazio anche con width:100% sull'input. Su un
   controllo piccolo (dimensionato sulla nostra iconcina decorativa sotto), quella
   zona finiva leggermente disallineata: cliccando sull'icona visibile non succedeva
   nulla, un po' più a destra sì. Facendola combaciare esplicitamente con l'intero
   controllo, tutta l'area è cliccabile. Solo WebKit/Blink (Chrome/Edge/Safari) hanno
   questo pseudo-elemento — Firefox non ne ha bisogno, il suo input è già a tutta area. */
#apt-datepicker-input::-webkit-calendar-picker-indicator {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0;
  cursor: pointer;
}
.apt-nav-text-btn {
  font-size: 13px; font-weight: 500; letter-spacing: .01em;
  background: none; border: none; cursor: pointer;
  color: var(--text2); padding: 4px 8px; border-radius: var(--r-sm);
}
.apt-nav-text-btn:hover { background: var(--gray6); color: var(--text); }
/* Le frecce dentro la scatola: stessa misura e stesso comportamento dei bottoni
   del selettore del mese nel Piano Ferie. */
.apt-nav-center > .btn-icon,
.apt-nav-center span > .btn-icon {
  width: 30px; height: 30px; border-radius: var(--r-xs);
  background: none; border: 0; color: var(--text2);
}
.apt-nav-center > .btn-icon:hover { background: var(--gray6); color: var(--text); }
.apt-day-btn {
  display: flex; flex-direction: column; align-items: center;
  padding: 5px 10px; border: none; background: none; cursor: pointer;
  border-radius: var(--r-sm); transition: background var(--t-stato);
  min-width: 48px; gap: 4px; flex-shrink: 0;
}
.apt-day-btn:hover { background: var(--gray6); }
/* Il giorno scelto era un rettangolo accent pieno alto quanto il pulsante. Nel
   Piano Ferie "oggi" e' il NUMERO dentro un cerchio pieno: due moduli che
   mostrano dei giorni devono segnarli allo stesso modo, o sembrano due
   programmi diversi. Qui il rettangolo lascia il posto al cerchio sul numero, e
   il pulsante tiene solo una velatura che dice quale colonna e' selezionata. */
.apt-day-btn.active { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.apt-day-btn .apt-day-num {
  width: 26px; height: 26px; border-radius: var(--r-full);
  display: grid; place-items: center;
  transition: background var(--t-stato), color var(--t-stato);
}
.apt-day-btn.active .apt-day-num { background: var(--accent); }
.apt-day-btn.today .apt-day-num {
  color: var(--accent); font-weight: 600;
}
/* Il nome del giorno sul pulsante scelto era BIANCO: aveva senso quando il
   pulsante era tutto accent pieno, non piu' da quando il fondo e' una velatura
   al 10% — bianco su quasi bianco. Sul numero il bianco resta, perche' li' sotto
   c'e' davvero il cerchio pieno d'accento.
   Sul nome NON si usa l'accento: accento sopra una velatura di accento non
   arriva a 4,5 per quanto la si aggiusti (misurato 4,21 al 10%, 4,42 al 5%) —
   il colore del testo normale ci sta a quindici, e a dire "questo e' il giorno
   scelto" bastano il cerchio pieno e la velatura. */
.apt-day-btn.active .apt-day-num  { color: var(--su-accento); }
.apt-day-btn.active .apt-day-name { color: var(--text); font-weight: 600; }
.apt-day-btn.active.today .apt-day-num { color: var(--su-accento); }
.apt-day-name { font-size: var(--fs-micro); color: var(--text3); text-transform: uppercase; letter-spacing: .06em; }
.apt-day-num  { font-size: var(--fs-md); font-weight: 500; color: var(--text); }

/* Wrap planner — un solo scroller verticale (.apt-container, il genitore): il planner
   non ha un'altezza fissa propria né uno scroll verticale indipendente, altrimenti la
   rotellina del mouse/lo swipe restano "intrappolati" dentro finché non si arriva in
   fondo, prima di scorrere anche le card sotto (Note/Tag/Assenze). Resta scorrevole
   solo in orizzontale, per sfogliare le colonne dei tecnici. */
/* ── IL PLANNER E' UNA SCHEDA ─────────────────────────────────────────────────
   Prima era una tabella a tutta larghezza appoggiata sul fondo della pagina,
   senza contorni: non si capiva dove cominciasse e dove finisse, ed era il
   difetto che nel Piano Ferie e' stato corretto per primo. Stessa cura: fondo
   proprio, un bordo, gli angoli e un'ombra sola.
   L'overflow resta VISIBILE e non hidden: le strisce appiccicate in alto
   (giorni, frecce, nomi dei tecnici) escono dal riquadro quando si scorre, e
   ritagliandole sparirebbero. Gli angoli si arrotondano quindi sui figli. */
/* Non e' piu' la scheda: quella e' .apt-scheda qui sopra, e questo torna a
   essere il semplice involucro della tavola. Niente altezza, niente scorrimento,
   niente contorni — li' mette tutto la scheda che lo contiene. */
.apt-planner-wrap { position: relative; }
/* La colonna delle ore NON va appiccicata a sinistra. Ogni tecnico ha gia' la
   sua — nel disegno la coppia e' <ora><colonna>, ripetuta per ognuno — quindi
   appiccicandole si sarebbero impilate tutte e cinque sul bordo sinistro una
   sopra l'altra. Ci si sposta di una coppia intera per volta: ogni colonna si
   porta dietro le proprie ore, ed e' giusto cosi'. */
/* Relative perche' la linea dell'ora ci si appoggia dentro: deve scorrere
   insieme alla griglia, non restare ferma sopra la finestra. */
/* La tavola si sposta di lato traslando, non scorrendo: e' quello che permette
   alla scheda di ritagliare invece di scorrere, e quindi ai nomi di restare
   fermi. Lo spostamento e' sempre un multiplo esatto della colonna, deciso dalle
   frecce.
   Relative perche' la linea dell'ora ci si appoggia. */
.apt-planner-scroll {
  width: max-content; min-width: 100%; position: relative; overflow: visible;
  transform: translateX(calc(-1 * var(--apt-scorrimento, 0px)));
  transition: transform .32s cubic-bezier(.2, 0, 0, 1);
}
/* Scroll-snap: lo scroll orizzontale (frecce, trackpad o swipe) si "aggancia" sempre
   al bordo sinistro di una colonna, invece di potersi fermare a metà — la freccetta
   sposta esattamente di una colonna, ma anche uno swipe manuale non lascia mai
   l'ultima colonna visibile tagliata a metà. Nessuna larghezza cambiata: la colonna
   in più che non entra per intero resta semplicemente fuori dalla vista finché non
   si scorre ancora. */
/* Lo scatto CSS e' stato tolto, e per un motivo misurato: la colonna delle ore
   e' "sticky", e un elemento appiccicato non e' un bersaglio di scatto valido —
   il browser lo salta e aggancia la prima colonna VERA, che comincia a 52px.
   Risultato: la tavola non tornava mai a zero, si fermava sempre 52 pixel piu' in
   la' con la prima colonna delle ore mangiata dal bordo, e la freccia sinistra
   restava accesa anche a inizio corsa.
   L'allineamento alle colonne intere lo fa adesso il disegno (aptAllineaColonne),
   arrotondando la posizione al multiplo esatto della colonna: e' preciso, vale
   anche per il trackpad, e non dipende da come un browser tratta gli elementi
   appiccicati dentro il calcolo dello scatto. */
/* La barra di scorrimento c'e' anche da desktop. Prima era nascosta perche' le
   frecce sopra la griglia bastano a spostarsi: e' vero che bastano a MUOVERSI,
   ma non dicono a che punto si e' ne' quanto manca — e con otto tecnici in
   colonna quella e' la domanda vera. Stesso trattamento del Piano Ferie: fascia
   da 18px e pollice da 8px centrato, cosi' i due moduli si scorrono allo stesso
   modo. Le frecce restano dove sono, per chi preferisce il salto di colonna.
   Le due proprieta' standard vanno tenute ad "auto": Chrome ignora le regole
   ::-webkit-scrollbar se sull'elemento c'e' uno scrollbar-color diverso da auto,
   e la regola "*" del foglio ne mette uno su tutto. */
.apt-planner-scroll { scrollbar-width: auto; scrollbar-color: auto; }
.apt-planner-scroll::-webkit-scrollbar { height: 18px; }
.apt-planner-scroll::-webkit-scrollbar-track { background: transparent; }
.apt-planner-scroll::-webkit-scrollbar-thumb {
  background: var(--gray2); border-radius: var(--r-full);
  border: 5px solid transparent; background-clip: content-box;
}
.apt-planner-scroll::-webkit-scrollbar-thumb:hover { background: var(--gray1); background-clip: content-box; }
.apt-planner-scroll::-webkit-scrollbar-button { display: none; width: 0; height: 0; }

@media (min-width: 700px) {

  /* Ho provato più volte a rendere sticky i nomi tecnici con solo CSS (vedi git/commenti
     precedenti) — ogni tentativo toccava .apt-planner-scroll/.apt-container, il vero
     scroller verticale della pagina, e finiva per romperlo in un modo o nell'altro
     (in un caso arrivando a un "doppio scroll" vero e proprio). Soluzione finale:
     .apt-planner-scroll resta scorrevole SOLO in orizzontale, come da progetto
     originale — i nomi tecnici NON sono più dentro la tabella che scorre, ma in una
     striscia a parte qui sotto (.apt-tech-strip), fuori da questo contenitore,
     sincronizzata via JS con lo scroll orizzontale (aptRenderPlanner in assets/app.js).
     Non avendo mai un proprio overflow/scrollbar, la striscia non può creare un
     secondo contenitore di scroll. */
  .apt-planner-scroll { overflow-y: visible; }

  /* Barra dei giorni e frecce: fondo pieno. La sfocatura ce l'avevano quando
     erano appiccicate e la pagina scorreva sotto; adesso che a scorrere e' solo
     la tavola dentro la scheda, sotto di loro non passa piu' niente — e una
     sfocatura che non ha niente da sfocare e' decorazione. Si sposta dove il
     mestiere c'e' davvero: la testata e la colonna delle ore, vedi sotto. */
  /* Niente fondo: le frecce stanno sul grigio della pagina, sopra la scheda.
     Il bianco serviva quando erano dentro il riquadro. */
  /* Barra dei giorni, frecce e nomi dei tecnici NON sono piu' appiccicati:
     stanno fuori dall'unico elemento che scorre (.apt-planner-scroll), quindi
     restano fermi da soli. Era tutta impalcatura che serviva a rimediare al
     fatto che scorresse la pagina — tolta quella causa, va via anche lei.
     Restano gli z-index, perche' le tendine che si aprono da queste barre
     devono passare sopra la tavola. */
  /* I comandi — giorni e frecce — restano in cima mentre il foglio scorre sotto:
     sono l'unico modo di cambiare giorno o colonna, e inseguirli scorrendo
     all'indietro sarebbe una scomodita' gratuita. Qui la sfocatura torna ad
     avere un mestiere, perche' sotto ci passa davvero la tavola. */
  /* L'appiccicatura e la sfocatura stanno nel corpo del foglio, valgono per
     tutte le larghezze: qui resta solo il respiro in alto. */
  .apt-week-nav { padding-top: 8px; }
  /* Niente: le frecce non sono piu' dentro niente che scorra. */

  /* Striscia nomi tecnici: sticky come le due barre sopra (impilata sotto di loro),
     ma "overflow:hidden" invece di un vero scroll — il contenuto interno si sposta
     solo via transform, guidato dallo scroll della griglia sotto, mai scrollabile
     per conto suo. Stesse identiche larghezze di .apt-time-th/.apt-col-th (42px/200px)
     per restare perfettamente allineata alle colonne della griglia sottostante. */
  /* La striscia gemella non viene piu' disegnata: la regola resta solo per non
     lasciare orfane le poche che la citano, ma non c'e' piu' niente da mostrare. */
  .apt-tech-strip { display: none; }
  .apt-tech-strip-inner { display: flex; will-change: transform; }
  .apt-tech-strip-time { width: 42px; min-width: 42px; flex-shrink: 0; }
  .apt-tech-strip-col {
    width: 200px; min-width: 200px; flex-shrink: 0;
    padding: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  }
}

/* Griglia — i nomi tecnici non sono sticky verticalmente (vedi commento su
   .apt-planner-scroll più sopra: creava un doppio scroll con la pagina). Resta
   sticky solo la colonna orario (.apt-time-th, a sinistra) durante lo scroll
   orizzontale della griglia, che non ha questo problema — non convive con nessun
   secondo contenitore di scroll verticale. */
.apt-grid { border-collapse: collapse; table-layout: fixed; width: max-content; min-width: 100%; }
.apt-grid thead th {
  background: var(--card);
  border-bottom: 1px solid var(--bordo-scheda); z-index: 10;
  padding: 8px 4px; white-space: nowrap;
}
.apt-time-th  { width: 42px; min-width: 42px; position: sticky; left: 0; z-index: 11; background: var(--card); }
.apt-col-th   { width: 200px; min-width: 200px; padding: 8px; vertical-align: middle; text-align: center; }
.apt-col-name { font-size: 14px; font-weight: 600; color: var(--text); letter-spacing: .01em; }

/* L'intestazione reale della tabella (.apt-grid thead) è ormai vuota su desktop
   (nome e badge assente vivono nella striscia sopra, vedi techStripHtml in
   aptRenderPlanner) — resta solo per dare alla tabella la larghezza delle colonne
   (table-layout:fixed la legge dalla prima riga). Azzerata in altezza cosi il
   bordo della striscia e quello della riga tag coincidono, senza spazio vuoto in
   mezzo. DEVE stare dopo la regola base ".apt-grid thead th" qui sopra: a parità
   di specificità vince l'ultima nell'ordine del file, non la media query più
   "specifica" — vedi bug identico già preso in questa stessa sessione. */
@media (min-width: 700px) {
  /* Con UNA colonna sola la riga dei nomi non serve: l'intestazione di una tabella
   a una colonna non distingue niente da niente. E chi sia quel tecnico lo dice
   gia' qualcos'altro — il pulsante "Solo mia" se e' la propria agenda, la
   navigazione fra tecnici (col nome e il contatore "1/5") su telefono.
   Tolta, sparisce anche la questione del centraggio: quel nome era centrato sulla
   sua colonna e non sulla scheda, perche' alla sua sinistra c'e' la colonna delle
   ore — quindi risultava spostato di mezza colonna oraria. */
.apt-grid-solo thead { display: none; }

/* I nomi dei tecnici restano fermi mentre la pagina scorre: scorrendo in fondo
   alla giornata senza di loro non si sa piu' in quale colonna si sta scrivendo.
   Si agganciano alla PAGINA (.apt-container) e non alla scheda, ed e' possibile
   solo perche' la scheda ritaglia invece di scorrere — vedi .apt-scheda.
   Il "top" e' l'altezza della riga dei comandi, che sta appiccicata sopra: senza,
   i nomi ci finirebbero sotto. La misura la passa il disegno, perche' dipende da
   quanto e' alta quella riga. */
.apt-grid thead th {
  position: sticky; top: var(--apt-testata-h, 90px); z-index: 12;
  background: var(--card);
  border-bottom: 1px solid var(--bordo-scheda);
  padding: 10px 8px; height: auto; line-height: 1.3;
}
/* La sfocatura su testata e ore e' stata tolta insieme alla loro appiccicatura:
   erano l'una la ragione dell'altra. */
/* L'angolo in alto a sinistra: sta fermo in tutt'e due i versi, quindi deve
   passare sopra sia alla testata sia alla colonna delle ore. */
.apt-grid thead .apt-time-th { z-index: 13; }
}

/* Frecce di scorrimento colonne (desktop, più tecnici di quanti ne stiano a schermo) —
   sopra la griglia, non accanto: a fianco avrebbero dovuto convivere con lo scroll
   verticale della pagina e finivano per scorrere via anche loro. */
/* Il posto delle frecce: una riga sopra la scheda, allineata al suo bordo
   destro. Sta FUORI dall'area che scorre, quindi non si muove — dentro, essendo
   in cima al contenuto, scivolava via di lato insieme alle colonne.
   La larghezza segue quella della scheda (che e' un numero intero di colonne),
   cosi' le frecce restano incolonnate col suo bordo invece che con quello della
   finestra. */
/* La riga dei comandi: scatola della data al centro, frecce accanto.
   L'allineamento verticale sta su "flex-start" e NON su "center", e il motivo e'
   che con center non converge: la colonna della data e' piu' alta delle frecce
   (ha sopra l'etichetta del mese), quindi allargando il margine delle frecce si
   sposta anche il centro della riga — ogni pixel aggiunto ne recupera meta'.
   Misurato: partendo da 6 avanzavano 7px, passando a 13 ne avanzavano ancora 4.
   Un numero fisso li' dentro non ci arriva mai.
   Con flex-start il margine sposta uno a uno, e quanto debba valere lo misura il
   disegno (aptAllineaFrecce): cosi' e' esatto e si rifa' da solo se un giorno
   cambia il corpo dell'etichetta del mese. */
.apt-testata {
  display: flex; align-items: flex-start; justify-content: center;
  gap: 10px; flex-shrink: 0;
  /* Resta in cima mentre il foglio scorre sotto: e' l'unico modo di cambiare
     giorno o colonna, e inseguirla scorrendo all'indietro sarebbe una
     scomodita' gratuita.
     Il velo con la sfocatura non e' un vezzo: senza, la colonna che passa sotto
     si interrompe di NETTO contro il fondo pieno, e a meta' di un appuntamento
     l'effetto e' quello di una cosa tagliata via. Sfocata si intravede che
     continua, che e' la verita'.
     Stava dentro il blocco per schermi grandi, quindi su telefono mancava — ed
     era li' che il taglio netto si notava di piu'. Vale a qualsiasi larghezza. */
  position: sticky; top: 0; z-index: 20;
  background: var(--bg);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .apt-testata {
    background: color-mix(in srgb, var(--bg) 80%, transparent);
    backdrop-filter: blur(14px) saturate(130%);
    -webkit-backdrop-filter: blur(14px) saturate(130%);
  }
}
.apt-nav-colonne { flex-shrink: 0; }
.apt-nav-colonne:empty { display: none; }

/* Le frecce sono l'UNICO modo di spostarsi fra le colonne, quindi devono
   sembrarlo: prima erano due iconcine appese in un angolo. Adesso hanno un
   contorno, e si spengono da sole quando da quella parte non c'e' piu' niente. */
.apt-desktop-scroll-nav {
  display: flex; align-items: center; gap: 8px; padding: 0;
}
.apt-desktop-scroll-nav .apt-mob-nav-btn {
  width: 34px; height: 34px; border-radius: var(--r-sm);
  border: 1px solid var(--bordo-scheda);
  background: var(--card); color: var(--text2);
  transition: border-color var(--t-stato), color var(--t-stato), opacity var(--t-stato);
}
.apt-desktop-scroll-nav .apt-mob-nav-btn:hover:not(:disabled) {
  border-color: var(--accent); color: var(--accent);
}
.apt-desktop-scroll-nav .apt-mob-nav-btn:disabled { opacity: .35; pointer-events: none; }

/* Nav mobile tecnici */
.apt-mobile-tech-nav {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; background: var(--card);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 5;
}
.apt-mob-tech-label {
  flex: 1; display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-md); font-weight: 600; color: var(--text);
}
.apt-mob-tech-dot {
  width: 10px; height: 10px; border-radius: var(--r-full); flex-shrink: 0;
}
.apt-mob-tech-count {
  font-size: 12px; color: var(--text3);
}
.apt-mob-nav-btn:disabled { opacity: .45; pointer-events: none; }

/* Celle orario — sticky a sinistra */
.apt-time-cell {
  /* 44 e non 52: dentro ci sta "08:30" a 12px e nient'altro, e i pixel avanzati
     erano una colonna vuota larga quanto mezza parola. Quelli che si liberano
     vanno alle colonne dei tecnici, cioe' agli appuntamenti.
     Al CENTRO e non a destra: schiacciata contro la linea divisoria sembrava
     l'etichetta della colonna accanto, e lo spazio vuoto restava tutto a
     sinistra — che e' esattamente cio' che la faceva sembrare troppo larga. */
  font-size: 12px; color: var(--text3); width: 42px; min-width: 42px;
  white-space: nowrap; text-align: center;
  /* In mezzo alla riga, non appoggiata al bordo di sopra: la riga E' la fascia
     dei quindici minuti, non una linea con un'etichetta attaccata. Con
     "vertical-align: top" e due pixel di spazio l'ora sfiorava il filo sopra e
     lasciava dieci pixel vuoti sotto — sbilanciata, e si vedeva. */
  vertical-align: middle; line-height: 1;
  padding: 0 2px; border-right: 1px solid var(--bordo-scheda);
  /* Il bordo sinistro da due pixel era il bordo della TABELLA, non una linea
     della griglia: adesso il contorno lo fa la scheda e questo non serve piu'. */
  position: sticky; left: 0; z-index: 2; background: var(--card);
}
.apt-grid tbody tr { height: 32px; }

/* Slot */
/* Ogni casella aveva un bordo su tre lati: il risultato era una carta a
   quadretti, e gli appuntamenti sembravano riempimenti di una tabella invece
   che blocchi appoggiati su un orario. Resta la sola linea VERTICALE fra un
   tecnico e l'altro — che serve, perche' senza non si capisce di chi sia una
   colonna — piu' una linea orizzontale ogni ora, messa piu' sotto. Le linee
   sono quelle tenui della scheda, non quelle dei campi. */
.apt-slot {
  border: none; border-right: 1px solid var(--bordo-scheda);
  padding: 0; cursor: default; position: relative;
  vertical-align: top; width: 200px; min-width: 200px;
}
/* La riga dell'ora tonda si vede, i quarti d'ora no: e' cosi' che si legge
   un'agenda — a colpo d'occhio si contano le ore, non i quindici minuti. */
.apt-grid tbody tr[data-time$=":00"] > .apt-slot,
.apt-grid tbody tr[data-time$=":00"] > .apt-time-cell {
  border-top: 1px solid var(--bordo-scheda);
}
.apt-grid tbody tr[data-time$=":30"] > .apt-slot {
  border-top: 1px solid color-mix(in srgb, var(--bordo-scheda) 45%, transparent);
}
.apt-slot-free { cursor: pointer; background: var(--card); }
.apt-slot-free:hover { background: color-mix(in srgb, var(--accent) 10%, var(--card)); }
/* Il "+" non cresce piu' da niente.
   La pastiglia che si gonfiava era graziosa da guardare una volta e faticosa
   dalla seconda in poi: passando il mouse sulla griglia si attraversano decine di
   caselle in un secondo, e ognuna faceva partire la sua animazioncina — il
   risultato era una schermata che sembrava rallentata.
   Un segno che sta a colpo d'occhio non ha bisogno di essere annunciato: la
   pastiglia c'e' o non c'e', senza transizione. Anche la velatura della casella
   e' istantanea, per lo stesso motivo. */
.apt-slot-free::after {
  content: '+'; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 20px; height: 20px; border-radius: var(--r-full);
  display: grid; place-items: center;
  background: var(--accent); color: var(--su-accento);
  font-size: 15px; font-weight: 500; line-height: 1;
  visibility: hidden;
  pointer-events: none;
}
.apt-slot-free:hover::after { visibility: visible; }
.apt-slot-out { background: var(--bg); }
.apt-slot-absent {
  background: repeating-linear-gradient(
    135deg, var(--gray6) 0px, var(--gray6) 4px, var(--gray5) 4px, var(--gray5) 8px
  );
  cursor: not-allowed;
}

/* Slot bloccato da un appuntamento di un altro tecnico (ambulatorio condiviso) */
.apt-slot-blocked {
  background: repeating-linear-gradient(
    135deg,
    color-mix(in srgb, var(--danger) 6%, var(--card)) 0px,
    color-mix(in srgb, var(--danger) 6%, var(--card)) 4px,
    color-mix(in srgb, var(--danger) 12%, var(--card)) 4px,
    color-mix(in srgb, var(--danger) 12%, var(--card)) 8px
  );
  cursor: not-allowed; padding: 4px 8px; vertical-align: middle;
}
.apt-slot-blocked-label {
  display: flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 600; color: var(--danger);
  line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apt-slot-blocked-label .material-icons-outlined { font-size: 13px; flex-shrink: 0; }

/* Colonna tecnico assente */
.apt-col-absent { background: var(--gray6); }
.apt-col-absent-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 700; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--r-pill); padding: 2px 8px;
  margin-top: 4px; letter-spacing: .03em; text-transform: uppercase;
}
.apt-col-absent-badge .material-icons-outlined { font-size: 12px; }
/* Chiusura (festa o chiusura della sede, dal Piano Ferie): stesso contrassegno
   delle assenze ma nella tinta dell'attesa, perche' non riguarda una persona —
   riguarda la sede — e deve distinguersi a colpo d'occhio da "Ferie". */
.apt-col-absent-badge.chiusura {
  color: var(--orange);
  background: color-mix(in srgb, var(--orange) 12%, transparent);
  border-color: color-mix(in srgb, var(--orange) 30%, transparent);
}
/* Nella riga MAT/POM della colonna chiusa, al posto dell'etichetta scrivibile,
   il nome della chiusura in sola lettura. */
.apt-tag-chiuso {
  font-size: var(--fs-xs); font-weight: 500; color: var(--orange); white-space: nowrap;
}
.apt-tag-chiuso .material-icons-outlined { font-size: 16px; vertical-align: -3px; margin-right: 4px; }

/* Pannello info giornaliero */
/* I pannelli del giorno stanno FUORI dalla scheda e galleggiano sul grigio della
   pagina, allineati a lei. Niente piu' trucchi per non farli scivolare di lato:
   non essendo dentro un riquadro che si sposta, non si spostano.
   Ognuno ha il suo riquadro, con lo stesso trattamento della scheda sopra —
   stesso bordo, stesso raggio, stessa ombra: sono oggetti della stessa famiglia. */
.apt-day-info {
  flex-shrink: 0;
  width: calc(var(--apt-colonne, 4) * var(--apt-unita, 252px) + var(--apt-barra-v, 0px));
  max-width: calc(100% - 2 * var(--gutter));
  margin: 0 auto;
  padding: 0 0 24px;
}
.apt-di-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
}
.apt-di-card {
  background: var(--card);
  /* Lo stesso trattamento della scheda sopra: bordo, raggio e ombra del
     progetto, non "--border" e "--radius" che sono di un'altra epoca del foglio. */
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: 16px 18px; display: flex; flex-direction: column; gap: 10px;
}
.apt-di-card-title {
  font-size: 13px; font-weight: 600; color: var(--text);
  display: flex; align-items: center; gap: 6px;
}
.apt-di-card-title .material-icons-outlined { font-size: 17px; color: var(--accent); }
.apt-di-abs-list { display: flex; flex-direction: column; gap: 8px; }
.apt-di-abs-row { display: flex; align-items: flex-start; gap: 8px; }
.apt-di-abs-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.apt-di-abs-name { font-size: 13px; font-weight: 600; color: var(--text); }
.apt-di-abs-detail { font-size: 12px; color: var(--text3); }
.apt-di-abs-note { font-size: 12px; color: var(--text2); font-style: italic; }
.apt-di-empty { font-size: 13px; color: var(--text3); margin: 0; }
/* Attrezzi fuori quel giorno, sopra il campo delle note: righe in sola lettura
   come le assenze, con l'icona dell'attrezzo al posto dell'avatar. */
.apt-di-eq-list { margin-bottom: 4px; }
.apt-di-eq-row { border-radius: var(--r-sm); margin: 0 -4px; padding: 4px; }
.apt-di-eq-row .apt-di-abs-text { flex: 1; }
.apt-di-eq-row .task-badge { align-self: flex-start; margin-top: 4px; }
.apt-di-eq-row.apribile { cursor: pointer; transition: background var(--transition); }
.apt-di-eq-row.apribile:hover { background: var(--gray6); }
.apt-di-eq-segno {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent);
}
.apt-di-eq-segno .material-icons-outlined { font-size: 16px; }
.apt-di-note-wrap { flex: 1; }
/* Un campo PIENO, senza bordo a riposo.
   Il bordo grigio stava dentro una scheda gia' bordata: due cornici annidate a
   pochi pixel l'una dall'altra, e il campo pesava piu' del pannello che lo
   contiene. A dire "qui si scrive" basta il riempimento — e' piu' leggero e non
   raddoppia il contorno.
   Il bordo torna, in accento, solo mentre ci si scrive: e' un'ombra INTERNA e non
   un bordo vero, cosi' comparendo non sposta il testo di un pixel e mezzo. */
.apt-di-textarea {
  width: 100%; box-sizing: border-box; resize: none; min-height: 80px; overflow-y: hidden;
  background: var(--gray6); border: none; border-radius: var(--r-sm);
  /* I 16px non sono una scelta estetica: sotto quella misura iOS ingrandisce da
     solo la pagina quando si tocca il campo. */
  padding: 10px 12px; font-size: 16px; color: var(--text); font-family: inherit;
  line-height: 1.5;
  transition: background var(--t-stato), box-shadow var(--t-stato);
}
.apt-di-textarea::placeholder { color: var(--text3); }
.apt-di-textarea:focus {
  outline: none;
  background: var(--card);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}
@media (max-width: 600px) {
  .apt-di-grid { grid-template-columns: 1fr; }
}

/* Appuntamento — position:absolute per non alterare l'altezza delle righe */
.apt-slot-appt {
  position: relative; padding: 0; overflow: hidden;
  /* La cella dell'appuntamento aveva "border: none !important": intorno a lei i
     fili della griglia non esistevano proprio — non erano coperti dalla scheda,
     mancavano. Si vedeva perche' la riga dell'ora si interrompeva sopra un
     appuntamento e il filo verticale spariva al suo fianco.
     Adesso la cella porta i suoi bordi come tutte le altre, e la scheda ci sta
     dentro staccata di tre pixel per lato: il blocco e' appoggiato sulla griglia,
     non incastrato al posto di un pezzo di griglia. Niente !important, o la riga
     dell'ora tonda non riuscirebbe a scriverci sopra il suo bordo. */
  border: none; border-right: 1px solid var(--bordo-scheda);
  cursor: default;
}
/* ── LA SCHEDA DELL'APPUNTAMENTO ─────────────────────────────────────────────
   Era un rettangolo con tre pixel di raggio e una spranga nera semitrasparente
   sul fianco sinistro, incollato al bordo della cella. Nel Piano Ferie lo stesso
   concetto — una cosa che dura nel tempo — e' una barra arrotondata dove il
   colore tinge tutto e non c'e' nessuna spranga: qui si parla quella lingua.
   Lo stacco dal bordo della cella passa da 1px a 3px per lato: e' quello che fa
   leggere gli appuntamenti come blocchi appoggiati sulla griglia invece che come
   caselle della griglia stessa. */
.apt-appt-fill {
  /* Lo stesso stacco su tutti e quattro i lati. Era "3px 3px 1px 3px": sopra la
     scheda arrivava a filo della linea dell'ora e la copriva, sotto restava un
     pixel e sembrava incastrata nella griglia invece che appoggiata sopra.
     Un blocco appoggiato non nasconde mai le righe su cui sta: si vede la linea
     dell'ora sopra, quella sotto e i fili verticali ai lati. */
  /* 4 sopra e sotto, 5 ai lati: con 3 tondi la nuvoletta arrivava quasi in
     battuta contro i fili verticali della griglia, e due appuntamenti in
     colonne vicine sembravano toccarsi. Lo spazio in piu' arriva dalla colonna
     dell'orario, che ne aveva d'avanzo. */
  position: absolute; inset: 4px 5px;
  display: flex; overflow: hidden;
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-1);
  /* Il colore di stato entra da un token unico: gli stati diversi si scrivono
     cambiando una variabile invece di ripetere ogni volta le stesse quattro
     dichiarazioni. */
  background: var(--apt-tinta, var(--accent));
}
/* Un appuntamento a cavallo del cambio di mezza giornata si disegna in due
   pezzi (vedi aptBuildSlotMap): quello che finisce sul confine perde gli angoli
   e lo stacco in basso, quello che riprende li perde in alto. Cosi' i due si
   leggono come una barra sola, interrotta solo dalla banda dei tag. */
.apt-appt-tagliato .apt-appt-fill {
  bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.apt-appt-continua .apt-appt-fill {
  top: 0; border-top-left-radius: 0; border-top-right-radius: 0;
}
.apt-appt-confirmed .apt-appt-fill { --apt-tinta: var(--accent); }
/* Era #FF9500: col bianco sopra faceva 2,20. Ora 4,53, stessa tinta. */
.apt-appt-pending   .apt-appt-fill { --apt-tinta: var(--stato-attesa); }
/* Questo passava gia' (5,25): tokenizzato per uniformita', valore invariato. */
.apt-appt-shared    .apt-appt-fill { --apt-tinta: var(--stato-condiviso); }
/* Il sollevamento al passaggio del mouse e' durato poco, e a ragione: un pixel
   di alzata su una scheda alta trentadue faceva comparire sotto un'ombra larga e
   squadrata, che in una griglia fitta e' solo sporco. Su una scheda incastrata
   fra altre schede il gesto "sollevo" non ha lo spazio per leggersi.
   Resta lo schiarimento appena accennato: si capisce su quale si e' senza che
   niente si muova. */
.apt-slot-appt:hover .apt-appt-fill { filter: brightness(1.08); }

/* Badge icone su appuntamento (condiviso, ricorrente, fuori orario) */
.apt-appt-badge { margin-left: 4px; opacity: .9; vertical-align: middle; }
.apt-appt-badge .material-icons-outlined { font-size: 13px; }
/* Accanto al nome, pero', il contrassegno deve stare DENTRO la riga da 16px e
   non allargarla: con l'allineamento "middle" la faceva diventare 18, e due
   pixel bastavano a far scivolare tutto il testo sotto e a farne tagliare
   l'ultima riga dal tetto del corpo. Alto 16 esatti, icona centrata dentro. */
.apt-appt-client .apt-appt-badge {
  display: inline-flex; align-items: center; height: 16px; vertical-align: top;
}

.apt-appt-body {
  /* 5 sopra e 8 a sinistra (erano 3 e 4): con la stondatura da 10px il nome
     partiva dentro la curva dell'angolo e sembrava schiacciato nel bordo.
     Sulla scheda da un quarto d'ora (24px) ci sta ancora: 5 + 16 di riga. */
  flex: 1; min-width: 0; padding: 5px 4px 3px 8px;
  overflow: hidden; cursor: pointer;
  display: flex; flex-direction: column; gap: 0;
  /* SOTTO LA SCRITTA DEL SERVIZIO SI VEDEVA UN TRATTINO BIANCO.
     Non era un segno: era la riga della nota, che cominciava nei tre pixel
     avanzati in fondo alla nuvoletta e veniva tagliata a un terzo di lettera.
     Adesso tutte e tre le righe — nome, servizio, nota — sono alte ESATTAMENTE
     16px, e il JS calcola quante ne entrano INTERE nell'altezza della scheda:
     una riga del planner e' alta 32px e la nuvoletta si stacca di 4 sopra e 4
     sotto, quindi l'altezza e' nota e non va misurata. Quello che non ci sta
     non viene nemmeno scritto.
     Questo tetto e' la seconda rete: se i conti sbagliassero di un pixel per i
     bordi della tabella, il taglio cadrebbe comunque su un confine di riga e
     non a meta' di una "g". */
  max-height: calc(var(--apt-righe, 99) * 16px + 8px);
}
.apt-appt-client {
  /* --su-colore e non #fff: e' il token del testo su fondo colorato, gia' usato
     ovunque nel progetto, e segue il tema. Il bianco letterale non lo fa. */
  font-size: 13px; font-weight: 600; color: var(--su-colore);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  line-height: 16px; flex-shrink: 0;
}
/* Meta e note vanno a capo per riempire l'altezza della card;
   sulle card basse l'eccesso viene tagliato dall'overflow del contenitore */
.apt-appt-meta {
  /* Era bianco all'85%: su un fondo di stato faceva 3,74. Pieno fa 4,53, e la
     riga resta comunque secondaria perche' e' piu' piccola del nome. */
  font-size: 12px; color: var(--su-colore);
  overflow: hidden; overflow-wrap: break-word;
  line-height: 16px; flex-shrink: 0;
  /* Quante righe: le decide il JS in base all'altezza della scheda, e i puntini
     cadono in fondo all'ultima riga scritta invece che a meta' della prima. */
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--apt-clamp, 2); line-clamp: var(--apt-clamp, 2);
}
/* Il separatore era al 55% di opacita': lo stesso problema della riga che lo
   contiene. Un punto di separazione non ha bisogno di essere sbiadito per
   leggersi come tale — gli bastano gli spazi che ha intorno. */
.apt-appt-sep { opacity: .8; }
/* Il 13/08/2026 la nota era stata schiacciata su UNA riga sola, con i puntini:
   una nota lunga andava a capo e rubava spazio a sede e servizio, finendo per
   sembrare piu' importante di loro. La cura pero' curava anche dove non serviva:
   su un appuntamento da un'ora la nota restava troncata a meta' parola con mezza
   nuvoletta vuota sotto (25/09/2026).
   Il problema non era il "va a capo": era che nessuno contava le righe. Ora le
   conta il JS — una per il nome, fino a due per sede e servizio, il resto alla
   nota — e la nota si prende tutto lo spazio che avanza, restando comunque
   l'ultima servita. Se lo spazio non c'e', la nota non si scrive affatto: meglio
   niente che un trattino bianco.
   Il testo intero resta a un tocco di distanza aprendo l'appuntamento, e nel
   title al passaggio del mouse. */
.apt-appt-notes {
  font-size: 11px; font-style: italic;
  /* Era un bianco letterale al 65%: sul tema chiaro non c'e' nessun bianco da
     sbiadire. Ora lo stesso token del resto della nuvoletta, appena velato. */
  color: color-mix(in srgb, var(--su-colore) 72%, transparent);
  /* 16px come le altre righe. Con 1.25 la riga era alta 13,75: la gambetta
     della "g" finiva sotto il taglio dell'overflow e si vedeva mozzata. */
  line-height: 16px; flex-shrink: 0;
  overflow: hidden; overflow-wrap: break-word;
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--apt-clamp, 1); line-clamp: var(--apt-clamp, 1);
}
/* L'icona sta nel flusso del testo, non in un contenitore flex a parte: dentro
   un -webkit-box la nota deve essere UN blocco di testo solo, o le righe non si
   contano e il ritaglio non avviene. */
.apt-appt-notes .material-icons-outlined { font-size: 12px; vertical-align: -2px; margin-right: 3px; }

/* Azioni sempre visibili */
.apt-appt-actions {
  display: flex; flex-direction: column; gap: 2px;
  /* Lo stacco SOTTO era zero: su una nuvoletta da mezz'ora i tre pulsanti
     chiedevano 76px dove ce n'erano 48, e l'ultimo usciva dal bordo — si vedeva
     un pulsante tagliato appoggiato alla stondatura in basso, con quattro pixel
     d'aria sopra e niente sotto.
     Ora lo stacco e' uguale sopra e sotto, e quanti pulsanti mostrare lo decide
     il JS contando quanti ce ne stanno interi: dove le tre icone separate non
     entrano si torna al "⋮" unico, che c'era gia' per il telefono. */
  padding: 3px 4px 3px 0; flex-shrink: 0;
}
/* Nuvoletta da un quarto d'ora: 24px di altezza utile in tutto. Un pulsante da
   24 la riempirebbe da bordo a bordo, quindi li' scende a 20. */
.apt-appt-azioni-mini { padding: 2px 3px 2px 0; }
.apt-appt-azioni-mini .apt-appt-btn { width: 20px; height: 20px; }
.apt-appt-azioni-mini .apt-appt-btn .material-icons-outlined { font-size: 13px; }
/* I pulsantini stavano su un bianco al 20%: sopra una scheda gia' chiara
   sparivano, sopra una scura erano l'unica cosa che si vedeva. Un velo del
   colore del testo funziona su qualunque tinta e segue il tema. */
.apt-appt-btn {
  width: 24px; height: 24px; border: none;
  background: color-mix(in srgb, var(--su-colore) 22%, transparent);
  border-radius: var(--r-xs); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--su-colore); padding: 0;
  transition: background var(--t-stato), color var(--t-stato);
}
.apt-appt-btn .material-icons-outlined { font-size: 15px; }
.apt-appt-btn:hover { background: color-mix(in srgb, var(--su-colore) 45%, transparent); }
/* Con il mouse i pulsanti compaiono al passaggio: una scheda alta trentadue
   pixel con tre bottoni sempre accesi e' piu' bottoni che informazione. Dove il
   passaggio del mouse non esiste — cioe' sul tocco — restano visibili, o
   sarebbero irraggiungibili. */
@media (hover: hover) and (pointer: fine) {
  .apt-appt-actions { opacity: 0; transition: opacity var(--t-stato); }
  .apt-slot-appt:hover .apt-appt-actions,
  .apt-slot-appt:focus-within .apt-appt-actions { opacity: 1; }
}
.apt-appt-btn-done { background: color-mix(in srgb, var(--su-colore) 16%, transparent); }
.apt-appt-btn-done:hover { background: rgba(80,200,80,.5); color: #fff; }
.apt-appt-btn-del:hover { background: rgba(180,20,20,.7); color: #fff; }

/* Pulsante approva sulla card pending */
.apt-appt-btn-ok { background: color-mix(in srgb, var(--su-colore) 32%, transparent); }
.apt-appt-btn-ok:hover { background: #2ea84a; color: #fff; }

/* Evidenziazione appuntamento (arrivo da Prenotazioni) */
.apt-appt-highlight .apt-appt-fill {
  animation: apt-hl-pulse 1s ease-in-out 3;
  outline: 3px solid var(--accent); outline-offset: 1px;
}
@keyframes apt-hl-pulse {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.25); }
}

/* Pagina Prenotazioni */
.apt-chip-count {
  background: var(--red); color: var(--su-colore); font-size: 10px; font-weight: 700;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: var(--r-pill);
  display: inline-flex; align-items: center; justify-content: center; margin-left: 4px;
}

/* ── Ortopedia: preventivi in pratica + invio al medico ── */
.ortho-quote-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 12px 16px; margin-bottom: 8px;
}
.ortho-quote-drop {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  border: 2px dashed var(--gray4); border-radius: var(--r-md);
  padding: 16px; margin-top: 4px;
  font-size: var(--fs-sm); color: var(--text3); cursor: pointer;
  transition: all var(--transition); text-align: center;
}
.ortho-quote-drop:hover, .ortho-quote-drop.drag-over {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.ortho-sent-banner {
  background: color-mix(in srgb, var(--green) 10%, transparent); border: 1px solid color-mix(in srgb, var(--green) 40%, transparent);
  border-radius: var(--r-md); padding: 12px 16px; margin-bottom: 12px;
  font-size: var(--fs-sm); color: var(--text2); line-height: 1.5;
}
.ortho-sent-banner .material-icons-outlined { color: var(--green); vertical-align: -4px; margin-right: 4px; }
.ortho-send-recipient {
  border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 12px; margin-bottom: 8px;
}

/* ── Firma email nel profilo: editor contenteditable con mini barra strumenti ── */
.sig-toolbar { display: flex; gap: 4px; margin-bottom: 8px; }
.sig-toolbar button {
  min-width: 34px; height: 34px; padding: 0 8px;
  border: 1.5px solid var(--bordo-campo); border-radius: 8px; background: var(--card);
  font-size: 14px; color: var(--text2); cursor: pointer; font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center;
  transition: all var(--transition);
}
.sig-toolbar button:hover { border-color: var(--accent); color: var(--accent); }
.sig-editor {
  min-height: 120px; padding: 12px 14px;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-md);
  font-size: 14px; background: var(--card); outline: none; line-height: 1.5;
}
.sig-editor:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent); }
/* max-width 100%, non un tetto fisso: la larghezza vera la decide l'attributo
   width messo al salvataggio (naturale, max 600px) — stessa resa della mail */
.sig-editor img { max-width: 100%; height: auto; }

/* ── Timbratura: avviso recidiva ritardi (deve NOTARSI, non è una nota qualsiasi) ── */
.tbr-late-alert {
  display: flex; align-items: flex-start; gap: 12px;
  margin-top: 20px; padding: 14px 16px;
  background: color-mix(in srgb, var(--red) 8%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--red) 45%, transparent); border-left: 5px solid var(--danger);
  border-radius: 12px;
  color: var(--danger); font-size: 14px; line-height: 1.45;
}
.tbr-late-alert .material-icons-outlined { color: var(--danger); font-size: 24px; flex-shrink: 0; }
.tbr-late-alert strong { font-weight: 600; } /* Peso 800 vietato (paragrafo 3 DESIGN.md): qui e testo dentro un paragrafo, non un contrassegno piccolo, quindi il tetto resta 600. */
/* "X volte" cliccabile: apre il riepilogo dei ritardi — deve leggersi come un
   pulsante (sfondo pieno, bordo) pur restando dentro il tono rosso dell'alert */
.tbr-late-alert-btn {
  display: inline-block; padding: 1px 9px; border-radius: 8px;
  background: var(--danger); color: var(--su-colore);
  border: none; cursor: pointer;
  font-family: inherit; font-size: var(--fs-base); font-weight: 600; /* 13.5 e 800 non ammessi (paragrafi 10.3 e 3): resta un bottone a pillola dentro il testo, quindi corpo base e peso 600. */
  text-decoration: underline; text-underline-offset: 2px;
  transition: filter .15s;
}
.tbr-late-alert-btn:hover { filter: brightness(.88); }

/* Promemoria "Sei al lavoro?": i tre rinvii diventano terziari (niente fondo ne
   bordo, testo accento) invece di condividere il peso visivo del bottone-pillola
   sopra — paragrafo 7 DESIGN.md. Stesso ordine, stesse etichette, stessa area di
   tocco: cambia solo lo stile, restando sulla classe .btn di base per le misure. */
.tbr-prompt-postpone { background: none; border: none; color: var(--accent); font-weight: 500; }
.tbr-prompt-postpone:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.tbr-prompt-postpone:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Dashboard ── */
/* Stesso padding orizzontale di .main-header/.filter-bar (28px): senza, il
   contenuto non era allineato al titolo sopra — sembrava un'altra pagina. */
/* Il contenitore di scroll resta a tutta larghezza (scrollbar al bordo finestra,
   come ogni altro modulo); il CONTENUTO invece ha una larghezza massima ed è
   centrato — su schermi larghi le card non si spalmano a dismisura. */
/* Rientro sul contenitore, come ogni altro elenco: prima il contenitore stava a
   --gutter e i figli si centravano da soli con un max-width. Stessa larghezza
   finale, ma il titolo in testata restava indietro a sinistra, perche' la
   regola che lo allinea guarda il contenitore, non i figli. */
.dash-wrap { flex: 1; overflow-y: auto; padding: 4px var(--rientro-lettura) 40px; box-sizing: border-box; }
/* I grafici dentro le card full-width: larghezza contenuta e centrata, così
   l'altezza (proporzionale) resta ragionevole invece di gonfiarsi. */
.dash-chart-wrap { max-width: 860px; margin: 0 auto; }
.dash-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 18px; }
.dash-toolbar select, .dash-toolbar input[type="date"] {
  font-size: 13px; padding: 8px 12px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  font-family: inherit; cursor: pointer;
}
.dash-toolbar input[type="date"] { cursor: text; }
.dash-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 16px;
}

/* ── LE SCHEDE DELLA DASHBOARD ───────────────────────────────────────────────
   Erano .apt-tpl-card: fascia grigia in cima col titolo, poi il corpo bianco —
   una scheda in due tinte, che e' il modo di prima. Nel resto dell'app rifatta
   una scheda e' di un colore solo, con il titolo dentro: la fascia separata
   raddoppia i contorni e fa sembrare il titolo un'etichetta appiccicata sopra
   invece del titolo di quella scheda.
   .apt-tpl-card NON e' stata toccata: la usano ancora 104 punti, quasi tutti in
   Impostazioni, e ridipingerla vorrebbe dire cambiare un modulo che nessuno ha
   chiesto di cambiare. Le schede della Dashboard hanno preso una classe loro. */
.dash-card {
  background: var(--card);
  border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  padding: 18px 20px 20px;
  animation: apt-entra var(--t-appare) both;
  animation-delay: var(--apt-ritardo, 0ms);
}
.dash-card-testa {
  display: flex; align-items: center; gap: 9px;
  margin-bottom: 14px;
  color: var(--accent);
}
.dash-card-testa h3 {
  margin: 0; font-size: var(--fs-md); font-weight: 600; color: var(--text);
}
.dash-card-corpo { min-width: 0; }

/* Anche l'elenco dei tecnici: dentro una scheda non serve un secondo riquadro,
   bastano le righe separate da un filo. */
.dash-card .list-card {
  background: transparent; border: none; border-radius: 0; box-shadow: none;
}
.dash-card .list-row { padding-left: 0; padding-right: 0; }
.dash-card .list-row:last-child { border-bottom: none; }

/* Il selettore del periodo: la stessa pastiglia bianca dei comandi del Piano
   Ferie e dell'Agenda, invece di una tendina di sistema. */
.dash-toolbar select, .dash-toolbar input[type="date"] {
  border: 1px solid var(--bordo-scheda);
  box-shadow: var(--shadow-1);
}
.dash-chart-card { grid-column: 1 / -1; }
.dash-chart-wrap { position: relative; }
.dash-chart-tooltip {
  position: absolute; top: 4px; min-width: 120px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 8px 12px; box-shadow: var(--shadow-sm); pointer-events: none; z-index: 5;
}
.dash-chart-total { text-align: center; font-size: 13px; color: var(--text3); margin-top: 8px; }
.dash-chart-total strong { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.dash-chart-legend {
  display: flex; gap: 16px; justify-content: center; margin-bottom: 8px;
  font-size: var(--fs-xs); color: var(--text2);
}
.dash-chart-legend i { display: inline-block; width: 16px; height: 3px; border-radius: 2px; vertical-align: middle; margin-right: 6px; }
.dash-kpi-row { display: flex; gap: 8px; flex-wrap: wrap; }
/* Riquadro PIENO, senza bordo: stava su fondo --card, cioe' lo stesso della
   scheda che lo contiene, e a distinguerlo c'era solo un filo — una scatola
   dentro una scatola. Riempito si legge subito come un blocco appoggiato, e i
   contorni nella schermata dimezzano. */
.dash-kpi {
  flex: 1; min-width: 90px; text-align: center;
  background: var(--gray6); border: none; border-radius: var(--r-md); padding: 14px 10px;
}
.dash-kpi-num { font-size: var(--fs-lg); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.dash-kpi-label { font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }
/* Stessa cosa delle pastiglie: dentro una scheda bianca un fondo bianco col
   filo intorno e' un contorno di troppo. */
.dash-stat-chip {
  background: var(--gray6); border: none; border-radius: var(--r-full);
  padding: 5px 12px; font-size: var(--fs-xs); color: var(--text2);
}
.dash-stat-chip strong { color: var(--text); font-weight: 400; }

/* Completato: sfondo verde, spunta illuminata */
.apt-appt-done .apt-appt-fill {
  /* Era #2ea84a: col bianco sopra 3,08. Ora 4,61, stesso verde. */
  background: var(--stato-fatto) !important;
  border-left-color: var(--stato-fatto-bordo) !important;
}
.apt-appt-done .apt-appt-btn-done {
  background: rgba(255,255,255,.35);
  color: #fff;
}
.apt-appt-done .apt-appt-client { opacity: .9; }

.apt-appt-btn-move:hover { background: rgba(255,255,255,.42); color: #fff; }

/* ── Spostamento appuntamento ── */
.apt-move-banner {
  flex-shrink: 0; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 8px 16px; background: var(--accent); color: var(--su-accento);
  font-size: 13px; font-weight: 500; position: sticky; top: 0; z-index: 18;
}
.apt-move-banner-icon { display: flex; align-items: center; }
.apt-move-banner-icon .material-icons-outlined { font-size: 18px; }
.apt-move-banner-text { flex: 1; }
.apt-move-banner .btn-ghost {
  background: rgba(255,255,255,.18); color: var(--su-accento); border: none;
}
.apt-move-banner .btn-ghost:hover { background: rgba(255,255,255,.3); }

/* Cella libera evidenziata come destinazione valida durante lo spostamento */
.apt-slot-move-target {
  background: color-mix(in srgb, var(--green) 14%, transparent) !important;
  position: relative;
}
.apt-slot-move-target::after {
  content: 'add_circle'; font-family: 'Material Icons Outlined';
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  color: var(--green); font-size: 18px; opacity: .55;
}
.apt-slot-move-target:hover { background: color-mix(in srgb, var(--green) 30%, transparent) !important; }
.apt-slot-move-target:hover::after { opacity: .9; }

/* Appuntamenti non rilevanti durante lo spostamento: attenuati e non cliccabili */
.apt-slot-move-blocked { opacity: .45; pointer-events: none; }

/* Card in fase di spostamento */
.apt-appt-moving .apt-appt-fill {
  outline: 2px dashed #fff; outline-offset: -2px;
}
.apt-appt-moving-label {
  width: 24px; height: 24px; display: flex; align-items: center; justify-content: center;
  color: #fff; animation: apt-move-pulse 1.1s ease-in-out infinite;
}
.apt-appt-moving-label .material-icons-outlined { font-size: 16px; }
@keyframes apt-move-pulse { 0%,100% { opacity: .5; } 50% { opacity: 1; } }

/* ── Le azioni di un appuntamento, dal "⋮" della nuvoletta ───────────────────
   Era un foglio che saliva dal basso, il modo di fare del telefono. Andava bene
   finche' si apriva solo sul telefono; da quando le tre icone lasciano il posto
   al "⋮" anche su desktop — sulle nuvolette troppo basse per contenerle — quel
   foglio ha cominciato a comparire sul computer, ed era l'unica finestra
   dell'app ad arrivare dal bordo invece che dal centro (25/09/2026).
   Ora e' un modale come tutti gli altri: qui restano solo le tre righe che ci
   stanno dentro. */
.modal.apt-azioni-modal { width: min(420px, 92vw); }
.apt-azioni-elenco { display: flex; flex-direction: column; gap: 2px; }
.apt-azione {
  display: flex; align-items: center; gap: 12px; width: 100%;
  /* 48 e non 50: e' la misura del bersaglio da dito usata nel resto dell'app. */
  min-height: 48px; padding: 0 12px; border: none; background: none;
  font-size: 15px; font-weight: 500; color: var(--text); font-family: inherit;
  border-radius: var(--r-sm); cursor: pointer; text-align: left;
  transition: background var(--t-stato);
}
.apt-azione:hover { background: var(--gray6); }
.apt-azione .material-icons-outlined { font-size: 21px; color: var(--accent); }
/* Eliminare resta rosso, ma NON e' il pulsante grosso accanto a Salva: qui e'
   una riga fra le altre, ed e' l'ultima. */
.apt-azione-elimina, .apt-azione-elimina .material-icons-outlined { color: var(--danger); }
.apt-azione-elimina:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* Appuntamento su giorno di assenza del tecnico */
.apt-appt-on-leave .apt-appt-fill {
  /* Era #b0b8c1: col bianco sopra 2,01, il peggiore dei quattro. Ora 4,58. */
  background: var(--stato-ferie) !important;
  border-left-color: var(--stato-ferie-bordo) !important;
  opacity: .75;
}
.apt-appt-on-leave .apt-appt-client { color: var(--su-colore); }
.apt-appt-on-leave .apt-appt-meta   { color: var(--su-colore); }

/* Tag rows — fascia mattino/pomeriggio */
.apt-tag-row { background: color-mix(in srgb, var(--accent) 8%, var(--card)); }
.apt-tag-row td { border-top: 1px solid color-mix(in srgb, var(--accent) 25%, var(--card)); border-bottom: 1px solid color-mix(in srgb, var(--accent) 25%, var(--card)); }
.apt-tag-label {
  font-size: 11px; font-weight: 600; color: var(--accent);
  text-align: right; padding: 5px 8px; white-space: nowrap;
  width: 52px; letter-spacing: .06em;
}
.apt-tag-cell-td {
  padding: 3px 4px; vertical-align: middle; display: table-cell;
}
.apt-tag-dot { font-size: 12px; color: color-mix(in srgb, var(--accent) 55%, var(--card)); margin-right: 4px; }
.apt-tag-input {
  border: none; background: transparent; font-size: var(--fs-sm); font-weight: 600;
  color: var(--accent); width: calc(100% - 20px);
  padding: 2px 4px; border-radius: var(--r-xs); outline: none;
  font-family: inherit;
}
.apt-tag-input:focus, .apt-tag-input:focus-visible {
  /* Anello unico: il box-shadow gia' cerchia il campo, l'outline ne aggiungeva
     un secondo appena piu' in fuori. */
  outline: none; background: var(--card); box-shadow: 0 0 0 2px var(--accent);
}
.apt-tag-input::placeholder { color: color-mix(in srgb, var(--accent) 45%, var(--card)); font-style: italic; font-weight: 400; }

/* Dropdown ricerca cliente */
.apt-client-search-wrap { position: relative; }
.apt-client-dropdown {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 50;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1);
  max-height: 200px; overflow-y: auto;
}
.apt-client-dropdown:empty { display: none; }
.apt-client-item {
  padding: 8px 12px; cursor: pointer; font-size: 14px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 6px;
  transition: background .12s;
}
.apt-client-item:last-child { border-bottom: none; }
.apt-client-item:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.apt-client-selected {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; background: var(--bg); border-radius: var(--r-sm);
  margin-top: 8px; font-size: 13px;
}

/* Cliente scelto nel modal appuntamento: nome in evidenza, sotto email e
   telefono in piccolo — nello stesso ordine dei tasti "Notifiche al cliente"
   (Email, poi SMS/WhatsApp). Presente = si tocca per correggerlo; assente =
   "+ Email" / "+ Telefono" in accento, stesso posto e stessa mossa. */
.apt-client-selected.apt-cliente-scheda {
  flex-direction: column; align-items: stretch; gap: 4px;
  padding: 10px 8px 10px 14px; border-radius: var(--r-xs);
}
.apt-cliente-testa { display: flex; align-items: center; gap: 8px; min-width: 0; }
.apt-cliente-nome {
  flex: 1; min-width: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em;
  color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apt-cliente-togli { color: var(--text3); flex-shrink: 0; }
.apt-cliente-togli:hover { color: var(--danger); }
/* Mentre si modifica un contatto la X accanto al campo annulla: quella del nome
   (togli il cliente) sparisce, o due X una sopra l'altra si confondono. */
.apt-cliente-scheda:has(.apt-contatto-modifica) .apt-cliente-testa .apt-cliente-togli { visibility: hidden; }
.apt-cliente-contatti { display: flex; flex-wrap: wrap; gap: 2px 4px; margin-left: -7px; min-width: 0; }
.apt-contatto {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 100%;
  padding: 3px 9px 3px 7px; border: 0; border-radius: var(--r-pill); background: transparent;
  font: inherit; font-size: 12.5px; font-weight: 400; color: var(--text2);
  cursor: pointer; transition: background .12s, color .12s;
}
.apt-contatto .material-icons-outlined { font-size: 14px; color: var(--text3); flex-shrink: 0; }
.apt-contatto-valore { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
/* Le estensioni del browser per chiamare (l'icona blu accanto al numero)
   infilano la loro icona DENTRO il valore: allineata sulla linea di base, alta
   quasi 30px, spingeva il numero 7px sotto la sua icona. Solo quando dentro c'e'
   qualcosa che non e' testo si passa a flex centrato: cosi' email e numeri
   normali tengono i puntini di troncamento. */
.apt-contatto-valore:has(> *) { display: inline-flex; align-items: center; gap: 6px; }
.apt-contatto:hover { background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text); }
.apt-contatto-manca, .apt-contatto-manca .material-icons-outlined { color: var(--accent); }
.apt-contatto-manca { font-weight: 600; }
.apt-contatto-manca:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.apt-contatto:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.apt-contatto-modifica { display: flex; align-items: center; gap: 6px; margin: 4px 0 0 7px; }
.apt-contatto-modifica input { flex: 1; min-width: 0; }
.apt-contatto-ok {
  width: 36px; height: 36px; flex-shrink: 0; border: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: var(--accent); color: var(--su-accento);
}
.apt-contatto-ok .material-icons-outlined { font-size: 18px; }
.apt-contatto-ok:disabled { opacity: .5; cursor: default; }
.apt-contatto-nota { margin: 2px 0 0 7px; font-size: 11.5px; color: var(--text3); }
.apt-contatto-nota.errore { color: var(--danger); font-weight: 500; }

/* "Nessun cliente": la stessa pillola delle notifiche, non una casella nativa,
   e compatta invece che a tutta larghezza. */
.apt-notify-pill.apt-nessun-cliente { display: inline-flex; margin-top: 10px; }

/* Bottone accent small (nuovo cliente) */
.btn-accent-sm {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 12px; border: none; border-radius: 8px; cursor: pointer;
  font-size: 13px; font-weight: 600; white-space: nowrap; flex-shrink: 0;
  background: var(--accent); color: var(--su-accento); transition: background .15s;
}
.btn-accent-sm .material-icons-outlined { font-size: 16px; }
/* Era var(--accent-dark, #1a8fa8): un nome mai definito, quindi sempre quel
   celeste scritto a mano — che con l'accento verde del marchio non c'entrava
   niente, ne' in chiaro ne' in scuro. Ora si scurisce l'accento vero. */
.btn-accent-sm:hover { background: color-mix(in srgb, var(--accent) 82%, #000); }

/* Layout ricerca cliente + pulsante sulla stessa riga */
.apt-client-search-row {
  display: flex; gap: 8px; align-items: stretch;
}
/* Era un secondo fondo pieno nella finestra di Nuovo/Modifica appuntamento,
   in conflitto col bottone primario "Salva" (§7). Declassato a terziario. */
.apt-btn-new-client {
  align-self: stretch; background: transparent; color: var(--accent); font-weight: 500;
}
.apt-btn-new-client:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }

/* Separatore form */
.apt-form-sep {
  border: none; border-top: 1px solid var(--border);
  margin: 4px 0 12px;
}

/* Pill Condividi / Ricorrente */
.apt-extra-row { display: flex; gap: 8px; margin-bottom: 4px; }
.apt-extra-pill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 8px 12px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
  border: 1.5px solid var(--border); color: var(--text3);
  background: var(--bg); cursor: pointer; transition: all .15s;
}
.apt-extra-pill .material-icons-outlined { font-size: 16px; }
.apt-extra-pill-on { background: var(--accent); color: var(--su-accento); border-color: var(--accent); }

/* Drag & drop ordine moduli */
.mod-order-list { display: flex; flex-direction: column; gap: 6px; }
.mod-order-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; background: var(--card);
  border: 1.5px solid var(--border); border-radius: 12px;
  cursor: grab; transition: box-shadow .15s, opacity .15s; user-select: none;
}
.mod-order-row:active, .mod-order-row.dragging { cursor: grabbing; opacity: .5; box-shadow: 0 6px 24px rgba(0,0,0,.15); }
.mod-order-drag { color: var(--text3); display: flex; align-items: center; }
.mod-order-drag .material-icons-outlined { font-size: 20px; }
.mod-order-icon { color: var(--accent); display: flex; align-items: center; }
.mod-order-icon .material-icons-outlined { font-size: 20px; }
.mod-order-label { font-size: 15px; font-weight: 500; color: var(--text); }

/* Wizard import contatti */
.apt-imp-cols { display: flex; flex-direction: column; gap: 8px; }
.apt-imp-col {
  display: flex; align-items: center; gap: 12px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 10px 12px;
}
.apt-imp-col-info { flex: 1; min-width: 0; }
.apt-imp-col-header { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apt-imp-col-samples { display: flex; gap: 6px; margin-top: 3px; flex-wrap: wrap; }
.apt-imp-col-samples span {
  font-size: 11px; color: var(--text3); background: var(--card);
  border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 140px;
}
.apt-imp-col-select { flex: 0 0 170px; font-size: 13px !important; padding: 8px 10px; }
.apt-imp-result { display: flex; gap: 12px; justify-content: center; }
.apt-imp-result-num {
  flex: 1; text-align: center; background: var(--bg); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px 8px; display: flex; flex-direction: column; gap: 2px;
}
.apt-imp-result-num strong { font-size: 24px; color: var(--accent); }
.apt-imp-result-num span { font-size: 12px; color: var(--text3); }
@media (max-width: 640px) {
  .apt-imp-col { flex-direction: column; align-items: stretch; gap: 8px; }
  .apt-imp-col-select { flex: none; width: 100%; }
}

/* Storico appuntamenti nel modal cliente */
.cl-history { margin-top: 8px; border-top: 1px solid var(--border); padding-top: 16px; }
.cl-history-title {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 12px;
}
.cl-history-title .material-icons-outlined { font-size: 17px; color: var(--accent); }
/* Il padding era 9px, che non e' un gradino della griglia a 4. */
.cl-hist-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--gray5);
}
.cl-hist-row:last-child { border-bottom: none; }
.cl-hist-when { display: flex; flex-direction: column; flex-shrink: 0; min-width: 78px; }
.cl-hist-when strong { font-size: 13px; color: var(--text); }
.cl-hist-when span { font-size: 12px; color: var(--text3); }
.cl-hist-info { flex: 1; min-width: 0; }
.cl-hist-what { font-size: 13px; font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cl-hist-meta { font-size: 12px; color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cl-hist-badge {
  flex-shrink: 0; font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: var(--r-pill);
}
.cl-hist-done      { background: color-mix(in srgb, var(--green) 12%, transparent);  color: var(--green); }
.cl-hist-future    { background: color-mix(in srgb, var(--accent) 10%, transparent);   color: var(--accent); }
.cl-hist-pending   { background: color-mix(in srgb, var(--orange) 12%, transparent);  color: var(--orange); }
.cl-hist-cancelled { background: color-mix(in srgb, var(--red) 10%, transparent);   color: var(--red); }
.cl-hist-past      { background: var(--gray6);          color: var(--text2); }

/* Pill notifiche */
.apt-notify-row {
  display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap;
}
.apt-notify-pill {
  display: flex; align-items: center; cursor: pointer;
}
.apt-notify-pill input { display: none; }
.apt-notify-pill span {
  display: flex; align-items: center; gap: 4px;
  padding: 8px 12px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
  border: 1.5px solid var(--border); color: var(--text3);
  background: var(--bg); transition: all .15s;
}
.apt-notify-pill span .material-icons-outlined { font-size: 16px; }
.apt-notify-pill input:checked + span {
  background: var(--accent); color: var(--su-accento); border-color: var(--accent);
}

/* Pill giorni settimana (modal ripetizione tag) */
.apt-dow-pill { display: inline-flex; cursor: pointer; }
.apt-dow-pill input { display: none; }
.apt-dow-pill span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 36px; border-radius: var(--r-pill); font-size: 13px; font-weight: 600;
  border: 1.5px solid var(--border); color: var(--text2);
  background: var(--bg); transition: all .15s;
}
.apt-dow-pill input:checked + span {
  background: var(--accent); color: var(--su-accento); border-color: var(--accent);
}

/* Riga contesto appuntamento (tecnico · data · ora) */
.apt-f-context {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px;
  font-size: 13px; color: var(--text2);
  background: var(--bg); border-radius: var(--r-xs);
  padding: 8px 12px; margin-bottom: 16px;
}
.apt-f-ctx-item { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.apt-f-context .material-icons-outlined { font-size: 15px; color: var(--text3); flex-shrink: 0; }
.apt-f-context strong { color: var(--text); }
.apt-f-time-inline {
  border: none; background: transparent; font-size: 13px; font-weight: 600;
  color: var(--accent); cursor: pointer; padding: 4px; margin: 0;
  font-family: inherit; -webkit-appearance: none; appearance: none;
  border-radius: var(--r-sm); max-width: 150px; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Era outline:none senza alcun sostituto a fuoco (accessibilità bloccante,
   §0.3): il tocco/tab su tecnico, data e ora non mostrava mai dove si era. */
.apt-f-time-inline:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.apt-f-time-inline:focus-visible {
  background: color-mix(in srgb, var(--text) 4%, transparent);
  outline: 2px solid var(--accent); outline-offset: 2px;
}
select.apt-f-time-inline { text-align: left; }

/* Pagina clienti */
/* (.apt-cl-toolbar e .apt-cl-list sono state tolte: erano la striscia bianca a
   tutta larghezza e l'elenco a tutta pagina di Clienti e Noleggi. Adesso tutti
   e due i moduli usano .vista-scorrevole + .elenco-colonna come gli altri.) */
.search-bar-wrap {
  flex: 1; max-width: 320px; position: relative;
  display: flex; align-items: center;
}
.search-icon {
  position: absolute; left: 13px; font-size: 18px;
  color: var(--text3); pointer-events: none;
}
/* Una pastiglia piena, non un rettangolo col bordo.
   Il fondo era --bg, cioe' lo STESSO della pagina: il campo non si vedeva, e a
   disegnarlo restava solo il bordo — da qui l'aria di scatola. Riempiendolo di
   --card si stacca da solo dal fondo (bianco su grigio chiaro, e la coppia si
   inverte da sola in tema scuro), e il bordo puo' tornare un filo. La forma
   tonda e' la stessa dei chip che gli stanno a fianco: una barra sola, un
   linguaggio solo. */
.search-bar-input {
  width: 100%; padding: 9px 14px 9px 38px;
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-pill);
  background: var(--card); font-size: 14px; color: var(--text);
  transition: border-color var(--t-stato), box-shadow var(--t-stato);
}
.search-bar-input::placeholder { color: var(--text3); }
.search-bar-input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
.search-clear { position: absolute; right: 4px; }
/* ── LE ANIMAZIONI ───────────────────────────────────────────────────────────
   Due sole, e tutt'e due dicono qualcosa.
   La prima: cambiando giorno le schede entrano invece di apparire di colpo.
   Salgono di sei pixel sfumando, sfalsate di pochi centesimi in base alla
   colonna, cosi' l'occhio segue la giornata da sinistra a destra e capisce che
   il contenuto e' cambiato — con lo scatto secco non si distingue un giorno
   pieno appena caricato da uno rimasto uguale.
   Lo sfalsamento arriva da --apt-ritardo, che il disegno mette su ogni colonna:
   senza, o partono tutte insieme (e non e' un'entrata, e' un lampo) o servirebbe
   una regola per colonna. */
@keyframes apt-entra {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.apt-slot-appt .apt-appt-fill {
  animation: apt-entra var(--t-appare) both;
  animation-delay: var(--apt-ritardo, 0ms);
}
/* NIENTE "animation: none" al passaggio del mouse. C'era per non far litigare
   il sollevamento con l'entrata, e ha prodotto il difetto peggiore di tutti:
   spegnendo l'animazione all'ingresso del mouse e riaccendendola all'uscita,
   quest'ultima RIPARTIVA DA CAPO — la scheda spariva e risaliva dal basso ogni
   volta che il mouse la lasciava. L'entrata deve girare una volta sola, al
   disegno, e non sapere piu' niente del mouse. */

/* La seconda: la linea dell'ora corrente. Non c'e' mai stata, ed e' l'unica cosa
   in un planner che dice "adesso siamo qui" — la si cerca appena si apre la
   giornata di oggi. Scorre da sola ogni minuto, e il pallino a sinistra pulsa
   piano perche' e' l'unica cosa viva in una griglia ferma. */
/* La linea dell'ora corrente serve a rispondere a una domanda di sfuggita —
   "a che punto siamo?" — e a una domanda di sfuggita si risponde sottovoce.
   Era due pixel di rosso pieno attraversati per tutta la tavola, con un pallino
   che pulsava all'infinito: piu' insistente degli appuntamenti, che sono la cosa
   che si sta guardando davvero.
   Adesso: un filo di un pixel in rosso velato, e un pallino piccolo e fermo
   all'inizio della riga. Il rosso resta perche' e' l'unico colore che in
   un'agenda vuol dire "adesso", ma smette di gridare. Niente animazione: una
   cosa che pulsa in un angolo tira l'occhio ogni volta che si muove. */
.apt-linea-ora {
  position: absolute; left: 0; height: 0; z-index: 3;
  border-top: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  pointer-events: none;
  transition: top .6s cubic-bezier(.2,0,0,1);
}
.apt-linea-ora::before {
  content: ''; position: absolute; left: 46px; top: -3px;
  width: 6px; height: 6px; border-radius: var(--r-full);
  background: color-mix(in srgb, var(--danger) 70%, transparent);
}

.apt-dropdown-menu {
  position: absolute; z-index: 200; min-width: 160px;
  background: var(--card); border: 1px solid var(--bordo-scheda);
  /* Raggio e ombra del progetto invece di due valori scritti a mano: una tendina
     e' un pannello, e i pannelli nel progetto hanno tutti lo stesso spessore. */
  border-radius: var(--r-md); box-shadow: var(--shadow-2);
  padding: 4px; overflow: hidden;
}
.apt-dropdown-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 10px 12px; font-size: 14px;
  color: var(--text); background: none; border: none;
  cursor: pointer; text-decoration: none; border-radius: 7px;
  font-family: inherit; white-space: nowrap;
}
.apt-dropdown-item:hover { background: var(--bg); }
.apt-dropdown-item .material-icons-outlined { font-size: 17px; color: var(--text3); }
/* Dentro la vista che scorre, non piu' una striscia incollata in fondo alla
   pagina: scende insieme all'elenco, come l'ultima riga di una lettura. */
.apt-cl-pagination {
  display: flex; align-items: center; justify-content: center;
  padding: 0 var(--rientro-lettura) 28px;
}
.apt-cl-count { font-size: 13px; color: var(--text3); }
.apt-cl-pages { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text2); }

/* Righe lista generica (clienti, admin rows) */
.list-card {
  background: var(--card); border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden;
}
.list-row {
  display: flex; align-items: center; gap: 12px;
  /* Era 12/16: §9 chiede 8 verticale / 12 orizzontale per la riga di elenco. */
  padding: 8px 12px; border-bottom: 1px solid var(--border);
  cursor: pointer; transition: background .12s;
}
.list-row:last-child { border-bottom: none; }
.list-row:hover { background: var(--bg); }
.list-row-body { flex: 1; min-width: 0; }
/* 14 (corpo normale) -> 13 (--fs-sm, "righe dense" in §2): un gradino in meno
   di riga senza perdere la distinzione dal peso, gia' a 600 e lasciato cosi'. */
.list-row-title { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.list-row-sub { font-size: 12px; color: var(--text3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.avatar-sm { width: 36px; height: 36px; font-size: 13px; flex-shrink: 0; }

.apt-cl-hist-btn { color: var(--accent); flex-shrink: 0; }
.apt-cl-hist-btn:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* Chiamata rapida dal bordo sinistro della riga, solo su mobile: da desktop il
   telefono è già visibile in chiaro nella riga stessa, il pulsante servirebbe solo
   a occupare spazio; su mobile invece è la scorciatoia per chiamare senza aprire
   la scheda cliente/medico. */
.list-row-call-btn {
  display: none; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 50%;
  align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--green) 10%, transparent); color: #34C759;
  text-decoration: none;
}
.list-row-call-btn .material-icons-outlined { font-size: 18px; }
.list-row-call-btn:active { background: color-mix(in srgb, var(--green) 22%, transparent); }
@media (max-width: 600px) {
  .list-row-call-btn { display: flex; }
}

/* ── Noleggi ── */
/* Card verticale indipendente (non più righe di un unico .list-card con filo da
   1px tra l'una e l'altra — con tante informazioni su più righe per richiesta si
   perdeva dove finiva una scheda e iniziava la successiva, 17/08/2026): stesso
   linguaggio visivo di .task-card, sfondo/ombra propri e distanza vera tra le
   card invece di un separatore sottile. Niente cursore a mano, non c'è nessun
   dettaglio da aprire cliccando la card, solo i pulsanti in fondo. */
.noleggi-cards {
  /* Qui NON si applica la conversione "schede -> righe con separatore" del §5.
     Le schede indipendenti non sono un residuo: sono una scelta presa il
     17/08/2026, perche' una richiesta di noleggio porta piu' righe di contenuto
     (prodotti, date, stato, note) e senza uno stacco netto si legge dove
     finisce una e comincia la successiva.
     Della regola si prende quello che serve — via l'ombra, spaziature sulla
     griglia — e si lascia stare quello che cancellerebbe una decisione presa
     con cognizione. La specifica serve a togliere il caso, non il pensiero. */
  display: flex; flex-direction: column; gap: 12px;
}
.noleggi-row {
  /* display:flex mancava: il gap non valeva niente e le righe si toccavano
     ("Consegna a domicilio" e l'indirizzo a 0px), tenute a distanza solo da
     margini sparsi (6, 8, 4). Ora un ritmo solo, 12 fra una riga e l'altra, e
     nessun margine ad hoc sotto. */
  display: flex; flex-direction: column; align-items: stretch; gap: 12px; cursor: default;
  /* Scheda: bordo e non ombra (§5). Spazio interno 20 (era 16): con dentro
     pillole, nota e pulsante, 16 la faceva sembrare piena fino al bordo. */
  background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md); padding: 20px;
}
.noleggi-row:hover { background: var(--card); }
.noleggi-top { display: flex; align-items: flex-start; gap: 12px; }
.noleggi-icon {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: #fff;
}
/* I prodotti sono il cuore della richiesta: chip colorati in grassetto, non testo
   grigio qualunque in cui si perdevano tra nome cliente e badge di stato. Viola
   (non il blu accent già usato da telefono/email/mappa) per non confonderli con
   i pulsanti di contatto — stesso sfondo/colore, sembravano la stessa cosa. */
/* Riga che va a capo con un gap vero, non line-height 2.2 + margini sotto a ogni
   chip: quelli lasciavano 12px vuoti in fondo e sbilanciavano la testata. */
.noleggi-presidi { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.noleggi-product-chip {
  display: inline-block; background: color-mix(in srgb, var(--purple) 10%, transparent); color: var(--purple);
  /* Era 700 (fuori dall'eccezione, non e' un glifo <=11px) e 3px/6px fuori
     griglia (§10.4): 600 e i due gradini piu' vicini, 4 e 8. */
  font-weight: 600; font-size: 13px; padding: 4px 10px; border-radius: var(--r-pill);
  margin: 0;
}
.noleggi-product-detail { display: inline-block; font-size: 12px; color: var(--text3); font-weight: 500; margin: 0; }
/* Badge centrati sulla riga del NOME (alta 18), non sull'intera testata: prima
   stavano 13px sotto, a meta' fra nome e prodotti. */
.noleggi-badges { display: flex; align-items: center; gap: 8px; flex-shrink: 0; height: 18px; }
/* Il cestino e' un pulsante da 44 col glifo in mezzo: il glifo finiva 10px prima
   del bordo, e sotto "Pronto" arriva fino al bordo. Si allinea il glifo. */
.noleggi-badges .btn-icon { margin-right: -10px; }
.noleggi-meta { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 13px; color: var(--text2); }
.noleggi-meta > span { display: inline-flex; align-items: center; gap: 6px; }
/* mi(..., 'sm') qui non bastava (icone.css arriva dopo e rimette 24px): icone
   da 24 accanto a testo da 13 sembravano fuori riga rispetto a quelle da 15
   delle pillole subito sotto. 17 come .detail-info-row, terziarie come testo. */
.noleggi-meta .material-icons-outlined { font-size: 17px; color: var(--text3); }
/* Nota: icona da 16 centrata sulla PRIMA riga (riga da 20), non 2,6px sotto. */
.noleggi-nota > span:not(.material-icons-outlined) { line-height: 20px; }
.noleggi-nota .material-icons-outlined { font-size: 16px; margin-top: 2px; color: var(--text3); }
/* Nessun margine: lo stacco dalle righe vicine lo da' il gap della scheda, che
   prima non funzionava (la scheda non era flex) e veniva rattoppato qui. */
.noleggi-address { font-size: 13px; color: var(--text2); }
/* La nota del cliente e' un blocco PIENO, e un blocco pieno appoggiato a un
   pulsante si legge come se lo toccasse: gli otto pixel di distacco della
   scheda bastano fra due righe di testo, non fra una campitura grigia e il
   bordo di "Conferma". Stesso motivo per cui l'indirizzo qui sopra ha un filo
   di spazio in piu'. Le misure stanno qui e non in un attributo style dentro
   il disegno, come tutto il resto della scheda. */
.noleggi-nota {
  display: flex; gap: 6px; align-items: flex-start;
  font-size: 13px; font-style: italic; color: var(--text2);
  background: var(--gray6); border-radius: var(--r-sm);
  /* 13 a sinistra = 1 di bordo + 12 di spazio delle pillole indirizzo/telefono:
     cosi' l'icona della nota cade sulla stessa colonna delle loro icone.
     Nessun margine: il distacco dal pulsante lo da' la riga dei contatti. */
  padding: 10px 13px; margin: 0;
}
/* 12 di gap della scheda + 4: le azioni stanno a 16 dal contenuto, un filo piu'
   staccate delle righe di informazione fra loro. */
.noleggi-footer { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; }
.noleggi-contacts { display: flex; gap: 8px; flex-wrap: wrap; }
/* margin-left:auto: sul telefono le azioni vanno a capo sotto i contatti e
   finivano a sinistra; restano a destra, sotto al cestino, come su computer. */
.noleggi-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* Chiama/scrivi/mappa come veri pulsanti (pillola con sfondo), non link sottolineati
   — devono percepirsi cliccabili a colpo d'occhio, non leggersi come testo normale.
   Componente generico (non solo Noleggi): riusato anche nelle schede di dettaglio
   di Clienti e Medici/Terapisti. */
.contact-btn {
  display: inline-flex; align-items: center; gap: 6px;
  /* Era 6px 12px (6 fuori griglia) e raggio 20px libero: c'e' gia' --r-pill. */
  padding: 8px 12px; border-radius: var(--r-pill);
  /* Era 600 (peso dell'azione primaria, §3): qui e' un'azione ripetuta, non la
     principale della vista. */
  font-size: 13px; font-weight: 500; white-space: nowrap;
  background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent); text-decoration: none;
  transition: background .12s;
}
.contact-btn:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.contact-btn .material-icons-outlined { font-size: 15px; }
/* Riga di pulsanti contatto in una scheda di dettaglio (Cliente/Medico) */
.detail-contacts { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.detail-info-row { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text2); }
.detail-info-row .material-icons-outlined { font-size: 17px; color: var(--text3); flex-shrink: 0; }

.badge-noleggi-nuovo            { background: var(--gray5); color: var(--text2); }
.badge-noleggi-in_preparazione  { background: color-mix(in srgb, var(--orange) 10%, transparent);   color: var(--orange); }
.badge-noleggi-pronto           { background: color-mix(in srgb, var(--accent) 10%, transparent);   color: var(--accent, var(--accent)); }
.badge-noleggi-completato       { background: color-mix(in srgb, var(--green) 10%, transparent);   color: var(--green); }
.badge-noleggi-rifiutato        { background: color-mix(in srgb, var(--red) 10%, transparent);   color: var(--red); }
.badge-noleggi-annullato        { background: var(--gray5); color: var(--text2); }
.badge-noleggi-urgent           { background: color-mix(in srgb, var(--red) 10%, transparent);   color: var(--red); }

/* ── Attrezzature ──
   Prenotazioni raggruppate per giorno nello stesso riquadro dei task
   (.task-group): intestazione fuori, righe con filo dentro. A sinistra
   l'orario come nell'agenda, al centro cosa e chi, a destra lo stato.
   Nessun colore scritto a mano: verde e arancio sono i token di stato. */
.eq-riga {
  position: relative;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 16px; background: var(--card);
  border-bottom: 1px solid var(--bordo-scheda);
}
.eq-riga:last-child { border-bottom: none; }
/* Da preparare, e tocca a te: la barretta dei task scaduti, in arancio.
   Disegnata sopra la riga, cosi' il testo resta in colonna con le altre. */
.eq-riga-da-fare::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--orange);
}
.eq-orario {
  min-width: 52px; flex-shrink: 0; padding-top: 1px;
  display: flex; flex-direction: column; gap: 2px;
  font-variant-numeric: tabular-nums; line-height: 1.25;
}
.eq-ora-inizio { font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.eq-ora-piccola { font-size: var(--fs-xs); color: var(--text2); white-space: nowrap; }
.eq-ora-fine { font-size: var(--fs-xs); color: var(--text3); }
.eq-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.eq-titolo { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; }
.eq-nome { font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.eq-sede { font-size: var(--fs-xs); color: var(--text3); }
.eq-righine {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px;
  font-size: var(--fs-xs); color: var(--text2);
}
.eq-chi { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; color: var(--text); }
.eq-chi .avatar { width: 20px; height: 20px; font-size: 9px; }
.eq-dettaglio { display: inline-flex; align-items: flex-start; gap: 4px; min-width: 0; line-height: 17px; }
/* Sulla prima riga anche quando il testo va a capo. */
.eq-dettaglio .material-icons-outlined { font-size: 15px; line-height: 17px; color: var(--text3); flex-shrink: 0; }
.eq-nota { font-style: italic; }
/* Stato e cestino sulla stessa riga, a destra. Il cestino e' un pulsante da
   44: si allinea il glifo al bordo come nelle schede Noleggi, e si centra
   verticalmente sulla riga del nome. */
.eq-azioni {
  display: flex; align-items: center; gap: 4px;
  flex-shrink: 0; margin-top: -10px; margin-right: -10px;
}
.eq-azioni > .task-badge, .eq-azioni > .btn-accent-sm { margin-right: 4px; }
.eq-pronto        { background: color-mix(in srgb, var(--green) 12%, transparent);  color: var(--green); }
.eq-da-preparare  { background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange); }
.eq-disattivo     { background: var(--gray5); color: var(--text2); margin-left: 4px; vertical-align: 1px; }
.eq-pronto .material-icons-outlined,
.eq-da-preparare .material-icons-outlined { font-size: 14px; }
.eq-pronto-tasto { border: none; cursor: pointer; font-family: inherit; transition: background var(--transition); }
.eq-pronto-tasto:hover { background: color-mix(in srgb, var(--green) 22%, transparent); }
/* Eliminare un attrezzo dall'editor e' un link piccolo, mai un pulsante accanto a Salva. */
.link-elimina {
  background: none; border: none; padding: 2px 0; cursor: pointer;
  font-family: inherit; text-decoration: underline; text-underline-offset: 2px;
  font-size: 13px; color: var(--danger);
}

/* La coda "da preparare": non un filtro fra i filtri, ma un lavoro che tocca a
   te. Sta sopra l'elenco, solo per chi cura la manutenzione, nel velo arancio
   dei contrassegni "da preparare". */
.eq-coda {
  display: flex; align-items: center; gap: 12px; width: 100%;
  margin: 0 0 16px; padding: 12px 16px; text-align: left;
  font-family: inherit; color: var(--text); cursor: pointer;
  background: color-mix(in srgb, var(--orange) 8%, var(--card));
  border: 1px solid color-mix(in srgb, var(--orange) 28%, transparent);
  border-radius: var(--r-md); transition: background var(--transition);
}
button.eq-coda:hover { background: color-mix(in srgb, var(--orange) 14%, var(--card)); }
.eq-coda.attiva { cursor: default; }
.eq-coda-segno {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--orange) 16%, transparent); color: var(--orange);
}
.eq-coda-segno .material-icons-outlined { font-size: 20px; }
.eq-coda-testo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.eq-coda-testo strong { font-size: var(--fs-base); font-weight: 600; }
.eq-coda-testo span { font-size: var(--fs-xs); color: var(--text2); }
.eq-coda-azione {
  display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0;
  background: none; border: none; padding: 4px 0; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--accent);
}
.eq-coda-azione .material-icons-outlined { font-size: 18px; }

/* Scheda appuntamento: gli attrezzi riservati come chip, con la ✕ per toglierli. */
.apt-eq { margin-bottom: 16px; }
.apt-eq > .field-label { display: flex; align-items: center; gap: 4px; }
.apt-eq > .field-label .material-icons-outlined { font-size: 16px; color: var(--text3); }
.apt-eq-lista { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.apt-eq-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 4px 4px 12px; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
  border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
  font-size: 13px; font-weight: 600; color: var(--text);
}
.apt-eq-chip > .material-icons-outlined { font-size: 16px; color: var(--accent); }
.apt-eq-chip-tag { font-size: var(--fs-xs); font-weight: 500; color: var(--text3); }
.apt-eq-chip.occupato {
  background: color-mix(in srgb, var(--red) 8%, var(--card));
  border-color: color-mix(in srgb, var(--red) 30%, transparent);
}
.apt-eq-chip.occupato > .material-icons-outlined,
.apt-eq-chip.occupato .apt-eq-chip-tag { color: var(--red); }
.apt-eq-chip-togli {
  width: 24px; height: 24px; border-radius: 50%; border: none; background: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text3); cursor: pointer; transition: background var(--transition);
}
.apt-eq-chip-togli:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
.apt-eq-chip-togli .material-icons-outlined { font-size: 16px; }
.apt-eq-avviso {
  display: flex; align-items: flex-start; gap: 4px; margin: 8px 0 0;
  font-size: 12px; line-height: 17px; color: var(--orange);
}
.apt-eq-avviso .material-icons-outlined { font-size: 15px; line-height: 17px; }
.apt-eq-scelta { margin: 8px 0 0; }
.apt-eq-nota { margin-top: 8px; }
.apt-eq-link {
  background: none; border: none; padding: 0; cursor: pointer; font-family: inherit;
  font-size: inherit; font-weight: 600; color: var(--accent);
}

/* Impostazioni → Attrezzature: nome sopra, dettagli sotto. Nella riga
   standard (nome e pillola affiancati) i dettagli lunghi stringevano il nome
   fino a spezzarlo su due righe. */
.apt-admin-row-info.eq-admin-info { flex-direction: column; align-items: flex-start; gap: 2px; padding: 4px 0; }
.eq-admin-info .apt-admin-row-meta { background: none; padding: 0; line-height: 1.45; }

/* Modale "Nuova prenotazione": ritiro e riconsegna come due passi. */
.eq-suggerimento { margin-top: 8px; line-height: 1.5; }
.eq-suggerimento .material-icons-outlined { font-size: 14px; vertical-align: -2px; }
.eq-intervallo-titolo {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  font-size: 13px; font-weight: 600; color: var(--text);
}
.eq-intervallo-titolo .material-icons-outlined { font-size: 16px; color: var(--text3); }
.eq-toggle > span { display: inline-flex; align-items: center; gap: 8px; }
.eq-toggle .material-icons-outlined { font-size: 18px; color: var(--text3); }
.eq-toggle-nota { margin-top: 4px; }
.eq-esito-lista {
  margin: 12px 0 4px; padding: 8px 12px 8px 32px; text-align: left;
  background: var(--gray6); border-radius: var(--r-sm);
  font-size: 13px; line-height: 1.6; color: var(--text2);
  max-height: 220px; overflow-y: auto;
}

/* Agenda → Servizi: la coda di attrezzi del servizio. */
.svc-eq .apt-tpl-hint { margin-top: 2px; }
.svc-eq-lista { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.svc-eq-riga {
  display: flex; align-items: center; gap: 4px;
  padding: 2px 2px 2px 12px; background: var(--card);
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-sm);
}
.svc-eq-num {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; margin-right: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gray6); color: var(--text3); font-size: var(--fs-xs); font-weight: 600;
}
.svc-eq-nome { flex: 1; min-width: 0; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.svc-eq-riga .btn-icon:disabled { opacity: .3; cursor: default; }
.svc-eq-aggiungi {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 8px; padding: 4px 0;
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: 13px; font-weight: 600; color: var(--accent);
}
.svc-eq-aggiungi .material-icons-outlined { font-size: 18px; }
.svc-eq-scelta { margin: 8px 0 0; }

@media (max-width: 600px) {
  .eq-riga { padding: 12px; }
  .eq-orario { min-width: 44px; }
}

/* ── Pagine admin (Servizi / Sedi / Tecnici) ── */
.apt-admin-page {
  flex: 1; overflow-y: auto; padding: 20px 16px;
}
.apt-admin-wrap {
  max-width: 680px; margin: 0 auto; display: flex; flex-direction: column; gap: 16px;
}
.apt-admin-card {
  background: var(--card); border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden;
}
.apt-admin-row {
  display: flex; align-items: center; justify-content: space-between;
  /* Era 12/16: stesso trattamento di .list-row per la densita' §9. */
  padding: 8px 12px; border-bottom: 1px solid var(--border); gap: 8px;
}
.apt-admin-row:last-child { border-bottom: none; }
.apt-admin-row-info { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
/* 14 -> 13 (--fs-sm): stesso gradino di .list-row-title per la stessa ragione. */
.apt-admin-row-name { font-size: var(--fs-sm); font-weight: 500; color: var(--text); }
.apt-admin-row-meta {
  font-size: 12px; color: var(--text3);
  background: var(--bg); padding: 2px 8px; border-radius: var(--r-md);
}
.apt-admin-row-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* Non solo dentro le righe admin (Sedi/Servizi): stessa classe è già usata anche
   nell'header di Signage e nelle nuove schede di dettaglio Cliente/Medico — quella
   restrizione lasciava quei pulsanti col colore normale invece che rosso. */
.btn-icon.danger { color: var(--danger); }
.apt-admin-empty { color: var(--text3); font-size: 13px; padding: 16px; margin: 0; }

/* ── Documenti: 3 livelli — dipendente > anno > documento — con peso visivo
   decrescente (padding, font, colore) così la gerarchia si legge a colpo d'occhio ── */
.doc-emp-card {
  background: var(--card); border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden; margin-bottom: 10px;
}
.doc-emp-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; gap: 8px; cursor: pointer;
}
.doc-emp-header:hover { background: var(--gray6); }
.doc-emp-name { font-size: var(--fs-md); font-weight: 600; color: var(--text); } /* 15px non e uno dei sette corpi ammessi: e il titolo della card dipendente, quindi fs-md. */
.doc-emp-summary { font-size: var(--fs-xs); color: var(--text3); margin-top: 1px; } /* Mezzo pixel vietato: e una didascalia, fs-xs. */
.doc-emp-body { border-top: 1px solid var(--border); }
.doc-chevron { color: var(--text3); transition: transform .2s; flex-shrink: 0; }

.doc-year-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 16px 8px 44px; gap: 8px; cursor: pointer;
  background: var(--gray6); border-top: 1px solid var(--border);
}
.doc-year-header:first-child { border-top: none; }
.doc-year-header:hover { filter: brightness(0.97); }
.doc-year-icon { color: var(--text3); font-size: 16px; }
.doc-year-label { font-size: var(--fs-sm); font-weight: 600; color: var(--text2); letter-spacing: .2px; } /* Mezzo pixel vietato: stessa taglia della riga documento sotto, la gerarchia resta nel peso. */
.doc-year-count {
  /* Mezzo pixel vietato (paragrafo 10.3) e sotto la taglia minima: sale a fs-micro. */
  font-size: var(--fs-micro); color: var(--text3); background: var(--card);
  padding: 1px 7px; border-radius: var(--r-pill);
}

.doc-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 16px 9px 44px; gap: 8px; border-top: 1px solid var(--border);
  position: relative;
}
/* Linea verticale che collega visivamente i documenti al loro anno, sotto la riga anno */
.doc-row::before {
  content: ''; position: absolute; left: 30px; top: 0; bottom: 0; width: 1px; background: var(--border);
}
.doc-row-icon { color: var(--text3); font-size: 15px; }
.doc-row-label { font-size: var(--fs-sm); font-weight: 400; color: var(--text2); } /* Mezzo pixel vietato: stessa taglia della riga anno sopra. */
.doc-test-badge {
  /* Era var(--warning, #FF9500) col bianco sopra: nome inesistente, arancio di
     iOS cablato, e in tema scuro il bianco ci spariva sopra. */
  background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange);
  font-size: 10px; font-weight: 700;
  padding: 2px 6px; border-radius: var(--r-pill); vertical-align: middle;
}
.apt-admin-form {
  background: var(--card); border-radius: var(--radius);
  border: 1px solid var(--border); padding: 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.apt-admin-form .form-group { margin: 0; }
.apt-admin-form .btn { align-self: flex-start; }

/* Template email (Conferme e Promemoria) */
.apt-tpl-vars {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 8px 12px; font-size: 12px;
}
.apt-tpl-vars-label { font-weight: 600; color: var(--text3); text-transform: uppercase; font-size: 11px; letter-spacing: .03em; margin-right: 4px; }
.apt-tpl-vars code {
  background: var(--bg); color: var(--accent); border-radius: var(--r-sm);
  padding: 2px 8px; font-size: 12px; font-family: 'SF Mono', Menlo, monospace;
}
.apt-tpl-card { padding: 0; }
.apt-tpl-card-header {
  display: flex; align-items: center; gap: 10px;
  padding: 16px; border-bottom: 1px solid var(--border);
  background: var(--bg); color: var(--accent);
}
.apt-tpl-card-header h3 { margin: 0; font-size: var(--fs-md); font-weight: 600; color: var(--text); flex: 1; }
.apt-tpl-card-body { padding: 16px; }
.apt-tpl-textarea { font-family: 'SF Mono', Menlo, monospace; font-size: 13px; line-height: 1.5; }
.apt-tpl-divider { height: 1px; background: var(--border); margin: 4px 0 16px; }

/* Sotto-servizio dentro una stessa scheda (es. Dropbox/Aruba Drive, WhatsApp/SMS):
   li isola visivamente così i campi dei due servizi non sembrano un unico blocco.
   Era una scheda a fondo grigio dentro la scheda Integrazioni — esattamente il
   caso "scheda dentro scheda" del §9: appiattita sul fondo della scheda che la
   contiene, l'isolamento resta leggibile col bordo + striscia colorata. */
.svc-subcard {
  border: 1px solid var(--border); border-left-width: 4px; border-left-style: solid;
  border-radius: var(--r-md); background: var(--card);
  padding: 16px; margin-bottom: 16px;
}
.svc-subcard-header { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.svc-subcard-header .material-icons-outlined { font-size: 18px; }
.svc-subcard-header strong { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.svc-subcard-active {
  margin-left: auto; font-size: var(--fs-micro); font-weight: 700; letter-spacing: .06em;
  color: var(--green); background: color-mix(in srgb, var(--green) 13%, transparent);
  /* Era --r-lg, cioe' il raggio delle SCHEDE su un'etichetta alta 16 pixel:
     sembrava una scheda in miniatura invece di un contrassegno. */
  padding: 2px 8px; border-radius: var(--r-pill);
}
.apt-tpl-hint { font-size: 12px; color: var(--text3); margin: 0; overflow-wrap: break-word; }
/* L'ICONA DI UNA NOTA E' LA COSA MENO IMPORTANTE DELLA RIGA MENO IMPORTANTE.
   Qui non c'era nessuna regola, quindi valeva il corpo di base — VENTI pixel,
   accanto a un testo di dodici. Nel modale dell'appuntamento la macchinina
   della trasferta era piu' grande dell'icona del tecnico che segue il cliente,
   e l'omino di "Inserito da" pure: due informazioni di servizio che tiravano
   l'occhio piu' del dato principale (25/09/2026).
   Quattordici pixel: si vede che c'e', non si vede per prima. Il colore lo
   prende gia' dalla nota (text3), quindi non si tocca — se una nota colora la
   sua icona apposta, quel colore resta. */
.apt-tpl-hint .material-icons-outlined {
  font-size: 14px;
  /* L'allineamento "middle" della regola di base lascia l'icona 1,67px sotto il
     centro della riga: accanto a un testo da 12px si vede, e la macchinina
     della trasferta sembrava appoggiata piu' in basso della frase.
     Il valore e' MISURATO su questa combinazione (12px di testo, riga 17,4,
     icona 14): porta lo scarto a 0,33px. Se un giorno cambia il corpo della
     nota, va rimisurato — non e' un numero magico, e' la soluzione di
     quell'equazione li'. */
  vertical-align: -2px;
}
.apt-tpl-hint code { background: var(--bg); border-radius: var(--r-xs); padding: 1px 8px; font-size: 11px; word-break: break-all; }

/* ── Schede orizzontali per pagine Impostazioni con più sotto-sezioni (13/08/2026,
   Integrazioni/Ortopedia/Quiz/Agenda) — stesso linguaggio cromatico di segTabBar
   (pieno accent quando attiva) ma a larghezza NATURALE con scroll orizzontale
   invece di segmenti forzati a larghezza uguale: con 4-5 etichette, alcune lunghe
   ("Conferme e Promemoria"), dividerle in parti identiche le strizzava o le
   mandava a capo. Puro show/hide lato client — nessun rifetch al cambio scheda. */
.settings-tabs {
  display: flex; gap: 6px; overflow-x: auto;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px; -ms-overflow-style: none; scrollbar-width: none;
}
.settings-tabs::-webkit-scrollbar { display: none; }
/* Le schede stanno sullo stesso asse del contenuto che aprono. Prima partivano
   dal bordo sinistro mentre sotto la scheda era centrata: due cose incolonnate
   con due assi diversi si leggono come due pezzi di pagine diverse.
   Si centra con i margini automatici del primo e dell'ultimo, non con
   justify-content: center — dentro un contenitore che scorre di lato, quello
   rende irraggiungibile la prima scheda appena le voci non ci stanno. I margini
   automatici, quando lo spazio finisce, valgono zero da soli: centrato se c'e'
   posto, allineato a sinistra e scorribile se non ce n'e'. */
.settings-tab-btn:first-child { margin-left: auto; }
.settings-tab-btn:last-child  { margin-right: auto; }
.settings-tab-btn {
  flex-shrink: 0; white-space: nowrap;
  font-family: inherit; font-size: 14px; font-weight: 400;
  padding: 10px 16px; border: none; background: none; cursor: pointer;
  color: var(--text3); border-radius: var(--r-sm) var(--r-sm) 0 0;
  position: relative; top: 1px; transition: color .15s, background .15s;
}
.settings-tab-btn:hover { color: var(--text); background: var(--gray6); }
/* La sottolineatura resta un box-shadow inset (non un'ombra di profondita': e'
   un tratto netto di 2.5px pensato per fondersi esattamente col bordo inferiore
   di .settings-tabs, sfruttando il "top:1px" qui sopra). Un vero border-bottom
   cambierebbe l'altezza della sola scheda attiva di 2.5px: si annota e si lascia. */
.settings-tab-btn.active { color: var(--accent); font-weight: 500; box-shadow: inset 0 -2.5px 0 var(--accent); }
.settings-tab-panel { display: none; }
.settings-tab-panel.active { display: block; }
/* TUTTE LE SCHEDE DELLE IMPOSTAZIONI SONO LARGHE UGUALI: quanto la testata,
   come Ortopedia. Servizi, Sedi, Tecnici, Conferme e Promemoria e Prenotazioni
   dell'Agenda sono nate come sotto-pagine a tutto schermo (aptRender…Page) e si
   portavano dietro la loro cornice: 16px di rientro in piu' e una colonna da
   680 centrata. Aprendo una scheda dopo l'altra il contenuto si allargava e
   stringeva — segnalato il 14/09/2026. Qui dentro la cornice si spegne; fuori
   dalle impostazioni (le pagine degli orari) resta com'era.
   14px sopra: lo stesso stacco dalle schede che ha Ortopedia (gap del suo
   contenitore), cosi' anche il primo elemento parte alla stessa altezza. */
.settings-tab-panel > .apt-admin-page { padding: 14px 0 0; overflow: visible; }
.settings-tab-panel .apt-admin-wrap { max-width: none; margin: 0; }

/* Anteprima testo estratto da una pagina (Documenti > Cedolini multipli) */
.doc-proposal-snippet {
  /* Mezzo pixel vietato (paragrafo 10.3): e una didascalia, fs-xs. */
  font-size: var(--fs-xs); color: var(--text3); background: var(--bg); border-radius: var(--r-sm);
  padding: 6px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: flex; align-items: center; gap: 5px;
}

/* Tecnici */
.apt-tech-list { display: flex; flex-direction: column; gap: 6px; }
.apt-tech-row {
  background: var(--card); border-radius: var(--radius);
  border: 1px solid var(--border); overflow: hidden;
  transition: box-shadow .15s, opacity .15s;
}
.apt-tech-dragging { opacity: .45; box-shadow: 0 8px 24px rgba(0,0,0,.18); }
.apt-tech-drag-over { box-shadow: 0 0 0 2px var(--accent); }
.apt-tech-row-header {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; cursor: pointer;
  user-select: none;
}
.apt-tech-row-header:hover { background: var(--bg); }
.apt-tech-drag-handle {
  color: var(--text3); cursor: grab; flex-shrink: 0;
  display: flex; align-items: center; touch-action: none;
}
.apt-tech-drag-handle .material-icons-outlined { font-size: 20px; }
.apt-tech-row-name { flex: 1; font-size: 15px; font-weight: 600; color: var(--text); }
.apt-tech-row-chevron { color: var(--text3); display: flex; transition: transform .2s; }
.apt-tech-row-chevron .material-icons-outlined { font-size: 20px; }
.apt-tech-body { border-top: 1px solid var(--border); }
.apt-admin-hint {
  font-size: 12px; color: var(--text3); display: flex; align-items: center; gap: 4px;
  margin: 0 0 12px;
}
.apt-admin-hint .material-icons-outlined { font-size: 15px; }
.apt-tech-sections { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.apt-tech-section {
  padding: 14px 16px;
  border-right: 1px solid var(--border);
}
.apt-tech-section:last-child { border-right: none; }
@media (max-width: 600px) {
  .apt-tech-sections { grid-template-columns: 1fr; }
  .apt-tech-section { border-right: none; border-bottom: 1px solid var(--border); }
  .apt-tech-section:last-child { border-bottom: none; }
}
.apt-tech-section-title {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--text3); margin-bottom: 10px;
}
.apt-tech-svc-form {
  display: flex; flex-direction: column; gap: 6px; margin-top: 8px;
}
.apt-checkbox-label {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; cursor: pointer; color: var(--text2);
}
.apt-checkbox-label input { cursor: pointer; }
.apt-loading { color: var(--text3); font-size: 13px; }

/* Tabella orari */
.apt-sched-table {
  width: 100%; border-collapse: collapse; font-size: 12px;
}
.apt-sched-table th {
  text-align: left; color: var(--text3); font-weight: 600;
  padding: 4px 8px; border-bottom: 1px solid var(--border);
}
.apt-sched-table td { padding: 4px 8px; color: var(--text2); }
.apt-sched-table tr:last-child td { border-bottom: none; }

/* Orari tecnico — pagina intera */
/* colonne: [label 90px] [time 100px] [sep 14px] [time 100px] [sede 1fr] [online auto] */
.apt-sched-page-wrap {
  max-width: 780px; margin: 0 auto; display: flex; flex-direction: column; gap: 8px;
}
.apt-sched-copy-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-xs);
  padding: 8px 12px; margin-bottom: 8px;
}
.apt-sched-copy-lbl { font-size: 13px; font-weight: 600; color: var(--text2); display: flex; align-items: center; gap: 5px; }
.apt-sched-copy-lbl .material-icons-outlined { font-size: 16px; color: var(--accent); }
.apt-sched-copy-bar select { font-size: 13px; padding: 6px 10px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--card); color: var(--text); }
.apt-sched-col-headers,
.apt-sched-session {
  display: grid;
  grid-template-columns: 90px 100px 14px 100px 1fr auto;
  align-items: center;
  gap: 8px;
}
.apt-sched-col-headers {
  padding: 0 16px 8px;
  border-bottom: 2px solid var(--border);
}
.apt-sched-col-headers span {
  font-size: 11px; font-weight: 500; text-transform: uppercase;
  color: var(--text3); letter-spacing: .04em;
}
.apt-sched-days {
  display: flex; flex-direction: column; gap: 8px;
}
.apt-sched-day-block {
  border-radius: var(--r-md); overflow: hidden;
  border: 1px solid var(--border);
}
.apt-sched-day-header-row {
  display: flex; align-items: center; justify-content: space-between;
  position: relative; background: var(--bg); padding-right: 8px;
}
.apt-sched-day-header {
  display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
  padding: 8px 12px; cursor: pointer; font-weight: 600; font-size: 14px;
  user-select: none;
}
.apt-sched-day-header input[type=checkbox] { cursor: pointer; width: 15px; height: 15px; }
.apt-sched-day-header-row .btn-icon { flex-shrink: 0; color: var(--text3); }
.apt-sched-sessions { background: var(--card); }
.apt-sched-session {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
}
.apt-sched-session:first-child { border-top: none; }
.apt-sched-session-lbl {
  font-size: 12px; color: var(--text3); font-weight: 500;
}
.apt-sched-sep {
  text-align: center; color: var(--text3); font-size: 13px;
}
.apt-sched-input {
  width: 100%; min-width: 0; font-size: 13px;
  padding: 6px 8px; border: 1px solid var(--border);
  border-radius: var(--r-sm); background: var(--card); color: var(--text);
  transition: border-color .15s;
}
.apt-sched-input:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent); }
.apt-sched-input:disabled {
  opacity: .4; background: var(--bg); cursor: not-allowed;
}
.apt-sched-online-lbl {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text2); cursor: pointer;
  white-space: nowrap;
}
.apt-sched-online-lbl input { cursor: pointer; width: 14px; height: 14px; }
.apt-sched-online-lbl input:disabled { opacity: .4; cursor: not-allowed; }
.apt-sched-field { min-width: 0; }
.apt-sched-mobile-lbl { display: none; }

/* Riorganizza la griglia orari tecnico in colonna su mobile: niente colonne nascoste */
@media (max-width: 700px) {
  .apt-sched-col-headers { display: none; }
  .apt-sched-session {
    display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  }
  .apt-sched-session-lbl { font-size: 13px; font-weight: 600; color: var(--text); }
  .apt-sched-sep { display: none; }
  .apt-sched-field { display: flex; flex-direction: column; gap: 4px; }
  .apt-sched-mobile-lbl {
    display: block; font-size: 11px; font-weight: 500; text-transform: uppercase;
    color: var(--text3); letter-spacing: .03em;
  }
  .apt-sched-input { width: 100%; }
  .apt-sched-online-lbl { padding-top: 2px; }
}

/* Mobile */
@media (max-width: 640px) {
  /* ── LA TESTATA SU TELEFONO ────────────────────────────────────────────────
     Il fondo bianco era rimasto qui dentro da prima: su schermo grande i comandi
     stanno sul grigio della pagina come nel Piano Ferie, e su telefono restava
     una fascia bianca dietro il mese che non somigliava a niente. Il fondo lo
     mette la riga intera (.apt-testata), come da desktop. */
  /* Il margine SOTTO conta piu' di quello che sembra: la riga dei comandi sta
     appiccicata in cima e il foglio le passa sotto, quindi fra la scatola della
     data e gli appuntamenti non c'e' nessuno stacco naturale — se non glielo si
     da' qui, scorrendo gli appuntamenti arrivano a filo della scatola.
     Su schermo grande erano gia' 18px; su telefono era rimasto zero. */
  .apt-week-nav { padding: 4px 8px 14px; gap: 6px; background: transparent; }
  /* (l'appiccicatura e la sfocatura arrivano dalla regola generale) */

  /* ── LA SCHEDA SU TELEFONO ─────────────────────────────────────────────────
     Niente conto delle colonne intere: qui si vede UN tecnico alla volta, con la
     sua barra di navigazione dedicata, e non c'e' niente da incolonnare.
     Il conto la faceva lo stesso, dando alla scheda una larghezza calcolata su
     misure da schermo grande: la tavola dentro restava piu' larga e gli
     appuntamenti finivano tagliati dal bordo destro — si vedeva perche' perdevano
     l'angolo arrotondato di chiusura, nascosto sotto il bordo.
     Qui la scheda e' larga quanto lo schermo e la tavola larga quanto la scheda. */
  /* Il margine si riscrive per intero, quindi va ripetuto anche lo stacco dalla
     data: con "0 12px 16px" si cancellava il margin-top messo piu' su, e la
     scheda tornava attaccata ai comandi (misurato: aria 0px). */
  .apt-scheda { width: auto; margin: 10px 12px 16px; }
  .apt-planner-scroll { width: 100%; min-width: 0; }
  .apt-day-btn { min-width: 36px; padding: 4px 4px; }
  .apt-day-num { font-size: 14px; }
  .apt-slot { min-width: 110px; }
  .apt-col-th { min-width: 110px; }
  /* Su mobile la tabella ha un solo tecnico → 2 colonne (orario + appuntamenti) per
     ~150px dichiarati, ma min-width:100% la costringe a riempire lo schermo: con
     table-layout:fixed lo spazio extra viene spalmato su TUTTE le colonne a larghezza
     fissa, gonfiando anche quella dell'orario (~100px reali) — era questo il "vuoto
     a sinistra dell'ora", non il vecchio disallineamento 36/40px. Con width:auto la
     colonna appuntamenti assorbe da sola tutto lo spazio extra e l'orario resta 40px. */
  .apt-time-cell { width: 40px; min-width: 40px; font-size: 11px; }
  .apt-time-th { width: 40px; min-width: 40px; }
  /* CAUSA VERA dello "spazio a sinistra dell'ora" (verificata sperimentalmente in
     un browser a 375px): width:max-content sulla tabella manda in tilt il
     table-layout:fixed — quando min-width:100% la costringe a riempire lo schermo,
     le larghezze dichiarate vengono ridistribuite IN PROPORZIONE (52:200 → la
     colonna orario diventava ~77px) invece di essere rispettate. Qualsiasi width
     sulle celle era quindi inutile: veniva riscalata comunque. Su mobile c'è un
     solo tecnico, la tabella non deve mai superare lo schermo: width:100% pieno,
     e le colonne tornano a rispettare i 40px dichiarati (misurato: 77px → 40px). */
  .apt-grid { width: 100%; }
  .apt-col-th { width: auto; }
  .apt-appt-client { font-size: 13px; }

  /* Pulsante unico azioni sulla card: area tap generosa */
  .apt-appt-btn-more { width: 34px; height: 34px; }
  .apt-appt-btn-more .material-icons-outlined { font-size: 19px; }

  /* Su mobile l'header sticky lascia il posto alla nav tecnico dedicata sotto */
  .apt-grid thead th { position: static; }
  .apt-mobile-tech-nav { position: sticky; top: 0; z-index: 15; }
}

/* ── Editor PDF Ortopedia (crocette/testo) ── */
.ortho-ed-tool {
  display: inline-flex; align-items: center; gap: 6px;
  height: 40px; padding: 0 16px; border-radius: var(--r-full); font-size: var(--fs-sm); font-weight: 500;
  background: var(--ortho-toolbar-bg); color: var(--ortho-toolbar-fg); border: none; cursor: pointer;
  font-family: inherit; white-space: nowrap;
}
.ortho-ed-tool.active { background: var(--accent); color: var(--su-accento); }
.ortho-mark {
  position: absolute; transform: translate(-50%,-50%); cursor: pointer;
  user-select: none; pointer-events: all;
}
.ortho-mark-x {
  color: var(--ortho-ann-red); font-weight: 600; display: flex; align-items: center; justify-content: center;
}
/* Dimensione ereditata dal font-size inline sul wrapper .ortho-mark-x (scalato con lo
   zoom in JS) — prima era fissa a 22px, quindi restava sempre uguale sullo schermo
   invece di seguire lo zoom della pagina, come ci si aspetterebbe da un segno "sulla carta". */
.ortho-mark-x .material-icons-outlined { font-size: inherit; font-weight: 600; }
.ortho-mark-text {
  color: var(--ortho-ann-ink); font-weight: 500; background: var(--ortho-ann-hl);
  padding: 1px 4px; border-radius: 3px; white-space: nowrap;
}
/* Lascia che il dito scorra la pagina (pan) — solo un tocco fermo mette un segno,
   distinto dal trascinamento via JS in orthoEditorBindStageGestures(). Il valore
   granulare "pan-x pan-y" ha supporto incoerente su iOS Safari (spesso finisce per
   bloccare lo scroll invece di permetterlo su entrambi gli assi) — "auto" è molto
   più affidabile lì. Lo zoom nativo della pagina resta comunque disabilitato dal
   tag viewport (user-scalable=no), quindi non entra in conflitto col pinch gestito
   via JS in questo stesso editor. */
#ortho-ed-marks { touch-action: auto; }

/* ── Visualizzatore a tutto schermo: foto e PDF in sola lettura ─────────────
   fileViewerOpenImage (foto di task e valutazioni) e orthoOpenEditor in sola
   lettura (PDF, anche via openPdfOverlay per documenti e file condivisi).
   Era "← Chiudi" a sinistra su una banda nera piatta: l'unico posto dell'app
   dove non si chiudeva con la X in alto a destra, e l'aria di vecchio.
   Sempre scuro in entrambi i temi (una foto o un foglio bianco ci si leggono
   meglio), con un guscio leggero: un velo appena chiaro e un filo, bottoni
   tondi traslucidi, il titolo a sinistra e la X sempre ULTIMA a destra.
   L'editor dei moduli (Salva, Crocetta, Testo) non passa di qui. */
.media-viewer { background: #151517 !important; }
/* Non piu' a tutto schermo: un pannello a 3/4, centrato, sul velo sfocato dei
   modal — con i loro stessi angoli, ombra ed entrata. L'editor dei moduli PDF
   (senza .media-viewer) resta a tutto schermo: li' si lavora, serve spazio. */
.media-viewer {
  inset: 12.5vh 12.5vw !important;
  border-radius: var(--r-lg); overflow: hidden;
  border: 1px solid rgba(255,255,255,.08); box-shadow: var(--shadow-2);
  animation: media-viewer-entra .2s ease both;
}
@keyframes media-viewer-entra {
  from { opacity: 0; transform: translateY(20px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.media-viewer-velo {
  position: fixed; inset: 0; z-index: 9999;
  background: var(--velo-sfondo);
  -webkit-backdrop-filter: var(--velo-sfocatura); backdrop-filter: var(--velo-sfocatura);
  opacity: 0; transition: opacity .2s;
}
.media-viewer-velo.open { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .media-viewer { animation: none; }
  .media-viewer-velo { transition: none; }
}
/* Sul telefono una foto a 3/4 dello schermo e' un francobollo: li' torna a
   tutto schermo, e il velo non serve. */
@media (max-width: 600px) {
  .media-viewer { inset: 0 !important; border-radius: 0; border: 0; box-shadow: none; }
  .media-viewer-velo { display: none; }
}
.media-viewer-header, .media-viewer-footer {
  display: flex; align-items: center; gap: 6px; flex-shrink: 0;
  background: rgba(255,255,255,.04);
}
.media-viewer-header {
  padding: calc(env(safe-area-inset-top) + 10px) 12px 10px 18px;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.media-viewer-footer { border-top: 1px solid rgba(255,255,255,.08); }
.media-viewer-title {
  flex: 1; min-width: 0; font-size: 14px; font-weight: 500; color: rgba(255,255,255,.92);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.media-viewer-azioni { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.media-viewer-btn {
  width: 38px; height: 38px; flex-shrink: 0; padding: 0; border: none; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; text-decoration: none;
  background: rgba(255,255,255,.08); color: #fff; transition: background .15s;
}
.media-viewer-btn:hover, .media-viewer-btn:active { background: rgba(255,255,255,.18); }
.media-viewer-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.media-viewer-btn:disabled { opacity: .5; cursor: default; }
.media-viewer-btn .material-icons-outlined { font-size: 20px; }
/* Foto: zoom e spostamento li gestisce imgViewerInitZoom (rotellina, pizzico,
   doppio tocco, trascinamento). Niente scorrimento nativo qui dentro: si
   contenderebbe il dito con lo spostamento dell'immagine ingrandita. */
.media-viewer-body {
  position: relative; flex: 1; min-height: 0; overflow: hidden; padding: 16px;
  display: flex; align-items: center; justify-content: center;
  touch-action: none;
}
.media-viewer-img {
  max-width: 100%; max-height: 100%; object-fit: contain;
  transform-origin: 0 0; will-change: transform;
  box-shadow: 0 4px 24px rgba(0,0,0,.45);
  cursor: zoom-in; -webkit-user-select: none; user-select: none; -webkit-user-drag: none;
}
.media-viewer-img.ingrandita { cursor: grab; }
.media-viewer-img.trascina   { cursor: grabbing; }
.media-viewer-img.animata    { transition: transform .22s cubic-bezier(.2, .8, .2, 1); }
@media (prefers-reduced-motion: reduce) { .media-viewer-img.animata { transition: none; } }
/* A che percentuale si e': compare mentre si ingrandisce e poi sparisce. */
.media-viewer-zoom {
  position: absolute; left: 50%; bottom: calc(env(safe-area-inset-bottom) + 18px);
  transform: translateX(-50%); pointer-events: none;
  padding: 5px 12px; border-radius: var(--r-full);
  font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums;
  background: rgba(0,0,0,.55); color: #fff; backdrop-filter: blur(8px);
  opacity: 0; transition: opacity .2s;
}
.media-viewer-zoom.visibile { opacity: 1; }
/* Formato che il dispositivo non sa mostrare (HEIC su computer): una frase
   ordinata col modo di uscirne, non un errore nudo. */
.media-viewer-vuoto {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  max-width: 34ch; text-align: center; font-size: 13px; line-height: 1.5; color: rgba(255,255,255,.65);
}
.media-viewer-vuoto .material-icons-outlined { font-size: 40px; color: rgba(255,255,255,.3); margin-bottom: 4px; }
.media-viewer-vuoto strong { font-size: 16px; font-weight: 600; color: #fff; }

/* ── Card allegato PDF (form nuova valutazione + dettaglio) ── */
.ortho-att-card {
  display: flex; align-items: center; gap: 12px;
  background: var(--card); border: 1.5px solid var(--border); border-radius: var(--r-md);
  padding: 12px 16px; margin-bottom: 12px;
}
.ortho-att-card.ortho-att-done { border-color: var(--green); }
.ortho-att-icon {
  width: 40px; height: 40px; border-radius: var(--r-md); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); color: var(--text3);
}
.ortho-att-card.ortho-att-done .ortho-att-icon { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.ortho-att-body { flex: 1; min-width: 0; }
.ortho-att-title-input {
  width: 100%; border: none; background: none; padding: 2px 0;
  font-size: 14px; font-weight: 600; color: var(--text); font-family: inherit;
  border-bottom: 1px solid transparent;
}
.ortho-att-title-input:focus { outline: none; border-bottom-color: var(--accent); }
.ortho-att-title-input::placeholder { font-weight: 400; color: var(--text3); }
.ortho-att-status {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 4px;
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: var(--r-full);
  background: var(--gray5); color: var(--text3);
}
.ortho-att-status .material-icons-outlined { font-size: 13px; }
.ortho-att-card.ortho-att-done .ortho-att-status { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.ortho-att-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.ortho-att-compile-btn {
  display: inline-flex; align-items: center; gap: 4px;
  height: 32px; padding: 0 12px; border-radius: var(--r-sm); border: none; cursor: pointer;
  font-size: var(--fs-sm); font-weight: 500; font-family: inherit; white-space: nowrap;
  background: transparent; color: var(--accent);
}
.ortho-att-compile-btn .material-icons-outlined { font-size: 16px; }



/* ═══════════════════════════════════════════════
   QUIZ AZIENDALE — coerente nella struttura (card, bottoni, radius) col resto
   dell'app, ma più giocoso nei colori/animazioni: è un momento di svago, non lavoro.
═══════════════════════════════════════════════ */
/* ── Hub Gioca/Classifiche/Duelli: stesso schema flex di .main-content (colonna,
   overflow:hidden), il figlio scrollabile resta .quiz-page invariato — vedi
   renderQuizView/quizRenderHubTab in app.js. ── */
.quiz-hub-shell { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.quiz-hub-tabs { padding: 16px 16px 0; }
.quiz-hub-body { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.quiz-page { flex: 1; overflow-y: auto; padding: 20px 16px 40px; display: flex; justify-content: center; }
.quiz-mascot-card, .quiz-game-card {
  max-width: 480px; width: 100%; background: var(--card); border-radius: var(--r-lg);
  border: 1px solid var(--border);
  padding: 32px 24px; text-align: center; position: relative; overflow: hidden;
}
.quiz-mascot { font-size: 64px; line-height: 1; margin-bottom: 12px; display: inline-block; }
.quiz-anim-bounce { animation: quizBounce 2s ease-in-out infinite; }
.quiz-anim-bounce-fast { animation: quizBounce 0.9s ease-in-out infinite; }
.quiz-anim-sleep { animation: quizSleep 3s ease-in-out infinite; }
@keyframes quizBounce { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-10px) rotate(-4deg); } }
@keyframes quizSleep { 0%,100% { transform: translateY(0); opacity:.85; } 50% { transform: translateY(-4px); opacity:1; } }
.quiz-title { font-size: var(--fs-lg); font-weight: 600; margin: 0 0 8px; color: var(--text); }
.quiz-sub { font-size: 14px; color: var(--text3); margin: 0 0 16px; line-height: 1.5; }
.quiz-streak {
  display: inline-flex; align-items: center; gap: 5px; background: linear-gradient(90deg, var(--orange), var(--red));
  color: var(--su-accento); font-weight: 600; font-size: 13px; padding: 6px 14px; border-radius: var(--r-pill); margin-bottom: 16px;
}
.quiz-play-btn {
  width: auto; padding: 14px 36px; font-size: 16px; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--accent), var(--purple));
}
.quiz-score-big {
  font-size: var(--fs-xl); font-weight: 600; background: linear-gradient(90deg, var(--accent), var(--purple));
  -webkit-background-clip: text; background-clip: text; color: transparent; margin: 4px 0 12px;
}

/* Gameplay */
.quiz-progress { font-size: var(--fs-micro); font-weight: 500; color: var(--text3); text-transform: uppercase; letter-spacing: .5px; margin-bottom: 10px; }
.quiz-timer-bar-wrap { height: 8px; background: var(--gray5); border-radius: 4px; overflow: hidden; margin-bottom: 20px; }
.quiz-timer-bar { height: 100%; width: 100%; background: linear-gradient(90deg, var(--green), #FFCC00, var(--red)); border-radius: 4px; }
.quiz-question-theme {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 500;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); padding: 3px 10px; border-radius: 12px;
  margin-bottom: 10px; text-transform: uppercase; letter-spacing: .3px;
}
.quiz-question { font-size: var(--fs-md); font-weight: 600; color: var(--text); margin-bottom: 20px; line-height: 1.4; }
.quiz-options { display: flex; flex-direction: column; gap: 10px; }
.quiz-option-btn {
  display: block; width: 100%; padding: 14px 16px; border-radius: var(--r-md);
  border: 2px solid var(--border); background: var(--bg); color: var(--text);
  font-size: var(--fs-base); font-weight: 500; font-family: inherit; cursor: pointer;
  text-align: left; transition: all .15s;
}
.quiz-option-btn:hover:not(:disabled) { border-color: var(--accent); background: var(--gray6); }
.quiz-option-btn:disabled { cursor: default; opacity: .7; }
.quiz-option-btn.quiz-correct { border-color: var(--green); background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); opacity: 1; }
.quiz-option-btn.quiz-wrong { border-color: var(--red); background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red); opacity: 1; }
.quiz-feedback {
  margin-top: 16px; font-size: 16px; font-weight: 600; padding: 10px; border-radius: 12px;
  animation: quizPop .3s ease-out;
}
.quiz-feedback-ok { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.quiz-feedback-ko { background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red); }
@keyframes quizPop { from { transform: scale(.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* Confetti */
.quiz-confetti-wrap { overflow: hidden; }
.quiz-confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.quiz-confetti-piece {
  position: absolute; top: -12px; width: 8px; height: 14px; border-radius: 2px;
  animation-name: quizConfettiFall; animation-timing-function: ease-in; animation-fill-mode: forwards;
}
@keyframes quizConfettiFall {
  from { transform: translateY(0) rotate(0deg); opacity: 1; }
  to   { transform: translateY(360px) rotate(540deg); opacity: 0; }
}

/* Classifica */
.quiz-leaderboard-tabs { margin-top: 20px; text-align: left; }
.quiz-lb-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 4px;
  border-bottom: 1px solid var(--border); text-align: left;
}
.quiz-lb-row:last-child { border-bottom: none; }
.quiz-lb-row.quiz-lb-me { background: color-mix(in srgb, var(--accent) 6%, transparent); border-radius: var(--r-md); }
.quiz-lb-rank { width: 26px; text-align: center; font-weight: 600; font-size: 14px; color: var(--text3); flex-shrink: 0; }
.quiz-lb-name { flex: 1; font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quiz-lb-score { font-size: 13px; font-weight: 600; color: var(--accent); flex-shrink: 0; }

/* ── Podio classifica Anno (sbloccata solo a consuntivo, 1° gennaio) — 3 gradini,
   coriandoli (riuso di .quiz-confetti), stesso linguaggio giocoso di fine partita. ── */
.quiz-podium-wrap { position: relative; margin-bottom: 20px; }
.quiz-podium { display: flex; align-items: flex-end; justify-content: center; gap: 10px; padding-top: 10px; }
.quiz-podium-col { display: flex; flex-direction: column; align-items: center; width: 84px; }
.quiz-podium-medal { font-size: 26px; margin-bottom: 2px; }
.quiz-podium-name { font-size: 12px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.quiz-podium-score { font-size: 11px; font-weight: 600; color: var(--accent); margin-bottom: 6px; }
.quiz-podium-step {
  width: 100%; border-radius: var(--r-md) 10px 0 0;
  background: linear-gradient(180deg, var(--gray5), var(--gray6));
}
.quiz-podium-first .quiz-podium-step { height: 92px; background: linear-gradient(180deg, #FFD54A, #FFCC00); }
.quiz-podium-second .quiz-podium-step { height: 68px; background: linear-gradient(180deg, #D8DCE2, #C7CCD3); }
.quiz-podium-third .quiz-podium-step { height: 52px; background: linear-gradient(180deg, #E3A56E, #CD8A52); }

/* ── Duelli 1v1: lista sfide + chip di stato colorati, coerenti con lo stile
   giocoso del resto del modulo ma senza il rosso "azionabile" degli altri badge. ── */
.quiz-duel-row {
  display: flex; align-items: center; gap: 10px; padding: 12px 10px;
  border-bottom: 1px solid var(--border); cursor: pointer; border-radius: var(--r-md);
  transition: background .12s;
}
.quiz-duel-row:hover { background: var(--gray6); }
.quiz-duel-row:last-child { border-bottom: none; }
.quiz-duel-row-mid { flex: 1; min-width: 0; }
.quiz-duel-row-name { font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quiz-duel-row-sub { font-size: 12px; color: var(--text3); margin-top: 1px; }
.quiz-duel-chip {
  display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: var(--r-pill); white-space: nowrap;
}
.quiz-duel-chip-turn { background: linear-gradient(90deg, var(--accent), var(--purple)); color: var(--su-accento); }
.quiz-duel-chip-wait { background: var(--gray5); color: var(--text3); }
.quiz-duel-chip-win  { background: rgba(255,204,0,.14); color: #B8860B; }
.quiz-duel-chip-lose { background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red); }
.quiz-duel-chip-draw { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.quiz-duel-waiting { text-align: center; padding: 20px 10px; font-size: 13px; color: var(--text3); line-height: 1.5; }
.quiz-duel-waiting .material-icons-outlined { display: block; font-size: 28px; margin-bottom: 6px; color: var(--text3); }

/* ── Tutorial animato di lancio — a tutto schermo sopra tutto il resto (stesso
   trucco di #img-viewer-overlay), passi con coriandoli e mascotte che rimbalza. ── */
.quiz-onboard-overlay {
  position: fixed; inset: 0; z-index: 10001;
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent) 94%, transparent), color-mix(in srgb, var(--purple) 94%, transparent));
  display: flex; align-items: center; justify-content: center; padding: 24px;
  animation: quizOnboardFadeIn .25s ease;
}
@keyframes quizOnboardFadeIn { from { opacity: 0; } to { opacity: 1; } }
.quiz-onboard-skip {
  position: absolute; top: calc(env(safe-area-inset-top) + 16px); right: 20px;
  background: rgba(255,255,255,.18); border: none; color: #fff; font-size: 13px; font-weight: 600;
  padding: 7px 16px; border-radius: var(--r-pill); cursor: pointer;
}
.quiz-onboard-card {
  max-width: 380px; width: 100%; background: var(--card); border-radius: var(--r-lg);
  padding: 40px 26px 30px; text-align: center; box-shadow: var(--shadow-2);
  position: relative; overflow: hidden;
}
.quiz-onboard-emoji { font-size: 60px; line-height: 1; margin-bottom: 14px; display: inline-block; }
.quiz-onboard-title { font-size: 20px; font-weight: 600; color: var(--text); margin: 0 0 10px; }
.quiz-onboard-text { font-size: 14px; color: var(--text2); line-height: 1.5; margin: 0 0 20px; }
.quiz-onboard-dots { display: flex; align-items: center; justify-content: center; gap: 6px; margin-bottom: 20px; }
.quiz-onboard-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--gray4); transition: background .2s, transform .2s; }
.quiz-onboard-dot.active { background: var(--accent); transform: scale(1.3); }

/* ── Tabellone di una rivalità (vittorie/pareggi persistenti tra due colleghi) ── */
.quiz-rivalry-scoreboard {
  display: flex; align-items: baseline; justify-content: center; gap: 14px; margin-bottom: 4px;
}
.quiz-rivalry-score-num {
  font-size: var(--fs-xl); font-weight: 600; background: linear-gradient(90deg, var(--accent), var(--purple));
  -webkit-background-clip: text; background-clip: text; color: transparent; line-height: 1;
}
.quiz-rivalry-score-mid { font-size: 16px; font-weight: 600; color: var(--text3); }
.quiz-rivalry-draws { font-size: 12px; color: var(--text3); margin-bottom: 6px; }
.quiz-duel-game-label { font-size: var(--fs-micro); font-weight: 500; color: var(--text3); text-transform: uppercase; letter-spacing: .4px; margin-bottom: 2px; }

/* ── Card di una rivalità nella lista Duelli — una card vera per ciascuna, grande e
   colorata in stile videogame: punteggio in grande evidenza, non un dettaglio in
   piccolo, striscia colorata in cima come "identità" della sfida. ── */
.quiz-rivalry-card {
  display: flex; flex-direction: column; gap: 12px; padding: 16px 18px 14px;
  background: linear-gradient(160deg, var(--card), color-mix(in srgb, var(--accent) 5%, transparent));
  border: 1px solid var(--border); border-radius: var(--r-lg);
  margin-bottom: 12px; cursor: pointer;
  transition: background var(--t-stato);
  position: relative; overflow: hidden;
}
.quiz-rivalry-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--purple));
}
.quiz-rivalry-card:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.quiz-rivalry-card-top { display: flex; align-items: center; gap: 12px; }
.quiz-rivalry-card-name {
  flex: 1; font-size: 16px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.quiz-rivalry-card-score {
  display: flex; align-items: center; justify-content: center; gap: 20px;
  padding: 8px 0; border-top: 1px dashed var(--border); border-bottom: 1px dashed var(--border);
}
.quiz-rivalry-card-score-side { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 60px; }
.quiz-rivalry-card-score-num {
  font-size: var(--fs-xl); font-weight: 600; line-height: 1;
  background: linear-gradient(90deg, var(--accent), var(--purple));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.quiz-rivalry-card-score-label {
  font-size: 11px; font-weight: 500; color: var(--text3); text-transform: uppercase;
  letter-spacing: .3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 74px;
}
.quiz-rivalry-card-vs { font-size: 20px; opacity: .75; }
.quiz-rivalry-card-meta { text-align: center; font-size: 12px; font-weight: 600; color: var(--text3); }
.quiz-rivalry-card-meta.tiny { font-size: 11px; opacity: .8; }

/* ── Card con partita aperta (03/08/2026, redesign): il bordo in cima si fa più
   marcato e pulsa piano se tocca a te, resta spento se aspetti l'avversario — il
   numero grande diventa il punteggio live al posto del tabellone storico. ── */
.quiz-rivalry-card.is-live::before { height: 5px; animation: quizRivalryPulse 1.8s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .quiz-rivalry-card.is-live::before { animation: none; } }
@keyframes quizRivalryPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.quiz-rivalry-card.is-waiting { background: linear-gradient(160deg, var(--card), color-mix(in srgb, var(--text) 4%, transparent)); }
.quiz-rivalry-card.is-waiting::before { background: var(--gray4); animation: none; }
.quiz-rivalry-livescore {
  display: flex; align-items: baseline; justify-content: center; gap: 16px; padding: 6px 0 2px;
}
.quiz-rivalry-livescore-num {
  font-size: var(--fs-xl); font-weight: 600; line-height: 1;
  background: linear-gradient(90deg, var(--accent), var(--purple));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.is-waiting .quiz-rivalry-livescore-num { background: none; -webkit-text-fill-color: initial; color: var(--text3); }
.quiz-rivalry-livescore-mid { font-size: 14px; font-weight: 600; color: var(--text3); }

/* Chi è avanti/indietro nella manche in corso (07/08/2026, su richiesta esplicita):
   prima i due numeri avevano sempre lo stesso colore, bisognava confrontarli a
   mente. Verde chi è avanti, grigio attenuato chi è indietro (niente rosso/allarme:
   è un gioco tra colleghi, non un errore) — vince anche sullo stato "in attesa"
   (colore neutro di default), qui l'informazione conta di più. */
.quiz-rivalry-livescore-num.leading,
.is-waiting .quiz-rivalry-livescore-num.leading {
  background: none; -webkit-text-fill-color: initial; color: var(--green);
}
.quiz-rivalry-livescore-num.trailing,
.is-waiting .quiz-rivalry-livescore-num.trailing {
  background: none; -webkit-text-fill-color: initial; color: var(--text3); opacity: .55;
}

/* Banner sopra il punteggio, stesso segnale ripetuto a parole (mockup approvato
   07/08/2026): testo leggero (peso 600, non 700) apposta per non rubare la scena
   ai numeri, che restano il vero protagonista della card. */
.quiz-duel-banner {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  padding: 4px 12px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .01em; margin: 2px 0;
}
.quiz-duel-banner-lead {
  /* Anche la seconda tinta era un verde di iOS scritto a mano: ora la sfumatura
     nasce dal verde del tema e si schiarisce da sola. Il testo bianco fisso era
     un bug in tema scuro (li' il verde diventa pastello): su-accento si inverte
     da solo. L'ombra e' andata via: e' un contrassegno, vietata dal §5. */
  background: linear-gradient(90deg, var(--green), color-mix(in srgb, var(--green) 72%, #fff));
  color: var(--su-accento);
  animation: quizBannerBob 1.8s ease-in-out infinite;
}
@keyframes quizBannerBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.5px); } }
@media (prefers-reduced-motion: reduce) { .quiz-duel-banner-lead { animation: none; } }
.quiz-duel-banner-trail, .quiz-duel-banner-tied { background: var(--gray6); color: var(--text3); }

/* ── Pallino messaggi non letti, sia sulla card sia sul pulsante nel dettaglio ── */
.quiz-rivalry-unread {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: var(--r-pill); background: var(--red); color: var(--su-colore);
  font-size: var(--fs-micro); font-weight: 700; flex-shrink: 0;
}
.quiz-duel-msgbtn {
  position: relative; width: 34px; height: 34px; border-radius: 50%; border: none;
  background: var(--gray6); color: var(--text2); font-size: 15px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; margin-left: auto;
}
.quiz-duel-msg-dot {
  position: absolute; top: -3px; right: -3px; min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: var(--r-pill); background: var(--red); color: var(--su-colore); font-size: 10px; font-weight: 700;
  display: flex; align-items: center; justify-content: center; border: 1.5px solid var(--card);
}

/* ── Chat come pannello sopra la partita, non sezione fissa sotto (03/08/2026) ──
   Il gioco resta il default: l'overlay copre solo quando aperto, chiuderlo torna
   esattamente al gioco così com'era, senza ricaricare nulla. ── */
/* min-height (03/08/2026): senza, l'overlay chat (inset:0 sul wrapper) era alto
   solo quanto il riepilogo partita sotto — bastavano 2 messaggi a riempirlo. Il
   wrapper deve garantire spazio vero alla chat indipendentemente da quanto è
   "corto" il contenuto della partita in quel momento. */
.quiz-duel-body-wrap { position: relative; min-height: 62vh; }
@media (max-width: 600px) { .quiz-duel-body-wrap { min-height: 58vh; } }
.quiz-duel-chat-overlay {
  position: absolute; inset: 0; background: var(--card); z-index: 2;
  display: flex; flex-direction: column; border-radius: 0 0 var(--r-lg) var(--r-lg);
  transform: translateY(100%); transition: transform .25s ease;
}
.quiz-duel-chat-overlay.open { transform: translateY(0); }
.quiz-duel-chat-top {
  display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.quiz-duel-chat-title { font-size: 14px; font-weight: 600; color: var(--text); }
.quiz-duel-chat-overlay .chat-messages { flex: 1; max-height: none; overflow-y: auto; padding: 10px 16px 4px; }
.quiz-duel-chat-overlay .chat-input-bar { flex-shrink: 0; }

.quiz-duel-fairnote { font-size: var(--fs-xs); color: var(--text3); margin: -2px 0 4px; line-height: 1.4; }

/* ── Icona risposta avversario nel feedback (03/08/2026): solo l'icona, mai un
   colore aggiunto alla riga — il verde/rosso restano solo sulla giusta/sulla mia. ── */
.quiz-opp-icon {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; color: var(--su-colore);
}
.quiz-opp-mark {
  position: absolute; bottom: -3px; right: -3px; width: 13px; height: 13px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 8px; font-weight: 700; color: var(--su-colore);
  border: 1.5px solid var(--card);
}
.quiz-opp-mark.ok { background: var(--green); }
.quiz-opp-mark.ko { background: var(--red); }

/* ── Storico partite di una rivalità ── */
.quiz-duel-history-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 0;
  border-bottom: 1px solid var(--border); font-size: 13px;
}
.quiz-duel-history-row:last-child { border-bottom: none; }
.quiz-duel-history-result { font-size: 16px; flex-shrink: 0; }
.quiz-duel-history-score { flex: 1; font-weight: 600; color: var(--text); }
.quiz-duel-history-date { color: var(--text3); font-size: 12px; }

/* ── Rivelazione animata del round (categoria + punteggio parziale della partita) ── */
.quiz-round-reveal { position: relative; padding: 10px 0; text-align: center; }
.quiz-round-reveal-emoji { font-size: 52px; line-height: 1; margin-bottom: 8px; display: inline-block; }
.quiz-round-reveal-round { font-size: var(--fs-micro); font-weight: 500; color: var(--text3); text-transform: uppercase; letter-spacing: .5px; }
.quiz-round-reveal-theme { font-size: var(--fs-lg); font-weight: 600; color: var(--text); margin: 4px 0 16px; }
.quiz-round-reveal-score {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-size: var(--fs-base); color: var(--text2); margin-bottom: 20px;
}
.quiz-round-reveal-score strong { color: var(--text); font-size: var(--fs-md); font-weight: 600; }
.quiz-round-reveal-vs { color: var(--text3); }

/* ── Reveal round duelli (03/08/2026): l'emoji arriva "da lontano" ruotando, con
   un rimbalzo all'atterraggio — sostituisce i coriandoli, che non c'entravano
   nulla con l'idea di categoria in arrivo: qui serve suspense, non festa. I testi
   seguono con un fade leggero e sfalsato per dare profondità. Nessun tasto dopo:
   l'intera sequenza (≈3.4s) è temporizzata dal JS che poi avvia la domanda da solo. */
.quiz-anim-spinin { animation: quizRoundSpinIn 1s cubic-bezier(.2,.8,.3,1) both; }
@keyframes quizRoundSpinIn {
  0%   { transform: scale(.1) rotate(-540deg); opacity: 0; }
  55%  { transform: scale(1.25) rotate(20deg); opacity: 1; }
  72%  { transform: scale(.92) rotate(-10deg); }
  86%  { transform: scale(1.06) rotate(4deg); }
  100% { transform: scale(1) rotate(0deg); }
}
.quiz-anim-revealtext { animation: quizRevealTextIn .5s ease both; animation-delay: .55s; }
.quiz-round-reveal-theme.quiz-anim-revealtext { animation-delay: .68s; }
.quiz-round-reveal-score.quiz-anim-revealtext { animation-delay: .8s; }
@keyframes quizRevealTextIn { from { transform: translateY(10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .quiz-anim-spinin, .quiz-anim-revealtext { animation: quizRevealTextIn .3s ease both; animation-delay: 0s !important; }
}

@media (max-width: 600px) {
  .quiz-mascot-card, .quiz-game-card { padding: 24px 16px; border-radius: var(--r-lg); }
  .quiz-mascot { font-size: 52px; }
  .quiz-question { font-size: 16px; }
  .quiz-option-btn { padding: 12px 14px; font-size: 14px; }
}

/* ── Pulsante Quiz in sidebar: giocoso e animato quando disponibile, spento e
   statico quando l'utente è timbrato adesso (coerente col blocco lato server) ── */
.sidebar-quiz-btn {
  /* Stesso box model esatto di .sidebar-module + .sidebar-module-header (margine
     esterno, padding, gap, border-radius) — solo colori/animazione cambiano,
     altrimenti risulta storto rispetto alle altre righe della sidebar. */
  position: relative;
  display: flex; align-items: center; gap: 10px; margin: 0 8px 4px;
  padding: 11px 12px; border-radius: var(--r-md); cursor: pointer;
  /* Era un gradiente accento->viola con ombra colorata: alone e sfumatura sono
     esattamente cio' che la nuova direzione estetica vieta fuori dallo sfondo
     di accesso. Fondo pieno sul token accento, nessuna ombra sulla sidebar. */
  background: var(--accent);
  transition: background .15s, opacity .3s, filter .3s;
}
/* Badge duelli in attesa: ambra/oro dedicato, MAI il pallino rosso standard degli
   altri badge azionabili — deve leggersi come "gioco", non come "lavoro da fare". */
.sidebar-quiz-duel-badge {
  /* Interamente DENTRO ai confini del pulsante, mai a cavallo dello spigolo: prima
     con un offset negativo finiva mezzo dentro mezzo fuori — stessa correzione
     del badge su segTabBar (.seg-tab-badge), stesso principio nel modulo. */
  position: absolute; top: 4px; right: 4px;
  display: flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  /* Stesso fondo pieno ambra-su-token usato altrove per i contrassegni di
     conteggio (es. .active-taken): un colore del progetto, non un gradiente
     ne' un esadecimale scritto a mano. 800 sparisce, 700 resta nel budget dei
     pallini <=11px. Nessuna ombra: non e' uno degli elementi L2 previsti. */
  background: var(--orange);
  color: var(--su-colore); font-size: 11px; font-weight: 700; border-radius: var(--r-pill);
}
/* Il salto in alto era un cambio di elevazione all'hover: la specifica vuole
   che l'hover scurisca il fondo, mai che sollevi l'elemento. */
.sidebar-quiz-btn:hover { background: color-mix(in srgb, var(--accent) 88%, #000); }
.sidebar-quiz-mascot { width: 22px; font-size: 20px; text-align: center; flex-shrink: 0; animation: quizSidebarBounce 2.2s ease-in-out infinite; }
/* Il fondo non e' piu' un blu fisso ma il token --accent: in tema scuro
   diventa un pastello chiaro, e un bianco fisso qui perderebbe contrasto.
   --su-accento e' gia' la coppia corretta per il testo sopra l'accento. */
.sidebar-quiz-label { flex: 1; color: var(--su-accento); font-weight: 600; font-size: 14px; }
@keyframes quizSidebarBounce { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-3px) rotate(-6deg); } }

.sidebar-quiz-btn.quiz-sidebar-locked {
  background: var(--gray5); box-shadow: none; filter: grayscale(1); opacity: .6; cursor: default;
}
.sidebar-quiz-btn.quiz-sidebar-locked:hover { transform: none; }
.sidebar-quiz-btn.quiz-sidebar-locked .sidebar-quiz-mascot { animation: none; }
.sidebar-quiz-btn.quiz-sidebar-locked .sidebar-quiz-label { color: var(--text3); }

/* ── Regolamento breve nella schermata iniziale del Quizzettone ── */
.quiz-rules {
  text-align: left; background: var(--gray6); border-radius: var(--r-md);
  padding: 14px 16px; margin-bottom: 20px; display: flex; flex-direction: column; gap: 10px;
}
.quiz-rules-row {
  display: flex; align-items: flex-start; gap: 8px; font-size: 13px; color: var(--text2); line-height: 1.4;
}
.quiz-rules-row .material-icons-outlined { color: var(--accent); flex-shrink: 0; margin-top: 1px; }

/* ── Sidebar comprimibile su desktop (torna utile con l'Agenda, più spazio al
   planner) — persistita in localStorage, un tocco per alternare.
   TUTTO dentro questa media query, mai sul selettore ".sidebar" nudo: quella regola
   sul mobile ha "position:fixed" + "transform:translateX(-100%)" per il pannello a
   scomparsa (vedi @media max-width:768px più sopra nel file) — un ".sidebar{position:
   relative}" fuori da una media query, comparendo più in basso nel file, vinceva
   sempre su mobile e rompeva lo scorrimento laterale (il menu restava "aperto" in
   modo statico, spingendo tutto il contenuto fuori schermo a destra). */
/* Nascosto di default: prende stile e visibilità SOLO nella media query desktop
   qui sotto. Senza questa riga il bottone compariva comunque su mobile, ma "grezzo"
   (nessuno stile applicato fuori dalla media query) — da qui la frecciona brutta. */
.sidebar-collapse-btn { display: none; }

/* pointer:fine esclude i touchscreen (telefoni/tablet, anche in landscape con
   larghezza >=769px): senza questo, un telefono ruotato orizzontale attivava QUESTA
   media query invece di quella mobile sopra (stessa larghezza, nessuna condizione sul
   tipo di puntatore) — la sidebar passava alla versione "collassata a icone" da
   desktop invece del normale drawer a scomparsa aperto/chiuso, e la regola successiva
   {position:relative} vinceva su quella mobile {position:fixed}, rompendo lo swipe. */
@media (min-width: 769px) and (pointer: fine) {
  .sidebar { position: relative; transition: width .2s ease, min-width .2s ease; }
  .sidebar-collapse-btn {
    /* .sidebar ha overflow:hidden — un right negativo (che sporge fuori dal bordo)
       veniva tagliato via, restando visibile solo a metà. Sta tutto DENTRO i confini. */
    position: absolute; top: 22px; right: 8px; z-index: 5;
    /* raggio ~25% dell'altezza per un comando di 26px -> r-xs, non un cerchio pieno. */
    /* Torna cerchio. Era stato portato a squircle applicando alla lettera la
     formula "raggio = 25% dell'altezza", che pero' serve a decidere i casi nuovi
     — non a cancellare una forma scelta apposta. Un cerchio qui dice "maniglia";
     uno squircle lo confonde con i bottoni che ha intorno. */
  width: 26px; height: 26px; border-radius: var(--r-full); border: 1px solid var(--gray5);
    background: var(--card); color: var(--text3); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    /* Un bottone a riposo sulla barra laterale desktop non proietta ombra. */
    transition: background .15s, color .15s;
  }
  .sidebar-collapse-btn:hover { background: var(--gray6); color: var(--accent); }
  .sidebar-collapse-btn .material-icons-outlined { font-size: 16px; }

  .sidebar.sidebar-collapsed { width: 72px; min-width: 72px; }
  .sidebar-collapsed .app-name,
  .sidebar-collapsed .sidebar-sub-section,
  .sidebar-collapsed .sidebar-module-body,
  .sidebar-collapsed .module-chevron,
  .sidebar-collapsed .module-label,
  .sidebar-collapsed .sidebar-mod-badge,
  .sidebar-collapsed .item-count,
  .sidebar-collapsed .role-badge,
  .sidebar-collapsed .sidebar-quiz-label,
  .sidebar-collapsed .user-info {
    display: none !important;
  }
  .sidebar-collapsed .sidebar-module-header { justify-content: center; padding: 10px 0; }
  .sidebar-collapsed .sidebar-logo { justify-content: center; width: 100%; }
  .sidebar-collapsed .sidebar-quiz-btn { justify-content: center; margin: 0 8px 4px; padding: 11px 0; }
  .sidebar-collapsed .avatar-btn { margin: 0 auto; }
  .sidebar-collapsed .sidebar-footer { flex-direction: column; gap: 8px; }
  .sidebar-collapsed .sidebar-footer > div { flex: none !important; }
}

/* ── Guida rapida (Impostazioni → Guida) ── */
.guida-list { display: flex; flex-direction: column; gap: 8px; }
.guida-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden;
}
.guida-card-header {
  display: flex; align-items: center; gap: 10px; padding: 13px 14px; cursor: pointer; user-select: none;
}
.guida-card-icon { color: var(--accent); font-size: 20px; flex-shrink: 0; }
.guida-card-title { flex: 1; font-size: 14px; font-weight: 600; color: var(--text); }
.guida-chevron { color: var(--text3); transition: transform .2s; flex-shrink: 0; }
.guida-card-body {
  padding: 0 16px 16px 44px; font-size: 13.5px; color: var(--text2); line-height: 1.55;
}
.guida-card-body p { margin: 0 0 8px; }
.guida-card-body p:last-child { margin-bottom: 0; }
.guida-card-body strong { color: var(--text); }

/* ── La guida che arriva dal server (24/09/2026) ──────────────────────────────
   Prima erano quattordici schede scritte dentro app.js; ora sono sedici sezioni
   con quattrocento paragrafi, e senza una ricerca non si trova piu' niente. */

.guida-cerca {
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 4px 14px; margin-bottom: 16px;
}
.guida-cerca .material-icons-outlined { color: var(--text3); font-size: 20px; flex-shrink: 0; }
.guida-cerca input {
  flex: 1; min-width: 0; border: none; background: none; outline: none;
  font: inherit; font-size: 14px; color: var(--text); padding: 12px 0;
}
.guida-cerca input::placeholder { color: var(--text3); }
.guida-cerca:focus-within { border-color: var(--accent); }

.guida-esiti { display: flex; flex-direction: column; gap: 6px; margin-bottom: 24px; }
.guida-esito {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
  border-radius: var(--r-md); padding: 12px 14px; cursor: pointer;
  font: inherit; transition: background var(--transition);
}
.guida-esito:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.guida-esito .material-icons-outlined { color: var(--accent); font-size: 20px; flex-shrink: 0; }
.guida-esito-testo { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.guida-esito-testo strong { font-size: 14px; font-weight: 600; color: var(--text); }
.guida-esito-testo small { font-size: 12px; color: var(--text3); }

.guida-niente, .guida-attesa {
  font-size: 13.5px; color: var(--text3); margin: 0 0 20px; padding: 14px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
}

.guida-sezione { margin-bottom: 28px; }
.guida-sezione-testa { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.guida-conta {
  font-size: 11px; font-weight: 600; color: var(--text3);
  background: var(--gray6); border-radius: var(--r-full); padding: 2px 8px; flex-shrink: 0;
}
.guida-sommario { font-size: 13px; color: var(--text3); margin: 0 0 10px 30px; }

/* Il corpo dei paragrafi nuovi non ha l'icona a sinistra, quindi non serve il
   rientro di 44px pensato per le vecchie schede. */
.guida-sezione .guida-card-body { padding-left: 16px; }
.guida-sezione .guida-card-body ul { margin: 8px 0; padding-left: 20px; }
.guida-sezione .guida-card-body li { margin: 4px 0; }
.guida-sezione .guida-card-body table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13px; }
.guida-sezione .guida-card-body th,
.guida-sezione .guida-card-body td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border); }
.guida-sezione .guida-card-body th { color: var(--text); font-weight: 600; }

.guida-ruolo {
  font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--stato-attesa); background: color-mix(in srgb, var(--stato-attesa) 14%, transparent);
  border-radius: var(--r-sm); padding: 3px 7px; flex-shrink: 0;
}

.guida-vedi-anche {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border);
}
.guida-vedi-anche > span {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); font-weight: 600;
}
.guida-rimando {
  font: inherit; font-size: 12.5px; color: var(--accent); cursor: pointer;
  background: none; border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--r-full); padding: 4px 11px;
}
.guida-rimando:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* I paragrafi proposti mentre uno scrive un ticket o apre la chat: sono un
   suggerimento, non un avviso, quindi stanno in disparte e non urlano. */
.ass-sugg {
  margin: -4px 0 18px; padding: 12px;
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-radius: var(--r-md);
}
.ass-sugg-testa {
  display: flex; align-items: center; gap: 6px; margin-bottom: 8px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent);
}
.ass-sugg-voce {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 9px 11px; margin-bottom: 6px; cursor: pointer; font: inherit;
  transition: border-color var(--transition);
}
.ass-sugg-voce:last-child { margin-bottom: 0; }
.ass-sugg-voce:hover { border-color: var(--accent); }
.ass-sugg-voce strong { font-size: 13.5px; font-weight: 600; color: var(--text); }
.ass-sugg-voce small { font-size: 11.5px; color: var(--text3); }

/* Editor timbrature su mobile (31/07/2026): la riga unica tipo+orario+bottoni
   schiacciava il selettore del tipo a due frecce illeggibili — su schermi
   stretti va a capo: tipo a tutta larghezza sopra, orario e bottoni sotto.
   !important per vincere sui flex inline del markup. */
@media (max-width: 600px) {
  .tbr-ed-row { flex-wrap: wrap; }
  .tbr-ed-row select { flex: 1 1 100% !important; }
  .tbr-ed-row input[type="time"] { flex: 1 1 auto; min-width: 0; }
}

/* ── Stato dell'abbonamento ────────────────────────────────────────────────
   Striscia sotto l'intestazione, sempre visibile ma mai invadente: informa,
   non spaventa, e non toglie spazio al contenuto più dello stretto necessario. */
/* Tutto il colore qui era scritto a mano (due volte: chiaro e scuro), il
   corpo era un mezzo pixel vietato (13.5), il padding fuori griglia (18,
   e nel breakpoint 9/14). Ricostruito sui token semantici gia' in uso in
   tutta l'app per gli stati (--orange per l'avviso, --red per il blocco in
   sola lettura), con lo stesso velo tinto usato da .install-status e
   .role-badge: colore pieno del token sul testo, un velo leggero sul fondo.
   Cosi' il blocco @media(dark) sparisce del tutto: --orange/--red cambiano
   gia' da soli in tema scuro, non serve piu' ridefinire i colori qui. Anche
   il grassetto di /* Il link dentro la striscia: sottolineato e dello stesso colore del testo.
   Un azzurro di sistema su un fondo arancione non si legge, ed e' l'unico
   pezzo cliccabile di tutta la riga (25/09/2026). */
.tenant-banner a { color: inherit; text-decoration: underline; font-weight: 600; white-space: nowrap; }

.tenant-banner strong scende a 600 — dentro una frase non
   e' un pallino di conteggio, non gli spetta il 700. */
.tenant-banner {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 16px;
  font-size: var(--fs-sm); line-height: 1.45;
  border-bottom: 1px solid;
  flex-shrink: 0;
}
.tenant-banner .material-icons-outlined { font-size: 18px; flex-shrink: 0; margin-top: 2px; }
.tenant-banner strong { font-weight: 600; }

.tenant-banner.warn {
  background: color-mix(in srgb, var(--orange) 12%, transparent);
  color: var(--orange);
  border-bottom-color: color-mix(in srgb, var(--orange) 30%, transparent);
}
.tenant-banner.readonly {
  background: color-mix(in srgb, var(--red) 12%, transparent);
  color: var(--red);
  border-bottom-color: color-mix(in srgb, var(--red) 30%, transparent);
}

@media (max-width: 560px) {
  .tenant-banner { padding: 8px 12px; font-size: var(--fs-xs); }
}


/* Marchio della piattaforma nella schermata di accesso: logo e nome sono
   quelli impostati nella console. Comanda Orthosuite qui e anche dentro l'app —
   il marchio dell'azienda vale solo verso i SUOI clienti (email, promemoria,
   prenotazione, PDF). Vedi platform/README.md. */
.auth-marchio {
  /* Tre volte i 64px di prima: il marchio è la prima cosa che si vede aprendo
     l'app, e a 64 px sembrava una favicon finita lì per sbaglio.
     Due tetti e nessuna misura fissa: il logo si iscrive in 192×192 tenendo le
     sue proporzioni. Un riquadro alto 192 con un logo largo e basso dentro
     lascerebbe ottanta pixel di vuoto sopra e sotto — grande sullo schermo,
     ma di aria. */
  width: auto;  max-width: 192px;
  height: auto; max-height: 192px;
  margin: 0 auto 14px; display: block;
}


/* Sfondo della piattaforma nella schermata di accesso, impostato dalla console.
   Il velo sopra l'immagine tiene leggibile la scheda: senza, una fotografia
   chiara mangia il testo e una scura mangia il riquadro. */
#auth-screen.con-sfondo {
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  position: relative;
}
#auth-screen.con-sfondo::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(255, 255, 255, .74);
  backdrop-filter: blur(2px);
  pointer-events: none;
}
#auth-screen.con-sfondo > * { position: relative; z-index: 1; }
#auth-screen.con-sfondo .auth-card {
  box-shadow: var(--shadow-2);
}

@media (prefers-color-scheme: dark) {
  #auth-screen.con-sfondo::before { background: rgba(18, 20, 22, .74); }
}

/* ── Identità della piattaforma dentro l'app ──────────────────────────────────
   Il marchio del gestionale è quello di Orthosuite. Il nome dell'azienda sta
   sotto, in piccolo: serve a sapere in quale cliente si sta lavorando, non a
   fare da marchio. */
.sidebar-logo .app-name small {
  display: block;
  /* 11.5 non e' uno dei sette corpi: e' una nota di riga sotto al nome della
     piattaforma, esattamente il caso d'uso di --fs-micro. */
  font-size: var(--fs-micro);
  font-weight: 400;
  color: var(--text3, #8e8e93);
  line-height: 1.25;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-logo img { max-height: 30px; max-width: 30px; object-fit: contain; }

/* Nota nelle impostazioni del tenant: dice a cosa servono davvero le scelte
   di quella scheda, che non è quello che ci si aspetta leggendo "Aspetto". */
.settings-hint {
  background: var(--bg2);
  border-radius: var(--r-md);
  padding: 12px 14px;
  margin-bottom: 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text2);
}

/* Scheda "Demo": esiste solo nell'azienda dimostrativa. */
#settings-panel .apt-admin-card h3 { margin: 0 0 8px; font-size: 16px; color: var(--text1); }
#settings-panel .apt-admin-card p  { font-size: 13.5px; color: var(--text2); line-height: 1.6; margin: 0 0 12px; }

/* Slot occupato da un appuntamento la cui testa e' stata inghiottita dal
   rowspan di un altro: e' una sovrapposizione, un dato da correggere. Si
   disegna a righe per distinguerla da un appuntamento normale, senza gridare. */
.apt-appt-overlap {
  background: repeating-linear-gradient(
    45deg,
    var(--gray5, #e5e5ea), var(--gray5, #e5e5ea) 6px,
    var(--card, #fff) 6px, var(--card, #fff) 12px
  );
  vertical-align: top;
}
.apt-overlap-label {
  display: block; padding: 3px 6px;
  font-size: 11px; font-weight: 600; color: var(--text3, #8e8e93);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── PASSATA GRAFICA (28/08/2026) ────────────────────────────────────────────
   Le tre analisi convergevano su tre cose, e sono qui in fondo per restare
   leggibili come un intervento invece che sparpagliate nel foglio.

   1. Il margine di pagina si stringe con lo schermo, e --gutter lo governa
      dappertutto. Prima Impostazioni stava a 20, l'agenda a 16 e la testata a
      16 su telefono contro il 12 delle liste: quattro bordi sinistri diversi
      che si vedevano a ogni cambio di schermata.
   2. Le etichette di servizio smettono di urlare. Erano 700 + MAIUSCOLO +
      spaziate: le cose piu' gridate della pagina erano quelle che dovevano
      sparire per prime.
   3. I bottoni non saltano piu' al passaggio del mouse. Il sollevamento di un
      pixel con l'alone colorato e' la firma di iOS 7, ed e' il dettaglio che
      data l'interfaccia piu' di ogni altro.
   ─────────────────────────────────────────────────────────────────────────── */

/* (il rientro di .settings-content arriva da --rientro-modulo, che sotto i
   768px vale gia' --gutter da solo) */
.apt-admin-page   { padding-left: var(--gutter); padding-right: var(--gutter); }

@media (max-width: 768px) {
  :root { --gutter: 16px; }
  /* La testata usava gia' 16 mentre le liste sotto stavano a 12: adesso
     partono tutte dalla stessa linea verticale. */
  #app-header, .filter-bar, .dash-wrap, .task-list-container, .leave-budget-cards {
    padding-left: var(--gutter); padding-right: var(--gutter);
  }
}

/* Etichette: peso e maiuscoletto via. Restano piccole e chiare, che e' il loro
   mestiere — dire cosa c'e' sotto, non farsi notare. */
.form-group label, .field-label, .task-group-header,
.detail-section-label, .sidebar-sub-title, .apt-tpl-vars-label {
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text3);
}

/* Niente salto e niente alone: al passaggio del mouse il bottone si scurisce e
   basta. Un bottone alto 34px non proietta un'ombra da 8 pixel. */
.btn-primary:hover, .azione-pagina:hover {
  transform: none;
  box-shadow: none;
  background: color-mix(in srgb, var(--accent) 88%, #000);
}
.azione-pagina { box-shadow: none; }


/* ── ASSISTENZA ─────────────────────────────────────────────────────────────
   Le bolle e la barra di scrittura NON sono qui: sono quelle della
   messaggistica interna (.chat-msg, .chat-bubble, .chat-input-bar), le stesse
   dei commenti su task e valutazioni. Qui c'è solo quello che le circonda.

   Un accesso solo, a tutte le larghezze: la riga "Assistenza" nella barra,
   sopra il piede. Prima erano due (bolla su desktop, icona nel menu su
   telefono) e sembravano un doppione, ma nessuna delle due si vedeva dove
   c'era l'altra: era una strada sola travestita da due. */


/* ── Il menù ─────────────────────────────────────────────────────────────────
   Il titolo aveva l'imbottitura di una riga e le voci un'altra: "Assistenza"
   finiva appiccicato al bordo mentre il testo sotto stava rientrato. Adesso
   una sola misura governa tutto il riquadro. */
.ass-menu {
  position: absolute; z-index: 200; display: none;
  min-width: 292px; padding: 8px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-xl);
  /* Menu e pannello sono elementi L2 (tendina / sollevato non modale): un'ombra
     sola dal token previsto, non due strati scritti a mano. */
  box-shadow: var(--shadow-1);
}
.ass-menu.open { display: block; }
.assistenza-wrap { position: relative; }
/* Dove si apre lo decide assistenzaPosizionaMenu(), perche' dipende da dove
   sta il bottone e da quanto schermo c'e': qui resta solo l'aspetto. */

/* Un bottone con l'icona E il nome, nello spazio libero del piede. Il nome non
   e' un vezzo: la versione precedente era la stessa cosa senza etichetta, e
   nessuno la trovava — un simbolo da solo si riconosce se lo conosci gia'. */
.sidebar-assistenza {
  position: relative;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 12px 7px 8px; border: none; border-radius: 999px;
  background: none; color: var(--text2); cursor: pointer;
  /* 13.5 non e' un corpo previsto; le altre voci della barra (item, header di
     modulo) sono a 14 -> stessa misura, non un valore intermedio per conto suo. */
  font: inherit; font-size: var(--fs-base); font-weight: 500; white-space: nowrap;
  transition: background .12s ease, color .12s ease;
}
.sidebar-assistenza:hover { background: var(--gray6); color: var(--text); }
.sidebar-assistenza .module-icon { display: grid; place-items: center; width: 22px; }
.sidebar-assistenza .module-icon .material-icons-outlined { font-size: 21px; }
.sidebar-assistenza .notif-badge { position: static; margin-left: 2px; }

/* A barra chiusa il piede diventa una colonna e lo spazio in orizzontale non
   c'e' piu': resta la sola icona, come per ogni altra voce. */
.sidebar-collapsed .sidebar-assistenza { padding: 8px; }
.sidebar-collapsed .sidebar-assistenza .module-label { display: none; }
.sidebar-collapsed .sidebar-assistenza .notif-badge {
  position: absolute; top: 0; right: 0; margin-left: 0;
}

.ass-menu-testa {
  padding: 8px 12px 10px; font-size: 12px; font-weight: 600;
  color: var(--text3); letter-spacing: .01em;
}
.ass-menu-voci { display: flex; flex-direction: column; gap: 2px; }

.ass-voce {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 11px 12px; border: none; border-radius: var(--r-md);
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.ass-voce:hover { background: var(--gray6); }
.ass-voce-testo { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.ass-voce-testo strong { font-size: 14px; font-weight: 600; }
.ass-voce-testo small { font-size: 12px; color: var(--text3); line-height: 1.35; }

/* Ogni porta ha il suo colore: sono tre cose diverse e l'occhio le separa
   prima di leggere. Le tinte nascono dai colori di stato, non da tre valori
   scelti a mano. */
.ass-voce-icona {
  flex: none; width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
}
.ass-voce-icona .material-icons-outlined { font-size: 20px; }
.tono-guida  { background: color-mix(in srgb, var(--purple) 12%, transparent); color: var(--purple); }
.tono-chat   { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
/* Stesso problema e stessa cura dell'avviso qui sopra: il colore deve
   restare un token per raggiungere anche il tema scuro. */
.tono-ticket { background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange); }
.ass-pallino-vivo { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--green); }

/* ── Il pannello ─────────────────────────────────────────────────────────── */
/* ── L'ASSISTENZA E' UNA FINESTRA, NON UN FUMETTO ────────────────────────────
   Era un riquadro da 390px incollato in basso a destra, come una chat di
   supporto di quelle che si aprono da sole sui siti. Due cose non tornavano:
   si apre da un pulsante in basso a SINISTRA, e comparire dall'angolo opposto
   fa perdere il filo di cosa si e' appena premuto; e soprattutto dentro un
   ticket ci vanno fotografie, schermate e testi lunghi — in una colonna da 390
   pixel si legge male e si scrive peggio.
   Adesso e' una finestra al centro, con il velo dietro come ogni altra finestra
   dell'app: si apre da dove vuoi, e ha lo spazio di quello che contiene. */
/* Il velo dietro al ticket e' LO STESSO velo dei modali dell'app: stesso nero,
   stessa sfocatura. Era un nero piatto al 45% senza sfocatura, e si vedeva —
   una finestra al centro con dietro la pagina ancora perfettamente leggibile
   sembrava appiccicata, e l'occhio ci tornava. Se cambia .modal-overlay va
   cambiato anche qui: sono la stessa cosa vista dall'utente. */
.ass-velo {
  position: fixed; inset: 0; z-index: 899; display: none;
  background: var(--velo-sfondo);
  backdrop-filter: var(--velo-sfocatura);
  -webkit-backdrop-filter: var(--velo-sfocatura);
}
.ass-velo.aperto { display: block; }

.ass-pannello {
  position: fixed; z-index: 900;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(820px, calc(100vw - 40px));
  height: min(760px, calc(100vh - 64px));
  display: none; flex-direction: column; overflow: hidden;
  background: var(--card); border-radius: var(--r-xl);
  /* Una finestra modale e' un elemento L3: l'ombra alta, come i modali. */
  box-shadow: var(--shadow-2);
}
.ass-pannello.aperto { display: flex; }

/* ── LA CHAT NON E' UN MODALE, IL TICKET SI' ─────────────────────────────────
   Sono due gesti diversi e devono avere due forme diverse.

   La CHAT e' una conversazione a fianco del lavoro: si scrive una riga, si
   torna a quello che si stava facendo, arriva la risposta. Percio' e' un
   pop-up piccolo, appoggiato sopra la riga "Assistenza" da cui e' uscito,
   senza velo: la pagina dietro resta viva e usabile, perche' serve — spesso
   si scrive proprio per chiedere di quello che si ha davanti.

   Il TICKET no: ci vanno dentro foto, allegati e testi lunghi, e mentre lo si
   compila si sta facendo quello e basta. Quello e' un modale vero, in mezzo
   allo schermo, con la pagina sfocata dietro. */
.ass-pannello.ass-chat {
  left: 16px; right: auto; top: auto; bottom: 84px; transform: none;
  width: min(380px, calc(100vw - 32px));
  height: min(560px, calc(100vh - 150px));
}

/* Sul telefono prende tutto lo schermo, come i modali dell'app — e la chat
   pure: un pop-up da trecentottanta pixel dentro uno schermo da trecentonovanta
   non e' un pop-up, e' la pagina con un bordo. */
@media (max-width: 640px) {
  .ass-pannello, .ass-pannello.ass-chat {
    left: 0; right: auto; top: 0; bottom: auto; transform: none;
    width: 100vw; height: 100dvh; max-width: none; border-radius: 0;
  }
}

.ass-testa {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 14px 12px 14px 16px; background: var(--accent); color: var(--su-accento);
}
.ass-testa strong { flex: 1; font-size: 15px; font-weight: 600;
                    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ass-testa .btn-icon { color: var(--su-accento); }
.ass-testa-segno { display: grid; place-items: center; opacity: .9; }
.ass-testa-segno .material-icons-outlined { font-size: 21px; }

.ass-corpo { padding: 16px; overflow-y: auto; display: flex; flex-direction: column; }
.ass-corpo-chat { flex: 1; min-height: 0; padding: 0; overflow: hidden; }
.ass-messaggi { flex: 1; min-height: 140px; overflow-y: auto; padding: 14px 16px 4px; }
/* L'area messaggi porta anche .chat-messages, che arriva dalla messaggistica
   interna e la' vive dentro una scheda: ha un tetto di 320px. Qui dentro no —
   il pannello ha un'altezza sua e i messaggi devono riempirla, o resta un
   vuoto sotto al campo di scrittura (e il campo galleggia a meta' finestra). */
.ass-corpo-chat .chat-messages { max-height: none; }

.ass-avviso {
  display: flex; gap: 11px; align-items: flex-start; flex: none;
  padding: 13px 15px; margin-bottom: 18px; border-radius: var(--r-md);
  font-size: 13px; line-height: 1.5;
  /* #7a5300 era scelto a mano: in tema scuro --orange diventa chiaro e questo
     bruno resta scuro, testo quasi invisibile sul suo stesso velo. var(--orange)
     e' la stessa coppia usata altrove nel file per i veli d'arancio ed e' gia'
     verificata sopra 4.5:1 in entrambi i temi. */
  background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange);
}
.ass-avviso.dentro { margin: 14px 16px 0; }
.ass-avviso em { display: block; margin-top: 4px; font-style: normal; opacity: .85; font-size: 12px; }
.ass-avviso-segno { display: grid; place-items: center; flex: none; }
.ass-avviso-segno .material-icons-outlined { font-size: 19px; }

.ass-titoletto { margin: 20px 0 2px; font-size: 12px; font-weight: 600; color: var(--text3); }
.ass-largo { width: 100%; margin-top: 14px; }
.ass-vuoto { color: var(--text3); font-size: var(--fs-sm); text-align: center;
             padding: 22px 8px; margin: 0; line-height: 1.5; }
.ass-facolt { font-weight: 400; color: var(--text3); }
.ass-chi { margin: 2px 0 0; font-size: var(--fs-xs); color: var(--text3); }

/* ── L'elenco dei ticket dentro il pannello ──────────────────────────────────
   Stessa lingua della scheda del singolo ticket: numero, stato, data. Chi apre
   questa voce sta chiedendo "quella cosa che ho segnalato, a che punto e'?", e
   deve poterlo leggere senza entrare in nessuna riga. */
.ass-corpo-elenco { flex: 1; min-height: 0; overflow-y: auto; }
.tkt-elenco { display: flex; flex-direction: column; margin: 0 -4px; }
.tkt-riga {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 12px 10px; border: none; border-radius: 12px;
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.tkt-riga:hover { background: var(--gray6); }
.tkt-riga-testo { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.tkt-riga-testo strong { font-size: 14px; font-weight: 500; overflow: hidden;
                         text-overflow: ellipsis; white-space: nowrap; }
/* Con una risposta da leggere il titolo si fa grassetto: e' lo stesso segnale
   della posta, e non chiede di imparare niente di nuovo. */
.tkt-riga.da-leggere .tkt-riga-testo strong { font-weight: 700; }
.tkt-riga-testo small { font-size: 12px; color: var(--text3); overflow: hidden;
                        text-overflow: ellipsis; white-space: nowrap; }
.tkt-riga .tkt-stato { flex: none; }

/* Lo stato vuoto: un segno, una riga che dice cosa manca, e una che dice cosa
   ci sara'. Non un "Nessun ticket." buttato in mezzo al bianco. */
.ass-nulla {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 34px 20px 10px; text-align: center;
}
.ass-nulla-segno {
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: var(--r-md);
  background: var(--gray6); color: var(--text3);
}
.ass-nulla-segno .material-icons-outlined { font-size: 24px; }
.ass-nulla strong { font-size: 15px; font-weight: 600; }
.ass-nulla p { margin: 0; max-width: 30ch; font-size: 13px; line-height: 1.5; color: var(--text3); }
.ass-pallino { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--red); }
.ass-chiusa { margin: 0; padding: 15px 16px; font-size: 13px; color: var(--text3);
              text-align: center; border-top: 1px solid var(--border); }

/* ── Il ticket ───────────────────────────────────────────────────────────────
   Un ticket non e' una chat, e non deve somigliarci: la chat e' una cosa che si
   fa adesso, il ticket una pratica che si riprende in mano fra tre settimane.
   Quindi niente fumetti, niente allineamento a destra, niente barra con la
   freccina d'invio. Un numero, uno stato, una data, e gli interventi impilati a
   tutta larghezza con sopra chi li ha scritti e quando — cioe' qualcosa che si
   rilegge, non qualcosa che scorre via. */
.ass-corpo-ticket { flex: 1; min-height: 0; padding: 0; overflow-y: auto; }

.tkt-testa {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; border-bottom: 1px solid var(--border); background: var(--gray6);
}
.tkt-num {
  font-size: 13px; font-weight: 700; letter-spacing: .3px; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.tkt-quando { font-size: 12px; color: var(--text3); margin-left: auto; }

/* Lo stato e' la prima cosa che si cerca aprendo un ticket vecchio. */
.tkt-stato {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  padding: 3px 8px; border-radius: var(--r-sm); white-space: nowrap;
}
.tkt-stato.aperto { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.tkt-stato.chiuso { background: var(--gray5); color: var(--text3); }

.tkt-nato {
  display: flex; align-items: center; gap: 6px; margin: 0;
  padding: 9px 16px; font-size: 12.5px; color: var(--text3);
  border-bottom: 1px solid var(--border);
}
.tkt-nato .material-icons-outlined { font-size: 16px; }

.tkt-filo { padding: 0; }
.tkt-post { padding: 14px 16px; border-bottom: 1px solid var(--border); }
/* La risposta dell'assistenza si distingue da sola, senza doverla cercare. */
.tkt-post.staff { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.tkt-post header {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 6px;
}
.tkt-post header strong { font-size: 13.5px; font-weight: 600; }
.tkt-post header time { margin-left: auto; font-size: 11.5px; color: var(--text3); }
.tkt-ruolo {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
  padding: 1px 6px; border-radius: 5px;
}
.tkt-testo { font-size: 14px; line-height: 1.55; color: var(--text); word-break: break-word; }

/* Rispondere e' un gesto deliberato: un campo con la sua etichetta e un
   pulsante che dice cosa fa. La freccina della chat qui direbbe la cosa
   sbagliata — che il messaggio parte come una battuta e sparisce. */
.tkt-rispondi { display: flex; flex-direction: column; gap: 8px; padding: 16px; }
.tkt-rispondi label { font-size: 12.5px; font-weight: 600; color: var(--text2); }
.tkt-rispondi textarea {
  width: 100%; padding: 11px 12px; border: 1px solid var(--border); border-radius: 12px;
  font: inherit; font-size: 14px; line-height: 1.5; resize: vertical; background: var(--card);
  color: var(--text);
}
.tkt-rispondi textarea:focus { outline: none; border-color: var(--accent); }
.tkt-rispondi button { align-self: flex-start; }

.tkt-fine {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  padding: 16px; border-top: 1px solid var(--border);
}
.tkt-fine strong { font-size: 13.5px; font-weight: 600; color: var(--text2); }

/* Nell'elenco: lo stato a destra, il numero e la data sotto l'oggetto. */
.tkt-riga .tkt-stato { flex: none; }

/* ── Telefono ────────────────────────────────────────────────────────────────
   Il pannello diventa un foglio a tutta larghezza, sopra la tacca di sistema —
   che tutto il resto del foglio già fa e qui era rimasto indietro. */
@media (max-width: 768px) {
  .ass-pannello, .ass-pannello.ass-chat {
    right: 0; left: 0; bottom: 0; top: auto; transform: none;
    width: auto; max-width: none;
    max-height: calc(100vh - 40px); max-height: calc(100dvh - 40px);
    border-radius: 20px 20px 0 0; border-bottom: none;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .ass-menu { min-width: 268px; }
}
/* Qui c'era una regola che NASCONDEVA l'assistenza dalla barra su desktop,
   perche' li' bastava la bolla fluttuante. Tolta la bolla — il posto in basso
   a destra e' della messaggistica — quella regola lasciava il desktop senza
   nessun accesso all'assistenza. Non erano due strade per la stessa cosa: era
   una strada sola, che cambiava forma a seconda dello schermo. */

/* ═══════════════════════════════════════════════
   POST-IT — icona fissa in header (.sticky-composer eredita l'aspetto da
   .notif-dropdown, vedi index.php) + livello globale sempre sopra al contenuto.
═══════════════════════════════════════════════ */
.sticky-wrap { position: relative; }
.sticky-composer { width: 260px; padding: 14px; display: none; }
.sticky-composer.open { display: block; }
@media (max-width: 600px) { .sticky-composer { width: auto; } }
.sticky-composer textarea {
  width: 100%; min-height: 80px; max-height: 200px;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 10px;
  font-family: inherit; font-size: 14px; resize: vertical; color: var(--text);
  background: var(--bg);
}
.sticky-composer-colors { display: flex; gap: 8px; margin: 10px 0; }
.sticky-swatch {
  width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent;
  cursor: pointer; padding: 0;
}
.sticky-swatch.active { border-color: var(--text); }
.sticky-composer .btn { margin-top: 0; }

/* Livello globale: sta SEMPRE sopra al contenuto (anche sopra ai modal, per
   scelta esplicita — un post-it si trascina via se dà fastidio, non si nasconde
   da solo). pointer-events:none qui, riacceso solo sulla singola nota: lo sfondo
   resta sempre utilizzabile mentre un post-it è in scena. */
#sticky-layer { position: fixed; inset: 0; z-index: 9500; pointer-events: none; }

.sticky-note {
  position: fixed;
  width: 190px; min-height: 150px;
  padding: 18px 14px 26px;
  /* Caveat era dichiarato qui ma non caricato da nessuna parte: nel riporto da
     un'altra app la regola e' arrivata e il font no. Non si rompeva niente —
     si ripiegava su Segoe Script, che su Windows c'e' — ma i post-it non erano
     quelli previsti, e su un computer senza nessuno di quei corsivi diventavano
     testo normale dentro un rettangolo giallo.
     Adesso arriva dal dominio, come le icone: 75 KB, nel guscio del service
     worker, quindi c'e' anche senza rete.
     I ripieghi restano: se il file non arrivasse, si degrada invece di sparire. */
  font-family: 'Caveat', 'Segoe Script', 'Bradley Hand', cursive;
  font-size: 21px; line-height: 1.3; color: #4a4520;
  box-shadow: var(--shadow-1); /* par.5: due ombre sole in tutto il progetto, mai a piu' strati */
  cursor: grab; touch-action: none; user-select: none;
  pointer-events: auto;
  will-change: transform, clip-path, left, top;
}
.sticky-note.dragging { cursor: grabbing; box-shadow: var(--shadow-2); z-index: 1 !important; }
.sticky-note.sticky-flying { cursor: default; }
.sticky-note::after {
  content: ''; position: absolute; right: 0; bottom: 0; width: 0; height: 0;
  border-style: solid; border-width: 0 0 20px 20px;
  border-color: transparent transparent rgba(0,0,0,.15) transparent;
}
.sticky-note--yellow { background: var(--sticky-yellow); }
.sticky-note--pink   { background: var(--sticky-pink); }
.sticky-note--green  { background: var(--sticky-green); }
.sticky-note--blue   { background: var(--sticky-blue); }
.sticky-note-top { display: flex; justify-content: flex-end; align-items: flex-start; margin-bottom: 4px; }
.sticky-note-actions { display: flex; gap: 2px; flex-shrink: 0; }
.sticky-note-btn {
  width: 22px; height: 22px; border-radius: 50%; border: none; background: rgba(0,0,0,.08);
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: #4a4520;
  flex-shrink: 0; padding: 0;
}
.sticky-note-btn .material-icons-outlined { font-size: 14px; }
.sticky-note-btn:hover { background: rgba(0,0,0,.16); }
.sticky-note-text { white-space: pre-wrap; word-break: break-word; }
/* Firma di chi lo ha mandato: in basso a destra, come ci si firma su un vero
   post-it — flusso normale (non posizionamento assoluto) dopo il testo, così
   resta sempre chiaramente sotto il messaggio e dentro il padding-bottom già
   riservato alla piega dell'angolo, qualunque sia la lunghezza del testo. */
.sticky-note-signature { text-align: right; margin-top: 8px; padding-right: 8px; font-style: italic; font-size: 0.85em; opacity: .7; }
@keyframes stickyTextIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes stickyTextOut { from { opacity: 1; } to { opacity: 0; } }

.sticky-send-menu {
  position: absolute; top: 26px; right: 8px; background: var(--card); border-radius: var(--r-lg);
  box-shadow: var(--shadow-1); padding: 6px; display: none; width: 220px;
  font-family: -apple-system, "Segoe UI", sans-serif; z-index: 1;
}
.sticky-send-menu.open { display: block; }
/* Ricerca dinamica: senza, con più di una decina di colleghi il menù sborda
   oltre lo schermo e non c'è modo di scorrerlo fino in fondo — richiesta
   esplicita pensando alle aziende con tanti dipendenti. */
.sticky-send-search {
  width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 7px 9px;
  border: 1px solid var(--border); border-radius: 8px; font-size: 13px;
  font-family: inherit; color: var(--text); background: var(--bg);
}
.sticky-send-list { max-height: 240px; overflow-y: auto; }
.sticky-send-item {
  display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: var(--r-sm);
  cursor: pointer; font-size: 13px; color: var(--text);
}
.sticky-send-item:hover { background: var(--gray6); }
.sticky-send-empty { padding: 10px 8px; font-size: 13px; color: var(--text3); text-align: center; }

@keyframes stickyPopIn {
  from { transform: scale(.7); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
.sticky-note.sticky-appearing { animation: stickyPopIn .28s cubic-bezier(.34,1.56,.64,1); }

/* Nuvoletta "poof" (sparizione/comparsa) — stesso spirito ludico dei coriandoli
   del Quizzettone (.quiz-confetti-piece): forme semplici, un solo keyframe,
   niente calcoli di traiettoria. */
.sticky-poof { position: fixed; pointer-events: none; z-index: 9600; }
.sticky-poof-puff {
  position: absolute; width: 22px; height: 22px; border-radius: 50%;
  background: #fff; animation: stickyPoofPuff .5s ease-out forwards;
}
@keyframes stickyPoofPuff { from { transform: scale(.4); opacity: .9; } to { transform: scale(2); opacity: 0; } }

/* Aeroplanino: piccolo dart dello stesso colore del post-it, vola in linea
   retta con un solo transition CSS (niente keyframe generati al volo) più un
   piccolo sobbalzo cartoon indipendente — stesso linguaggio del bounce della
   mascotte del Quizzettone (.quiz-anim-bounce). */
.sticky-plane2 {
  position: fixed; width: 30px; height: 26px; margin: -13px 0 0 -15px;
  pointer-events: none; z-index: 9600;
  transition: left 1s ease-in-out, top 1s ease-in-out, opacity .3s ease-in;
}
.sticky-plane2-shape {
  width: 100%; height: 100%;
  clip-path: polygon(0% 15%, 100% 50%, 0% 85%, 22% 50%);
  box-shadow: 1px 3px 6px rgba(0,0,0,.3);
  animation: stickyPlaneBob .4s ease-in-out infinite alternate;
}
@keyframes stickyPlaneBob {
  from { transform: rotate(calc(var(--sticky-plane-angle, 0deg) - 5deg)) translateY(-2px); }
  to   { transform: rotate(calc(var(--sticky-plane-angle, 0deg) + 5deg)) translateY(2px); }
}

/* ═══════════════════════════════════════════════
   CHAT INTERNA — pulsante flottante + pannello (DM e gruppi di lavoro).
   I messaggi riusano .chat-msg/.chat-bubble/.chat-avatar/.chat-sender/.chat-time
   già definiti sopra per i commenti di task/Ortopedia/duelli Quiz — stesso
   linguaggio visivo, solo la lista conversazioni e il pannello sono nuovi.
═══════════════════════════════════════════════ */
.chat-fab {
  position: fixed; bottom: 20px; right: 20px; z-index: 950;
  width: 56px; height: 56px; border-radius: var(--r-full); border: none;
  background: var(--accent); /* stesso blu piatto di .btn-primary, non un colore nuovo di zecca */
  color: var(--su-accento);
  /* Era un'ombra colorata sull'accento ("l'alone segue il cliente"): la nuova
     direzione vieta gli aloni colorati e le ombre fuori dai due token previsti.
     Il pulsante fluttuante e' L2: shadow-1 e' la sua ombra corretta. */
  box-shadow: var(--shadow-1);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: transform .15s;
}
.chat-fab:hover { transform: scale(1.06); }
.chat-fab .material-icons-outlined { font-size: 25px; }
.chat-fab.bounce { animation: chatFabBounce .6s cubic-bezier(.34,1.56,.64,1); }
@keyframes chatFabBounce {
  0%   { transform: scale(1) rotate(0deg); }
  25%  { transform: scale(1.15) rotate(-8deg); }
  50%  { transform: scale(.95) rotate(6deg); }
  75%  { transform: scale(1.06) rotate(-3deg); }
  100% { transform: scale(1) rotate(0deg); }
}
.chat-fab-badge {
  position: absolute; top: -2px; right: -2px; min-width: 20px; height: 20px;
  /* Il ripiego #FF3B30 era un esadecimale a mano, e sui toni chiari e brillanti
     che --danger assume in tema scuro il testo bianco fisso scende sotto 4.5:1.
     var(--danger) e' gia' definito (=var(--red)) e su-colore e' la stessa coppia
     usata per ogni altro contrassegno pieno del progetto. */
  border-radius: var(--r-pill); background: var(--danger); color: var(--su-colore);
  font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center;
  padding: 0 5px; border: 2px solid var(--bg);
}
.chat-fab-badge.pop { animation: chatBadgePop .4s cubic-bezier(.34,1.56,.64,1); }
@keyframes chatBadgePop {
  0%   { transform: scale(0); }
  60%  { transform: scale(1.3); }
  100% { transform: scale(1); }
}

/* Fumetto di anteprima: appare sopra il pulsante quando arriva un messaggio ad
   app aperta, si dissolve da solo — cliccabile, apre dritto la conversazione. */
/* Fumetto non modale, sempre L2: bordo + --shadow-1, non un'ombra a mano.
   Su fondo card bianco/scuro il bordo serve a farlo staccare — a differenza
   del toast pieno colorato, qui senza bordo si perdeva contro la pagina. */
.chat-toast {
  position: fixed; bottom: 86px; right: 20px; z-index: 951;
  max-width: 280px; background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow-1); padding: 12px 16px;
  display: flex; gap: 10px; align-items: flex-start; cursor: pointer;
  animation: chatToastIn .45s cubic-bezier(.34,1.56,.64,1);
}
.chat-toast.hide { animation: chatToastOut .22s ease-in forwards; }
@keyframes chatToastIn {
  0%   { transform: translateY(16px) scale(.8); opacity: 0; }
  60%  { transform: translateY(-3px) scale(1.03); opacity: 1; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes chatToastOut { from { transform: translateY(0) scale(1); opacity: 1; } to { transform: translateY(10px) scale(.9); opacity: 0; } }
.chat-toast-title { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.chat-toast-text {
  font-size: 13px; color: var(--text2); overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

/* Non e' un modale (nessun velo dietro, si interagisce ancora col resto
   della pagina): e' un pannello flottante non modale, L2 come da §5 —
   bordo + --shadow-1, non l'ombra pesante da foglio. */
.chat-panel {
  position: fixed; bottom: 88px; right: 20px; z-index: 940;
  width: 370px; height: 560px; max-height: calc(100vh - 110px);
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--shadow-1);
  display: none; flex-direction: column; overflow: hidden;
}
.chat-panel.open { display: flex; }
@media (max-width: 600px) {
  /* A tutto schermo il bordo aggiunto qui sopra diventerebbe una cornice
     intorno all'intero schermo: si toglie solo qui. */
  .chat-panel { position: fixed; inset: 0; width: auto; height: auto; border-radius: 0; border: none; max-height: none; }
  /* env(safe-area-inset-*) — senza, il pulsante finisce sotto la curvatura dello
     schermo o dietro la barra home, invece di starne rispettosamente in disparte. */
  .chat-fab { bottom: calc(12px + env(safe-area-inset-bottom)); right: calc(22px + env(safe-area-inset-right)); }
  /* Solo qui il pulsante sparisce a pannello aperto, e per un motivo preciso:
     sotto i 600 il pannello e' a tutto schermo (inset: 0) e il pulsante, che
     sta piu' in alto nell'impilamento, coprirebbe la barra per scrivere. Da 601
     in su il pannello parte a 88px dal fondo e i due non si toccano: li' il
     pulsante resta, e serve anche a richiudere. */
  .chat-aperta .chat-fab { display: none; }
  .chat-toast {
    right: calc(16px + env(safe-area-inset-right)); left: calc(16px + env(safe-area-inset-left));
    max-width: none; bottom: calc(82px + env(safe-area-inset-bottom));
  }
  .chat-panel .chatw-header { padding-top: calc(14px + env(safe-area-inset-top)); }
  .chat-panel .chat-input-bar { padding-bottom: calc(12px + env(safe-area-inset-bottom)); }
}

.chatw-header {
  display: flex; align-items: center; gap: 10px; padding: 14px 16px;
  border-bottom: 1px solid var(--border); flex-shrink: 0; background: var(--surface, var(--card));
}
.chatw-header h3 { margin: 0; font-size: 16px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chatw-header-sub { font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }
.chatw-header-sub:empty { display: none; }
.chatw-header-sub.chatw-typing { color: var(--accent); font-style: italic; }

.chatw-list, .chatw-contacts-list { flex: 1; overflow-y: auto; position: relative; min-height: 0; }
/* Swipe-to-delete (stile Mail/WhatsApp, stessa tecnica di .task-swipe-wrap) */
.chatw-swipe-wrap { position: relative; overflow: hidden; touch-action: pan-y; }
.chatw-swipe-wrap .chatw-row { position: relative; z-index: 1; background: var(--card); }
/* Stesso fallback morto di sopra, e stesso #fff fisso: in scuro il rosso di
   sfondo (--red scuro, un corallo chiaro) con un'icona bianca fissa avrebbe
   meno contrasto di quanto dia --su-colore, calcolato apposta per i due temi. */
.chatw-swipe-bg { position: absolute; inset: 0; background: var(--danger); display: flex; align-items: stretch; justify-content: flex-end; }
.chatw-swipe-trash { width: 80px; border: none; background: transparent; color: var(--su-colore); display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; }
.chatw-swipe-trash .material-icons-outlined { font-size: 22px; }
/* Separatore su --gray6: in chiaro coincide col fondo app, in scuro e' quasi
   uguale alla riga stessa — una riga senza riga. --border e' il separatore
   che usa gia' .notif-item qui sopra. Gap 10 non era in griglia. */
.chatw-row { display: flex; align-items: center; gap: 8px; padding: 12px 16px; cursor: pointer; border-bottom: 1px solid var(--border); }
.chatw-avatar-wrap { position: relative; flex-shrink: 0; }
.chatw-group-badge {
  position: absolute; bottom: -3px; right: -3px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--accent); color: var(--su-accento); display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--card);
}
.chatw-group-badge .material-icons-outlined { font-size: 11px; }
.chatw-row:hover { background: var(--gray6); }
.chatw-row-info { flex: 1; min-width: 0; }
.chatw-row-top { display: flex; justify-content: space-between; gap: 6px; }
.chatw-row-name { font-size: 14px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chatw-row-time { font-size: var(--fs-xs); color: var(--text3); flex-shrink: 0; }
/* Da blocco con i puntini di sospensione a riga in fila, per far stare la
   spunta accanto all'anteprima. I puntini si spostano sul figlio che porta il
   testo: lasciandoli sul contenitore verrebbe accorciata anche la spunta, che
   sta in testa — e sparirebbe proprio l'informazione che si voleva dare. */
.chatw-row-preview { font-size: 13px; color: var(--text3); margin-top: 2px;
                     display: flex; align-items: center; gap: 4px; min-width: 0; }
.chatw-row-preview-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* La spunta non si lascia schiacciare da un'anteprima lunga, e qui non si clicca
   (nel thread invece apre l'elenco di chi ha letto). */
.chatw-row-preview .chat-receipt { flex: none; cursor: default; }
.chatw-row-preview.unread { color: var(--text); font-weight: 600; }
.chatw-row-badge {
  min-width: 20px; height: 20px; border-radius: var(--r-pill); background: var(--accent); color: var(--su-accento);
  font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center; padding: 0 4px; flex-shrink: 0;
}
.chatw-empty { padding: 40px 20px; text-align: center; color: var(--text3); font-size: 14px; }

/* Swipe-back animato: la lista è già pronta sotto (invisibile, pointer-events:none),
   .chatw-slide è lo strato in cima che trascini — vedi chatSwipeMove/End in app.js. */
.chatw-back-preview {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  pointer-events: none; z-index: 0;
}
/* E' la riga in trascinamento del rientro swipe-back: L2 anche questa,
   bordo + --shadow-1 invece dell'ombra direzionale scritta a mano. */
.chatw-slide {
  position: relative; z-index: 1; display: flex; flex-direction: column; flex: 1; min-height: 0;
  background: var(--card); border-left: 1px solid var(--border); box-shadow: var(--shadow-1);
}
.chatw-thread { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.chatw-messages { flex: 1; overflow-y: auto; padding: 12px 16px; display: flex; flex-direction: column; gap: 8px; }

/* Allegato dentro una bolla di chat */
/* Raggio annidato: la bolla intorno e' r-xl (18), con ~8px di margine
   interno il raggio corretto e' 18-8=10, cioe' r-sm — non un 12 a mano. */
.chat-att-image { display: block; max-width: 220px; max-height: 220px; border-radius: var(--r-sm); cursor: pointer; }
/* IMMAGINE SOPRA, TESTO SOTTO. La bolla e' una riga flessibile (contenuto +
   cestino accanto): immagine e testo ci stavano dentro come due colonne, e la
   colonna del testo — con word-break che permette di spezzare ovunque — si
   stringeva fino a una lettera per riga accanto all'immagine incollata.
   Ora stanno in un contenitore a colonna, largo quanto serve: l'immagine in
   cima, la didascalia sotto, come in ogni app di messaggi. */
.chat-bubble-content { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.chat-bubble-content .chat-text { flex: none; }
.chat-bubble-content .chat-att-image { max-width: 100%; }
/* Con un allegato la bolla parte larga almeno quanto l'immagine: una
   didascalia di due parole non la stringe attorno a se'. */
.chat-bubble-allegato .chat-bubble-content { min-width: min(220px, 100%); }
/* rgba a mano → token. Nella bolla propria il fondo e' l'accento: il
   riquadro dell'allegato e il suo testo devono restare leggibili anche in
   scuro, dove l'accento e' un pastello chiaro — --su-accento e' il colore
   pensato apposta, non un bianco fisso. Padding 10px fuori griglia. */
.chat-att-file {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--text) 6%, transparent); font-size: 13px; text-decoration: none; color: inherit;
}
.chat-mine .chat-att-file { background: color-mix(in srgb, var(--su-accento) 18%, transparent); color: var(--su-accento); }

/* La stessa anteprima dentro i dettagli di task e valutazioni: stessi margini
   laterali dei messaggi (20px) invece dei 16 del pannello chat. */
.detail-modal-chat .comment-attach-preview .chatw-attach-preview { padding-left: 20px; padding-right: 20px; }
.chatw-attach-preview {
  display: flex; align-items: center; gap: 8px; padding: 8px 16px; border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text2); background: var(--gray6);
}
/* E' proprio la "miniatura" della tabella dei raggi: r-xs, non r-sm. */
.chatw-attach-preview img { width: 34px; height: 34px; object-fit: cover; border-radius: var(--r-xs); }
.chatw-attach-preview .material-icons-outlined { font-size: 20px; }
.chatw-attach-preview .remove { margin-left: auto; cursor: pointer; color: var(--text3); }

/* Il contenitore serve solo a tenere la X dentro al campo: i margini restano
   dov'erano, sul campo, cosi' il resto del pannello non si sposta di un pixel. */
.chatw-search-wrap { position: relative; }
/* Margine 10px/14px lasciato com'e': la larghezza qui sotto e' calcolata
   apposta su quel margine (28px = 14*2) per riempire il contenitore, ed e'
   struttura di layout, non solo estetica — si tocca solo cio' che non la
   sposta di un pixel: bordo dei comandi (era --border, sotto al 3:1) e
   raggio (20px non era un gradino ammesso; a questa altezza r-lg produce
   comunque la stessa capsula quasi tutta arrotondata).
   Dall'08/09/2026 il tratto e' quello leggero come nelle altre ricerche
   dell'app: il campo qui e' gia' RIEMPITO (--gray6 sul pannello bianco), e
   il riempimento dice da solo dove si scrive — il bordo forte era la seconda
   volta che lo diceva. */
.chatw-search {
  width: 100%; box-sizing: border-box; margin: 10px 14px; width: calc(100% - 28px);
  padding: 8px 34px 8px 14px; border: 1px solid var(--bordo-scheda); border-radius: var(--r-pill);
  font-size: 14px; font-family: inherit; color: var(--text); background: var(--gray6);
}
/* Sovrapposta al campo, non accanto: accanto avrebbe accorciato il campo di
   trenta pixel per una cosa che si vede solo mentre si cerca. */
.chatw-search-x {
  position: absolute; top: 50%; right: 22px; transform: translateY(-50%);
  /* 24 e non 22: e' il bersaglio minimo che WCAG chiede per un comando
     (SC 2.5.8). Due pixel non si vedono, la differenza fra dentro e fuori
     norma si'. */
  display: grid; place-items: center; width: 24px; height: 24px;
  border: none; border-radius: 50%; cursor: pointer;
  background: var(--gray4); color: var(--card);
  padding: 0; line-height: 1;
}
.chatw-search-x:hover { background: var(--text3); }
.chatw-search-x .material-icons-outlined { font-size: 15px; }
/* Stessa .filter-chip già usata ovunque nell'app per i filtri dei task/ferie/ecc,
   solo un contenitore con padding adatto al pannello stretto invece di .filter-bar
   (pensata per la colonna task, molto più larga). */
.chatw-filter-bar { display: flex; gap: 8px; flex-wrap: wrap; padding: 0 16px 12px; }
.btn-icon.chatw-fav-active { color: var(--pink); }
.chatw-contact-row { display: flex; align-items: center; gap: 8px; padding: 12px 16px; cursor: pointer; }
.chatw-contact-row:hover { background: var(--gray6); }
.chatw-group-avatar {
  width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 15px; flex-shrink: 0;
}
/* .form-group label, .field-label { display:block; text-transform:uppercase; ... } ha
   specificità pari a .chatw-member-pick da sola e vinceva per ordine nel foglio di
   stile: checkbox/avatar/nome andavano a capo uno sotto l'altro, TUTTO MAIUSCOLO —
   serve un selettore più specifico per riprendere davvero il controllo qui. */
.form-group label.chatw-member-pick {
  display: flex; align-items: center; gap: 10px; padding: 8px 4px; cursor: pointer;
  margin-bottom: 0; text-transform: none; letter-spacing: normal;
  font-size: 14px; font-weight: 400; color: var(--text);
}
.chatw-member-pick input { width: 17px; height: 17px; flex-shrink: 0; }

#install-banner {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  background: var(--accent); color: var(--su-accento);
  border-radius: var(--r-xl); padding: 14px 16px;
  box-shadow: var(--shadow-2);
  z-index: 9000; width: calc(100% - 40px); max-width: 460px;
  animation: slideUp .3s ease-out;
}
/* slideUp non si ridefinisce: e' gia' identico piu' su, dove nasce il toast. */


/* ── La scelta del tema, nelle impostazioni ───────────────────────────────────
   Tre riquadri che MOSTRANO il risultato invece di descriverlo: "come il
   dispositivo" ne fa vedere due mezzi, perche' e' esattamente quello che fa. */
.tema-scelta { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.tema-opzione {
  flex: 1 1 0; min-width: 130px;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 14px 12px; border-radius: var(--radius); cursor: pointer;
  border: 1.5px solid var(--bordo-campo); background: var(--card);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text2);
  transition: border-color var(--transition), background var(--transition);
}
.tema-opzione:hover { background: var(--gray6); }
.tema-opzione.scelta {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
/* I due saggi restano di colore FISSO e non seguono i token: devono far vedere
   com'e' il tema chiaro e com'e' quello scuro anche mentre si sta guardando
   l'altro. Se seguissero i token, in tema scuro sarebbero due riquadri scuri
   uguali e la scelta non mostrerebbe piu' niente. */
.tema-saggio {
  width: 52px; height: 34px; border-radius: 8px; overflow: hidden;
  display: flex; box-sizing: border-box; border: 1px solid var(--gray3);
}
.tema-saggio i { flex: 1; display: block; }
.tema-saggio .chiaro { background: #f4f4f6; }
.tema-saggio .scuro  { background: #14171a; }
.tema-nota { display: block; margin-top: 10px; font-size: var(--fs-xs); color: var(--text3); }


/* La proposta "Scrivi a…" dentro al riquadro della ricerca a vuoto. Le righe
   riusano .chatw-contact-row del selettore "Nuovo messaggio": stesso aspetto,
   stesso modo di toccarle, nessun componente nuovo da mantenere. */
.chatw-suggerisci-testo { margin-bottom: 8px; }
#chatw-list-search-empty .chatw-contact-row { text-align: left; }


/* Chi ha inserito l'appuntamento: sta sotto la riga tecnico/data/ora, e deve
   leggersi solo se la si cerca. Riusa .apt-tpl-hint, gia' in uso nello stesso
   modale per l'avviso sulla trasferta: nessun componente nuovo. */
.apt-chi-crea { display: flex; align-items: center; gap: 5px;
                margin: -4px 0 12px; font-size: 12px; }


/* ── LA MESSA A FUOCO ────────────────────────────────────────────────────────
   Un contorno solo, per tutto: chi si muove con la tastiera deve sempre sapere
   dov'e'. :focus-visible e non :focus, cosi' non compare a chi clicca col mouse.
   Se una regola piu' avanti spegne l'outline senza rimettere qualcosa al suo
   posto, e' un difetto: lo cerca verifica-design.js. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* Chi ha chiesto meno movimento non deve subirne. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}


/* ── IL CARATTERE SCRITTO A MANO DEI POST-IT ─────────────────────────────────
   Un post-it scritto col carattere dell'interfaccia non sembra un post-it:
   sembra un riquadro giallo. E' l'unico punto dell'app dove il carattere porta
   un significato invece di limitarsi a essere leggibile.

   Servito da qui e non da Google, per gli stessi due motivi delle icone: senza
   rete deve esserci lo stesso, e ogni apertura non deve diventare una richiesta
   a un terzo.

   "swap" e non "block", al contrario delle icone: qui il ripiego e' un corsivo
   di sistema, cioe' del testo perfettamente leggibile — meglio mostrarlo subito
   e sostituirlo un istante dopo, che lasciare il post-it vuoto. Per le icone
   valeva l'opposto, perche' li' il ripiego e' la PAROLA "delete" al posto del
   cassonetto. */
@font-face {
  font-family: 'Caveat';
  font-style: normal;
  font-weight: 400 700;
  src: url('font/caveat.woff2') format('woff2');
  font-display: swap;
  /* Solo i caratteri latini: il file ne contiene un sottoinsieme, e dirlo evita
     che il browser lo scarichi per una pagina che non ne ha bisogno. */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ── Credito messaggi ───────────────────────────────────────────────────────
   Il saldo e' la cosa che si viene a guardare: sta in alto, grande, e cambia
   colore quando c'e' da preoccuparsi. I tagli della ricarica sono bottoni veri,
   non righe di listino: si arriva qui per premerne uno. */

/* L'ICONA IN TESTATA
   Sta fra le azioni della pagina agenda, l'ultima prima delle tre fisse.

   L'icona resta GRIGIA sempre, come tutte le altre: a parlare e' solo il
   pallino, che e' lo stesso segnale della campana delle notifiche — chi lavora
   sa gia' cosa vuol dire. Rosso quando il credito e' finito (i promemoria non
   partono piu'), arancione quando sta per finire. Quando ce n'e', niente: un
   pallino verde per dire "tutto a posto" e' un segnale acceso che non chiede
   niente, e a furia di vederlo non si guarda piu' nemmeno quando diventa rosso. */
.credito-icona { position: relative; }
.credito-pallino {
  position: absolute; top: 6px; right: 6px;
  width: 7px; height: 7px; border-radius: 50%;
  /* Un anello del colore della testata: senza, il pallino si confonde con
     l'icona che ha sotto invece di staccarsene. */
  box-shadow: 0 0 0 2px var(--bg);
}
.credito-pallino.pallino-basso  { background: var(--stato-attesa); }
.credito-pallino.pallino-finito { background: var(--danger); }

/* LA CONFERMA DELLA RICARICA
   Un riepilogo di spesa, non un avviso: niente segno grande al centro, testo a
   sinistra e cifre a destra, incolonnate come in fondo a un carrello.
   L'occhiello dice DOVE si e' (piccolo, spaziato); il titolo dice COSA si
   prende; a destra il prezzo, e sotto in grigio il totale con l'IVA.
   Il numero grosso e' l'imponibile: fra aziende l'IVA si recupera, e il prezzo
   che hanno in testa e' quello netto. */
.ric { padding: 22px 24px 18px; }
.ric-occhiello {
  font-size: 11.5px; font-weight: 600; letter-spacing: .6px; text-transform: uppercase;
  color: var(--text3); margin-bottom: 14px;
}
.ric-sommario {
  display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
  padding-bottom: 14px; border-bottom: 1px solid var(--border);
}
.ric-cosa { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ric-cosa strong { font-size: var(--fs-lg); font-weight: 600; color: var(--text); line-height: 1.2; }
.ric-cosa span { font-size: 12.5px; font-weight: 400; color: var(--text3); }
.ric-prezzo { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: none; }
.ric-prezzo strong {
  font-size: var(--fs-lg); font-weight: 600; color: var(--text);
  line-height: 1.2; font-variant-numeric: tabular-nums;
}
.ric-prezzo span { font-size: 12.5px; font-weight: 400; color: var(--text3); font-variant-numeric: tabular-nums; }
.ric-nota {
  margin: 12px 0 0; font-size: var(--fs-sm); font-weight: 400;
  line-height: 1.55; color: var(--text3);
}
.ric-nota strong { font-weight: 600; color: var(--text2); }

/* IL PANNELLO
   Piccolo di proposito: qui si viene per due cose, quanto resta e ricaricare.
   Tutto il resto — i movimenti — sta sotto, a un tocco. */
.modal.modal-stretto { max-width: 460px; }
.cred-modale-corpo { padding: 20px; }
.cred-storico {
  margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px;
}
.cred-storico > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--text3);
  list-style: none; padding: 2px 0;
}
.cred-storico > summary::-webkit-details-marker { display: none; }
.cred-storico > summary::before { content: '▸ '; }
.cred-storico[open] > summary::before { content: '▾ '; }
.cred-storico > summary:hover { color: var(--text); }

.cred-saldo {
  border: 1px solid var(--border); border-left: 4px solid var(--stato-fatto);
  border-radius: var(--r-md); background: var(--card);
  padding: 18px 20px; margin-bottom: 16px;
}
.cred-saldo.cred-basso  { border-left-color: var(--stato-attesa); }
.cred-saldo.cred-finito { border-left-color: var(--danger); }

.cred-saldo-num { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.cred-saldo-num strong {
  font-size: 34px; font-weight: 700; letter-spacing: -.02em; line-height: 1;
  color: var(--stato-fatto); font-variant-numeric: tabular-nums;
}
.cred-basso  .cred-saldo-num strong { color: var(--stato-attesa); }
.cred-finito .cred-saldo-num strong { color: var(--danger); }
.cred-saldo-num span { font-size: 14px; color: var(--text3); }
.cred-saldo-nota { font-size: 13px; color: var(--text3); margin-top: 8px; line-height: 1.5; }

.cred-righe { margin-bottom: 4px; }
.cred-righe > div {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 14px;
}
.cred-righe > div:last-child { border-bottom: 0; }
.cred-righe span { color: var(--text3); }
.cred-righe strong { font-variant-numeric: tabular-nums; }

.cred-titolo { font-size: 15px; margin: 0 0 6px; }

.cred-pacchetti {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; margin-top: 14px;
}
.cred-pacchetto {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 16px 18px; cursor: pointer; text-align: left;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--card); color: var(--text);
  transition: border-color .12s, transform .12s;
}
.cred-pacchetto:hover {
  border-color: var(--accent); transform: translateY(-1px);
}
.cred-pacchetto .cred-q {
  font-size: 24px; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.cred-pacchetto .cred-q-lab { font-size: 12px; color: var(--text3); margin-bottom: 10px; }
.cred-pacchetto .cred-p { font-size: 17px; font-weight: 600; color: var(--accent); }
.cred-pacchetto .cred-p-lab { font-size: 11.5px; color: var(--text3); }

.cred-mov { margin-top: 10px; }
.cred-mov-riga {
  display: grid; grid-template-columns: 88px 1fr auto; gap: 12px; align-items: baseline;
  padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13.5px;
}
.cred-mov-riga:last-child { border-bottom: 0; }
.cred-mov-data { color: var(--text3); font-variant-numeric: tabular-nums; }
.cred-mov-cosa em { font-style: normal; color: var(--text3); }
.cred-mov-delta { font-weight: 600; font-variant-numeric: tabular-nums; }
.cred-mov-delta.su  { color: var(--stato-fatto); }
.cred-mov-delta.giu { color: var(--text3); }

@media (max-width: 520px) {
  .cred-mov-riga { grid-template-columns: 1fr auto; }
  .cred-mov-data { grid-column: 1 / -1; }
}


/* ── Presidi di una valutazione su misura ───────────────────────────────────
   Il riepilogo di quello che si e' gia' aggiunto. Sta sopra al "+" e non e' un
   elenco puntato: sono voci che si possono togliere, e devono sembrarlo. */

.ortho-presidi { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.ortho-presidio-chip {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 5px 6px 5px 11px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  font-size: 13px; font-weight: 600;
}
.ortho-presidio-x {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: inherit; cursor: pointer; opacity: .65;
}
.ortho-presidio-x:hover { opacity: 1; background: color-mix(in srgb, var(--accent) 18%, transparent); }
.ortho-presidio-x .material-icons-outlined { font-size: 15px; }


/* ── LE LISTE NELLA COLONNA DI LETTURA ───────────────────────────────────────
   Stesso impianto di Task e delle Prenotazioni: la vista scorre, la barra dei
   filtri resta in cima (.vista-scorrevole se ne occupa da sola), e l'elenco sta
   nella larghezza di lettura invece di andare da bordo a bordo. Su uno schermo
   largo le righe arrivavano a due metri di distanza fra il nome del cliente e
   il suo stato, che e' il modo piu' rapido di leggere la riga sbagliata.

   Prima l'elenco stava in .apt-cl-list (rientro fisso di 16px) con sopra una
   striscia bianca a tutta larghezza per la sola ricerca: tre allineamenti
   diversi in tre fasce sovrapposte. */

.elenco-colonna { padding: 4px var(--rientro-lettura) 28px; }
/* Il tipo di pratica (Privata / ASL / INAIL) sulla riga dei dettagli, non
   davanti al nome: e' un attributo della pratica, non il suo soggetto. Con la
   pastiglia piena davanti si leggeva "ASL" e poi "Cordioli Teresa", cioe' la
   categoria prima della persona. Qui resta riconoscibile per colore e resta
   leggibile, ma non compete piu' col nome. */
.ortho-tag {
  font-weight: 700; font-size: var(--fs-micro); letter-spacing: .03em;
  color: color-mix(in srgb, var(--tinta-stato, var(--text3)) 72%, var(--text));
}
/* Le stesse misure che .apt-cl-list dava alle sue righe: qui cambia il
   contenitore, non l'aspetto delle righe. */
.elenco-colonna .list-card { box-shadow: var(--shadow); }
.elenco-colonna .list-row { padding: 14px 16px; }

/* Il selettore a schede dentro una barra di filtri: e' un elemento in fila
   accanto ai chip, non un blocco che occupa la riga — quindi non si stira e non
   spinge in basso quello che viene dopo. */
.seg-tab-bar.compatta { margin: 0; flex: none; }
.seg-tab-bar.compatta .seg-tab { flex: none; padding: 6px 14px; font-size: 13px; }

/* La ricerca chiude la barra a destra quando c'e' spazio: e' l'ultimo gesto
   della riga, non il primo. Sotto i 700px torna in fondo a tutta riga, perche'
   spinta a destra su una barra che va a capo finirebbe da sola in mezzo. */
/* ── LA BARRA DEI FILTRI A DUE ZONE ──────────────────────────────────────────
   A sinistra si sceglie cosa vedere, a destra si cerca. Sono due gesti opposti
   — restringere per categoria, cercare per nome — e stando in fila di seguito
   la ricerca sembrava appiccicata all'ultimo chip, come se fosse l'ottavo
   filtro. Ai due capi della stessa riga si leggono per quello che sono, e la
   ricerca finisce allineata al bordo destro delle schede, non a caso.
   Le due zone sono BLOCCHI: quando lo spazio finisce va a capo la zona intera,
   non l'ultimo pezzo di una fila. */
.filter-bar.due-zone { justify-content: space-between; align-items: center; }
.filter-bar .zona-filtri {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0;
}
.filter-bar .zona-cerca { flex: 0 1 280px; min-width: 220px; }
.filter-bar .zona-cerca .search-bar-wrap { max-width: none; width: 100%; }
/* Il filo verticale fra il selettore di vista e i filtri: dice che sono due
   gruppi, non nove comandi in fila. */
.filter-bar .sep-verticale {
  width: 1px; align-self: stretch; margin: 2px 4px;
  background: var(--bordo-scheda);
}
@media (max-width: 700px) {
  .filter-bar.due-zone .zona-cerca { flex: 1 1 100%; }
  .filter-bar .sep-verticale { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   REAZIONI RAPIDE AI MESSAGGI
   Una pastiglia appoggiata sul bordo basso della bolla, come nelle app di
   messaggi: sta addosso al messaggio a cui si riferisce, non in una riga a se'
   che lo allontana dall'orario. Icone del set dell'app, monocromatiche; la
   propria reazione nel colore dell'accento.
   ═══════════════════════════════════════════════════════════════════════════ */
.chat-reazioni-posto { display: flex; }
.chat-reazioni-posto:empty { display: none; }
.chat-reazioni {
  display: inline-flex; align-items: center; gap: 4px;
  position: relative; z-index: 1; margin-top: -8px;
  padding: 2px 8px; border-radius: 999px;
  /* Il fondo della PAGINA e non quello della scheda: la bolla di un collega ha
     gia' il fondo --card, e una pastiglia dello stesso colore ci spariva sopra —
     in tema scuro restavano solo le icone, appoggiate sul bordo. L'anello del
     colore della scheda la ritaglia sulla bolla, come nelle app di messaggi. */
  background: var(--bg); border: 2px solid var(--card);
  box-shadow: var(--shadow-1);
  font: inherit; color: var(--text2); cursor: pointer;
  transition: transform var(--t-stato);
}
.chat-reazioni:hover { transform: translateY(-1px); }
.chat-mine .chat-reazioni { margin-right: 8px; }
.chat-theirs .chat-reazioni { margin-left: 8px; }
.chat-reazione { display: inline-flex; align-items: center; gap: 2px; }
.chat-reazione .material-icons-outlined { font-size: 16px; }
.chat-reazione b { font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chat-reazione.mia { color: var(--accent); }

/* La fila delle tre reazioni in cima al menu del messaggio: tasti tondi grandi
   quanto un polpastrello, separati dalle azioni da un filo. */
.reazioni-barra {
  display: flex; justify-content: space-between; gap: 4px;
  padding: 4px 4px 8px; margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.reazioni-scelta {
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  background: none; border: 0; cursor: pointer; color: var(--text2);
  transition: transform var(--t-stato), background var(--t-stato), color var(--t-stato);
}
.reazioni-scelta:hover { background: var(--bg); color: var(--text); transform: scale(1.12); }
.reazioni-scelta .material-icons-outlined { font-size: 24px; }
.reazioni-scelta.scelta { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }

/* Occhiello e voci su due righe del menu a comparsa (chi ha reagito). */
.menu-occhiello {
  padding: 8px 12px 4px;
  font-size: 12px; font-weight: 600; letter-spacing: .6px; text-transform: uppercase;
  color: var(--text3);
}
.apt-dropdown-item.inerte { cursor: default; }
.apt-dropdown-item.inerte:hover { background: none; }
.voce-due-righe { display: flex; flex-direction: column; line-height: 1.3; text-align: left; }
.voce-due-righe span { font-weight: 500; }
.voce-due-righe small { font-size: 12px; font-weight: 400; color: var(--text3); }

/* Sul telefono il tocco prolungato apre il menu del messaggio: la selezione del
   testo e il fumetto nativo di iOS partirebbero nello stesso istante e se lo
   contenderebbero. Si copia con "Copia il testo" dal menu. */
@media (hover: none) {
  .chat-bubble { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
}

/* ── Stato del messaggio (chi l'ha ricevuto, chi l'ha letto) ─────────────── */
.ricevute-riassunto {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px;
  margin: 0 0 12px; padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
.ricevute-riassunto strong { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
.ricevute-riassunto span { font-size: var(--fs-sm); font-weight: 400; color: var(--text3); }
.ricevuta-riga { gap: 12px; }
.ricevuta-nome { flex: 1; min-width: 0; font-weight: 500; }
.ricevuta-stato {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--text3); font-variant-numeric: tabular-nums;
}
.ricevuta-stato.stato-recapitato { color: var(--text2); }
.ricevuta-stato.stato-letto { color: var(--blue); }
.ricevute-vuoto { margin: 0; padding: 8px 0; font-size: var(--fs-sm); color: var(--text3); }

/* ═══════════════════════════════════════════════════════════════════════════
   LE FOTO DI UNA VALUTAZIONE
   Miniature quadrate a riempimento, tagliate e non deformate; l'ultima casella
   aggiunge. La crocetta per togliere compare al passaggio del mouse, e sul
   telefono — dove il passaggio non esiste — resta sempre visibile.
   ═══════════════════════════════════════════════════════════════════════════ */
.ortho-foto-griglia {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px;
  border-radius: var(--r-md); transition: background var(--t-stato);
}
.ortho-foto-griglia.drag-over { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.ortho-foto {
  position: relative; aspect-ratio: 1 / 1; overflow: hidden;
  border-radius: var(--r-md); background: var(--gray6);
  border: 1px solid var(--bordo-scheda);
}
.ortho-foto-apri {
  display: block; width: 100%; height: 100%; padding: 0; margin: 0;
  background: none; border: 0; cursor: zoom-in;
}
.ortho-foto-apri:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ortho-foto img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Ancorato al riquadro (.ortho-foto e' relative) e non alle misure del
   pulsante: l'altezza di un figlio in percentuale dentro un riquadro che la
   prende da aspect-ratio non sempre si risolve, e il segno finiva in cima. */
/* Due classi e non una: icone.css si carica DOPO app.css, e la sua regola
   .material-icons-outlined, a parita di specificita, si riprendeva display e
   font-size. Il segno restava inline-block, in cima al riquadro, e piu piccolo. */
.ortho-foto .ortho-foto-rotta {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 28px; color: var(--text3);
}
.ortho-foto-togli {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px; border-radius: 50%; border: 0; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: rgba(0, 0, 0, .6); color: #fff;
  opacity: 0; transition: opacity var(--t-stato);
}
.ortho-foto-togli .material-icons-outlined { font-size: 16px; }
.ortho-foto:hover .ortho-foto-togli, .ortho-foto-togli:focus-visible { opacity: 1; }
@media (hover: none) { .ortho-foto-togli { opacity: 1; } }
.ortho-foto-carica {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
}
.ortho-foto-carica small { font-size: 12px; color: var(--text3); font-variant-numeric: tabular-nums; }
.ortho-foto-aggiungi {
  aspect-ratio: 1 / 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  border: 2px dashed var(--gray4); border-radius: var(--r-md); background: none;
  font: inherit; font-size: var(--fs-sm); color: var(--text3); cursor: pointer;
  transition: border-color var(--t-stato), color var(--t-stato), background var(--t-stato);
}
.ortho-foto-aggiungi .material-icons-outlined { font-size: 24px; }
.ortho-foto-aggiungi:hover, .ortho-foto-griglia.drag-over .ortho-foto-aggiungi {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.ortho-foto-conta {
  margin-left: 8px; padding: 0 8px; border-radius: 999px;
  background: var(--gray6); font-size: 12px; font-weight: 600; color: var(--text2);
  font-variant-numeric: tabular-nums;
}
/* Nel form la sezione sta fra i campi: stesso respiro sotto di un campo. */
.ortho-foto-nel-form { margin-bottom: 16px; }

/* ── NOTE SPESE ───────────────────────────────────────────────────────────────
   L'elenco delle note usa l'involucro comune (.task-group-riquadro con dentro
   le .task-card): quello che serve qui sono solo le misure di cio' che sta
   dentro una riga e dentro la nota aperta.

   L'importo sta a SINISTRA, prima del nome: in un elenco di rimborsi la prima
   cosa che si cerca e' quanto, non quale. E' incolonnato con tabular-nums, cosi'
   le cifre si leggono una sotto l'altra invece di ballare. */
.ns-riga-corpo { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
.ns-riga-importo {
  min-width: 88px; text-align: right; flex-shrink: 0;
  font-size: var(--fs-md); font-weight: 600; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.ns-riga-testo { flex: 1; min-width: 0; }
.ns-riga-testa { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ns-riga-titolo { font-weight: 500; }
.ns-riga-chi { font-size: var(--fs-xs); color: var(--text3); }
.ns-riga-meta { margin-top: 4px; font-size: var(--fs-xs); color: var(--text2); }
.ns-riga-freccia { color: var(--gray3); flex-shrink: 0; }

/* La nota aperta. */
.ns-testata {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-bottom: 16px;
}
.ns-testata-chi { font-size: var(--fs-md); font-weight: 600; }
.ns-testata-quando { font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }

/* La riga della firma: prima e' un invito, dopo e' una ricevuta. */
.ns-firma {
  display: flex; align-items: center; gap: 8px;
  padding: 12px; margin-bottom: 16px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--orange) 10%, transparent);
  color: var(--text2); font-size: var(--fs-xs);
}
.ns-firma .material-icons-outlined { color: var(--orange); font-size: 20px; }
.ns-firma.fatta { background: color-mix(in srgb, var(--green) 10%, transparent); }
.ns-firma.fatta .material-icons-outlined { color: var(--green); }

/* Le spese dentro la nota: righe di una stessa scheda, divise da un filo. */
.ns-spese { border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); overflow: hidden; }
.ns-spesa { padding: 12px; border-bottom: 1px solid var(--bordo-scheda); position: relative; }
.ns-spesa:last-child { border-bottom: none; }
.ns-spesa-testa { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.ns-spesa-titolo { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0; }
.ns-spesa-causale { font-weight: 500; }
.ns-spesa-data { font-size: var(--fs-xs); color: var(--text3); }
.ns-spesa-importo { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ns-spesa-dove { margin-top: 4px; font-size: var(--fs-xs); color: var(--text2); }
.ns-spesa-note { margin-top: 4px; font-size: var(--fs-xs); color: var(--text3); }
.ns-spesa-azioni { display: flex; gap: 4px; justify-content: flex-end; margin-top: 4px; }
.ns-vuoto { padding: 20px 12px; text-align: center; font-size: var(--fs-xs); color: var(--text3); margin: 0; }

/* Gli scontrini: pastiglie, non miniature. Una fotografia di uno scontrino
   rimpicciolita non si legge comunque, e in fila fanno un muro grigio. */
.ns-foto { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.ns-foto-uno {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px; border: 1px solid var(--bordo-scheda); border-radius: var(--r-full);
  background: var(--card); color: var(--text2); font-size: var(--fs-xs); cursor: pointer;
}
.ns-foto-uno .material-icons-outlined { font-size: 16px; color: var(--accent); }
/* Il nome del file al posto di "Scontrino": fra i documenti ci sono anche le
   fatture, e un PDF chiamato scontrino e' un'etichetta che mente. */
.ns-foto-uno > span:not(.material-icons-outlined):not(.ns-foto-togli) {
  max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ns-pdf { height: 75vh; }
.ns-pdf iframe { width: 100%; height: 100%; border: none; }
.ns-foto-uno:hover { background: color-mix(in srgb, var(--text) 4%, var(--card)); }
.ns-foto-togli { color: var(--red); display: inline-flex; margin-left: 4px; }
/* I documenti nel modulo della spesa: stessa gerarchia degli attrezzi di un
   servizio (.svc-eq-*) — righe, e sotto "+ Aggiungi un altro documento". */
.ns-doc-lista { margin-top: 0; }
.ns-doc-icona { display: inline-flex; color: var(--accent); margin-right: 8px; }
.ns-doc-icona .material-icons-outlined { font-size: 20px; }
.ns-doc-nome {
  background: none; border: none; padding: 8px 0; text-align: left; cursor: pointer;
  font-family: inherit; color: var(--text);
}
.ns-doc-nome:hover { color: var(--accent); }
.ns-doc-carica { width: 100%; margin-top: 0; }

.ns-aggiungi { width: 100%; margin-top: 12px; }
.ns-totale {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--bordo-scheda);
  font-size: var(--fs-xs); color: var(--text3);
}
.ns-totale strong { font-size: var(--fs-lg); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.ns-metodo { display: flex; align-items: center; gap: 4px; margin-top: 4px; font-size: var(--fs-xs); color: var(--text2); }
.ns-metodo .material-icons-outlined { font-size: 16px; }
.ns-azioni { display: flex; flex-direction: column; gap: 8px; margin-top: 20px; }
.ns-azioni .btn { margin-top: 0; }

/* La storia: chiusa di suo. Serve quando qualcosa non torna, non tutte le volte. */
.ns-storia { margin-top: 20px; }
.ns-storia summary {
  cursor: pointer; font-size: var(--fs-xs); color: var(--text3);
  display: flex; align-items: center; gap: 4px;
}
.ns-storia summary .material-icons-outlined { font-size: 16px; }
.ns-storia-riga {
  display: flex; gap: 8px; padding: 8px 0;
  border-bottom: 1px solid var(--bordo-scheda);
  font-size: var(--fs-xs); color: var(--text2);
}
.ns-storia-riga:last-child { border-bottom: none; }
.ns-storia-quando { color: var(--text3); white-space: nowrap; flex-shrink: 0; }
.ns-elimina-riga { text-align: center; margin-top: 20px; }

.ns-invio-testo { font-size: var(--fs-xs); color: var(--text3); margin: 0 0 16px; }
.ns-metodi { display: flex; gap: 8px; margin-top: 4px; }
.ns-metodo-scelta { flex: 1; cursor: pointer; }
.ns-metodo-scelta input { position: absolute; opacity: 0; pointer-events: none; }
.ns-metodo-scelta span {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 12px 8px; border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm);
  color: var(--text2); font-size: var(--fs-xs);
  transition: border-color var(--t-stato), background var(--t-stato), color var(--t-stato);
}
.ns-metodo-scelta input:checked + span {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.ns-metodo-scelta input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Impostazioni: la riga della causale, come quella degli attrezzi. */
.apt-admin-row-info.ns-admin-info { display: flex; flex-direction: column; gap: 2px; }
.apt-admin-row-info.ns-admin-info span { font-size: var(--fs-xs); color: var(--text3); }
.ns-spenta { color: var(--text3); text-decoration: line-through; }

/* Piano Ferie: gli appuntamenti gia' fissati dentro una chiusura appena messa. */
.pf-chiusura-elenco {
  margin: 12px 0 0; padding: 8px 12px 8px 32px; text-align: left;
  background: var(--gray6); border-radius: var(--r-sm);
  font-size: var(--fs-sm); line-height: 1.6; color: var(--text2);
  max-height: 220px; overflow-y: auto;
}
.pf-chiusura-tecnico { color: var(--text3); }

/* SOLO DEMO: il cambio di profilo in fondo alla sidebar, sopra l'avatar. */
.demo-profili {
  padding: 8px 12px; border-top: 1px solid var(--gray5);
  display: flex; flex-direction: column; gap: 8px;
}
.demo-profili:empty { display: none; }
.demo-profili-titolo {
  display: flex; align-items: center; gap: 4px;
  font-size: var(--fs-micro); letter-spacing: .06em; text-transform: uppercase;
  font-weight: 500; color: var(--text3);
}
.demo-profili-titolo .material-icons-outlined { font-size: 16px; }
/* Tre voci in una sidebar stretta: corpo e respiro ridotti, larghezze uguali. */
.seg-tab-bar.demo-profili-scelte { margin: 0; width: 100%; }
.seg-tab-bar.demo-profili-scelte .seg-tab {
  flex: 1; min-width: 0; padding: 4px 4px; font-size: var(--fs-xs); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-collapsed .demo-profili { display: none; }

/* Dettaglio task: la scheda del cliente e' quella dell'appuntamento, ma le
   pastiglie sono collegamenti (chiama, scrivi) e non pulsanti che correggono. */
a.apt-contatto { text-decoration: none; }
.task-cliente-scheda { margin-top: 0; }
.task-cliente-vuoto { font-size: var(--fs-xs); color: var(--text3); padding: 4px 8px; }

/* ── File condivisi gestiti (22/09/2026) ──────────────────────────────────────
   Le righe sono le solite .apt-admin-row; qui solo quello che serve a gestirle:
   il menu appoggiato alla riga, i bersagli del trascinamento, la scheda di
   caricamento, il registro. Colori sempre dai token: la cartella e' accent,
   il bersaglio e' un velo di accent, il pericolo e' rosso. */
.fc-riga { position: relative; }
.fc-riga-gest { touch-action: pan-y; }              /* lo scorrimento resta; il trascinamento parte dalla pressione lunga */
.fc-riga-info { cursor: pointer; }
.fc-riga-testo { min-width: 0; }
.fc-riga-meta { font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }
.fc-riga-icona { color: var(--text3); }
.fc-riga[data-type="folder"] .fc-riga-icona { color: var(--accent); }
.fc-briciole { font-size: var(--fs-sm); color: var(--text3); margin-bottom: 14px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.fc-crumb { color: var(--accent); text-decoration: none; padding: 2px 4px; border-radius: var(--r-sm); }
.fc-menu { top: 40px; }
.fc-dove { font-size: var(--fs-sm); color: var(--text3); margin: -4px 0 14px; }

/* Trascinamento: la riga di partenza sbiadisce, il bersaglio si accende. */
.fc-riga-sorgente { opacity: .35; }
.fc-drop-target {
  background: color-mix(in srgb, var(--accent) 12%, transparent) !important;
  outline: 2px dashed var(--accent); outline-offset: -2px; border-radius: var(--r-sm);
}
.fc-drop-attivo #fc-list { outline: 2px dashed var(--accent); outline-offset: 4px; }
.fc-ghost { background: var(--card); border: 1px solid var(--bordo-scheda); border-radius: var(--r-sm); box-shadow: var(--shadow-2); }
body.fc-trascina { user-select: none; -webkit-user-select: none; cursor: grabbing; }

/* La scheda di avanzamento sopra l'elenco. */
.fc-upload {
  display: flex; align-items: center; gap: 12px; padding: 12px 16px; margin-bottom: 12px;
  background: var(--card); border: 1px solid var(--bordo-scheda); border-radius: var(--r-md);
}
.fc-upload-testo { flex: 1; min-width: 0; }
.fc-upload-titolo { font-size: var(--fs-sm); font-weight: 600; }
.fc-upload-nome { font-size: var(--fs-xs); color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-upload-barra { height: 4px; background: var(--gray6); border-radius: 2px; margin-top: 6px; overflow: hidden; }
.fc-upload-barra i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .2s; }

/* Il conflitto di nome: occhiello, domanda, dettaglio (mai piatto). */
.fc-occhiello { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); margin: 0 0 6px; }
.fc-per-tutti { display: inline-flex; align-items: center; gap: 8px; margin-top: 14px; font-size: var(--fs-sm); color: var(--text2); cursor: pointer; }
.fc-per-tutti input { accent-color: var(--accent); width: 16px; height: 16px; }

/* Il selettore "Sposta in…". */
.fc-picker-testa { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.fc-picker-dove { font-size: var(--fs-sm); font-weight: 600; }
.fc-picker-lista { max-height: 50vh; overflow: auto; }

/* Ultime modifiche. */
.fc-att { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--bordo-scheda); }
.fc-att:last-child { border-bottom: none; }
.fc-att-icona {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent);
}
.fc-att-icona .material-icons-outlined { font-size: 18px; }
.fc-att-icona.upload, .fc-att-icona.replace, .fc-att-icona.mkdir { background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); }
.fc-att-icona.delete { background: color-mix(in srgb, var(--red) 14%, transparent); color: var(--red); }
.fc-att-testo { font-size: var(--fs-sm); }
.fc-att-quando { font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }

/* Avviso con un tasto ("Annulla"). */
.toast-azione { align-items: center; }
.toast-btn {
  background: transparent; color: inherit; border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  border-radius: var(--r-sm); padding: 4px 10px; font: inherit; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.toast-btn:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.fc-avviso { display: flex; align-items: flex-start; gap: 6px; font-size: var(--fs-xs); color: var(--text3); margin: -6px 0 12px; }
/* La nota accanto al nome del servizio in Integrazioni: "compreso nel piano". */
.svc-subcard-nota { font-size: var(--fs-xs); font-weight: 400; color: var(--text3); margin-left: 4px; }

/* ── Libreria schede PDF (Ortopedia) ─────────────────────────────────────────
   Stesse righe delle altre liste; in piu' le "cartelle" per produttore, che si
   aprono e chiudono, e la zona di trascinamento. */
.lib-corpo-modal { min-height: 40vh; }
.lib-barra { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.lib-sotto { font-size: var(--fs-xs); color: var(--text3); margin: 0 0 12px; }
.lib-corpo { display: flex; flex-direction: column; gap: 8px; }
.lib-prod-testa {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 10px 12px; background: var(--card); border: 1px solid var(--bordo-scheda);
  border-radius: var(--r-md); cursor: pointer; font: inherit; color: var(--text);
}
.lib-prod.aperto .lib-prod-testa { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.lib-prod-icona { color: var(--accent); }
.lib-prod-nome { flex: 1; font-size: var(--fs-sm); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-prod-n { font-size: var(--fs-xs); color: var(--text3); background: var(--gray6); padding: 2px 8px; border-radius: var(--r-full); }
.lib-prod-freccia { color: var(--text3); transition: transform .15s; }
.lib-prod.aperto .lib-prod-freccia { transform: rotate(180deg); }
.lib-prod-lista { border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; }
.lib-riga-icona { color: var(--red); }
.lib-vuota { text-align: center; padding: 32px 16px; color: var(--text3); font-size: var(--fs-sm); }
.lib-vuota .material-icons-outlined { font-size: 40px; display: block; margin: 0 auto 8px; color: var(--accent); }
.lib-vuota b { color: var(--text); }
.lib-drop-attivo .lib-corpo { outline: 2px dashed var(--accent); outline-offset: 4px; border-radius: var(--r-md); }
.lib-campo-prod { text-align: left; margin: 14px 0 0; }
.lib-settings-riga { font-size: var(--fs-sm); color: var(--text2); margin: 0 0 12px; }
.lib-quick-drive { color: var(--accent); font-weight: 500; }
@media (pointer: coarse) { .lib-solo-desktop { display: none; } }

/* ── Rimborso chilometrico (Note spese) ──────────────────────────────────────
   La tariffa e' un dato calcolato, non un campo: si mostra come valore con la
   sua fonte sotto. L'importo calcolato si vede che non si scrive. */
.km-tariffa { min-height: 40px; display: flex; flex-direction: column; justify-content: center; font-size: var(--fs-sm); color: var(--text2); }
.km-tariffa b { color: var(--text); }
.km-tariffa small { font-size: var(--fs-xs); color: var(--text3); }
input.km-calcolato { background: var(--gray6); color: var(--text2); }
.km-picker select[size] { height: auto; padding: 4px; }
.km-picker select[size] option { padding: 6px 8px; border-radius: var(--r-sm); }
.km-ricorda { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text2); margin: 4px 0 14px; cursor: pointer; }
.km-ricorda input { accent-color: var(--accent); width: 16px; height: 16px; }
.km-dove .material-icons-outlined { vertical-align: -3px; margin-right: 2px; }
.km-fonte { font-size: var(--fs-micro, 10px); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--accent); margin-left: 4px; }
.km-scelta { display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px; border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); margin-bottom: 8px; cursor: pointer; }
.km-scelta:has(input:checked) { border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 6%, var(--card)); }
.km-scelta input { accent-color: var(--accent); width: 18px; height: 18px; margin-top: 2px; flex: none; }
.km-scelta span { display: flex; flex-direction: column; gap: 2px; }
.km-scelta b { font-size: var(--fs-sm); }
.km-scelta small { font-size: var(--fs-xs); color: var(--text3); line-height: 1.4; }
.km-fisso { margin: 8px 0 0; }
.km-totale { display: flex; align-items: baseline; justify-content: space-between; padding: 10px 12px; margin: 0 0 14px; background: var(--gray6); border-radius: var(--r-md); font-size: var(--fs-sm); color: var(--text2); }
.km-totale b { font-size: var(--fs-lg); color: var(--text); }
.km-nota-anno { font-size: var(--fs-xs); color: var(--text3); margin: 6px 0 0; line-height: 1.4; }
.km-scelto { display: flex; align-items: center; gap: 12px; padding: 10px 12px; margin: 0 0 12px; border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card); }
.km-scelto > .material-icons-outlined { color: var(--accent); }
.km-scelto-testo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.km-scelto-testo b { font-size: var(--fs-sm); }
.km-scelto-testo small { font-size: var(--fs-xs); color: var(--text3); }
.km-totale > div { display: flex; flex-direction: column; gap: 2px; }
.km-totale small { font-size: var(--fs-xs); color: var(--text3); }
.km-ricorda small { color: var(--text3); font-weight: 400; }

/* ── Schede che si toccavano (22/09/2026) ────────────────────────────────────
   Nelle impostazioni il contenitore e' un blocco semplice, senza gap: due
   schede una dopo l'altra (Ortopedia: libreria + cartelle del drive; Note
   spese: rimborso km + causali) o l'elenco seguito dal riquadro "Aggiungi"
   (Noleggi, Attrezzature) finivano bordo contro bordo. Lo stesso stacco che
   c'e' altrove fra le schede: 14px. E un bottone seguito da una spiegazione
   non ci si appoggia sopra. */
.settings-content > .apt-admin-card + .apt-admin-card,
.settings-content > .apt-admin-card + .apt-admin-form,
.settings-tab-panel > .apt-admin-card + .apt-admin-card,
.settings-tab-panel > .apt-admin-card + .apt-admin-form { margin-top: 14px; }
.apt-tpl-card-body > .btn + .apt-tpl-hint { margin-top: 12px; }

/* Spostamento: il posto attuale dell'appuntamento resta visibile (tratteggio,
   nome all'inizio) ma e' cliccabile come ogni altra cella libera — cosi' si
   sposta anche di un quarto d'ora dentro la sua stessa fascia. */
.apt-slot-origine { background: color-mix(in srgb, var(--accent) 10%, transparent) !important; box-shadow: inset 2px 0 0 color-mix(in srgb, var(--accent) 60%, transparent), inset -2px 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
.apt-slot-origine-inizio { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--accent) 60%, transparent), inset -2px 0 0 color-mix(in srgb, var(--accent) 60%, transparent), inset 0 2px 0 color-mix(in srgb, var(--accent) 60%, transparent); position: relative; }
.apt-origine-nome { position: absolute; left: 8px; top: 4px; right: 8px; font-size: var(--fs-xs); font-weight: 600; color: var(--accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; }

/* ── La trasferta sulla scheda dell'appuntamento ─────────────────────────────
   In testa al blocco, alta quanto il viaggio, a righe diagonali: la stessa
   tinta dell'appuntamento ma velata, cosi' si legge "e' suo, ma non e' ancora
   dal cliente". Il resto della scheda resta com'era, sotto. */
.apt-appt-fill.con-trasferta { flex-direction: column; }
.apt-trasferta {
  flex: 0 0 auto; min-height: 0; overflow: hidden;
  display: flex; align-items: center; gap: 4px; padding: 0 8px;
  font-size: var(--fs-xs); font-weight: 600; color: color-mix(in srgb, #fff 88%, transparent);
  background: repeating-linear-gradient(135deg,
      color-mix(in srgb, #000 16%, transparent) 0 6px,
      color-mix(in srgb, #000 4%, transparent) 6px 12px);
  border-bottom: 1px dashed color-mix(in srgb, #fff 45%, transparent);
  cursor: pointer;
}
.apt-trasferta .material-icons-outlined { font-size: 14px; }
.apt-appt-riga { flex: 1 1 0; min-height: 0; display: flex; }

/* ── Password provvisoria e primo accesso (22/09/2026) ──────────────────────
   Occhiello, titolo, spiegazione, scheda con i dati, nota: la password e'
   l'unica cosa in evidenza, in cifre larghe e ben distinguibili. */
.pwdp-occhiello { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); }
.pwdp-intro { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 14px; font-size: var(--fs-sm); line-height: 1.55; color: var(--text2); }
.pwdp-intro .material-icons-outlined { color: var(--accent); font-size: 20px; flex: none; }
.pwdp-scheda { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; background: var(--bg2); border: 1px solid var(--bordo-scheda); border-radius: var(--r-md, 12px); }
.pwdp-riga { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pwdp-riga span { font-size: var(--fs-xs); color: var(--text3); }
.pwdp-riga strong { font-size: var(--fs-md, 15px); font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.pwdp-riga .pwdp-password { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 22px; letter-spacing: .08em; user-select: all; }
.pwdp-nota { display: flex; gap: 6px; align-items: center; margin: 12px 0 0; font-size: var(--fs-xs); color: var(--text3); }
.pwdp-nota .material-icons-outlined { font-size: 16px; }

/* ═══════════════════════════════════════════════════════════════════════════
   CONFIGURAZIONE GUIDATA — il wizard a tutto schermo
   Lo schema del percorso noleggi (colonna stretta, barra a segmenti, una
   domanda per schermata, schede grandi da toccare, bottone pieno in fondo)
   fatto coi token dell'app: stesso carattere, stessi colori, stesso buio.
   Sta sopra i pulsanti flottanti (950) e sotto i modal (1000).
   ═══════════════════════════════════════════════════════════════════════════ */
.wz {
  position: fixed; inset: 0; z-index: 980;
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--text);
  overflow-y: auto; overscroll-behavior: contain;
  padding-top: env(safe-area-inset-top);
  animation: wz-entra var(--t-appare, .25s) ease-out;
}
@keyframes wz-entra { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .wz { animation: none; } }

.wz-testata {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; max-width: 1100px; margin: 0 auto; padding: 20px 24px;
}
.wz-marchio { display: flex; align-items: center; gap: 10px; font-weight: 600; }
.wz-marchio img { height: 30px; width: auto; }
.wz-esci {
  background: none; border: 0; padding: 6px 4px; cursor: pointer; font-family: inherit;
  font-size: var(--fs-sm); color: var(--text3); text-decoration: underline; text-underline-offset: 3px;
}
.wz-esci:hover { color: var(--text2); }

/* Un passo del wizard è una pagina intera con dentro poche cose: gli spazi
   sono quelli di pagina (24 e 32), non quelli di una riga di elenco. */
.wz-colonna {
  width: 100%; max-width: 620px; margin: 0 auto;
  padding: 24px 24px calc(48px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
}
.wz-segmenti { display: flex; gap: 8px; margin-bottom: 12px; }
.wz-segmenti span { flex: 1; height: 4px; border-radius: var(--r-full); background: var(--border); transition: background var(--t-stato); }
.wz-segmenti span.on { background: var(--stato-fatto); }
.wz-segmenti span.ora { background: var(--accent); }
/* Maiuscoletto: 11px con +0.06em, come vuole la scala (DESIGN §2). */
.wz-dove {
  margin-bottom: 24px; font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--text3);
}
.wz-indietro {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 2px;
  margin: -4px 0 16px -6px; padding: 4px 6px; border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--accent);
}
.wz-indietro .material-icons-outlined { font-size: 20px; }

.wz-titolo {
  margin: 0 0 12px; font-size: var(--fs-xl); line-height: 1.2; letter-spacing: -0.02em;
  font-weight: 700; text-wrap: balance;
}
.wz-sotto {
  margin: 0 0 32px; font-size: var(--fs-md); line-height: 1.6; color: var(--text2);
  text-wrap: pretty;
}
.wz-sotto strong { color: var(--text); font-weight: 600; }
.wz-nota { font-size: var(--fs-xs); line-height: 1.5; color: var(--text3); display: inline-flex; align-items: center; gap: 4px; }
.wz-facoltativo { font-weight: 400; color: var(--text3); }
.wz-colonna .form-group { margin-bottom: 20px; }
.wz-colonna .error-msg { margin: 4px 0 0; }

.wz-eroe .material-icons-outlined { font-size: 52px; color: var(--accent); margin-bottom: 16px; }
.wz-eroe-fatto .material-icons-outlined { color: var(--stato-fatto); }

/* Il bottone che manda avanti: pieno, largo quanto la colonna. */
.wz-btn {
  width: 100%; margin-top: 32px; padding: 16px 20px; border: 0; border-radius: var(--r-md);
  background: var(--accent); color: #fff; font-family: inherit; font-size: var(--fs-md); font-weight: 600;
  cursor: pointer; transition: filter var(--t-stato), opacity var(--t-stato);
}
.wz-btn:hover { filter: brightness(1.06); }
.wz-btn:disabled { opacity: .5; cursor: default; }
.wz-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Saltare e' una risposta lecita, ma la piu' quieta. */
.wz-salta {
  align-self: center; margin-top: 16px; padding: 8px; border: 0; background: none; cursor: pointer;
  font-family: inherit; font-size: var(--fs-sm); color: var(--text3);
  text-decoration: underline; text-underline-offset: 3px;
}
.wz-salta:hover { color: var(--text2); }
/* "Aggiungine un'altra": tratteggiato, come "Aggiungi un altro articolo" nei noleggi. */
.wz-piu {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  margin-top: 16px; padding: 16px; border: 1.5px dashed var(--bordo-campo); border-radius: var(--r-md);
  background: none; color: var(--text2); font-family: inherit; font-size: var(--fs-base); font-weight: 600; cursor: pointer;
}
.wz-piu:hover { border-color: var(--accent); color: var(--accent); }

/* Le schede da toccare. */
.wz-opzioni, .wz-modelli { display: flex; flex-direction: column; gap: 12px; }
.wz-opt {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px; border: 1.5px solid var(--bordo-scheda); border-radius: var(--r-md);
  background: var(--card); color: var(--text); font-family: inherit; cursor: pointer;
  transition: border-color var(--t-stato), background var(--t-stato);
}
.wz-opt + .wz-opt { margin-top: 0; }
.wz-opt > .material-icons-outlined { color: var(--text3); font-size: 22px; flex: none; }
.wz-opt:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--bordo-scheda)); }
.wz-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wz-opt.scelta { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--card)); }
.wz-opt.scelta > .material-icons-outlined:first-child { color: var(--accent); }
.wz-opt-testo { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wz-opt-testo strong { font-size: var(--fs-base); font-weight: 600; }
.wz-opt-testo small { font-size: var(--fs-sm); line-height: 1.4; color: var(--text3); }
.wz-interruttore { margin-bottom: 12px; }
.wz-interruttore .toggle-switch { flex: none; pointer-events: none; }

/* Le tessere da scegliere a piu' d'una (famiglie di presidi). */
.wz-tessere { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.wz-tessera {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 14px 14px 13px; min-height: 74px; text-align: left; cursor: pointer; font-family: inherit;
  border: 1.5px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card); color: var(--text);
  transition: border-color var(--t-stato), background var(--t-stato);
}
.wz-tessera strong { font-size: var(--fs-base); font-weight: 600; padding-right: 26px; line-height: 1.25; }
.wz-tessera small { font-size: var(--fs-xs); color: var(--text3); }
.wz-tessera-segno {
  position: absolute; top: 12px; right: 12px; width: 22px; height: 22px; border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--bordo-campo); color: transparent;
}
.wz-tessera-segno .material-icons-outlined { font-size: 16px; }
.wz-tessera.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--card)); }
.wz-tessera.on .wz-tessera-segno { background: var(--accent); border-color: var(--accent); color: #fff; }
.wz-tessera:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Benvenuto: la scaletta dei passi. */
.wz-scaletta { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.wz-scaletta li { display: flex; align-items: center; gap: 14px; }
.wz-scaletta .material-icons-outlined {
  width: 40px; height: 40px; flex: none; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center; font-size: 22px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--card));
}
.wz-scaletta span { display: flex; flex-direction: column; }
.wz-scaletta strong { font-weight: 600; }
.wz-scaletta small { font-size: var(--fs-sm); color: var(--text3); }

/* Elenchi (sedi, persone). */
.wz-elenco { display: flex; flex-direction: column; border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card); overflow: hidden; }
.wz-voce { display: flex; align-items: center; gap: 12px; padding: 12px 14px; }
.wz-voce + .wz-voce { border-top: 1px solid var(--border); }
.wz-voce-icona .material-icons-outlined { color: var(--accent); }
.wz-voce-testo { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.wz-voce-testo strong { font-weight: 600; }
.wz-voce-testo small { font-size: var(--fs-sm); color: var(--text3); overflow-wrap: anywhere; }
.wz-voce .btn { width: auto; flex: none; }
.wz-tu { font-weight: 400; color: var(--text3); }

/* Il logo: un riquadro grande quanto serve a riconoscerlo. */
.wz-logo {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  width: 100%; min-height: 120px; padding: 16px; cursor: pointer; font-family: inherit;
  border: 1.5px dashed var(--bordo-campo); border-radius: var(--r-md); background: var(--card); color: var(--text2);
}
.wz-logo .material-icons-outlined { font-size: 30px; color: var(--accent); }
.wz-logo small { font-size: var(--fs-xs); color: var(--text3); }
.wz-logo.pieno { border-style: solid; border-color: var(--bordo-scheda); }
.wz-logo img { max-height: 72px; max-width: 80%; object-fit: contain; }
.wz-logo:hover { border-color: var(--accent); }

.wz-colori { margin-bottom: 18px; }
.wz-colonna .colore-su-misura { margin-bottom: 14px; }

.wz-griglia { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; }
.wz-griglia .wz-largo { grid-column: 1 / -1; }

/* Gli orari: un interruttore per giorno, due fasce. */
.wz-modelli { margin-bottom: 18px; }
.wz-modelli .wz-opt { padding: 12px 14px; }
.wz-orari { border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card); }
.wz-giorno { display: flex; align-items: center; gap: 12px; padding: 10px 14px; min-height: 52px; }
.wz-giorno + .wz-giorno { border-top: 1px solid var(--border); }
.wz-giorno-nome { display: flex; align-items: center; gap: 10px; width: 104px; flex: none; cursor: pointer; font-weight: 600; font-size: var(--fs-sm); }
.wz-giorno-nome input { width: 17px; height: 17px; accent-color: var(--accent); }
.wz-giorno.chiuso .wz-giorno-nome span { color: var(--text3); font-weight: 500; }
.wz-giorno-chiuso { font-size: var(--fs-sm); color: var(--text3); }
.wz-fasce { display: flex; flex-wrap: wrap; gap: 6px 14px; flex: 1; min-width: 0; }
.wz-fascia { display: inline-flex; align-items: center; gap: 4px; color: var(--text3); }
.wz-fascia input[type=time] {
  width: 86px; padding: 6px 6px; font-family: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--bg); color: var(--text);
  -webkit-appearance: none; appearance: none;
}

/* Le durate: un elenco in colonna, raggruppato, niente mosaico. */
.wz-durate { display: flex; flex-direction: column; gap: 18px; }
.wz-durate-gruppo h2 { margin: 0 0 6px; font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); }
.wz-durate-gruppo { border-bottom: 1px solid var(--border); padding-bottom: 10px; }
.wz-durata { display: flex; align-items: center; gap: 12px; padding: 6px 0; }
.wz-durata-nome { flex: 1; min-width: 0; font-weight: 500; }
.wz-durata select {
  width: 104px; padding: 7px 8px; font-family: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--card); color: var(--text);
}
.wz-online { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); color: var(--text2); cursor: pointer; width: 78px; }
.wz-online input { width: 16px; height: 16px; accent-color: var(--accent); }
.wz-aggiungi { display: flex; align-items: flex-end; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.wz-aggiungi .form-group { flex: 1; min-width: 180px; margin-bottom: 0; }
.wz-aggiungi .wz-aggiungi-durata { flex: 0 0 120px; min-width: 0; }
.wz-aggiungi .btn { width: auto; min-height: 48px; }  /* alto quanto i campi accanto */

/* Riepilogo finale e credenziali. */
.wz-riepilogo { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin-bottom: 16px; }
.wz-riepilogo div {
  display: flex; flex-direction: column; padding: 14px; border-radius: var(--r-md);
  border: 1px solid var(--bordo-scheda); background: var(--card);
}
.wz-riepilogo strong { font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.wz-riepilogo span { font-size: var(--fs-sm); color: var(--text3); }
.wz-riga-azioni { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.wz-riga-azioni .btn { width: auto; }
.wz-attesa { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 60px 0; color: var(--text3); }

@media (max-width: 560px) {
  .wz-testata { padding: 16px; }
  .wz-esci { white-space: nowrap; font-size: var(--fs-xs); }
  .wz-colonna { padding-left: 16px; padding-right: 16px; padding-top: 16px; }
  /* Un gradino della scala, non una misura inventata: 24px (fra --fs-lg e --fs-xl
     non c'e' niente, e 28 a 375px manda a capo i titoli lunghi). */
  .wz-titolo { font-size: 24px; }
  .wz-sotto { font-size: var(--fs-base); margin-bottom: 24px; }
  .wz-btn { margin-top: 24px; }
  .wz-griglia { grid-template-columns: 1fr; }
  .wz-giorno { flex-wrap: wrap; }
  .wz-giorno-nome { width: 100%; }
  .wz-fasce { padding-left: 27px; }
}

/* Il richiamo in Dashboard finche' la configurazione non e' finita. */
.cfg-banner {
  display: flex; align-items: center; gap: 14px; margin-bottom: 16px; padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--bordo-scheda));
  border-radius: var(--r-md); background: color-mix(in srgb, var(--accent) 6%, var(--card));
}
.cfg-banner-icona .material-icons-outlined { font-size: 24px; color: var(--accent); }
.cfg-banner-testo { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cfg-banner-testo strong { font-weight: 600; }
.cfg-banner-testo span { font-size: var(--fs-sm); color: var(--text3); }
.cfg-banner .btn { width: auto; flex: none; }
@media (max-width: 640px) { .cfg-banner { flex-wrap: wrap; } .cfg-banner .btn { width: 100%; } }

/* I recapiti in Aspetto: letti come un elenco, scritti in una griglia. */
.imp-recapiti { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px 20px; margin: 0; }
.imp-recapiti dt { font-size: var(--fs-xs); color: var(--text3); display: flex; align-items: center; gap: 4px; }
.imp-recapiti dd { margin: 2px 0 0; font-size: var(--fs-base); font-weight: 500; color: var(--text); overflow-wrap: anywhere; }
.imp-recapiti-form { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0 16px; }

/* Modalita prova del wizard (?wizard=prova): si dice chiaro che niente resta. */
.wz-prova {
  margin-left: 6px; padding: 3px 10px; border-radius: var(--r-full);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  color: color-mix(in srgb, var(--stato-attesa) 75%, var(--text));
  background: color-mix(in srgb, var(--stato-attesa) 16%, var(--card));
}
@media (max-width: 560px) { .wz-marchio { flex-wrap: wrap; } .wz-prova { margin-left: 0; } }

/* Un suggerimento sotto le scelte: dice dove si fa quello che qui non c e. */
.wz-suggerimento {
  display: flex; align-items: flex-start; gap: 8px; margin: 16px 0 0;
  font-size: var(--fs-sm); line-height: 1.5; color: var(--text2);
}
.wz-suggerimento .material-icons-outlined { font-size: 20px; color: var(--accent); flex: none; }
.wz-suggerimento strong { font-weight: 600; color: var(--text); }

/* Il secondo bottone delle schermate "a giro": lì il gesto principale è
   AGGIUNGERE (una sede, una persona), e "sono a posto" è la via d'uscita. */
.wz-btn.wz-btn-2 {
  margin-top: 10px; background: transparent; color: var(--text);
  border: 1.5px solid var(--bordo-campo); font-weight: 600;
}
.wz-btn.wz-btn-2:hover { filter: none; border-color: var(--accent); color: var(--accent); }
.wz-btn .material-icons-outlined { font-size: 20px; vertical-align: -4px; margin-right: 4px; }

/* Fine: ogni passo si riapre. */
.wz-rivedi { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.wz-rivedi-titolo { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); margin-bottom: 2px; }
.wz-rivedi .wz-opt { padding: 11px 14px; }

.wz-copia { margin: 14px 0 16px; }

/* Le fasce da appuntamenti: per ogni giorno di lavoro, mattina e pomeriggio. */
.wz-giorno-app { align-items: flex-start; }
.wz-giorno-app .wz-giorno-nome { padding-top: 8px; }
.wz-fasce-colonna { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.wz-fascia-app { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; }
.wz-fascia-app-nome { display: inline-flex; align-items: center; gap: 8px; width: 108px; font-size: var(--fs-sm); font-weight: 600; cursor: pointer; }
.wz-fascia-app-nome input { width: 17px; height: 17px; accent-color: var(--accent); }
.wz-fascia-app.spenta .wz-fascia-app-nome { color: var(--text3); font-weight: 500; }
.wz-fascia-app select {
  padding: 6px 8px; font-family: inherit; font-size: var(--fs-sm); max-width: 150px;
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--bg); color: var(--text);
}
.wz-fascia-app .wz-online { width: auto; }
.wz-fasce-app { margin-top: 14px; }
@media (max-width: 560px) {
  .wz-giorno-app .wz-giorno-nome { padding-top: 0; }
  .wz-fascia-app-nome { width: 100%; }
}

/* "Manca un servizio?": una scheda sua, con famiglia e tipo al posto del nome
   scritto a mano (sostituisce la riga unica di prima). */
.wz-aggiungi {
  display: block; margin-top: 22px; padding: 16px 16px 14px;
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card);
}
.wz-aggiungi h2 { margin: 0 0 4px; font-size: var(--fs-md); font-weight: 600; }
.wz-aggiungi > p { margin: 0 0 14px; font-size: var(--fs-sm); line-height: 1.5; color: var(--text3); }
.wz-aggiungi .form-group { flex: none; min-width: 0; margin-bottom: 12px; }
.wz-aggiungi-riga { display: flex; align-items: flex-end; gap: 10px; }
.wz-aggiungi-riga .wz-aggiungi-durata { flex: 0 0 150px; margin-bottom: 0; }

/* Famiglia e tipo, affiancati (wizard e Impostazioni → Agenda → Servizi). */
.svc-nome-campi { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
@media (max-width: 560px) { .svc-nome-campi { grid-template-columns: 1fr; } }

/* Storico del cliente: ogni riga porta al planner su quell appuntamento. */
.cl-hist-cliccabile { cursor: pointer; border-radius: var(--r-sm); margin: 0 -8px; padding-left: 8px; padding-right: 4px; transition: background var(--t-stato); }
.cl-hist-cliccabile:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.cl-hist-cliccabile:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cl-hist-vai .material-icons-outlined { font-size: 20px; color: var(--text3); }

/* ── Configurazione guidata, fase 2 ─────────────────────────────────────── */
.wz-griglia.wz-griglia-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.wz-proposte { display: flex; flex-direction: column; gap: 8px; margin: 18px 0 4px; }
.wz-proposte .wz-opt { padding: 11px 14px; }

/* Le sedi di una chiusura: pastiglie da accendere e spegnere. */
.wz-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.wz-chip {
  padding: 7px 14px; border-radius: var(--r-full); cursor: pointer; font-family: inherit;
  font-size: var(--fs-sm); font-weight: 600;
  border: 1.5px solid var(--bordo-campo); background: var(--card); color: var(--text3);
}
.wz-chip.on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--card)); }

/* Una spunta con la sua frase, fuori da un .form-group. */
.wz-spunta { display: flex; align-items: flex-start; gap: 10px; margin: 4px 0 14px; font-size: var(--fs-sm); color: var(--text2); cursor: pointer; line-height: 1.45; }
.wz-spunta input { width: 17px; height: 17px; margin-top: 1px; accent-color: var(--accent); flex: none; }

/* Le colonne del file dei clienti: cosa c'è dentro, e a cosa corrisponde. */
.wz-colonne .wz-voce select {
  width: 170px; flex: none; padding: 7px 8px; font-family: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--bg); color: var(--text);
}
.wz-progresso { height: 8px; border-radius: var(--r-full); background: var(--gray6); overflow: hidden; margin: 10px 0 12px; }
.wz-progresso i { display: block; height: 100%; background: var(--accent); transition: width var(--t-stato); }

/* Il link della prenotazione, da copiare. */
.wz-link {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card);
}
.wz-link code { flex: 1; min-width: 0; font-size: var(--fs-sm); overflow-wrap: anywhere; color: var(--text); }
.wz-link .btn { width: auto; flex: none; }

/* Riepilogo: le cose che attiva Orthosuite. */
.wz-voce-stato { border: 1px solid var(--bordo-scheda); border-radius: var(--r-md); background: var(--card); }
.wz-rivedi .wz-voce-stato + .wz-voce-stato { border-top: 1px solid var(--bordo-scheda); }

@media (max-width: 560px) {
  .wz-griglia.wz-griglia-3 { grid-template-columns: 1fr 1fr 1fr; gap: 0 8px; }
  .wz-colonne .wz-voce { flex-wrap: wrap; }
  .wz-colonne .wz-voce select { width: 100%; }
}

/* Benvenuto personale: istruzioni numerate e firma. */
.wz-istruzioni { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 10px; font-size: var(--fs-base); line-height: 1.5; color: var(--text2); }
.wz-istruzioni strong { color: var(--text); font-weight: 600; }
.wz-istruzioni .material-icons-outlined { vertical-align: -3px; }
.wz-firma { min-height: 110px; padding: 12px 14px; border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--card); color: var(--text); line-height: 1.5; }
.wz-firma:focus { outline: none; border-color: var(--accent); }
#wz #p-auto .apt-admin-card.apt-tpl-card { margin: 0; }

/* ── Editor della firma email ────────────────────────────────────────────
   Barra unica sopra l'area: menu per carattere e dimensione, poi pulsanti a
   gruppi separati da un filo. I pulsanti accesi dicono com'è il testo dove
   sta il cursore. Le due barre a comparsa (collegamento, immagine) stanno fra
   la barra e l'area, così non coprono quello che si sta scrivendo. */
.siged { display: flex; flex-direction: column; }
.siged-barra {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  padding: 6px; border: 1.5px solid var(--bordo-campo); border-bottom: 0;
  border-radius: var(--r-md) var(--r-md) 0 0; background: var(--gray6);
}
.siged-sel {
  height: 32px; padding: 0 6px; font-family: inherit; font-size: var(--fs-sm);
  border: 1px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--card); color: var(--text);
  max-width: 120px;
}
.siged-b {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; cursor: pointer; font-family: inherit;
  border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text2);
}
.siged-b:hover { background: var(--card); border-color: var(--bordo-campo); color: var(--text); }
.siged-b.on { background: color-mix(in srgb, var(--accent) 14%, var(--card)); border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--accent); }
.siged-b:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.siged-sep { width: 1px; height: 20px; background: var(--bordo-campo); margin: 0 4px; }
.siged-colore input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; padding: 0; border: 0; }
.siged-link, .siged-img {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px;
  border: 1.5px solid var(--bordo-campo); border-bottom: 0; background: var(--card);
  font-size: var(--fs-sm); color: var(--text2);
}
.siged-link[hidden], .siged-img[hidden] { display: none; }
.siged-link input {
  flex: 1; min-width: 160px; padding: 7px 10px; font-family: inherit; font-size: var(--fs-sm);
  border: 1.5px solid var(--bordo-campo); border-radius: var(--r-sm); background: var(--bg); color: var(--text);
}
.siged-link .btn, .siged-img .btn { width: auto; }
.siged .siged-area { border-radius: 0 0 var(--r-md) var(--r-md); min-height: 140px; }
.siged-area a { color: var(--accent); }
.siged-area img { cursor: pointer; }
.siged-area img.siged-scelta { outline: 2px solid var(--accent); outline-offset: 2px; }
.siged-area ul { margin: 0; padding-left: 22px; }

/* Dentro un .form-group la regola generica dei campi (padding 12px, larghezza
   piena) nasconderebbe il testo dei due menu: qui vince la misura della barra. */
.form-group .siged-sel, .siged .siged-sel { height: 32px; padding: 0 6px; width: auto; max-width: 128px; font-size: var(--fs-sm); border-width: 1px; }
.form-group .siged-link input { padding: 7px 10px; }

/* Attrezzature, "da preparare": rosso = tocca a te oggi, arancio = sei il
   sostituto e il responsabile c'e' (per conoscenza). Il pallino in sidebar e
   l'avviso sopra l'elenco usano gli stessi numeri e lo stesso colore. */
.sidebar-mod-badge.info { background: var(--orange); }
.eq-coda.urgente {
  background: color-mix(in srgb, var(--red) 7%, var(--card));
  border-color: color-mix(in srgb, var(--red) 26%, transparent);
}
button.eq-coda.urgente:hover { background: color-mix(in srgb, var(--red) 12%, var(--card)); }
.eq-coda.urgente .eq-coda-segno { background: color-mix(in srgb, var(--red) 14%, transparent); color: var(--red); }


/* ── Oltre l'orario (22/09/2026) ─────────────────────────────────────────────
   Un binario a righe oblique, bordo tratteggiato: e' il linguaggio delle cose
   "fuori dalla norma" (trasferta, chiusure velate). Il pomello si trascina con
   resistenza fino in fondo; sbloccato diventa una riga ambra con "Richiudi". */
.apt-oltre { margin: 12px 0 18px; }
.apt-oltre-binario {
  position: relative; height: 44px; border-radius: var(--r-pill); overflow: hidden;
  user-select: none; -webkit-user-select: none; touch-action: pan-y; outline: none;
  background: repeating-linear-gradient(135deg,
    color-mix(in srgb, var(--orange) 8%, var(--card)) 0 7px,
    color-mix(in srgb, var(--orange) 3%, var(--card)) 7px 14px);
  border: 1px dashed color-mix(in srgb, var(--orange) 45%, transparent);
}
.apt-oltre-binario:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--orange) 30%, transparent); }
.apt-oltre-scia {
  position: absolute; inset: 0 auto 0 0; border-radius: inherit; pointer-events: none;
  width: calc(var(--x, 0) * 1px + 44px);
  background: color-mix(in srgb, var(--orange) calc(10% + var(--p, 0) * 22%), transparent);
}
.apt-oltre-testo {
  position: absolute; inset: 0; padding-left: 46px; pointer-events: none;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 13px; font-weight: 600; color: var(--text);
  opacity: calc(1 - var(--p, 0) * 1.6);
}
.apt-oltre-testo span { font-weight: 400; color: var(--text2); }
.apt-oltre-testo::after {
  content: '›››'; letter-spacing: 1px; color: var(--orange); font-weight: 700;
  animation: apt-oltre-invito 1.8s ease-in-out infinite;
}
@keyframes apt-oltre-invito { 0%, 100% { opacity: .25; transform: translateX(0); } 50% { opacity: 1; transform: translateX(3px); } }
.apt-oltre-pomello {
  position: absolute; top: 2px; left: 2px; width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--orange); color: var(--su-colore); cursor: grab; touch-action: none;
  transform: translateX(calc(var(--x, 0) * 1px));
  box-shadow: 0 1px 2px rgba(0, 0, 0, .12), 0 2px 8px color-mix(in srgb, var(--orange) 35%, transparent);
}
.apt-oltre-pomello .material-icons-outlined { font-size: 20px; }
.apt-oltre.tieni .apt-oltre-pomello { cursor: grabbing; transform: translateX(calc(var(--x, 0) * 1px)) scale(1.06); }
.apt-oltre.torna .apt-oltre-pomello { transition: transform .5s cubic-bezier(.34, 1.56, .64, 1); }
.apt-oltre.torna .apt-oltre-scia    { transition: width .5s cubic-bezier(.34, 1.56, .64, 1); }
.apt-oltre.sbloccato .apt-oltre-binario { animation: apt-oltre-scatto .32s ease-out; }
@keyframes apt-oltre-scatto { 40% { transform: scale(1.015); } 100% { transform: scale(1); } }

.apt-oltre-aperto {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--orange) 9%, var(--card));
  border: 1px dashed color-mix(in srgb, var(--orange) 45%, transparent);
  animation: apt-oltre-entra .25s ease-out;
}
@keyframes apt-oltre-entra { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.apt-oltre-luna {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--orange) 16%, transparent); color: var(--orange);
}
.apt-oltre-luna .material-icons-outlined { font-size: 18px; }
.apt-oltre-aperto-testo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.apt-oltre-aperto-testo strong { font-size: var(--fs-base); font-weight: 600; }
.apt-oltre-aperto-testo span { font-size: var(--fs-xs); color: var(--text2); }
.apt-oltre-richiudi {
  flex-shrink: 0; background: none; border: 0; padding: 4px 2px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--accent);
}
.apt-oltre-richiudi:hover { text-decoration: underline; }

/* Nel planner: le righe aggiunte per il fuori orario sono velate a righe
   oblique, e l'appuntamento ha il bordo tratteggiato ambra. */
.apt-riga-oltre .apt-time-cell { color: var(--orange); }
.apt-riga-oltre .apt-slot-out {
  background: repeating-linear-gradient(135deg,
    color-mix(in srgb, var(--orange) 6%, var(--bg)) 0 6px, var(--bg) 6px 12px);
}
.apt-slot-appt.apt-appt-oltre .apt-appt-fill {
  background-image: repeating-linear-gradient(135deg, rgba(255, 255, 255, .13) 0 6px, transparent 6px 12px);
}

@media (prefers-reduced-motion: reduce) {
  .apt-oltre-testo::after, .apt-oltre.sbloccato .apt-oltre-binario, .apt-oltre-aperto { animation: none; }
  .apt-oltre.torna .apt-oltre-pomello, .apt-oltre.torna .apt-oltre-scia { transition: none; }
}


/* La propria cella fuori orario si tocca (22/09/2026): al passaggio compare la
   luna, come il + delle destinazioni di Sposta. */
.apt-slot-oltre-mio { cursor: pointer; position: relative; }
.apt-slot-oltre-mio::after {
  content: 'bedtime'; font-family: 'Material Icons Outlined';
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  color: var(--orange); font-size: 17px; opacity: 0; transition: opacity var(--transition);
}
.apt-slot-oltre-mio:hover {
  background: repeating-linear-gradient(135deg,
    color-mix(in srgb, var(--orange) 10%, var(--bg)) 0 6px, var(--bg) 6px 12px);
}
.apt-slot-oltre-mio:hover::after { opacity: .85; }
.apt-oltre.atteso .apt-oltre-binario { animation: apt-oltre-attesa 1.1s ease-out 2; }
@keyframes apt-oltre-attesa {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--orange) 45%, transparent); }
  100% { box-shadow: 0 0 0 10px transparent; }
}
@media (prefers-reduced-motion: reduce) { .apt-oltre.atteso .apt-oltre-binario { animation: none; } }


/* Il resto del modulo finche' "Oltre l'orario" non e' sbloccato. */
.apt-oltre-velato { opacity: .32; filter: grayscale(.6); transition: opacity .25s ease, filter .25s ease; }


/* ── Foto profilo (23/09/2026) ───────────────────────────────────────────────
   La foto sta DENTRO il cerchio delle iniziali e lo copre. Le iniziali restano
   sotto: se l'immagine non arriva, l'onerror toglie l'<img> e si rivedono. */
.avatar, .tbr-avatar { position: relative; overflow: hidden; }
.avatar-foto {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: inherit; display: block;
}
.quiz-podium-avatar { display: flex; justify-content: center; margin: 0 auto 6px; }


/* Scelta della foto profilo (o del gruppo): il cerchio grande, i due tasti,
   e la riga che dice dove finisce quella foto. */
.avatar-xl { width: 76px; height: 76px; font-size: 28px; }
.avatar-scelta { display: flex; align-items: center; gap: 16px; margin: 0 0 20px; }
.avatar-scelta-lato { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.avatar-scelta-azioni { display: flex; align-items: center; gap: 12px; }
.avatar-scelta-nota { margin: 0; font-size: var(--fs-xs); color: var(--text2); line-height: 1.45; }
.avatar-scelta-togli {
  background: none; border: 0; padding: 2px; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text3); text-decoration: underline;
}
.avatar-scelta-togli:hover { color: var(--danger); }
.avatar-scelta-attesa { opacity: .5; pointer-events: none; }
.wz-colonna .avatar-scelta { margin: 24px 0 28px; }


/* Il mio profilo: le schede stanno a 16 l'una dall'altra (griglia a 4, DESIGN
   §8 "fra schede"). Lo spazio lo mette il contenitore: prima ogni scheda si
   portava il suo margine in riga, e quella delle auto — disegnata a parte da
   kmProfiloRender — non ce l'aveva e si appiccicava alla precedente. */
#profile-tab-content > .apt-admin-card + .apt-admin-card,
#profile-tab-content > #p-auto > .apt-admin-card { margin-top: 16px; }

/* ── Piano Ferie: chi non ha l'orario di lavoro ────────────────────────────
   Sta in cima alla griglia perché è lì che lo vede chi può rimediare: un
   titolare apre il Piano Ferie tutte le settimane, la scheda di un utente quasi
   mai. Arancione e non rosso: non è andato storto niente, manca un dato — ma
   finché manca quelle persone non possono chiedere assenze, quindi non può
   nemmeno essere una notarella grigia. */
.pf-avviso-orario {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 12px; padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--orange) 38%, transparent);
  border-radius: 10px;
  background: color-mix(in srgb, var(--orange) 9%, var(--card));
  font-size: 13px; line-height: 1.5; color: var(--text);
}
.pf-avviso-orario .material-icons-outlined { font-size: 18px; color: var(--orange); flex: none; margin-top: 1px; }
.pf-avviso-orario strong { font-weight: 600; }
.pf-avviso-dove { display: block; margin-top: 2px; color: var(--text2); font-size: 12.5px; }

/* ── Gli appuntamenti annullati: da chi, e come si riconosce ─────────────────
   Nella stessa coda ci sono due cose diverse — quello che si è tolto il cliente
   da solo e quello che abbiamo cancellato noi. Si distinguono in TRE modi
   insieme: l'icona, la pastiglia con scritto chi, e la striscia colorata a
   sinistra. Il colore da solo non è un'informazione per chi non lo distingue,
   e una coda dove le due cose si confondono non serve a niente. */
.apt-ann { position: relative; padding-left: 14px; gap: 10px; }
.apt-ann::before {
  content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px;
  border-radius: 0 3px 3px 0;
}
.apt-ann-cliente::before { background: var(--danger); }
.apt-ann-noi::before     { background: var(--text3); }

.apt-ann-segno {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.apt-ann-segno .material-icons-outlined { font-size: 19px; }
.apt-ann-cliente .apt-ann-segno {
  background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger);
}
/* Quello cancellato da noi non è un allarme: è una traccia. Grigio, non rosso —
   se fossero tutti e due rossi la coda sembrerebbe tutta un problema. */
.apt-ann-noi .apt-ann-segno {
  background: color-mix(in srgb, var(--text2) 14%, transparent); color: var(--text2);
}

/* Acceso solo finché nessuno l'ha guardato, e solo per il cliente: quelli
   nostri li sappiamo già, li abbiamo fatti noi. */
.apt-ann-nuova { background: color-mix(in srgb, var(--orange) 10%, transparent); }
.apt-ann-pallino {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--danger); margin-right: 6px; vertical-align: middle;
}

.apt-ann-quando { color: var(--text3); font-size: 12px; margin-top: 2px; }
.apt-ann-coda { display: flex; align-items: center; gap: 8px; flex: none; }
.apt-ann-badge-noi {
  background: color-mix(in srgb, var(--text2) 15%, transparent); color: var(--text2);
}
.apt-ann-riprendi { color: var(--text3); }
.apt-ann-riprendi:hover { color: var(--accent); }

/* ── ABBONAMENTO (Impostazioni) ───────────────────────────────────────────────
   E' la schermata in cui il programma chiede di essere creduto sui soldi, e si
   legge in quest'ordine: lo stato (a colori, in cima), il pacchetto col
   prossimo addebito, con cosa si paga, quanto se ne usa, le fatture, e in
   fondo — piccola — la disdetta. Mai un pulsante rosso in una pagina dove non
   c'e' altro da fare: sarebbe un invito (25/09/2026). */
.abb-attesa {
  display: flex; align-items: center; gap: 8px;
  padding: 18px 2px; color: var(--text3); font-size: 14px;
}
.abb-card { margin-bottom: 16px; }

/* ── LE DUE COLONNE ─────────────────────────────────────────────────────────
   minmax(0, …) e non 1fr secco: senza, una tabella o una riga lunga dentro una
   colonna la fa crescere oltre la sua parte e manda l'altra fuori pagina. E'
   la stessa ragione per cui il planner usa minmax dappertutto. */
.abb-griglia {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 16px; align-items: start;
  /* Il gap vale FRA le celle, non sotto la griglia: senza questo le fatture
     si appoggiavano alla scheda sopra, mentre tutte le altre erano staccate. */
  margin-bottom: 16px;
}

/* Quanti messaggi restano: il numero si deve leggere senza cercarlo, e il
   colore lo prende solo quando c'e' da accorgersene. */
.abb-msg-quanti { margin: 0; font-size: 14px; color: var(--text2); }
.abb-msg-quanti b {
  font-size: 26px; font-weight: 700; letter-spacing: -.02em; color: var(--text);
}
.abb-msg-quanti.quasi b { color: var(--orange); }
.abb-msg-quanti.pieno { color: var(--danger); font-weight: 600; }
/* Dentro una colonna le schede si distanziano col gap della griglia, non col
   margine: due meccanismi di spaziatura sulla stessa cosa si sommano e
   scollano le due colonne. */
.abb-col { display: grid; gap: 16px; align-content: start; }
.abb-col .abb-card { margin-bottom: 0; }

@media (max-width: 900px) {
  .abb-griglia { grid-template-columns: 1fr; }
}

/* ── Lo stato, in cima ────────────────────────────────────────────────────
   Il colore, la parola e la frase arrivano tutti e tre dallo stesso campo
   (ABB_STATI in app.js): e' cosi' che si evita la schermata che dice "Attivo"
   in verde e sotto "il pagamento non e' andato a buon fine". */
.abb-fascia {
  display: flex; gap: 12px; align-items: flex-start;
  border-radius: var(--r-md); padding: 16px; margin-bottom: 16px;
  border: 1px solid transparent;
}
.abb-f-segno .material-icons-outlined { font-size: 24px; }
.abb-f-stato { margin: 0 0 4px; font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.abb-f-frase { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--text2); }
.abb-f-attivo  { background: color-mix(in srgb, var(--green) 10%, transparent); }
.abb-f-attivo  .abb-f-segno { color: var(--green); }
.abb-f-prova   { background: color-mix(in srgb, var(--blue) 10%, transparent); }
.abb-f-prova   .abb-f-segno { color: var(--blue); }
.abb-f-ritardo { background: color-mix(in srgb, var(--orange) 13%, transparent);
                 border-color: color-mix(in srgb, var(--orange) 34%, transparent); }
.abb-f-ritardo .abb-f-segno { color: var(--orange); }
.abb-f-chiuso  { background: var(--bg2); border-color: var(--border); }
.abb-f-chiuso  .abb-f-segno { color: var(--text3); }

/* ── Il prezzo ─────────────────────────────────────────────────────────────
   Grande il mese, piccolo l'anno: il numero con cui si e' scelto il pacchetto
   e' il primo, il totale annuo e' solo quello che arriva sulla carta. */
.abb-prezzo { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0 0 2px; }
.abb-prezzo b { font-size: 32px; font-weight: 700; letter-spacing: -.025em; }
.abb-prezzo span { font-size: 14px; color: var(--text2); }
.abb-prezzo small { font-size: 12px; color: var(--text3); }
.abb-prezzo-anno { margin: 0; font-size: 13px; color: var(--text3); }
.abb-piano-nota { margin: 10px 0 0; font-size: 13px; line-height: 1.5; color: var(--text2); }

/* Righe dato: etichetta a sinistra, valore a destra, una linea sottile in
   mezzo. E' la stessa forma delle altre schede di riepilogo dell'app. */
.abb-righe { margin: 16px 0 0; }
.abb-righe > div {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 9px 0; border-top: 1px solid var(--border);
}
.abb-righe dt { font-size: 13.5px; color: var(--text2); }
.abb-righe dd { margin: 0; font-size: 13.5px; text-align: right; font-variant-numeric: tabular-nums; }

.abb-invito {
  display: flex; gap: 10px; align-items: flex-start; margin: 16px 0 0;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  border-radius: var(--r-sm); padding: 12px 14px; font-size: 13.5px; line-height: 1.5;
}
.abb-invito .material-icons-outlined { font-size: 20px; flex: none; color: var(--accent); }
.abb-invito a { color: var(--accent); font-weight: 600; }

/* ── La carta ─────────────────────────────────────────────────────────────── */
.abb-carta { display: flex; align-items: center; gap: 10px; margin: 0; }
.abb-carta-segno .material-icons-outlined { font-size: 22px; color: var(--text3); }
.abb-carta b { font-size: 15px; font-variant-numeric: tabular-nums; }
.abb-carta small { display: block; font-size: 12.5px; color: var(--text3); margin-top: 2px; }
.abb-niente { margin: 0; font-size: 13.5px; color: var(--text3); }

.abb-avviso {
  display: flex; gap: 10px; align-items: flex-start;
  border-radius: var(--r-sm); padding: 12px 14px; margin: 12px 0 0;
  font-size: 13.5px; line-height: 1.5;
}
.abb-avviso .material-icons-outlined { font-size: 20px; flex: none; }
.abb-avviso-ritardo { background: color-mix(in srgb, var(--orange) 12%, transparent); }
.abb-avviso-ritardo .material-icons-outlined { color: var(--orange); }

/* ── Quanto se ne usa ──────────────────────────────────────────────────────
   La barra e' un dato, non una decorazione: cambia colore solo quando serve
   accorgersene, se no e' una fila di righe verdi che non dicono niente. */
.abb-consumi { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.abb-consumi li { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: baseline; }
.abb-c-nome { font-size: 13.5px; }
.abb-c-num { font-size: 13.5px; color: var(--text2); font-variant-numeric: tabular-nums; }
.abb-c-num b { color: var(--text); }
.abb-c-barra {
  grid-column: 1 / -1; height: 6px; border-radius: 3px;
  background: var(--bg2); overflow: hidden;
}
.abb-c-barra i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.abb-c-barra.quasi i { background: var(--orange); }
.abb-c-barra.pieno i { background: var(--danger); }

/* ── Le fatture ───────────────────────────────────────────────────────────── */
.abb-fatture { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.abb-fatture td { padding: 10px 8px; border-top: 1px solid var(--border); vertical-align: middle; }
.abb-fatture tr:first-child td { border-top: 0; }
.abb-fa-data { color: var(--text2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.abb-fa-num  { color: var(--text3); font-size: 12.5px; }
.abb-fa-tot  { text-align: right; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.abb-fa-giu  { text-align: right; width: 40px; }
.abb-fa-giu a { color: var(--text3); display: inline-flex; }
.abb-fa-giu a:hover { color: var(--accent); }
.abb-tag {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  background: var(--bg2); color: var(--text2);
}
.abb-tag-paid { background: color-mix(in srgb, var(--green) 16%, transparent); color: var(--green); }
.abb-tag-open { background: color-mix(in srgb, var(--orange) 16%, transparent); color: var(--orange); }

/* ── Come si smette ───────────────────────────────────────────────────────── */
.abb-fondo { margin-top: 4px; }
.abb-nota { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text3); }
.abb-solo-titolare {
  display: flex; align-items: center; gap: 6px;
  margin: 0; font-size: 13px; color: var(--text3);
}
/* Piccolo, e rosso solo quando ci si passa sopra: si trova senza fatica ma non
   chiama. E' la stessa regola di tutte le azioni che non si tornano indietro. */
.abb-disdici {
  font-size: 13px; color: var(--text3); text-decoration: underline;
  text-underline-offset: 2px; cursor: pointer;
}
.abb-disdici:hover { color: var(--danger); }

@media (max-width: 560px) {
  .abb-righe > div { flex-direction: column; gap: 2px; }
  .abb-righe dd { text-align: left; }
  .abb-fa-num { display: none; }   /* il numero non serve a riconoscerla: bastano data e importo */
}

/* ── NIENTE FRECCETTE SU E GIU' ───────────────────────────────────────────────
   Le due mezze freccette di <input type="number"> sono minuscole, stanno una
   sull'altra, e servono a spostarsi di uno alla volta: su un numero di utenti
   o di messaggi non e' mai quello che si vuole fare — si scrive il numero.
   Peggio: prendono il posto dell'ultima cifra, e su un campo stretto si finisce
   a cliccarle per sbaglio mentre si cerca di correggere quello che c'e'
   scritto. Si tolgono ovunque, in tutti e due i temi (25/09/2026).

   Il campo resta type="number": la tastiera del telefono resta quella
   numerica, e la validazione del browser pure. Sparisce solo il comando che
   non serviva. */
input[type=number] { -moz-appearance: textfield; appearance: textfield; }
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }


/* ── LA RIGA DI TESTA DEL MODULO APPUNTAMENTO, QUANDO NON SI TOCCA ───────────
   Tecnico, data e ora in modifica si leggono soltanto: per spostare c'e'
   «Sposta», che sul planner fa vedere dove si puo' andare. Restano gli stessi
   elementi disabilitati — il resto del modulo li legge per nome — ma non
   devono SEMBRARE campi: niente bordo, niente freccetta, niente cursore da
   testo. Un comando spento che sembra acceso e' peggio di un comando
   assente (25/09/2026). */
.apt-f-context-fissa select,
.apt-f-context-fissa input[type=date] {
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; padding: 0; cursor: default;
  color: var(--text); opacity: 1;      /* Safari sbiadisce i disabled: no */
}
.apt-f-context-fissa input[type=date]::-webkit-calendar-picker-indicator { display: none; }
.apt-f-sposta {
  display: inline-flex; align-items: center; gap: 5px;
  margin-left: auto; padding: 5px 11px;
  background: none; border: 1px solid var(--border); border-radius: var(--r-sm);
  font: inherit; font-size: 13px; color: var(--text2); cursor: pointer;
}
.apt-f-sposta:hover { color: var(--accent); border-color: var(--accent); }

/* La garanzia in fondo alla pagina Abbonamento: verde, perche' e' una buona
   notizia, e sopra il comando che la usa. Chi arriva in fondo a questa pagina
   di solito sta pensando di andarsene: e' l'ultimo momento utile per dirgli
   che non ci rimette niente (25/09/2026). */
.abb-garanzia {
  display: flex; gap: 10px; align-items: flex-start;
  margin: 0 0 14px; padding: 13px 15px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--green) 10%, transparent);
  font-size: 13.5px; line-height: 1.55;
}
.abb-garanzia .material-icons-outlined { font-size: 20px; flex: none; color: var(--green); }
