/* Hallmark · genre: atmospheric · design-system: design.md · designed-as-app
 * macrostructure: Marquee Hero (vetrina) · Workbench (lavoro) · Index-First
 *                 (indice) · Long Document (lettura)
 * theme: lumen · drop: night-foundry · nav: N3 side-rail · footer: Ft5 statement
 * enrichment: apparato costruito — banda di memoria (Tier-A CSS+SVG)
 * axes: dark / classical-serif-lowercase / brass-50
 * pre-emit critique: P5 H5 E4 S5 R4 V5
 * deroghe dichiarate in design.md: nomi propri con maiuscole · token in
 * italiano · nessuna libreria di movimento
 */

/* Nicola Sabaini — foglio di stile unico
   =====================================
   Nessuno stile inline, nessuno script inline, nessuna richiesta a terzi:
   e' cio' che permette al server di tenere una Content-Security-Policy
   stretta senza 'unsafe-inline', condivisa con gli altri siti della macchina.
   Un solo style="..." aggiunto qui per comodita' costringerebbe ad allentare
   la policy per tutti.

   Nessun font dal web: i caratteri di sistema non costano una richiesta ne'
   un handshake TLS, e su una macchina con poca CPU la differenza si vede.

   Indice
   0.  Caratteri            9.  Riga di tre numeri   18. Prosa
   1.  Token               10.  Sezioni              19. Piede
   2.  Azzeramento         11.  Schede progetto      20. Preferenze utente
   3.  Guscio              12.  Pila dei progetti    21. Movimento
   4.  Side-rail           13.  Specifiche           22. Galleria
   5.  Salta e focus       14.  Bottoni              23. Telefono
   6.  Occhielli           15.  Articoli             24. Stampa
   7.  Apertura            16.  Da un pezzo al poi   25. Fosforo
   8.  Apparato + meter    17.  Intestazioni interne 26. Dettagli            */


/* 0. Caratteri ─────────────────────────────────────────────────────────────
   Tre famiglie, tre mestieri, tutte da questo dominio. Non da Google: la CSP
   della macchina dichiara `font-src 'self'`, e caricarli da fonts.gstatic.com
   vorrebbe dire allentarla per ogni sito ospitato qui — oltre a raccontare a
   Google chi passa da questa pagina.

   Instrument Serif fa i titoli: e' un serif da rivista tecnica anni Sessanta.
   Instrument Sans fa il corpo — stessa fonderia, disegnato per stare con
   l'altro. JetBrains Mono fa le etichette, e solo quelle.

   Qui c'era Geist. E' un carattere ben fatto, ma sta addosso a mezzo web di
   strumenti AI: su un sito il cui scopo dichiarato e' non sembrare generato,
   il carattere di Vercel su ogni riga di testo lavorava contro. Instrument
   Sans e' della stessa mano di Instrument Serif, quindi il sistema chiude.

   Divisi per sottoinsieme: `latin` basta all'italiano e all'inglese,
   `latin-ext` si scarica solo se in pagina compare un carattere che lo
   richiede. Chi legge in italiano scarica 82 kB, una volta sola, e poi mai
   piu' — il nome del foglio porta l'impronta del contenuto, quindi la cache
   puo' essere eterna senza rischi.

   `font-display: swap`: il testo si legge subito col carattere di sistema e
   viene sostituito quando il file arriva. Mai una pagina bianca in attesa.  */

