/* Sito Simply Future — cimentación heredada de dendoo.it.
   Tokens semánticos + .on-dark, escala tipográfica única, layout, botones,
   header, footer y micro-interacciones. Los componentes de página se escriben
   debajo, contra los tokens: ningún componente escribe un color fijo.

   Los VALORES (rampa de color, fuentes) están todavía calibrados para dendoo:
   se recalibran desde la página de Framer. La ESTRUCTURA no se toca. */

:root {
  /* --- rampa blu: campionata dal master --------------------------------
     I gradini escono uno a uno da gradient.-2.png, letti alla luminosità
     che ogni token portava già: cambia la tinta, non la chiarezza, quindi
     nessun contrasto si muove. Scegliere un gradino, non inventare una
     tinta.

     Il master non ha una tinta sola: ha un arco. 196-200° in HSL sulle luci,
     213-217° sulle ombre, e la rotazione va con la luminosità. Le due rampe
     di prima quell'arco l'avevano schiacciato su un angolo unico, ognuna
     prendendo un capo e stendendolo su tutto. La 196° teneva la tinta delle
     luci e mandava le ombre nel teal — è il bagliore che si vedeva. La 213°
     ha preso quella delle ombre e ha spostato l'errore in cima: da --blue-600
     in su ogni gradino stava 7-16° oltre il master, e --mist-200 era il caso
     peggiore. Qui ogni gradino porta la tinta che il master ha alla sua
     altezza, e nient'altro.

     Dal master viene anche il croma, che nella metà scura era del 15-25%
     sopra il vero: --blue-700 stava a 0.051 contro 0.043.

     Dieci gradini: --blue-850 e --blue-600 servono al gradiente, che con
     otto lasciava un vuoto di trenta L* fra --blue-800 e --blue-500 — era
     lì che si vedeva la banda. */
  --blue-950: #04070c;
  --blue-950-rgb: 4, 7, 12;
  --blue-900: #080e15;
  --blue-850: #0e1720;
  --blue-800: #172532;
  --blue-700: #283d50;
  /* Accento sul chiaro. Non è --blue-500: quel gradino cade a L* 63 e su
     bianco tiene 2.88:1, illeggibile. Questo fa 6.13:1 e chiude la falla del
     4.44:1 di due rampe fa, che il commento stesso dava per insufficiente
     sul testo corrente. */
  --blue-600: #49657a;
  --blue-500: #819cad;
  --blue-400: #abc2ce;
  --blue-300: #cbdce3;
  --blue-200: #dbe7ed;

  /* Foschia: i fondi chiari. I primi tre stanno ancora dentro il master e
     sono campionati come tutto il resto. --mist-100 no: a okL 0.966 sta sopra
     il punto più chiaro del master (0.933), perché non è una fermata del
     gradiente ma il fondo di pagina, e gli serve stare più in alto del
     chiaro da cui l'hero riparte. La sua tinta è l'arco del master
     prolungato di poco oltre il capo; a quel croma la rotazione non arriva a
     un livello su otto bit, e infatti il valore si muove di un digit. */
  --mist-400: #d4e1e9;
  --mist-300: #d5e3ea;
  --mist-200: #dfeaee;
  --mist-100: #eef5f9;

  /* --- turchese: adesso è la marca ------------------------------------
     Sta sui dettagli che segnalano uno stato — risposta scelta, tappa
     conclusa, esito positivo. Finché l'azione era blu, questo era l'unica
     tinta fuori dalla rampa e la regola era di non usarlo come accento
     generale: due sistemi accostati si sarebbero letti come un errore.

     Adesso l'azione è ciano e quella regola si rovescia. Il vecchio #39cdf6
     stava a 221° con croma 0.132; --brand-2 sta a 214° con 0.104: sette gradi
     e un filo di croma di distanza, cioè due ciani quasi uguali accanto. È
     esattamente il difetto che il commento di prima descriveva. Quindi il
     token resta — venti punti del sito lo chiamano — ma punta alla marca.

     Il contrasto non si muove: sui fondi scuri dove vive faceva 10.80:1 e
     8.04:1, adesso fa 10.93:1 e 8.13:1. */
  --teal-500: var(--brand-2);

  /* --- neutra e azione: le rampe del sito -----------------------------
     Dalla proposta ColorBox, adottate per tutto il sito il 4 settembre 2026:
     fondi, testi, fili, pulsanti, schede. La blu qui sopra non è sparita —
     resta la rampa dei gradienti, perché è campionata dal master e la
     neutra non scende fino al suo nero (L* 6 contro 2): l'hero, la FAQ e la
     chiusura, che continuano quel gradiente in tinta piatta, restano sulla
     blu. Gli indici sono quelli dello strumento, dal chiaro allo scuro, come
     per le rampe di stato: non dicono la chiarezza, la dice il gradino. */
  --steel-0: #f7f4f2;
  --steel-1: #e8e7e6;
  --steel-2: #d8d8d8;
  --steel-3: #c8c8c8;
  --steel-4: #b7b7b7;
  --steel-5: #a5a4a3;
  --steel-6: #93918f;
  --steel-7: #7f7b7a;
  --steel-8: #6a6664;
  --steel-9: #56504f;
  --steel-10: #403a38;
  --steel-11: #2a2524;
  --steel-12: #151110;

  /* I nomi di prima restano come alias: --steel-* è il nome che la rampa
     porta nell'app, --neutral-* quello con cui il sito la chiama in 112
     punti. Un valore solo, due nomi, nessun componente da riscrivere. */
  --neutral-0: var(--steel-0);
  --neutral-1: var(--steel-1);
  --neutral-2: var(--steel-2);
  --neutral-3: var(--steel-3);
  --neutral-4: var(--steel-4);
  --neutral-5: var(--steel-5);
  --neutral-6: var(--steel-6);
  --neutral-7: var(--steel-7);
  --neutral-8: var(--steel-8);
  --neutral-9: var(--steel-9);
  --neutral-10: var(--steel-10);
  --neutral-11: var(--steel-11);
  --neutral-12: var(--steel-12);

  /* --- azione: il ciano ------------------------------------------------
     La rampa dell'azione non è più blu. Il ciano stacca dalla steel, che il
     blu di prima non faceva: erano due blu accanto, e l'accento non si
     leggeva come tale.

     Segna solo ciò che si può premere o che ha il fuoco. Il decorativo —
     icone, occhielli, marcatori, avatar — sta sulla steel.

     I gradini 3 e 4, il ciano vivo, tengono solo sul bianco: su --steel-1 o
     più scuro cadono sotto il 3:1. Su superficie tinta si passa da
     --accent. */
  --brand-0: #ecf4fd;
  --brand-1: #c0daf7;
  --brand-2: #92c0f1;
  --brand-3: #6da5e0;
  --brand-4: #4e8bcd;
  --brand-5: #3874b6;
  --brand-6: #275d97;
  --brand-7: #1b497d;
  --brand-8: #133662;
  --brand-9: #032550;

  /* --- inchiostro: sei gradini, solo per il testo ----------------------
     Rampa nuova. La steel fa le superfici, i bordi e i separatori; il testo
     esce di qui e da nessun'altra parte. Sei gradini dal velato al pieno:
     0-2 servono allo scuro, 3-5 al chiaro. */
  --ink-0: #a3a2a1;
  --ink-1: #8d8b89;
  --ink-2: #767371;
  --ink-3: #5e5958;
  --ink-4: #47413f;
  --ink-5: #161211;

  --ink: var(--ink-5);
  --ink-deep: var(--ink-5);
  --paper: var(--neutral-0);

  /* Canali per le trasparenze. rgba() non legge un token esadecimale e
     color-mix() non vale il rischio (vedi .shimmer): i veli d'inchiostro, le
     luci sullo scuro e il vetro si scrivono rgba(var(--ink-rgb), α), così il
     colore viene dalla rampa e nel componente resta solo l'opacità. Sono i
     canali di neutral-12, neutral-11, neutral-6, neutral-0 e del turchese,
     scritti per esteso perché è l'unico modo di passarli a rgba(). */
  --ink-rgb: 22, 18, 17;
  --night-rgb: 17, 41, 56;
  --mid-rgb: 113, 152, 169;
  --paper-rgb: 247, 244, 242;
  --surface-rgb: 255, 255, 255;
  --teal-rgb: 97, 205, 229;

  /* --- stati: tre rampe dalla proposta ColorBox ------------------------
     Adottate il 4 settembre 2026, e solo loro: della stessa proposta non è
     entrata la portante — meno profonda della blu, si ferma a L* 6 dove
     la blu arriva a 2, e ai gradienti non serve — e nemmeno l'azione.
     Gli indici sono quelli dello strumento, 0-9 dal chiaro allo scuro, e non
     dicono la chiarezza: --warning-3 sta a L* 82 dove --danger-3 sta a 67.
     Per questo nei componenti si passa dai semantici (--ok, --warn, --error
     e le loro varianti), mai dal gradino. */
  --success-0: #d9fffc;
  --success-1: #76e9e1;
  --success-2: #24d5c9;
  --success-3: #0dbfb1;
  --success-4: #00a99b;
  --success-5: #009487;
  --success-6: #007e72;
  --success-7: #00675d;
  --success-8: #004f47;
  --success-9: #003630;

  --warning-0: #fff3d3;
  --warning-1: #ffe4a6;
  --warning-2: #ffd17b;
  --warning-3: #ffc056;
  --warning-4: #fea33a;
  --warning-5: #fd8824;
  --warning-6: #f96f14;
  --warning-7: #e65509;
  --warning-8: #c83e03;
  --warning-9: #b02f00;

  --danger-0: #fff1f2;
  --danger-1: #ffc8cc;
  --danger-2: #ff9ea6;
  --danger-3: #ff7785;
  --danger-4: #ff5969;
  --danger-5: #eb3856;
  --danger-6: #d32149;
  --danger-7: #b71140;
  --danger-8: #980837;
  --danger-9: #76022d;

  /* Corallo dei grafici: campiture larghe, mai testo. Non è il rosso di
     segnalazione — quello è --error, più sotto. */
  --bad: #ff5f56;

  /* --- gradienti di marca ---------------------------------------------
     La verticale è il fondo principale: scende dal nero al chiaro passando
     per tutta la rampa, e le sue fermate sono i token qui sopra, non tinte
     a parte. Le altre due sono la foschia chiara e l'alone sfocato.

     Dal master vengono i colori, non le fermate: quelle stanno dove le porta
     la luminosità. Il perché è scritto sulla rovesciata, qui sotto. */
  --grad-sky: linear-gradient(
    180deg,
    var(--blue-950) 0%,
    var(--blue-900) 2%,
    var(--blue-850) 4.5%,
    var(--blue-800) 9.6%,
    var(--blue-700) 17.3%,
    var(--blue-600) 29.5%,
    var(--blue-500) 45.6%,
    var(--blue-400) 55.8%,
    var(--blue-300) 62.8%,
    var(--blue-200) 66.1%,
    var(--mist-100) 70%
  );
  /* La verticale rovesciata: apre chiara e chiude sul nero. È il fondo
     dell'hero della home. La discesa è compressa in alto — sotto il 30% il
     fondo è già scuro, perché è lì che comincia il testo bianco.

     Le fermate non sono a intervalli pari: ognuna sta dove la porta la sua
     luminosità, così la discesa perde la stessa quantità di L* per pixel dal
     principio alla fine.

     Questa regola *non* è la curva del master, e la differenza è voluta. Il
     master lineare non è: brucia quasi metà della sua gamma in un quarto solo
     e poi tira una coda scura lunga. Ricalcarlo si è provato, e su una
     superficie di questa misura a otto bit per canale non regge: i tratti
     lenti della sua curva allargano le bande da 4 a 9 pixel e le bande
     visibili passano da 2 a 7. Il master quel problema non ce l'ha perché è
     un'immagine e si porta dietro la propria grana; un gradiente dichiarato
     in CSS ha solo i livelli che gli dà il canale. Quindi dal master vengono
     i colori — quelli sì, uno a uno — e la ripartizione resta quella che non
     fa scalini.

     Nemmeno ripartire per numero di livelli a 8 bit conviene, che pure
     porterebbe la banda peggiore a 3 pixel: sposta la discesa più in basso e
     il titolo, sulle finestre corte, scende a 2.64:1 — sotto il 3:1 dei testi
     grandi. La ripartizione per luminosità è il punto in cui le due cose
     stanno insieme: banda peggiore 4 pixel, titolo da 3.03:1 a 4.92:1.

     La discesa chiude al 70%, non al 50: compressa in cima soffocava il
     chiaro. Oltre non si può allungare — il titolo comincia verso il 36%
     dell'altezza e lì il bianco tiene 4.92:1; più giù scenderebbe sotto il
     3:1 dei testi grandi.

     Questa è la versione di base, in sRGB. Più sotto un `@supports` la
     ridichiara in oklab dove il browser lo consente. Non si può mettere
     `in oklab` direttamente qui: se il browser non lo capisce il token resta
     invalido *al momento dell'uso*, e l'hero si ritroverebbe senza fondo —
     non con un fondo peggiore. */
  --grad-sky-invert: linear-gradient(
    180deg,
    var(--mist-100) 0%,
    var(--blue-200) 3.9%,
    var(--blue-300) 7.2%,
    var(--blue-400) 14.2%,
    var(--blue-500) 24.4%,
    var(--blue-600) 40.5%,
    var(--blue-700) 52.7%,
    var(--blue-800) 60.4%,
    var(--blue-850) 65.5%,
    var(--blue-900) 68%,
    var(--blue-950) 70%,
    var(--blue-950) 100%
  );

  /* Grana. Sta in un token perché serve identica in due posti — sull'hero e
     sul blocco che lo segue — e due copie che divergono lascerebbero una
     cucitura visibile al confine. Serve anche a un secondo scopo: il rumore
     spezza le bande che un gradiente lungo produce a 8 bit per canale. */
  /* Il rumore non è decorazione: è il dither che spezza le bande di un
     gradiente a 8 bit. Troppo basso e smette di farlo. Sul chiaro non entra
     comunque — a tenerlo fuori è la maschera su .hero::after, non questo
     valore — quindi qui si può dargli corpo senza sporcare il bianco. */
  --grain-opacity: 0.3;
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
  /* Foco dal basso, alla maniera di Nothing. La differenza con --grad-sky
     non sono i colori — sono gli stessi — ma la curva: le fermate seguono la
     caduta della luce, che va con l'inverso del quadrato della distanza.
     Il primo quarto della scala consuma il 6% del raggio invece del 24%, così
     il nucleo resta acceso e la discesa si allunga verso il bordo. È quello a
     leggersi come luce invece che come sfumatura.

     Attenzione alla coda: da --blue-900 a --blue-950 restano trentasei
     scalini interi da spendere su quasi cinquecento pixel, cioè bande da
     tredici. In CSS quella coda si vede sempre; per questo Nothing la
     immagine se la cuoce invece di dichiararla. Va usata con `--grain-lift`
     sopra, che somma invece di moltiplicare e quindi sul quasi-nero esiste
     ancora. */
  --grad-glow: radial-gradient(
    125% 78% at 50% 104%,
    var(--mist-100) 0%,
    var(--blue-200) 1.6%,
    var(--blue-300) 2.6%,
    var(--blue-400) 4.4%,
    var(--blue-500) 8.1%,
    var(--blue-600) 16.4%,
    var(--blue-700) 24.6%,
    var(--blue-800) 32.4%,
    var(--blue-850) 39.2%,
    var(--blue-900) 44.6%,
    var(--blue-950) 100%
  );

  /* La discesa di /compliance-intelligence: dal nero al bianco pieno. È la
     terza faccia della stessa rampa — --grad-sky scende sulla foschia,
     --grad-sky-invert sale dal chiaro al nero, questa chiude su #ffffff e non
     su --mist-100. È la ragione per cui la pagina si legge più bianca delle
     altre: sotto la rampa non c'è velatura, c'è bianco.

     La discesa è lineare in L* fino a L* 86 — stessa uniformità di --grad-sky,
     stessa quantità di chiarezza persa a ogni pixel — e da lì entra nel bianco
     con una coda quadratica invece che di colpo.

     La coda serve perché la rampa finisce dentro una pagina bianca. Arrivando
     a velocità costante, l'ultimo pixel di sfumatura sta a 0.23 L* dal fondo e
     il successivo è fondo: non c'è gradino misurabile, ma la rampa si stacca
     lo stesso e si legge come una fascia appoggiata sopra invece che come una
     luce che si spegne. Con la coda l'ultimo tratto scende a 0.056 L* per
     pixel, un quarto del ritmo del corpo, e il punto in cui la rampa smette
     non si trova più.

     Le fermate non sono quindi proporzionali a L* fino in fondo, ma lo sono
     dove conta: nel corpo. Comprimere invece il corpo — provato, --blue-600
     spostato al 62%, all'80%, all'84% — si vede eccome: la discesa perde
     l'uniformità e il fondo passa quasi tutta la sua altezza nei gradini
     centrali, i meno carichi della scala, e diventa slavato.

     (Il grano non c'entra col colore: spegnendolo il croma si muove di due
     punti su cento e la luminosità di uno. Misurato.) */

  --grad-ci: linear-gradient(
    180deg,
    var(--blue-950) 0.0%,
    var(--blue-900) 1.66%,
    var(--blue-850) 4.57%,
    var(--blue-800) 10.14%,
    var(--blue-700) 19.2%,
    var(--blue-600) 32.92%,
    var(--blue-500) 50.8%,
    var(--blue-400) 62.6%,
    var(--blue-300) 70.76%,
    var(--blue-200) 75.81%,
    var(--mist-100) 84.17%,
    #ffffff 100%
  );

  --grad-mist: linear-gradient(135deg, var(--mist-100) 0%, var(--mist-200) 55%, var(--mist-300) 100%);
  --grad-haze:
    radial-gradient(80% 60% at 26% 0%, rgba(203, 220, 227, 0.85), transparent 64%),
    linear-gradient(170deg, var(--blue-700) 0%, var(--blue-800) 45%, var(--blue-900) 100%);

  /* --- token semantici: il tema chiaro è quello di base ---------------
     Fondo, testo e accento vengono dalla neutra e dall'azione. Il fondo di
     pagina è il primo gradino della neutra e non il bianco: il bianco è la
     superficie sollevata, ed è il salto fra i due a far leggere una scheda
     come scheda. Il testo secondario e il terziario sono gradini pieni, non
     più inchiostro velato: sul fondo tengono 10.10:1 e 5.17:1. */
  --bg: #ffffff;
  --bg-alt: #ffffff;
  --fg: #000000;                       /* 21:1 sul bianco: il nero pieno della pagina */
  --fg-muted: var(--ink-4);            /* 9.08:1 */
  --fg-faint: var(--ink-3);            /* 6.25:1 */
  --line: var(--steel-2);
  --surface: #ffffff;
  --surface-2: rgba(var(--ink-rgb), 0.045);
  --card: #f0f5f7;
  --section-grey: var(--steel-0);
  /* 6.21:1 sul fondo: regge anche sul testo corrente. Dove finisce
     dentro un paragrafo va comunque accompagnato dalla sottolineatura, così
     non è il colore da solo a portare il significato.

     Solo per ciò che si può premere o che ha il fuoco: link, tab attiva,
     bordi a fuoco, casella, segno della FAQ. L'azione porta quattro volte il
     croma della neutra, e messa su un'icona o un occhiello non segnala
     niente: fa solo un blu in più accanto agli altri. Il decorativo — icone,
     occhielli, marcatori, avatar — sta sulla neutra. */
  --accent: var(--brand-6);
  /* --- stati ------------------------------------------------------------
     Tre famiglie, tre ruoli ciascuna: il fondo tenue, il pieno per
     riempimenti e fili, il colore da testo. Il gradino non è lo stesso nelle
     tre. Warning è la rampa più chiara e il suo pieno, --warning-3, su
     bianco fa 1.6:1: è un riempimento su cui si scrive in inchiostro, non un
     inchiostro — il testo salta al gradino 8, che fa 5.1:1. Nelle altre due
     il testo sta un gradino sotto il pieno.

     I rossi stanno sui gradini chiari, non sui cupi: il pieno è il 5
     (3.66:1 sul fondo — basta a fili, bordi e icone, non a un testo) e il
     testo il 6, l'unico gradino chiaro che sul fondo passa il 4.5:1
     (4.69:1). --error non è --bad (#ff5f56): quel corallo serve ai
     grafici, in campiture larghe, e per un bordo non arriva al 3:1. A
     differenza del #c8402f di prima, dentro `.on-dark` --error viene
     ridichiarato: quello restava uguale e sullo scuro scendeva a 3.1:1. */
  --ok-sutil: var(--success-0);
  --ok: var(--success-6);
  --ok-texto: var(--success-7);
  --warn-sutil: var(--warning-0);
  --warn: var(--warning-3);
  --warn-texto: var(--warning-8);
  --error-sutil: var(--danger-0);
  --error: var(--danger-6);
  --error-texto: var(--danger-7);
  --shadow: 0 14px 34px rgba(var(--ink-rgb), 0.12);

  /* Primario in contrasto pieno col fondo, non in blu: chiaro sulle sezioni
     scure, inchiostro su quelle chiare. Sta nei token perché `.on-dark` li
     ribalta da solo, senza regole per componente. L'inchiostro del tasto è
     neutral-11 e non il 12 del testo: alla chiarezza del tasto di prima, che
     era scuro e non nero. */
  --btn-bg: var(--steel-11);
  --btn-bg-hover: var(--steel-12);
  --btn-fg: var(--steel-0);


  /* Plus Jakarta Sans per titoli e wordmark, Inter per il testo. Variable
     font dal link in head: tutti i pesi disponibili (200–800 / 100–900). */
  --font-display: "DM Sans", "Open Runde", system-ui, sans-serif;
  --font-text: "Open Runde", "DM Sans", system-ui, -apple-system, sans-serif;

  /* --- scala tipografica ---------------------------------------------
     Un gradino è corpo + interlinea + spaziatura, e ogni testo del sito ne
     prende uno: mai un corpo proprio. Se un gradino va ritoccato si ritocca
     qui e cambia ovunque insieme. I corpi grandi sono fluidi fra un telefono
     da 390px e un desktop da 1440px, scritti rem + vw così seguono anche lo
     zoom del testo; fuori da quell'intervallo si fermano ai due capi.

       gradino   390 → 1440px   ruolo
       display   41.6 → 89.6    apertura delle pagine editoriali: home,
                                prodotto, blog, team, manifesto CI
       h1        33.6 → 54.4    titolo delle pagine di servizio e di lettura
                                (get-started, articolo, privacy, 404, design
                                system) e frasi-manifesto della CI
       h2        28 → 44        titolo di sezione, capitolo CI, feature
       h3        24 → 34.4      fascia CTA, titolo di colonna (split del
                                team), scheda alta del bento
       h4        21 → 26        scheda in evidenza, tab e pannello della
                                panoramica, titoletto dentro un articolo
       h5        18.4 → 20      scheda compatta, tappa della roadmap, domanda
                                dei problemi e delle FAQ, catena CI
       h6        17             titoletto di servizio (regole del DS)
       quote     20.8 → 30.4    citazioni e frasi editoriali
       xl        18 → 22        incipit di un articolo: l'unico testo sopra
                                il corpo di lettura che non è un titolo
       lg        17 → 19.2      lead sotto un titolo di pagina o di sezione
                                (anche la descrizione di ogni feature e la
                                nota dell'hero CI); corpo di lettura lunga
                                (articolo, privacy, prosa CI)
       md        16             corpo di interfaccia: è il body
       sm        15             testo secondario: schede, FAQ, nav, bottoni
       xs        13             meta: date, ruoli, etichette, note legali
       2xs       12             occhielli maiuscoli e micro-etichette

     A desktop i titoli salgono di 1.18-1.32 per gradino (display a parte,
     che stacca di 1.65 apposta); a telefono la scala si stringe a 1.08-1.24,
     perché sette gradini fra 16 e 42px più larghi non ci stanno. Sotto i
     380px il display segue la finestra: vedi il @media qui sotto. Il mock
     dell'interfaccia (.mock) e le micro-etichette delle campiture (.ds-cmp)
     restano fuori scala: sono miniature, non testo di pagina.

     Il display arriva al suo massimo a 1700px di finestra e non a 1440: sono
     gli stessi due estremi di prima — 41.6px sotto i 390, 89.6 in cima — ma
     la salita è più lunga, quindi fra i 390 e i 1700 il titolo è più piccolo
     dell'11%, e da 1700 in su non cambia di un pixel.

     La ragione è di composizione, non di gusto. Il claim della home è la riga
     più lunga del sito: 11.8 volte il corpo, cioè 1057px a 89.6. Alla vecchia
     curva quel massimo si raggiungeva già a 1440, dove lo shell misura 1368
     di luce: il titolo ne prendeva il 77% e quel che resta a destra non basta
     più a niente — il portatile dell'apertura si riduceva a 540px a 1440 e
     419 a 1280. Spostando il massimo a 1700 il claim scende a 984px a 1440 e
     915 a 1280, e il portatile risale a 480. Sopra i 1700, dove lo spazio non
     manca, il titolo resta quello di prima: a 2560 ne prende il 54%. */
  --text-display: clamp(3.625rem, 3.1143rem + 2.0952vw, 5rem);
  --text-h1: clamp(3.625rem, 3.1607rem + 1.9048vw, 4.875rem);
  --text-h2: clamp(3.1875rem, 2.514rem + 2.762vw, 5rem);   /* 51 a 390, 80 a 1440 */
  --text-h3: clamp(1.75rem, 1.2857rem + 1.9048vw, 3rem);
  --text-h4: clamp(1.375rem, 1.1893rem + 0.7619vw, 1.875rem);
  --text-h5: clamp(1.15rem, 1.113rem + 0.152vw, 1.25rem);
  --text-h6: 1.0625rem;
  --text-quote: clamp(1.3rem, 1.077rem + 0.914vw, 1.9rem);
  --text-xl: clamp(1.125rem, 1.032rem + 0.381vw, 1.375rem);
  --text-lg: clamp(1.0625rem, 0.9929rem + 0.2857vw, 1.25rem);
  --text-md: 1rem;
  --text-sm: 0.9375rem;
  --text-xs: 0.8125rem;
  --text-2xs: 0.75rem;
  /* Ruoli con un nome proprio: alias di un gradino, non gradini in più. */
  --text-lead: var(--text-lg);
  --text-eyebrow: var(--text-2xs);

  /* Interlinea e spaziatura di ogni gradino. Più il corpo cresce, più
     l'interlinea si stringe e le lettere si avvicinano: a 90px l'aria
     naturale del font è troppa, a 13px è appena sufficiente. */
  --leading-display: 0.85;
  --leading-h1: 0.9;
  --leading-h2: 0.8;
  --leading-h3: 1.1;
  --leading-h4: 1.2;
  --leading-h5: 1.3;
  --leading-h6: 1.35;
  --leading-quote: 1.35;
  --leading-xl: 1.45;
  --leading-lg: 1.55;
  --leading-body: 1.5;
  --tracking-display: -0.065em;
  --tracking-h1: -0.07em;
  --tracking-h2: -0.06em;
  --tracking-h3: -0.05em;
  --tracking-h4: -0.04em;
  --tracking-h5: -0.012em;
  --tracking-h6: -0.01em;
  --tracking-quote: -0.02em;
  --tracking-xl: -0.015em;

  /* Contenitore largo, margini laterali stretti: il testo lungo resta
     comunque leggibile perché le colonne di prosa hanno un loro max-width. */
  --shell: 1440px;
  --shell-narrow: 780px;
  --radius: 14px;
  --radius-lg: 22px;

  --header-h: 72px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Il minimo di 2.6rem del display viene da un telefono da 390px. A 320 la
   parola più lunga fra i titoli display — "Approfondimenti", in apertura del
   blog — misura da sola 322px contro i 280 della colonna: non potendo andare
   a capo sforava, e con lei scorreva di lato l'intera pagina. Sotto i 380px il
   display smette di avere un minimo fisso e segue la finestra. */
@media (max-width: 380px) {
  :root { --text-display: 10.4vw; }
}

/* In oklab l'interpolazione avviene in uno spazio percettivamente uniforme:
   i passaggi perdono la gobba scura che sRGB lascia a metà fra due tinte, ed
   è questo — più delle fermate fitte — a togliere lo scalino. */
@supports (background-image: linear-gradient(in oklab, red, blue)) {
  :root {
    --grad-sky-invert: linear-gradient(
      180deg in oklab,
      var(--mist-100) 0%,
      var(--blue-200) 3.9%,
      var(--blue-300) 7.2%,
      var(--blue-400) 14.2%,
      var(--blue-500) 24.4%,
      var(--blue-600) 40.5%,
      var(--blue-700) 52.7%,
      var(--blue-800) 60.4%,
      var(--blue-850) 65.5%,
      var(--blue-900) 68%,
      var(--blue-950) 70%,
      var(--blue-950) 100%
    );
    --grad-ci: linear-gradient(
      180deg in oklab,
      var(--blue-950) 0.0%,
      var(--blue-900) 1.66%,
      var(--blue-850) 4.57%,
      var(--blue-800) 10.14%,
      var(--blue-700) 19.2%,
      var(--blue-600) 32.92%,
      var(--blue-500) 50.8%,
      var(--blue-400) 62.6%,
      var(--blue-300) 70.76%,
      var(--blue-200) 75.81%,
      var(--mist-100) 84.17%,
      #ffffff 100%
    );
  }
}

/* Ribalta i token per un intero blocco. Tutto ciò che sta dentro si adatta
   da solo: non serve una regola per componente. */
.on-dark {
  --bg: var(--steel-11);
  --bg-alt: var(--steel-12);
  /* Sullo scuro il testo non esce da ink. La rampa dell'inchiostro è fatta
     per il fondo chiaro: si ferma a #9da3a9, e a quella chiarezza su un fondo
     scuro non si legge come testo pieno — si legge come testo spento. Qui il
     testo torna al capo chiaro della steel, dove il bianco è bianco.
     Rispetto alla rampa di prima (0/3/5) i tre gradini salgono a 0/2/4: più
     chiari tutti e tre, stessa gerarchia. */
  --fg: var(--steel-0);               /* 13.71:1 sul fondo del blocco */
  --fg-muted: var(--steel-2);         /* 10.62:1 */
  --fg-faint: var(--steel-4);         /* 7.55:1 */
  --line: var(--steel-8);
  /* Superficie e scheda sono gradini pieni, non più bianco velato: la scheda
     sta un gradino sopra la superficie, come sul chiaro sta un gradino
     sotto. Il velo resta solo per --surface-2, che è un passaggio del
     cursore e non una superficie. */
  --surface: var(--steel-10);
  --surface-2: rgba(var(--paper-rgb), 0.06);
  --card: var(--steel-9);
  --section-grey: var(--steel-11);
  /* Sullo scuro l'accento resta blu — il gradino chiaro dell'azione,
     7.67:1 sul fondo. Il turchese non entra qui: è dei dettagli di
     stato. */
  --accent: var(--brand-2);
  --shadow: 0 20px 46px rgba(var(--ink-rgb), 0.4);

  /* Stati sullo scuro. Il pieno sale di due gradini (4 al posto del 6;
     warning resta al 3, che sullo scuro fa 9.6:1) e il testo un gradino
     sopra il pieno: così tutti e nove passano il 4.5:1 sia sul fondo del
     blocco sia sul proprio fondo tenue. Il fondo tenue non può essere un gradino:
     nessuna delle tre rampe scende abbastanza — warning si ferma a L* 40 — e
     un gradino pieno sul fondo scuro sarebbe una toppa, non un velo. È il
     pieno al 14% di opacità, translucido come --surface e --card qui sopra e
     per la stessa ragione: sullo scuro il fondo sotto è spesso un gradiente.
     I canali sono quelli di --success-4, --warning-3 e --danger-4 scritti
     per esteso, perché rgba() non legge un token. */
  --ok-sutil: rgba(0, 169, 155, 0.14);
  --ok: var(--success-4);
  --ok-texto: var(--success-3);
  --warn-sutil: rgba(255, 192, 86, 0.14);
  --warn: var(--warning-3);
  --warn-texto: var(--warning-2);
  --error-sutil: rgba(255, 89, 105, 0.14);
  --error: var(--danger-4);
  --error-texto: var(--danger-3);

  --btn-bg: var(--steel-0);
  --btn-bg-hover: var(--steel-1);
  --btn-fg: var(--steel-12);


  background: var(--bg);
  color: var(--fg);
}


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

/* La barra è agganciata: senza riserva, ogni salto a un'ancora — il link
   «Vai al contenuto» per primo — fermerebbe la pagina con il bersaglio già
   coperto dai 72px di vetro. */
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Il footer si appoggia al fondo della viewport anche quando la pagina e'
   corta: senza, sotto la sua fascia restava una striscia di fondo alta quanto
   lo scarto, che si legge come un pezzo di pagina rotto. Il main si prende
   quel che avanza e il footer torna al bordo.
   Sicuro da rendere flex: apertura (position: absolute) e velatura di fondo
   (::before, position: fixed) sono fuori flusso e non diventano voci del
   flex; script e style in fondo al body sono display: none. */
body {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  margin: 0;
  font-family: var(--font-text);
  font-size: var(--text-md);
  line-height: var(--leading-body);
  color: var(--fg);
  background: var(--bg-alt);
  -webkit-font-smoothing: antialiased;
}

body > main { flex: 1 0 auto; }

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  margin: 0;
  font-weight: 600;
}

