/* Gestionale — foglio di stile unico
 *
 * Impianto: iOS. Superfici morbide su fondo grigio, angoli tondi, ombre basse,
 * barre traslucide, filetti sottilissimi al posto delle cornici. Le densità da
 * gestionale restano — righe compatte, tabelle fitte, tutto in vista — perché
 * qui si lavora su ottocento articoli, non si sfoglia un feed.
 *
 * Colori: palette di sistema Apple, scurita dove sopra ci va del testo. Il blu
 * di iOS (#007AFF) contro il bianco fa 4.02:1 e non basta per il testo: resta
 * per i pieni senza scritte (interruttori, indicatori), mentre i bottoni e i
 * collegamenti usano --primario, più profondo di un soffio e leggibile.
 *
 * Contrasti verificati (WCAG AA vuole 4.5:1 per il testo, 3:1 per i comandi):
 *   --primario     #0062cc  testo bianco sopra ......... 5.8:1
 *   --primario     #0062cc  su bianco (collegamenti) ... 5.8:1  su #f2f2f7  5.2:1
 *   --verde        #1e7a34  testo bianco sopra ......... 5.4:1
 *   --rosso        #d70015  testo bianco sopra ......... 5.4:1
 *   --ambra        #a05a00  su bianco .................. 5.3:1
 *   --viola        #7d3aaf  su bianco .................. 6.8:1
 *   --testo-tenue  #6c6c70  su bianco 5.2:1   su #f2f2f7  4.7:1
 *   tinte tenui con il proprio colore sopra ......... da 4.6:1 a 5.7:1
 */

:root {
  /* superfici */
  --sfondo: #f2f2f7;
  --superficie: #ffffff;
  --superficie-2: #f7f7fa;
  --riempimento: #eff0f4;
  --chrome: rgba(248, 248, 250, .82);
  --bordo: #e5e5ea;
  --bordo-forte: #d1d1d6;

  /* testo */
  --testo: #1c1c1e;
  --testo-tenue: #6c6c70;

  /* identità: blu vivo per i pieni muti, blu profondo dove c'è del testo */
  --blu-vivo: #007aff;
  --primario: #0062cc;
  --primario-forte: #00519f;
  --su-primario: #ffffff;
  --primario-tenue: #e6f0ff;

  /* selezione nella griglia */
  --selezione: #e6f0ff;
  --su-selezione: #00519f;
  --selezione-tenue: #f0f5ff;

  --accento: #1e7a34;
  --accento-vivo: #34c759;
  --su-accento: #ffffff;
  --accento-testo: #1e7a34;
  --accento-tenue: #e3f7e8;

  /* stati semaforo */
  --verde: #1e7a34;
  --verde-vivo: #34c759;
  --verde-tenue: #e3f7e8;
  --ambra: #a05a00;
  --ambra-vivo: #ff9500;
  --ambra-tenue: #fff2dd;
  --rosso: #d70015;
  --rosso-vivo: #ff3b30;
  --rosso-testo: #d70015;
  --rosso-tenue: #ffe9e7;
  --viola: #7d3aaf;
  --viola-vivo: #af52de;
  --viola-tenue: #f3e8fd;

  --anello: #007aff;

  /* densità */
  --altezza-riga: 26px;
  --altezza-strumenti: 56px;
  --altezza-sezione: 46px;
  --altezza-azioni: 42px;
  --larghezza-dettaglio: 300px;

  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;

  /* angoli: iOS ne usa pochi valori, ripetuti ovunque */
  --raggio-1: 7px;
  --raggio: 10px;
  --raggio-2: 12px;
  --raggio-3: 16px;
  --pillola: 980px;

  /* ombre basse e larghe: la superficie si stacca, non salta in aria */
  --ombra-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 1px rgba(0, 0, 0, .03);
  --ombra-2: 0 2px 10px rgba(0, 0, 0, .07), 0 1px 2px rgba(0, 0, 0, .04);
  --ombra-alta: 0 24px 60px rgba(0, 0, 0, .22), 0 4px 12px rgba(0, 0, 0, .1);

  --vetro: saturate(180%) blur(20px);
  --molla: cubic-bezier(.32, .72, 0, 1);

  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Segoe UI Variable Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono", Consolas, Menlo, monospace;
}

[data-tema="scuro"] {
  --sfondo: #000000;
  --superficie: #1c1c1e;
  --superficie-2: #2c2c2e;
  --riempimento: #2c2c2e;
  --chrome: rgba(28, 28, 30, .78);
  --bordo: #38383a;
  --bordo-forte: #48484a;

  --testo: #ffffff;
  --testo-tenue: #98989f;

  --blu-vivo: #0a84ff;
  --primario: #0a84ff;
  --primario-forte: #0a6fd8;
  --su-primario: #ffffff;
  --primario-tenue: #10233a;

  --selezione: #10233a;
  --su-selezione: #6cb6ff;
  --selezione-tenue: #14283f;

  --accento: #30d158;
  --accento-vivo: #30d158;
  --su-accento: #04150e;
  --accento-testo: #30d158;
  --accento-tenue: #0d2a16;

  --verde: #30d158;
  --verde-vivo: #30d158;
  --verde-tenue: #0d2a16;
  --ambra: #ff9f0a;
  --ambra-vivo: #ff9f0a;
  --ambra-tenue: #35240a;
  --rosso: #ff453a;
  --rosso-vivo: #ff453a;
  --rosso-testo: #ff453a;
  --rosso-tenue: #3a1512;
  --viola: #bf5af2;
  --viola-vivo: #bf5af2;
  --viola-tenue: #2a1440;

  --anello: #0a84ff;

  --ombra-1: 0 1px 2px rgba(0, 0, 0, .5);
  --ombra-2: 0 2px 10px rgba(0, 0, 0, .55);
  --ombra-alta: 0 24px 60px rgba(0, 0, 0, .75), 0 4px 12px rgba(0, 0, 0, .5);
}

/* I pieni con testo bianco vanno scuriti anche di notte: #0a84ff con sopra il
   bianco è 3.6:1, sotto la soglia. */