@font-face {
    font-family: "Instrument Serif";
    src: url("/caratteri/instrument-serif-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                   U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                   U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                   U+FFFD;
}

@font-face {
    font-family: "Instrument Serif";
    src: url("/caratteri/instrument-serif-latin-ext.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                   U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                   U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                   U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "Instrument Sans";
    src: url("/caratteri/instrument-sans-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                   U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                   U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                   U+FFFD;
}

@font-face {
    font-family: "Instrument Sans";
    src: url("/caratteri/instrument-sans-latin-ext.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                   U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                   U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                   U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: "JetBrains Mono";
    src: url("/caratteri/jetbrains-mono-latin.woff2") format("woff2");
    font-weight: 100 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                   U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                   U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                   U+FFFD;
}

@font-face {
    font-family: "JetBrains Mono";
    src: url("/caratteri/jetbrains-mono-latin-ext.woff2") format("woff2");
    font-weight: 100 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F,
                   U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                   U+2C60-2C7F, U+A720-A7FF;
}


/* 1. Token ─────────────────────────────────────────────────────────────────
   Night Foundry: carta viola-nera, accento ottone fuso. Il viola a 265 gradi
   non e' un vezzo — tiene la carta lontana dal blu di ogni pannello scuro
   generato, e fa leggere l'ottone come metallo caldo invece che come giallo.

   Due colori con due mestieri: l'ottone segna cio' che si tocca e cio' che
   lo strumento emette; il corallo segna una parola sola per titolo, il verbo.
   Mai un terzo.                                                            */

:root {
    color-scheme: dark;

    /* Carta e inchiostro */
    --fondo:          oklch(13%  0.014 265);
    --fondo-alto:     oklch(17%  0.016 265);
    --fondo-cima:     oklch(22%  0.018 263);
    --riga:           oklch(30%  0.018 265);
    --riga-forte:     oklch(42%  0.020 263);
    --fioco:          oklch(60%  0.016 263);   /* 5,08:1 — minimo per il testo piccolo */
    --inciso:         oklch(50%  0.018 265);   /* 3,3:1 — SOLO testo da 24px in su */
    --tenue:          oklch(72%  0.014 263);
    --testo:          oklch(82%  0.010 262);
    --testo-alto:     oklch(96%  0.006 262);

    /* Accento e corda */
    --ottone:         oklch(76%  0.17  50);
    --corallo:        oklch(68%  0.16  18);
    --su-ottone:      oklch(13%  0.014 265);
    --fuoco:          oklch(76%  0.17  50);

    /* Fisica dello strumento: l'apparato contiene la luce, la carta la lascia
       passare appena. Nessun bagliore piu' grande dell'apparato. */
    --alone:          oklch(80%  0.16  50 / 0.42);
    --alone-fioco:    oklch(80%  0.16  50 / 0.12);
    --emissione:      oklch(76%  0.17  50 / 0.04);
    --filo-blueprint: oklch(96%  0.006 262 / 0.045);

    /* Caratteri */
    /* Il carattere di ripiego non deve cambiare l'ingombro del testo quando
       il woff2 arriva: se lo cambia, il titolo va a capo in un altro punto e
       la pagina salta sotto gli occhi di chi sta leggendo. `font-size-adjust`
       scala il ripiego finche' una sua misura non coincide con quella del
       carattere vero. Quale misura, pero', si sceglie misurando.

       Scarto di larghezza fra ripiego e carattere definitivo, preso in
       Chrome sui titoli e sui testi veri del sito:

                       senza     altezza x     larghezza dello 0
         display       +38%        +47%              +1%
         prosa          -2%         -0%             +21%
         etichette     ±10%        ±15%             ±14%

       Da cui le tre scelte, che non sono la stessa:

       - Il display si aggancia alla larghezza dello zero. Georgia e' molto
         piu' larga di Instrument Serif, e agganciarla all'altezza della x la
         faceva pure crescere: il rimedio peggiorava il salto. Cosi' invece
         il ripiego occupa la stessa riga, e resta un filo piu' piccolo per
         qualche centinaio di millisecondi. E' il baratto giusto: il corpo si
         nota molto meno di un titolo che si riscrive.
       - La prosa si aggancia all'altezza della x, che e' il caso normale.
       - Le etichette a niente. Hanno 0,10em di crenatura, e la crenatura non
         scala insieme al carattere: nessun aggancio le fa quadrare, e ogni
         tentativo allarga lo scarto invece di chiuderlo. Lasciarle stare e'
         la scelta misurata, non la pigrizia — per questo sta scritto. */
    --occhio-prosa:  0.51;   /* altezza della x di Instrument Sans */
    --zero-display:  0.46;   /* larghezza dello zero di Instrument Serif */

    --display: "Instrument Serif", "Tiempos Headline", ui-serif, Georgia, serif;
    --prosa:   "Instrument Sans", ui-sans-serif, system-ui, -apple-system,
               "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --mono:    "JetBrains Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo,
               Consolas, "Liberation Mono", monospace;

    /* Scala tipografica */
    --display-grande: clamp(3rem, 6.5vw + 0.75rem, 6.75rem);
    --display-medio:  clamp(2.25rem, 3.75vw + 1rem, 3.75rem);
    --display-basso:  clamp(1.75rem, 2vw + 1rem, 2.5rem);

    --crena-display: -0.032em;
    --crena-stretta: -0.014em;
    --crena-etichetta: 0.10em;
    --crena-callout:   0.16em;

    --alt-stretta: 1.02;
    --alt-snella:  1.18;
    --alt-normale: 1.6;
    --alt-larga:   1.75;

    /* Spazio: scala a 4 punti, nomi e non numeri */
    --spazio-3xs: 0.25rem;
    --spazio-2xs: 0.5rem;
    --spazio-xs:  0.75rem;
    --spazio-sm:  1rem;
    --spazio-md:  1.5rem;
    --spazio-lg:  2rem;
    --spazio-xl:  3rem;
    --spazio-2xl: 4.5rem;
    --spazio-3xl: 7rem;

    --stacco-sezione: clamp(4rem, 9vw, 6.5rem);
    --misura:  62ch;
    --colonna: 74rem;
    --gutter:  clamp(20px, 4vw, 48px);
    --rail:    clamp(56px, 6vw, 88px);   /* larghezza della side-rail */

    /* Forma */
    --raggio-scheda: 10px;
    --raggio-input:  8px;
    --raggio-pillola: 999px;
    --filo: 1px;
    --ombra-alta: 0 24px 60px -28px oklch(0% 0 0 / 0.55),
                  0 1px 2px oklch(0% 0 0 / 0.4);

    /* Movimento: tre andamenti con un nome, mai `ease` del browser */
    --uscita:  cubic-bezier(0.22, 0.61, 0.36, 1);
    --entrata: cubic-bezier(0.55, 0, 1, 0.45);
    --morbido: cubic-bezier(0.65, 0, 0.35, 1);
    --breve:   180ms;
    --medio:   320ms;
    --lungo:   600ms;
    --pulsazione: 4s;
}

/* Il chiaro non e' un secondo tema: e' lo stesso strumento sotto un'altra
   luce. Carta e inchiostro si ribaltano, l'ottone scende di luminosita' per
   restare leggibile sopra 4,5:1, l'apparato smette di emettere e si limita a
   segnare. Bianco puro e nero puro sono due modi diversi di stancare gli
   occhi: qui la carta e' ossa fredde con lo stesso tilt viola.             */
@media (prefers-color-scheme: light) {
    :root {
        color-scheme: light;

        --fondo:          oklch(97%  0.008 265);
        --fondo-alto:     oklch(99%  0.004 265);
        --fondo-cima:     oklch(94%  0.010 265);
        --riga:           oklch(88%  0.012 265);
        --riga-forte:     oklch(74%  0.014 265);
        --fioco:          oklch(50%  0.018 265);   /* 4,63:1 sulla carta */
        --inciso:         oklch(62%  0.016 265);   /* 3,1:1 — solo testo grande */
        --tenue:          oklch(40%  0.018 265);
        --testo:          oklch(26%  0.016 265);
        --testo-alto:     oklch(16%  0.014 265);

        --ottone:         oklch(48%  0.15  50);    /* 4,71:1 sulla carta */
        --corallo:        oklch(50%  0.18  18);
        --su-ottone:      oklch(99%  0.004 265);
        --fuoco:          oklch(48%  0.15  50);

        --alone:          oklch(48%  0.15  50 / 0.22);
        --alone-fioco:    oklch(48%  0.15  50 / 0.08);
        --emissione:      oklch(48%  0.15  50 / 0.035);
        --filo-blueprint: oklch(16%  0.014 265 / 0.05);

        --ombra-alta: 0 20px 48px -30px oklch(20% 0.02 265 / 0.35),
                      0 1px 2px oklch(20% 0.02 265 / 0.12);
    }
}


/* 2. Azzeramento ───────────────────────────────────────────────────────── */

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

/* `clip` e non `hidden`: hidden su html/body rompe `position: sticky` in
   mezza pagina, ed e' la pila dei progetti a dipenderne. */
html {
    overflow-x: clip;
    scroll-behavior: smooth;
    /* La side-rail non deve coprire il titolo raggiunto da un'ancora. */
    scroll-padding-top: var(--spazio-xl);
}

body {
    margin: 0;
    overflow-x: clip;
    background: var(--fondo);
    color: var(--testo);
    font-family: var(--prosa);
    font-size-adjust: var(--occhio-prosa);
    font-size: clamp(1rem, 0.35vw + 0.95rem, 1.0625rem);
    line-height: var(--alt-normale);
    font-variant-numeric: tabular-nums;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-weight: 400;
    font-style: normal;           /* mai corsivo: e' il tell piu' affidabile */
    color: var(--testo-alto);
    letter-spacing: var(--crena-display);
    line-height: var(--alt-stretta);
    /* gate 51: un titolo display non deve mai sfondare lo schermo stretto */
    overflow-wrap: anywhere;
    min-width: 0;
    margin: 0;
    text-wrap: balance;
}

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

img, svg, video { max-width: 100%; height: auto; display: block; }

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

::selection {
    background: var(--ottone);
    color: var(--su-ottone);
}


/* 3. Guscio ────────────────────────────────────────────────────────────────
   La pagina intera e' spostata a destra della side-rail. Un solo posto in cui
   si decide la larghezza della colonna di lettura.                         */

body {
    padding-left: var(--rail);
}

.guscio {
    width: 100%;
    max-width: var(--colonna);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

main { display: block; }


/* 4. Side-rail ─────────────────────────────────────────────────────────────
   N3. Il nome in verticale sul bordo, le destinazioni numerate sotto. Non e'
   una barra che scorre con la pagina: sta ferma, come la costola di un
   raccoglitore. Sotto i 60rem diventa una barra in cima, perche' su un
   telefono il bordo sinistro e' pollice, non spazio.                       */

.rail {
    position: fixed;
    inset-block: 0;
    left: 0;
    width: var(--rail);
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    padding-block: var(--spazio-md);
    border-right: var(--filo) solid var(--riga);
    background: var(--fondo);
}

.rail-marchio {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--testo-alto);
    white-space: nowrap;
    writing-mode: vertical-rl;
    transform: rotate(180deg);   /* si legge dal basso, come una costola */
    padding-block: var(--spazio-xs);
}

/* Il contenitore resta in scrittura orizzontale e impila normalmente; e'
   ogni singola voce a girare. Mettere `writing-mode: vertical-rl` sul
   contenitore ribalta anche gli assi del flex — `column` seguirebbe l'asse di
   blocco, che in verticale e' orizzontale, e le voci uscirebbero dallo
   schermo a sinistra invece di incolonnarsi. */
.rail-voci {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spazio-lg);
}

.rail-voce {
    writing-mode: vertical-rl;
    transform: rotate(180deg);   /* si legge dal basso, come la costola */
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    letter-spacing: var(--crena-callout);
    text-transform: uppercase;
    color: var(--tenue);
    white-space: nowrap;          /* gate 49: mai un link su due righe */
    padding: var(--spazio-2xs) var(--spazio-3xs);
    transition: color var(--breve) var(--uscita);
}

.rail-voce::before {
    content: attr(data-numero) " ";
    color: var(--fioco);
}

.rail-voce:hover,
.rail-voce:focus-visible { color: var(--testo-alto); }

.rail-voce[aria-current="page"] { color: var(--ottone); }
.rail-voce[aria-current="page"]::before { color: var(--ottone); }

.rail-coda {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spazio-sm);
}

.rail-lingua {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--fioco);
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
    padding: var(--spazio-2xs) var(--spazio-xs);
    transition: color var(--breve) var(--uscita),
                border-color var(--breve) var(--uscita);
}

.rail-lingua:hover,
.rail-lingua:focus-visible {
    color: var(--testo-alto);
    border-color: var(--riga-forte);
}

/* Il filo che corre lungo la rail: e' la stessa lingua della griglia
   blueprint, non un ornamento. */
.rail-filo {
    flex: 1;
    width: var(--filo);
    background: linear-gradient(to bottom,
                transparent, var(--riga) 20%, var(--riga) 80%, transparent);
    margin-block: var(--spazio-sm);
}


/* 5. Salta e focus ─────────────────────────────────────────────────────────
   L'anello di focus non si anima mai: deve comparire nell'istante in cui il
   focus arriva, o chi naviga col Tab perde il segno.                       */

.salta {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: var(--ottone);
    color: var(--su-ottone);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.75rem;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    padding: var(--spazio-xs) var(--spazio-md);
    border-radius: 0 0 var(--raggio-input) 0;
}

.salta:focus {
    left: var(--rail);
}

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

main:focus { outline: none; }


/* 6. Occhielli ─────────────────────────────────────────────────────────────
   Il registro mono MAIUSCOLO e' l'unica superficie maiuscola del sito. E'
   il contrasto fra prosa quieta e lettura di macchina a fare la firma.

   Stanno sempre SOPRA il titolo, nella stessa colonna. Etichetta a sinistra e
   titolo a destra e' il segno editoriale piu' riconoscibile fra quelli
   generati, e qui non si usa.                                             */

.etichetta,
.callout,
.meter-etichetta,
.numero-etichetta,
.scheda-genere,
.durata,
.quando,
.tag-riga li {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--fioco);
    font-variant-numeric: tabular-nums;
}

.etichetta { margin-bottom: var(--spazio-sm); }
.etichetta a { color: inherit; border-bottom: var(--filo) solid var(--riga); }
.etichetta a:hover { color: var(--ottone); border-bottom-color: var(--ottone); }


/* 7. Apertura ──────────────────────────────────────────────────────────────
   Marquee Hero. Il nome in grande a sinistra, l'apparato a destra, e sotto la
   frase che dice il mestiere con un verbo solo in colore.

   La griglia blueprint al 4% e' il segnale "progettato, non vibrato": Aurora
   mette bagliori, Lumen mette la griglia. Sotto ci passa l'emissione, cosi'
   la carta sembra emettere attraverso le linee.                            */

.apertura {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spazio-2xl);
    padding-block: clamp(3rem, 8vw, 6rem) var(--spazio-2xl);
    overflow: clip;              /* l'alone dell'apparato resta dentro */
}

.apertura::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        linear-gradient(var(--filo-blueprint) 1px, transparent 1px) 0 0 / 48px 48px,
        linear-gradient(90deg, var(--filo-blueprint) 1px, transparent 1px) 0 0 / 48px 48px,
        radial-gradient(58% 48% at 78% 32%, var(--emissione) 0%, transparent 65%);
    mask-image: linear-gradient(to bottom, black 55%, transparent 100%);
}