/* Il gradino di partenza segue il livello del tag. Una classe di componente
   può spostare un titolo su un altro gradino — l'h2 nella colonna stretta
   dello split prende h3, l'h3 di una scheda compatta prende h5 — ma allora
   porta con sé anche interlinea e spaziatura di quel gradino, mai il corpo
   da solo: sono le tre cose insieme a fare il gradino. */
h1 { font-size: var(--text-h1); line-height: var(--leading-h1); letter-spacing: var(--tracking-h1); }
h2 { font-size: var(--text-h2); line-height: var(--leading-h2); letter-spacing: var(--tracking-h2); }
h3 { font-size: var(--text-h3); line-height: var(--leading-h3); letter-spacing: var(--tracking-h3); }
h4 { font-size: var(--text-h4); line-height: var(--leading-h4); letter-spacing: var(--tracking-h4); }
h5 { font-size: var(--text-h5); line-height: var(--leading-h5); letter-spacing: var(--tracking-h5); }
h6 { font-size: var(--text-h6); line-height: var(--leading-h6); letter-spacing: var(--tracking-h6); }

p { margin: 0; }

/* --- niente parole orfane nel testo corrente -----------------------------
   `text-wrap: pretty` chiede al browser di rifare gli a capo delle ultime
   righe pur di non lasciarci una parola sola. Era già sparso su una parte dei
   testi (bento, citazioni, sottotitoli); qui vale per tutti quelli lunghi,
   perché la regola è la stessa ovunque e tenerla per componente significava
   dimenticarsene — è così che le schede dei problemi si sono ritrovate
   «unica.» e «bilancio.» da sole in fondo.
   I titoli non entrano in questo elenco: lì serve `text-wrap: balance`, che
   pareggia le righe invece di curare solo l'ultima. */
