/* ============================================================
   ORDINE DEI LAYER — dichiarato qui perche' questo e' il primo CSS
   con layer che il browser incontra, e l'ordine si fissa alla prima
   apparizione. Cambiarlo qui cambia chi vince in tutta l'app.

     guardie   regole che devono vincere SEMPRE (vedi sotto)
     tokens    questo file
     vendor    Leaflet (via vendor/leaflet/leaflet-layer.css)
     base      il <style> inline di index.html (shell, login, card, modali)
     componenti preventivatore.css
     runtime   il CSS iniettato da JS: P2_CSS, nova.js, nova-fab.js,
               mappa-piattaforma.js
     tema      glass.css
     app       instaurus-app.css — il CSS nuovo del restyle

   L'ordine ricalca l'ordine di documento reale, quindi togliere gli
   !important non ha cambiato chi vince.

   LE DUE REGOLE DA RICORDARE, che sono opposte:
   - dichiarazioni NORMALI: vince il layer dichiarato per ULTIMO.
     Percio' `app` sta in fondo: il CSS nuovo vince senza !important.
   - dichiarazioni !important: vince il layer dichiarato per PRIMO,
     e un !important NON layerizzato perde contro qualunque !important
     layerizzato. Percio' `guardie` sta in testa: quello che ci mettiamo
     dentro con !important batte tutto, oggi e in ogni fase futura,
     compreso il CSS iniettato a runtime.

   NON aggiungere !important per far vincere una regola nuova: mettila
   nel layer giusto. Se serve davvero che vinca sempre, sta in `guardie`.

   FUORI DAI LAYER restano solo due cose, e per motivi diversi:
   - vendor/fonts/instaurus-fonts.css, che contiene solo @font-face e
     quindi non partecipa a nessuna gara;
   - i <style> che prev2-import-catalogo.js inietta nel <body>. Essendo
     ultimi in ordine di documento vincono su tutto il layerizzato: e'
     esattamente il comportamento di prima, e l'import catalogo si tocca
     per ultimo, quando sara' il suo turno.

   ATTENZIONE, e' la trappola che ci e' gia' costata un bug: una
   dichiarazione NORMALE non layerizzata batte QUALUNQUE dichiarazione
   normale dentro un layer, e la specificita' non conta piu'. Percio'
   lasciare fuori dai layer un foglio di terze parti significa dargli
   diritto di veto su tutto il CSS dell'app. E' successo con Leaflet: il
   fondo della mappa era tornato grigio. Ora Leaflet sta nel layer
   `vendor` — vedi vendor/leaflet/leaflet-layer.css.
   ============================================================ */
@layer guardie, tokens, base, vendor, componenti, runtime, tema, app;

/* ============================================================
   @layer guardie — le poche regole che devono vincere SEMPRE.
   ------------------------------------------------------------
   Sta per prima nell'ordine dei layer, e questo per gli !important
   vuol dire che vince su tutti gli altri: su glass.css, sul CSS che
   nova.js e preventivo2.js iniettano a runtime, e anche su un
   !important non layerizzato, che perde contro qualunque !important
   dentro un layer.

   E' l'UNICO posto del progetto dove !important e' legittimo. Se una
   regola nuova non vince, la risposta e' il layer giusto, non un
   !important qui dentro: qui ci sta solo cio' che non deve poter
   essere sovrascritto per sbaglio da nessuna fase futura.
   ============================================================ */
@layer guardie {

  /* ---- MOVIMENTO: rispetta la preferenza di sistema ----
     Prima la copertura era a macchia di leopardo: 6 media query in
     index.html, una in nova.js, una in nova-fab.js. Restavano scoperti,
     fra gli altri, l'apertura dei modali (ovlIn/modalIn), l'entrata del
     login (loginUp), lo spinner INFINITO del preventivatore (prev2spin),
     il cassetto laterale su mobile, la transizione globale su ogni
     `button`, tutte le transizioni di Nova e del FAB, e per intero
     prev2-import-catalogo.js, che non aveva alcuna copertura.

     Una regola sola li chiude tutti, presenti e futuri, compreso il CSS
     iniettato a runtime che nessuno strumento CSS vede.

     Perche' `.01ms` e non `none`: cosi' gli eventi animationend e
     transitionend continuano a scattare. Del codice ci si appoggia per
     sapere quando un pannello ha finito di aprirsi; con `none` quegli
     eventi non arrivano e resta appeso. Il movimento sparisce lo stesso.

     Cosa NON sparisce, ed e' voluto: i segnali di stato che passano dal
     colore. `.nova-rec` perde il battito ma resta rosso #C32A2A, quindi
     si continua a capire che sta registrando. */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: .01ms !important;
      animation-delay: .01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: .01ms !important;
      transition-delay: 0s !important;
      scroll-behavior: auto !important;
    }
  }

  /* ---- iOS: niente auto-zoom sui campi ----
     Su iPhone, toccando un input con font < 16px Safari ingrandisce la
     pagina e NON torna indietro: l'operatore si ritrova l'interfaccia
     zoomata in mezzo al cantiere e deve ridimensionare a mano. Forziamo
     >=16px solo su schermi piccoli; il desktop resta identico.
     Sta qui, e non fra i token, perche' deve battere anche gli stili
     iniettati a runtime (modale catalogo, chat di Nova) che non
     conoscono questa regola. */
  @media (max-width: 600px) {
    input, select, textarea { font-size: 16px !important; }
  }
  /* Nell'APP la soglia sale a 760px (data-pagina="app" sta solo su index.html):
     e' il confine sotto cui vivono la barra in basso e le schede del telefono,
     e fra 601 e 760 — iPhone SE in orizzontale, iPad mini — un campo da
     13,5px zoomava lo stesso. La landing e la scheda pubblica restano a 600. */
  @media (max-width: 760px) {
    html[data-pagina="app"] :is(input, select, textarea) { font-size: 16px !important; }
  }

  /* ---- La toolbar Backup/Ripristina/CSV, sul telefono ----
     funzioni-trasversali.js la monta nella .topbar con un display:flex
     INLINE, e la regola a 760px di instaurus-app.css che doveva nasconderla
     non ha mai potuto vincere su un inline: sul telefono restava li', e
     schiacciava il titolo di pagina a zero (visto a 390px il 07/09/2026).
     Sotto i 760px quelle tre funzioni stanno nel menu dell'account
     (app/guscio/telefono.js): qui si spegne la barra con l'unico peso che
     batte un inline, e solo nell'app. */
  @media (max-width: 760px) {
    html[data-pagina="app"] .topbar #ord-trasv-bar { display: none !important; }
  }

  /* ---- .hidden: non e' decorazione ----
     supabase.js la usa 13 volte per commutare fra schermata di accesso e
     applicazione. Se perde, non si entra. */
  .hidden { display: none !important; }

}
/* fine @layer guardie */