@media (min-width: 62rem) {
    .apertura {
        grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
        align-items: start;
        gap: var(--spazio-xl);
    }
}

.apertura-testo { min-width: 0; }

.apertura-firma {
    display: flex;
    align-items: center;
    gap: var(--spazio-sm);
    margin-bottom: var(--spazio-md);
}

/* Adesso qui dentro c'e' il mestiere, non la parola «profilo»: la riga e'
   piu' lunga e deve poter andare a capo accanto al ritratto senza spingere
   fuori niente. */
.apertura-firma .etichetta {
    margin-bottom: 0;
    min-width: 0;
    line-height: var(--alt-snella);
}

/* Il nome tiene le maiuscole: e' un nome proprio, non prosa. */
.apertura h1 {
    font-size: var(--display-grande);
    max-width: 12ch;
    margin-bottom: var(--spazio-md);
}

/* Il mestiere: la riga che un recruiter legge per prima, e deve poterla
   leggere davvero. Corpo di lettura, non etichetta mono maiuscola da 11px:
   cinquanta caratteri in maiuscoletto spaziato sono il fatto che qualifica
   Nicola reso nel testo meno leggibile della pagina. */
.mestiere {
    font-size: 1.0625rem;
    line-height: var(--alt-snella);
    color: var(--tenue);
    margin-bottom: var(--spazio-md);
    max-width: 46ch;
}

/* La frase che dichiara il mestiere. Minuscola, con una parola sola in
   corallo: il verbo. Mai due, mai un sostantivo. */
.claim {
    /* Frase corta, su piu' righe, senza cornice: e' il caso per cui
       `balance` esiste. Sulle schede invece non va: pareggiare le righe
       dentro un riquadro con lo sfondo lascia vuoti che si vedono. */
    text-wrap: balance;
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: var(--display-medio);
    line-height: var(--alt-snella);
    letter-spacing: var(--crena-stretta);
    color: var(--testo-alto);
    text-transform: lowercase;
    max-width: 18ch;
    margin-bottom: var(--spazio-md);
}

/* <em> e' ridefinito: non e' corsivo, e' il verbo. Colore piu' un filo che si
   disegna una volta sola e poi resta. */
.claim em {
    font-style: normal;
    color: var(--corallo);
    position: relative;
    white-space: nowrap;
}

.claim em::after {
    content: "";
    position: absolute;
    left: 0.05em;
    right: 0.05em;
    bottom: 0.02em;
    height: 1px;
    background: var(--corallo);
    transform-origin: left;
    animation: filo-verbo var(--medio) var(--uscita) 700ms backwards;
}

@keyframes filo-verbo {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.ruolo {
    color: var(--testo);
    font-size: 1.0625rem;
    line-height: var(--alt-larga);
    max-width: 48ch;
    margin-bottom: var(--spazio-lg);
}

/* Due richiami sulla stessa riga: «chi sono» e «scrivimi». Su schermo
   stretto vanno a capo e restano leggibili, non si stringono. */
.apertura-oltre {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spazio-sm) var(--spazio-lg);
    margin-top: var(--spazio-md);
}


/* 8. Apparato e meter ──────────────────────────────────────────────────────
   Lumen vieta la sfera luminosa e pretende un oggetto costruito, che dica
   cosa fa la cosa. Qui l'oggetto c'era gia': 512 celle da un kilobyte,
   diciotto libere. Era un disegno, adesso e' lo strumento della pagina.

   Le annotazioni portano valori veri. Un callout con `LOREM · 000` dentro
   sarebbe esattamente il contrario di cio' che l'apparato serve a dire.    */

.apparato {
    position: relative;
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-scheda);
    background:
        radial-gradient(70% 60% at 50% 40%, var(--alone-fioco) 0%, transparent 70%),
        var(--fondo-alto);
    padding: var(--spazio-md);
    min-width: 0;
}

/* Le quattro angolature: lo stesso segno dei mirini e dei disegni tecnici.
   Dicono "questo e' uno strumento" senza scriverlo. */
.apparato::before,
.apparato::after {
    content: "";
    position: absolute;
    width: 10px;
    height: 10px;
    border: var(--filo) solid var(--riga-forte);
    pointer-events: none;
}

.apparato::before {
    top: -1px; left: -1px;
    border-right: 0; border-bottom: 0;
}

.apparato::after {
    bottom: -1px; right: -1px;
    border-left: 0; border-top: 0;
}

.apparato-titolo {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--tenue);
    display: flex;
    justify-content: space-between;
    gap: var(--spazio-sm);
    padding-bottom: var(--spazio-sm);
    border-bottom: var(--filo) solid var(--riga);
    margin-bottom: var(--spazio-md);
}

.apparato-titolo span:last-child { color: var(--ottone); }

.banda-memoria { margin: 0; }

.memoria { width: 100%; height: auto; }

.memoria .spenta { fill: var(--riga); }

/* Le diciotto accese sono l'unica cosa che emette. Il filtro e' un alone
   morbido, non un bagliore: l'apparato contiene la luce, non la spara. */
.memoria .viva,
.memoria .occupata {
    fill: var(--ottone);
    filter: drop-shadow(0 0 3px var(--alone));
}

.memoria .occupata { fill: var(--corallo); }

.memoria-viva { cursor: pointer; }

.memoria-viva:hover .viva { fill: var(--testo-alto); }

.banda-memoria figcaption {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    color: var(--fioco);
    line-height: var(--alt-snella);
    min-height: 2.4em;
    margin-top: var(--spazio-sm);
}

/* I callout: micro-tipografia mono su linea guida. Tre o cinque, mai zero. */
.callouts {
    display: grid;
    gap: var(--spazio-2xs);
    margin-top: var(--spazio-md);
    padding-top: var(--spazio-sm);
    border-top: var(--filo) solid var(--riga);
}

.callout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--spazio-sm);
    font-size: 0.625rem;
    letter-spacing: var(--crena-callout);
}

/* La linea guida vera e propria: unisce l'etichetta al valore, come su un
   disegno quotato. */
.callout > span:first-child {
    display: grid;
    grid-template-columns: auto minmax(var(--spazio-sm), 1fr);
    align-items: center;
    gap: var(--spazio-2xs);
}

.callout > span:first-child::after {
    content: "";
    height: 1px;
    background: var(--riga);
}

.callout > span:last-child {
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
}

.apparato-stack {
    margin-top: var(--spazio-md);
    padding-top: var(--spazio-sm);
    border-top: var(--filo) solid var(--riga);
}

.apparato-stack .etichetta { margin-bottom: var(--spazio-2xs); }

.pannello-stack {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.75rem;
    line-height: var(--alt-normale);
    color: var(--tenue);
    overflow-wrap: anywhere;
}

/* Il meter strip: una stampa di misura, non un flusso in diretta. Statico di
   proposito — una barra che si agita da sola e' decorazione che finge di
   essere dato. Le altezze vengono da un inviluppo, non dal caso. */
.meter {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--spazio-md);
    padding: var(--spazio-xs) 0;
    border-block: var(--filo) solid var(--riga);
    background:
        linear-gradient(90deg, var(--filo-blueprint) 1px, transparent 1px) 0 0 / 48px 48px;
}

/* Le tacche sono un SVG, non 64 <span> con un'altezza inline: la CSP vieta
   `style="..."` e un attributo di presentazione SVG non e' uno stile inline.
   Le altezze vengono da un inviluppo calcolato una volta sola, non dal caso:
   una fila di tacche tutte uguali legge come motivo decorativo, non come
   misura. */
.meter-barre {
    min-width: 0;
    line-height: 0;
}

.meter-barre svg {
    width: 100%;
    height: 26px;
    display: block;
}

.meter-barre rect { fill: var(--ottone); }

.meter-etichetta { white-space: nowrap; }


/* 9. Riga di tre numeri ────────────────────────────────────────────────────
   Tre celle. Due leggono come un confronto, quattro come un bento. I numeri
   sono veri e verificabili: se un giorno non lo fossero piu', questa riga va
   tolta, non aggiornata a occhio.                                          */

.numeri {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-scheda);
    overflow: clip;
    margin-top: var(--spazio-xl);
}

.numero {
    padding: var(--spazio-md) var(--spazio-sm);
    border-right: var(--filo) solid var(--riga);
    min-width: 0;
}

.numero:last-child { border-right: 0; }

.numero-valore {
    display: block;
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: clamp(2rem, 3.2vw + 0.75rem, 3.25rem);
    line-height: 1;
    letter-spacing: var(--crena-display);
    color: var(--testo-alto);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.numero-etichetta {
    display: block;
    margin-top: var(--spazio-2xs);
    line-height: var(--alt-snella);
}


/* 10. Sezioni ──────────────────────────────────────────────────────────────
   La testata di sezione e' una colonna sola: occhiello mono numerato, poi il
   titolo. Il rimando "tutti i…" va sotto, non a destra del titolo.         */

.sezione {
    padding-block: var(--stacco-sezione);
    border-top: var(--filo) solid var(--riga);
}

.sezione-attaccata { border-top: 0; padding-top: var(--spazio-lg); }

.sezione-testata {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spazio-2xs);
    margin-bottom: var(--spazio-xl);
}

.sezione-testata h2 {
    font-size: var(--display-basso);
    text-transform: lowercase;
}

.sezione-numero {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--fioco);
}