.section__lead,
.feature__desc,
.blog-banner__lead,
.roadmap__body,
.manifesto__item p,
.standards__card p,
.article__excerpt,
.article__body p,
.prose p,
.ds-grad__lead {
  text-wrap: pretty;
}

ul, ol, dl, dd { margin: 0; padding: 0; list-style: none; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: 1rem; top: -100px;
  z-index: 200;
  padding: 0.7rem 1.1rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border-radius: 8px;
  font-weight: 600;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 1rem; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --------------------------------------------------------------- layout -- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 3vw, 2.25rem);
}

.shell--narrow { max-width: var(--shell-narrow); }

.section {
  padding: clamp(2.5rem, 5.56vw, 80px) 0;
  background: var(--bg);
}

/* Le sezioni dentro il blocco scuro non hanno fondo proprio. */
.hero-block .section { background: transparent; }

/* Prima zona scura: niente grigi. Il testo secondario resta bianco pieno e il
   terziario scende appena, quanto basta a tenere una gerarchia senza perdere
   leggibilità sul fondo. */
.hero-block {
  --fg-muted: var(--neutral-0);
  --fg-faint: rgba(var(--paper-rgb), 0.88);
}

/* Raccordo fra un blocco e il successivo: la sezione che segue sale di
   `--round` e arrotonda i suoi angoli alti, scoprendo il colore di quella
   sopra. È un raccordo di forma, non di colore — quindi non c'è nessuna rampa
   che possa lasciare bande, che è il difetto di qualunque fascia sfumata:
   un `colore -> transparent` è una rampa di *alfa*, e l'alfa a 8 bit su
   parecchi pixel produce sempre gradini.

   Chi sta sopra deve riservare lo spazio con `padding-bottom: var(--round)`,
   altrimenti il raccordo mangia l'ultima riga di contenuto. */