/* ============================================================
   INSTAURUS — Design Tokens ("Sabbia" chiaro / "Notturna" scuro)
   ------------------------------------------------------------
   Va importato PER PRIMO, prima di ogni altro CSS. Nei componenti si
   usano le variabili SEMANTICHE (--bg, --ink, --action...), mai i
   valori grezzi: e' quello che rende possibile cambiare tema senza
   rincorrere i colori dentro cinquanta file.

   I FONT NON VANNO PRESI DA GOOGLE. Sono self-hostati: collega
   vendor/fonts/instaurus-fonts.css PRIMA di questo file. Il perche'
   per esteso e' in testa a quel file (service worker + CSP).

   ------------------------------------------------------------
   COME SI SCEGLIE UN TOKEN, in ordine di domanda:

   1) E' un FONDO?            --bg / --surface / --surface-2
   2) E' TESTO?               --ink / --ink-muted
                              su un riempimento: --*-on
   3) E' un'AZIONE primaria?  --action (+ --action-on, --action-strong)
   4) E' NOVA?                --accent (+ --accent-on, --accent-text)
   5) E' uno STATO?           --ok / --warn / --err (+ --*-text, --*-on)
   6) E' una LINEA?           --line, decorativa
                              --line-strong, se e' il bordo di un campo

   ------------------------------------------------------------
   LE DUE REGOLE CHE NON SI NEGOZIANO

   A. L'ORO E' UN RIEMPIMENTO, MAI TESTO SU FONDO CHIARO.
      --accent (#C39A3E) su --bg (#EAE5DA) da' 2,09:1. La soglia AA per
      il testo e' 4,5:1: e' meno della meta'. Quando l'oro deve essere
      testo su chiaro si usa --accent-text (#6F5316, 5,72:1).
      Nel tema scuro i due COINCIDONO, quindi il codice non ha bisogno
      di condizionali: si usa sempre il token del ruolo, e il tema fa
      la cosa giusta da solo.

   B. L'ORO E' NOVA, E SOLO NOVA.
      Non e' il colore delle azioni primarie, non e' "successo", non e'
      decorazione. Serve a far riconoscere l'assistente in mezzo
      all'interfaccia: se lo si sparge ovunque smette di significare
      qualcosa. Le azioni primarie usano --action (inchiostro pieno),
      che nei due temi si inverte da solo.

   ------------------------------------------------------------
   CONTRASTO. Ogni coppia testo/fondo qui sotto e' stata misurata con
   la formula WCAG 2.x, non stimata a occhio. I numeri in commento sono
   nell'ordine  --bg / --surface / --surface-2.
   Due valori arrivavano dal brief sotto soglia e sono stati scuriti a
   parita' di tinta: --ink-muted (era #6E6A5F, 4,30/4,83/3,84) e
   --accent-text (era #7E5F1C, 4,72/5,30/4,22).
   ============================================================ */