.sezione-numero::after {
    /* Il separatore c'era e la parola no: usciva «01 ·» e poi il vuoto, cioe'
       un punto che non separa niente. Il titolo sta gia' nell'h2 sotto, quindi
       il punto se ne va e resta il numero, che e' l'ancora del ritmo. */
    content: none;
}

.oltre {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--ottone);
    white-space: nowrap;
    border-bottom: var(--filo) solid transparent;
    transition: border-color var(--breve) var(--uscita);
}

.oltre::after {
    content: " →";
}

.oltre:hover,
.oltre:focus-visible { border-bottom-color: var(--ottone); }

.sezione-testata .oltre { margin-top: var(--spazio-2xs); }

/* Il rimando in coda all'elenco esiste solo dove l'elenco viene troncato,
   cioe' su telefono. Su schermo largo si vedono tutti i progetti e un
   "tutti i progetti" in fondo a tutti i progetti non vuol dire niente. */
.oltre-in-coda { display: none; }


/* 11. Schede progetto ──────────────────────────────────────────────────────
   Workbench. Il lavoro si mostra: dove esiste una schermata vera si mette
   quella, il glifo disegnato resta il ripiego per cio' che non ha una faccia.

   Le schede NON sono sei righe identiche. La prima e' in rilievo e occupa
   tutta la larghezza; le altre alternano il lato della schermata. Sei righe
   uguali immagine-a-sinistra sono l'anti-pattern piu' citato del mestiere.  */

.elenco-progetti {
    display: grid;
    gap: var(--spazio-lg);
}

.scheda {
    position: relative;
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-scheda);
    background:
        radial-gradient(90% 70% at 50% 0%, var(--emissione) 0%, transparent 70%),
        var(--fondo-alto);
    padding: var(--spazio-md);
    min-width: 0;
    transition: transform var(--medio) var(--uscita),
                border-color var(--medio) var(--uscita),
                background-color var(--medio) var(--uscita);
}

/* Emissione interna che sale, non ombra portata. Lumen usa l'ombra solo per
   la cromatura elevata; le schede sono illuminate da dentro. */
.scheda:hover {
    transform: translateY(-4px);
    border-color: var(--riga-forte);
    background:
        radial-gradient(90% 70% at 50% 0%, var(--alone-fioco) 0%, transparent 70%),
        var(--fondo-alto);
}

.scheda:focus-within {
    border-color: var(--ottone);
}

@media (min-width: 52rem) {
    .scheda {
        display: grid;
        grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
        gap: var(--spazio-lg);
        align-items: start;
        padding: var(--spazio-lg);
    }

    /* Le pari ribaltano il lato: il ritmo non e' una fila. */
    .elenco-progetti > .scheda:nth-child(even):not(.scheda-rilievo) {
        grid-template-columns: minmax(0, 1fr) minmax(0, 19rem);
    }

    .elenco-progetti > .scheda:nth-child(even):not(.scheda-rilievo) .scheda-media {
        order: 2;
    }
}

.scheda-indice {
    display: flex;
    align-items: baseline;
    gap: var(--spazio-sm);
    margin-bottom: var(--spazio-sm);
}

@media (min-width: 52rem) {
    .scheda-indice {
        grid-column: 1 / -1;
        padding-bottom: var(--spazio-sm);
        border-bottom: var(--filo) solid var(--riga);
        margin-bottom: 0;
    }
}

/* Qui stava `.scheda-numero`, il 01 / 02 / 03 davanti a ogni progetto. Tolto:
   numerare un elenco dice al lettore che e' una classifica, e questo non lo
   e'. Resta il genere, che e' un'informazione vera. */

.scheda-media { min-width: 0; }

.scheda-media img,
.scheda-media svg {
    width: 100%;
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
    background: var(--fondo);
}

.scheda-ritratto .scheda-media img { max-width: 18rem; }

.scheda-corpo { min-width: 0; }

.scheda-corpo h2,
.scheda-corpo h3 {
    font-size: clamp(1.5rem, 1.4vw + 1.1rem, 2rem);
    margin-bottom: var(--spazio-2xs);
}

.scheda-corpo h2 a,
.scheda-corpo h3 a {
    border-bottom: var(--filo) solid transparent;
    transition: border-color var(--breve) var(--uscita),
                color var(--breve) var(--uscita);
}

.scheda-corpo h2 a:hover,
.scheda-corpo h3 a:hover {
    color: var(--ottone);
    border-bottom-color: var(--ottone);
}

.sommario {
    text-wrap: pretty;
    color: var(--testo);
    max-width: var(--misura);
    margin-bottom: var(--spazio-md);
}

/* La prima scheda prende tutta la larghezza e la schermata va sopra: e' il
   pezzo forte, e non si legge come le altre. */
@media (min-width: 52rem) {
    .scheda-rilievo {
        grid-template-columns: minmax(0, 1fr);
        padding: var(--spazio-lg);
    }

    .scheda-rilievo .scheda-media img { max-height: 30rem; object-fit: cover; }

    .scheda-rilievo .scheda-corpo {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
        gap: var(--spazio-lg);
        align-items: start;
    }

    .scheda-rilievo .specifiche { margin-top: 0; }
}


/* 12. Pila dei progetti ────────────────────────────────────────────────────
   Le schede si impilano mentre si scorre: ognuna si ferma sotto la
   precedente, e la pila cresce. E' scroll-driven CSS nativo — nessuna
   libreria, nessun listener, e con JavaScript spento resta un elenco
   normale che si legge dall'alto in basso.

   Solo da tablet in su, e solo se il browser sa fare `animation-timeline`:
   su un telefono la pila ruberebbe schermo a cio' che conta.              */

@supports (animation-timeline: view()) {
    @media (min-width: 62rem) and (prefers-reduced-motion: no-preference) {
        .elenco-progetti {
            gap: var(--spazio-xl);
        }

        /* Ogni scheda si ferma un filo piu' in basso della precedente: si
           vede il bordo di quelle sotto, come fogli impilati sul tavolo.
           Scritto a mano e non con una variabile inline, perche' la CSP
           vieta `style="..."` e un `--indice` nel markup sarebbe quello. */
        /* La scheda in rilievo resta fuori dalla pila. E' alta piu' di uno
           schermo, e una cosa piu' alta della finestra non si "appiccica":
           resterebbe ferma mezza fuori vista mentre le altre le scorrono
           addosso. Il pezzo forte si legge intero, poi comincia la pila. */
        .elenco-progetti > .scheda:not(.scheda-rilievo) {
            position: sticky;
            top: var(--spazio-xl);
            animation: pila-esce linear both;
            animation-timeline: view();
            animation-range: exit 20% exit 100%;
            /* Da qui in giu' si puo' chiedere se la scheda e' ferma in cima
               davvero, invece di dedurlo con un listener sullo scroll. Il
               nome e' obbligatorio: senza, query annidate si pestano. */
            container-type: scroll-state;
            container-name: pila;
        }

        /* La scheda appiccicata in cima e' quella che il lettore sta
           guardando: il filo sotto l'intestazione si marca e il genere
           smette di essere un sussurro. Cambia solo colore — nessuna
           misura, nessun riquadro che si sposta — e quindi non serve
           spegnere l'ancoraggio dello scroll sul genitore.

           La query la leggono i discendenti, mai il contenitore stesso:
           `.scheda` non puo' stilarsi da sola, e non ce n'e' bisogno.

           Chrome e Edge dal 133. Altrove la pila resta quella di prima,
           che gia' funziona: e' un di piu', non una stampella. */
        @container pila scroll-state(stuck: top) {
            .scheda-indice { border-bottom-color: var(--riga-forte); }
            .scheda-genere { color: var(--tenue); }
        }

        .elenco-progetti > .scheda:nth-child(2) { top: calc(var(--spazio-xl) + 14px); }
        .elenco-progetti > .scheda:nth-child(3) { top: calc(var(--spazio-xl) + 28px); }
        .elenco-progetti > .scheda:nth-child(4) { top: calc(var(--spazio-xl) + 42px); }
        .elenco-progetti > .scheda:nth-child(5) { top: calc(var(--spazio-xl) + 56px); }
        .elenco-progetti > .scheda:nth-child(6) { top: calc(var(--spazio-xl) + 70px); }
        .elenco-progetti > .scheda:nth-child(7) { top: calc(var(--spazio-xl) + 84px); }
        /* Dall'ottavo in poi lo scalino si ferma: oltre un certo punto la
           pila mangerebbe lo schermo invece di raccontare qualcosa. */
        .elenco-progetti > .scheda:nth-child(n+8) { top: calc(var(--spazio-xl) + 98px); }

        /* Quella che esce dall'alto arretra e si spegne, invece di sparire di
           colpo sotto la successiva. */
        @keyframes pila-esce {
            to {
                transform: scale(0.965) translateY(-8px);
                opacity: 0.55;
            }
        }
    }
}


/* 13. Specifiche ───────────────────────────────────────────────────────────
   Ogni progetto porta i numeri che lo descrivono davvero: un wargame si
   misura in missioni, un sistema operativo nel SoC su cui gira.            */

.specifiche {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: var(--spazio-sm) var(--spazio-md);
    border-top: var(--filo) solid var(--riga);
    padding-top: var(--spazio-sm);
    margin-top: var(--spazio-md);
    margin-bottom: var(--spazio-md);
}

.specifiche > div { min-width: 0; }

.specifiche dt {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: var(--crena-callout);
    text-transform: uppercase;
    color: var(--fioco);
    margin-bottom: var(--spazio-3xs);
}

.specifiche dd {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.8125rem;
    color: var(--tenue);
    line-height: var(--alt-snella);
    overflow-wrap: anywhere;
}