.hero-block + *,
.page-hero + *,
.roadmap + .blog-teaser {
  --round: clamp(1.75rem, 4vw, 3.25rem);

  position: relative;
  z-index: 1;
  margin-top: calc(var(--round) * -1);
  border-top-left-radius: var(--round);
  border-top-right-radius: var(--round);
}

.section--dark { background: var(--bg-alt); }

.section--light { background: var(--bg-alt); }

.section__title {
  font-size: var(--text-h2);
  max-width: 26ch;
}


.section__title--center {
  margin-inline: auto;
  text-align: center;
  max-width: 24ch;
}

.section__lead {
  margin-top: 1.1rem;
  max-width: 62ch;
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  color: var(--fg-muted);
}

.section__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  margin-bottom: 2.75rem;
}

/* Intestazione impilata e allineata a sinistra: titolo e riga di
   accompagnamento uno sopra l'altro, al margine della colonna. È la forma
   dell'archivio di riferimento — il centraggio lì non c'è. */
.section__head--stack {
  display: block;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}

.section__head--stack .section__title {
  max-width: 30ch;
}

.section__head--stack .section__lead {
  margin-top: 0.5rem;
}

/* Variante con un richiamo in fondo a destra, sulla stessa riga del titolo:
   i correlati in fondo a un articolo. */
