/* ============================================================================
   Innovation Learning Platform — design system

   Il rischio dichiarato in v6 è la «piattaforma morta»: tabelle grigie e form
   anonimi che sembrano un gestionale degli anni 2000. Questo file esiste per
   evitarlo.

   ## Tre piani, non uno
   La prima versione aveva pagina bianca e card bianche: una distesa di
   rettangoli senza gerarchia, corretta e spenta. Ora ci sono tre piani, e
   ognuno dice una cosa diversa:

     inchiostro  →  la cornice dell'applicazione (la barra in alto). Non è
                    contenuto: è il telaio, e sta sul lato scuro perché il
                    contenuto possa venire avanti.
     fondo       →  la pagina. Tinta e con due velature radiali, mai bianca.
     superficie  →  il contenuto. Bianco sul tinto, quindi si stacca da solo
                    senza bisogno di bordi pesanti.

   Da qui viene quasi tutta la differenza percepita: senza il piano di fondo
   ogni ombra è invisibile e ogni card sembra un bordo disegnato sul nulla.

   ## Colori parametrici, non cablati
   `q-identita-visiva` è aperta: la piattaforma Educational viene data in
   gestione alla Fondazione ITS, ma l'unico brand ricevuto è il logo
   Innovazione. Fallback adottato: sistema neutro con i colori come token, così
   applicare il tema della Fondazione è una modifica di configurazione.
   NON scrivere valori di colore fuori dal blocco :root.

   ## Gerarchia tipografica su due caratteri
   Un solo carattere per titoli e testo appiattisce tutto sullo stesso tono.
   Qui: Plus Jakarta Sans per i titoli (geometrico, sicuro di sé) e Inter per il
   testo e i dati (leggibile a 13px in tabella). È la stessa coppia degli altri
   prodotti FixIA, quindi la famiglia si riconosce.

   ## Accessibilità
   `vinc-accessibilita`: contrasto sufficiente, focus sempre visibile,
   navigazione da tastiera. E soprattutto: **uno stato non è mai deducibile dal
   solo colore** — ogni badge porta pallino *e* etichetta testuale.
   ========================================================================== */

/* I caratteri arrivano dalla CDN di Google, come negli altri prodotti FixIA.
   Nota per il deploy: è una chiamata a un terzo a ogni caricamento, e su una
   piattaforma pubblica con utenti minorenni la scelta va confermata in sede di
   `q-hosting-e-titolarita-dati`. Ospitarli in `static/fonts/` è una modifica di
   due righe (questo @import e un blocco @font-face) e non tocca nient'altro:
   lo stack di fallback qui sotto regge già da solo. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@600;700;800&display=swap');

:root {
  /* ---------------------------------------------------------- brand (tema) */
  /* Sovrascrivibili a runtime per applicare il tema di un'organizzazione.
     Dalla revisione 11 la famiglia viene dal LOGO — il triangolo di nodi
     azzurro/turchese/verde: il primario è l'azzurro del logo portato a un
     tono che regge il testo bianco (AA), la CTA è il suo verde, il telaio
     è un petrolio scuro nella stessa gamma. I toni pieni del logo
     (#009cd8, #3cc0d8, #54b460) restano per le tinte e i grafici. */
  --c-primary:        #0c78ae;   /* l'azzurro del logo, in tono da azione */
  --c-primary-hover:  #0a6a9a;
  --c-primary-deep:   #085b85;
  --c-primary-vivid:  #00a3dc;   /* il tono PIENO del logo: grafici, gradienti,
                                    accenti decorativi — mai sotto un testo */
  --c-primary-soft:   #e2f3fb;
  --c-primary-tint:   #f3fafd;
  --c-primary-border: #b6dff2;

  --c-accent:         #0d8446;   /* il verde del logo: solo per le CTA */
  --c-accent-hover:   #0a6f3a;
  --c-accent-vivid:   #4cb862;
  --c-accent-soft:    #e4f5ea;
  --c-accent-border:  #b9e3c8;

  /* L'inchiostro: il telaio dell'applicazione. Non è il primario scurito, è
     un petrolio proprio, nella gamma fredda del logo — un primario scuro
     tingerebbe tutta la barra di brand e competerebbe col contenuto. */
  --c-ink:        #0b2331;
  --c-ink-soft:   #143446;
  --c-ink-line:   #1d4358;

  /* Gradienti: uno per le CTA, uno per i blocchi in evidenza. Sono qui e non
     inline perché un gradiente cablato in pagina è il primo posto in cui il
     tema di un'organizzazione smette di funzionare. */
  --g-primary:   linear-gradient(135deg, #119cd6 0%, #0a6a9a 100%);
  --g-primary-h: linear-gradient(135deg, #0c78ae 0%, #085b85 100%);
  --g-accent:    linear-gradient(135deg, #23a25a 0%, #0a6f3a 100%);
  --g-ink:       linear-gradient(155deg, #143446 0%, #08161f 100%);
  /* il gradiente del LOGO: i suoi tre nodi in fila. Per le fasce d'ingresso
     e i blocchi che devono dire «questa e' la piattaforma». */
  --g-logo:      linear-gradient(120deg, #00a3dc 0%, #3cc0d8 48%, #54b460 100%);

  /* ------------------------------------------------------------ semantici */
  --c-success:      #0d8446;
  --c-success-soft: #e4f5ea;
  --c-warning:      #9a6206;
  --c-warning-soft: #fdf2df;
  --c-danger:       #bf2f26;
  --c-danger-soft:  #fceceb;
  --c-info:         #0c78ae;
  --c-info-soft:    #e2f3fb;

  /* Tinte per i chip-icona degli indicatori: servono a distinguere cinque
     numeri affiancati senza dipingerli di cinque colori pieni, che
     urlerebbero tutti insieme. */
  --t-blu:    #e2f3fb;  --t-blu-fg:    #0a6a9a;
  --t-verde:  #e4f5ea;  --t-verde-fg:  #0d8446;
  --t-ambra:  #fdf2df;  --t-ambra-fg:  #8a5806;
  --t-viola:  #ece9fb;  --t-viola-fg:  #5442ad;
  --t-ciano:  #ddf4f8;  --t-ciano-fg:  #0b7d96;

  /* ------------------------------------------------------------- neutrali */
  --c-bg:            #f1f5f9;   /* la pagina: tinta fredda, mai bianca */
  --c-bg-deep:       #e7eef4;
  --c-surface:       #ffffff;
  --c-surface-alt:   #f7fafc;
  --c-surface-sunk:  #eff4f8;   /* fasce di intestazione, teste di tabella */
  /* usato da una decina di regole ma mai DEFINITO: tutto cio' che ci poggiava
     (righe dei corsi, chip di filtro, pannelli della fase) era trasparente
     senza che nessuno se ne accorgesse. Alias del «sunk». */
  --c-surface-2:     var(--c-surface-sunk);
  --c-border:        #dfe7ee;
  --c-border-strong: #c3d1dc;

  --c-text:        #0e1c26;
  --c-text-muted:  #4c6273;
  --c-text-subtle: #7a909f;
  --c-text-invert: #ffffff;

  /* ---------------------------------------------------------- tipografia */
  --font-display: "Plus Jakarta Sans", "Inter", -apple-system, BlinkMacSystemFont,
                  "Segoe UI", Roboto, sans-serif;
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Gerarchia costruita con peso E dimensione, non solo col colore. */
  --fs-xs:   0.75rem;
  --fs-sm:   0.8125rem;
  --fs-base: 0.9375rem;
  --fs-md:   1.0625rem;
  --fs-lg:   1.25rem;
  --fs-xl:   1.5rem;
  --fs-2xl:  1.875rem;
  --fs-3xl:  2.375rem;
  --fs-4xl:  3rem;

  --fw-normal:   400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;
  --fw-black:    800;

  /* --------------------------------------------- spaziatura (generosa) */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;

  /* ------------------------------------------------------------- forma */
  /* Raggi piu' ampi e in scala regolare: il rettangolo appena stondato
     leggeva come «modulo di un gestionale», la curva vera come oggetto. */
  --r-sm: 9px;
  --r-md: 13px;
  --r-lg: 18px;
  --r-xl: 26px;
  --r-pill: 999px;

  /* Ombre a strati e con spread negativo: una sola ombra piatta legge come un
     bordo sfocato, due strati leggono come distanza dal piano. */
  /* Ombre a strati, con spread negativo e tinta PETROLIO (non grigia): una
     sola ombra piatta legge come un bordo sfocato, due strati leggono come
     distanza dal piano — e il grigio neutro sporca una pagina fredda. */
  --sh-xs: 0 1px 2px rgba(11, 35, 49, 0.05);
  --sh-sm: 0 1px 2px rgba(11, 35, 49, 0.04), 0 4px 12px -6px rgba(11, 35, 49, 0.10);
  --sh-md: 0 12px 28px -12px rgba(11, 35, 49, 0.18), 0 4px 10px -6px rgba(11, 35, 49, 0.10);
  --sh-lg: 0 32px 64px -24px rgba(11, 35, 49, 0.28), 0 12px 26px -16px rgba(11, 35, 49, 0.16);
  --sh-ink: 0 1px 0 rgba(11, 35, 49, 0.06), 0 8px 24px -16px rgba(11, 35, 49, 0.22);
  /* le ombre delle azioni prendono il COLORE dell'azione: un alone grigio
     sotto un bottone azzurro e' la firma di un tema non finito */
  --sh-cta: 0 8px 20px -10px rgba(12, 120, 174, 0.65);
  --sh-cta-a: 0 8px 20px -10px rgba(13, 132, 70, 0.60);

  /* Una curva sola in tutta l'app: l'accelerazione è parte dell'identità
     quanto il colore, e mescolarne tre fa sembrare l'insieme sciatto. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 130ms var(--ease);
  --t-base: 200ms var(--ease);
  --t-slow: 360ms var(--ease);

  --nav-h: 64px;
}

/* ========================================================== reset leggero */

*, *::before, *::after { box-sizing: border-box; }

/* `hidden` deve vincere sempre. Senza questo, un elemento con `display:flex` o
   `display:grid` resta visibile anche con l'attributo `hidden`: la regola del
   browser (`[hidden] { display: none }`) ha la stessa specificità di una classe
   e perde contro quella dichiarata dopo. È il tipo di bug che si manifesta come
   «il titolo non spariva» e fa perdere mezz'ora. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.55;
  /* Il micro-tracking negativo è quello che distingue un testo impaginato da un
     testo capitato lì: a 15px vale ~0.1px per lettera e si nota nell'insieme. */
  letter-spacing: -0.006em;
  color: var(--c-text);
  background-color: var(--c-bg);
  /* Le due velature danno profondità al piano di fondo senza disegnare niente.
     `fixed` perché devono appartenere alla finestra, non scorrere col
     contenuto: attaccate al documento sembrerebbero due macchie che scivolano. */
  background-image:
    radial-gradient(900px 420px at 100% -8%, rgba(0, 163, 220, 0.07), transparent 62%),
    radial-gradient(760px 380px at -6% 2%, rgba(84, 180, 96, 0.05), transparent 58%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  letter-spacing: -0.021em;
}
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }
p  { margin: 0 0 var(--sp-3); }

a { color: var(--c-primary); text-decoration: none; transition: color var(--t-fast); }
a:hover { color: var(--c-primary-hover); text-decoration: underline; }

code, pre { font-family: var(--font-mono); font-size: 0.9em; }
::selection { background: var(--c-primary); color: var(--c-text-invert); }

/* Focus SEMPRE visibile: requisito di accessibilità, non un dettaglio. Il
   filo pieno dice DOVE, l'alone morbido lo stacca dallo sfondo senza
   disegnare un secondo bordo. */
:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: var(--r-sm);
  box-shadow: 0 0 0 5px var(--c-primary-soft);
}

/* =============================================================== utilità */

.text-muted  { color: var(--c-text-muted); }
.text-subtle { color: var(--c-text-subtle); font-size: var(--fs-sm); }
.text-sm     { font-size: var(--fs-sm); }
.text-xs     { font-size: var(--fs-xs); }
.fw-medium   { font-weight: var(--fw-medium); }
.fw-semibold { font-weight: var(--fw-semibold); }

/* Numeri: cifre a larghezza fissa, altrimenti un contatore che si aggiorna
   balla in orizzontale a ogni cambio. */
.num, .stat-value { font-variant-numeric: tabular-nums; }

/* Titoli display: per la pagina di accesso e le intestazioni che devono avere
   una voce. `clamp` invece di media query — la dimensione segue la finestra in
   modo continuo, senza scatti a una soglia. */
.display-1 { font-family: var(--font-display); font-weight: var(--fw-black);
             font-size: clamp(1.875rem, 4.2vw, var(--fs-4xl)); line-height: 1.06;
             letter-spacing: -0.028em; margin: 0 0 var(--sp-3); }
.display-2 { font-family: var(--font-display); font-weight: var(--fw-black);
             font-size: clamp(1.5rem, 3vw, var(--fs-3xl)); line-height: 1.1;
             letter-spacing: -0.026em; margin: 0 0 var(--sp-3); }

/* Micro-etichetta in maiuscoletto spaziato: dice «di cosa stiamo parlando»
   sopra un titolo, senza rubargli peso. */
.eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--c-text-subtle);
}

.stack     { display: flex; flex-direction: column; gap: var(--sp-3); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.cluster   { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }

/* Non visibile ma leggibile dagli screen reader */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Riga sottile di separazione, quando serve dividere senza pesare */
.hr { height: 1px; background: var(--c-border); border: 0; margin: var(--sp-4) 0; }

/* ================================================================ layout */

.app-shell { min-height: 100vh; display: flex; flex-direction: column; }

.container {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 var(--sp-5);
}

.page { padding: var(--sp-6) 0 var(--sp-8); flex: 1; }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--sp-4); margin-bottom: var(--sp-5); flex-wrap: wrap;
}
.page-head h1 { margin-bottom: var(--sp-1); font-size: clamp(var(--fs-xl), 2.6vw, var(--fs-2xl)); }
.page-head .subtitle { color: var(--c-text-muted); margin: 0; max-width: 68ch; }

/* Griglia dei riquadri: le dashboard e i workspace la usano per i loro blocchi.
   La scala è COMPLETA di proposito: con solo alcune misure definite, una classe
   plausibile come `col-5` non fa niente e il blocco si accartoccia su una
   colonna su dodici — è già accaduto in validazione.html, e non dava errore. */
.grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(12, 1fr); }
.col-2  { grid-column: span 2; }
.col-3  { grid-column: span 3; }
.col-4  { grid-column: span 4; }
.col-5  { grid-column: span 5; }
.col-6  { grid-column: span 6; }
.col-7  { grid-column: span 7; }
.col-8  { grid-column: span 8; }
.col-9  { grid-column: span 9; }
.col-10 { grid-column: span 10; }
.col-12 { grid-column: span 12; }

/* ============================================================== navbar

   Il telaio è CHIARO: vetro smerigliato sopra la pagina, con una riga sola a
   separarlo. La barra scura era una fascia pesante che schiacciava il
   contenuto e obbligava il logo dentro una tessera bianca — «incastonato in
   un quadrato bianco», e aveva ragione: un marchio non si mette in una
   scatola, gli si dà il fondo giusto. Il buio resta dove serve davvero (la
   fascia d'ingresso), non addosso a ogni pagina di lavoro.                    */

.navbar {
  height: var(--nav-h);
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border-bottom: 1px solid var(--c-border);
  box-shadow: var(--sh-ink);
  display: flex; align-items: center;
  position: sticky; top: 0; z-index: 40;
}
.navbar .container { display: flex; align-items: center; gap: var(--sp-5); }