/* Lo stato e' l'unica pastiglia del sito, e porta un punto acceso. */
.stato {
    display: inline-flex;
    align-items: center;
    gap: var(--spazio-2xs);
}

.stato::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--riga-forte);
    flex: none;
}

.stato-attivo::before,
.stato-corrente::before {
    background: var(--ottone);
    box-shadow: 0 0 6px var(--alone);
}

.stato-pubblicato::before,
.stato-rilasciato::before { background: var(--corallo); }


/* 14. Bottoni ──────────────────────────────────────────────────────────────
   Un solo pieno per vista. Il secondario e' un legame tipografico, non un
   secondo rettangolo: due bottoni pieni affiancati sono la firma di una
   pagina che non sa cosa vuole.                                            */

.collegamenti {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spazio-sm);
}

.bottone {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--tenue);
    white-space: nowrap;          /* gate 49 */
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
    padding: var(--spazio-2xs) var(--spazio-md);
    transition: color var(--breve) var(--uscita),
                border-color var(--breve) var(--uscita),
                background-color var(--breve) var(--uscita),
                transform var(--breve) var(--uscita);
}

.bottone:hover {
    color: var(--testo-alto);
    border-color: var(--riga-forte);
    background: var(--fondo-cima);
}

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

.bottone-forte {
    background: var(--ottone);
    border-color: var(--ottone);
    color: var(--su-ottone);
}

.bottone-forte:hover {
    background: var(--ottone);
    border-color: var(--ottone);
    color: var(--su-ottone);
    filter: brightness(1.08);
}

.collegamenti-larghi { margin-top: var(--spazio-lg); }


/* 14.1 Il player della radio ───────────────────────────────────────────────
   Sta dentro la scheda del progetto, non sopra la pagina: e' una cosa che quel
   progetto sa fare, mostrata li' dove si racconta.                          */

.ascolto {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "etichetta etichetta"
        "tasto     ora";
    align-items: center;
    gap: var(--spazio-2xs) var(--spazio-sm);
    margin: 0 0 var(--spazio-md);
    padding: var(--spazio-sm) var(--spazio-md);
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
    background: var(--fondo);
}

.ascolto-etichetta {
    grid-area: etichetta;
    display: flex;
    align-items: center;
    gap: var(--spazio-2xs);
    margin-bottom: 0;
}

/* Il punto acceso. Spento e' un cerchio qualsiasi; mentre la diretta suona
   respira, con lo stesso battito dell'apparato in home. Non e' decorazione:
   e' l'unica cosa in pagina che dice "sta andando adesso". */
.ascolto-etichetta::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--riga-forte);
    flex: none;
    transition: background-color var(--breve) var(--uscita);
}

.ascolto-acceso .ascolto-etichetta::before {
    background: var(--ottone);
    box-shadow: 0 0 8px var(--alone);
}

@media (prefers-reduced-motion: no-preference) {
    .ascolto-acceso .ascolto-etichetta::before {
        animation: respiro var(--pulsazione) var(--morbido) infinite;
    }
}

.ascolto-tasto { grid-area: tasto; }

.ascolto-ora {
    grid-area: ora;
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    color: var(--tenue);
    line-height: var(--alt-snella);
    min-height: 1.2em;
    overflow-wrap: anywhere;
}

/* Con JavaScript spento l'elemento tiene il suo attributo `controls` e si
   vede la barra nativa del browser: brutta, ma la radio si ascolta. Quando lo
   script parte toglie `controls`, e questa regola lo fa sparire — al suo
   posto c'e' il bottone nel tema. Nessuna delle due strade passa da uno
   `style="..."`, che la CSP vieta. */
.ascolto-audio:not([controls]) { display: none; }

.ascolto-audio[controls] {
    grid-area: tasto / tasto / ora / ora;
    width: 100%;
    max-width: 22rem;
}


/* 15. Articoli ─────────────────────────────────────────────────────────────
   Index-First. La pagina degli articoli E' l'elenco: nessuna apertura
   illustrata, nessun eroe. Solo l'ultimo in grande e poi le righe.         */

.elenco-articoli {
    display: grid;
    border-top: var(--filo) solid var(--riga);
}

.riga-articolo {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spazio-2xs);
    padding-block: var(--spazio-md);
    border-bottom: var(--filo) solid var(--riga);
    position: relative;
    transition: background-color var(--breve) var(--uscita);
}

@media (min-width: 46rem) {
    .riga-articolo {
        grid-template-columns: 7rem minmax(0, 1fr) auto;
        gap: var(--spazio-lg);
        align-items: baseline;
    }
}

/* Il filo che si accende sotto la riga: dice "questa" senza spostare niente
   di posto. Nessun riquadro che compare, nessun salto. */
.riga-articolo::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: var(--ottone);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--medio) var(--uscita);
}

.riga-articolo:hover::after,
.riga-articolo:focus-within::after { transform: scaleX(1); }

.riga-articolo h3 {
    font-size: clamp(1.25rem, 1vw + 1rem, 1.625rem);
    margin-bottom: var(--spazio-3xs);
}

.riga-articolo h3 a:hover { color: var(--ottone); }

.riga-articolo .sommario {
    margin-bottom: 0;
    font-size: 0.9375rem;
    color: var(--fioco);
}

.quando { color: var(--fioco); white-space: nowrap; }
.durata { color: var(--fioco); white-space: nowrap; }

.stacco-anno {
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: 2rem;
    color: var(--inciso);
    padding-block: var(--spazio-lg) var(--spazio-2xs);
    border-bottom: var(--filo) solid var(--riga);
    font-variant-numeric: tabular-nums;
}

/* L'ultimo uscito. Un archivio in cui tutte le righe pesano uguale non offre
   un punto da cui cominciare. */
/* Era una scheda: bordo, sfondo, angoli, emissione. Adesso e' la prima voce
   dell'indice, e basta. Index-First dice che la pagina E' l'elenco: una
   scatola in cima la trasforma in una pagina con un eroe sopra a un elenco,
   che e' un'altra cosa. Resta piu' grande delle altre — il peso lo fa il
   corpo del titolo, non una cornice. */
.articolo-aperto {
    padding-bottom: var(--spazio-lg);
    margin-bottom: var(--spazio-lg);
    border-bottom: var(--filo) solid var(--riga);
}

.articolo-aperto h2 {
    font-size: clamp(1.75rem, 2.4vw + 1rem, 2.75rem);
    margin-block: var(--spazio-2xs) var(--spazio-sm);
}

.articolo-aperto h2 a:hover { color: var(--ottone); }

.riga-firma {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spazio-sm);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--fioco);
    margin-top: var(--spazio-md);
}

.riga-firma a { color: var(--ottone); }
.riga-firma a:hover { border-bottom: var(--filo) solid var(--ottone); }

.tag-riga {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spazio-2xs);
    margin-top: var(--spazio-sm);
}

.tag-riga li {
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-pillola);
    padding: 2px var(--spazio-2xs);
    font-size: 0.5625rem;
}

.nota-feed {
    margin-top: var(--spazio-xl);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
}

.nota-feed a {
    color: var(--ottone);
    border-bottom: var(--filo) solid var(--riga);
}

.nota-feed a:hover { border-bottom-color: var(--ottone); }

.vuoto { color: var(--fioco); }


/* 16. Da un pezzo al prossimo ──────────────────────────────────────────────
   Un articolo che finisce e basta e' un vicolo cieco: chi ha letto fin qui e'
   la persona piu' disposta a leggere il prossimo.                          */

.scorrimento {
    display: grid;
    gap: var(--spazio-sm);
    margin-top: var(--spazio-2xl);
    padding-top: var(--spazio-lg);
    border-top: var(--filo) solid var(--riga);
}

@media (min-width: 46rem) {
    .scorrimento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.scorrimento-voce {
    display: grid;
    gap: var(--spazio-2xs);
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-scheda);
    padding: var(--spazio-md);
    min-width: 0;
    transition: border-color var(--breve) var(--uscita),
                background-color var(--breve) var(--uscita);
}

.scorrimento-voce:hover {
    border-color: var(--riga-forte);
    background: var(--fondo-alto);
}

.scorrimento-avanti { text-align: right; }

.scorrimento-verso {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    letter-spacing: var(--crena-callout);
    text-transform: uppercase;
    color: var(--fioco);
}

.scorrimento-titolo {
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: 1.125rem;
    line-height: var(--alt-snella);
    color: var(--testo-alto);
    overflow-wrap: anywhere;
}

.ritorno {
    margin-top: var(--spazio-lg);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
}

.ritorno a {
    color: var(--ottone);
    border-bottom: var(--filo) solid transparent;
}

.ritorno a:hover { border-bottom-color: var(--ottone); }


/* 17. Intestazioni interne ─────────────────────────────────────────────── */

.intestazione-pagina {
    padding-block: clamp(2.5rem, 6vw, 4.5rem) var(--spazio-lg);
    border-bottom: var(--filo) solid var(--riga);
}

.intestazione-pagina h1 {
    font-size: var(--display-medio);
    max-width: 20ch;
    text-transform: lowercase;
}

/* Il titolo di un articolo non e' prosa generica: e' una frase sua, e la
   tiene come l'ha scritta. */
.intestazione-articolo h1,
.intestazione-ritratto h1 { text-transform: none; }

/* Long Document · articolo e Chi sono.
   Via il filo sotto l'intestazione. Quel filo diceva "qui finisce la testata e
   comincia il contenuto", cioe' trattava la pagina come un sito fatto di
   componenti. Un documento lungo non ha una testata: ha un titolo, un
   sommario e poi il testo, e fra loro c'e' spazio, non un confine. */