.section__head--split {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* Intestazione centrata e impilata: il testo mantiene la sua misura di lettura
   ed è il margine automatico a centrarlo. */
.section__head--center {
  display: block;
  text-align: center;
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

/* Il titolo si ferma ben prima del bordo del contenitore: a piena larghezza
   un titolo lungo faceva due righe sbilanciate, con una sola parola sotto.
   `balance` distribuisce le parole fra le righe invece di riempirle a turno. */
.section__head--center .section__title {
  max-width: 22ch;
  margin-inline: auto;
  text-wrap: balance;
}

.section__head--center .section__lead { margin-inline: auto; }

/* Titolo su una riga sola. Le misure qui sopra servono ai titoli lunghi, che
   altrimenti si stirerebbero per tutta la pagina; questo ne ha 34 e con 22ch
   andava a capo per un soffio. Deve stare *dopo* quelle regole: la specificità
   è la stessa e a parità vince l'ultima. Il limite si toglie, la riga non si
   forza: su viewport stretti deve poter andare a capo, o esce dallo schermo. */
.blog-teaser .section__head--center .section__title {
  max-width: none;
  text-wrap: nowrap;
}

@media (max-width: 720px) {
  .blog-teaser .section__head--center .section__title { text-wrap: balance; }
}

.eyebrow {
  font-size: var(--text-eyebrow);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin-bottom: 0.9rem;
}

/* ----------------------------------------------------------------- icone -- */

/* Set Lucide, inline via views/partials/icon.ejs. Senza argomenti l'icona
   prende la dimensione del testo accanto a cui sta: è quasi sempre la misura
   giusta, e resta giusta quando il testo cambia corpo.
   Lucide disegna il tratto per 2 su griglia 24; qui sta a 1.75, che regge sia
   sul chiaro sia dentro .on-dark senza assottigliarsi. È un token: si cambia
   qui per tutto il sito, o su un blocco solo ridefinendo --icon-stroke. */
.icon {
  inline-size: var(--icon-size, 1em);
  block-size: var(--icon-size, 1em);
  stroke-width: var(--icon-stroke, 1.75);
  flex: none;
  vertical-align: -0.145em;
}

/* ---------------------------------------------------------------- figure -- */

/* Figure isometriche generate (scripts/build-figures.js), inline via
   views/partials/figure.ejs. Ogni figura porta la propria viewBox: la
   larghezza la decide chi la usa, l'altezza segue.

   Il tratto NON scala con la figura. È la regola che tiene insieme la
   famiglia: la stessa figura a 90px e a 300px deve avere lo stesso filo,
   altrimenti da piccola sembra un disegno e da grande un contorno spesso.
   `non-scaling-stroke` lo misura in pixel di schermo invece che in unità di
   viewBox, ed è l'unico modo di ottenerlo senza generare due file. */
.figure {
  display: block;
  width: 100%;
  height: auto;
}

.figure path {
  vector-effect: non-scaling-stroke;
  stroke-width: var(--figure-stroke, 1.2);
}

/* Il riempimento è il colore del fondo su cui la figura sta, e serve a una
   cosa sola: tappare quello che le passa dietro. Senza, due volumi
   sovrapposti si mostrano le linee a vicenda e la figura smette di avere
   profondità — si legge come un groviglio piatto.
   Il valore lo mette chi usa la figura, perché solo lui sa su che fondo la
   mette; senza, il ripiego è trasparente e si torna al filo di ferro. */
.figure__fill {
  fill: var(--figure-fill, none);
  stroke: none;
}

/* I pieni portano la forma, le guide la spiegano. Il bianco sta a 0.85 di
   opacità e non a pieno: resta `currentColor`, così sul chiaro diventa
   inchiostro da solo, e la trasparenza fa il resto. Scriverlo come
   rgba(255,255,255,.85) darebbe lo stesso identico bianco qui e un fantasma
   invisibile su qualunque pagina chiara. */
/* Bianco pieno, non velato: l'opacità che stava qui le rendeva grigie e le
   figure sembravano spente accanto al testo, che è bianco al 100%. */
.figure__solid { opacity: 1; }

/* --- alone -----------------------------------------------------------------
   Due ombre concentriche per tratto: una stretta, che dà al filo un bordo
   acceso, e una larga e appena accennata, che è quella che si legge come
   luce. Una sola ombra larga fa nebbia, una sola stretta fa contorno: serve
   la coppia.

   L'alone sta sui TRATTI e non sul gruppo. Il gruppo contiene anche la sagoma
   piena che serve all'occlusione: un filtro sul gruppo la includerebbe, e
   invece di illuminare gli spigoli disegnerebbe un alone attorno all'intero
   blocco, sagoma compresa. È il motivo del `:not(.figure__fill)`.

   Il raggio è in unità di viewBox, non in pixel di schermo come lo spessore
   del tratto: cresce quindi con la figura, che è quel che serve — a 320px
   l'alone è di tre pixel scarsi, e se un giorno la figura raddoppia raddoppia
   con lei invece di restare un filo.

   Sull'accento l'alone è più marcato che sul bianco: il turchese ha meno
   luminanza del bianco e senza quel po' in più si spegnerebbe accanto. */
.figure__solid path:not(.figure__fill) {
  filter:
    drop-shadow(0 0 1px rgba(var(--paper-rgb), 0.4))
    drop-shadow(0 0 4px rgba(var(--paper-rgb), 0.14));
}

.figure__guide path {
  filter:
    drop-shadow(0 0 1.2px rgba(var(--teal-rgb), 0.6))
    drop-shadow(0 0 5.5px rgba(var(--teal-rgb), 0.3));
}

/* A contrasto forzato l'alone è rumore: il sistema ridipinge i tratti e la
   sfocatura resta come una macchia attorno. */
@media (forced-colors: active) {
  .figure__solid path:not(.figure__fill),
  .figure__guide path { filter: none; }
}

/* Non più in uso: i dischi attenuati sono spariti quando il diagramma è
   diventato una griglia di blocchi. Resta il gancio, se servirà. */
.figure__solid--faint { opacity: 0.5; }

/* PROVA — annotazioni in turchese invece che in bianco attenuato.
   L'idea: il tratteggio è la parte che porta il concetto, ed è la stessa cosa
   che fa la parola in evidenza nella domanda sotto. Dargli la stessa tinta
   lega le due, e l'annotazione smette di essere un dettaglio da cercare.
   Colore e opacità stanno in due token per poter tornare indietro cambiando
   una riga: senza valore, il tratteggio resta bianco tenue com'era. */
.figure__guide {
  stroke: var(--figure-guide, currentColor);
  opacity: var(--figure-guide-opacity, 0.2);
  stroke-dasharray: 6 5;
}

/* Stesso tratto del resto: a distinguere l'annotazione dall'oggetto bastano
   colore e tratteggio. Un peso diverso faceva sembrare le due cose disegnate
   da mani diverse. */

/* -------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.7rem 1.3rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: transform 0.18s var(--ease), background-color 0.18s var(--ease),
              border-color 0.18s var(--ease);
}

.btn--lg { padding: 0.9rem 1.7rem; font-size: var(--text-md); }

/* L'icona nel tasto sta appena sopra il corpo dell'etichetta: a 1em, accanto a
   un testo in 600, si legge come un refuso. Il `gap` del tasto fa la spaziatura.

   L'icona nomina la cosa, non il gesto: accanto a «Scarica» ci va un documento,
   non una freccia che scende — il verbo è già scritto, ripeterlo in figura non
   aggiunge niente, mentre la figura dell'oggetto dice che cosa si riceve.
   Sta in testa quando nomina l'oggetto, in coda quando indica che si va
   altrove: quella è l'unica freccia ammessa, e solo dove porta fuori. */
.btn .icon { --icon-size: 1.15em; }

/* Schermi da 320px: "Scopri la Compliance Intelligence" in un tasto grande
   misura 312px contro i 280 della colonna, e siccome `nowrap` non lascia
   andare a capo l'eccedenza usciva dal viewport — l'intera pagina scorreva di
   lato, non solo il tasto. Qui il `nowrap` cade e i fianchi si stringono:
   l'etichetta va su due righe, che è l'unica alternativa a un tasto più
   largo dello schermo. */
@media (max-width: 380px) {
  .btn {
    max-width: 100%;
    white-space: normal;
    text-align: center;
  }

  .btn--lg { padding-inline: 1.15rem; }
}

/* Primario in contrasto pieno col fondo, non in blu: bianco sulle sezioni
   scure, inchiostro su quelle chiare. In entrambi i casi il testo sta sopra
   i 14:1, molto oltre il minimo di 4.5. */
.btn--accent {
  background: var(--btn-bg);
  color: var(--btn-fg);
}

.btn--accent:hover {
  background: var(--btn-bg-hover);
  transform: translateY(-1px);
}

/* Secondario: nessun riempimento, solo il tratto. Il colore non e' scritto
   qui ma preso dal testo — currentColor — e il testo segue --fg, che .on-dark
   ribalta: bianco sulle fasce scure, inchiostro su quelle chiare, senza una
   regola per contesto.

   Prima il fondo era --surface, cioe' bianco pieno sulle pagine chiare: un
   tasto pieno che si spacciava per secondario. E il tratto era --line, la
   stessa riga da 13% che divide i blocchi: troppo debole per dire dove
   finisce un pulsante. */
.btn--ghost {
  border-color: currentColor;
  border-width: 1.5px;
  color: var(--fg);
  background: transparent;
}

/* Il richiamo chiude la sezione invece di anticiparla: sta sotto il contenuto,
   centrato. Lo usano la galleria di prodotto e la fascia di articoli, quindi il
   nome non è di nessuna delle due. */
.section__foot {
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  text-align: center;
}


/* L'hover non riempie il tasto: lo vela appena. --surface-2 e' inchiostro al
   4.5% sul chiaro e bianco al 6% sullo scuro, quindi si adatta da solo — il
   bianco al 28% scritto a mano di prima, sulle pagine chiare, schiariva il
   bordo invece di segnarlo. */
.btn--ghost:hover {
  background: var(--surface-2);
  transform: translateY(-1px);
}

/* --------------------------------------------------------------- header -- */

/* Forma di base: trasparente, appoggiata in cima al documento. Da sola la
   barra scorrerebbe via con la pagina — a tenerla in vista è
   `site-header--sticky` qui sotto, che è la variante che l'header monta. */
.site-header {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
}

/* --- variante agganciata, a tutta larghezza -------------------------------
   Attiva: è la classe che porta l'header in views/partials/header.ejs. La
   barra resta in vista scorrendo e oltre la soglia si accende di vetro a
   tutta larghezza. Il vetro è davvero trasparente: a renderla leggibile è la
   sfocatura, non una velatura coprente. Il colore del testo dipende da cosa
   le passa sotto — lo decide il JS con `.is-over-dark` — perché un solo
   colore fisso sarebbe illeggibile sopra metà pagina. */
.site-header--sticky {
  position: fixed;
}

.site-header--sticky.is-stuck {
  background: rgba(var(--surface-rgb), 0.82);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  box-shadow: 0 1px 0 rgba(var(--ink-rgb), 0.08);
}

.site-header--sticky.is-stuck .site-header__inner {
  --fg: var(--ink);
  --fg-muted: var(--ink-4);
  --accent: var(--brand-6);
  color: var(--fg);
}

/* Sopra le zone scure la barra si inverte. */
.site-header--sticky.is-stuck.is-over-dark {
  background: rgba(var(--night-rgb), 0.72);
  box-shadow: 0 1px 0 rgba(var(--paper-rgb), 0.08);
}

.site-header--sticky.is-stuck.is-over-dark .site-header__inner {
  --fg: var(--steel-0);
  --fg-muted: var(--steel-2);
  --accent: var(--brand-2);
}

/* A riposo, sopra un'apertura scura, la barra prende il bianco: gli stessi
   valori che `.is-over-dark` dà alla barra agganciata. La regola serve perché
   l'header sta fuori da `.hero-block` e da solo erediterebbe l'inchiostro del
   chiaro.

   `.is-over-dark` in più: prima la regola valeva per ogni apertura, perché
   l'hero della home era scuro fin dal bordo alto. Col gradiente nuovo non lo
   è più — parte a rgb(238,245,249) e non arriva allo scuro prima di y=220 —
   e la barra si dipingeva bianca su quasi bianco: 1.40:1, illeggibile. Ora
   comanda il JS, che il fondo lo misura invece di dedurlo dalla classe.
   Quando sotto passa chiaro la regola non si applica e l'header torna a
   ereditare l'inchiostro, che è esattamente quel che serve. */
body:has(.hero) .site-header.is-over-dark:not(.is-stuck) .site-header__inner {
  --fg: var(--steel-0);
  --fg-muted: var(--steel-2);
  --accent: var(--brand-2);

  color: var(--fg);
}

/* Il server marca `on-dark` le aperture scure, e senza quel default
   lampeggerebbero d'inchiostro prima che il JS giri. La home non è più fra
   quelle: da quando il gradiente parte quasi bianco la sua rotta dichiara
   `lightHeader`, così la barra è giusta già al primo disegno: prima usciva
   bianca su quasi bianco, 1.02:1 sui link misurato a 1440x900.

   `is-over-light` resta la rete: la mette il JS dopo aver misurato il fondo
   davvero dipinto, e ribalta il default per le aperture che restano scure ma
   che sotto la barra, a quell'altezza, chiare lo sono. A barra agganciata non
   serve: comanda `.is-stuck`, che ha già le sue due varianti. */
.site-header.on-dark.is-over-light:not(.is-stuck) .site-header__inner {
  --fg: var(--ink);
  --fg-muted: var(--ink-4);
  --accent: var(--brand-6);

  color: var(--fg);
}

/* Il tasto pieno non segue `--fg`: ha un fondo suo, e a deciderlo sono
   `--btn-bg` e `--btn-fg`, che `.on-dark` ribalta per l'intero blocco. Finché
   quei due token restavano appesi alla classe del server, il tasto non
   guardava cosa gli passa sotto: sulla home usciva bianco sull'apertura quasi
   bianca — pillola 242,245,246 su fondo 213,227,233, cioè 1.20:1 — e sopra le
   fasce chiare agganciate faceva 1.52:1. Lo stesso difetto su /product da
   y=900 in giù.

   Qui seguono il fondo misurato, come già il testo: dove passa chiaro il tasto
   è inchiostro con etichetta bianca — gli stessi valori delle pagine che
   aprono chiare, 13.3:1 sul vetro — e dove passa scuro torna bianco con
   etichetta d'inchiostro. Vale agganciata e da ferma, perché il fondo cambia
   in tutti e due gli stati.

   Il menu del telefono non lo tocca: i suoi token li dichiara `.site-nav`, che
   sta più vicino al tasto e vince per eredità, non per specificità. */
.site-header.is-over-light .site-header__inner {
  --btn-bg: var(--steel-11);
  --btn-bg-hover: var(--steel-12);
  --btn-fg: var(--steel-0);
}

.site-header.is-over-dark .site-header__inner {
  --btn-bg: var(--steel-0);
  --btn-bg-hover: var(--steel-1);
  --btn-fg: var(--steel-12);
}

/* --- variante a pillola sospesa -------------------------------------------
   Attiva, insieme a `--sticky`: scorrendo la barra non si accende da bordo a
   bordo, si raccoglie in una pillola di vetro sospesa al centro. È la forma
   di dendoo.it.

   La fascia a tutta larghezza della variante agganciata va quindi spenta:
   accesa insieme alla pillola disegnerebbe due oggetti sovrapposti, la
   pillola dentro la sua stessa banda. Il vetro passa al contenitore
   interno — è lui la pillola — e qui resta solo il trasporto. */
.site-header--pill.site-header--sticky.is-stuck,
.site-header--pill.site-header--sticky.is-stuck.is-over-dark {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.site-header--pill.site-header--sticky.is-stuck .site-header__inner {
  max-width: 66rem;
  padding: 0.5rem 0.5rem 0.5rem 1.5rem;
  backdrop-filter: saturate(170%) blur(16px);
  -webkit-backdrop-filter: saturate(170%) blur(16px);
}

/* Sopra le zone chiare: velo bianco appena accennato e testo scuro. */
.site-header--pill.site-header--sticky.is-stuck .site-header__inner {
  --fg: var(--ink);
  --fg-muted: var(--ink-4);
  --accent: var(--brand-6);

  color: var(--fg);
  background: rgba(var(--surface-rgb), 0.5);
  box-shadow:
    inset 0 0 0 1px rgba(var(--surface-rgb), 0.5),
    0 8px 30px rgba(var(--ink-rgb), 0.1);
}

/* Sopra le zone scure: il velo si inverte e il testo torna bianco. */
.site-header--pill.site-header--sticky.is-stuck.is-over-dark .site-header__inner {
  --fg: var(--steel-0);
  --fg-muted: var(--steel-2);
  --accent: var(--brand-2);

  background: rgba(var(--paper-rgb), 0.07);
  box-shadow:
    inset 0 0 0 1px rgba(var(--paper-rgb), 0.14),
    0 8px 30px rgba(var(--ink-rgb), 0.28);
}

.site-header--pill.site-header--sticky.is-stuck .site-nav { gap: 1.4rem; }

.site-header--pill.site-header--sticky.is-stuck .site-nav__cta { padding: 0.6rem 1.15rem; }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  border-radius: 999px;
  transition:
    max-width 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    padding 0.45s cubic-bezier(0.16, 1, 0.3, 1),
    background-color 0.35s var(--ease),
    box-shadow 0.35s var(--ease),
    color 0.35s var(--ease);
}

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

.logo {
  display: inline-flex;
  align-items: center;
  line-height: 1;
}

/* Wordmark ufficiale (public/images/logo-dendoo.svg), inline così eredita
   il colore dal contesto: bianco su fondo scuro, ink su fondo chiaro. */
.logo__svg {
  display: block;
  height: 25px;
  width: auto;
  color: var(--fg);
}

.logo--sm .logo__svg { height: 21px; }

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

.site-nav__link {
  font-size: var(--text-sm);
  /* Colore pieno, non attenuato: le voci di menu sono navigazione primaria. */
  color: var(--fg);
  transition: opacity 0.18s var(--ease);
}

.site-nav__link:hover { opacity: 0.7; }

.site-nav__link.is-active { font-weight: 600; }

.nav-toggle {
  display: none;
  width: 42px; height: 42px;
  align-items: center;
  justify-content: center;
  background: var(--card);
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  color: inherit;
}

.nav-toggle__bars { display: block; width: 18px; }

.nav-toggle__bars span {
  display: block;
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}

.nav-toggle__bars span + span { margin-top: 5px; }

.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:first-child {
  transform: translateY(3.5px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bars span:last-child {
  transform: translateY(-3px) rotate(-45deg);
}

/* ------------------------------------------------ riempimento allo scroll -- */

/* Il testo si tinge man mano che la sezione entra in pagina. Il gradiente è
   ritagliato sulla forma dei glifi e la sua soglia è `--fill`, che il JS
   aggiorna in base a quanto l'elemento ha attraversato la finestra.
   Verticale e non orizzontale: così si riempie riga per riga, nell'ordine in
   cui si legge, invece che in diagonale su tutte le righe insieme.
   Valore iniziale 100%: senza JS il testo resta pieno e leggibile. */
.reveal-fill {
  --fill: 100%;
  background-image: linear-gradient(
    180deg,
    var(--fg) calc(var(--fill) - 12%),
    var(--fg-faint) calc(var(--fill) + 4%)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .reveal-fill { color: var(--fg); -webkit-text-fill-color: var(--fg); }
}

@media (forced-colors: active) {
  .reveal-fill {
    background-image: none;
    color: var(--fg);
    -webkit-text-fill-color: var(--fg);
  }
}

/* ----------------------------------------------------- micro-interazioni -- */

/* Le frecce nei link scorrono in avanti al passaggio: segnala la direzione
   dell'azione meglio di un cambio di colore. Il <span> che le contiene è già
   `aria-hidden`, quindi il movimento non tocca ciò che viene letto. */
.overview__link span,
.card__cta span {
  display: inline-block;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

@media (hover: hover) {
  .overview__link:hover span,
  .card__cta:hover span,
  .card__link:hover .card__cta span { transform: translateX(4px); }
}

/* Risposta al tocco: senza, su mobile la pressione non dà alcun segnale
   finché la pagina non cambia. */
.btn:active { transform: translateY(1px) scale(0.985); }

.card:active { transform: translateY(-1px); }

.faq__q:active { opacity: 0.72; }

@media (prefers-reduced-motion: reduce) {
  .overview__link span,
  .bento__art { transition: none; }
}

/* ----------------------------------------------- entrate allo scorrimento -- */

/* Il contenuto entra quando attraversa il bordo della finestra. Lo stato di
   partenza è dietro `.js-motion`, messo dal JS sull'<html>: senza JS nulla è
   nascosto, quindi la pagina resta leggibile e indicizzabile. */
.js-motion [data-enter] {
  opacity: 0;
  transform: translateY(18px);
}

.js-motion [data-enter].is-in {
  opacity: 1;
  transform: none;
  /* Curva lunga in uscita: parte decisa e si posa. */
  transition:
    opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1) var(--enter-delay, 0ms),
    transform 0.7s cubic-bezier(0.16, 1, 0.3, 1) var(--enter-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .js-motion [data-enter] { opacity: 1; transform: none; }
}

/* -------------------------------------------- fondo che vira allo scroll -- */

/* Come su icreon: entrando nella zona di chiusura, il fondo scuro vira al blu
   di marca. Il colore sta su uno strato ::before la cui opacità è `--bg-reveal`
   (0..1), aggiornata dal JS leggendo lo scroll. Animare un'opacità è composita:
   niente ricalcoli di layout a ogni frame. Senza JS resta il fondo scuro. */
/* Un contenitore solo per banda e footer: il colore sta qui, quindi la zona
   è una superficie continua. Con due strati separati, ciascuno sopra una base
   diversa, restava un salto di tono nel punto di giunzione. */
.closing {
  position: relative;
  /* Stesso fondo della FAQ che la precede: erano due neri diversi e nel
     punto di giunzione si vedeva la riga. */
  background: var(--blue-950);
}

/* Il viraggio prende tutta la zona scura, non solo la fine: articoli, FAQ e
   chiusura sono tre blocchi neri di fila, e tingerne solo due lascia la
   cucitura un gradino più su invece di toglierla. Fondere i soli fondi di
   base non basta: quelli coincidono già: è arrivando in fondo che il cierre
   vira al blu e chi resta fuori resta nero, ed è lì che si vedono insieme.
   Il gradiente è quasi orizzontale, così blocchi impilati di altezza diversa
   lo disegnano identico e nei punti di giunzione non resta cucitura. */
.blog-teaser,
.faq { position: relative; }

.blog-teaser > *,
.faq > * { position: relative; z-index: 1; }

.blog-teaser::before,
.faq::before,
.closing::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Orizzontale esatto, non «quasi». Tre gradi di inclinazione sembrano
     niente, ma la lunghezza dell'asse di un gradiente li fa pesare
     sull'altezza: su un blocco da 390x1216 il verso verticale vale il 14%
     della corsa, e ogni blocco la ricomincia da capo. Misurato al confine fra
     le domande e la chiusura, il salto era da rgb(20,57,73) a rgb(14,53,68) —
     una riga netta attraverso una zona che deve leggersi come una superficie
     sola. A 90 gradi l'altezza non entra più nel conto: tre blocchi impilati
     dipingono la stessa rampa e il confine sparisce. */
  background: linear-gradient(90deg, var(--blue-800), var(--blue-700) 52%, var(--blue-800));
  /* Il blog ha gli angoli alti arrotondati dal raccordo: senza ereditare il
     raggio il velo li ridisegna quadrati e lo spigolo ricompare. */
  border-radius: inherit;
  /* La transizione copre gli scatti fra un fotogramma di scroll e l'altro:
     senza, su rotelle a scatti il viraggio si vede procedere a gradini. */
  opacity: var(--bg-reveal, 0);
  transition: opacity 0.45s cubic-bezier(0.33, 1, 0.68, 1);
}

.closing > * { position: relative; z-index: 1; }

.cta-band .btn--accent {
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
              transform 0.18s var(--ease);
}

.is-bg-revealed .btn--ghost { border-color: rgba(var(--paper-rgb), 0.55); }

.cta-band .btn--ghost,
.cta-band .eyebrow,
.site-footer,
.site-footer a {
  transition: color 0.4s var(--ease), border-color 0.4s var(--ease);
}

/* Sul blu i toni attenuati non reggono: si risalgono per l'intera zona. */
.is-bg-revealed {
  --fg-muted: var(--steel-2);
  --fg-faint: var(--steel-4);
}

/* --------------------------------------------------- testo con gradiente -- */

/* Il gradiente scorre dentro la sagoma delle lettere: `background-clip: text`
   ritaglia lo sfondo sulla forma del glifo e il colore trasparente lo lascia
   vedere. Si anima `background-position`, non il gradiente stesso: spostare
   una posizione è economico, ricalcolare le tinte a ogni frame no.

   Gli strati sono due. Sotto l'onda di fondo, che dà alle lettere il loro
   corpo in movimento; sopra un lampo stretto che le attraversa in senso
   contrario e con un'altra inclinazione — 78° contro 100°, quindi i due non
   sono paralleli e l'incrocio disegna una losanga di luce invece di una banda.

   L'onda è due picchi bianchi e due avvallamenti, ripetuti due volte. Gli
   avvallamenti sono il punto debole: è lì che la parola può sprofondare nel
   fondo. Sotto la prima riga del titolo la discesa dell'hero sta fra #7d98a9
   sugli schermi bassi e #587488 su un 1080, e sul caso peggiore --blue-400
   tiene 1.63:1 — sotto il 3:1 dei testi grandi. Il fondo dell'onda sale quindi
   a --blue-200 (2.40:1 sul peggiore, 3.90:1 sul 1080) e quello profondo passa
   a --teal-500.
   È la differenza di *croma*, non di luce, a staccare la parola dal campo: il
   fondo qui porta la tinta che il master ha a questa altezza, e le fermate di
   prima erano tutte quella stessa tinta schiarita — la parola era più chiara
   del cielo, non altro dal cielo. Il turchese è l'unica tinta della tavola fuori dal blu, e qui sta
   nella proporzione che gli spetta: due avvallamenti stretti e la frangia del
   lampo, non l'accento della parola, che resta blu.

   Le liste stanno in due token perché servono identiche due volte — qui e
   nell'`@supports` in oklab più sotto — e due copie che divergono si
   vedrebbero come uno scarto di tinta fra un browser e l'altro. */
.shimmer {
  --shimmer-stops:
    #ffffff 0%,
    var(--steel-1) 12%,
    var(--brand-0) 25%,
    var(--brand-2) 37%,
    #ffffff 50%,
    var(--steel-1) 62%,
    var(--brand-0) 75%,
    var(--brand-2) 87%,
    #ffffff 100%;

  /* Nucleo bianco con la frangia turchese in entrata e fredda in uscita: è
     l'aberrazione cromatica di un riflesso speculare. Il turchese resta un
     bordo sottile, non il colore del lampo.
     L'alfa serve: il lampo deve lasciar passare l'onda che gli sta sotto. È
     una rampa di alfa, ma corta e ritagliata dentro le aste delle lettere,
     non stesa su una superficie grande — è lì che l'alfa fa bande, non qui.
     I valori sono letterali e non token: dentro `rgba()` un token esadecimale
     non entra, e `color-mix()` non vale il rischio — se una sola tinta del
     gradiente non viene capita cade tutto `background-image`, e con il testo
     trasparente il titolo sparirebbe. Sono --brand-2 e --steel-1 scritti per
     esteso, come già altrove nel file. */
  --shimmer-glint:
    rgba(255, 255, 255, 0) 44%,
    rgba(97, 205, 229, 0.5) 47.5%,
    rgba(255, 255, 255, 0.95) 50%,
    rgba(226, 233, 236, 0.5) 52.5%,
    rgba(255, 255, 255, 0) 56%;

  background-image:
    linear-gradient(78deg, var(--shimmer-glint)),
    linear-gradient(100deg, var(--shimmer-stops));
  background-size: 300% 100%, 200% 100%;
  background-position: 0 0, 0 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: shimmer-pan 6.8s linear infinite;
}

/* In sRGB il tratto dal turchese al bianco passa per grigi slavati e il lampo
   perde proprio il croma per cui è lì. In oklab la saturazione regge fino in
   fondo. Sta in un `@supports` perché `in oklab` dentro la regola di base
   renderebbe la dichiarazione invalida dove non è capita, e il titolo
   resterebbe senza gradiente: cioè trasparente, quindi invisibile. */
@supports (background-image: linear-gradient(in oklab, red, blue)) {
  .shimmer {
    background-image:
      linear-gradient(78deg in oklab, var(--shimmer-glint)),
      linear-gradient(100deg in oklab, var(--shimmer-stops));
  }
}

/* Un'animazione sola muove entrambi gli strati: `background-position` è una
   proprietà unica con una lista, e due animazioni separate si sovrascriverebbero
   invece di sommarsi.
   Le posizioni non sono scelte a occhio. Con `background-size: W` e
   `background-position: P`, lo scarto vale P/100 × (C − W) con C la larghezza
   dell'elemento: il fondo a 200% e 200% percorre 2C, cioè due periodi interi
   della sua trama; il lampo a 300% e −150% percorre 3C, cioè una trama intera.
   Numeri interi da entrambe le parti, quindi l'ultimo fotogramma coincide con
   il primo e il giro non salta.
   I due strati vanno a passi diversi apposta. Il fondo corre — una cresta ogni
   3.4s — e il lampo no: 0.44 C/s, un solo passaggio per giro, 0.82s per
   scavalcare un punto della parola. È la differenza fra i due a farsi vedere;
   se corrono insieme non si legge né l'uno né l'altro.
   Il lampo va a velocità costante. Una versione precedente gli dava fermate
   spaziate in modo diseguale, per dargli peso: a tre passaggi per giro quel
   peso si leggeva come scatto, non come inerzia. Con un passaggio solo e lento
   la rampa lineare basta, ed è l'unica che non ha nulla da nascondere nel
   punto in cui il giro si richiude. */
@keyframes shimmer-pan {
  from { background-position:    0 0,   0 0; }
  to   { background-position: -150% 0, 200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .shimmer { animation: none; }
}

/* Se il testo trasparente non è supportato — o in modalità a contrasto
   forzato — il titolo tornerebbe invisibile: qui si ripristina il colore. */
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .shimmer {
    color: var(--fg);
    -webkit-text-fill-color: var(--fg);
  }
}

@media (forced-colors: active) {
  .shimmer {
    background-image: none;
    color: var(--fg);
    -webkit-text-fill-color: var(--fg);
  }
}

/* --------------------------------------------------------------- footer -- */

/* Nessun bordo e nessuno stacco di fondo rispetto alla sezione sopra: la
   chiusura della pagina è una zona sola, non due riquadri accostati.

   Lo stacco in alto è lo stesso che apriva la banda di chiusura, ora che il
   piede la segue direttamente: l'aria fra l'ultima sezione e il piede resta
   quella di prima, senza la banda in mezzo. */
.site-footer {
  padding: clamp(3.5rem, 7vw, 5.5rem) 0 2.25rem;
  background: transparent;
}

.site-footer__inner {
  display: flex;
  /* Chiuse in basso, non appese in alto: il blocco legale a destra è più
     alto, e con flex-start il marchio restava sospeso a mezz'aria. */
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
}

.site-footer__brand { display: grid; gap: 0.75rem; }

.site-footer__privacy { font-size: var(--text-xs); color: var(--fg-muted); }
.site-footer__privacy:hover { color: var(--fg); }

.site-footer__legal {
  text-align: right;
  font-size: var(--text-xs);
  line-height: 1.7;
  color: var(--fg-faint);
}

.site-footer__company { color: var(--fg-muted); font-weight: 600; }

.site-footer__legal a { color: inherit; }
.site-footer__legal a:hover { color: var(--fg); }

@media (max-width: 780px) {
  .logo {
      padding-block: 0.6rem;
      margin-block: -0.6rem;
    }

  .site-footer__privacy,
    .site-footer__legal a,
    .start__contact a,
    .overview__link {
      display: inline-block;
      padding-block: 0.7rem;
    }

  .site-footer__brand { gap: 0.25rem; }

  .site-header {
      --header-h: 84px;
  
      position: fixed;
      inset: 0 0 auto 0;
      /* Il token resta a 84 perché è la riserva che la pagina si tiene sotto la
         barra; la barra invece è più bassa, così fra il suo bordo e la prima
         riga resta dell'aria invece di un pareggio. */
      height: 64px;
      background: transparent;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
      transition: background-color 0.3s var(--ease);
    }

  body { --header-h: 84px; }

  .site-header__inner {
      --fg: var(--ink);
      --fg-muted: var(--ink-4);
      --accent: var(--brand-6);
  
      gap: 0.75rem;
      padding-block: 0;
      color: var(--fg);
      /* Il vetro sta sulla barra, non sul suo contenuto: qui si azzera quel che
         la variante a pillola metterebbe. */
      background: none;
      border-radius: 0;
      box-shadow: none;
    }

  .site-header.is-over-dark .site-header__inner {
      --fg: var(--steel-0);
      --fg-muted: var(--steel-2);
      --accent: var(--brand-2);
    }

  .site-header--pill.site-header--sticky.is-stuck {
      background: rgba(var(--surface-rgb), 0.7);
      backdrop-filter: saturate(180%) blur(18px);
      -webkit-backdrop-filter: saturate(180%) blur(18px);
      box-shadow: none;
    }

  .site-header--pill.site-header--sticky.is-stuck.is-over-dark {
      background: rgba(var(--night-rgb), 0.62);
      backdrop-filter: saturate(180%) blur(18px);
      -webkit-backdrop-filter: saturate(180%) blur(18px);
      box-shadow: none;
    }

  .site-header--pill.site-header--sticky.is-stuck .site-header__inner,
    .site-header--pill.site-header--sticky.is-stuck.is-over-dark .site-header__inner {
      max-width: var(--shell);
      padding: 0 clamp(1.25rem, 3vw, 2.25rem);
      background: none;
      border-radius: 0;
      box-shadow: none;
      backdrop-filter: none;
      -webkit-backdrop-filter: none;
    }

  .nav-toggle {
      display: inline-flex;
      width: 44px;
      height: 44px;
      border-radius: 999px;
      background: var(--neutral-11);
      color: var(--neutral-0);
    }

  .site-header.is-over-dark .nav-toggle {
      background: var(--neutral-0);
      color: var(--neutral-12);
    }

  .nav-toggle__bars { width: 20px; }

  .nav-toggle__bars span { height: 2px; }

  .nav-toggle__bars span + span { margin-top: 6px; }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bars span:first-child {
      transform: translateY(4px) rotate(45deg);
    }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bars span:last-child {
      transform: translateY(-4px) rotate(-45deg);
    }

  .site-nav {
      position: fixed;
      top: 64px;
      left: 0;
      right: 0;
      flex-direction: column;
      align-items: stretch;
      gap: 0.15rem;
      padding: 0.5rem clamp(1.25rem, 3vw, 2.25rem) 1.35rem;
      border-radius: 0 0 1.5rem 1.5rem;
      /* Pieno, non velato: a 0.92 il titolo dell'apertura si leggeva ancora
         attraverso il pannello, e un menu che lascia vedere quel che copre non
         si legge come uno strato ma come un difetto. La pillola può permettersi
         il vetro perché è alta sessanta pixel e sotto ci passa poco; un
         pannello che copre mezzo schermo, no. */
      background: var(--paper);
      backdrop-filter: saturate(180%) blur(18px);
      -webkit-backdrop-filter: saturate(180%) blur(18px);
      box-shadow:
        inset 0 0 0 1px rgba(var(--ink-rgb), 0.08),
        0 14px 40px rgba(var(--ink-rgb), 0.18);
      --fg: var(--ink);
      --fg-muted: var(--ink-4);
      --btn-bg: var(--neutral-11);
      --btn-bg-hover: var(--neutral-12);
      --btn-fg: var(--neutral-0);
      color: var(--fg);
      transform: translateY(-10px);
      opacity: 0;
      visibility: hidden;
      transition: transform 0.24s var(--ease), opacity 0.24s var(--ease), visibility 0.24s;
    }

  .site-nav.is-open { transform: translateY(0); opacity: 1; visibility: visible; }

  .site-nav__link {
      padding: 0.8rem 0;
      font-size: var(--text-md);
      border-bottom: 1px solid rgba(var(--ink-rgb), 0.08);
    }

  .site-nav__link:last-of-type { border-bottom: 0; }

  .site-nav__cta { margin-top: 0.85rem; }

  .section__lead { margin-top: 1.4rem; }

  .btn {
      /* L'interlinea del corpo — 1.6 — dentro un tasto è aria che non serve a
         nessuno: da sola valeva nove pixel dei cinquanta. Qui la riga torna
         alta quanto le lettere e l'altezza la decide il padding. */
      line-height: 1.15;
      padding: 0.6rem 1.05rem;
      font-size: var(--text-sm);
    }

  .btn--lg {
      padding: 0.72rem 1.25rem;
      font-size: var(--text-sm);
    }

  .section__foot .btn { display: flex; }

  .hero__description,
    .section__lead,
    .page-hero__note,
    .split__body,
    .manifesto__item p,
    .standards__card p,
    .card__excerpt,
    .faq__a p,
    .team__role,
    .bento__body,
    .roadmap__body { text-wrap: pretty; }

  .site-footer__inner {
      flex-direction: column;
      /* `flex-end` incolonna il marchio contro il bordo destro mentre il blocco
         legale, allineato a sinistra qui sotto, resta dall'altra parte: due
         allineamenti opposti nello stesso footer. In riga quel valore serviva
         ad appoggiare il marchio sulla base del blocco più alto; in colonna non
         ha più niente da appoggiare. */
      align-items: flex-start;
      gap: 2.25rem;
    }

  .site-footer__legal { text-align: left; }
}

/* ------------------------------------------------------- componenti -- */

/* Qui sotto va tutto ciò che è di questo sito e non della cimentazione.
   I valori — corpi, interlinee, colori, misure — sono misurati uno a uno
   sulla pagina di riferimento con Chrome headless, non stimati a occhio.

   La pagina è bianca, il testo corrente è DM Sans 18/27 a -0.02em su
   rgba(0,0,0,0.8), i titoli sono neri pieni. L'unico colore è il verde
   ghiaccio delle pastiglie e della riga sotto l'apertura. */

/* DM Sans di Google porta l'asse ottico `opsz` 9..40 e il browser lo alza da
   sé al crescere del corpo: a 80px sceglie 40, che è un disegno più stretto e
   più serrato. La pagina di riferimento serve un'istanza fissa, senza
   quell'asse, e i suoi titoli sono circa l'11% più larghi a parità di corpo e
   di spaziatura. Si spegne l'automatismo e il disegno torna quello giusto. */
html {
  font-optical-sizing: none;
  font-variation-settings: 'opsz' 14;
}

:root {
  /* Il nero dei tasti non è il nero del testo: è appena più caldo. */
  --tasto: #1a1615;
  /* La scheda chiara: metodo, modulo, coda delle pastiglie. */
  --ghiaccio: #f0f5f7;
  /* Il gradiente delle pastiglie, campionato dalla pagina. */
  --pastiglia: linear-gradient(96deg, rgba(209, 249, 255, 0.86) 0%,
                               rgb(222, 255, 235) 35.89%, rgb(240, 245, 247) 101%);
  /* La riga sotto il titolo d'apertura: verticale, dal ghiaccio al verde. */
  --riga-apertura: linear-gradient(rgb(216, 250, 254) 0%, rgb(223, 255, 236) 100%);
  --corpo-colore: rgba(0, 0, 0, 0.8);
  /* Il tasto sotto il mouse: lo stesso verde ghiaccio delle pastiglie, ma
     inclinato come sulla pagina. */
  --tasto-hover: linear-gradient(250deg, rgb(210, 249, 254) -26%,
                                 rgb(210, 249, 255) 0%, rgb(222, 255, 235) 100%);
  /* La curva che la pagina usa per i passaggi di colore. */
  --curva-pagina: cubic-bezier(0.44, 0, 0.56, 1);
  /* La molla. Sulla pagina niente si ferma di netto: arriva presto, sfora di
     un paio di punti e rientra. L'etichetta del tasto tocca la meta a 90ms su
     260 di corsa; la scheda a 130 su 420. Questa curva fa lo stesso. */
  --molla: cubic-bezier(0.15, 1.35, 0.35, 1);
  /* La scheda sfora molto meno del tasto: 2% contro 5%, misurati. Una molla
     sola per tutti e due dava un rimbalzo esagerato sull'apertura. */
  --molla-morbida: cubic-bezier(0.2, 1.18, 0.4, 1);
}

/* A 1440 il contenuto sta in 1200 con 120 di margine per lato: il guscio
   tiene la larghezza piena e sono i fianchi a fare la misura. */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  /* 16 a 390, 120 a 1440: la retta che passa per i due punti misurati. */
  padding: 0 clamp(16px, calc(-22.6px + 9.905vw), 120px);
}

/* Il testo corrente della pagina. Non è il body — il body resta su Open
   Runde per moduli e tasti — ma tutto ciò che è prosa di sezione. */
.prodotti__sommario,
.metodo__sommario,
.passo__testo,
.hero__lead,
.clienti__titolo,
.site-footer__claim {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 27px;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--corpo-colore);
  margin: 0;
}

/* --------------------------------------------------------- titoli -- */

.titolo-sezione {
  margin: 0;
  font-size: var(--text-h2);
  line-height: var(--leading-h2);
  letter-spacing: var(--tracking-h2);
  color: var(--fg);
  text-align: right;
}

/* «Il Metodo» sta in una colonna stretta: allineato a destra dentro una
   scatola larga quanto la parola, cade a sinistra nella pagina. */
.titolo-sezione--stretto { text-align: left; }
.titolo-sezione--centro { text-align: center; }

/* ------------------------------------------------------- marchio -- */

/* In cima non c'è una barra: c'è il marchio, centrato, nel flusso. */
.site-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  padding: clamp(3rem, 10.42vw, 150px) 0 0;
}

.site-brand__link { display: inline-flex; }

.logo {
  height: 52px;
  width: auto;
}

.logo--bianco { height: 85px; }

.site-brand__nav { display: flex; gap: 1.75rem; }

.site-brand__voce {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: -0.02em;
  color: var(--corpo-colore);
}

.site-brand__voce:hover { color: var(--fg); }

/* --------------------------------------------------------- tasti -- */

/* Pillola nera, 55 di altezza, etichetta in maiuscolo. Il corpo e il peso
   sono quelli della pagina: Open Runde 16 semibold. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 18px 24px;
  border: 0;
  border-radius: 100px;
  background: var(--tasto);
  color: #fff;
  font-family: var(--font-text);
  font-size: 16px;
  line-height: 1.2;
  font-weight: 600;
  letter-spacing: normal;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  /* Il fondo cambia quasi subito: sulla pagina è già verde a 9ms. */
  transition: background-image 0.09s linear,
              background-color 0.09s linear;
}

/* La cornice sta ferma e taglia: è alta una riga. A muoversi sono le due
   voci dentro. Se a traslare fosse la cornice, il ritaglio viaggerebbe con
   lei e resterebbe sempre visibile la stessa voce. */
.btn__rullo {
  display: grid;
  grid-auto-rows: 19.2px;
  height: 19.2px;
  overflow: hidden;
}

.btn__voce {
  display: block;
  transition: transform 0.26s var(--molla);
}

.btn__voce--hover { color: #000; }

.btn:hover,
.btn:focus-visible {
  background-color: transparent;
  background-image: var(--tasto-hover);
}

.btn:hover .btn__voce,
.btn:focus-visible .btn__voce { transform: translateY(-19.2px); }

/* Chi ha chiesto meno movimento vede solo il cambio di fondo: l'etichetta
   nera prende il posto della bianca senza scorrere. */
@media (prefers-reduced-motion: reduce) {
  .btn__voce { transition: none; }
}

/* Nel modulo il tasto chiude la scheda da bordo a bordo. */
.btn--pieno { width: 100%; }

/* ------------------------------------------------------- apertura -- */

.hero {
  padding: 69px 0 44px;
}

.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero__titolo {
  margin: 0;
  max-width: 1232px;
  font-size: var(--text-h1);
  line-height: var(--leading-h1);
  letter-spacing: var(--tracking-h1);
  text-align: center;
  text-wrap: balance;
}

.hero__riga {
  width: min(960px, 100%);
  height: 6px;
  margin: 31px 0 0;
  background: var(--riga-apertura);
}

.hero__lead {
  margin: 46px 0 0;
  max-width: 700px;
  text-align: center;
  text-wrap: pretty;
}

.hero .btn { margin-top: 54px; }

/* -------------------------------------------------------- clienti -- */

.clienti { padding: clamp(2.5rem, 6vw, 4.5rem) 0; }

.clienti__titolo {
  margin: 0 0 2.5rem;
  text-align: center;
}

/* La striscia non si ferma: due nastri identici uno dietro l'altro, ognuno
   trasla della propria larghezza più lo stacco. Quando il primo è uscito, il
   secondo è già dove stava lui e il giro riparte senza salto. */
.clienti__pista {
  /* Sulla pagina la striscia non tocca i bordi della finestra: sta in 1072,
     centrata. È dentro quella cornice che i marchi entrano ed escono. */
  max-width: 1072px;
  margin-inline: auto;
  display: flex;
  gap: 51px;
  overflow: hidden;
  /* I capi sfumano invece di tagliarsi netti sul bordo della finestra. */
  mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}

.clienti__nastro {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 51px;
  margin: 0;
  padding: 0;
  list-style: none;
  /* 60 px/s: la stessa andatura della pagina, misurata sul suo fotogramma. */
  animation: clienti-scorri 23.5s linear infinite;
}

.clienti__voce { display: flex; align-items: center; }

/* Ogni marchio tiene la sua misura: sulla pagina non sono normalizzati a
   un'altezza sola, e forzarli li deformerebbe. La misura sta negli attributi
   del tag, non qui: i file di Framer non portano width/height propri e con
   `auto` collasserebbero a zero. */
.clienti__logo { flex: 0 0 auto; max-width: none; }

@keyframes clienti-scorri {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-100% - 51px)); }
}