.brand {
  display: flex; align-items: center; gap: var(--sp-3);
  font-family: var(--font-display);
  font-weight: var(--fw-black); font-size: var(--fs-md);
  color: var(--c-text); letter-spacing: -0.015em;
}
.brand:hover { text-decoration: none; color: var(--c-text); }
/* Il marchio è il logo e basta: niente tessera, niente fondo, niente bordo.
   Su barra chiara il PNG ritagliato appoggia sul bianco della pagina. */
.brand-mark {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
}
.brand-mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Dove il fondo è scuro (la fascia d'ingresso) il marchio resta lo stesso: i
   tre nodi del logo sono abbastanza vividi da reggere il petrolio. */

.nav-links { display: flex; align-items: center; gap: var(--sp-1); margin-left: auto; }
.nav-link {
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-pill);
  color: var(--c-text-muted);
  font-weight: var(--fw-medium); font-size: var(--fs-sm);
  transition: background var(--t-fast), color var(--t-fast);
  white-space: nowrap;
}
.nav-link:hover {
  background: var(--c-surface-sunk);
  color: var(--c-text); text-decoration: none;
}
/* La voce attiva riflette la posizione REALE nella gerarchia
   programma → progetto → journey → fase (ui-navigazione-persistente).
   Su fondo chiaro basta la pastiglia tinta: piena di inchiostro sarebbe una
   macchia scura in mezzo a una barra leggera. */
.nav-link.is-active {
  background: var(--c-primary-soft); color: var(--c-primary-deep);
  font-weight: var(--fw-semibold);
}
.nav-link.is-active:hover { background: var(--c-primary-soft); color: var(--c-primary-deep); }

/* Piu' specifico di `.btn { display: inline-flex }`, che viene definito dopo:
   a pari specificita' vincerebbe quello, e l'hamburger comparirebbe anche su
   desktop. */
.navbar .nav-toggle { display: none; }

/* ================================================================== piede

   Le informazioni legali e la bandella dei finanziatori, in fondo a ogni
   pagina. Il piede non compete col contenuto: fondo appena piu' freddo della
   pagina, testo piccolo, una riga sottile a separarlo. La bandella dei loghi
   istituzionali sta invece su una fascia BIANCA — quei marchi non si posano
   su un fondo tinto e non si ricolorano. */

.piede {
  margin-top: var(--sp-8);
  border-top: 1px solid var(--c-border);
  background: var(--c-surface-alt);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}
/* il filo dei tre colori del logo chiude la pagina come apre i blocchi scuri */
.piede { position: relative; }
.piede::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: var(--g-logo); opacity: .85;
}
.piede > .container { padding-top: var(--sp-5); padding-bottom: var(--sp-5); }

.piede__riga {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-5); flex-wrap: wrap;
  margin-top: var(--sp-4); padding-top: var(--sp-4);
  border-top: 1px solid var(--c-border);
}
.piede__soggetto { display: flex; align-items: center; gap: var(--sp-4); min-width: 0; }
/* Il marchio dell'ente e' un lockup verticale (marchio sopra, diciture
   sotto): gli serve altezza, non un quadratino da 34px. */
.piede__marchio { width: auto; height: 74px; object-fit: contain; flex: none; }
.piede__nome {
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: var(--fs-base); color: var(--c-text); letter-spacing: -0.01em;
}
/* I dati legali: voci separate da un punto medio DISEGNATO, non scritto —
   cosi' non finisce negli appunti quando si copia la P.IVA. */
.piede__dati { display: flex; flex-wrap: wrap; gap: 0 var(--sp-3); margin-top: 2px; }
.piede__dato { display: inline-flex; align-items: center; gap: .3rem; }
.piede__dato + .piede__dato::before {
  content: "·"; margin-right: .3rem; color: var(--c-border-strong);
}
.piede__et { color: var(--c-text-subtle); }
.piede__coda {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: var(--sp-1); margin-left: auto; text-align: right;
}
.piede__legali { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: flex-end; }
.piede__legali a { color: var(--c-text-muted); }
.piede__legali a:hover { color: var(--c-primary); }
.piede__copy { font-size: var(--fs-xs); color: var(--c-text-subtle); }

/* --------------------------------------------- la bandella dei finanziatori */
.bandella {
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
  background: var(--c-surface);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
}
.bandella__et {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--c-text-subtle); flex: none;
}
/* I loghi restano UNA immagine: sono un lockup istituzionale, e spezzarlo in
   sei file per allinearli meglio significherebbe poterli comporre a modo
   nostro — cosa che con questi marchi non si fa. Scala, non si taglia. */
.bandella__loghi {
  flex: 1 1 320px; min-width: 0; max-width: 780px;
  height: auto; object-fit: contain; display: block;
}
/* La versione della pagina d'accesso: etichetta sopra, loghi sotto, dentro
   la colonna del modulo. In colonna il `flex-basis` dei loghi cresceva in
   ALTEZZA e apriva un riquadro vuoto con i marchi minuscoli in mezzo: qui
   l'immagine non flette, prende la larghezza e si scala da se'. */
.bandella--compatta {
  padding: var(--sp-4); gap: var(--sp-3);
  flex-direction: column; align-items: center;
}
.bandella--compatta .bandella__loghi {
  flex: none; width: 100%; max-width: 100%; height: auto;
}

@media (max-width: 720px) {
  .bandella { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
  .bandella__loghi { width: 100%; max-width: 100%; }
  .piede__riga { flex-direction: column; }
  .piede__coda { align-items: flex-start; text-align: left; margin-left: 0; }
  .piede__legali { justify-content: flex-start; }
}

/* ============================================================== la vetrina

   La bacheca e' l'unica pagina con un pubblico ESTERNO, e non deve leggersi
   come l'elenco dei progetti: qui non si amministra, si guarda. Da qui le
   sue forme proprie — la scheda in evidenza, l'indice per settore, le
   schede col pitch e con le facce di chi c'era, e la corsia di curatela
   tenuta fuori dalla vetrina. */

/* la coda di chi cura: righe strette, non schede — qui si lavora */
.curatela {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-accent);
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-5); box-shadow: var(--sh-xs);
}
.curatela__testa {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3); margin-bottom: var(--sp-2);
}
.curatela__riga {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: .45rem 0; flex-wrap: wrap;
}
.curatela__riga + .curatela__riga { border-top: 1px solid var(--c-border); }
.curatela__titolo { font-size: var(--fs-sm); font-weight: var(--fw-semibold); flex: 1 1 220px; }
.curatela__riga .btn { margin-left: auto; }

/* la scheda in evidenza: due colonne, il pitch in grande */
.evidenza {
  display: grid; grid-template-columns: 1fr 260px; gap: var(--sp-5);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); box-shadow: var(--sh-sm);
  padding: var(--sp-5); margin-bottom: var(--sp-5);
  position: relative; overflow: hidden;
}
.evidenza::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: var(--g-logo);
}
.evidenza__eyebrow {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--c-primary); margin: 0 0 var(--sp-2);
}
.evidenza__titolo {
  font-family: var(--font-display); font-size: var(--fs-xl);
  line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 var(--sp-3);
}
.evidenza__pitch {
  font-size: var(--fs-md); line-height: 1.5; color: var(--c-text-muted);
  margin: 0 0 var(--sp-3);
}
.evidenza__lato {
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding-left: var(--sp-5); border-left: 1px solid var(--c-border);
}
.evidenza__lato .btn { align-self: flex-start; }

/* l'indice: come si scorre una vetrina di cento schede */
.vindice {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
/* i chip dei settori sono FILTRI (bottoni), non ancore: il verso attivo lo
   danno le regole di `.chip--scelta`, qui basta la mano del cursore */
.vindice .chip--scelta { cursor: pointer; }

.vsezione { margin-bottom: var(--sp-6); scroll-margin-top: calc(var(--nav-h) + var(--sp-4)); }
.vsezione__testa {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding-bottom: var(--sp-2); margin-bottom: var(--sp-3);
  border-bottom: 1px solid var(--c-border);
}
.vsezione__nome {
  font-family: var(--font-display); font-size: var(--fs-md);
  letter-spacing: -0.01em; margin: 0;
}
/* schede piu' strette delle card di progetto: qui se ne guardano tante */
.vgriglia {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
}
.vscheda {
  display: flex; flex-direction: column; gap: .45rem;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding: var(--sp-4); box-shadow: var(--sh-xs);
  transition: box-shadow var(--t-base), border-color var(--t-base), transform var(--t-base);
}
.vscheda:hover {
  box-shadow: var(--sh-md); border-color: var(--c-border-strong);
  transform: translateY(-2px);
}
.vscheda--lavorazione { border-style: dashed; box-shadow: none; }
.vscheda__testa { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.vscheda__tipo {
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  letter-spacing: .06em; text-transform: uppercase; color: var(--t-blu-fg);
}
.vscheda__tipo--verde { color: var(--t-verde-fg); }
.vscheda__tipo--ambra { color: var(--t-ambra-fg); }
.vscheda__tipo--viola { color: var(--t-viola-fg); }
.vscheda__tipo--ciano { color: var(--t-ciano-fg); }
.vscheda__titolo {
  font-family: var(--font-display); font-size: var(--fs-md);
  line-height: 1.2; letter-spacing: -0.015em; margin: 0;
}
.vscheda__dove { font-size: var(--fs-xs); color: var(--c-text-subtle); margin: 0; }
/* il pitch si legge: quattro righe, poi i puntini — non una riga e mezza */
.vscheda__pitch {
  font-size: var(--fs-sm); line-height: 1.5; color: var(--c-text-muted);
  margin: .2rem 0 0; display: -webkit-box; -webkit-line-clamp: 4;
  -webkit-box-orient: vertical; overflow: hidden;
}
.vscheda__cat { display: flex; flex-wrap: wrap; gap: .3rem; }
.vscheda__piede {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); margin-top: auto; padding-top: var(--sp-3);
  border-top: 1px solid var(--c-border);
}
/* le facce: chi c'era, non «4 persone» */
.facce { display: flex; align-items: center; gap: .3rem; min-width: 0; }
.facce .avatar { margin-right: -8px; box-shadow: 0 0 0 2px var(--c-surface); }
.facce .avatar:last-of-type { margin-right: 0; }
.facce__altri {
  font-size: var(--fs-xs); color: var(--c-text-subtle);
  margin-left: 10px; flex: none;
}
.facce__nomi {
  font-size: var(--fs-xs); color: var(--c-text-subtle); margin-left: .35rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* le voci dell'anteprima newsletter */
.nl-voce {
  border-left: 2px solid var(--c-primary-border);
  padding: .1rem 0 .1rem var(--sp-3);
}

@media (max-width: 900px) {
  .evidenza { grid-template-columns: 1fr; }
  .evidenza__lato { padding-left: 0; border-left: 0;
                    padding-top: var(--sp-4); border-top: 1px solid var(--c-border); }
  .facce__nomi { display: none; }
}

/* il piede di un elenco a finestre: quante su quante, e come chiederne altre */
.altre {
  display: flex; align-items: center; justify-content: center;
  gap: var(--sp-3); padding: var(--sp-4) 0 var(--sp-2);
}
.altre__conta { font-size: var(--fs-sm); color: var(--c-text-subtle); }

/* L'intestazione della colonna «Chi lo vede» nel Portfolio: sta sopra le
   tendine, e ne prende la larghezza per restarci allineata. */
.portfolio__chi { width: 190px; text-align: left; flex: none; }
@media (max-width: 720px) { .portfolio__chi { display: none; } }

/* ================================================================= card */

.card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-sm);
  padding: var(--sp-5);
  transition: box-shadow var(--t-base), border-color var(--t-base),
              transform var(--t-base);
}
.card--hover:hover {
  box-shadow: var(--sh-md);
  border-color: var(--c-border-strong);
  transform: translateY(-2px);
}
a.card { color: inherit; display: block; }
a.card:hover { text-decoration: none; color: inherit; }
.card--flush { padding: 0; overflow: hidden; }

.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); margin-bottom: var(--sp-4);
}
.card-title {
  font-family: var(--font-sans);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--c-text-subtle); margin: 0;
}

/* Intestazione a fascia, per le card `--flush` che contengono una tabella:
   dà un attacco al blocco senza aggiungere un bordo in più. */
.card--flush .card-head {
  margin: 0; padding: var(--sp-4) var(--sp-5);
  background: var(--c-surface-sunk);
  border-bottom: 1px solid var(--c-border);
}

/* La card in evidenza: usata per la Next Best Action, che nella Dashboard
   Studente deve stare in posizione dominante (ui-dashboard-studente).
   Il filo verticale d'accento e la velatura la fanno leggere come «questa
   prima delle altre» senza gridare. */
.card--accent {
  border-color: var(--c-accent-border);
  background:
    linear-gradient(180deg, var(--c-accent-soft) 0%, rgba(253, 241, 232, 0) 46%),
    var(--c-surface);
  box-shadow: var(--sh-md);
  position: relative; overflow: hidden;
}
.card--accent::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--g-accent);
}

/* Blocco in inchiostro: per un'intestazione che deve dominare la pagina
   (accesso, hero di una scheda). Il testo ci va sopra invertito. */
.card--hero {
  background: var(--c-ink); background-image: var(--g-ink);
  border: none; color: var(--c-text-invert);
  box-shadow: var(--sh-lg);
  position: relative; overflow: hidden;
}
.card--hero h1, .card--hero h2, .card--hero h3,
.card--hero .display-1, .card--hero .display-2 { color: var(--c-text-invert); }
.card--hero .text-muted,
.card--hero .subtitle { color: rgba(255, 255, 255, 0.72); }
.card--hero .eyebrow  { color: rgba(255, 255, 255, 0.58); }
.card--hero .card-title { color: rgba(255, 255, 255, 0.62); }
/* L'alone d'accento in un angolo: rompe il rettangolo pieno, che altrimenti
   legge come un blocco di colore invece che come una superficie. */
.card--hero::after {
  content: ""; position: absolute; top: -140px; right: -100px;
  width: 340px; height: 340px; pointer-events: none;
  background: radial-gradient(circle at center, rgba(0, 163, 220, 0.40), transparent 62%);
}
/* Un filo dei tre colori del logo sul bordo alto: firma il blocco senza
   metterci un marchio dentro. */
.card--hero::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: var(--g-logo); opacity: .9; z-index: 2;
}
.card--hero > * { position: relative; z-index: 1; }

/* --------------------------------------------------- indicatori (KPI) */
/* Un numero grande, la sua etichetta in maiuscoletto e un chip-icona tinto.
   Cinque indicatori affiancati hanno bisogno di distinguersi fra loro senza
   cinque colori pieni: le tinte `--t-*` sono chiare di proposito. */
.stat-card { display: flex; align-items: flex-start; gap: var(--sp-4); }
.stat-body { min-width: 0; flex: 1; }
.stat-label {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--c-text-subtle);
}
.stat-value {
  font-family: var(--font-display);
  font-size: var(--fs-2xl); font-weight: var(--fw-black);
  letter-spacing: -0.03em; line-height: 1.1; margin-top: var(--sp-1);
  color: var(--c-text);
}
.stat-unit { font-size: var(--fs-md); font-weight: var(--fw-bold); color: var(--c-text-subtle); }
.stat-note { font-size: var(--fs-xs); color: var(--c-text-muted); margin-top: var(--sp-1); }
.stat-icon {
  width: 42px; height: 42px; border-radius: var(--r-md); flex: none;
  display: grid; place-items: center;
  /* corpo grande solo come RIPIEGO per un glifo non mappato: il segno vero
     e' l'SVG di `UI.innestaIcone`, centrato per costruzione */
  font-size: 1.625rem; line-height: 1; font-weight: var(--fw-bold);
  background: var(--t-blu); color: var(--t-blu-fg);
}
/* l'icona disegnata riempie la tessera senza toccarne i bordi, e resta in
   proporzione su tutte le taglie (42, 34, 32) senza regole per caso */