.intestazione-articolo,
.intestazione-ritratto {
    border-bottom: 0;
    padding-bottom: 0;
}

.intestazione-articolo + .prosa,
.intestazione-ritratto + .prosa,
.intestazione-articolo ~ .prosa,
.intestazione-ritratto ~ .prosa {
    padding-top: var(--spazio-lg);
}

/* Index-First · l'indice degli articoli.
   La macrostruttura vieta il carattere display in testa: la pagina E' l'elenco,
   e un titolo alto sei centimetri sopra a un elenco ne fa una pagina con un
   eroe. Qui il titolo resta, perche' serve a chi naviga con un lettore di
   schermo e ai motori, ma torna alla misura di una riga di testo. */
.intestazione-indice {
    padding-block: clamp(2rem, 4vw, 3rem) var(--spazio-md);
    border-bottom: 0;
}

.intestazione-indice h1 {
    font-size: clamp(1.5rem, 1.2vw + 1.1rem, 2rem);
    max-width: none;
}

.intestazione-indice .occhiello {
    font-size: 1rem;
    max-width: 58ch;
}

/* Misurato a 5,08:1 con `--fioco`: passa AA e fallisce AAA. Ma questo non
   e' un'etichetta da 11px: e' il sommario di un articolo, prosa da 17px che
   si legge davvero. Con `--tenue` sale sopra 7:1 e resta comunque sotto al
   titolo, quindi la gerarchia non si appiattisce. */
.occhiello {
    text-wrap: pretty;
    color: var(--tenue);
    font-size: 1.0625rem;
    line-height: var(--alt-larga);
    max-width: 52ch;
    margin-top: var(--spazio-sm);
}

.intestazione-ritratto {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spazio-lg);
}

.intestazione-ritratto > div { min-width: 0; flex: 1 1 22rem; }

.ritratto {
    border-radius: 50%;
    border: var(--filo) solid var(--riga);
    width: 168px;
    height: 168px;
    object-fit: cover;
    filter: grayscale(1) contrast(1.05);
    transition: filter var(--medio) var(--uscita);
}

.ritratto:hover { filter: grayscale(0) contrast(1); }

.ritratto-piccolo { width: 56px; height: 56px; }


/* 17.1 La pagina di un progetto ────────────────────────────────────────────
   Quattordici pagine che nel primo giro di riscrittura erano rimaste senza
   regole: le specifiche uscivano come un elenco crudo, etichetta e valore
   impilati senza niente che li distinguesse. Qui prendono la stessa lingua
   delle schede — etichetta mono minuscola sopra, valore in mono sotto.      */

.lettura {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
    gap: var(--spazio-md);
    margin-top: var(--spazio-lg);
    padding-top: var(--spazio-md);
    border-top: var(--filo) solid var(--riga);
}

/* La variante fitta e' quella dell'intestazione: piu' voci, meno aria. */
.lettura-fitta {
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: var(--spazio-sm) var(--spazio-md);
}

.lettura > div { min-width: 0; }

.lettura dt {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: var(--crena-callout);
    text-transform: uppercase;
    color: var(--fioco);
    margin-bottom: var(--spazio-3xs);
}

.misurato {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.8125rem;
    line-height: var(--alt-snella);
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

/* L'apertura di un progetto: la cosa stessa, non una decorazione sopra al
   titolo. Prende il filo e l'angolo delle schede, cosi' si legge come parte
   dello stesso strumento. */
.apertura-media {
    margin: var(--spazio-xl) auto 0;
}

.apertura-media img {
    width: 100%;
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-scheda);
    background: var(--fondo-alto);
}

/* Un ritratto non va allargato a tutta la colonna: si deforma o si taglia. */
.apertura-ritratto img {
    max-width: 30rem;
    margin-inline: auto;
}

.apertura-media figcaption {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    color: var(--fioco);
    line-height: var(--alt-snella);
    margin-top: var(--spazio-sm);
    max-width: var(--misura);
}

/* Una testata di sezione dentro una pagina, non in cima: stesso ritmo, meno
   stacco sopra, perche' quello lo da' gia' il testo che la precede. */
.sezione-testata-interna {
    margin-top: var(--spazio-2xl);
    padding-top: var(--spazio-md);
    border-top: var(--filo) solid var(--riga);
}

.sezione-testata-interna h2 { font-size: var(--display-basso); }

/* Il glifo disegnato: il ripiego per cio' che non ha una faccia da mostrare —
   la musica, un libro. Eredita il colore dal testo, quindi cambia col tema
   senza una riga in piu'. */
.glifo {
    width: 100%;
    max-width: 12rem;
    margin-inline: auto;
    padding: var(--spazio-lg);
    color: var(--riga-forte);
    transition: color var(--medio) var(--uscita);
}

.scheda:hover .glifo { color: var(--ottone); }

/* La firma dell'autore in cima a un articolo: dentro `.riga-firma`, che detta
   gia' famiglia e corpo. Qui serve solo che non sparisca fra le date. */
.autore { color: var(--tenue); }


/* 18. Prosa ────────────────────────────────────────────────────────────────
   Long Document. Qui comanda il testo: nessun arricchimento, nessuna
   figura decorativa, una colonna sola e una misura che si legge.           */

.prosa {
    max-width: var(--misura);
    font-size: 1.0625rem;
    line-height: var(--alt-larga);
    color: var(--testo);
    /* `pretty` guarda le ultime righe di ogni paragrafo e sposta la
       spezzatura per non lasciare una parola sola in fondo. Si eredita, e
       quindi copre p, li, blockquote e tutto il resto della prosa; i titoli
       no, perche' la regola h1-h4 ci mette `balance` e vince. Firefox lo
       ignora e manda a capo come sempre: e' un di piu', non un requisito. */
    text-wrap: pretty;
}

.prosa > * + * { margin-top: var(--spazio-md); }

.prosa h2 {
    font-size: clamp(1.375rem, 1vw + 1rem, 1.75rem);
    /* Il filo sopra e' sparito: in un documento lungo il divisore e' il vuoto.
       Una riga orizzontale ogni due schermate spezza la lettura in capitoli
       che il testo non ha, e fa sembrare la pagina un sito invece che una
       cosa scritta. Lo spazio dice la stessa cosa senza disegnare niente. */
    margin-top: var(--spazio-3xl);
    margin-bottom: calc(var(--spazio-md) * -0.25);
}

.prosa h3 {
    font-size: clamp(1.125rem, 0.6vw + 1rem, 1.3125rem);
    margin-top: var(--spazio-2xl);
    margin-bottom: calc(var(--spazio-md) * -0.35);
    color: var(--tenue);
}

.prosa a {
    color: var(--testo-alto);
    border-bottom: var(--filo) solid var(--ottone);
    transition: background-color var(--breve) var(--uscita);
}

.prosa a:hover {
    background: var(--alone-fioco);
}

.prosa strong { color: var(--testo-alto); font-weight: 500; }

/* design.md diceva «mai corsivo in nessun punto», e questa riga lo
   contraddiceva in silenzio. La regola nasce dal tema e riguarda i TITOLI:
   li' il corsivo e' il tell. Dentro un paragrafo e' l'unico modo che
   l'italiano ha di marcare una parola senza gridare. La deroga adesso sta
   scritta in design.md, non nascosta qui. */
.prosa em { font-style: italic; }

.prosa ul, .prosa ol {
    padding-left: var(--spazio-md);
    display: grid;
    gap: var(--spazio-2xs);
}

.prosa li { list-style: none; position: relative; }

.prosa ul > li::before {
    content: "";
    position: absolute;
    left: calc(var(--spazio-md) * -1);
    top: 0.72em;
    width: 6px;
    height: 1px;
    background: var(--ottone);
}

.prosa ol { counter-reset: passo; }

.prosa ol > li { counter-increment: passo; }

.prosa ol > li::before {
    content: counter(passo, decimal-leading-zero);
    position: absolute;
    left: calc(var(--spazio-lg) * -1);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    color: var(--fioco);
    top: 0.3em;
}

.prosa blockquote {
    border-left: 2px solid var(--ottone);
    padding-left: var(--spazio-md);
    color: var(--tenue);
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: 1.375rem;
    line-height: var(--alt-snella);
}

.prosa code {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.875em;
    background: var(--fondo-alto);
    border: var(--filo) solid var(--riga);
    border-radius: 4px;
    padding: 1px 5px;
    overflow-wrap: anywhere;
}

.prosa pre {
    background: var(--fondo-alto);
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
    padding: var(--spazio-md);
    overflow-x: auto;
    font-size: 0.8125rem;
    line-height: var(--alt-normale);
}

.prosa pre code {
    background: none;
    border: 0;
    padding: 0;
    font-size: inherit;
}

.prosa img {
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
}

.prosa figcaption {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    color: var(--fioco);
    margin-top: var(--spazio-2xs);
}

.prosa hr {
    border: 0;
    border-top: var(--filo) solid var(--riga);
    margin-block: var(--spazio-xl);
}

.prosa table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9375rem;
}

.prosa th, .prosa td {
    text-align: left;
    padding: var(--spazio-2xs) var(--spazio-sm);
    border-bottom: var(--filo) solid var(--riga);
}

.prosa th {
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.625rem;
    letter-spacing: var(--crena-callout);
    text-transform: uppercase;
    color: var(--fioco);
}