@layer tokens {

/* ============ TEMA CHIARO — "Sabbia" (DEFAULT) ============ */
:root,
[data-theme="sabbia"] {

  /* ---- Fondi ---- */
  --bg:              #FCFAF5;  /* sfondo pagina, carta luminosa */
  --surface:         #FFFFFF;  /* schede e pannelli in rilievo */
  --surface-2:       #F6F1E8;  /* aree incassate, campi, righe zebrate */
  --surface-inverse: var(--shell);

  /* ---- Testo ---- */
  --ink:             #221E17;  /* primario    15,12 / 16,32 / 13,97 */
  --ink-muted:       #6B6353;  /* secondario   5,42 /  5,84 /  5,00 */
  --ink-on-dark:     #F8F4EC;  /* testo sopra --surface-inverse */

  /* ---- Linee ---- */
  --line:            #E9E2D6;  /* divisori: decorativi, opachi come nel mockup */
  --line-strong:     #8C8270;  /* bordo dei campi  3,45 / 3,73 / 3,19
                                  WCAG 1.4.11: il bordo e l unico modo
                                  per riconoscere l elemento, servono 3:1 */

  /* ---- AZIONE PRIMARIA — inchiostro pieno, non oro ----
     Un bottone pieno di inchiostro con testo carta: 12,47:1, e nel tema
     scuro si inverte da solo restando altrettanto leggibile. */
  --action:          #221E17;
  --action-strong:   #100E0A;  /* hover / premuto */
  --action-on:       #FFFDF8;  /* testo sopra --action        16,32 */
  --action-soft:     rgba(34,30,23,.08);
  --action-text:     #221E17;  /* l'azione come TESTO (link)  15,12 / 16,32 / 13,97 */

  /* ---- NOVA — l'accento oro. Vedi regola B. ---- */
  --accent:          #B08A3C;  /* SOLO riempimenti: badge, pastiglie, blocchi */
  --accent-on:       #231B08;  /* testo sopra --accent          5,31 */
  --accent-text:     #7A5D14;  /* l'oro come TESTO su chiaro  5,62 / 6,07 / 5,20 */
  --accent-soft:     rgba(176,138,60,.20);

  --focus:           #7A5D14;

  /* Nova che ascolta e Nova che parla: due segnali di STATO, non due
     decorazioni. Restano fuori dalla scala oro perche non dicono
     "assistente" ma "ti sto sentendo" / "sto rispondendo", e vivono
     sempre sul pannello scuro di Nova. */
  --nova-ascolto:  rgba(255,165,145,.55);   /* corallo */
  --nova-parla:    rgba(160,245,205,.60);   /* menta   */
  --nova-urgente:  #FF8570;                 /* avviso ad alta severita, 5,5:1 su scuro */

  /* Le stesse due tinte in forma PIENA, per quando devono essere INCHIOSTRO e
     non riempimento. Le tre righe qui sopra sono tinte da anello: translucide,
     giuste addosso a un bordo e sbagliate come testo — il corallo a .55 sul
     guscio composita a 3,42:1, sotto la soglia. Queste sono opache e misurate
     su --shell, in Sabbia e in Notturna:
       --nova-ascolto-ink  7,93 / 8,93     --nova-parla-ink  11,80 / 13,30
       --nova-ok           7,15 / 8,06     --nova-rec        2,65 / 2,98
     --nova-rec e' l'unica sotto soglia, ed e' un RIEMPIMENTO, non un testo: e'
     il disco del comando mentre registra, e il significato non ce l'ha la tinta
     ma il quadrato di stop sopra (bianco sul rosso: 5,09:1) piu' la parola
     REGISTRA scritta sotto. E' il rosso del mockup, e batte comunque --err, che
     su questo fondo fa 2,00.
     Identiche nei due temi, come le tre sopra e per lo stesso motivo: il
     pannello di Nova e' scuro anche nel tema chiaro. Non toccano la scala oro
     e non entrano da nessun'altra parte del prodotto. */
  --nova-ascolto-ink: #FFA591;
  --nova-parla-ink:   #A0F5CD;
  --nova-ok:          #8FBF86;
  --nova-rec:         #C32A2A;

  /* ---- Superfici scure ----
     Barra laterale, barra in alto e testata della dashboard restano a
     inchiostro pieno anche nel tema chiaro: e' il carattere dell'app, e
     un gestionale che il cantiere guarda in controluce ci guadagna un
     bordo netto fra navigazione e contenuto. Su quelle superfici il
     testo e l'evidenza non seguono --ink, che li' sarebbe invisibile. */
  --shell:           #241F18;  /* barra laterale, barra in alto, testata */
  --shell-2:         #1B1712;  /* il piano piu profondo dentro il guscio */
  --shell-alto:      #2E2820;  /* elemento sollevato sul guscio */
  --shell-line:      rgba(248,244,236,.12);
  --on-dark-ink:     #F8F4EC;  /* 13,29 sul guscio */
  --on-dark-muted:   rgba(248,244,236,.64);  /* 6,35 sul guscio, alfa compositata */
  --on-dark-accent:  #F8F4EC;  /* voce attiva, nome nel saluto */
  --on-dark-line:    rgba(248,244,236,.12);
  --on-dark-soft:    rgba(248,244,236,.10);  /* tinta di passaggio sul guscio */

  /* ---- Ombre e veli ---- */
  --ombra:           rgba(120,96,44,.14);  /* ombre CALDE: e il passaggio di Alabastro */
  --ombra-forte:     rgba(120,96,44,.30);
  --velo:            rgba(34,30,23,.42);  /* dima dietro modali e cassetto */
  --alone:         var(--action-soft);   /* bagliore sotto un elemento attivo */

  /* ---- Stati ---- */
  --ok:            #3D6B4A;  --ok-on:   #FFFFFF;  /* 6,18 */
  --ok-text:         #356043;  /* 6,59 / 7,11 / 6,09 */
  --ok-soft:         #E3EDE4;
  --warn:          #8A6410;  --warn-on: #FFFFFF;  /* 5,37 */
  --warn-text:       #7E5B0D;  /* 5,65 / 6,09 / 5,22 */
  --warn-soft:       #FAF0DA;
  --err:           #B8452F;  --err-on:  #FFFFFF;  /* il toro, 5,34 */
  --err-text:        #9E3A27;  /* 6,20 / 6,69 / 5,73 */
  --err-soft:        #F9E5E0;

  --shadow-1:        0 1px 2px rgba(120,96,44,.06), 0 1px 3px rgba(120,96,44,.10);
  --shadow-2:        0 24px 50px -22px rgba(120,96,44,.28);

  color-scheme: light;
}

/* ============ TEMA SCURO — "Notturna" ============ */
[data-theme="notturna"] {

  --bg:              #151310;
  --surface:         #1D1A16;
  --surface-2:       #12100D;
  --surface-inverse: var(--shell);

  --ink:             #F5F1E8;  /* 16,45 / 15,38 / 16,85 */
  --ink-muted:       #A79E8D;  /*  6,99 /  6,54 /  7,16 */
  --ink-on-dark:     #221E17;  /* qui "dark" e la superficie CHIARA invertita */

  --line:            rgba(245,241,232,.10);
  --line-strong:     #7C7466;  /* 4,01 / 3,75 / 4,11 */

  /* L'azione si inverte: carta piena su fondo grafite. */
  --action:          #F5F1E8;
  --action-strong:   #FFFFFF;
  --action-on:       #1D1A16;  /* 15,38 */
  --action-soft:     rgba(245,241,232,.10);
  --action-text:     #F5F1E8;  /* 16,45 / 15,38 / 16,85 */

  /* Sul fondo scuro l'oro pieno e' leggibile: --accent e --accent-text
     coincidono, e il codice che usa il token giusto non se ne accorge. */
  --accent:          #C9A653;
  --accent-on:       #221B08;  /* 7,38 */
  --accent-text:     #D8B96A;  /* 9,77 / 9,13 / 10,01 */
  --accent-soft:     rgba(201,166,83,.15);

  --focus:           #C9A653;

  /* Nova che ascolta e Nova che parla: due segnali di STATO, non due
     decorazioni. Restano fuori dalla scala oro perche non dicono
     "assistente" ma "ti sto sentendo" / "sto rispondendo", e vivono
     sempre sul pannello scuro di Nova. */
  --nova-ascolto:  rgba(255,165,145,.55);   /* corallo */
  --nova-parla:    rgba(160,245,205,.60);   /* menta   */
  --nova-urgente:  #FF8570;                 /* avviso ad alta severita, 5,5:1 su scuro */

  /* Le stesse due tinte in forma PIENA, per quando devono essere INCHIOSTRO e
     non riempimento. Le tre righe qui sopra sono tinte da anello: translucide,
     giuste addosso a un bordo e sbagliate come testo — il corallo a .55 sul
     guscio composita a 3,42:1, sotto la soglia. Queste sono opache e misurate
     su --shell, in Sabbia e in Notturna:
       --nova-ascolto-ink  7,93 / 8,93     --nova-parla-ink  11,80 / 13,30
       --nova-ok           7,15 / 8,06     --nova-rec        2,65 / 2,98
     --nova-rec e' l'unica sotto soglia, ed e' un RIEMPIMENTO, non un testo: e'
     il disco del comando mentre registra, e il significato non ce l'ha la tinta
     ma il quadrato di stop sopra (bianco sul rosso: 5,09:1) piu' la parola
     REGISTRA scritta sotto. E' il rosso del mockup, e batte comunque --err, che
     su questo fondo fa 2,00.
     Identiche nei due temi, come le tre sopra e per lo stesso motivo: il
     pannello di Nova e' scuro anche nel tema chiaro. Non toccano la scala oro
     e non entrano da nessun'altra parte del prodotto. */
  --nova-ascolto-ink: #FFA591;
  --nova-parla-ink:   #A0F5CD;
  --nova-ok:          #8FBF86;
  --nova-rec:         #C32A2A;

  /* Nel tema scuro le "superfici scure" sono di poco piu' chiare del
     fondo: restano distinte per elevazione, non per contrasto. */
  --shell:           #1B1712;
  --shell-2:         #141109;
  --shell-alto:      #26211A;
  --shell-line:      rgba(245,241,232,.10);
  --on-dark-ink:     #F5F1E8;  /* 14,17 sul guscio */
  --on-dark-muted:   rgba(245,241,232,.62);  /* 6,28 sul guscio, alfa compositata */
  --on-dark-accent:  #F5F1E8;
  --on-dark-line:    rgba(245,241,232,.10);
  --on-dark-soft:    rgba(245,241,232,.08);

  --ombra:         rgba(0,0,0,.45);
  --ombra-forte:   rgba(0,0,0,.68);
  --velo:          rgba(0,0,0,.62);
  --alone:         var(--action-soft);

  --ok:            #7FBF8E;  --ok-on:   #0F1F13;  /* 7,95 */
  --ok-text:         #7FBF8E;  /* 8,61 / 8,04 / 8,81 */
  --ok-soft:         rgba(127,191,142,.16);
  --warn:          #DFB55F;  --warn-on: #241B06;  /* 8,84 */
  --warn-text:       #DFB55F;  /* 9,64 / 9,01 / 9,87 */
  --warn-soft:       rgba(223,181,95,.16);
  --err:           #E88A72;  --err-on:  #2B0E08;  /* il toro schiarito, 7,11 */
  --err-text:        #E88A72;  /* 7,34 / 6,86 / 7,52 */
  /* .12 e non .16: il velo dell'errore ha la STESSA tinta del suo testo, e a
     .16 comprimeva il contrasto del badge "Rifiutato" a 4,47 — appena sotto la
     soglia. Verde e ambra passano perche' il loro testo e' piu' chiaro. */
  --err-soft:        rgba(232,138,114,.12);

  /* Su fondo scuro un'ombra nera non si vede: si alza il nero e si
     stringe il raggio, altrimenti le schede galleggiano nel nulla. */
  --shadow-1:  0 1px 2px rgba(0,0,0,.30), 0 1px 3px rgba(0,0,0,.36);
  --shadow-2:  0 12px 28px -14px rgba(0,0,0,.62);

  color-scheme: dark;
}

/* ============ Valori indipendenti dal tema ============ */
:root {

  /* ---- Tipografia: Fraunces (display) + Instrument Sans (tutto il resto) ----
     DUE famiglie con due mestieri distinti, non due gusti:
       display -> h1, h2 e il logotipo. Serif variabile con asse ottico.
       ui      -> tutto il resto: interfaccia, dati, codici, targhette.
     I fallback non sono decorativi: se il woff2 non e' ancora sceso, il
     browser dipinge con il primo che trova. Georgia per il display e
     system-ui per l'interfaccia tengono la pagina leggibile invece di
     farla franare su Times.
     ERANO TRE. Archivo e IBM Plex Mono sono uscite con Alabastro, che una
     terza famiglia non la prevede. La trappola dei pesi resta scritta
     perche' e' scattata una volta: IBM Plex Mono self-hostato aveva solo
     400/500/600 STATICI, e chiedere il 700 faceva ripiegare il browser sul
     600 senza dirlo. Instrument Sans e' variabile 400-700, quindi i pesi
     intermedi di Alabastro (560, 620, 650, 680) sono veri — ma il controllo
     va rifatto ogni volta che entra una famiglia nuova, perche' quando
     fallisce non lo annuncia nessuno. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-ui:      "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Alabastro non prevede un monospazio: --font-mono e' un ALIAS di --font-ui.
     I circa trenta punti che lo chiedono (glass.css, nova.js, landing.html)
     continuano a funzionare senza essere toccati uno per uno, e il giorno che
     i codici in colonna dessero fastidio basta ridare un valore proprio a
     questa riga sola. */
  --font-mono:    var(--font-ui);

  --fs-300: 0.8125rem;  /* etichette        */
  --fs-400: 0.9375rem;  /* corpo            */
  --fs-500: 1.0625rem;
  --fs-600: 1.375rem;   /* titoli sezione   */
  --fs-700: 2rem;       /* titoli           */
  --fs-900: 3rem;       /* display          */

  --tracking-wide: 0.02em;   /* display */
  --tracking-ui:   0.01em;
  --tracking-mono: 0.12em;   /* etichette mono UPPERCASE */

  /* ---- Motion (sobria) ---- */
  --dur-1: .14s; --dur-2: .24s; --dur-3: .5s;
  --ease-out:    cubic-bezier(.22,.61,.36,1);
  --ease-spring: cubic-bezier(.22,.61,.36,1);
  --ease-tema:   cubic-bezier(.32,.72,0,1);

  /* ---- Forme ---- */
  /* La scala delle forme di Alabastro. Prima erano quattordici valori
     diversi (2,3,4,5,6,7,8,9,10,11,12,14,16,20px) messi a occhio file per
     file: i token c'erano ma non li usava nessuno — --radius aveva DUE usi
     in tutto il progetto, e le --fs-* zero. Adesso le forme passano di qui,
     e un ritocco e' una riga sola invece di settanta. */
  --radius-xs: 6px;   /* targhette, pastiglie minute */
  --radius-sm: 10px;  /* pulsantini, chip */
  --radius:    12px;  /* pulsanti, campi */
  --radius-lg: 18px;  /* schede, pannelli, modali */

  /* ---- Spaziature (griglia 8px) ---- */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px;

  /* ---- IL MARCHIO, nelle sue tre riduzioni ----
     Il toro di InsTaurus come maschera CSS. Il colore NON sta qui: lo
     mette chi usa il segno, con background-color: currentColor. Vedi
     .instaurus-mark in instaurus-app.css.
     Il #000 dentro le data-URI non e' vernice: una maschera usa il
     canale ALFA, quindi conta dove c'e' disegno, non di che colore.
     Tre disegni e non uno rimpicciolito, perche' sotto una certa
     dimensione un tratto sottile si chiude e resta una macchia.
     La regola: OGNI RIDUZIONE PERDE IL DETTAGLIO CHE HA SMESSO DI PAGARE.
       grande  44px  tratto 24  profilo + occhi + CORNA
       medio   20px  tratto 28  profilo + CORNA        (gli occhi a questa
                                 misura diventano una sbavatura dentro la V)
       piccolo 16px  tratto 32  solo profilo           (con le corna il
                                 disegno e largo 225 unita su 240 invece di
                                 185: a 16px rimpicciolirebbero la V del 18%
                                 per due pixel che sembrano fianchi piu alti)
     LE CORNA sono la geometria che il prodotto gia spedisce OVUNQUE:
     icons/favicon.svg, le sette icone, la cartolina social, nova.js,
     nova-fab.js, la barra della landing e il render 3D della testata,
     che e cotto nei .webp e non si puo rigenerare. Erano questi token
     l unico posto con un altro animale: senza corna e con un MUSO
     rettangolare che non esiste in nessun altro file. Il muso e uscito.
     dimensione un tratto sottile si chiude e resta una macchia. */
  /* Il rosso degli occhi del toro. NON e --err: quello e uno STATO, e in
     notturna diventa rosa (#F08A8A) perche deve leggersi su fondo scuro. Il
     rosso del marchio non cambia col tema, come non cambia la geometria del
     segno: e una costante di marca. Vive fuori dai blocchi dei temi apposta.
     Da 6,87:1 su --bg sabbia e 7,42:1 su --surface: sopra la soglia AA.
     Sul guscio fa 2,17:1 e su --bg notturna 2,46:1, ed e il motivo per cui la
     landing e passata alla carta chiara invece di schiarire il rosso: nel piede
     il logotipo va in monocromia (.piede .logo-t{color:inherit}).
     NON PORTARLO AL ROSSO DI ALABASTRO #B8452F. Gli occhi del render 3D della
     landing sono COTTI nei .webp a #A4201F: contro questo token fanno dE2000
     0,4 (combaciano), contro #B8452F ne fanno 8,8 (due rossi diversi accostati
     nella stessa testata). E il guadagno sarebbe nullo: qui il rosso non tocca
     mai un fondo scuro, perche' il piede si sfila da solo. */
  --marchio-occhio: #A32020;

  /* Lo stesso rosso, per quando il fondo e SCURO. Non e un colore nuovo: e
     "il toro schiarito", lo stesso #E88A72 con cui viene stampata la variante
     scura delle icone (scripts/genera-icone.mjs). Serve perche il rosso di
     marca sul guscio fa 2,17:1 e sparisce, e perche la T del logotipo la
     vogliamo rossa anche nella barra laterale — che e scura ANCHE nel tema
     chiaro, quindi un valore per-tema non basterebbe: come --marchio-occhio,
     questo vive fuori dai blocchi dei temi.
     Misurato sui tre fondi scuri del progetto:
       5,77 su --shell-alto (il punto piu chiaro del gradiente della barra,
            cioe il caso peggiore)   6,47 su --shell   7,34 su --bg notturna.
     Sopra la soglia AA su tutti e tre. */
  --marchio-occhio-chiaro: #E88A72;

  --marchio-grande: url("data:image/svg+xml,%3Csvg viewBox='0 0 240 240' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M40 56 V96 L120 176 L200 96 V56' fill='none' stroke='%23000' stroke-width='24' stroke-linecap='square' stroke-linejoin='miter'/%3E%3Cpath d='M78 88 L112 116 L78 104 Z' fill='%23000'/%3E%3Cpath d='M162 88 L128 116 L162 104 Z' fill='%23000'/%3E%3Cpath d='M26 54 L8 14 L52 32 L52 50 Z' fill='%23000'/%3E%3Cpath d='M214 54 L232 14 L188 32 L188 50 Z' fill='%23000'/%3E%3C/svg%3E");
  --marchio-medio:  url("data:image/svg+xml,%3Csvg viewBox='0 0 240 240' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M40 56 V96 L120 176 L200 96 V56' fill='none' stroke='%23000' stroke-width='28' stroke-linecap='square' stroke-linejoin='miter'/%3E%3Cpath d='M26 54 L8 14 L52 32 L52 50 Z' fill='%23000'/%3E%3Cpath d='M214 54 L232 14 L188 32 L188 50 Z' fill='%23000'/%3E%3C/svg%3E");
  --marchio-piccolo: url("data:image/svg+xml,%3Csvg viewBox='0 0 240 240' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M40 56 V96 L120 176 L200 96 V56' fill='none' stroke='%23000' stroke-width='32' stroke-linecap='square' stroke-linejoin='miter'/%3E%3C/svg%3E");
}

/* ============================================================
   ALIAS STORICI — non usarli nel codice nuovo.
   ------------------------------------------------------------
   Sono i nomi della palette precedente (crema/blu blueprint). Restano
   vivi per una ragione precisa: molti compaiono DENTRO stringhe di CSS
   che il JavaScript inietta a runtime, dove nessun refactor automatico
   li vedrebbe, e toglierli tutti in un colpo lascerebbe l'app a meta'
   guado. Qui puntano ai token nuovi, cosi' esiste UN SOLO posto dove
   cambiare un colore.

   Attenzione al mestiere, non al nome: i token che significavano
   "azione primaria" (--vetro, --oro, --accento, --blueprint) puntano a
   --action, NON a --accent. L'oro adesso e' Nova, e Nova soltanto.
   ============================================================ */
:root,
[data-theme="sabbia"],
[data-theme="notturna"] {
  /* fondi e inchiostro */
  --carta:        var(--bg);
  --grafite:      var(--ink);
  --grafite-2:    var(--line-strong);
  --notte:        var(--shell);
  --carbone:      var(--shell);
  --carbone-2:    var(--shell-alto);
  --border:       var(--line);
  --divider:      var(--line);
  --hairline:     var(--line);
  --hairline-soft: var(--line);
  --text:         var(--ink);
  --text-muted:   var(--ink-muted);
  --muted:        var(--ink-muted);
  --text-on-dark: var(--ink-on-dark);

  /* azione primaria (erano il blu blueprint, prima ancora l'oro) */
  --accento:        var(--action);
  --accento-forte:  var(--action-strong);
  --accento-chiaro: var(--on-dark-accent);  /* era il periwinkle sulle superfici scure */
  --accento-velo:   var(--action-soft);
  --accento-tenue:  var(--action-soft);
  --accento-08:     var(--action-soft);
  --accento-10:     var(--action-soft);
  --accento-16:     var(--action-soft);
  --accento-18:     var(--action-soft);
  --vetro:        var(--action);
  --vetro-12:     var(--action-soft);
  --vetro-20:     var(--action-soft);
  --oro:          var(--action);
  --oro-hi:       var(--action);
  --oro-deep:     var(--action-strong);
  --oro-ink:      var(--action);
  --oro-10:       var(--action-soft);
  --oro-22:       var(--action-soft);
  --grad-oro:     var(--action);   /* non e' un gradiente: tinta piatta */
  --blueprint:        var(--action);
  --blueprint-hover:  var(--action-strong);
  --blueprint-tint:   var(--action-soft);
  --text-link:        var(--action-text);
  --focus-ring:       var(--focus);
  --grafite-08:   var(--action-soft);
  --grafite-14:   var(--action-soft);
  --grafite-60:   var(--ink-muted);
  /* NB: --accent NON compare qui. Nella palette precedente significava
     "azione primaria"; adesso e' l'oro di Nova, definito sopra nei due
     temi. L'unico punto che lo usava con il vecchio significato era
     --grad-green in glass.css, rimappato su --action. */

  /* Nova */
  --ai:           var(--accent);

  /* ---- Ripiegati qui da glass.css (@layer tema) e dal <style> di
     index.html (@layer base). Stavano in due :root che, essendo in layer
     dichiarati DOPO `tokens`, vincevano sui token e tenevano l'app
     inchiodata alla palette vecchia: era il motivo per cui il tema non
     si applicava. Ora esiste un posto solo. ---- */
  --card:        var(--surface);
  --line-soft:   var(--line);
  --ink-soft:    var(--ink);
  --ink-deep:    var(--surface-2);
  --cream:       var(--bg);
  --bg-end:      var(--bg);
  --teal:        var(--action);
  --teal-d:      var(--action-strong);
  --teal-soft:   var(--action-soft);
  --amber:       var(--warn-text);
  --amber-d:     var(--warn-text);
  --amber-light: var(--warn-soft);
  --burnt:       var(--err);
  --burnt-d:     var(--err);
  --green:       var(--action);
  --green-d:     var(--ok-text);   /* prezzi e conferme: semantica verde */
  --green-l:     var(--action-strong);
  --green-soft:  var(--action-soft);
  --grad-green:   var(--action);
  --grad-primary: var(--ink);
  --grad-gold:    var(--action);
  --grad-teal:    var(--action);
  --grad-ink:     var(--ink);
  --grad-card:    var(--surface);
  --grad-bg:      var(--bg);
  --shadow-sm:   var(--shadow-1);
  --shadow:      var(--shadow-1);
  --shadow-lg:   var(--shadow-2);
  --muted-l:     var(--ink-muted);

  /* stati */
  --verde:        var(--ok);
  --rosso:        var(--err);
  --success:      var(--ok);
  --danger:       var(--err);
  --status-attivo:  var(--ok);
  --status-trial:   var(--accent-text);
  --status-sospeso: var(--err);
  --status-cessato: var(--ink-muted);
  --stato-bozza-bg: var(--warn-soft);     --stato-bozza-tx: var(--warn-text);
  --stato-inviato-bg: var(--action-soft); --stato-inviato-tx: var(--action-text);
  --stato-accettato-bg: var(--ok-soft);   --stato-accettato-tx: var(--ok-text);
}

/* ============================================================
   TELEFONO — la palette di evilinstaurus sotto i 760px (blocco 1, 07/09/2026)
   ------------------------------------------------------------
   Sul telefono l'app adotta il linguaggio visivo di evilinstaurus
   (evilinstaurus.netlify.app). Il suo repository GitHub e' vuoto: i valori
   qui sotto sono LETTI da src/mist.css del deploy, non dedotti da uno
   screenshot. Si dichiarano una volta come --mist-*, e i token di RUOLO
   vengono ri-mappati sopra: cosi' ogni componente segue la palette nuova
   senza sapere che esiste, e il rollback e' questo blocco e basta.

   TRE CONFINI, tutti voluti:
   - `max-width: 760px`, il confine telefono di tutto il progetto (il brief
     diceva 768: fra 761 e 767 non esiste nessun dispositivo, e a 768 —
     iPad verticale — resta il cassetto tablet con tutt'e due le soglie);
   - `data-pagina="app"`, che porta solo index.html: la landing (pinnata a
     Sabbia) e scheda.html non cambiano di un pixel;
   - `data-theme="sabbia"`: evilinstaurus e' `color-scheme: light`, non ha
     un tema scuro. Notturna resta com'e', e l'indicatore attivo navy
     diventa carta come fa --action.

   DUE VALORI NON SONO QUELLI DI EVIL, e sono misurati (scripts/contrasti.js
   li prova nel terzo esame): il muted #5c707e fa 4,37 su #e8edf1, sotto la
   soglia AA, quindi --ink-muted scende a #526676 (5,06 / 5,75 / 5,29); il
   bordo dei campi (--line-strong, 1.4.11, 3:1) non puo' essere la --line di
   evil (1,25) e prende il suo muted (4,37 / 4,97 / 4,57).
   Gli stati --ok/--warn/--err restano quelli di InsTaurus: passano sui
   fondi nuovi (6,13 / 5,26 / 5,77). L'oro resta Nova: --accent-text fa
   5,23 su #e8edf1.

   La POSIZIONE conta: questo blocco deve stare DOPO i due temi. Sia
   scripts/css-parsabile.js (check 4a) sia scripts/contrasti.js leggono il
   PRIMO selettore di tema che incontrano; il selettore qui sotto mette
   data-theme per primo apposta, cosi' non contiene mai la sequenza
   «attributo del tema, spazio, graffa» che contrasti.js cerca come
   apertura di Sabbia. Il commento «fine mist» in fondo al blocco chiude la
   lettura del terzo esame di contrasti.js: non spostarlo e non citarlo
   dentro un altro commento (un commento dentro un commento si chiude in
   anticipo: e' la trappola per cui esiste css-parsabile.js).
   ============================================================ */
@media (max-width: 760px) {
  html[data-theme="sabbia"][data-pagina="app"] {
    /* ---- sorgente: evilinstaurus.netlify.app/src/mist.css ----
       NB: in questi commenti non si scrive mai «due trattini, nome, due
       punti»: contrasti.js legge il blocco SENZA togliere i commenti, e
       una sequenza cosi' dentro un commento viene presa per una
       dichiarazione e si mangia quella vera sulla riga dopo. */
    --mist-bg:           #e8edf1;     /* il fondo di pagina di evil */
    --mist-paper:        #f9fbfc;     /* la «paper» di evil: contenitori, spesso con alfa 65..bd */
    --mist-surface-2:    #edf2f6;     /* .secondary */
    --mist-ink:          #263643;     /* l'inchiostro: 10,53 / 11,96 / 11,02 */
    --mist-muted:        #526676;     /* evil #5c707e scurito, vedi sopra */
    --mist-line:         #cbd6dd;     /* i divisori di evil, 1,25: mai un bordo di campo */
    --mist-line-strong:  #5c707e;     /* il muted di evil, come bordo dei campi */
    --mist-navy:         #324a61;     /* l'azione di evil (.primary, .send, .avatar): bianco sopra 9,18 */
    --mist-navy-forte:   #243b50;     /* hover di .primary e .send: bianco sopra 11,56 */
    --mist-navy-rgb:     50 74 97;    /* per i veli navy con alfa */
    --mist-ombra-rgb:    84 107 124;  /* #546b7c: l'ombra del .panel (alfa .03) */
    --mist-velo-rgb:     35 55 70;    /* #233746: il backdrop del dialog (alfa .33) */
    --mist-nebbia-1:     #d7e9f1;     /* radial-gradient(ellipse at 17% 60%) */
    --mist-nebbia-2:     #dfddec;     /* radial-gradient(ellipse at 80% 20%) */
    /* ---- la ri-mappa dei ruoli ---- */
    --bg:              var(--mist-bg);
    --surface:         var(--mist-paper);
    --surface-2:       var(--mist-surface-2);
    --ink:             var(--mist-ink);
    --ink-muted:       var(--mist-muted);
    --line:            var(--mist-line);
    --line-strong:     var(--mist-line-strong);
    --action:          var(--mist-navy);
    --action-strong:   var(--mist-navy-forte);
    --action-text:     var(--mist-navy);
    --action-soft:     rgb(var(--mist-navy-rgb) / .10);
    --focus:           var(--mist-navy);
    --velo:            rgb(var(--mist-velo-rgb) / .33);
    --ombra:           rgb(var(--mist-ombra-rgb) / .14);
    --ombra-forte:     rgb(var(--mist-ombra-rgb) / .30);
    --shadow-1:        0 12px 32px rgb(var(--mist-ombra-rgb) / .03);   /* il .panel di evil */
    --shadow-2:        0 30px 100px rgb(var(--mist-velo-rgb) / .27);   /* il dialog di evil */
    /* fine mist */
  }
  /* Tipografia e forme non sono palette: valgono in TUTT'E DUE i temi.
     evilinstaurus ha un solo sans (DM Sans, che qui non entra: font-src
     'self' e service worker); sul telefono anche i titoli passano a
     Instrument Sans, con scala e pesi di evil. Il raggio grande diventa
     quello del suo .panel (20px). */
  html[data-pagina="app"] {
    --font-display: var(--font-ui);
    --radius-lg:    20px;
  }
}

} /* fine @layer tokens */