.stat-icon svg, .empty-icon svg {
  width: 62%; height: 62%; display: block;
}
.passo__icona svg { width: 58%; height: 58%; display: block; }
.stat-icon--verde { background: var(--t-verde); color: var(--t-verde-fg); }
.stat-icon--ambra { background: var(--t-ambra); color: var(--t-ambra-fg); }
.stat-icon--viola { background: var(--t-viola); color: var(--t-viola-fg); }
.stat-icon--ciano { background: var(--t-ciano); color: var(--t-ciano-fg); }

/* =============================================================== bottoni */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  min-height: 40px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font: inherit;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.004em;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover { text-decoration: none; }
/* Il micro-sollevamento in hover e l'affondo al click: è il feedback che fa
   sembrare un bottone un oggetto invece di un rettangolo colorato. */
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled, .btn.is-disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }

.btn--primary {
  background: var(--c-primary); background-image: var(--g-primary);
  color: var(--c-text-invert); box-shadow: var(--sh-cta);
}
.btn--primary:hover:not(:disabled) {
  background-image: var(--g-primary-h); color: var(--c-text-invert);
  box-shadow: 0 10px 24px -8px rgba(12, 120, 174, 0.72); transform: translateY(-1px);
}

/* L'accento è riservato alle CTA: se è su tutto, non è più un accento. */
.btn--accent {
  background: var(--c-accent); background-image: var(--g-accent);
  color: var(--c-text-invert); box-shadow: var(--sh-cta-a);
}
.btn--accent:hover:not(:disabled) {
  color: var(--c-text-invert); box-shadow: 0 10px 24px -8px rgba(13, 132, 70, 0.68);
  transform: translateY(-1px);
}

.btn--outline {
  background: var(--c-surface); border-color: var(--c-border-strong);
  color: var(--c-text); box-shadow: var(--sh-xs);
}
.btn--outline:hover:not(:disabled) {
  background: var(--c-surface-alt); border-color: var(--c-text-subtle);
  box-shadow: var(--sh-sm);
}

.btn--ghost { background: transparent; color: var(--c-text-muted); }
.btn--ghost:hover:not(:disabled) { background: var(--c-surface-sunk); color: var(--c-text); }

.btn--danger { background: var(--c-danger); color: var(--c-text-invert);
               box-shadow: 0 8px 20px -10px rgba(191, 47, 38, 0.55); }
.btn--danger:hover:not(:disabled) { color: var(--c-text-invert); transform: translateY(-1px); }

.btn--sm { min-height: 32px; padding: var(--sp-1) var(--sp-3); font-size: var(--fs-sm);
           border-radius: var(--r-sm); }
.btn--lg { min-height: 48px; padding: var(--sp-3) var(--sp-5); font-size: var(--fs-md); }
.btn--block { width: 100%; }

/* Su fondo scuro le ombre colorate non si vedono e il bordo sparisce: qui
   servono varianti proprie, altrimenti un bottone dentro `.card--hero`
   sembra un buco. (La barra in alto non ne ha piu' bisogno: da questa
   revisione e' chiara, e il ghost normale ci sta bene.) */

.card--hero .btn--outline,
.card--hero .btn--ghost {
  background: rgba(255, 255, 255, 0.10); color: var(--c-text-invert);
  border-color: rgba(255, 255, 255, 0.28); box-shadow: none;
}
.card--hero .btn--outline:hover,
.card--hero .btn--ghost:hover {
  background: rgba(255, 255, 255, 0.20); border-color: rgba(255, 255, 255, 0.6);
  color: var(--c-text-invert);
}

/* =========================================================== badge stato

   `style-stato-sempre-visibile` + `vinc-accessibilita`: gli stati usano la
   stessa grammatica cromatica in tutta la piattaforma, e portano SEMPRE
   l'etichetta testuale — il colore da solo non basta.                        */

.badge {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 3px var(--sp-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
  /* L'alone attorno al pallino lo stacca dal fondo tinto della pillola: senza,
     a 6px si impasta col colore di sfondo e si perde. */
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.65);
}

/* bozza · in corso · da revisionare · approvato · completato · archiviato */
.badge--bozza      { background: var(--c-surface-sunk); color: var(--c-text-muted); border-color: var(--c-border); }
.badge--corso      { background: var(--c-info-soft);    color: var(--c-info);    border-color: #cfe3ee; }
.badge--revisione  { background: var(--c-warning-soft); color: var(--c-warning); border-color: #f3e0bd; }
.badge--approvato  { background: var(--c-success-soft); color: var(--c-success); border-color: #c9e6d7; }
.badge--completato { background: var(--c-success-soft); color: var(--c-success); border-color: #c9e6d7; }
.badge--archiviato { background: var(--c-surface-sunk); color: var(--c-text-subtle); border-color: var(--c-border); }
.badge--attenzione { background: var(--c-danger-soft);  color: var(--c-danger);  border-color: #f2ccc9; }
/* fase non iniziata: neutro, e senza pallino pieno */
.badge--inattivo   { background: transparent; color: var(--c-text-subtle); border-color: var(--c-border-strong); }
.badge--inattivo::before { background: transparent; border: 1px solid currentColor; box-shadow: none; }

/* Etichetta neutra non di stato (conteggi, tag, tipologie): non usa la
   grammatica degli stati, così non si confonde con essa. */
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 3px var(--sp-2); border-radius: var(--r-sm);
  background: var(--c-primary-tint); color: var(--c-primary);
  border: 1px solid var(--c-primary-border);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
}

/* Varianti del chip. `--muted` e `--verde` dicono un sì/no con il colore E con
   la parola dentro: `vinc-accessibilita` non ammette informazione affidata al
   solo colore, e «gestito in piattaforma» è esattamente un sì/no che conta. */
.chip--sm { padding: 1px var(--sp-1); font-size: 11px; }
.chip--muted {
  background: var(--c-surface-2); color: var(--c-text-muted);
  border-color: var(--c-border);
}
.chip--verde {
  background: var(--t-verde); color: var(--t-verde-fg);
  border-color: #c9e6d7;
}

/* Una riga che c'è ma non è in uso: il modulo importato e non acceso. Si legge,
   non urla, e non sparisce — sparire farebbe credere che non sia stato importato. */

/* Le righe di `Modale.elenco`: un elenco che si legge, non una tabella. */
.modale__righe {
  list-style: none; margin: 0 0 var(--sp-4); padding: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.modale__righe li {
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm);
  background: var(--c-surface-2); font-size: var(--fs-sm);
}

/* La NOTA in pagina: quando una pagina non puo' fare il suo lavoro e va detto
   perche' e cosa fare. Non un toast (sparisce) e non un empty state (occupa tutta
   l'area): sta dentro il campo che non si puo' compilare. */
.nota {
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm);
  border: 1px solid var(--c-border); background: var(--c-surface-2);
  font-size: var(--fs-sm); line-height: 1.55; color: var(--c-text);
}
.nota b { font-weight: var(--fw-semibold); }
.nota--attenzione {
  background: var(--t-ambra); border-color: #f0d9b6; color: var(--t-ambra-fg);
}
.nota--attenzione a { color: inherit; text-decoration: underline; }

/* Una riga con la spunta: piu' compatta di `.scelta`, per elenchi di cose da
   selezionare dove il testo conta piu' del riquadro. */
.riga-scelta {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm);
  background: var(--c-surface-2); cursor: pointer;
  font-size: var(--fs-sm); line-height: 1.4;
  border: 1px solid transparent; transition: border-color var(--t-fast);
}
.riga-scelta:hover { border-color: var(--c-border-strong); }
.riga-scelta:has(input:checked) {
  border-color: var(--c-primary); background: var(--c-primary-tint);
}
.riga-scelta input { margin-top: 2px; flex: none; }

/* Il chip come pulsante di filtro dentro la modale. `is-attivo` non e' solo
   colore: il bordo cambia peso, perche' `vinc-accessibilita`. */
.chip--scelta {
  cursor: pointer; background: var(--c-surface-2); color: var(--c-text-muted);
  border-color: var(--c-border);
}
.chip--scelta:hover { border-color: var(--c-border-strong); color: var(--c-text); }
.chip--scelta.is-attivo {
  background: var(--c-primary); border-color: var(--c-primary); color: #fff;
}

/* La riga di corso in Gestione e' un comando: sceglierla filtra le classi a
   fianco. Il bordo, non solo il colore, dice quale e' scelta
   (`vinc-accessibilita`); `is-vuoto` smorza i corsi senza classi nell'anno
   scelto, che restano comunque selezionabili e modificabili. */
.corso-riga {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); padding: .5rem .65rem; border-radius: var(--r-sm);
  background: var(--c-surface-2); border: 1px solid transparent;
  cursor: pointer; transition: border-color var(--t-fast);
}
.corso-riga:hover { border-color: var(--c-border-strong); }
.corso-riga.is-attivo {
  border-color: var(--c-primary); background: var(--c-primary-tint);
}
.corso-riga.is-vuoto > div:first-child { opacity: .6; }
.modale__filtro {
  display: flex; flex-direction: column; gap: var(--sp-1);
  margin-bottom: var(--sp-3);
}
/* La classe accanto al nome: allineata a destra, cosi' la colonna si legge
   scorrendo l'elenco invece di cercarla riga per riga. Ma il NOME comanda:
   la nota cede e si tronca quando la tessera e' stretta — prima era lei,
   `flex: none`, a schiacciare il nome fino a sparire. */
.persona__nota {
  margin-left: auto; padding-left: var(--sp-3);
  flex: 0 1 auto; min-width: 0; max-width: 46%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-xs); color: var(--c-text-muted); text-align: right;
}

/* LE BRICIOLE — Corso > Classe > Modulo > anno scolastico.
   `dec-gerarchia-corso-classe-modulo`: da questa revisione un lavoro non e' piu'
   un oggetto isolato, sta dentro quattro contenitori, e chi apre la pagina deve
   vederli senza cliccare. Non sono link: sono contesto. Fossero link direbbero
   «qui si naviga», e non e' quello il loro compito.
   Il separatore e' generato dal CSS e non scritto nel testo, cosi' non finisce
   negli appunti quando si copia la riga. */
.briciole {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1);
  font-size: var(--fs-xs); line-height: 1.4;
  color: var(--c-text-muted);
}
.briciole > span + span::before {
  content: "›"; margin-right: var(--sp-1); opacity: .6;
}
.briciole > span:last-child { font-weight: var(--fw-semibold); }
/* La variante che NON va a capo: dentro una scheda in una fila di schede, una
   riga che diventa due sposta tutto quello che sta sotto e rompe l'allineamento
   fra le schede (`style-allineamento-schede`). Meglio troncare che disallineare. */
.briciole--riga {
  flex-wrap: nowrap; overflow: hidden;
  margin-bottom: var(--sp-2); min-height: 1.4em;
}
.briciole--riga > span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* L'ultimo segmento cede prima: il primo (la classe) è quello che serve
   riconoscere scorrendo un elenco. */
.briciole--riga > span:last-child { flex: 0 1 auto; min-width: 0; }
.briciole--riga > span:first-child { flex: 0 0 auto; max-width: 60%; }

/* Dentro un'intestazione in inchiostro il testo va schiarito, non lasciato grigio */
.card--hero .briciole { color: rgba(255, 255, 255, .68); }
.card--hero .briciole > span:last-child { color: rgba(255, 255, 255, .92); }

/* L'ALBERO corso → classe nel pannello dei filtri.
   Il corso e' un pulsante che accende tutte le sue classi, non un valore: nei
   dati un progetto d'impresa appartiene a una classe, non a un corso. */
.f-albero { display: flex; flex-direction: column; gap: var(--sp-2); }
.f-albero__ramo { display: flex; flex-direction: column; gap: 2px; }
.f-albero__corso,
.f-albero__classe {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); width: 100%; text-align: left;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; cursor: pointer;
  font-family: inherit; color: var(--c-text);
  transition: background var(--t-fast), color var(--t-fast),
              border-color var(--t-fast);
}
.f-albero__corso {
  padding: var(--sp-2) var(--sp-2);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--c-text-muted);
}
.f-albero__corso:hover { background: var(--c-surface-2); color: var(--c-text); }
.f-albero__corso.is-attivo { color: var(--c-primary); }
.f-albero__figli {
  display: flex; flex-direction: column; gap: 2px;
  padding-left: var(--sp-2); margin-left: var(--sp-1);
  border-left: 1px solid var(--c-border);
}
.f-albero__classe { padding: var(--sp-1) var(--sp-2); font-size: var(--fs-sm); }
.f-albero__classe:hover { background: var(--c-surface-2); }
/* Selezionata: fondo pieno E peso del testo. Il colore da solo non basta. */
.f-albero__classe.is-attivo {
  background: var(--c-primary); border-color: var(--c-primary);
  color: #fff; font-weight: var(--fw-semibold);
}
.f-albero__conta {
  flex: none; font-size: 11px; font-variant-numeric: tabular-nums;
  color: inherit; opacity: .7;
}

/* Chi resta fuori dalla classe scelta: si vede, non si puo' spuntare, e il
   perche' e' nel `title`. Nasconderlo farebbe credere che quello studente non
   esista, e cercarlo per dieci minuti e' peggio che vederlo spento. */
.persona--fuori { opacity: .45; cursor: not-allowed; }
.persona--fuori input { cursor: not-allowed; }

/* ================================================================= form */

.field { display: flex; flex-direction: column; gap: var(--sp-1); margin-bottom: var(--sp-4); }
.label { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--c-text); }
.hint  { font-size: var(--fs-xs); color: var(--c-text-muted); }

.input, .select, .textarea {
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  min-height: 42px;
  font: inherit;
  color: var(--c-text);
  /* il campo e' un incavo, non un rettangolo con un filo intorno: fondo
     appena piu' freddo della carta e un'ombra interna di un pixel */
  background: var(--c-surface-alt);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  box-shadow: inset 0 1px 2px rgba(11, 35, 49, 0.04);
  transition: border-color var(--t-fast), box-shadow var(--t-fast),
              background var(--t-fast);
}
.input::placeholder, .textarea::placeholder { color: var(--c-text-subtle); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--c-border-strong); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  background: var(--c-surface);
  border-color: var(--c-primary);
  box-shadow: 0 0 0 4px var(--c-primary-soft);
}
.textarea { min-height: 100px; resize: vertical; line-height: 1.6; }
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--c-danger); }
.input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--c-danger-soft); }
.field-error { font-size: var(--fs-xs); color: var(--c-danger); font-weight: var(--fw-semibold); }

/* =============================================================== tabelle

   Le viste dati vanno pensate, non subite: una tabella pura è la scelta giusta
   solo quando lo è. Quando lo è, almeno che sia leggibile.                    */