/* Una tabella larga non deve mai far scorrere la pagina intera. */
/* Lo scorrimento va sull'INVOLUCRO, non sulla tabella. `display: block` su un
   <table> distrugge la semantica: un lettore di schermo riceve una fila piatta
   di celle invece di una griglia, e le intestazioni smettono di esserlo.
   Nell'articolo sulla VRAM quel confronto esiste solo nella geometria
   righe/colonne. L'involucro porta `tabindex="0"` perche' anche da tastiera si
   possa raggiungere la colonna fuori schermo: senza, e' irraggiungibile. */
.tabella-scorre {
    overflow-x: auto;
    max-width: 100%;
    margin-block: var(--spazio-md);
}

.tabella-scorre:focus-visible {
    outline: 2px solid var(--fuoco);
    outline-offset: 3px;
}

.prosa .tabella { display: block; overflow-x: auto; }


/* 18.1 La chiusura ────────────────────────────────────────────────────────
   Una pagina che si legge per decidere qualcosa deve finire con quella
   decisione a portata di mano. Fino a ieri ogni bottone pieno del sito
   mandava il lettore altrove — GitHub, Amazon, Spotify, la radio — e l'unica
   azione che conviene a chi il sito lo possiede era un legame in mezzo a un
   paragrafo. Questo e' il solo pieno che punta dentro.                     */

.chiusura {
    max-width: var(--misura);
    margin-top: var(--spazio-2xl);
    padding-top: var(--spazio-lg);
    border-top: var(--filo) solid var(--riga);
    display: grid;
    gap: var(--spazio-md);
}

.chiusura-riga {
    text-wrap: balance;
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: clamp(1.25rem, 1.4vw + 1rem, 1.75rem);
    line-height: var(--alt-snella);
    letter-spacing: var(--crena-stretta);
    color: var(--testo-alto);
    max-width: 34ch;
}


/* 19. Piede ────────────────────────────────────────────────────────────────
   Ft5 Statement. Una frase che chiude, non quattro colonne di link: le
   colonne di link sono l'impronta digitale piu' riconoscibile di un piede
   generato, e questo sito ha quattro destinazioni in tutto.                */

.piede {
    border-top: var(--filo) solid var(--riga);
    padding-block: var(--spazio-2xl) var(--spazio-xl);
    margin-top: var(--stacco-sezione);
}

/* Larghezza di riga stretta, ma il blocco NON si centra: sta dentro un
   `.guscio` a piena larghezza, e qui si limita solo la misura del testo. Se la
   max-width stesse sul `.guscio` stesso, i suoi `margin-inline: auto` la
   centrerebbero, e il piede si ritroverebbe tre bordi sinistri diversi uno
   sopra l'altro. */
.piede-frase {
    text-wrap: balance;
    font-family: var(--display);
    font-size-adjust: ch-width var(--zero-display);
    font-size: clamp(1.5rem, 2.2vw + 1rem, 2.5rem);
    line-height: var(--alt-snella);
    letter-spacing: var(--crena-stretta);
    color: var(--testo-alto);
    text-transform: lowercase;
    max-width: 38ch;
    margin-bottom: var(--spazio-xl);
}

.piede-interno {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spazio-sm) var(--spazio-lg);
    align-items: baseline;
    padding-top: var(--spazio-md);
    border-top: var(--filo) solid var(--riga);
    font-family: var(--mono);
    font-size-adjust: none;
    font-size: 0.6875rem;
    letter-spacing: var(--crena-etichetta);
    text-transform: uppercase;
    color: var(--fioco);
}

.piede-interno a {
    color: var(--tenue);
    white-space: nowrap;
    border-bottom: var(--filo) solid transparent;
    transition: color var(--breve) var(--uscita),
                border-color var(--breve) var(--uscita);
}

.piede-interno a:hover {
    color: var(--ottone);
    border-bottom-color: var(--ottone);
}

.colophon {
    margin-top: var(--spazio-md);
    font-size: 0.75rem;
    line-height: var(--alt-normale);
    color: var(--fioco);
    max-width: 62ch;
}


/* 20. Preferenze utente ────────────────────────────────────────────────────
   Chi chiede meno movimento lo ottiene davvero: non "meno", zero. Tutto va
   allo stato finale, subito. Il focus non era animato nemmeno prima.       */

@media (prefers-reduced-motion: reduce) {
    /* Si spegne il MOVIMENTO, non il riscontro.
       La mannaia `* { transition-duration: 1ms }` e' comoda e sbagliata:
       toglie anche il colore che cambia sotto il dito, e chi ha chiesto meno
       movimento non ha chiesto un'interfaccia che non risponde. Qui cade cio'
       che si sposta — animazioni, scorrimento morbido, trasformazioni — e
       resta cio' che dice «ti ho sentito». */
    *,
    *::before,
    *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
        transition-property: color, background-color, border-color, outline-color,
                             fill, stroke, opacity !important;
        transition-duration: 120ms !important;
    }

    /* Nessuno spostamento resta in piedi: le schede non salgono, i bottoni
       non scendono, i fili non si disegnano. */
    .scheda:hover,
    .bottone:active,
    .scorrimento-voce:hover { transform: none !important; }

    .claim em::after { animation: none; transform: scaleX(1); }
    .memoria .viva { filter: none; }
    .riga-articolo::after { transition: none; transform: scaleX(1); opacity: 0.35; }
}

@media (prefers-contrast: more) {
    :root {
        --riga:   oklch(52% 0.02 265);
        --fioco:  oklch(78% 0.014 263);
        --testo:  oklch(94% 0.008 262);
    }
}


/* 21. Movimento ────────────────────────────────────────────────────────────
   Tutto quello che si muove qui e' `transform` oppure `opacity`. Mai una
   proprieta' di layout: animare `height` o `top` fa ricalcolare la pagina a
   ogni fotogramma, e su una macchina modesta si vede.

   Le sezioni entrano con `animation-timeline: view()` — scroll-driven nativo,
   zero JavaScript, zero listener, e con JS spento non cambia niente perche'
   non c'e' JS da spegnere.                                                 */

@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        /* `.riga-articolo` e `.articolo-aperto` non sono piu' in elenco.
           Index-First e Long Document dichiarano tutt'e due "Reveal: none":
           una riga d'archivio che compare mentre scorri e' un effetto addosso
           a una cosa che serve solo a essere scorsa, e in un documento lungo
           il testo che si materializza e' rumore fra il lettore e la frase. */
        .sezione-testata,
        .scheda,
        .numeri,
        .piede-frase {
            animation: entra var(--lungo) var(--uscita) both;
            animation-timeline: view();
            animation-range: entry 0% entry 42%;
        }

        /* La pila dei progetti ha una sua animazione di uscita: non deve
           anche entrare, o le due si accavallano sullo stesso elemento. */
        @media (min-width: 62rem) {
            .elenco-progetti > .scheda:not(.scheda-rilievo) {
                animation-name: pila-esce;
            }
        }
    }
}

@keyframes entra {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}

/* Il passaggio da una pagina all'altra.

   Un sito statico cambia pagina con un lampo bianco-nero: il browser butta
   via il documento e ne dipinge un altro. `@view-transition` gli chiede di
   dissolvere l'uno nell'altro. Serve che sia la pagina di partenza sia
   quella d'arrivo lo dichiarino, ed e' cosi': tutte portano questo foglio.

   Nessuna animazione scritta a mano. La dissolvenza predefinita del browser
   e' la cosa piu' silenziosa che ci sia, e una pagina che scivola da destra
   racconterebbe un movimento fra le sezioni che non esiste.

   Firefox lo ignora e cambia pagina di colpo, come ha sempre fatto: e'
   progressivo, non un requisito. Sotto `prefers-reduced-motion: reduce` non
   si dichiara affatto, quindi non c'e' niente da spegnere dopo. */
@media (prefers-reduced-motion: no-preference) {
    @view-transition {
        navigation: auto;
    }
}

/* L'apparato pulsa. Non ruota: la rotazione era la firma della sfera
   luminosa, la firma di un oggetto costruito e' che si vede che e' costruito. */
@media (prefers-reduced-motion: no-preference) {
    .memoria .viva {
        animation: respiro var(--pulsazione) var(--morbido) infinite;
    }
}

@keyframes respiro {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.82; }
}

/* Mentre l'allocatore gira, la griglia e' accesa davvero. */
.memoria.in-esecuzione { outline: none; }

.memoria.in-esecuzione .spenta { fill: var(--riga); }


/* 22. Galleria ─────────────────────────────────────────────────────────── */

.galleria {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: var(--spazio-sm);
    margin-top: var(--spazio-lg);
}

.galleria figure { margin: 0; min-width: 0; }

.galleria img {
    width: 100%;
    border: var(--filo) solid var(--riga);
    border-radius: var(--raggio-input);
}


/* 23. Telefono ─────────────────────────────────────────────────────────────
   Sotto i 60rem la side-rail diventa una barra in cima. Il bordo sinistro di
   un telefono e' pollice, non spazio di progetto.

   Verificato a 320, 375, 414 e 768: nessuno scorrimento orizzontale, nessun
   link che va a capo, nessuna testata a due colonne.                       */