@media (prefers-reduced-motion: reduce) {
  .clienti__nastro { animation: none; }
  .clienti__pista { justify-content: center; flex-wrap: wrap; }
  .clienti__nastro[aria-hidden="true"] { display: none; }
}

/* ------------------------------------------------------- prodotti -- */

.prodotti__testa {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1.5rem;
}

.prodotti__sommario {
  max-width: 44ch;
  text-align: right;
  text-wrap: pretty;
}

.prodotti__lista {
  list-style: none;
  margin: clamp(2.5rem, 7.43vw, 107px) 0 0;
  padding: 0;
  display: grid;
  gap: 24px;
}

/* La pastiglia è il <details>: il fondo e il raggio stanno qui, così
   crescono con lei quando si apre. */
.voce__apri {
  border-radius: 12px;
  background: var(--pastiglia);
}

/* Senza questo non si può animare verso `auto`, e l'apertura è uno scatto. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
}

.voce__apri::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 0.34s var(--molla-morbida),
              content-visibility 0.34s allow-discrete;
}

.voce__apri[open]::details-content { block-size: auto; }

/* La riga tiene il titolo in alto e cresce col padding: così fra chiusa e
   aperta non c'è un salto ma una corsa sola, insieme al corpo. 16+52.8+16
   fa gli 85 della pastiglia chiusa. */