.table-wrap {
  overflow-x: auto;
  /* Rete di sicurezza: dentro un elemento di griglia la larghezza minima del
     contenuto puo' allargare la colonna, e una tabella larga fa scorrere LA
     PAGINA. Con `min-width: 0` scorre la tabella, che e' quello che ha il
     bordo e lo dice. */
  min-width: 0;
  border-radius: var(--r-lg);
  border: 1px solid var(--c-border);
  background: var(--c-surface);
  box-shadow: var(--sh-sm);
}
.table { width: 100%; border-collapse: collapse; background: var(--c-surface); }
.table th, .table td { padding: var(--sp-3) var(--sp-4); text-align: left; }
.table thead th {
  background: var(--c-surface-sunk);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--c-text-subtle);
  border-bottom: 1px solid var(--c-border);
  position: sticky; top: 0; z-index: 1;
  white-space: nowrap;
}
.table tbody tr { border-top: 1px solid var(--c-border); transition: background var(--t-fast); }
.table tbody tr:hover { background: var(--c-primary-tint); }
.table tbody tr.is-selected { background: var(--c-primary-soft); }
.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------- tabella densa
   Per gli elenchi di anagrafica dentro una card che non occupa tutta la pagina:
   sei o sette colonne in due terzi di larghezza non ci stanno, e lo scorrimento
   orizzontale in una tabella e' il modo di non far leggere le ultime colonne.

   `table-layout: fixed` con larghezze dichiarate: senza, una cella lunga si
   prende lo spazio delle altre e la tabella esce dal contenitore. Con le
   larghezze fisse e' il TESTO che va a capo, e va a capo dove decidiamo noi. */
.table--densa { table-layout: fixed; font-size: var(--fs-sm); }
.table--densa th, .table--densa td { padding: var(--sp-2) var(--sp-3); }

/* Nei DATI la parola si spezza dove capita. E' il rovescio di `table-layout:
   fixed`: una parola che non puo' andare a capo non allarga la colonna, esce
   dentro quella dopo e ci si sovrappone. `anywhere` spezza solo quando serve —
   `break-all` spezzerebbe anche le parole normali. */
.table--densa td { overflow-wrap: anywhere; vertical-align: top; }

/* Nelle INTESTAZIONI no: spezzare «STUDENTI» in «STUDE / NTI» e' peggio del
   problema che risolve. Vanno a capo solo fra le parole, e per farci stare
   «Progetti d'impresa» si toglie il maiuscolo e la spaziatura fra le lettere:
   in una tabella densa quei due orpelli costano trenta pixel di larghezza
   ciascuno e non aggiungono niente. Abbreviare il vocabolario del dominio
   («Prog. d'impr.») sarebbe peggio di entrambe le cose. */
.table--densa thead th {
  white-space: normal; line-height: 1.25;
  overflow-wrap: normal; word-break: keep-all; hyphens: none;
  text-transform: none; letter-spacing: 0;
  font-size: var(--fs-xs); color: var(--c-text-muted);
}
/* Il chip e' `inline-flex`: il suo testo da solo non andrebbe a capo. Nei dati
   deve poterlo fare, altrimenti un codice lungo sborda. */
.table--densa td .chip { white-space: normal; overflow-wrap: anywhere; max-width: 100%; }

/* La riga di GRUPPO — e i suoi TOTALI.
   Raggruppando per corso, la colonna «Corso» sparisce: la dice il gruppo. Ed e'
   anche la distinzione delle righe che una tabella lunga chiede, senza zebratura
   che con i gruppi verrebbe sfalsata.

   **Senza `colspan`**, e non e' un dettaglio: una cella che attraversa tutte le
   colonne corre sotto quelle numeriche e si legge come una cella sbordata, non
   come un gruppo. Ogni totale sta nella SUA colonna, e la tabella resta
   colonnare. I totali sono anche un dato che prima non si vedeva da nessuna
   parte: quanti studenti ha un corso in tutto. */
.table__gruppo > th,
.table__gruppo > td {
  background: var(--c-surface-sunk);
  border-top: 1px solid var(--c-border-strong);
  padding: var(--sp-2) var(--sp-3);
  text-transform: none; letter-spacing: 0;
  position: static;
  font-weight: var(--fw-semibold); color: var(--c-text);
  vertical-align: top;
}
.table__gruppo > th { text-align: left; }
.table__gruppo .gruppo__nome {
  overflow-wrap: anywhere; font-weight: var(--fw-semibold);
}
/* Le righe di dato di un gruppo rientrano di poco: dice «queste stanno dentro
   quello sopra» senza bisogno di una linea in piu'. */
.cella__figlia { padding-left: calc(var(--sp-3) + var(--sp-3)) !important; }
.table__gruppo:first-child > th { border-top: none; }
.table__gruppo .gruppo__nome {
  font-size: var(--fs-sm); font-weight: var(--fw-semibold);
  color: var(--c-text);
}
.table__gruppo .gruppo__nota {
  font-size: var(--fs-xs); font-weight: var(--fw-normal);
  color: var(--c-text-muted); text-transform: none; letter-spacing: 0;
}
/* Alternanza calcolata DENTRO il gruppo, non con `nth-child`: le righe di gruppo
   contano nel conteggio del CSS e le strisce uscirebbero sfalsate. */
.table--densa tbody tr.is-pari { background: var(--c-surface-alt); }
.table--densa tbody tr.is-pari:hover { background: var(--c-primary-tint); }
/* La riga di gruppo non reagisce al passaggio del mouse: non e' cliccabile, e
   illuminarsi promette qualcosa che non fa. */
.table--densa tbody tr.table__gruppo:hover > th,
.table--densa tbody tr.table__gruppo:hover > td { background: var(--c-surface-sunk); }

/* I numeri AL CENTRO della loro colonna, non schiacciati a destra. Con colonne
   strette e allineamento a destra i numeri di colonne diverse si toccavano fra
   loro, e tutto lo spazio avanzato finiva nella prima colonna — che restava mezza
   vuota. Sono valori a una o due cifre: incolonnarli a destra per confrontarli
   non serve, e centrati la tabella respira. */
.table--densa td.mid, .table--densa th.mid {
  text-align: center; font-variant-numeric: tabular-nums;
}
.table--densa td.azioni { text-align: right; }
/* «1/4»: il denominatore non deve gridare come il numeratore. Solo il colore —
   `.text-subtle` porta con se' anche una dimensione, e dentro una cella densa
   renderebbe il denominatore piu' grande del numero. */
.cella__su { color: var(--c-text-subtle); font-weight: var(--fw-normal); }

/* Il secondo rigo di una cella: l'anno scolastico sotto il nome della classe. */
.cella__sotto {
  display: block; font-size: var(--fs-xs); color: var(--c-text-subtle);
  margin-top: 1px;
}

/* ========================================================== empty state

   `style-empty-states-guidati`: ogni area vuota dice PERCHÉ è vuota e qual è
   l'azione. Vale in particolare per lo studente al primo accesso e per lo
   stakeholder esterno la cui autorizzazione è scaduta.

   Il bordo tratteggiato è deliberato: dice «qui ci andrà qualcosa», mentre un
   bordo pieno direbbe «questo è un blocco», e un'area senza bordo sembrerebbe
   un guasto di caricamento.                                                   */

.empty {
  text-align: center;
  padding: var(--sp-6) var(--sp-5);
  color: var(--c-text-muted);
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-md);
  background: var(--c-surface-alt);
}
.empty-icon {
  width: 46px; height: 46px; margin: 0 auto var(--sp-3);
  border-radius: var(--r-md);
  background: var(--c-primary-soft); color: var(--c-primary);
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: var(--fw-bold);
  box-shadow: inset 0 0 0 1px var(--c-primary-border);
}
.empty-title { font-family: var(--font-display); font-weight: var(--fw-bold);
               color: var(--c-text); margin-bottom: var(--sp-1); }
.empty-text  { font-size: var(--fs-sm); max-width: 46ch; margin: 0 auto var(--sp-4); }

/* ============================================================== skeleton */

.skeleton {
  background: linear-gradient(90deg, var(--c-surface-sunk) 25%,
              var(--c-bg-deep) 37%, var(--c-surface-sunk) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: var(--r-sm);
  min-height: 1em;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* =========================================================== avanzamento */

.progress {
  height: 9px; background: var(--c-bg-deep); border-radius: var(--r-pill);
  overflow: hidden; box-shadow: inset 0 1px 2px rgba(11, 35, 49, 0.06);
}
.progress-bar {
  height: 100%; border-radius: var(--r-pill);
  background: var(--c-primary); background-image: var(--g-primary);
  transition: width var(--t-slow);
}
/* Arrivare in fondo si vede: la barra piena prende il verde del logo. */
.progress--success .progress-bar { background-image: var(--g-accent); }
.progress--warning .progress-bar { background-image: none; background: var(--c-warning); }

/* ============================================================== autosave

   `style-autosave`: indicatore leggibile dello stato del salvataggio.
   Perdere quattro ore di lavoro sul canvas è il difetto peggiore che questo
   prodotto possa avere.                                                       */

.autosave { display: inline-flex; align-items: center; gap: var(--sp-1);
            font-size: var(--fs-xs); font-weight: var(--fw-medium);
            color: var(--c-text-subtle); }
.autosave--salvato  { color: var(--c-success); }
.autosave--in-corso { color: var(--c-text-muted); }
.autosave--errore   { color: var(--c-danger); font-weight: var(--fw-bold); }

/* ================================================================ toast */

.toast-area { position: fixed; right: var(--sp-5); bottom: var(--sp-5); z-index: 90;
              display: flex; flex-direction: column; gap: var(--sp-2); }
.toast {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-info);
  border-radius: var(--r-md); box-shadow: var(--sh-lg);
  padding: var(--sp-3) var(--sp-4); max-width: 360px; font-size: var(--fs-sm);
  animation: sali var(--t-base) both;
}
.toast--success { border-left-color: var(--c-success); }
.toast--error   { border-left-color: var(--c-danger); }
@keyframes sali { from { opacity: 0; transform: translateY(8px); }
                  to   { opacity: 1; transform: translateY(0); } }

/* ====================================================== selettore a fasce

   Per i filtri a poche opzioni mutuamente esclusive. Meglio di una `select`
   quando le opzioni sono due o tre: si vedono tutte senza aprire niente.      */

.segmented {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--c-surface-sunk); border: 1px solid var(--c-border);
  border-radius: var(--r-pill);
}
.segmented button {
  appearance: none; background: transparent; border: none;
  padding: var(--sp-1) var(--sp-4); border-radius: var(--r-pill);
  font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-semibold);
  color: var(--c-text-muted); cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.segmented button:hover { color: var(--c-text); }
.segmented button.is-active {
  background: var(--c-surface); color: var(--c-primary); box-shadow: var(--sh-xs);
}

/* ============================================================== accesso

   Le pagine di accesso sono le uniche a tutta finestra: due metà, l'inchiostro
   a sinistra col nome del prodotto, il form a destra sul chiaro. È anche il
   punto dove la piattaforma si presenta, e presentarsi con un form centrato su
   grigio è un'occasione buttata.                                              */

.auth {
  min-height: 100vh;
  display: grid; grid-template-columns: 1.05fr 1fr;
}
.auth__hero {
  background-color: var(--c-ink);
  background-image:
    radial-gradient(circle at 10% 92%, rgba(60, 192, 216, 0.20), transparent 58%),
    var(--g-ink);
  color: var(--c-text-invert);
  padding: var(--sp-8) var(--sp-7);
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-6);
  position: relative; overflow: hidden;
}
/* La meta' scura non ha un claim (via con gli spiegoni): il MARCHIO stesso,
   grande e centrato, e' il contenuto del pannello — come si fa su una
   copertina, non un timbrino in alto a sinistra (revisione 12). */
.auth__hero > * { position: relative; z-index: 1; }
/* Il marchio nella fascia scura: il testo torna bianco (nella barra in alto,
   che ora e' chiara, resta inchiostro) e il logo sta senza tessera anche qui —
   i suoi tre nodi sono abbastanza vividi da reggere il petrolio. */
.auth__hero .brand, .auth__hero .brand:hover { color: var(--c-text-invert); }
.auth__hero .brand {
  margin: auto;                      /* al centro del pannello, su entrambi gli assi */
  flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-5);
}
.auth__hero .brand-mark {
  width: clamp(110px, 13vw, 170px); height: auto; aspect-ratio: 1;
  filter: drop-shadow(0 18px 40px rgba(0, 0, 0, 0.35));
}
.auth__hero .brand > span:last-child {
  font-size: clamp(2.1rem, 3.4vw, 3.2rem); line-height: 1.08;
  letter-spacing: -0.025em; max-width: 13ch;
}
/* Il filo dei tre colori del logo lungo il bordo destro della fascia: e' il
   punto in cui il marchio incontra il modulo d'accesso. */
.auth__hero::before {
  content: ""; position: absolute; inset: 0 0 0 auto; width: 3px;
  background: var(--g-logo); z-index: 2;
}
.auth__claim {
  font-family: var(--font-display); font-weight: var(--fw-black);
  font-size: clamp(1.75rem, 3.4vw, var(--fs-4xl)); line-height: 1.08;
  letter-spacing: -0.03em; margin: 0; max-width: 22ch;
}
.auth__sub { color: rgba(255, 255, 255, 0.74); margin: var(--sp-4) 0 0; max-width: 44ch; }
.auth__note { color: rgba(255, 255, 255, 0.52); font-size: var(--fs-xs); margin: 0; }
.auth__panel {
  display: grid; place-items: center; align-content: center;
  gap: var(--sp-5); padding: var(--sp-7) var(--sp-5);
}
/* la bandella non e' vincolata ai 400px del modulo: le serve larghezza */
.auth__panel #bandella-accesso { width: min(520px, 100%); }
.auth__box { width: 100%; max-width: 400px; }

/* ============================================================ responsive

   `style-desktop-first-mobile-consultazione`: desktop e tablet per lavorare,
   mobile per consultare. Nessuna schermata richiede scroll orizzontale della
   PAGINA — le tabelle scorrono nel proprio contenitore (.table-wrap).          */

@media (max-width: 1080px) {
  .col-2 { grid-column: span 3; }
  .col-5, .col-7 { grid-column: span 6; }
  .col-9, .col-10 { grid-column: span 12; }
}

@media (max-width: 960px) {
  .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8 { grid-column: span 6; }
  .auth { grid-template-columns: 1fr; }
  /* Su tablet la metà in inchiostro diventa una fascia in cima, non sparisce:
     è dove la piattaforma dice come si chiama. */
  .auth__hero { padding: var(--sp-6) var(--sp-5); gap: var(--sp-4); }
  .auth__hero .auth__note { display: none; }
}

/* La coppia «Corsi» + «Classi» di Gestione: la tabella delle classi ha bisogno di
   circa 500px per non scorrere, e mezza griglia glieli da' solo oltre i 1200px di
   finestra. Sotto, le due schede vanno una sull'altra — e' il CONTENUTO che decide
   il punto di rottura, non la griglia generica. Fra 720 e 960px la scheda restava
   a mezza larghezza e la tabella spingeva la pagina a scorrere in orizzontale. */
@media (max-width: 1200px) {
  #pannello-struttura .col-4,
  #pannello-struttura .col-8 { grid-column: span 12; }
}

@media (max-width: 720px) {
  .container { padding: 0 var(--sp-4); }
  .page { padding: var(--sp-5) 0 var(--sp-6); }

  /* card a piena larghezza */
  .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-12 {
    grid-column: span 12;
  }
  .card { padding: var(--sp-4); border-radius: var(--r-md); }

  /* le azioni primarie devono essere toccabili col dito */
  .btn { min-height: 48px; }
  .btn--sm { min-height: 40px; }

  h1 { font-size: var(--fs-xl); }
  h2 { font-size: var(--fs-lg); }
  .stat-value { font-size: var(--fs-xl); }
  .auth__hero { display: none; }   /* sul telefono il form si prende tutto */
}

/* Chi ha chiesto meno animazioni non deve ricevere né transizioni né i
   sollevamenti in hover: `transform` è movimento quanto un'animazione. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .btn:hover, .card--hover:hover, .btn:active { transform: none !important; }
}

/* ================================================================ stampa */