@media (max-width: 60rem) {
    body { padding-left: 0; padding-top: 3.25rem; }

    .rail {
        inset: 0 0 auto 0;
        width: 100%;
        height: 3.25rem;
        flex-direction: row;
        justify-content: space-between;
        gap: var(--spazio-2xs);
        /* Margine laterale piu' stretto del resto della pagina: in barra ogni
           pixel e' una lettera in piu' che si legge. */
        padding: 0 var(--spazio-sm);
        border-right: 0;
        border-bottom: var(--filo) solid var(--riga);
    }

    .rail-marchio,
    .rail-voce {
        writing-mode: horizontal-tb;
        transform: none;
    }

    /* In barra ci devono stare cinque cose in 320 pixel: il nome, tre
       destinazioni e la lingua. La spaziatura fra le lettere e' quello che
       costa di piu' — 0,16em su otto caratteri sono tredici pixel buttati per
       voce — quindi in orizzontale si stringe. I numeri delle voci spariscono:
       servivano a dare ordine alla costola verticale, in riga sono rumore. */
    .rail-marchio {
        padding-block: 0;
        font-size: 0.625rem;
        letter-spacing: 0.04em;
    }

    .rail-voci {
        flex-direction: row;
        gap: var(--spazio-xs);
        /* Rete di sicurezza: se un giorno le destinazioni diventano cinque,
           scorrono invece di uscire dallo schermo. */
        overflow-x: auto;
        scrollbar-width: none;
    }

    .rail-voci::-webkit-scrollbar { display: none; }

    .rail-filo { display: none; }

    .rail-voce {
        font-size: 0.625rem;
        letter-spacing: 0.04em;
        padding-inline: 0;
    }

    .rail-voce::before { content: none; }

    /* Senza cornice: un rettangolo intorno a due lettere, in una barra alta
       52 pixel, e' un bottone che non serve a niente. */
    .rail-lingua {
        border: 0;
        padding: 0;
        font-size: 0.625rem;
        letter-spacing: 0.04em;
    }

    .salta:focus { left: 0; }

    /* Su telefono la home si fermava a dieci schermate, e sette progetti di
       fila sono la meta' di quella lunghezza. Qui l'elenco si ferma al terzo
       e passa il resto alla pagina dei progetti.
       `nth-child(n+4)` non conta quanti sono: quando i progetti diventeranno
       nove, la regola vale ancora e non c'e' nessun numero da aggiornare.
       Solo l'elenco della home — quello della pagina progetti non si tocca,
       e' il posto dove si vedono tutti. */
    /* Prima queste quattro sparivano. Sbagliato: l'ampiezza del lavoro E'
       l'argomento — e' cio' che separa Nicola da un backendista qualunque —
       e chi apriva la home dal telefono se ne andava convinto che i progetti
       fossero tre, senza sapere che esistono un libro pubblicato e della
       musica uscita.
       Adesso si compattano: restano genere, titolo e una riga di sommario,
       spariscono la schermata e la griglia di specifiche. L'ampiezza
       sopravvive a una frazione dell'altezza. */
    .elenco-ridotto > .scheda:nth-child(n+4) {
        padding-block: var(--spazio-md);
    }

    .elenco-ridotto > .scheda:nth-child(n+4) .scheda-media,
    .elenco-ridotto > .scheda:nth-child(n+4) .specifiche,
    .elenco-ridotto > .scheda:nth-child(n+4) .collegamenti,
    .elenco-ridotto > .scheda:nth-child(n+4) .ascolto { display: none; }

    .elenco-ridotto > .scheda:nth-child(n+4) .sommario {
        margin-bottom: 0;
        font-size: 0.9375rem;
        color: var(--fioco);
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .elenco-ridotto > .scheda:nth-child(n+4) h2,
    .elenco-ridotto > .scheda:nth-child(n+4) h3 {
        font-size: 1.25rem;
    }

    .oltre-in-coda {
        display: block;
        margin-top: var(--spazio-lg);
    }
}

@media (max-width: 46rem) {
    .apertura h1 { max-width: none; }

    .claim { max-width: none; }

    .numeri { grid-template-columns: minmax(0, 1fr); }

    .numero {
        border-right: 0;
        border-bottom: var(--filo) solid var(--riga);
    }

    .numero:last-child { border-bottom: 0; }

    .scorrimento-avanti { text-align: left; }

    .ritratto { width: 116px; height: 116px; }

    .meter { grid-template-columns: minmax(0, 1fr); gap: var(--spazio-2xs); }

    .meter-etichetta { font-size: 0.625rem; }

    .meter-barre { order: -1; }
}

@media (max-width: 26rem) {
    .callout { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .callout > span:first-child::after { display: none; }
}

/* A 320 pixel — il vecchio SE — alla barra mancavano otto pixel e le tre
   destinazioni finivano in uno scorrimento orizzontale. Otto pixel si trovano
   negli spazi fra le voci, non rimpicciolendo il testo: a quella misura
   scendere sotto i dieci pixel renderebbe la navigazione illeggibile proprio
   sullo schermo dove serve di piu'. */
@media (max-width: 22.5rem) {
    .rail-voci { gap: var(--spazio-2xs); }
}


/* 24. Stampa ───────────────────────────────────────────────────────────────
   Un articolo stampato non ha bisogno della rail, dell'apparato, ne' del
   fondo scuro: ha bisogno di essere leggibile su carta.                    */

@media print {
    :root {
        --fondo: #fff;
        --fondo-alto: #fff;
        --testo: #111;
        --testo-alto: #000;
        --fioco: #555;
        --tenue: #333;
        --riga: #ccc;
        --riga-forte: #999;
        --ottone: #000;
    }

    body { padding-left: 0; }

    .rail,
    .apparato,
    .meter,
    .scorrimento,
    .ritorno,
    .salta,
    .collegamenti,
    .nota-feed { display: none; }

    .prosa a { border-bottom: 0; }

    .prosa a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-family: var(--mono);
        font-size-adjust: none;
        font-size: 0.75em;
        color: #555;
        word-break: break-all;
    }

    .sezione, .piede { border-color: #ccc; }
}


/* 25. Fosforo ──────────────────────────────────────────────────────────────
   Il codice Konami accende la tavolozza dei monitor a fosfori ambra, quelli
   dei cabinati. Non e' un filtro sopra la pagina: e' lo stesso impaginato con
   altre variabili, quindi non rompe niente e resta leggibile.              */

[data-tema="fosforo"] {
    color-scheme: dark;

    --fondo:          oklch(12%  0.020  80);
    --fondo-alto:     oklch(16%  0.026  78);
    --fondo-cima:     oklch(20%  0.030  76);
    --riga:           oklch(30%  0.040  78);
    --riga-forte:     oklch(44%  0.060  78);
    --fioco:          oklch(66%  0.090  80);
    --inciso:         oklch(52%  0.070  78);
    --tenue:          oklch(78%  0.110  80);
    --testo:          oklch(86%  0.130  82);
    --testo-alto:     oklch(93%  0.150  84);

    --ottone:         oklch(86%  0.160  84);
    --corallo:        oklch(74%  0.150  55);
    --su-ottone:      oklch(12%  0.020  80);
    --fuoco:          oklch(86%  0.160  84);

    --alone:          oklch(88%  0.160  84 / 0.45);
    --alone-fioco:    oklch(88%  0.160  84 / 0.14);
    --emissione:      oklch(86%  0.160  84 / 0.05);
    --filo-blueprint: oklch(93%  0.150  84 / 0.05);
}


/* 25.1 Bersagli ────────────────────────────────────────────────────────────
   WCAG 2.2, criterio 2.5.8: un comando deve offrire almeno 24x24 px su cui
   premere. Misurati, i legami di questo sito stavano fra 13 e 19 px di
   altezza — leggibili, ma stretti per un pollice.

   Si allarga l'area, non il disegno. Su un elemento in linea il riempimento
   verticale non alza la riga: cresce solo la zona che risponde al tocco, e in
   pagina non si sposta niente. Dove il riempimento sposterebbe (nella barra
   del telefono, che e' stretta) lo si compensa con un margine negativo di
   pari misura: il bersaglio cresce, l'ingombro resta quello di prima.

   Restano fuori i legami dentro la prosa: il criterio esenta il testo in
   linea dentro una frase, e allargarli spezzerebbe l'interlinea di un
   paragrafo.                                                                */

.piede-interno a,
.oltre,
.etichetta a,
.ritorno a,
.nota-feed a,
.riga-firma a {
    padding-block: 6px;
}

/* Il piu' stretto di tutti: due lettere nella barra del telefono, 13x16.
   Padding piu' margine negativo — l'area di tocco arriva a 29x32 e la barra
   non se ne accorge. */
.rail-lingua,
.rail-marchio {
    padding: var(--spazio-2xs);
    margin: calc(var(--spazio-2xs) * -1);
}

.rail-lingua {
    /* Il bordo c'era gia' e va tenuto dov'era, non spinto fuori dal padding. */
    padding: var(--spazio-2xs) var(--spazio-xs);
    margin: calc(var(--spazio-2xs) * -1) calc(var(--spazio-xs) * -1);
}


/* 26. Dettagli ─────────────────────────────────────────────────────────────
   Cose piccole che si notano solo quando mancano.                          */

/* I numeri incolonnano ovunque compaiano: e' quello che rende una tabella di
   specifiche leggibile a colpo d'occhio invece che a lettura. */
time, .numero-valore, .specifiche dd, .callout, .meter-etichetta {
    font-variant-numeric: tabular-nums;
}

/* Un'ancora raggiunta non deve finire sotto la barra del telefono. */
:target { scroll-margin-top: 4.5rem; }

/* Su schermo largo la colonna di lettura resta dove l'occhio la cerca, anche
   se la rail ha gia' spostato tutto a destra. */
@media (min-width: 100rem) {
    .guscio { max-width: 78rem; }
}