[data-tema="scuro"] .btn-primario,
[data-tema="scuro"] .btn-primario:hover { background: #0a6fd8; border-color: #0a6fd8; }
/* Il pieno passa da `--pieno-btn` e non dallo sfondo diretto: così anche la
   regola `:hover` più in basso pesca il colore giusto senza dover ripetere il
   tema, e senza dipendere da chi delle due è scritta per ultima. */
[data-tema="scuro"] .btn-pericolo { --pieno-btn: #e0243a; color: #fff; }
[data-tema="scuro"] .btn-successo { --pieno-btn: #248a3d; color: #fff; }

* { box-sizing: border-box; }

html { scroll-padding-top: calc(var(--altezza-sezione) + var(--altezza-azioni)); }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.45;
  letter-spacing: -.01em;
  color: var(--testo);
  background: var(--sfondo);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.nascosto { display: none !important; }
[hidden] { display: none !important; }

.solo-lettori {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

:focus-visible { outline: 2px solid var(--anello); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }

.salta-al-contenuto {
  position: absolute; left: var(--s2); top: -60px; z-index: 300;
  background: var(--primario); color: var(--su-primario);
  padding: var(--s2) var(--s4); font-weight: 600; text-decoration: none;
  border-radius: var(--raggio);
}
.salta-al-contenuto:focus { top: var(--s2); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

.contenuto a:not(.btn):not(.btn-icona):not(.badge):not(.titolo-riga),
.pannello-corpo a:not(.btn):not(.titolo-riga) { color: var(--primario); text-underline-offset: 2px; }
.contenuto a:not(.btn):not(.btn-icona):not(.badge):not(.titolo-riga):hover,
.pannello-corpo a:not(.btn):not(.titolo-riga):hover { text-decoration: underline; }

/* Nome dell'articolo dentro una griglia: si comporta da collegamento — cursore
   a mano, apre la scheda — senza vestirsi da collegamento, che in una tabella
   fitta di nomi diventerebbe un muro di blu sottolineato. */
a.titolo-riga {
  color: inherit; text-decoration: none; cursor: pointer;
  text-underline-offset: 2px;
}
a.titolo-riga:hover { text-decoration: underline; }

.icona { flex: none; display: block; }

.num, .valore, .kpi .valore, table.tabella .num, .riquadro-totali {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------- avvio e login */

/* La schermata che copre l'attesa iniziale.
 *
 * Serve perché la pagina è una sola e le tre schermate stanno tutte nel
 * documento: quella che parte visibile si disegna subito, mentre sapere se si
 * è già entrati richiede una risposta dal server. Prima partiva visibile
 * l'accesso, e chi aveva la sessione aperta lo vedeva lampeggiare per un
 * istante prima di ritrovarsi dentro — con l'aria di essere stato buttato
 * fuori. Adesso parte questa, e a risposta arrivata si scopre l'accesso o
 * l'applicazione.
 *
 * Il cerchio si fa aspettare un terzo di secondo: in rete locale la risposta
 * arriva in poche decine di millisecondi, e una rotella che compare e sparisce
 * si nota più dell'attesa che dovrebbe coprire. Chi apre il gestionale vede il
 * fondo della finestra e poi la sua schermata; la rotella la vede solo chi sta
 * aspettando davvero. */
.schermata-avvio {
  min-height: 100vh; min-height: 100dvh; display: grid; place-items: center;
  background: var(--sfondo);
}
[data-tema="scuro"] .schermata-avvio { background: #000; }
.schermata-avvio .cerchio {
  margin: 0; opacity: 0;
  animation: gira .7s linear infinite, comparire .25s ease-out .35s forwards;
}
@keyframes comparire { to { opacity: 1; } }

.schermata-login {
  min-height: 100vh; min-height: 100dvh; display: grid; place-items: center;
  padding: var(--s5); background: var(--sfondo);
}
[data-tema="scuro"] .schermata-login { background: #000; }
.carta-login {
  width: 100%; max-width: 340px; background: var(--superficie);
  border: none; border-radius: var(--raggio-3); padding: var(--s5);
  box-shadow: var(--ombra-2);
  display: flex; flex-direction: column; gap: var(--s3);
}
.carta-login h1 { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -.4px; }
.carta-login p { margin: 0; color: var(--testo-tenue); font-size: 13px; }
/* L'unico campo della schermata non segue la densità del gestionale: sotto i
   16px il telefono ingrandisce la pagina appena lo si tocca, e la schermata
   resta ingrandita e spostata di lato anche dopo essere entrati. Qui di campi
   ce n'è uno solo: dei 13px non se ne guadagna niente. */
.carta-login .campo input { font-size: 16px; }
.marchio { display: flex; align-items: center; gap: var(--s2); }
/* L'icona quadra con l'angolo tondo è la firma di iOS: qui vale da logo. */
.logo-quadro {
  width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  background: linear-gradient(180deg, #2a90ff, var(--primario));
  color: #fff; font-weight: 700; font-size: 17px;
  border-radius: 9px; box-shadow: var(--ombra-1);
}
[data-tema="scuro"] .logo-quadro { background: linear-gradient(180deg, #3a9cff, #0a6fd8); }

/* --------------------------------------------------- struttura a finestra */

.applicazione {
  display: flex; flex-direction: column;
  height: 100vh; height: 100dvh; overflow: hidden;
}

/* barra strumenti: icona sopra, etichetta sotto, su vetro smerigliato */
.barra-strumenti {
  display: flex; align-items: stretch; gap: var(--s2);
  height: var(--altezza-strumenti); flex: none;
  background: var(--chrome);
  -webkit-backdrop-filter: var(--vetro); backdrop-filter: var(--vetro);
  border-bottom: 1px solid var(--bordo);
  padding: 0 var(--s3); position: relative; z-index: 30;
}

.identita {
  display: flex; align-items: center; gap: var(--s2);
  padding-right: var(--s3); border-right: 1px solid var(--bordo);
  flex: none; max-width: 200px;
}
.identita strong {
  font-size: 13px; font-weight: 600; line-height: 1.2; letter-spacing: -.2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

#navigazione {
  display: flex; align-items: center; gap: 1px;
  flex: 1; min-width: 0; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; padding: 0 var(--s1);
}
#navigazione::-webkit-scrollbar { display: none; }
/* Le voci non si stringono mai sotto i 56px: più strette diventano illeggibili.
   Quando non ci stanno — a 1440px con tutte le aree assegnate ne avanza già
   qualcuna fuori — la barra scorre di lato, senza scrollbar in vista. */
#navigazione a {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 5px 6px; min-width: 56px; flex: none;
  color: var(--testo-tenue); text-decoration: none; font-size: 11px; white-space: nowrap;
  border: none; border-radius: var(--raggio);
  transition: background-color .18s var(--molla), color .18s var(--molla);
}
#navigazione a .icona { opacity: .9; }
#navigazione a:hover { background: rgba(120, 120, 128, .12); color: var(--testo); }
#navigazione a[aria-current="page"] {
  background: var(--primario-tenue); color: var(--primario); font-weight: 600;
}
#navigazione a[aria-current="page"] .icona { opacity: 1; }
[data-tema="scuro"] #navigazione a[aria-current="page"] { color: #6cb6ff; }
.separatore-nav { width: 1px; background: var(--bordo); flex: none; margin: var(--s3) var(--s1); }

.strumenti-destra {
  display: flex; align-items: center; gap: var(--s1);
  padding-left: var(--s3); border-left: 1px solid var(--bordo); flex: none;
}
/* È un bottone (apre il cambio password) ma deve leggersi come l'etichetta
   che era prima: niente cornice, solo il cursore e il colore a dire che si clicca. */
.utente-attivo {
  font-size: 12px; color: var(--testo-tenue); max-width: 120px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: none; border: 0; padding: 0; font-family: inherit;
  cursor: pointer; text-align: left;
}
.utente-attivo:hover { color: var(--testo); }

/* Campo di ricerca alla iOS: pieno grigio, angoli tondi, lente dentro. */
.ricerca-globale { position: relative; width: 220px; }
.ricerca-globale .involucro-campo { position: relative; display: flex; align-items: center; }
.ricerca-globale .involucro-campo .icona {
  position: absolute; left: 9px; color: var(--testo-tenue); pointer-events: none;
}
.ricerca-globale input {
  width: 100%; padding: 6px var(--s3) 6px 30px; border: 1px solid transparent;
  border-radius: var(--raggio); background: var(--riempimento); color: var(--testo);
  font: inherit; font-size: 13px; min-height: 32px;
  transition: background-color .18s, border-color .18s;
}
.ricerca-globale input:focus { background: var(--superficie); border-color: var(--bordo-forte); }
/* Il pannello è più largo del campo che lo apre, e il campo sta all'estremità
   destra della barra: si aggancia quindi a destra e cresce verso sinistra —
   ancorandolo a sinistra, su un telefono finirebbe metà fuori dallo schermo.
   `max-width` col margine della finestra è la rete: non sborda comunque. */
.risultati-ricerca {
  position: absolute; top: calc(100% + 6px); right: 0; left: auto;
  width: max-content; min-width: 100%; max-width: min(360px, calc(100vw - var(--s4)));
  background: var(--superficie); border: 1px solid var(--bordo);
  border-radius: var(--raggio-2); box-shadow: var(--ombra-alta);
  max-height: 60vh; overflow-y: auto; z-index: 40; padding: var(--s1);
}
.risultati-ricerca .titolo-gruppo {
  font-size: 11px; letter-spacing: 0; color: var(--testo-tenue);
  padding: var(--s2) var(--s2) 2px; font-weight: 600; background: none;
}
.risultati-ricerca a {
  display: block; padding: 6px var(--s2); text-decoration: none; color: var(--testo);
  font-size: 13px; border-radius: var(--raggio-1);
}
.risultati-ricerca a:hover, .risultati-ricerca a:focus-visible {
  background: var(--primario-tenue); color: var(--primario);
}
.risultati-ricerca a:hover small, .risultati-ricerca a:focus-visible small { color: var(--primario); }
.risultati-ricerca small { color: var(--testo-tenue); }

.contenuto { flex: 1; min-height: 0; overflow-y: auto; scrollbar-gutter: stable; background: var(--sfondo); }
/* Titolo e comandi sono a tutta larghezza; tutto il resto rientra. */
.contenuto > *:not(.a-tutta-larghezza) { margin-left: var(--s4); margin-right: var(--s4); }
.contenuto > .a-tutta-larghezza + *:not(.a-tutta-larghezza) { margin-top: var(--s3); }
.contenuto > *:last-child:not(.a-tutta-larghezza) { margin-bottom: var(--s4); }

/* Titolo grande su vetro, come la barra di navigazione di iOS: niente fascia
   colorata, il colore lo mettono i contenuti. */
.barra-sezione {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--s3);
  min-height: var(--altezza-sezione); padding: 0 var(--s4);
  background: var(--chrome);
  -webkit-backdrop-filter: var(--vetro); backdrop-filter: var(--vetro);
  border-bottom: 1px solid var(--bordo); color: var(--testo);
}
.barra-sezione h1 { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.5px; }
.barra-sezione .sottotitolo-sezione {
  font-size: 12.5px; color: var(--testo-tenue); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.barra-sezione .azioni { margin-left: auto; display: flex; gap: var(--s1); flex-wrap: wrap; padding: 5px 0; }
.barra-sezione + .barra-azioni-pagina { margin-top: 0; }
.barra-sezione .btn {
  background: rgba(120, 120, 128, .12); border-color: transparent;
  color: var(--primario); min-height: 28px; padding: 3px var(--s3); font-size: 13px;
}
.barra-sezione .btn:hover { background: rgba(120, 120, 128, .2); }
.barra-sezione .btn-primario, .barra-sezione .btn-successo {
  background: var(--primario); border-color: var(--primario); color: #fff; font-weight: 600;
}
[data-tema="scuro"] .barra-sezione .btn-primario,
[data-tema="scuro"] .barra-sezione .btn-successo { color: #fff; }
.barra-sezione .btn-primario:hover, .barra-sezione .btn-successo:hover { background: var(--primario-forte); }

.corpo-pagina { padding: var(--s3); }

/* Riga dei comandi: appesa sotto al titolo, resta in vista mentre si scorre.
   Gli 0,5px di sovrapposizione evitano la riga chiara che il browser lascia
   fra due fasce appiccicate quando la pagina scorre a passi frazionari. */
.barra-azioni-pagina {
  position: sticky; top: calc(var(--altezza-sezione) - 0.5px); z-index: 19;
  display: flex; align-items: center; gap: var(--s2); flex: none;
  min-height: var(--altezza-azioni); padding: var(--s1) var(--s4);
  background: var(--chrome);
  -webkit-backdrop-filter: var(--vetro); backdrop-filter: var(--vetro);
  border-bottom: 1px solid var(--bordo);
}
/* I comandi stanno a sinistra, dove l'occhio arriva per primo; il conteggio
   viene spinto all'estremo opposto. L'ordine nel DOM è già questo, così la
   sequenza di tabulazione segue quella visiva. */
.barra-azioni-pagina .comandi { display: flex; gap: var(--s1); flex-wrap: wrap; }
.barra-azioni-pagina .conteggio {
  margin-left: auto; padding-left: var(--s3); white-space: nowrap;
  font-size: 12.5px; color: var(--testo-tenue); font-variant-numeric: tabular-nums;
}

/* Comandi raccolti dietro a un tasto «Azioni».
   Da computer e da tablet il tasto non esiste e i comandi stanno tutti in
   riga, che è il modo più veloce di usarli: si vedono e si premono. È sotto i
   760px — telefoni, non tablet in verticale — che la scheda di un documento
   arriva a quattordici bottoni e ne mangia tre righe, coprendo il totale e le
   righe della merce prima ancora di scorrere. */
.azioni-raggruppate .apri-azioni { display: none; }
/* I comandi fissi stanno in riga con gli altri e non dentro al pannello. Il
   passo della barra scende a quello dei comandi, così da computer la riga resta
   spaziata com'era prima che questi due gruppi diventassero separati. */
.azioni-raggruppate { gap: var(--s1); }
.comandi-fissi { display: flex; gap: var(--s1); flex: none; }

@media (max-width: 760px) {
  .azioni-raggruppate .apri-azioni { display: inline-flex; align-items: center; gap: 6px; }
  /* Il pannello scende dalla barra, che è `sticky` e quindi gli fa già da
     riferimento. Sopra a tutto il resto, perché sotto ci sono altre fasce
     appiccicate che se lo mangerebbero. */
  .azioni-raggruppate .comandi {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0; z-index: 30;
    flex-direction: column; align-items: stretch; flex-wrap: nowrap;
    padding: var(--s2); gap: var(--s1);
    background: var(--superficie); border: 1px solid var(--bordo);
    border-top: none; border-radius: 0 0 var(--raggio-2) var(--raggio-2);
    box-shadow: var(--ombra-2);
    /* Più alto dello schermo scorre dentro di sé invece di uscire di sotto. */
    max-height: 70vh; overflow-y: auto; overscroll-behavior: contain;
  }
  .azioni-raggruppate.aperta .comandi { display: flex; }
  /* Righe da toccare col pollice, allineate a sinistra come una lista: qui
     sono voci di menu, non bottoni stretti in una barra. */
  .azioni-raggruppate .comandi .btn {
    justify-content: flex-start; min-height: 42px; font-size: 15px;
    padding: var(--s2) var(--s3);
  }
}

/* ------------------------------------------------------------ bottoni */

.btn {
  font: inherit; font-size: 13px; font-weight: 500; padding: 4px var(--s3);
  border: 1px solid var(--bordo-forte); border-radius: var(--raggio);
  background: var(--superficie); color: var(--testo);
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap; min-height: 30px; text-decoration: none;
  transition: background-color .16s var(--molla), transform .1s var(--molla), filter .16s;
}
.btn:hover { background: var(--riempimento); border-color: var(--bordo-forte); }
/* La pressione che affonda: è il gesto che rende "vivo" un comando su iOS. */
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.btn-primario {
  background: var(--primario); border-color: var(--primario); color: var(--su-primario);
  font-weight: 600; box-shadow: var(--ombra-1);
}
.btn-primario:hover { background: var(--primario-forte); border-color: var(--primario-forte); }
/* Il secondario di iOS non è un bordo: è un pieno tenue senza cornice. */
.btn-secondario {
  background: rgba(120, 120, 128, .12); border-color: transparent; color: var(--primario);
}
.btn-secondario:hover { background: rgba(120, 120, 128, .2); }
.btn-pericolo {
  --pieno-btn: var(--rosso);
  background: var(--pieno-btn); border-color: var(--pieno-btn); color: #fff; font-weight: 600;
}
.btn-successo {
  --pieno-btn: var(--verde);
  background: var(--pieno-btn); border-color: var(--pieno-btn); color: #fff; font-weight: 600;
  box-shadow: var(--ombra-1);
}
/* Il pieno colorato se lo tengono anche sotto al puntatore. `.btn:hover` qui
   sopra riscrive lo sfondo di *ogni* bottone, e a parità di peso vince perché
   viene dopo: senza queste due righe il rosso e il verde diventavano grigio
   chiaro appena ci si passava sopra, col testo bianco dentro. */
.btn-pericolo:hover, .btn-successo:hover {
  background: var(--pieno-btn); border-color: var(--pieno-btn); filter: brightness(1.08);
}
/* 24px è il bersaglio minimo WCAG 2.2: sotto non si scende. */
.btn-piccolo { padding: 2px var(--s2); font-size: 12.5px; min-height: 26px; border-radius: var(--raggio-1); }
.btn-blocco { width: 100%; justify-content: center; min-height: 38px; border-radius: var(--raggio); }

.btn-icona {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; min-height: 28px; padding: 4px; border-radius: 50%;
  background: none; border: 1px solid transparent; cursor: pointer;
  color: var(--testo-tenue); text-decoration: none;
  transition: background-color .16s, color .16s, transform .1s var(--molla);
}
.btn-icona:hover { background: rgba(120, 120, 128, .14); border-color: transparent; color: var(--testo); }
.btn-icona:active { transform: scale(.92); }
.btn-icona.pericolo:hover { color: var(--rosso); background: var(--rosso-tenue); }
tr[aria-selected="true"] .btn-icona { color: var(--primario); }
tr[aria-selected="true"] .btn-icona:hover { background: rgba(0, 122, 255, .16); border-color: transparent; color: var(--primario-forte); }

/* -------------------------------------------------------------- pannelli */

.carta {
  background: var(--superficie); border: 1px solid var(--bordo);
  /* `clip` e non `hidden`: taglia gli angoli allo stesso modo ma non diventa
     un contenitore di scorrimento, e la testata dei filtri può restare
     appiccicata alla finestra invece che alla carta. */
  border-radius: var(--raggio-3); overflow: clip; box-shadow: var(--ombra-1);
}
.carta + .carta { margin-top: var(--s3); }
.carta-testata {
  padding: var(--s2) var(--s3); border-bottom: 1px solid var(--bordo);
  background: var(--superficie);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); flex-wrap: wrap; min-height: 38px;
}
.carta-testata h2 {
  margin: 0; font-size: 13.5px; font-weight: 600; text-transform: none;
  letter-spacing: -.2px; color: var(--testo);
}
.comandi-carta { display: flex; align-items: center; gap: var(--s1); flex-wrap: wrap; }
/* Filtri sempre a portata: scorrendo mille righe restano sotto alle due fasce
   in cima, invece di sparire dopo la prima schermata. */
.carta-testata.appiccicata {
  position: sticky; top: calc(var(--altezza-sezione) + var(--altezza-azioni) - 1px);
  z-index: 18; background: var(--superficie);
}
.carta-corpo { padding: var(--s3); }

/* Fascia della selezione multipla: ultima riga della testata della carta, e
   c'è solo mentre la selezione è accesa — quando non serve non ruba spazio
   all'elenco. I margini negativi le fanno toccare i bordi della carta, che la
   testata ha il suo respiro attorno; stando dentro alla testata resta
   appiccicata insieme a lei senza doverne indovinare l'altezza. */
.barra-selezione {
  flex: 0 0 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); flex-wrap: wrap;
  margin: 0 calc(var(--s3) * -1) calc(var(--s2) * -1);
  padding: var(--s1) var(--s3); border-top: 1px solid var(--bordo);
  background: var(--primario-tenue); color: var(--primario);
  font-size: 12.5px; font-weight: 600;
}
.barra-selezione .comandi { display: flex; align-items: center; gap: var(--s1); flex-wrap: wrap; }
/* Un bottone che resta premuto: «Seleziona» è un interruttore, non un comando
   che parte e finisce, e si deve vedere che è acceso. Vale anche per i comandi
   che aprono e chiudono un riquadro — «Statistiche» — dove il premuto dice che
   quel riquadro adesso è in vista. */
.btn[aria-pressed="true"], .btn[aria-expanded="true"] {
  background: var(--primario-tenue); border-color: var(--primario); color: var(--primario);
}

.griglia { display: grid; gap: var(--s3); }
.griglia-kpi { grid-template-columns: repeat(auto-fit, minmax(172px, 1fr)); }
.griglia-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.griglia-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* Riquadro di sintesi: niente barra colorata a sinistra, il colore sta in un
   pallino accanto all'etichetta, come i punti di stato di iOS. */
.kpi {
  background: var(--superficie); border: 1px solid var(--bordo);
  border-radius: var(--raggio-2); padding: var(--s3);
  box-shadow: var(--ombra-1);
}
.kpi .etichetta {
  font-size: 12px; color: var(--testo-tenue); text-transform: none;
  letter-spacing: 0; font-weight: 500;
  display: flex; align-items: center; gap: 6px;
}
.kpi .etichetta::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--bordo-forte);
}
.kpi .valore { font-size: 24px; font-weight: 700; margin-top: 2px; letter-spacing: -.7px; }
.kpi .nota { font-size: 12px; color: var(--testo-tenue); }
.kpi.accento .etichetta::before { background: var(--blu-vivo); }
.kpi.verde .etichetta::before   { background: var(--verde-vivo); }
.kpi.ambra .etichetta::before   { background: var(--ambra-vivo); }
.kpi.rosso .etichetta::before   { background: var(--rosso-vivo); }
.kpi.viola .etichetta::before   { background: var(--viola-vivo); }
button.kpi {
  width: 100%; text-align: left; font: inherit; cursor: pointer;
  color: inherit; background: var(--superficie);
  transition: transform .12s var(--molla), box-shadow .16s;
}
button.kpi:hover { background: var(--superficie); box-shadow: var(--ombra-2); transform: translateY(-1px); }
button.kpi:active { transform: scale(.99); }

/* ------------------------------------------------------------- griglia */

.tabella-contenitore { overflow: auto; }

/* Elenco senza pagine: la tabella si prende l'altezza che avanza e scorre da
   sola. Serve perché l'intestazione delle colonne è `position: sticky` e si
   appende al suo contenitore di scorrimento: se quel contenitore è alto
   ventitremila pixel, dopo venti righe l'intestazione è sparita.
   Gli 84px sono la testata della carta, i margini attorno e i filetti. Sotto i
   1100 px si torna allo scorrimento normale della pagina, dove due barre di
   scorrimento annidate darebbero solo fastidio. */
.tabella-contenitore.elenco-intero {
  max-height: calc(100vh - var(--altezza-strumenti) - var(--altezza-sezione)
    - var(--altezza-azioni) - 84px);
}
@media (max-width: 1100px) {
  .tabella-contenitore.elenco-intero { max-height: none; }
}

/* Elenco che riempie la finestra: la carta si prende l'altezza che avanza e a
   scorrere è la sola tabella, così l'intestazione delle colonne resta in cima
   mentre si scorrono le righe — come la riga dei filtri, che era già appesa.

   Perché serve girare la pagina in flex, invece di appiccicare l'intestazione
   come si è fatto per i filtri: `.tabella-contenitore` ha `overflow: auto`
   perché le tabelle larghe devono scorrere in orizzontale invece di gonfiare la
   pagina, e in CSS non si scorre su un asse solo — chiedere lo scorrimento
   orizzontale lo accende anche in verticale. Quindi un `position: sticky` dentro
   alla tabella si appende a quel contenitore e non alla pagina, e finché quel
   contenitore è alto quanto tutte le righe insieme non si appende a niente.
   Dandogli un'altezza che finisce dove finisce la finestra, l'intestazione ha
   qualcosa a cui restare attaccata.

   Le altezze non si scrivono da nessuna parte: le distribuisce il flex. Sopra
   alla tabella ci sono i riquadri di sintesi e i filtri, che cambiano altezza
   con la larghezza della finestra e con la selezione accesa, e un `calc()` con
   dentro dei numeri fissi sarebbe sbagliato in metà delle situazioni.

   Dove si rinuncia, e perché su due misure diverse. In **altezza** sotto ai
   520 px, perché quel che avanza alla tabella sono due righe e tanto vale
   vederle tutte scorrendo la pagina. In **larghezza** sotto ai 760 px, che è la
   soglia a cui tutto il resto della pagina si rimpicciolisce: lì la riga dei
   filtri va a capo quattro volte e da sola è alta 278 px misurati, più di mezzo
   schermo di telefono, e non avrebbe senso tenerla ferma davanti a un elenco di
   due dita.

   Quei 1100 px di larghezza che c'erano prima erano invece sbagliati: bastava
   un portatile con Windows al 125% di ingrandimento, che di pixel CSS ne conta
   mille scarsi, per non vedere mai l'intestazione appesa. Una soglia dice in
   che situazione si rinuncia, e «monitor piccolo» e «telefono» non sono la
   stessa situazione anche se qualche volta danno lo stesso numero.

   La regola sta dietro a `:has` apposta: dove non c'è — un browser vecchio —
   non si applica e l'elenco scorre come prima. Si perde l'intestazione appesa,
   non l'elenco. */
.contenuto:has(> .carta.elenco-pieno) { display: flex; flex-direction: column; }
/* `min-height` qui fa due mestieri in una riga sola, e il valore è il secondo.
   Il primo è esserci: un elemento flex senza `min-height` non scende sotto al
   proprio contenuto, e una carta che non si rimpicciolisce si pianta
   all'altezza di tutte le righe insieme — niente da distribuire, pagina che
   scorre, intestazione che scappa. Scrivendo un valore quel minimo automatico
   si spegne e la carta si adatta a quel che avanza.

   Il secondo è il valore: 300 px è il fondo sotto cui non deve andare. `.carta`
   è `overflow: clip`, quindi una carta schiacciata non mostra meno elenco —
   lo taglia via tutto, e si resta a guardare una schermata vuota. È successo,
   su iPhone: carta alta 2 px, testata dei filtri che ne chiedeva 278. Lì il
   fondo non bastava comunque, ed è il motivo per cui sotto ai 760 px si
   rinuncia del tutto (vedi sopra); qui il fondo serve per le misure di mezzo.

   Promettere quei pixel più in basso, alla tabella, non rimedia: `min-height`
   alza il minimo di chi ce l'ha, non abbassa quello di chi lo contiene. Il
   fondo va messo sulla cosa che qualcuno può schiacciare. */
.carta.elenco-pieno {
  flex: 1; min-height: 300px;
  display: flex; flex-direction: column;
}
.carta.elenco-pieno > .carta-testata { flex: none; }
/* L'area dell'elenco: la tabella più, sotto, l'impaginazione. */
.carta.elenco-pieno > :not(.carta-testata) {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
}
.carta.elenco-pieno .tabella-contenitore { flex: 1; min-height: 0; }
.carta.elenco-pieno .impaginazione { flex: none; }

@media (max-height: 520px), (max-width: 760px) {
  .contenuto:has(> .carta.elenco-pieno) { display: block; }
  .carta.elenco-pieno,
  .carta.elenco-pieno > :not(.carta-testata),
  .carta.elenco-pieno .tabella-contenitore {
    display: block; flex: none; min-height: 0;
  }
}
table.tabella { width: 100%; border-collapse: collapse; font-size: 13px; }
/* Nelle liste di iOS non ci sono righelli verticali: le colonne si leggono
   dall'allineamento, non da una gabbia. */
table.tabella th {
  text-align: left; padding: 4px var(--s3); background: var(--superficie-2);
  color: var(--testo-tenue); font-size: 12px; font-weight: 600;
  border-bottom: 1px solid var(--bordo); border-right: none;
  white-space: nowrap; position: sticky; top: 0; z-index: 1; height: 32px;
}
table.tabella th:last-child { border-right: none; }
table.tabella td {
  padding: 0 var(--s3); height: var(--altezza-riga);
  border-bottom: 1px solid var(--bordo); border-right: none;
  vertical-align: middle; overflow: hidden; text-overflow: ellipsis;
  /* Riga singola come nelle griglie desktop: la riga resta bassa e la
     tabella scorre in orizzontale invece di gonfiarsi in altezza. */
  white-space: nowrap;
}
table.tabella td .secondario { display: inline; margin-left: 6px; }
table.tabella td:last-child { border-right: none; }
table.tabella td.alto { padding: var(--s1) var(--s3); height: auto; white-space: normal; }
table.tabella tbody tr:hover { background: rgba(120, 120, 128, .08); }
table.tabella tbody tr.cliccabile { cursor: pointer; }
/* Selezione tenue con testo blu: il pieno saturo con testo bianco è il modo
   di Windows, non quello di iOS, dove la riga scelta si accende appena. */
table.tabella tbody tr[aria-selected="true"] {
  background: var(--selezione); color: var(--su-selezione);
}
table.tabella tbody tr[aria-selected="true"] .secondario,
table.tabella tbody tr[aria-selected="true"] a { color: var(--primario); }
table.tabella tbody tr[aria-selected="true"] .badge {
  background: rgba(255, 255, 255, .75); color: var(--primario-forte); border-color: transparent;
}
table.tabella tbody tr:focus-visible { outline: 2px solid var(--anello); outline-offset: -2px; }
/* Riga scelta nella selezione multipla. Non usa `aria-selected`, che qui vuol
   già dire un'altra cosa — la riga su cui sta il fuoco — e la confonderebbe
   con quelle spuntate: la barretta a sinistra si vede anche scorrendo in
   orizzontale, quando la casella è finita fuori dallo schermo. */
table.tabella tbody tr.riga-scelta > td:first-child { box-shadow: inset 3px 0 0 var(--primario); }
table.tabella tbody tr.riga-scelta { background: var(--primario-tenue); }
table.tabella tbody tr.riga-scelta:hover { background: var(--selezione); }
table.tabella .num { text-align: right; white-space: nowrap; }
table.tabella .compatto { width: 1%; white-space: nowrap; }
/* fascia che separa i documenti raggruppati per data: è l'intestazione di
   sezione di una lista raggruppata, quindi tinta tenue e nessuna cornice */
.intestazione-gruppo th {
  position: static; text-align: left; height: auto; white-space: normal;
  background: var(--primario-tenue); color: var(--primario-forte);
  border-top: none; border-bottom: 1px solid var(--bordo);
  border-right: none; padding: 0;
}
.fascia-gruppo {
  display: flex; align-items: center; gap: var(--s3);
  padding: 6px var(--s3); min-height: 32px; flex-wrap: wrap;
}
.fascia-gruppo .titolo { font-size: 13.5px; font-weight: 700; letter-spacing: -.2px; }
.fascia-gruppo .conteggio { font-size: 12px; font-weight: 400; margin-right: auto; }
.fascia-gruppo .totale {
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
}
[data-tema="scuro"] .intestazione-gruppo th { color: #6cb6ff; border-bottom-color: var(--bordo); }

/* Rimando al documento nato da questo: sta in una cella stretta, non deve
   mandare la riga a capo. */
.collegamento-derivato { white-space: nowrap; font-size: 12.5px; }

.riga-vuota td { text-align: center; color: var(--testo-tenue); padding: var(--s5) var(--s3); }
.principale { font-weight: 600; }
.secondario { color: var(--testo-tenue); font-size: 12px; }
/* Importo che toglie invece di aggiungere: una riga libera col prezzo negativo,
   cioè uno sconto in euro. Il rosso non segnala un errore, segnala il verso —
   il segno meno da solo, incolonnato fra le altre cifre, si legge poco.
   Nella scheda l'importo sta dentro a uno `span.prezzo`, che oggi il colore lo
   eredita: nominarlo serve a non perdere il rosso il giorno che ne prende uno. */
.importo-negativo, .importo-negativo .prezzo { color: var(--rosso-testo); }

th.ordinabile { padding: 0; }
th.ordinabile button[data-ordina] {
  font: inherit; font-size: 12px; font-weight: 600; color: inherit;
  background: none; border: none; cursor: pointer; width: 100%;
  display: flex; align-items: center; gap: 3px; padding: 4px var(--s3); height: 32px;
}
th.ordinabile.num button[data-ordina] { justify-content: flex-end; }
th.ordinabile button[data-ordina]:hover { color: var(--testo); }
th.ordinabile button[data-ordina] .icona { opacity: .4; }
th[aria-sort]:not([aria-sort="none"]) button[data-ordina] { color: var(--testo); }
th[aria-sort]:not([aria-sort="none"]) button[data-ordina] .icona { opacity: 1; color: var(--primario); }

/* prezzi: commutatore netto / IVA compresa
   Il testo del prezzo è il comando: cliccandolo si cambia modo di lettura. */
.testata-prezzo { display: flex; align-items: center; gap: 2px; }
.testata-prezzo button[data-ordina] { flex: 1; min-width: 0; padding-right: 0; }
.testata-prezzo .pastiglia-prezzi { margin-right: 4px; }
.etichetta-prezzo, .pastiglia-prezzi {
  font: inherit; color: inherit; background: none; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px; min-height: 24px; padding: 0;
  text-align: left;
}
.stato-prezzi {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  line-height: 1; padding: 3px 5px; border: 1px solid transparent;
  border-radius: var(--pillola);
  color: var(--testo-tenue); background: rgba(120, 120, 128, .16);
}
[data-modo-prezzi][aria-pressed="true"] .stato-prezzi {
  background: var(--primario-tenue); border-color: transparent; color: var(--primario);
}
[data-modo-prezzi]:hover .stato-prezzi { color: var(--primario); }
[data-modo-prezzi]:focus-visible { outline: 2px solid var(--anello); outline-offset: 2px; }
[data-tema="scuro"] [data-modo-prezzi][aria-pressed="true"] .stato-prezzi { color: #6cb6ff; }
[data-tema="scuro"] [data-modo-prezzi]:hover .stato-prezzi { color: #6cb6ff; }

/* lista con pannello di dettaglio affiancato */
.area-lista { display: flex; align-items: stretch; min-height: 0; }
.colonna-griglia { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pannello-dettaglio {
  width: var(--larghezza-dettaglio); flex: none;
  border-left: 1px solid var(--bordo); background: var(--superficie);
  display: flex; flex-direction: column;
  position: sticky; top: calc(var(--altezza-sezione) + var(--altezza-azioni));
  align-self: flex-start;
  max-height: calc(100vh - var(--altezza-strumenti) - var(--altezza-sezione) - var(--altezza-azioni) - var(--s5));
}
.dettaglio-testata {
  padding: var(--s3); border-bottom: 1px solid var(--bordo); background: var(--superficie);
}
.dettaglio-testata h3 {
  margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dettaglio-testata .secondario { display: block; }
.dettaglio-corpo { padding: var(--s3); overflow-y: auto; flex: 1; }
.dettaglio-piede {
  padding: var(--s3); border-top: 1px solid var(--bordo);
  display: flex; gap: var(--s1); flex-wrap: wrap;
}
.dettaglio-vuoto { padding: var(--s5) var(--s3); text-align: center; color: var(--testo-tenue); font-size: 12.5px; }

/* --------------------------------------------------- barra di quota */

/*
 * Quanto pesa una voce sul totale, dentro a una cella di tabella: il numero
 * accanto dice l'importo esatto, questa dice a colpo d'occhio quale riga si
 * mangia il mese. Il valore vero resta nel `title` e nelle colonne di fianco,
 * quindi la barra è decorativa e non porta informazione da sola.
 */
.barra-quota {
  height: 8px; border-radius: var(--pillola); overflow: hidden;
  background: rgba(120, 120, 128, .16); min-width: 60px;
}
.barra-quota > div {
  height: 100%; border-radius: var(--pillola);
  background: var(--ambra-vivo);
}

/* -------------------------------------------------------------- badge */

.badge {
  display: inline-flex; align-items: center; gap: 3px; padding: 0 8px;
  font-size: 11.5px; font-weight: 600; white-space: nowrap; line-height: 18px;
  border-radius: var(--pillola);
  background: rgba(120, 120, 128, .14); color: var(--testo-tenue); border: 1px solid transparent;
}
.badge.grigio { background: rgba(120, 120, 128, .14); color: var(--testo-tenue); }
.badge.blu    { background: var(--primario-tenue); color: var(--primario); border-color: transparent; }
.badge.verde  { background: var(--verde-tenue); color: var(--verde); border-color: transparent; }
.badge.ambra  { background: var(--ambra-tenue); color: var(--ambra); border-color: transparent; }
.badge.rosso  { background: var(--rosso-tenue); color: var(--rosso-testo); border-color: transparent; }
.badge.viola  { background: var(--viola-tenue); color: var(--viola); border-color: transparent; }
[data-tema="scuro"] .badge.blu { color: #6cb6ff; }

/* --------------------------------------------------------------- form */

.campo { display: flex; flex-direction: column; gap: 3px; margin-bottom: var(--s3); }
.campo > span { font-size: 12.5px; font-weight: 500; color: var(--testo-tenue); }
/* Campi pieni, non incorniciati: al fuoco si accendono di bianco col bordo. */
.campo input, .campo select, .campo textarea, .controllo {
  font: inherit; font-size: 13px; padding: 5px var(--s2);
  border: 1px solid transparent; border-radius: var(--raggio);
  background: var(--riempimento); color: var(--testo); width: 100%; min-height: 32px;
  transition: background-color .16s, border-color .16s;
}
.campo input:focus, .campo select:focus, .campo textarea:focus, .controllo:focus {
  background: var(--superficie); border-color: var(--bordo-forte);
}
.campo textarea { resize: vertical; min-height: 62px; }
.campo input[readonly] { background: var(--riempimento); color: var(--testo-tenue); }
.campo input[aria-invalid="true"], .campo select[aria-invalid="true"] { border-color: var(--rosso); }
.campo .errore-campo { font-size: 12px; color: var(--rosso-testo); font-weight: 500; }
/* etichetta di un campo prezzo: il nome resta una <label> vera, la pastiglia
   accanto commuta netto/ivato senza rubare il clic al campo */
.campo > span.con-prezzi { display: flex; align-items: center; gap: 6px; }
.campo > span.con-prezzi label { cursor: pointer; }
.campo-riga { display: grid; gap: var(--s2) var(--s3); grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
/* Scelta delle colonne: caselle in colonne strette. Non levette — quelle
   accendono un'impostazione, qui si spuntano voci di un elenco — e non due
   sole colonne: con venti campi la lista finiva sotto il bordo della finestra. */
.elenco-colonne {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
  gap: 2px var(--s4);
}
.spunta-colonna {
  display: flex; align-items: center; gap: var(--s2);
  min-height: 28px; padding: 2px 6px; margin: 0;
  border-radius: var(--raggio-1); cursor: pointer; font-size: 13px;
  transition: background-color .14s;
}
.spunta-colonna:hover { background: rgba(120, 120, 128, .1); }
.spunta-colonna > span { min-width: 0; overflow-wrap: anywhere; }
/* La colonna che identifica la riga si vede spuntata ma non si tocca. */
.spunta-colonna.fissa { cursor: default; color: var(--testo-tenue); }
.spunta-colonna.fissa:hover { background: none; }
.spunta-colonna.fissa input { cursor: default; }
.campo-interruttore { flex-direction: row; align-items: center; gap: var(--s2); cursor: pointer; min-height: 32px; }
.campo-interruttore > span { font-size: 13px; color: var(--testo); font-weight: 400; }
input[type="checkbox"], input[type="radio"] {
  width: 16px; height: 16px; min-height: 0; accent-color: var(--blu-vivo);
  cursor: pointer; margin: 0; flex: none;
}
/* L'interruttore di iOS: la levetta che scorre. Vale solo per le opzioni di un
   form — nelle celle di una tabella resta la casella, che si legge in fila. */
.campo-interruttore input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 42px; height: 26px; border-radius: var(--pillola);
  background: rgba(120, 120, 128, .28); position: relative; flex: none;
  transition: background-color .24s var(--molla);
}
.campo-interruttore input[type="checkbox"]::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 22px; height: 22px;
  border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, .25);
  transition: transform .24s var(--molla);
}
.campo-interruttore input[type="checkbox"]:checked { background: var(--verde-vivo); }
.campo-interruttore input[type="checkbox"]:checked::after { transform: translateX(16px); }
input[type="file"] { min-height: 32px; font: inherit; font-size: 13px; color: var(--testo); }

/* Elenco di spunte in griglia (le aree di un utente): qui la levetta di iOS
   sarebbe fuori scala — tredici voci da leggere in colonna vogliono la casella. */
.casella-area {
  display: flex; align-items: center; gap: var(--s2);
  font-size: 13px; min-height: 26px; cursor: pointer;
}
fieldset.sezione.disabilitata { opacity: .45; }
fieldset.sezione.disabilitata .casella-area { cursor: default; }

fieldset.sezione { border: none; padding: 0; margin: 0; }
fieldset.sezione > legend {
  font-size: 12px; text-transform: none; letter-spacing: 0; color: var(--testo-tenue);
  font-weight: 600; padding: var(--s3) 0 var(--s1); width: 100%;
  border-bottom: none; margin-bottom: var(--s2);
}

.filtri {
  display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
}
.filtri input:not([type="checkbox"]):not([type="radio"]), .filtri select {
  width: auto; min-width: 140px;
}
/* Data con la sua paroletta davanti: «Dal [__]». Su un campo data il
   placeholder non si vede — il browser ci mette già gg/mm/aaaa — quindi senza
   l'etichetta accanto due caselle uguali non direbbero quale è quale. */
.filtro-data { display: inline-flex; align-items: center; gap: 6px; }
.filtro-data > .secondario { font-size: 12px; }

/* Controllo segmentato: la pastiglia bianca che scorre sul fondo grigio. */
.gruppo-periodo { border: none; padding: 0; margin: 0; min-width: 0; }
.filtro-periodo {
  display: inline-flex; flex-wrap: wrap; gap: 2px;
  border: none; border-radius: var(--raggio); padding: 2px;
  background: rgba(120, 120, 128, .12);
}
.filtro-periodo input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.filtro-periodo label {
  display: inline-flex; align-items: center; min-height: 26px;
  padding: 0 var(--s3); font-size: 12.5px; white-space: nowrap; font-weight: 500;
  color: var(--testo); cursor: pointer; border-left: none;
  border-radius: var(--raggio-1); transition: background-color .18s var(--molla);
}
.filtro-periodo label:first-of-type { border-left: none; }
.filtro-periodo label:hover { background: rgba(120, 120, 128, .12); color: var(--testo); }
.filtro-periodo input:checked + label {
  background: var(--superficie); color: var(--testo); font-weight: 600;
  box-shadow: var(--ombra-1);
}
.filtro-periodo input:focus-visible + label { outline: 2px solid var(--anello); outline-offset: -2px; }

.riepilogo-errori {
  background: var(--rosso-tenue); border-left: none; border-radius: var(--raggio-2);
  padding: var(--s3); margin-bottom: var(--s2);
}
.riepilogo-errori h3 { margin: 0 0 2px; font-size: 13px; color: var(--rosso-testo); }
.riepilogo-errori ul { margin: 0; padding-left: var(--s4); font-size: 13px; }
.riepilogo-errori a { color: var(--rosso-testo); }
.riepilogo-errori p { margin: 0; font-size: 13px; }
/* Non è un errore: è un «guarda che forse». Ambra, e il salvataggio resta lì
   sotto a portata di secondo clic. */
.riepilogo-errori.avviso { background: var(--ambra-tenue); }
.riepilogo-errori.avviso h3 { color: var(--ambra); }
.riepilogo-errori.avviso p { margin-top: var(--s2); color: var(--testo-tenue); }

/* ------------------------------------------------------------ finestre */

.sovrapposizione {
  position: fixed; inset: 0; background: rgba(0, 0, 0, .4); z-index: 100;
  display: flex; align-items: flex-start; justify-content: center;
  padding: var(--s5); overflow-y: auto;
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.pannello {
  background: var(--superficie); border: none; border-radius: var(--raggio-3);
  box-shadow: var(--ombra-alta); width: 100%; max-width: 700px; margin: auto;
  overflow: hidden; animation: sale .28s var(--molla);
}
@keyframes sale { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
.pannello.largo { max-width: 1020px; }
.pannello.stretto { max-width: 400px; }
/* Testata chiara col titolo in mezzo, come i fogli modali di iOS. */
.pannello-testata {
  padding: var(--s2) var(--s3); background: var(--superficie); color: var(--testo);
  border-bottom: 1px solid var(--bordo);
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2); min-height: 46px;
}
.pannello-testata h2 { margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.3px; }
/* La X di iOS è un tondino grigio, non un'icona nuda sul colore. */
.pannello-testata .btn-icona {
  color: var(--testo-tenue); background: rgba(120, 120, 128, .14); border-radius: 50%;
}
.pannello-testata .btn-icona:hover { background: rgba(120, 120, 128, .24); border-color: transparent; color: var(--testo); }
.pannello-corpo { padding: var(--s4); max-height: calc(100vh - 210px); overflow-y: auto; }
.pannello-piede {
  padding: var(--s3) var(--s4); border-top: 1px solid var(--bordo); background: var(--superficie);
  display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); flex-wrap: wrap;
}
/* Riepilogo a sinistra, comandi a destra: usato dal selettore a catalogo. */
.pannello-piede .a-sinistra { margin-right: auto; }

/* I comandi per comporre le righe stanno accanto al titolo, non in fondo:
   margin-right auto annulla lo space-between della testata. */
.strumenti-righe {
  display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap;
  margin-right: auto;
}
/* Il campo di ricerca prodotto: sotto questa misura i nomi degli articoli
   arrivano tagliati e non si distinguono più fra loro. */
#selettore-prodotto { min-width: 260px; }

/* Roba che compare solo sul telefono, dove qualcos'altro è sparito per far
   posto: il commutatore netto/ivato quando l'intestazione della tabella non
   c'è più. Sul resto degli schermi non esiste. */
.solo-telefono { display: none; }

/* Casella dentro una cella: l'etichetta allarga il bersaglio oltre i 24px
   che il quadratino da solo non raggiunge. */
.spunta-cella {
  display: flex; align-items: center; justify-content: center;
  min-width: 28px; min-height: 24px; cursor: pointer; margin: 0;
}

/* ------------------------------------------------ impostazioni: stampa */

/* Le scelte a sinistra e il foglio a destra: si cambia il colore e lo si vede.
   Sotto ai 900 px vanno una sull'altra, con l'anteprima per seconda. */
.griglia-stampa {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: var(--s4);
  align-items: start;
}
@media (max-width: 900px) { .griglia-stampa { grid-template-columns: 1fr; } }

.anteprima-pdf {
  width: 100%; height: 620px; border: 1px solid var(--bordo);
  border-radius: var(--raggio-2); background: var(--sfondo);
}
@media (max-width: 900px) { .anteprima-pdf { height: 460px; } }

.riga-colore { display: flex; gap: var(--s2); align-items: center; }
.riga-colore input[type="color"] {
  width: 44px; height: 34px; flex: none; padding: 2px;
  border: 1px solid var(--bordo-forte); border-radius: var(--raggio-2);
  background: var(--chrome); cursor: pointer;
}
.riga-colore input[type="text"] { width: 9ch; flex: none; font-family: var(--mono); }

/* ---------------------------------------------------------- notifiche */

/* In basso a sinistra: è l'angolo che resta libero mentre si lavora, lontano
   dai bottoni di salvataggio in fondo alle schede. */
.notifiche {
  position: fixed; left: var(--s4); bottom: var(--s4);
  z-index: 200; display: flex; flex-direction: column; gap: var(--s2);
  max-width: 380px; pointer-events: none;
}
/* Il banner di iOS: pillola morbida su vetro, il colore lo porta l'icona. */
.notifica {
  background: var(--chrome); border: 1px solid var(--bordo);
  -webkit-backdrop-filter: var(--vetro); backdrop-filter: var(--vetro);
  border-left: 1px solid var(--bordo); border-radius: var(--raggio-2);
  padding: var(--s3); box-shadow: var(--ombra-2); font-size: 13px;
  display: flex; gap: var(--s2); align-items: flex-start; pointer-events: auto;
  animation: entra .3s var(--molla);
}
.notifica.successo { border-left-color: var(--bordo); }
.notifica.successo .icona { color: var(--verde); }
.notifica.errore { border-left-color: var(--bordo); }
.notifica.errore .icona { color: var(--rosso-testo); }
.notifica.attenzione { border-left-color: var(--bordo); }
.notifica.attenzione .icona { color: var(--ambra); }
@keyframes entra { from { opacity: 0; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }

.avviso-errore {
  background: var(--rosso-tenue); color: var(--rosso-testo);
  padding: var(--s3); font-size: 13px; border-left: none; border-radius: var(--raggio-2);
}
.avviso-informativo {
  background: var(--primario-tenue); color: var(--primario);
  padding: var(--s3); font-size: 13px; margin-bottom: var(--s2);
  border-left: none; border-radius: var(--raggio-2);
}
.avviso-informativo code { font-family: var(--mono); font-size: 12px; }
[data-tema="scuro"] .avviso-informativo { color: #6cb6ff; }

/* -------------------------------------------------------- vari widget */

.stato-vuoto { text-align: center; padding: var(--s5) var(--s4); color: var(--testo-tenue); }
.stato-vuoto .icona { margin: 0 auto var(--s2); opacity: .25; }
.stato-vuoto h3 { margin: 0 0 2px; color: var(--testo); font-size: 15px; font-weight: 600; }

/* Filo di avanzamento del cambio pagina: due pixel che scorrono sotto alla
   barra degli strumenti. Tiene il suo posto anche da spento — `height` fissa,
   niente `display:none` — così accendendosi non sposta di due pixel tutto
   quello che ha sotto. */
.avanzamento { height: 2px; flex: none; overflow: hidden; background: transparent; }
.avanzamento.attivo { background: var(--bordo); }
.avanzamento.attivo::after {
  content: ""; display: block; height: 100%; width: 40%;
  background: var(--primario); animation: scorre 1s ease-in-out infinite;
}
@keyframes scorre {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}
/* Chi ha chiesto meno animazioni si tiene il filo fermo e acceso: dice
   comunque che si sta aspettando, senza niente che si muove. */
@media (prefers-reduced-motion: reduce) {
  .avanzamento.attivo::after { animation: none; width: 100%; opacity: .6; }
}

/* Un elenco che si ridisegna con dentro già qualcosa non si svuota: resta
   leggibile e si smorza, così si vede che sta arrivando la versione nuova
   senza che la tabella sparisca e la pagina si accartocci. */
.in-aggiornamento { opacity: .85; transition: opacity .12s ease-out; pointer-events: none; }

.caricamento { display: grid; place-items: center; padding: var(--s5); color: var(--testo-tenue); }
.cerchio {
  width: 22px; height: 22px; border: 2px solid var(--bordo); border-top-color: var(--primario);
  border-radius: 50%; animation: gira .7s linear infinite; margin-bottom: var(--s2);
}
@keyframes gira { to { transform: rotate(360deg); } }

.impaginazione {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); padding: var(--s2) var(--s3); border-top: 1px solid var(--bordo);
  background: var(--superficie); flex-wrap: wrap;
}
.impaginazione .info { font-size: 12px; color: var(--testo-tenue); }
.impaginazione-info, .impaginazione-taglia {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
}
.impaginazione-taglia .controllo { width: auto; min-width: 80px; }

.grafico { display: flex; align-items: flex-end; gap: var(--s2); height: 132px; padding-top: var(--s2); }
.grafico .colonna {
  flex: 1; display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; gap: 3px; height: 100%; background: none; border: none;
  font: inherit; color: inherit; cursor: default; padding: 0;
}
.grafico .asta {
  width: 100%; max-width: 46px; background: var(--blu-vivo); min-height: 3px;
  border-radius: var(--raggio-1) var(--raggio-1) 3px 3px; transition: background-color .18s;
}
.grafico .colonna:hover .asta, .grafico .colonna:focus-visible .asta { background: var(--verde-vivo); }
.grafico .etichetta { font-size: 10.5px; color: var(--testo-tenue); white-space: nowrap; }
.riepilogo-grafico { font-size: 13px; color: var(--testo-tenue); margin: 0 0 var(--s2); }
details.dati-grafico { margin-top: var(--s2); }
details.dati-grafico > summary {
  cursor: pointer; font-size: 12.5px; color: var(--primario); font-weight: 600; padding: 2px 0;
}

.elenco-semplice { display: flex; flex-direction: column; }
.elenco-semplice .voce {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: var(--s2) 0; border-bottom: 1px solid var(--bordo); font-size: 13px;
}
.elenco-semplice .voce:last-child { border-bottom: none; }
.elenco-semplice a { color: var(--testo); text-decoration: none; }

/* ------------------------------------------------ pagina di un documento
 *
 * Preventivi, ordini e DDT non sono elenchi: sono fogli. Stirarli da bordo a
 * bordo su un monitor largo allontana la descrizione dal suo importo e rende
 * un campo data largo mezzo schermo. Quindi larghezza massima e pagina
 * centrata, come il documento che poi si stampa.
 */
/* Il selettore è ancorato a .contenuto perché lì i figli hanno già un margine
   laterale fisso, che va sostituito da quello automatico senza perdere il
   respiro sui lati quando la finestra è stretta. */
/* La regola dei margini qui sopra vale anche per il foglio: questa deve
   batterla per specificità, non per ordine di scrittura. */
.contenuto > .foglio:not(.a-tutta-larghezza) {
  max-width: 1240px; width: calc(100% - var(--s4) * 2);
  margin-left: auto; margin-right: auto;
}

/* Testata: intestatario a sinistra, dati del documento a destra, come sulla
   carta. Prima erano due file di campi tutti larghi uguale. */
.testata-documento {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 0 var(--s4); align-items: start;
}
.campo-coppia { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--s2); }
.campo-coppia.sbilanciata { grid-template-columns: 2fr 1fr; }
.riquadro-intestatario {
  border: 1px solid transparent; background: var(--riempimento);
  border-radius: var(--raggio); padding: 5px var(--s2); min-height: 32px;
  margin-bottom: var(--s3);
}
.riquadro-intestatario.modificabile { cursor: pointer; transition: background-color .16s; }
.riquadro-intestatario.modificabile:hover { border-color: var(--bordo-forte); background: var(--superficie-2); }

/* Il riquadro dell'intestatario nella scheda: si apre in finestra, quindi si
   comporta da bersaglio cliccabile pur restando un blocco di dati. */
.blocco-intestatario {
  cursor: pointer; border-radius: var(--raggio);
  margin: -6px calc(var(--s2) * -1); padding: 6px var(--s2);
  transition: background-color .16s;
}
.blocco-intestatario:hover { background: var(--riempimento); }
.azioni-testata { display: flex; gap: 6px; }

/* Scheda articolo in finestra: dati a sinistra, descrizione e movimenti a
   destra. Sotto i 620px la finestra è già stretta e le due colonne si
   impilano da sole. */
.scheda-finestra {
  display: grid; grid-template-columns: minmax(210px, 300px) 1fr;
  gap: var(--s4); margin-top: var(--s4);
}
@media (max-width: 620px) { .scheda-finestra { grid-template-columns: 1fr; } }
.titolo-riquadro {
  margin: 0 0 var(--s1); font-size: 12.5px; font-weight: 600; text-transform: none;
  letter-spacing: 0; color: var(--testo-tenue);
}

/* Corpo della scheda: il documento a sinistra, stato e totali in una colonna
   che resta in vista mentre si scorrono le righe. */
.documento-affiancato { display: flex; gap: var(--s3); align-items: flex-start; }
.documento-corpo { flex: 1; min-width: 0; }
.documento-riepilogo {
  width: 292px; flex: none;
  position: sticky; top: calc(var(--altezza-sezione) + var(--altezza-azioni) + var(--s2));
  display: flex; flex-direction: column; gap: var(--s3);
}
@media (max-width: 1100px) {
  .documento-affiancato { display: block; }
  .documento-riepilogo { width: auto; position: static; margin-top: var(--s3); }
}

.azioni-stato { display: flex; flex-wrap: wrap; gap: var(--s1); }

/* Contatori in testa a un elenco di documenti: schede di larghezza propria,
   allineate a sinistra. Stirate su tutta la finestra il numero si perdeva in
   mezzo al bianco. */
.riepilogo-documenti {
  display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(180px, 232px));
  justify-content: start;
}

.righe-documento { width: 100%; border-collapse: collapse; font-size: 13px; }
/* Colonne numeriche a larghezza fissa: allargarle su uno schermo grande
   servirebbe solo ad allontanare il prezzo dalla sua descrizione. */
.righe-documento { table-layout: fixed; min-width: 820px; }
.righe-documento th {
  font-size: 11.5px; text-transform: none; letter-spacing: 0;
  color: var(--testo-tenue); text-align: left; padding: 2px 4px; font-weight: 600;
}
/* Le righe sono a riga singola: i valori calcolati e il comando di rimozione
   vanno centrati sui campi, non appoggiati in alto. */
.righe-documento td { padding: 3px 4px; vertical-align: middle; }
.righe-documento td.importo-riga { font-weight: 600; }
.righe-documento input, .righe-documento select, .righe-documento textarea {
  font: inherit; font-size: 13px; padding: 4px 7px; border: 1px solid transparent;
  border-radius: var(--raggio-1); background: var(--riempimento); color: var(--testo);
  width: 100%; min-height: 30px; transition: background-color .16s, border-color .16s;
}
.righe-documento input:focus, .righe-documento select:focus, .righe-documento textarea:focus {
  background: var(--superficie); border-color: var(--bordo-forte);
}
.righe-documento textarea { min-height: 30px; resize: vertical; }
.righe-documento .num input { text-align: right; font-variant-numeric: tabular-nums; }
/* Nell'editor la descrizione è un campo a riga singola: la foto gli sta di
   fianco centrata, non appesa in alto. */
.righe-documento .cella-descrizione { align-items: center; }
/* I saldi sono cinque colonne, non nove: non hanno bisogno degli 820px che
   servono alle righe del documento, e su un portatile ci stanno senza scorrere. */
.tabella-saldi { min-width: 540px; }

/* Piede dell'editor: note a sinistra, sconto e totali in un riquadro a destra
   che si legge come il totale di una fattura, non come un campo qualsiasi. */
.piede-editor {
  display: flex; gap: var(--s4); margin-top: var(--s4); flex-wrap: wrap;
  align-items: flex-start;
}
.note-editor { flex: 1; min-width: 260px; max-width: 640px; }
.totali-editor {
  flex: 0 0 300px; border: 1px solid var(--bordo); border-radius: var(--raggio-2);
  background: var(--superficie-2); padding: var(--s3);
}
.totali-editor .campo { margin-bottom: var(--s2); }
.totali-editor .riquadro-totali { max-width: none; }
@media (max-width: 720px) { .totali-editor { flex: 1 1 100%; } }

.riquadro-totali { margin-left: auto; max-width: 300px; }
.riquadro-totali .riga { display: flex; justify-content: space-between; padding: 3px 0; font-size: 13px; }
.riquadro-totali .riga.grande {
  border-top: 1px solid var(--bordo); margin-top: var(--s1); padding-top: var(--s2);
  font-size: 19px; font-weight: 700; letter-spacing: -.4px;
}
.riquadro-totali .etichetta { color: var(--testo-tenue); }

.selettore { position: relative; }
.selettore-elenco {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; background: var(--superficie);
  border: 1px solid var(--bordo); border-radius: var(--raggio-2); box-shadow: var(--ombra-alta);
  max-height: 240px; overflow-y: auto; z-index: 60; padding: var(--s1);
}
.selettore-elenco [role="option"] {
  padding: 6px var(--s2); cursor: pointer; font-size: 13px; border-radius: var(--raggio-1);
}
.selettore-elenco [role="option"]:hover,
.selettore-elenco [role="option"][aria-selected="true"] { background: var(--primario-tenue); color: var(--primario); }
.selettore-elenco [role="option"]:hover small,
.selettore-elenco [role="option"][aria-selected="true"] small { color: var(--primario); }
.selettore-elenco small { color: var(--testo-tenue); display: block; }
/* Ricerca per nome e, di fianco, il bottone che apre l'elenco intero: due modi
   di scegliere la stessa cosa, sulla stessa riga. */
.campo-con-azione { display: flex; align-items: center; gap: var(--s1); }
.campo-con-azione > .selettore { flex: 1 1 auto; min-width: 0; }

.selettore-vuoto {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: 6px var(--s2); font-size: 13px; color: var(--testo-tenue);
}
.selettore-vuoto .btn { flex: none; }

/* Schede alla iOS: pastiglie su fondo grigio, non linguette di cartella. */
.schede {
  display: flex; gap: 2px; border-bottom: none; margin-bottom: var(--s3); flex-wrap: wrap;
  background: rgba(120, 120, 128, .12); border-radius: var(--raggio); padding: 2px;
  align-self: flex-start; width: fit-content; max-width: 100%;
}
.schede button {
  font: inherit; font-size: 13px; padding: 4px var(--s3); border: none;
  background: none; color: var(--testo); cursor: pointer;
  min-height: 28px; margin-bottom: 0; border-radius: var(--raggio-1);
  transition: background-color .18s var(--molla);
}
.schede button[aria-selected="true"] {
  color: var(--testo); background: var(--superficie); font-weight: 600;
  border-color: transparent; box-shadow: var(--ombra-1);
}

/* align-items: la riga di un'etichetta cliccabile cresce fino al bersaglio da
   24px, e senza questo il valore accanto resterebbe disallineato in alto. */
.dati-coppia {
  display: grid; grid-template-columns: 112px 1fr; align-items: center;
  gap: 3px var(--s2); font-size: 13px; margin: 0;
}
.dati-coppia dt { color: var(--testo-tenue); }
.dati-coppia dd { margin: 0; overflow-wrap: anywhere; }

/* Numero di telefono: il numero e, per chi ha configurato un telefono IP, il
   bottone che glielo fa comporre. Il bottone sta stretto accanto al numero e
   non in fondo alla colonna, così si capisce a quale dei due si riferisce
   quando ce ne sono due — telefono e cellulare — uno sotto l'altro. */
.dato-telefono { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.dato-telefono .btn-icona { min-width: 24px; min-height: 24px; padding: 3px; }

/* Il numero si tocca come la cornetta, ma non deve urlare che è un
   collegamento: dentro una riga di elenco, in mezzo a città e partite IVA, un
   numero blu e sottolineato è l'unica cosa che si vede. Tiene il colore del
   testo e si sottolinea quando ci passi sopra, come i nomi nelle tabelle. */
a.numero-telefono {
  color: inherit; text-decoration: none; cursor: pointer; text-underline-offset: 2px;
}
a.numero-telefono:hover { text-decoration: underline; }
/* Mentre la chiamata parte: il numero resta leggibile ma non più toccabile,
   così un secondo tocco non parte e si vede che qualcosa sta succedendo. */
[data-chiamando] { opacity: .55; pointer-events: none; }

/* Il tasto di WhatsApp: verde suo, non il grigio degli altri comandi. È un
   marchio, e lo si cerca con la coda dell'occhio fra dieci righe di anagrafica:
   riconoscerlo dal colore prima ancora di leggere è tutto il suo lavoro. Il
   verde ufficiale tiene il contrasto sia sul chiaro sia sullo scuro. */
.btn-icona.btn-whatsapp { color: #25d366; }
.btn-icona.btn-whatsapp:hover { color: #1da851; background: rgba(37, 211, 102, .14); }

/* Una riga dell'elenco dei telefoni: nome, indirizzo e il cestino in fondo.
   Il cestino si allinea in basso perché i due campi hanno l'etichetta sopra e
   sono più alti di lui. Su un telefono i campi vanno a capo e il cestino si
   sposta in fondo, dove non si preme per sbaglio mentre si scrive. */
.riga-telefono {
  display: flex; gap: var(--s2); align-items: flex-end;
  margin-bottom: var(--s2); flex-wrap: wrap;
}
.riga-telefono .campo { flex: 1 1 180px; margin: 0; }
.riga-telefono .btn-icona { margin-bottom: 4px; }

/* La finestra che chiede da quale telefono chiamare: un bottone per
   apparecchio, uno sotto l'altro e alti da premere col pollice. Nome in
   evidenza e indirizzo dietro, che serve solo a distinguere due stanze
   chiamate quasi uguale. */
.scelta-telefoni { display: grid; gap: var(--s2); }
.scelta-telefoni .btn { justify-content: flex-start; gap: var(--s2); padding: var(--s3) var(--s2); }
.scelta-telefoni .btn .secondario { margin-left: auto; font-size: 12px; }
.scelta-telefoni .btn-primario .secondario { color: inherit; opacity: .75; }

/* Esito delle copie del backup, una riga per destinazione con l'errore per
   esteso sotto. Va letto, non intravisto: se una copia non è partita è quello
   il momento per accorgersene, e una notifica che sparisce non basta. */
.esiti-destinazioni {
  list-style: none; margin: 0 0 var(--s3); padding: 0; display: grid; gap: 6px;
}
.esiti-destinazioni li {
  padding: var(--s2); border: 1px solid var(--bordo); border-radius: var(--raggio-1);
  background: var(--superficie-2); font-size: 13px; overflow-wrap: anywhere;
}

/* Riepilogo dei dati aziendali: logo di fianco e poche righe di testo. Quei
   campi si compilano una volta sola alla partenza, e un form aperto su mezza
   pagina per sempre è spazio tolto a quello che si guarda davvero — il vero
   form si apre in finestra, come per clienti e prodotti. */
.riepilogo-azienda { display: flex; gap: var(--s3); align-items: flex-start; flex-wrap: wrap; }
.riepilogo-azienda .logo { flex: none; }
.riepilogo-azienda .dati { min-width: 0; line-height: 1.6; overflow-wrap: anywhere; }

/* Angoli tondi come le icone delle app: è il dettaglio che dice "Apple". */
.miniatura {
  width: 26px; height: 26px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--bordo); background: var(--superficie-2); display: block;
}
/* Miniatura dentro alla riga di un documento, accanto alla descrizione. */
.miniatura-riga {
  width: 24px; height: 24px; object-fit: cover; border-radius: 5px;
  border: 1px solid var(--bordo); background: var(--superficie-2);
  display: block; flex: none; margin-top: 2px;
}
/* La foto sta accanto al testo, non sopra: la descrizione è quello che si
   legge, e deve restare larga quanto la cella. */
.cella-descrizione { display: flex; gap: var(--s2); align-items: flex-start; }
.cella-descrizione > div { min-width: 0; flex: 1; }
.cella-descrizione > textarea { flex: 1; min-width: 0; }

/* Caricamento della foto sulla scheda prodotto: anteprima a sinistra, il modo
   per cambiarla al centro, il "togli" in fondo. */
.blocco-immagine { display: flex; gap: var(--s3); align-items: flex-start; flex-wrap: wrap; }
.blocco-immagine > div:nth-child(2) { flex: 1; min-width: 220px; }
.anteprima-immagine {
  width: 92px; height: 92px; flex: none; display: flex; align-items: center;
  justify-content: center; text-align: center; padding: 4px; font-size: 12px;
  border: 1px solid var(--bordo); border-radius: var(--raggio); background: var(--superficie-2);
}
.anteprima-immagine img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px; }

/* -------------------------------------------------- calendario delle ore */

/* Il mese è una griglia in cui si scrive, non una tabella da leggere: sette
   colonne uguali per i giorni e una in fondo per il totale della settimana,
   che sta fuori dai giorni perché non è un giorno. Le caselle hanno un'altezza
   fissa: riempiendosi la griglia non deve cambiare forma sotto al puntatore. */

.navigatore-mese { display: flex; align-items: center; gap: var(--s1); margin-left: auto; }
.navigatore-mese strong { min-width: 150px; text-align: center; font-size: 14px; }

.nota-calendario { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 var(--s2); }
.nota-calendario .icona { flex: none; margin-top: 1px; }

table.calendario { width: 100%; border-collapse: collapse; table-layout: fixed; }
table.calendario th {
  font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  color: var(--testo-tenue); text-align: left; padding: 4px 6px;
  border-bottom: 1px solid var(--bordo);
}
table.calendario th.festivo { color: var(--rosso-testo); }
table.calendario th.num { text-align: right; width: 104px; }

td.giorno {
  height: 68px; vertical-align: top; padding: 5px 6px; cursor: pointer;
  border: 1px solid var(--bordo); background: var(--superficie);
  /* Il doppio clic apre la casella: senza questo selezionerebbe anche il
     numero del giorno, lasciando la griglia blu di testo evidenziato. */
  user-select: none;
  transition: background-color .12s;
}
td.giorno:hover { background: var(--riempimento); }
td.giorno:focus-visible { outline: 2px solid var(--anello); outline-offset: -2px; }
td.giorno.festivo { background: var(--superficie-2); }
/* Il posto dei giorni del mese vicino: tiene in riga le colonne dei giorni
   della settimana e non fa altro. Niente puntatore e niente evidenziazione al
   passaggio: non è una casella su cui si possa fare qualcosa. */
td.giorno.vuota, td.giorno.vuota:hover {
  background: var(--sfondo); border-color: transparent; cursor: default;
}
td.giorno.con-ore { background: var(--primario-tenue); }
td.giorno.oggi { box-shadow: inset 0 0 0 2px var(--primario); }

.numero-giorno { display: block; font-size: 12px; color: var(--testo-tenue); }
td.giorno.oggi .numero-giorno { color: var(--primario); font-weight: 700; }
.ore-giorno {
  display: block; margin-top: 2px; font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dettaglio-giorno {
  display: block; margin-top: 1px; font-size: 11px; color: var(--testo-tenue);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* La nota del giorno — «straordinario», «trasferta», «mezza giornata» — è
   quello che si va a cercare scorrendo il mese: rossa e più grande del
   contorno si trova senza aprire le caselle una per una. Se non ci sta per
   intero, il testo completo è nel suggerimento della casella. */
.nota-giorno {
  display: block; margin-top: 1px; font-size: 13px; font-weight: 600;
  line-height: 1.15; color: var(--rosso-testo);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
td.totale-settimana {
  border: 1px solid var(--bordo); background: var(--superficie-2);
  vertical-align: top; padding: 5px 8px; white-space: nowrap;
  font-weight: 600; font-variant-numeric: tabular-nums;
}

.totali-mese {
  display: flex; flex-wrap: wrap; gap: var(--s5); margin-top: var(--s3);
  padding-top: var(--s3); border-top: 1px solid var(--bordo);
}
.totali-mese .etichetta {
  display: block; font-size: 11.5px; color: var(--testo-tenue);
  text-transform: uppercase; letter-spacing: .4px;
}
.totali-mese strong { font-size: 18px; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ responsive */

@media (max-width: 1100px) {
  .pannello-dettaglio { display: none; }
}

@media (max-width: 760px) {
  .barra-strumenti { height: auto; flex-wrap: wrap; padding: var(--s1) var(--s2); gap: var(--s1); }
  .identita { border-right: none; }
  .strumenti-destra { border-left: none; margin-left: auto; }
  /* La ricerca globale sparisce: ridotta alla larghezza di un telefono era un
     campo da due parole con sotto un pannello di risultati che copriva la
     schermata, e spingeva la barra su tre righe. Ogni elenco ha la sua ricerca
     in testa, che cerca dove si sta guardando. */
  .ricerca-globale { display: none; }
  .utente-attivo { display: none; }
  /* Il menu va a capo e si prende la riga tutta sua. `width: 100%` da solo non
     basta: con `flex: 1` e `min-width: 0` la barra preferisce stringerlo fino a
     un moncone di una voce sola invece di mandarlo a capo. La base dev'essere
     il 100%, ed è quella a costringere l'a capo. */
  #navigazione { order: 3; flex: 1 0 100%; width: 100%; }
  #navigazione a { min-width: 62px; padding: 6px; }
  .corpo-pagina { padding: var(--s2); }
  .campo-riga { grid-template-columns: 1fr; }
  .dati-coppia { grid-template-columns: 96px 1fr; }
  .sovrapposizione { padding: var(--s2); }
  .barra-sezione { flex-wrap: wrap; padding: var(--s2); min-height: 0; }
  .barra-sezione h1 { font-size: 18px; }
  .barra-sezione .azioni { margin-left: 0; width: 100%; }
  /* Otto colonne su un telefono diventano illeggibili: il calendario tiene la
     sua misura e scorre di lato dentro al contenitore, come le altre tabelle. */
  table.calendario { min-width: 620px; }
  .navigatore-mese { margin-left: 0; }
  .totali-mese { gap: var(--s4); }
  .contenuto > *:not(.a-tutta-larghezza) { margin-left: var(--s2); margin-right: var(--s2); }
  /* iOS non ingrandisce se il campo parte da 16px */
  .campo input, .campo select, .campo textarea, .controllo,
  .ricerca-globale input, .righe-documento input,
  .righe-documento select, .righe-documento textarea { font-size: 16px; }
  .solo-telefono { display: inline-flex; }

  /* La finestra modale si prende quasi tutto lo schermo: su un telefono i
     margini di un dialogo desktop sono spazio buttato. `dvh` invece di `vh`
     perché su iOS `100vh` conta anche la barra dell'indirizzo, e il piede col
     bottone «Salva» finiva sotto al bordo. */
  .pannello-corpo { max-height: calc(100vh - 140px); max-height: calc(100dvh - 140px); }
  .pannello, .pannello.largo, .pannello.stretto { max-width: none; }

  /* La barra dei comandi di una scheda: bottoni a piena riga invece che tre
     mozziconi in fila, che col pollice si sbagliano. */
  .barra-sezione .azioni .btn { flex: 1 1 auto; justify-content: center; }

  /* Filtri: ricerca e tendine ognuna sulla sua riga, che a metà larghezza le
     voci si tagliano a metà parola. I bottoni restano della loro misura. */
  .filtri > .controllo, .filtri > .filtro-data { flex: 1 1 100%; }
  .filtri input:not([type="checkbox"]):not([type="radio"]), .filtri select { min-width: 0; }
  .filtro-data > .controllo { flex: 1; }

  /* ---- Editor documenti: le righe diventano schede -------------------
     Nove colonne su uno schermo da 360px non si stringono, si impilano. La
     tabella resta una tabella nel DOM — il codice cerca `closest('tr')` e le
     celle per campo, e non se ne accorge — cambia solo come si dispone: via
     l'intestazione, e ogni campo si porta l'etichetta da `data-etichetta`. */
  .righe-documento, .tabella-saldi { min-width: 0; table-layout: auto; display: block; }
  .righe-documento thead { display: none; }
  .righe-documento tbody { display: block; }
  .righe-documento tr {
    display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--s2);
    padding: var(--s3); margin-bottom: var(--s2);
    border: 1px solid var(--bordo); border-radius: var(--raggio-2);
    background: var(--superficie);
  }
  .righe-documento td { display: block; padding: 0; min-width: 0; }
  .righe-documento td::before {
    content: attr(data-etichetta); display: block; margin-bottom: 2px;
    font-size: 11px; font-weight: 600; color: var(--testo-tenue);
  }
  /* In una scheda i numeri stanno sotto la loro etichetta, a sinistra:
     allinearli a destra come in colonna li staccherebbe dal nome. */
  .righe-documento .num input, .righe-documento td.num { text-align: left; }

  .righe-documento td[data-cella="descrizione"] { grid-column: span 6; order: 1; }
  .righe-documento td[data-cella="quantita"] { grid-column: span 2; order: 2; }
  .righe-documento td[data-cella="unita_misura"] { grid-column: span 2; order: 3; }
  .righe-documento td[data-cella="prezzo"] { grid-column: span 2; order: 4; }
  .righe-documento td[data-cella="sconto"] { grid-column: span 2; order: 5; }
  .righe-documento td[data-cella="iva"] { grid-column: span 2; order: 6; }
  .righe-documento td[data-cella="sku"] { grid-column: span 2; order: 7; }
  .righe-documento td[data-cella="importo"] { grid-column: span 5; order: 8; font-size: 15px; }

  .tabella-saldi td[data-cella="saldo-data"] { grid-column: span 3; order: 1; }
  .tabella-saldi td[data-cella="saldo-importo"] { grid-column: span 3; order: 2; }
  .tabella-saldi td[data-cella="saldo-metodo"] { grid-column: span 6; order: 3; }
  .tabella-saldi td[data-cella="saldo-note"] { grid-column: span 6; order: 4; }

  /* Il cestino non ha bisogno di un'etichetta e sta in fondo alla scheda, dove
     il pollice arriva senza passare sopra ai campi. 36px di bersaglio. */
  .righe-documento td[data-cella="rimuovi"] {
    grid-column: span 1; order: 9; align-self: end; justify-self: end;
  }
  .righe-documento td[data-cella="rimuovi"]::before { content: none; }
  .righe-documento td[data-cella="rimuovi"] .btn-icona { min-width: 36px; min-height: 36px; }

  /* La ricerca prodotto in testa alle righe: riga intera, non un moncone. */
  .strumenti-righe { width: 100%; }
  #selettore-prodotto { flex: 1 1 100%; min-width: 0; }
}

/* ------------------------------------------------------- schermi da toccare

   I 16px sui campi stanno anche qui, e non solo sotto i 760px, perché quella
   soglia è sulla larghezza e ci sono tre casi in cui non scatta pur essendo su
   un telefono: lo schermo girato in orizzontale, un tablet, e Safari a cui si è
   chiesto «sito desktop» (lì la finestra si dichiara larga 980px). In tutti e
   tre toccare un campo da 13px ingrandisce la pagina, e nessuno la
   rimpicciolisce più: resta ingrandita e storta finché non si allarga con le
   dita. `pointer: coarse` guarda com'è fatto il dito, non quanto misura lo
   schermo, e un portatile col touch non ci finisce dentro — lì il puntatore
   principale resta il trackpad. */
@media (pointer: coarse) {
  .campo input, .campo select, .campo textarea, .controllo,
  .ricerca-globale input, .filtri input, .filtri select,
  .righe-documento input, .righe-documento select, .righe-documento textarea,
  input[type="file"] { font-size: 16px; }
}