.voce__riga {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2rem;
  padding: 16px 48px;
  cursor: pointer;
  list-style: none;
  transition: padding 0.34s var(--molla-morbida);
}

.voce__riga::-webkit-details-marker { display: none; }

/* Aperta, il titolo scende a 36 dal bordo e il corpo prende il posto sotto. */
.voce__apri[open] > .voce__riga { padding: 36px 48px 0; }

.voce__titolo {
  margin: 0;
  /* 27 a 390, 48 a 1440: la pastiglia stringe il titolo, la scheda no. */
  font-size: clamp(1.6875rem, 1.2rem + 2vw, 3rem);
  line-height: var(--leading-h3);
  letter-spacing: var(--tracking-h3);
  color: var(--fg);
}

/* Il segno è disegnato con due tratti: niente carattere tipografico, che a
   questo corpo cadrebbe fuori asse. Aperta la voce, la croce ruota di 45° e
   diventa una «×», come sulla pagina. */
.voce__segno {
  position: relative;
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  margin-top: 12px;
  transition: transform 0.34s var(--molla-morbida);
}

.voce__segno::before,
.voce__segno::after {
  content: '';
  position: absolute;
  inset: 50% 0 auto;
  height: 2.5px;
  background: var(--fg);
  transform: translateY(-50%);
}