@media print {
  .navbar, .nav-links, .toast-area, .btn, .segmented, .piede { display: none !important; }
  body { background: #fff; background-image: none; }
  .card, .table-wrap { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  .card--hero { background: #fff !important; background-image: none !important; color: #000; }
  .card--hero::after { display: none; }
}

/* ====================================================== pannello dei filtri

   Ancorato al bordo SINISTRO, fuori dal `.container`, e quando è aperto la
   pagina si stringe invece di andargli sotto. A destra resta la corsia delle
   statistiche (`.statistiche`): filtri da una parte, numeri dall'altra, il
   lavoro in mezzo. È l'impianto dei pannelli di compatt e cit_group, con tre
   tipi di controllo:

     chip         →  poche opzioni, selezione multipla a un clic
     multicheck   →  ha l'aspetto di una select, ma dentro sono checkbox, con
                     una riga di riepilogo («3 selezionati»)
     multiselect  →  molte opzioni: campo di ricerca interno + lista scorrevole

   Due scelte di comportamento che valgono più di qualunque dettaglio grafico:
   - **niente bottone «Applica»**: i filtri si applicano al cambio, con debounce
     sul testo. Un Applica aggiunge un passo e lascia sempre il dubbio se il
     filtro sia attivo o solo scritto;
   - **i filtri attivi sono elencati in cima**, ognuno rimovibile con una x. Un
     pannello richiuso con tre filtri dentro fa sembrare rotta la pagina: qui
     quello che è attivo si vede sempre, e da lì si toglie.                    */

:root {
  --fp-w: 268px;              /* larghezza di ENTRAMBE le corsie laterali */
  --fp-gap: 14px;             /* stacco dal bordo e dal contenuto */
  /* Il tasto «indietro» sta in alto a sinistra e ha la precedenza: i pannelli
     laterali partono sotto di lui, non gli si sovrappongono. */
  --fp-top: calc(var(--nav-h) + 56px);
  --fp-band: calc(var(--fp-w) + var(--fp-gap) * 2);
}

/* Quando il pannello è aperto la pagina si stringe: `.container` è centrato con
   `margin:auto`, quindi il padding sul `.page` lo ricentra nello spazio che
   resta, senza toccarne la larghezza massima. */
/* **La colonna centrale non si muove. Mai.**
   I due pannelli sono `position: fixed` e galleggiano SOPRA i margini della
   pagina: aprirli e chiuderli non tocca il contenuto, che resta centrato nella
   finestra esattamente dov'era. Nessun `padding` sul `.page`.

   Il prezzo è dichiarato: su una finestra più stretta di ~1830px il pannello
   copre il bordo della colonna centrale, e per questo la linguetta di
   apertura/chiusura è sempre a portata. La reazione da evitare era l'altra —
   una colonna che scivola di 150px a ogni apertura, con la riga che si stava
   leggendo che si sposta sotto gli occhi. */

.filtri {
  position: fixed; z-index: 45;
  top: var(--fp-top);
  left: var(--fp-gap);
  width: var(--fp-w);
  max-height: calc(100vh - var(--fp-top) - var(--fp-gap));
  display: flex; flex-direction: column;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-lg);
  transition: transform var(--t-base), opacity var(--t-base);
}
/* Chiuso esce di scena dal proprio lato, non con `display:none`: così apertura
   e chiusura hanno una direzione, e si capisce dove è finito. */
.filtri.is-chiuso {
  transform: translateX(calc(-100% - var(--fp-gap) * 2));
  opacity: 0; pointer-events: none;
}

.filtri__testa {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--c-border);
  background: var(--c-surface-sunk);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.filtri__titolo {
  font-family: var(--font-sans);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--c-text-subtle); margin: 0;
}
.filtri__conta {
  display: inline-grid; place-items: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--c-accent); color: var(--c-text-invert);
  font-size: 0.6875rem; font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}
.filtri__pulisci {
  margin-left: auto; background: none; border: 0; padding: 0;
  font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  color: var(--c-primary); cursor: pointer;
}
.filtri__pulisci:hover { text-decoration: underline; }
.filtri__chiudi {
  background: none; border: 0; padding: 2px 5px; cursor: pointer;
  color: var(--c-text-subtle); font-size: var(--fs-md); line-height: 1;
  border-radius: var(--r-sm);
}
.filtri__chiudi:hover { background: var(--c-bg-deep); color: var(--c-text); }

/* I filtri attivi, in cima e rimovibili uno per uno */
.filtri__attivi { display: flex; flex-wrap: wrap; gap: var(--sp-1);
                  padding: var(--sp-3) var(--sp-4) 0; }
.filtri__attivi:empty { display: none; }
.filtro-attivo {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px var(--sp-2); border-radius: var(--r-pill);
  background: var(--c-primary-soft); color: var(--c-primary);
  border: 1px solid var(--c-primary-border);
  font-size: 0.6875rem; font-weight: var(--fw-semibold);
  max-width: 100%;
}
.filtro-attivo span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filtro-attivo button {
  background: none; border: 0; padding: 0; cursor: pointer; line-height: 1;
  color: inherit; opacity: 0.6; font-size: 0.8125rem; flex: none;
}
.filtro-attivo button:hover { opacity: 1; }

.filtri__corpo { overflow-y: auto; padding: var(--sp-4); display: grid; gap: var(--sp-4); }

.filtri__gruppo { display: grid; gap: var(--sp-2); }
.filtri__label {
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--c-text-subtle);
}

/* Ricerca con la lente dentro il campo */
.filtri__ricerca { position: relative; }
.filtri__ricerca .input { padding-left: 1.9rem; }
.filtri__ricerca::before {
  content: "\2315"; position: absolute; left: 0.6rem; top: 50%;
  transform: translateY(-52%); color: var(--c-text-subtle);
  font-size: var(--fs-md); pointer-events: none;
}

/* Chip a selezione multipla */
.filtri__chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.f-chip {
  border: 1px solid var(--c-border-strong); background: var(--c-surface);
  color: var(--c-text); border-radius: var(--r-pill);
  font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  padding: 3px var(--sp-3); cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.f-chip:hover { background: var(--c-surface-sunk); }
.f-chip.is-attivo {
  background: var(--c-primary); background-image: var(--g-primary);
  border-color: transparent; color: var(--c-text-invert);
}

/* Multicheck: sembra una select, dentro sono checkbox */
.f-multi { position: relative; }
.f-multi__trigger {
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-2) 1.9rem var(--sp-2) var(--sp-3);
  min-height: 38px;
  background: var(--c-surface); color: var(--c-text);
  border: 1px solid var(--c-border-strong); border-radius: var(--r-md);
  font: inherit; font-size: var(--fs-sm);
  display: flex; align-items: center;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.f-multi__trigger::after {
  content: "\25BE"; position: absolute; right: var(--sp-3); top: 50%;
  transform: translateY(-50%); color: var(--c-text-subtle); font-size: var(--fs-xs);
}
.f-multi__trigger:hover { border-color: var(--c-text-subtle); }
.f-multi__trigger:focus-visible { border-color: var(--c-primary); box-shadow: 0 0 0 3px var(--c-primary-soft); }
.f-multi__riepilogo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Senza selezione il riepilogo è un segnaposto, e si vede che lo è */
.f-multi:not(.ha-valore) .f-multi__riepilogo { color: var(--c-text-subtle); }

.f-multi__pannello {
  display: none; position: absolute; z-index: 5;
  top: calc(100% + 4px); left: 0; right: 0;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-md); box-shadow: var(--sh-md);
  padding: var(--sp-1); max-height: 240px; overflow-y: auto;
}
.f-multi.is-aperto .f-multi__pannello { display: block; }

/* Lista con ricerca interna, per quando le opzioni sono molte */
.f-lista {
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  background: var(--c-surface); overflow: hidden;
}
.f-lista__cerca { padding: var(--sp-1); border-bottom: 1px solid var(--c-border);
                  background: var(--c-surface-sunk); }
.f-lista__cerca input {
  width: 100%; border: 0; background: transparent; outline: none;
  font: inherit; font-size: var(--fs-sm); padding: var(--sp-1) var(--sp-2);
  color: var(--c-text);
}
.f-lista__voci { max-height: 176px; overflow-y: auto; padding: var(--sp-1); }
.f-lista__vuoto { padding: var(--sp-3); font-size: var(--fs-xs); color: var(--c-text-subtle);
                  text-align: center; }

/* La riga con la checkbox: tutta cliccabile, non solo il quadratino */
.f-check {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2); border-radius: var(--r-sm);
  font-size: var(--fs-sm); cursor: pointer; margin: 0;
  transition: background var(--t-fast);
}
.f-check:hover { background: var(--c-primary-tint); }
.f-check input { margin: 0; flex: none; width: 15px; height: 15px;
                 accent-color: var(--c-primary); cursor: pointer; }
.f-check span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-check__conta { margin-left: auto; font-size: var(--fs-xs); color: var(--c-text-subtle);
                  font-variant-numeric: tabular-nums; flex: none; }

/* Intervallo di date: due campi affiancati con «dal / al» sopra */
/* `minmax(0, 1fr)` e non `1fr`: un `input[type=date]` ha una larghezza minima
   intrinseca (il segnaposto più l'iconcina del calendario) e con `1fr` la
   griglia la rispetta, sfondando il pannello invece di comprimersi. */
.filtri__periodo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
                   gap: var(--sp-2); }
.filtri__periodo > div { min-width: 0; }
.filtri__periodo .input {
  font-size: var(--fs-xs); min-height: 36px; min-width: 0;
  padding-left: var(--sp-2); padding-right: var(--sp-1);
}
.filtri__mini { font-size: 0.6875rem; color: var(--c-text-subtle); font-weight: var(--fw-medium); }

/* La linguetta: **sempre presente**, sia per aprire sia per chiudere. Quando il
   pannello è aperto si sposta sul suo bordo esterno e il chevron si gira; quando
   è chiuso torna al bordo della finestra e porta il contatore dei filtri attivi
   — altrimenti un filtro attivo su un pannello chiuso diventa invisibile.

   Un pannello che si apre da una linguetta e si chiude solo da una x dentro di sé
   costringe a cercare due controlli diversi per la stessa cosa. */
.filtri-tab {
  position: fixed; z-index: 46; left: 0;
  top: calc(var(--fp-top) + 4px);
  transition: left var(--t-base), background var(--t-fast), transform var(--t-fast);
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-3);
  border: 1px solid var(--c-border); border-left: 0;
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--c-surface); color: var(--c-text);
  font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-semibold);
  box-shadow: var(--sh-md); cursor: pointer;
  transition: background var(--t-fast), transform var(--t-fast);
}
.filtri-tab:hover { background: var(--c-surface-alt); }
.filtri-tab[hidden] { display: none; }
/* A pannello aperto la linguetta si appoggia al suo fianco destro, così resta
   sempre alla portata senza coprire i controlli. */
.filtri-tab.is-aperto {
  left: calc(var(--fp-w) + var(--fp-gap));
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding-left: var(--sp-2); padding-right: var(--sp-2);
}
/* Il verso lo decide il carattere messo dal JS («›» chiuso, «‹» aperto):
   ruotarlo ANCHE qui lo capovolgeva due volte, e la freccia non cambiava mai. */
.filtri-tab__chev { display: inline-block; }

@media (max-width: 1100px) {
  /* Sopra il contenuto: la linguetta resta al bordo, altrimenti finirebbe in
     mezzo alla pagina sotto il velo. */
  .filtri-tab.is-aperto { left: 0; }
}

/* Da tablet in giù il pannello va SOPRA il contenuto, con un velo dietro:
   stringere una pagina già stretta non lascia spazio a nessuno dei due. */
@media (max-width: 1280px) {
  /* Prima cade la corsia delle statistiche: i numeri tornano dentro la pagina,
     dove il posto c'è. I filtri restano — sono uno strumento, non un riepilogo. */
  .statistiche { display: none; }
  .statistiche-in-pagina { display: block; }
}

@media (max-width: 1100px) {
  .filtri-velo {
    position: fixed; inset: var(--nav-h) 0 0; z-index: 44;
    background: rgba(22, 28, 38, 0.38);
  }
  .filtri-velo[hidden] { display: none; }
}
/* La NAVBAR collassa a 1000px e non a 720 come il resto del layout: il punto di
   rottura di una barra di navigazione lo decide QUANTO E' LARGA, cioe' quante voci
   ha il ruolo che sta guardando — non la larghezza a cui le card vanno a capo.
   Con sei voci (il coordinatore, dopo che la revisione 2 ha aggiunto la Bacheca)
   fra 720 e 1000px la barra usciva dalla finestra e faceva scorrere la pagina in
   orizzontale: un difetto che si vedeva solo in quella fascia, e la suite del
   browser controlla i 390px. */
@media (max-width: 1000px) {
  .navbar .nav-toggle { display: inline-flex; margin-left: auto; }
  .nav-links {
    display: none; position: absolute; top: var(--nav-h); left: 0; right: 0;
    flex-direction: column; align-items: stretch;
    background: var(--c-surface);
    border-bottom: 1px solid var(--c-border);
    padding: var(--sp-3); gap: var(--sp-1); box-shadow: var(--sh-md);
    z-index: 46;
  }
  .nav-links.is-open { display: flex; }
  .nav-link { padding: var(--sp-3); border-radius: var(--r-sm); }
}

@media (max-width: 720px) {
  .filtri { right: var(--fp-gap); width: auto; }
}

/* ================================================== scheda di un programma

   Una scheda d'elenco deve rispondere a tre domande senza aprirla: che cosa è,
   come sta andando, quanto è grande. Da qui il glifo tinto per la tipologia, il
   badge di stato, i tre numeri in fondo e la barra dei conclusi.

   Le altezze sono allineate con flex e non con `height`: i titoli su due righe
   e le descrizioni corte non devono lasciare schede di misure diverse in fila. */

/* `a.prog-card` e non `.prog-card`: la regola `a.card { display: block }` più
   sopra ha specificità di tipo+classe e vinceva su una classe sola. Risultato: la
   scheda NON era un contenitore flex, quindi il `margin-top: auto` del piede non
   spingeva niente in basso e le barre di avanzamento finivano ad altezze diverse
   in ogni scheda della stessa riga. È il tipo di difetto che si vede solo
   affiancando tre schede con contenuti di lunghezza diversa. */
.prog-card, a.prog-card { display: flex; flex-direction: column; gap: var(--sp-3); }
.prog-card__testa { display: flex; align-items: flex-start; gap: var(--sp-3); }

/* Le altezze delle righe interne sono FISSE, non dettate dal contenuto: così la
   stessa informazione sta alla stessa altezza in tutte le schede della riga.
   Senza, un'etichetta di tipologia che va a capo sposta in basso tutto il resto
   di quella scheda sola, e la fila si sfalsa. */
.prog-card__testa .stat-label {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.1em; line-height: 1.05;
}
.prog-card__titolo {
  font-size: var(--fs-md); line-height: 1.25; margin: 2px 0 0;
  /* Due righe e poi taglia: un titolo lungo non deve spingere in basso i numeri
     e sfalsare la griglia. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.5em;
}
.prog-card__desc {
  font-size: var(--fs-sm); color: var(--c-text-muted); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  /* Tre righe ESATTE, corte o lunghe. `3.9em` era il conto sbagliato: con
     `line-height: 1.55` tre righe misurano 4.65em, quindi una descrizione lunga
     sfondava il minimo e spingeva giù di 10px tutto il resto di quella scheda
     sola — la fila si sfalsava di dieci pixel, che si vedono. */
  overflow: hidden; min-height: 4.7em;
}
/* Anche la riga di mezzo ha un'altezza sua: con un chip che va a capo su una
   scheda e non sull'altra, i numeri in fondo si disallineavano. */