/* ============================================================
   LA TRANSIZIONE FRA I DUE TEMI
   ------------------------------------------------------------
   Sta in @layer guardie perche' deve raggiungere anche il CSS che
   nova.js, preventivo2.js e prev2-import-catalogo.js iniettano a
   runtime: quel CSS non sa niente dei temi, e senza questa regola i
   suoi pannelli scatterebbero da un tema all'altro mentre il resto
   della pagina sfuma.

   PERCHE' UNA CLASSE E NON UNA REGOLA PERMANENTE. Una transizione su
   `*` sempre attiva rallenterebbe ogni hover, ogni apertura di modale e
   ogni ridisegno di tabella, per un beneficio che dura 250ms una volta
   ogni tanto. Il bootstrap del tema aggiunge .tema-in-transito
   sull'<html> subito prima di cambiare attributo e la toglie a
   transizione finita: il costo si paga solo quando serve davvero.

   `prefers-reduced-motion` e' gia' coperto in testa a questo file da
   una regola che azzera OGNI durata: chi ha chiesto meno movimento
   vede il cambio di tema istantaneo, senza che serva ripeterlo qui.
   ============================================================ */
@layer guardie {
  html.tema-in-transito,
  html.tema-in-transito *,
  html.tema-in-transito *::before,
  html.tema-in-transito *::after {
    transition: background-color .25s var(--ease-tema),
                color            .25s var(--ease-tema),
                border-color     .25s var(--ease-tema),
                fill             .25s var(--ease-tema),
                stroke           .25s var(--ease-tema) !important;
  }
}

/* L'anti auto-zoom iOS e la regola su prefers-reduced-motion stanno in
   @layer guardie, in testa a questo file: devono battere anche il CSS
   iniettato a runtime. */