.voce__segno::after { transform: translateY(-50%) rotate(90deg); }

.voce__apri[open] .voce__segno { transform: rotate(45deg); }

/* Tre colonne: descrizione 528, elenco 215, secondo elenco 215. Le distanze
   escono dalle x misurate sul pannello aperto (168 / 769 / 1057). */
.voce__corpo {
  display: flex;
  padding: 48px 48px 36px;
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 27px;
  letter-spacing: -0.02em;
}

.voce__testo {
  width: 528px;
  margin: 0 73px 0 0;
  color: var(--fg);
  text-wrap: pretty;
}

.voce__elenco {
  width: 215px;
  margin: 0 73px 0 0;
  padding: 0;
  list-style: none;
  color: rgba(0, 0, 0, 0.7);
}

.voce__elenco li { position: relative; }

.voce__elenco li::before {
  content: '•';
  position: absolute;
  left: -30px;
}

/* La seconda colonna parte una riga più in basso: è così sulla pagina. */
.voce__elenco--due { margin: 27px 0 0; }

/* --------------------------------------------------------- metodo -- */

.metodo__testa {
  display: flex;
  flex-direction: column;
  gap: 45px;
}

.metodo__sommario {
  max-width: 46ch;
  text-wrap: pretty;
}

.metodo__passi {
  list-style: none;
  margin: clamp(2rem, 4.1vw, 59px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}

.passo {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  min-height: 327px;
  padding: 46px;
  border-radius: 12px;
  background: var(--ghiaccio);
}

.passo__icona { width: 57px; height: 57px; margin-bottom: 20px; }

/* Il numero sta dentro al titolo, come sulla pagina: «1. Studio e ricerca»
   è una riga sola, stesso corpo e stesso peso. */
.passo__titolo {
  margin: 0;
  /* Nelle schede il titolo tiene i 48 anche sullo stretto: va a capo, non
     rimpicciolisce. È così sulla pagina. */
  font-size: 48px;
  line-height: var(--leading-h3);
  letter-spacing: var(--tracking-h3);
  color: var(--fg);
}

.passo__testo { text-wrap: pretty; }

/* --------------------------------------------------------- dendoo -- */

.dendoo__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.dendoo__marchio { width: 258px; height: auto; }

.dendoo__testo--stretto { display: none; }

.dendoo__testo {
  margin: 32px 0 0;
  max-width: 700px;
  font-family: var(--font-text);
  font-size: 20px;
  line-height: 30px;
  color: #12161d;
  text-align: center;
  text-wrap: pretty;
}

/* Sull'originale l'immagine partiva dal filo sinistro e finiva 96 prima del
   destro. Quella però era una foto che riempiva il suo riquadro, e lo
   sbilanciamento si leggeva come una scelta. Questo mockup ha il fondo
   trasportato e attorno al portatile c'è aria: tenuto a sinistra sembrerebbe
   un errore di impaginazione. Quindi sta in mezzo. */
.dendoo__visual {
  display: flex;
  justify-content: center;
  width: 100%;
  margin: clamp(2rem, 5vw, 72px) 0 0;
}

.dendoo__visual img {
  width: min(1104px, 100%);
  height: auto;
  border-radius: 16px;
}

.dendoo .btn { margin-top: clamp(2.5rem, 6.6vw, 95px); }

/* ------------------------------------------------------- contatti -- */

/* Il titolo sta fuori dalla scheda; dentro, il modulo su due colonne. */
/* Fra il tasto di dendoo e «Iniziamo da qui» la pagina lascia 200. */
.contatti { padding-top: clamp(3rem, 8.34vw, 120px); }

.modulo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem 24px;
  max-width: 1104px;
  margin: 60px auto 0;
  padding: 32px;
  border-radius: 16px;
  background: var(--ghiaccio);
}

.campo {
  display: grid;
  gap: 0.5rem;
  margin: 0;
}

/* Email e Messaggio prendono la riga intera; Nome e Cognome si dividono. */
.campo--largo { grid-column: 1 / -1; }

.campo__label {
  font-family: var(--font-text);
  font-size: 15px;
  line-height: 1.5;
  font-weight: 500;
  color: var(--fg);
}

.campo__input {
  font: inherit;
  font-size: 16px;
  color: var(--fg);
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  padding: 0.85rem 1rem;
}

.campo__input::placeholder { color: rgba(0, 0, 0, 0.35); }

.campo__input--testo { resize: vertical; min-height: 100px; }

.campo__input:focus-visible {
  outline: 2px solid var(--tasto);
  outline-offset: 1px;
  border-color: transparent;
}

/* Fra l'ultimo campo e il tasto la scheda lascia aria: è quella che porta la
   scheda a 575, la misura della pagina. */
.modulo .btn { grid-column: 1 / -1; margin-top: 73px; }

/* ------------------------------------------------------- privacy -- */

/* Pagina a sé: niente marchio in cima, una colonna sola e il fondo che parte
   dal ghiaccio e sbianca scendendo. Le misure sono quelle della pagina:
   titolo a 225 dal bordo, corpo in 650 centrati, tasto 120 sotto il testo. */
.privacy {
  padding: 225px 0 0;
  background: linear-gradient(rgb(240, 245, 247) 0%,
                              rgb(240, 245, 247) 10.81%,
                              rgb(255, 255, 255) 100%);
}

.privacy__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.privacy__titolo {
  margin: 0;
  max-width: 600px;
  font-size: var(--text-h2);
  line-height: var(--leading-h2);
  letter-spacing: var(--tracking-h2);
  color: var(--fg);
  text-align: center;
}

.privacy__data {
  margin: 24px 0 0;
  max-width: 600px;
  font-family: var(--font-text);
  font-size: 20px;
  line-height: 30px;
  color: #12161d;
  text-align: center;
}

/* Il corpo è giustificato, come sull'originale, e in un inchiostro più
   morbido del nero dei titoli. */
.privacy__corpo {
  width: 100%;
  max-width: 650px;
  margin: 76px 0 0;
  font-family: var(--font-text);
  font-size: 18px;
  line-height: 27px;
  color: rgb(69, 63, 61);
  text-align: justify;
}

/* Fra un blocco e l'altro passa esattamente una riga vuota. */
.privacy__corpo p { margin: 0 0 27px; }
.privacy__corpo p:last-child { margin-bottom: 0; }

.privacy .btn { margin-top: 120px; }

/* Qui il piede scende molto più del solito: sotto il tasto la pagina lascia
   una campata di bianco prima della fascia nera. */
.privacy + .site-footer { margin-top: 449px; }

@media (max-width: 900px) {
  .privacy { padding-top: clamp(6rem, 24vw, 225px); }
  .privacy__corpo { margin-top: 48px; text-align: left; }
  .privacy .btn { margin-top: 72px; }
  .privacy + .site-footer { margin-top: clamp(4rem, 21vw, 302px); }
}

/* --------------------------------------------------------- piede -- */

/* Fascia nera con i due angoli alti arrotondati: si appoggia sotto la
   pagina bianca invece di continuarla. */
.site-footer {
  margin-top: clamp(3rem, 15.9vw, 229px);
  padding: 80px 0 41px;
  border-radius: 16px 16px 0 0;
  background: #000;
  color: #fff;
}

/* `gap: 0` non è di troppo: la cimentazione dà 2rem a questo stesso
   selettore, e senza azzerarlo resterebbe fra le righe della pila. */
.site-footer__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}

.site-footer__marchio {
  display: grid;
  justify-items: start;
  gap: 20px;
}

/* Il link attorno al marchio non deve aggiungere altezza propria: da inline
   porterebbe lo scarto della riga di testo e spingerebbe giù tutto. */
.site-footer__marchio > a { display: block; line-height: 0; }

.site-footer__claim {
  max-width: 658px;
  color: rgba(255, 255, 255, 0.8);
}

.site-footer__social {
  margin-top: 12px;
  display: inline-flex;
  color: rgba(255, 255, 255, 0.85);
}

.site-footer__social:hover { color: #fff; }

.site-footer__legale {
  margin-top: 70px;
  display: grid;
  gap: 32px;
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.4;
  letter-spacing: -0.02em;
  text-align: right;
  color: #fff;
}

.site-footer__legale p { margin: 0; }
.site-footer__legale a { color: inherit; }
.site-footer__legale a:hover { text-decoration: underline; }

.site-footer__privacy {
  justify-self: start;
  margin-top: 32px;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: -0.02em;
  color: rgb(186, 186, 186);
}

.site-footer__privacy { transition: color 0.2s var(--curva-pagina); }
.site-footer__privacy:hover { color: #fff; }

/* ------------------------------------------------------- stretto -- */

@media (max-width: 900px) {
  .metodo__passi { grid-template-columns: 1fr; }
  .passo { min-height: 0; padding: 32px; }

  .prodotti__testa { align-items: flex-start; }
  .titolo-sezione,
  .prodotti__sommario { text-align: left; }

  /* 21+29.7+21 fa i 72 della pastiglia chiusa sullo stretto. */
  .voce__riga { padding: 21px 24px; }
  .voce__apri[open] > .voce__riga { padding: 24px 24px 0; }
  /* Sullo stretto le tre colonne si mettono in fila indiana. */
  .voce__corpo { flex-direction: column; gap: 24px; padding: 24px 24px 28px; }
  .voce__testo { width: auto; margin: 0; }
  .voce__elenco { width: auto; margin: 0 0 0 30px; }
  .voce__elenco--due { margin-top: 0; }

  .modulo { grid-template-columns: 1fr; padding: 24px; }

  .site-footer__legale { margin-top: 2.5rem; text-align: left; }
  .site-footer__privacy { margin-top: 2.5rem; }

  .clienti__pista, .clienti__nastro { gap: 40px; }
  @keyframes clienti-scorri {
    from { transform: translateX(0); }
    to { transform: translateX(calc(-100% - 40px)); }
  }
}

@media (max-width: 600px) {
  .logo { height: 40px; }
  .logo--bianco { height: 56px; }
  .hero__riga { margin-top: 12px; }
  .hero__lead { margin-top: 32px; }
  .hero .btn { margin-top: 36px; }
  .dendoo__marchio { width: 200px; }
  .dendoo__testo { font-size: 18px; line-height: 27px; }
  .dendoo__testo--largo { display: none; }
  .dendoo__testo--stretto { display: block; }
}


/* Stato, validazione e protezioni del modulo contatti. */
.modulo__trap {
  position: absolute !important;
  left: -10000px !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
}

.campo__error {
  min-height: 1.25em;
  font-family: var(--font-text);
  font-size: 14px;
  line-height: 1.25;
  color: #a12622;
}

.campo.is-invalid .campo__input {
  border-color: #a12622;
}

.modulo__check {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  font-family: var(--font-text);
  font-size: 15px;
  line-height: 1.5;
}

.modulo__check input { margin-top: 0.25rem; }
.modulo__check a { text-decoration: underline; }

.modulo__verifica { min-height: 65px; }

.modulo__feedback {
  max-width: 1104px;
  margin: 32px auto 0;
  padding: 1rem 1.25rem;
  border-radius: 10px;
  font-family: var(--font-text);
  line-height: 1.5;
}

.modulo__feedback--success {
  background: #e8f5ee;
  color: #174c32;
}

.modulo__feedback--failure {
  background: #faeceb;
  color: #7f201d;
}

.modulo .modulo__feedback {
  margin: 0;
}

.modulo .btn { margin-top: 1.5rem; }