.prog-card__meta {
  display: flex; align-items: center; gap: var(--sp-2);
  /* `nowrap` e non `wrap`: se il chip del corso e la data non ci stanno, andando
     a capo alzano di 10px tutto quello che sta sotto in QUELLA scheda sola, e la
     fila si sfalsa. Meglio troncare il chip: la data è corta e non si tocca. */
  flex-wrap: nowrap; min-height: 26px; min-width: 0;
}
.prog-card__meta .chip {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.prog-card__meta > .text-xs { flex: none; }
/* `auto` sul margine superiore incolla il piede in basso: le barre di tutte le
   schede della riga finiscono alla stessa altezza. */
.prog-card__piede { margin-top: auto; display: grid; gap: var(--sp-2); }

/* La barra sopra l'elenco dei programmi: vista card/lista e raggruppamento.
   Il gruppo e' un titolo di sezione, non una card: piu' e' profondo, piu' e'
   piccolo e rientrato — la gerarchia si vede dal margine, come in un indice. */
.vista-scelta {
  display: inline-flex; border: 1px solid var(--c-border);
  border-radius: var(--r-sm); overflow: hidden; background: var(--c-surface);
}
.vista-scelta__voce {
  border: 0; background: transparent; cursor: pointer;
  padding: .35rem .8rem; font: inherit; font-size: var(--fs-sm);
  color: var(--c-text-muted);
}
.vista-scelta__voce + .vista-scelta__voce { border-left: 1px solid var(--c-border); }
.vista-scelta__voce.is-attivo {
  background: var(--c-primary); color: #fff; font-weight: var(--fw-semibold);
}
.prog-gruppo { margin-bottom: var(--sp-4); }
.prog-gruppo .prog-gruppo { margin: var(--sp-3) 0 var(--sp-3) var(--sp-4); }
.prog-gruppo__testa {
  display: flex; align-items: center; gap: var(--sp-2);
  font-weight: var(--fw-semibold); margin-bottom: var(--sp-2);
}
.prog-gruppo--l1 > .prog-gruppo__testa { font-size: var(--fs-md); }
.prog-gruppo--l2 > .prog-gruppo__testa,
.prog-gruppo--l3 > .prog-gruppo__testa { font-size: var(--fs-sm); color: var(--c-text-muted); }
.riga-cliccabile { cursor: pointer; }
.riga-cliccabile:hover > td { background: var(--c-surface-2); }
.prog-card__cifre {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  font-size: var(--fs-xs); color: var(--c-text-muted);
  /* `baseline` e non `center`: il numero in grande alza la sua voce, e le voci
     senza numero finivano dieci pixel piu' su. Si vedeva. */
  align-items: baseline;
}
.prog-card__cifre b {
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: var(--fs-base); color: var(--c-text);
  font-variant-numeric: tabular-nums;
}

/* ================================================ corsia delle statistiche

   Il lato destro: i numeri. La divisione è deliberata e vale per tutte le
   pagine — **a sinistra si agisce, in mezzo si lavora, a destra si legge**.
   Tenere i filtri e i totali sullo stesso lato costringe a scorrere avanti e
   indietro fra la causa e l'effetto.

   I numeri qui dentro si riferiscono a ciò che i filtri lasciano passare, non
   al totale assoluto: altrimenti il pannello di sinistra e la corsia di destra
   raccontano due storie diverse sulla stessa schermata.                       */

:root {
  /* Stessa larghezza dei filtri: è la condizione perché la colonna centrale
     resti centrata quando si apre un pannello solo. */
  --st-w: var(--fp-w);
}


.statistiche {
  position: fixed; z-index: 43;
  top: var(--fp-top);
  right: var(--fp-gap);
  width: var(--st-w);
  max-height: calc(100vh - var(--fp-top) - var(--fp-gap));
  overflow-y: auto;
  display: grid; gap: var(--sp-3);
  align-content: start;
}

/* Le tessere della corsia sono più compatte di quelle in pagina: qui contano
   dieci numeri leggibili, non quattro numeri grandi. */
.statistiche .card { padding: var(--sp-4); border-radius: var(--r-md); }
.statistiche .stat-value { font-size: var(--fs-xl); }
.statistiche .stat-icon { width: 34px; height: 34px; font-size: 1.25rem; }
.statistiche .card-title { margin-bottom: var(--sp-3); }

/* Riga «etichetta … valore»: la forma più densa per una lista di numeri. */
.st-riga {
  display: flex; align-items: baseline; gap: var(--sp-2);
  font-size: var(--fs-sm); padding: var(--sp-1) 0;
}
.st-riga + .st-riga { border-top: 1px dashed var(--c-border); }
.st-riga__etichetta { color: var(--c-text-muted); min-width: 0;
                      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-riga__valore {
  margin-left: auto; flex: none;
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums; color: var(--c-text);
}

/* Barra orizzontale con etichetta sopra: per le distribuzioni brevi (stati,
   tipologie). Più leggibile di una torta quando le voci sono più di tre e i
   valori vicini fra loro. */
.st-barra { display: grid; gap: 3px; padding: var(--sp-1) 0; }
.st-barra__capo { display: flex; align-items: baseline; gap: var(--sp-2);
                  font-size: var(--fs-xs); }
.st-barra__capo b { margin-left: auto; font-variant-numeric: tabular-nums;
                    font-weight: var(--fw-bold); }
.st-barra__traccia { height: 6px; background: var(--c-bg-deep);
                     border-radius: var(--r-pill); overflow: hidden; }
.st-barra__pieno { height: 100%; border-radius: var(--r-pill);
                   background: var(--c-primary); transition: width var(--t-slow); }
.st-barra__pieno--verde { background: var(--c-success); }
.st-barra__pieno--ambra { background: var(--c-warning); }
.st-barra__pieno--rosso { background: var(--c-danger); }
.st-barra__pieno--ciano { background: var(--c-info); }
.st-barra__pieno--viola { background: #5b45a8; }

/* ============================================ corsia destra di contesto

   Le pagine di creazione hanno un riquadro che spiega cosa succederà («Cosa
   succede dopo», «Perché queste classificazioni»). Dentro la griglia si prende
   una colonna intera e la lascia vuota per due terzi dell'altezza: il testo è
   corto, il form è lungo.

   Qui quel riquadro si **stacca nella corsia di destra** quando c'è spazio, e
   resta nel flusso quando non c'è. È tutto in CSS, senza spostare nodi nel DOM:
   così sotto la soglia il contenuto è esattamente dov'era, e nessuno rischia di
   perderlo perché un `display:none` l'ha nascosto.

   **Queste pagine restano larghe come tutte le altre**: nessun container
   ristretto. Sotto la soglia il riquadro è una fascia a piena larghezza in fondo
   al form — corta, su due colonne di testo — e non una colonna alta e vuota
   accanto a un form lungo.

   La soglia non è a caso: perché il contenuto resti **centrato nella finestra**
   con il container normale (1240px) e una corsia larga `--fp-band`, servono
   almeno `1240 + 2 × 282` px. Da qui i 1810px: sotto, la corsia coprirebbe il
   form, e il rimedio sarebbe peggio del male.                                  */

.container--stretto { max-width: 840px; }



/* ======================================================= scelta a tessere

   Un gruppo di radio con descrizione non va incolonnato: quattro opzioni in
   verticale fanno una card lunga e mezza pagina vuota accanto. In griglia
   occupano metà dell'altezza e si confrontano con un colpo d'occhio, che è
   esattamente ciò che serve quando la scelta cambia il resto del form.

   La radio nativa resta (accessibilità e tastiera funzionano da sole): è
   nascosta alla vista e la tessera reagisce con `:has()`.                     */

.scelta-griglia {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.scelta {
  position: relative; display: block; cursor: pointer;
  padding: var(--sp-4);
  border: 1px solid var(--c-border-strong); border-radius: var(--r-md);
  background: var(--c-surface);
  transition: border-color var(--t-fast), box-shadow var(--t-fast),
              background var(--t-fast), transform var(--t-fast);
}
.scelta:hover { border-color: var(--c-text-subtle); box-shadow: var(--sh-sm); }
.scelta input { position: absolute; opacity: 0; pointer-events: none; }
/* Selezionata: bordo e velatura del primario, più il segno di spunta in alto a
   destra. Il colore da solo non basta — `vinc-accessibilita`. */
.scelta:has(input:checked) {
  border-color: var(--c-primary); background: var(--c-primary-tint);
  box-shadow: 0 0 0 1px var(--c-primary), var(--sh-sm);
}
.scelta:has(input:checked)::after {
  content: "\2713"; position: absolute; top: var(--sp-3); right: var(--sp-3);
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--c-primary); color: var(--c-text-invert);
  display: grid; place-items: center; font-size: 0.6875rem; font-weight: 700;
}
.scelta:has(input:focus-visible) { outline: 2px solid var(--c-primary); outline-offset: 2px; }
.scelta__testa { display: flex; align-items: center; gap: var(--sp-3);
                 margin-bottom: var(--sp-2); }
.scelta__titolo { font-family: var(--font-display); font-weight: var(--fw-bold);
                  font-size: var(--fs-base); }
.scelta__desc { font-size: var(--fs-sm); color: var(--c-text-muted); margin: 0; }
.scelta__nota { font-size: var(--fs-xs); color: var(--c-text-subtle);
                margin-top: var(--sp-2); }

/* Fallback per i browser senza `:has()`: la classe la mette il JS al cambio. */
.scelta.is-scelta { border-color: var(--c-primary); background: var(--c-primary-tint); }

/* Un campo dentro la griglia a 12 colonne del form */
.field.col-3, .field.col-4, .field.col-5, .field.col-6,
.field.col-7, .field.col-8, .field.col-12 { margin-bottom: 0; }

/* ==================================================== tessera di persona

   Scegliere i componenti di un team da una lista di checkbox con nome ed email
   è la forma più povera possibile: venti righe identiche in cui si perde il
   segno. Qui ogni persona è una tessera con le iniziali colorate — la tinta è
   derivata dal nome, quindi la stessa persona ha sempre lo stesso colore in
   tutta la piattaforma, e si riconosce prima di leggere.

   La checkbox nativa resta sotto (tastiera e screen reader funzionano da soli):
   la tessera è la sua etichetta.                                               */

.persone { display: grid; gap: var(--sp-2);
           grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }

.persona {
  position: relative; display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); cursor: pointer;
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  background: var(--c-surface); min-width: 0;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.persona:hover { border-color: var(--c-border-strong); box-shadow: var(--sh-xs); }
.persona input { position: absolute; opacity: 0; pointer-events: none; }
.persona:has(input:checked) {
  border-color: var(--c-primary); background: var(--c-primary-tint);
  box-shadow: 0 0 0 1px var(--c-primary);
}
.persona:has(input:focus-visible) { outline: 2px solid var(--c-primary); outline-offset: 2px; }
.persona.is-scelta { border-color: var(--c-primary); background: var(--c-primary-tint); }

.avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: var(--fs-xs); letter-spacing: -0.01em;
  background: var(--t-blu); color: var(--t-blu-fg);
}
.avatar--verde { background: var(--t-verde); color: var(--t-verde-fg); }
.avatar--ambra { background: var(--t-ambra); color: var(--t-ambra-fg); }
.avatar--viola { background: var(--t-viola); color: var(--t-viola-fg); }
.avatar--ciano { background: var(--t-ciano); color: var(--t-ciano-fg); }
.avatar--sm { width: 26px; height: 26px; font-size: 0.625rem; }
.avatar--lg { width: 44px; height: 44px; font-size: var(--fs-sm); }

.persona__dati {
  flex: 1 1 auto; min-width: 0;
  /* Colonna, e non due span inline: su un elemento inline `overflow: hidden` e
     i puntini di sospensione NON hanno effetto, quindi l'email non veniva
     troncata e finiva sotto l'etichetta della classe, sovrapponendosi. */
  display: flex; flex-direction: column;
}
.persona__nome { font-size: var(--fs-sm); font-weight: var(--fw-semibold);
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.persona__mail { font-size: var(--fs-xs); color: var(--c-text-subtle);
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Contenitore scorrevole quando le persone sono molte: scorre la lista, non la
   pagina, e l'altezza massima tiene il form leggibile.

   `overflow: hidden auto` e non `overflow-y: auto`: con il solo asse verticale
   il browser calcola l'orizzontale come `auto`, e la barra orizzontale compare
   per i due pixel della propria barra verticale. È inutile e si vede. */
.persone--scroll {
  max-height: 232px;
  overflow: hidden auto;
  padding: 2px;
  margin: -2px;   /* recupera il padding, così le tessere restano allineate */
}

/* ------------------------------------------------ intestazione di sezione

   Sostituisce la card unica lunghissima: più riquadri corti, ognuno con la sua
   intestazione e il suo glifo. Costa una riga di markup e rende la pagina
   leggibile a salti invece che dall'inizio alla fine.                          */

.sez-testa { display: flex; align-items: center; gap: var(--sp-3);
             margin-bottom: var(--sp-4); }
.sez-testa .stat-icon { width: 34px; height: 34px; font-size: 1.25rem; }
.sez-testa h2 { margin: 0; font-size: var(--fs-md); }
.sez-testa p { margin: 0; font-size: var(--fs-xs); color: var(--c-text-subtle); }

/* Il riquadro di contesto in fondo al form: due colonne di testo, così è una
   fascia bassa e non un paragrafo lungo a tutta larghezza (che a 1200px
   diventerebbe una riga da 150 caratteri, illeggibile). */

/* ================================================= linea del tempo verticale

   Le milestone in colonna con un filo che le unisce: si legge la sequenza, non
   solo l'elenco. Lo stato è nel pallino E nel colore del testo, non solo nel
   colore — `vinc-accessibilita`. */

.timeline { list-style: none; margin: 0; padding: 0 0 0 var(--sp-5); position: relative; }
.timeline::before {
  content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px;
  width: 2px; background: var(--c-border);
}
.timeline__voce { position: relative; padding: var(--sp-2) 0; }
.timeline__voce::before {
  content: ""; position: absolute; left: calc(-1 * var(--sp-5) + 1px); top: 12px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--c-surface); border: 2px solid var(--c-border-strong);
}
.timeline__voce--fatta::before  { background: var(--c-success); border-color: var(--c-success); }
.timeline__voce--persa::before  { background: var(--c-danger);  border-color: var(--c-danger); }
.timeline__voce--attesa::before { border-color: var(--c-primary); }
.timeline__data { font-size: var(--fs-xs); color: var(--c-text-subtle);
                  font-variant-numeric: tabular-nums; }
.timeline__titolo { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }

/* Testo lungo su più colonne: a 1200px una riga a piena larghezza è da 150
   caratteri, il doppio di quanto l'occhio segue senza perdere la riga. */
.testo-colonne {
  display: grid; gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.testo-colonne p { margin: var(--sp-1) 0 0; }

/* ============================================================== indietro

   Risalita di un livello, in alto a destra su tutte le pagine. Fissa e fuori dal
   flusso: dentro il `page-head` sarebbe in una posizione diversa su ogni pagina
   (alcune non ce l'hanno, altre lo nascondono), e un comando di navigazione deve
   stare sempre nello stesso punto per essere trovato senza cercarlo. */
.indietro {
  position: fixed; z-index: 47;
  top: calc(var(--nav-h) + var(--sp-3));
  left: var(--sp-5);
  background: var(--c-surface); box-shadow: var(--sh-sm);
}
.indietro:hover { box-shadow: var(--sh-md); }
/* Il tasto e' `fixed` in alto a sinistra e vive in <body>: la testa della pagina
   non puo' accorgersene con un selettore, quindi `shell.js` marca la radice.
   Da questa revisione la testa comincia con le briciole, e senza questo spazio
   la prima finisce sotto il bottone. */
.con-indietro .page > .container > .page-head,
.con-indietro .page #intestazione { padding-top: var(--sp-6); }
@media (max-width: 720px) { .indietro { left: var(--sp-4); top: calc(var(--nav-h) + var(--sp-2)); } }
@media print { .indietro { display: none; } }

/* ================================================================ modale

   Sostituisce i dialoghi del browser. `<dialog>` porta con sé il velo, la
   gestione del fuoco e la chiusura con Esc: qui si veste, non si reimplementa.
   Il velo è `::backdrop`, che si può stilare solo così. */

.modale {
  border: none; padding: 0; background: transparent;
  /* WIDTH, non solo max-width: il <dialog> nativo e' largo quanto il
     contenuto, e un modulo con la sola textarea collassava a 250px —
     «anche questo come altri pannelli e' inusabile» (revisione 12) */
  width: min(560px, calc(100vw - 2rem));
  max-height: calc(100vh - 4rem);
  color: var(--c-text);
}
.modale::backdrop { background: rgba(16, 21, 30, 0.52); backdrop-filter: blur(2px); }
.modale__corpo {
  background: var(--c-surface); border-radius: var(--r-lg);
  box-shadow: var(--sh-lg); padding: var(--sp-5);
  display: flex; flex-direction: column; gap: var(--sp-4);
  max-height: calc(100vh - 4rem); overflow: hidden auto;
  animation: sali var(--t-base) both;
}
.modale__corpo--larga { max-width: none; }
.modale:has(.modale__corpo--larga) { width: min(760px, calc(100vw - 2rem)); }
.modale__corpo--media { max-width: none; }
.modale:has(.modale__corpo--media) { width: min(640px, calc(100vw - 2rem)); }

.modale__testa { display: grid; gap: var(--sp-2); }
.modale__titolo { font-family: var(--font-display); font-weight: var(--fw-bold);
                  font-size: var(--fs-lg); margin: 0; letter-spacing: -0.02em; }
.modale__testo { margin: 0; font-size: var(--fs-sm); color: var(--c-text-muted); }
/* il corpo di `Modale.pannello`: scorre lui, non tutta la finestra, cosi'
   testa e piede restano fermi mentre si legge un'anteprima lunga */
.modale__contenuto { min-height: 0; overflow: auto; }
.modale__campi { display: grid; gap: var(--sp-3); }
.modale__campi .field { margin-bottom: 0; }
.modale__campi--2 { grid-template-columns: 1fr 1fr; column-gap: var(--sp-4); }
.modale__campi--2 .field--intera { grid-column: 1 / -1; }
.modale__piede {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  padding-top: var(--sp-4); border-top: 1px solid var(--c-border);
  /* il piede resta in fondo anche quando il corpo scorre */
  position: sticky; bottom: calc(-1 * var(--sp-5)); background: var(--c-surface);
  margin: 0 calc(-1 * var(--sp-5)) calc(-1 * var(--sp-5));
  padding: var(--sp-4) var(--sp-5);
}

/* ============================================================== grafici

   Nessuna libreria: sono SVG e CSS scritti a mano. Non è integralismo — una
   libreria da CDN aggiungerebbe una chiamata a un terzo (la stessa questione dei
   caratteri, `q-hosting-e-titolarita-dati`), 200 KB per quattro grafici, e uno
   stile che non è il nostro. Quattro forme bastano a tutto l'Observatory:

     ciambella  →  una composizione in poche fette (stati, tipologie)
     imbuto     →  una sequenza che si restringe (la pipeline)
     barre      →  un confronto fra molte voci (settori, competenze)
     colonne    →  un andamento nel tempo

   Le fette e le barre portano SEMPRE l'etichetta e il numero accanto: un grafico
   che si legge solo passandoci sopra col mouse non si legge da telefono e non si
   legge affatto con uno screen reader.                                        */

.graf { display: grid; gap: var(--sp-4); }

/* ------------------------------------------------------------- ciambella */
.ciambella { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }
.ciambella__disegno { flex: none; position: relative; width: 148px; height: 148px; }
.ciambella__disegno svg { transform: rotate(-90deg); }   /* si parte da ore 12 */
.ciambella__centro {
  position: absolute; inset: 0; display: grid; place-content: center; text-align: center;
}
.ciambella__totale {
  font-family: var(--font-display); font-weight: var(--fw-black);
  font-size: var(--fs-xl); line-height: 1; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.ciambella__etichetta { font-size: var(--fs-xs); color: var(--c-text-subtle); }
/* `minmax(0, 1fr)` sulla colonna e `min-width: 0` sulle righe: gli elementi di
   una griglia hanno `min-width: auto`, quindi NON si stringono sotto la larghezza
   del loro contenuto. Senza queste due righe la legenda sfonda la card su
   telefono, e la pagina prende una barra di scorrimento orizzontale. */
.ciambella__legenda { display: grid; grid-template-columns: minmax(0, 1fr);
                      gap: var(--sp-2); min-width: 0; flex: 1 1 140px; }
.legenda-voce { display: flex; align-items: center; gap: var(--sp-2);
                font-size: var(--fs-sm); min-width: 0; }
.legenda-voce__punto { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legenda-voce__nome { min-width: 0; overflow: hidden; text-overflow: ellipsis;
                      white-space: nowrap; color: var(--c-text-muted); }
.legenda-voce__val { margin-left: auto; flex: none; font-family: var(--font-display);
                     font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.legenda-voce__quota { flex: none; font-size: var(--fs-xs); color: var(--c-text-subtle);
                       min-width: 3.2em; text-align: right; }

/* ---------------------------------------------------------------- imbuto */
/* Ogni gradino è largo in proporzione al suo valore e porta la caduta rispetto
   al gradino precedente: è l'informazione che serve in una pipeline, e in un
   grafico a barre normale non si vede. */
.imbuto { display: grid; gap: var(--sp-2); }
.imbuto__passo { display: grid; gap: 3px; }
.imbuto__capo { display: flex; align-items: baseline; gap: var(--sp-2); font-size: var(--fs-sm); }
.imbuto__nome { color: var(--c-text-muted); }
.imbuto__val { margin-left: auto; font-family: var(--font-display);
               font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.imbuto__caduta { font-size: var(--fs-xs); color: var(--c-danger); flex: none; }
.imbuto__barra {
  height: 26px; border-radius: var(--r-sm);
  background: var(--g-primary); min-width: 3px;
  display: flex; align-items: center;
  transition: width var(--t-slow);
}
.imbuto__vuoto { height: 26px; border-radius: var(--r-sm);
                 background: var(--c-surface-sunk); border: 1px dashed var(--c-border-strong); }

/* ----------------------------------------------------------------- barre */
.barre { display: grid; gap: var(--sp-3); }
.barra-riga { display: grid; gap: 4px; }
.barra-riga__capo { display: flex; align-items: baseline; gap: var(--sp-2);
                    font-size: var(--fs-sm); }
.barra-riga__nome { min-width: 0; overflow: hidden; text-overflow: ellipsis;
                    white-space: nowrap; color: var(--c-text); }
.barra-riga__meta { margin-left: auto; flex: none; font-size: var(--fs-xs);
                    color: var(--c-text-subtle); }
.barra-riga__val { flex: none; font-family: var(--font-display); font-weight: var(--fw-bold);
                   font-variant-numeric: tabular-nums; }
.barra-riga__traccia { height: 10px; background: var(--c-bg-deep);
                       border-radius: var(--r-pill); overflow: hidden; }
.barra-riga__pieno { height: 100%; border-radius: var(--r-pill);
                     background: var(--g-primary); transition: width var(--t-slow); }
.barra-riga__pieno--verde { background: var(--c-success); }
.barra-riga__pieno--ambra { background: var(--c-warning); }
.barra-riga__pieno--viola { background: #5b45a8; }
.barra-riga__pieno--ciano { background: var(--c-info); }

/* -------------------------------------------------------------- colonne */
.colonne { display: flex; align-items: flex-end; gap: var(--sp-2); height: 132px; }
.colonna { flex: 1; display: flex; flex-direction: column; justify-content: flex-end;
           align-items: center; gap: 4px; min-width: 0; }
.colonna__barra { width: 100%; max-width: 46px; border-radius: var(--r-sm) var(--r-sm) 0 0;
                  background: var(--g-primary); min-height: 2px;
                  transition: height var(--t-slow); }
.colonna__val { font-size: var(--fs-xs); font-weight: var(--fw-bold);
                font-variant-numeric: tabular-nums; }
.colonna__nome { font-size: 0.6875rem; color: var(--c-text-subtle);
                 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
                 max-width: 100%; }

/* Le tessere-indicatore dell'Observatory sono cliccabili: un numero che non si
   può aprire non aiuta a decidere (`style-priorita-dashboard`). */
.stat-card--apribile { cursor: pointer; }
.stat-card--apribile:hover .stat-value { color: var(--c-primary); }

/* ============================================== impacchettamento a colonne

   Il problema: una griglia a due campate con card di altezze diverse lascia
   sempre un buco sotto la colonna che finisce prima, e quale sia dipende dai
   dati — quindi non si può sistemare a mano.

   `columns` risolve alla radice: il browser **bilancia le altezze** distribuendo
   i blocchi, e i buchi non si formano. Il prezzo è che l'ordine di lettura
   diventa per colonna (tutta la sinistra, poi tutta la destra): accettabile per
   riquadri indipendenti come quelli di un pannello di analisi, sbagliato per un
   testo che si legge in sequenza — e per questo non è la regola generale della
   pagina ma una classe che si chiede.

   Le card usano `margin-bottom` e non `gap`: dentro un contesto multi-colonna il
   `gap` non separa i blocchi in verticale. */

.pacco { columns: 2; column-gap: var(--sp-4); }
.pacco > * {
  break-inside: avoid;
  /* `inline-block` con larghezza piena: senza, un blocco alto viene spezzato a
     metà fra due colonne nonostante `break-inside`. */
  display: inline-block; width: 100%;
  margin: 0 0 var(--sp-4);
  vertical-align: top;
}
.pacco--3 { columns: 3; }
@media (max-width: 1080px) { .pacco, .pacco--3 { columns: 2; } }
@media (max-width: 720px)  { .pacco, .pacco--3 { columns: 1; } }

/* ============================================================ notifiche

   Righe con glifo tinto per tipo, ora a destra, e il testo in evidenza solo se
   non lette. La versione precedente era un elenco piatto di righe identiche con
   la data ripetuta trenta volte: con dieci notifiche dello stesso tipo non si
   distingueva nulla, e la data su ogni riga era rumore.                       */

.notifiche { display: grid; }
.notifica {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--c-border);
  color: inherit; text-decoration: none;
  transition: background var(--t-fast);
}
.notifica:first-child { border-top: none; }
a.notifica:hover { background: var(--c-primary-tint); text-decoration: none; color: inherit; }
/* Non letta: fondo tinto E testo in grassetto. Il solo fondo non basta a chi non
   distingue quel contrasto (`vinc-accessibilita`). */
.notifica--nuova { background: var(--c-primary-soft); }
.notifica--nuova .notifica__testo { font-weight: var(--fw-semibold); }
.notifica--nuova::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--c-primary);
}
.notifica { position: relative; }
.notifica .stat-icon { width: 32px; height: 32px; font-size: 1.2rem; margin-top: 2px; }
.notifica__corpo { min-width: 0; flex: 1; display: grid; gap: 2px; }
.notifica__capo { display: flex; align-items: baseline; gap: var(--sp-2); }
.notifica__tipo { font-size: var(--fs-xs); font-weight: var(--fw-semibold);
                  text-transform: uppercase; letter-spacing: 0.07em;
                  color: var(--c-text-subtle); }
.notifica__ora { margin-left: auto; font-size: var(--fs-xs); color: var(--c-text-subtle);
                 font-variant-numeric: tabular-nums; flex: none; }
.notifica__testo { font-size: var(--fs-sm); }
.notifica__vai { color: var(--c-text-subtle); font-size: var(--fs-md); line-height: 1;
                 align-self: center; flex: none; }
a.notifica:hover .notifica__vai { color: var(--c-primary); }

/* Sotto i 480px la ciambella e la sua legenda si impilano: affiancate, la
   legenda resterebbe larga 130px e i nomi delle voci sparirebbero nei puntini. */
@media (max-width: 480px) {
  .ciambella { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
  .ciambella__legenda { width: 100%; }
}

/* ================================================================== tab

   Le tab di contenuto (workspace di progetto, console di gestione). Erano
   `.btn--ghost` con una classe `is-active` che **nessuna regola stilava**: la
   tab aperta era indistinguibile dalle altre, e l'unico modo di sapere dove si
   era era guardare il contenuto sotto.

   Sottolineatura e non pillola piena: sono tab di navigazione dentro una
   pagina, e la sottolineatura le lega al pannello che sta sotto — una pillola
   colorata le farebbe leggere come filtri, che è un'altra cosa e sta a
   sinistra. La riga di base sul contenitore dà alla barra un appoggio: senza,
   la sottolineatura della tab attiva galleggia nel vuoto.

   Lo stato non è solo colore: la tab attiva è anche in **semibold** e ha la
   barra sotto (`vinc-accessibilita`). */

.tabs {
  display: flex; align-items: stretch; gap: var(--sp-1);
  border-bottom: 1px solid var(--c-border);
  margin: var(--sp-5) 0;
  overflow-x: auto;                 /* otto tab su un tablet devono scorrere */
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tabs > button, .tabs > a {
  appearance: none; background: none; border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;              /* la barra copre quella del contenitore */
  padding: var(--sp-3) var(--sp-4);
  font: inherit; font-size: var(--fs-sm); font-weight: var(--fw-medium);
  color: var(--c-text-muted); cursor: pointer; white-space: nowrap;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color var(--t-fast), background var(--t-fast),
              border-color var(--t-fast);
}
.tabs > button:hover, .tabs > a:hover {
  color: var(--c-text); background: var(--c-surface-sunk); text-decoration: none;
}
.tabs > .is-active, .tabs > [aria-selected="true"] {
  color: var(--c-primary); font-weight: var(--fw-bold);
  border-bottom-color: var(--c-primary);
  background: none;
}
.tabs > .is-active:hover { background: none; }
/* Un contatore dentro la tab (es. «Feedback 3») */
.tabs .chip { margin-left: var(--sp-2); }

@media (max-width: 720px) {
  .tabs > button, .tabs > a { padding: var(--sp-3) var(--sp-3); }
}

/* ======================================================= il proprio profilo

   Nella barra in alto il profilo era un `nav-link` col nome dell'utente: aveva
   la stessa forma delle sezioni, e leggendo la barra sembrava esserci una voce
   che cambia nome a ogni persona (Giulia, Anna…). Un pallino con le iniziali si
   riconosce per convenzione, e non compete con la navigazione.

   Il nome resta raggiungibile: sta nel `title` e in un testo per gli screen
   reader, così l'informazione non si perde per nessuno. */
.nav-utente {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; margin-left: var(--sp-2);
  border-radius: 50%;
  background: var(--c-surface-sunk);
  box-shadow: inset 0 0 0 1px var(--c-border);
  color: var(--c-text-muted); text-decoration: none;
  transition: background var(--t-fast), box-shadow var(--t-fast),
              color var(--t-fast);
}
.nav-utente:hover, .nav-utente:focus-visible {
  background: var(--c-primary-soft); text-decoration: none;
  color: var(--c-primary-deep);
}
.nav-utente.is-active {
  background: var(--c-primary); color: var(--c-text-invert);
  box-shadow: inset 0 0 0 1px var(--c-primary-deep);
}
.nav-utente__segno {
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: 0.6875rem; letter-spacing: 0.01em; line-height: 1;
}
/* Nel menu a tendina del telefono il pallino da solo non si capisce: là torna
   una riga con l'etichetta accanto. */
@media (max-width: 720px) {
  .nav-utente {
    width: auto; height: auto; margin: 0; border-radius: var(--r-sm);
    grid-auto-flow: column; justify-content: start; gap: var(--sp-2);
    padding: var(--sp-3); background: none; box-shadow: none;
    color: var(--c-text-muted);
  }
  .nav-utente::after { content: "Il mio profilo"; font-size: var(--fs-sm);
                       font-weight: var(--fw-medium); }
  .nav-utente__segno {
    display: grid; place-items: center; width: 26px; height: 26px;
    border-radius: 50%; background: var(--c-surface-sunk);
  }
}



/* ==================================================== striscia delle fasi

   Nove fasi affiancate, scorrevoli. Portano DUE informazioni che prima si
   confondevano: quale stai guardando (risponde al clic) e dove è arrivato il
   progetto. La prima è lo stato pieno, la seconda un cartellino — perché possono
   non coincidere: guardare avanti nel Journey è previsto, non un errore.

   Più il pallino di stato, che dice se la fase è chiusa, aperta o ancora da
   iniziare: in una striscia di nove, senza quello, si legge solo l'ordine. */

.fasi-guscio { padding: var(--sp-3); overflow: hidden; }
.fasi {
  display: flex; gap: var(--sp-2); overflow-x: auto;
  padding: 2px;             /* spazio per l'anello di fuoco */
  scroll-snap-type: x proximity;
}
.fasi::-webkit-scrollbar { height: 8px; }
.fasi::-webkit-scrollbar-thumb { background: var(--c-border-strong); border-radius: 4px; }

.fase {
  flex: none; scroll-snap-align: start;
  display: grid; gap: 4px; align-content: start;
  min-width: 148px; max-width: 200px;
  padding: var(--sp-2) var(--sp-3);
  text-align: left; cursor: pointer;
  background: var(--c-surface); color: var(--c-text);
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  font: inherit;
  transition: background var(--t-fast), border-color var(--t-fast),
              box-shadow var(--t-fast), color var(--t-fast);
}
.fase:hover { border-color: var(--c-border-strong); box-shadow: var(--sh-xs); }

.fase__capo { display: flex; align-items: center; gap: var(--sp-2); }
.fase__n { font-family: var(--font-display); font-weight: var(--fw-bold);
           font-size: var(--fs-xs); color: var(--c-text-subtle);
           font-variant-numeric: tabular-nums; }
.fase__punto { width: 7px; height: 7px; border-radius: 50%; flex: none;
               background: var(--c-border-strong); }
.fase__punto--completata { background: var(--c-success); }
.fase__punto--in_corso { background: var(--c-accent); }
.fase__punto--in_revisione { background: var(--c-warning); }
/* «in corso» è un cartellino, non un colore: il colore lo usa già la selezione */
.fase__ora {
  margin-left: auto; font-size: 0.625rem; font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--c-accent);
}
.fase__titolo {
  font-size: var(--fs-sm); font-weight: var(--fw-medium); line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ------------------------------------------------ LA LINEA DEL PERCORSO
   `feat-journey-engine`, revisione 2. Il cliente disegna un percorso come una
   linea orizzontale con le tappe alternate sopra e sotto (`Flow Example.jpeg`),
   e nello stesso incontro ha chiesto la stessa cosa guardando questa striscia:
   «potremmo rendere quel flusso una sorta di schema a blocchi, ti vai a
   costruire, metti una dopo l'altra le fasi di quel progetto».

   Quindi: una spina continua, le tappe alternate, un raccordo con la punta verso
   la linea. Cambia la FORMA, non la logica: la fase che guardi resta piena e
   quella in corso resta col cartellino — la distinzione che la revisione 1 ha
   introdotto e che non va perduta.

   Sotto i 760px si torna alla striscia semplice: l'alternanza ha bisogno di
   larghezza, e su un telefono produrrebbe una scala invece di una linea. */
/* Le righe della linea. Con nove o dieci fasi una riga sola non ci sta, e fino
   alla revisione 5 il resto si raggiungeva **scorrendo in orizzontale**: il
   percorso, che è tutto il senso di questo disegno, non si vedeva mai intero.
   Ora la linea va a capo, come un testo, e il numero di tappe per riga lo
   calcola il JS dalla larghezza disponibile (`--n`). */
.fasi-righe { display: grid; gap: var(--sp-2); }

.fasi--linea {
  position: relative;
  align-items: center;
  gap: var(--sp-2);
  padding: 0;
  overflow: visible;        /* niente scorrimento: le righe vanno a capo */
  /* Un solo spessore per tutto il disegno — spina, raccordi e bordo dei punti.
     Averne due (la spina a 3px, i raccordi a 2px) faceva sembrare il tratto
     sbagliato invece che gerarchico. */
  --spessore-linea: 2px;
  /* La larghezza di una tappa, dichiarata una volta: la usano sia le tappe sia
     la spina, che deve fermarsi esattamente su un punto. Due formule scritte
     due volte prima o poi divergono. */
  --tappa: calc((100% - (var(--n, 6) - 1) * var(--sp-2)) / var(--n, 6));
  /* Altezza FISSA: due tappe da due righe piu' i due raccordi. La geometria non
     puo' dipendere dall'altezza delle tappe, altrimenti una tappa con il titolo
     su due righe sposta la spina e le altre le finiscono addosso. Si e' visto. */
  min-height: 11.5rem;
}
.fasi--linea .fase {
  position: relative;
  /* Larghezza uguale per TUTTE le tappe, anche nell'ultima riga se è parziale:
     il numero per riga è lo stesso ovunque (`--n`), quindi le colonne di righe
     diverse restano incolonnate. */
  flex: 0 0 var(--tappa);
  min-width: 0; max-width: none;
  /* `center` piu' una traslazione di meta' se stessa: cosi' il bordo della tappa
     resta a 1.4rem dalla spina QUALUNQUE sia la sua altezza. */
  align-self: center;
  transform: translateY(calc(-50% - 1.4rem));
}
/* La spina: **una sola linea per riga**, non un pezzo per tappa.

   I pezzi per tappa erano il modo ovvio di far finire la linea dove finiscono
   le tappe nell'ultima riga, ma a schermo si vedevano le giunzioni: ogni pezzo
   partiva dal bordo della sua tappa e i mezzi pixel si sommavano diversamente
   sopra e sotto la spina, quindi la linea sembrava di spessore variabile.

   Con una linea sola per riga l'arrotondamento è uno solo, e il punto dove
   fermarla si calcola: con `--n` tappe per riga e `--k` tappe in QUESTA riga,
   lo spazio da lasciare a destra è `(n - k) / n` della larghezza più il
   divario. Nessuna giunzione, nessuna misura presa a occhio.

   Tinta piena e non un gradiente: col gradiente la metà sinistra sbiadiva sul
   bianco e la linea non si vedeva. */
.fasi--linea::before,
.fasi--linea::after {
  content: ""; position: absolute; z-index: 0;
  /* Da punto a punto: la linea comincia sul primo punto della riga e finisce
     sull'ultimo, invece di correre fino ai bordi del riquadro. Correndo fino ai
     bordi finiva nel vuoto dopo l'ultima fase, e il disegno sembrava troncato
     invece che concluso. */
  left: calc(var(--tappa) / 2);
  right: calc((var(--n, 6) - var(--k, var(--n, 6))) * (var(--tappa) + var(--sp-2))
              + var(--tappa) / 2);
  top: 50%; height: var(--spessore-linea); margin-top: calc(var(--spessore-linea) / -2);
  background: var(--c-border-strong); border-radius: 1px;
}
/* Il tratto già percorso, sopra quello grigio: la linea dice a colpo d'occhio
   fin dove si è arrivati, che è la domanda per cui si guarda un percorso.
   `--c` sono le tappe concluse in QUESTA riga; senza, non si disegna. */
.fasi--linea::after {
  right: calc((var(--n, 6) - var(--c, 0)) * (var(--tappa) + var(--sp-2))
              + var(--tappa) / 2);
  background: var(--c-success);
}
/* Con zero tappe concluse il bordo destro cade oltre quello sinistro e la
   larghezza si azzera da sé: non serve nasconderlo con un selettore che
   frughi nell'attributo `style`. */
.fasi--linea .fase:nth-child(even) {
  transform: translateY(calc(50% + 1.4rem));
}
/* il raccordo: dal bordo della tappa fino alla spina, dello stesso spessore */
.fasi--linea .fase::after {
  content: ""; position: absolute; left: 50%;
  margin-left: calc(var(--spessore-linea) / -2);
  width: var(--spessore-linea); height: 1.4rem;
  background: var(--c-border-strong);
  top: 100%;
}
.fasi--linea .fase:nth-child(even)::after { top: auto; bottom: 100%; }
/* il punto SULLA spina */
.fasi--linea .fase::before {
  content: ""; position: absolute; left: 50%; margin-left: -5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--c-surface);
  border: var(--spessore-linea) solid var(--c-border-strong);
  top: calc(100% + 1.4rem); margin-top: -5px; z-index: 1;
}
.fasi--linea .fase:nth-child(even)::before {
  top: auto; bottom: calc(100% + 1.4rem); margin-top: 0; margin-bottom: -5px;
}
/* La tappa selezionata segna anche il suo punto sulla spina: senza, la linea non
   direbbe DOVE sei, e la linea e' tutto il senso di questo disegno. */
.fasi--linea .fase.is-scelta::after { background: var(--c-primary); }
.fasi--linea .fase.is-scelta::before {
  background: var(--c-primary); border-color: var(--c-primary);
  box-shadow: 0 0 0 4px var(--c-primary-tint);
}
/* Completata: il punto pieno di verde. Lo stato si legge sulla linea senza
   aprire la tappa. */
.fasi--linea .fase[data-stato="completata"]::before {
  background: var(--c-success); border-color: var(--c-success);
}
/* In corso: cambia il COLORE, non lo spessore. Un punto con il bordo più spesso
   degli altri si legge come un tratto sbagliato, non come uno stato. */
.fasi--linea .fase[data-stato="in_corso"]::before {
  border-color: var(--c-accent);
  box-shadow: 0 0 0 3px var(--c-accent-soft);
}
/* Il titolo su due righe al massimo: e' la condizione perche' l'altezza fissa
   del contenitore basti. */
.fasi--linea .fase__titolo { -webkit-line-clamp: 2; }

@media (max-width: 760px) {
  /* Sotto i 760px l'alternanza sopra/sotto non ha larghezza per esistere e
     produrrebbe una scala invece di una linea: si torna all'elenco semplice,
     che qui **va a capo** invece di scorrere. */
  .fasi--linea { padding: 2px; gap: var(--sp-2); align-items: stretch;
                 min-height: 0; flex-wrap: wrap; }
  .fasi--linea .fase,
  .fasi--linea .fase:nth-child(even) { transform: none; align-self: auto;
                                       flex: 1 1 140px; }
  .fasi--linea::before,
  .fasi--linea .fase::before,
  .fasi--linea .fase::after { display: none; }
}

/* Quella che stai guardando: piena. È lo stato che risponde al clic, quindi è
   quello che deve essere impossibile non vedere. */
.fase.is-scelta {
  background: var(--c-primary); background-image: var(--g-primary);
  border-color: transparent; color: var(--c-text-invert);
  box-shadow: var(--sh-cta);
}
.fase.is-scelta .fase__n { color: rgba(255, 255, 255, 0.7); }
.fase.is-scelta .fase__titolo { font-weight: var(--fw-semibold); }
.fase.is-scelta .fase__ora { color: #b9e6fa; }
.fase.is-scelta .fase__punto { box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35); }


/* ============================== i blocchi della fase

   La fase mostra tre cose diverse — il lavoro da produrre, come si lavora, i
   compiti — e la gerarchia deve VEDERSI, non dedursi (revisione 10). Ma non a
   colpi di pannelli grigi impilati (revisione 12: «lo sfondo grigio non e'
   bellissimo»): le sezioni respirano sul bianco della card, separate da un
   filo, e il titolo porta il trattino del logo. Tre livelli, tre forme:
     1. la sezione: aria, un filo di separazione e il maiuscoletto firmato;
     2. il gruppo dentro la sezione: una card bordata con un nome semibold e
        il suo comando a destra;
     3. le righe: dentro il gruppo, separate da un filo. */
.fase-blocco { margin-top: var(--sp-5); }
.fase-blocco:first-of-type { margin-top: var(--sp-4); }
.fase-blocco + .fase-blocco {
  border-top: 1px solid var(--c-border);
  padding-top: var(--sp-4);
}
.fase-blocco__titolo {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--c-text-muted); margin: 0 0 var(--sp-3);
}
/* il trattino dei tre colori del logo: e' lui a dire «qui comincia una
   sezione», al posto del pannello grigio */
.fase-blocco__titolo::before {
  content: ""; width: 18px; height: 3px; border-radius: 2px;
  background: var(--g-logo); flex: none;
}
/* i gruppi dentro una sezione: card bordate, stessa forma, penne diverse */
.fase-compiti {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  padding: .6rem .9rem .5rem;
  box-shadow: var(--sh-xs);
}
.fase-compiti + .fase-compiti { margin-top: var(--sp-2); }
.fase-compiti__testa {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); min-height: 30px;
}
.fase-compiti__nome { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.compito-riga { padding: .5rem 0; }
.compito-riga + .compito-riga { border-top: 1px solid var(--c-border); }
.fase-vuoto {
  font-size: var(--fs-sm); color: var(--c-text-subtle);
  font-style: italic; margin: .35rem 0 .2rem;
}

/* La catena dei passi: ogni cosa da produrre e' un anello con lo stato, e
   l'ultimo anello e' la consegna/approvazione. La linea verticale fra le
   icone dice l'ordine e la dipendenza senza spiegarli a parole. */
.lista-passi { display: grid; }
.passo {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: .55rem 0; position: relative;
}
.passo + .passo::before {
  content: ''; position: absolute; left: 13px; top: -12px;
  width: 2px; height: 20px; background: var(--c-border-strong);
}
.passo__icona {
  width: 28px; height: 28px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-size: 13px;
  font-weight: var(--fw-bold); position: relative; z-index: 1;
}
.passo__icona--fatto { background: var(--c-success); color: #fff; }
.passo__icona--attesa { background: var(--t-ambra); color: var(--t-ambra-fg); }
.passo__icona--tocca { background: var(--c-accent-soft); color: var(--c-accent);
                       border: 2px solid var(--c-accent); }
.passo__icona--vuoto { background: var(--c-surface);
                       border: 2px solid var(--c-border-strong); }
.passo__corpo { flex: 1; min-width: 0; }
.passo__titolo { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.passo__sotto { font-size: var(--fs-xs); color: var(--c-text-subtle); }
.passo__chi { flex: none; }
.passo__azione { flex: none; display: flex; gap: var(--sp-2); }
/* l'ultimo anello si stacca: e' il traguardo della catena, non un altro
   documento — un filo piu' d'aria e la riga di confine sopra */
.passo--finale { margin-top: .35rem; padding-top: .8rem;
                 border-top: 1px dashed var(--c-border-strong); }
.passo--finale::before { display: none; }
.passo--finale .passo__titolo { font-size: var(--fs-md); }
