/* Elena Tredici - sito pubblico.

   Monocromo, spigolo vivo, due registri tipografici. Nessuna ombra, nessun
   gradiente, nessun raggio: il colore lo mettono le fotografie.

   **Nessuna media query di breakpoint in questo file**: stanno nei quattro
   file per device. Le feature query non dimensionali, come
   prefers-reduced-motion, restano ammesse. */

:root {
    --paper:    #F7F7F7;   /* il fondo della pagina */
    --paper-alto: #FFFFFF; /* la testata */
    --ink:      #111111;
    --ink-60:   #6E6E6E;
    --rule:     #D8D6D2;

    /* Le inversioni, per la macro-area scura */
    --paper-dark: #111111;
    --ink-dark:   #FFFFFF;
    --rule-dark:  #333333;

    /* Due registri e nulla in mezzo: fra 15 e 31px non esiste niente */
    --micro:   0.875rem;  /* 14px - il pavimento di leggibilita' */
    --display: 2rem;      /* 32px */

    --t-opacity:   200ms;
    --t-transform: 280ms;
    --t-page:      240ms;
    --ease: cubic-bezier(.2, .7, .2, 1);

    --testata-h: 54px;

    /* Le tre barre del segno del menu. Il `gap` e' 3.6 e non 4 perche' a 4 le
       barre sembravano di larghezze diverse - un effetto ottico, misurate
       2px tutte e tre.
       Lo scarto della X si RICAVA da questi due: (larghezza + gap) e' quanto
       dista dal centro ogni barra laterale, ed e' di quanto vanno riportate
       sull'asse. Scritto a mano si sfasa al primo ritocco del gap - ed e'
       successo: con 6px fissi le barre si incrociavano 0.82px oltre. */
    --barra-w: 2px;
    --barra-gap: 3.6px;
    --barra-scarto: calc(var(--barra-w) + var(--barra-gap));

    /* I recapiti sono ancorati al fondo: il contenuto deve sapere quanto
       spazio lasciargli, e il numero sta in un posto solo */
    --contatti-h: 76px;
}

[data-theme="dark"] {
    --paper: var(--paper-dark);
    --ink:   var(--ink-dark);
    --rule:  var(--rule-dark);

    /* Anche la testata si inverte: lasciarla bianca qui le darebbe testo
       bianco su fondo bianco, contrasto 1:1.
       Nera PIENA e non appena piu' chiara: fra #1A1A1A e #111111 lo stacco e'
       1.08:1, che su un monitor diverso sparisce o sembra una macchia. Qui a
       separare e' il filetto sotto, come fa il resto del sito */
    --paper-alto: var(--paper-dark);
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: var(--paper);
    color: var(--ink);
    font-family: Inter, system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
    font-size: var(--micro);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    color: inherit;
    text-decoration: none;
}

/* Testata ---------------------------------------------------------- */

/* Bianca sul fondo appena piu' scuro della pagina: e' cio' che la stacca,
   insieme al filetto. Sta sopra le fotografie negli stili che scorrono */
.testata {
    display: flex;
    align-items: center;
    justify-content: center;
    position: sticky;
    top: 0;
    z-index: 5;
    height: var(--testata-h);
    padding: 0 24px;
    background: var(--paper-alto);
    border-bottom: 1px solid var(--rule);
}

/* Il marchio a sinistra, l'etichetta al centro: il centro resta il centro
   della PAGINA, non quello dello spazio rimasto fra logo e menu */
.testata__logo {
    position: absolute;
    left: 24px;
    display: flex;
    align-items: center;
}

/* Il marchio prende il colore del testo, e basta.

   **Niente `mix-blend-mode`**, che c'era e lampeggiava: `difference` non e' un
   colore, e' un'inversione di cio' che sta sotto, e con le fotografie che
   cambiano ogni 120ms il marchio passava da bianco a scuro otto volte al
   secondo. Misurato: su dieci foto, otto hanno l'angolo molto piu' chiaro o
   piu' scuro della media, quindi nemmeno un colore calcolato per foto avrebbe
   retto.

   Il problema si e' tolto invece di risolverlo: il marchio sta nella testata,
   che ha un fondo pieno. Dietro non ci passa mai una fotografia. */
.marchio {
    display: block;
    width: 35px;
    height: 35px;
    color: currentColor;
}

.marchio svg {
    display: block;
    width: 100%;
    height: 100%;
}

.testata__etichetta {
    font-size: var(--display);
    font-weight: 700;
    letter-spacing: 0.01em;
    text-transform: uppercase;
    line-height: 1;
}

.testata__menu {
    position: absolute;
    right: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--barra-gap);
    width: 32px;
    height: 32px;
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
}

/* Tre barre VERTICALI, non l'hamburger orizzontale: e' il segno dei wireframe.

   Erano un elemento con due pseudo-elementi posizionati a -6px e +6px, e le
   due distanze non venivano uguali: 2px di barra piu' 6px di scarto lasciano
   4px di vuoto da un lato e 6 dall'altro, e quella di mezzo SEMBRA piu'
   sottile anche misurando 2px come le altre. Adesso sono tre elementi veri
   distanziati da `gap`, che il vuoto lo divide da solo - e servono comunque
   tre nodi per la X. */
.testata__barra {
    width: var(--barra-w);
    height: 18px;
    background: currentColor;
    transition:
        transform var(--t-transform) var(--ease),
        opacity var(--t-opacity) var(--ease);
}

/* Le tre barre diventano una X.

   Da verticali: quella di mezzo sparisce, le altre due si portano al centro e
   ruotano fino a incrociarsi. Lo scarto e' `--barra-scarto`, cioe' esattamente
   quanto ogni barra laterale dista dall'asse: MISURATO 5.59px con il gap a
   3.6. Con i 6px fissi di prima le due barre si incrociavano **0.82px oltre**,
   e la X si vedeva storta. */
.testata__menu[aria-expanded="true"] .testata__barra:nth-child(1) {
    transform: translateX(var(--barra-scarto)) rotate(45deg);
}

.testata__menu[aria-expanded="true"] .testata__barra:nth-child(2) {
    opacity: 0;
}

.testata__menu[aria-expanded="true"] .testata__barra:nth-child(3) {
    transform: translateX(calc(var(--barra-scarto) * -1)) rotate(-45deg);
}

/* Il pulsante resta sopra il pannello: e' anche quello che lo chiude.

   **La testata deve cedergli il passo.** `.testata` e' `sticky` con
   `z-index: 5`, e questo crea un contesto di impilamento: il 20 qui sotto
   varrebbe solo DENTRO la testata, che sta sotto il menu. MISURATO: il
   pulsante c'era, le barre ruotavano in X, ma `elementFromPoint` restituiva
   il pannello - la X era dietro al velo e non si poteva cliccare. */
.testata:has(.testata__menu[aria-expanded="true"]) {
    z-index: 20;
}

/* Nessun colore qui: la X sta sulla testata, che resta sopra il pannello col
   suo fondo, e deve avere il colore del testo della testata. Bianca fissa
   spariva sul fondo bianco del tema chiaro */
.testata__menu[aria-expanded="true"] {
    position: fixed;
    top: 11px;
    right: 24px;
    z-index: 20;
}

/* Menu ------------------------------------------------------------- */

.menu {
    position: fixed;
    inset: 0;
    z-index: 10;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: var(--paper-dark);
    color: var(--ink-dark);
}

.menu[hidden] {
    display: none;
}

/* Il marchio in cima al menu, ed **e' lui il link a casa**: la voce "HOME"
   non c'e' piu', erano due collegamenti allo stesso posto uno sopra l'altro.

   **Piu' piccolo che nel loader**, e non per gusto: li' il marchio E' la
   pagina e puo' prendersi `min(20vw, 20vh)`; qui sotto ci stanno le voci, e
   lo spazio verticale e' loro.
   Il margine sotto e' quello che aveva "HOME": lo stacco fra l'insegna e
   l'elenco resta lo stesso, sono 69px di testo a sparire. */
.menu__marchio {
    display: block;
    width: 56px;
    margin: 0 auto 48px;
    color: var(--ink-dark);
}

/* Il marchio arriva dal partial, quindi in mezzo c'e' uno `span.marchio` che
   ha una sua misura fissa: qui deve lasciarsi misurare da chi lo contiene */
.menu__marchio .marchio,
.ingresso__marchio .marchio {
    width: 100%;
    height: auto;
}

/* Le voci si dispongono in colonne, da 4 in su.

   **Una regola sola invece di cinque casi**: al massimo tre righe per colonna.
   Da li' escono tutte le disposizioni che il committente ha elencato - 4
   diventa due colonne da due, 5 diventa 3+2, 6 tre da due, 9 tre da tre - e il
   tetto di nove figli della dashboard e' esattamente 3x3.

   `grid-auto-flow: column` riempie in VERTICALE prima di passare alla colonna
   successiva, che e' come si legge un indice. Con `row` si leggerebbe a zigzag.

   MISURATO: quattro voci in colonna singola chiedono **639px** e sfondano
   sotto i 640 di finestra; nove ne chiederebbero circa 1200, cioe' piu' di
   qualunque schermo. */
.menu__elenco {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(3, auto);
    justify-content: center;
    align-content: start;
    gap: 48px 96px;
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: center;
}

/* Fino a tre voci restano una colonna sola, centrata: e' il caso piu' comune
   e non ha bisogno di niente */
.menu__elenco[data-voci="1"],
.menu__elenco[data-voci="2"],
.menu__elenco[data-voci="3"] {
    grid-template-rows: none;
    grid-auto-flow: row;
}

/* Quattro voci: due colonne da due, non tre piu' una spaiata */
.menu__elenco[data-voci="4"] {
    grid-template-rows: repeat(2, auto);
}

/* Lo spazio fra le voci lo fa il `gap` della griglia: un `margin-top` sul
   fratello lo raddoppierebbe fra le righe e lo lascerebbe a zero fra le
   colonne */

.menu__indice {
    display: block;
    margin-bottom: 8px;
    font-size: var(--micro);
    color: var(--ink-60);
}

.menu__link {
    font-size: var(--display);
    font-weight: 700;
    text-transform: uppercase;
}

/* La voce dove ci si trova adesso.

   Tre cose insieme, ognuna a una distanza di lettura diversa: il quadratino
   accanto al titolo si vede da lontano, il numero acceso guida l'occhio lungo
   la colonna, il corsivo si trova leggendo.

   Il quadratino sta sul LINK e non sull'indice: agganciato al numero risultava
   allineato a quello e non al titolo, che e' la cosa che si legge. */
.menu__voce.e-attiva .menu__link {
    font-style: italic;
}

/* Il numero della voce attiva si accende: bianco pieno contro il grigio delle
   altre, che restano attenuate */
.menu__voce.e-attiva .menu__indice {
    color: var(--ink-dark);
}

.menu__link {
    position: relative;
}

/* Piu' grande di quello dell'elenco: qui il testo e' display, non micro */
.menu__voce.e-attiva .menu__link::before {
    content: "";
    position: absolute;
    left: -22px;
    top: 50%;
    width: 10px;
    height: 10px;
    background: currentColor;
    transform: translateY(-50%);
}

/* Le voci entrano verso il basso, una dopo l'altra.

   Lo stesso passo della testata - 60ms per posizione - perche' e' lo stesso
   gesto: un blocco che si compone, non elementi che arrivano a caso. */
.menu[hidden] .menu__voce {
    animation: none;
}

.menu:not([hidden]) .menu__voce {
    animation: riga-entra 460ms var(--ease) both;
}

.menu:not([hidden]) .menu__voce:nth-child(1) { animation-delay: 120ms; }
.menu:not([hidden]) .menu__voce:nth-child(2) { animation-delay: 180ms; }
.menu:not([hidden]) .menu__voce:nth-child(3) { animation-delay: 240ms; }
.menu:not([hidden]) .menu__voce:nth-child(4) { animation-delay: 300ms; }
.menu:not([hidden]) .menu__voce:nth-child(5) { animation-delay: 360ms; }

/* Mentre il menu copre la pagina, sotto non si scorre */
body.menu-aperto {
    overflow: hidden;
}

/* La freccia per tornare al livello sopra ------------------------------ */

/* Sempre nello stesso posto, dentro il menu e sulle pagine: se cambiasse
   angolo a seconda di dove si e', smetterebbe di essere un gesto e
   tornerebbe a essere un pulsante da cercare. */
/* Il pulsante che torna al livello sopra.

   Si chiamava `.risalita`, che diceva il gesto ma non l'oggetto: `.indietro`
   si capisce leggendo, ed e' quello che il committente ha chiesto.

   Fissa nell'angolo, **fuori dalla barra dei recapiti**.

   Dentro, con 1rem dai bordi e 3rem di lato, sborderebbe dai margini della
   barra e i due elementi si vincolerebbero a vicenda - la freccia era gia'
   stata schiacciata a 0px di larghezza da quel flex. Cosi' ognuno ha la sua
   posizione e nessuno stringe l'altro.

   `z-index: 21` la tiene sopra il menu aperto (10) e sopra il suo pulsante di
   chiusura (20): resta **nello stesso punto** e cliccabile, aperto o chiuso. */
.indietro {
    position: fixed;
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    left: 1rem;
    z-index: 21;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    color: var(--ink);
}

/* Col menu aperto il fondo dietro e' scuro: il segno si inverte.
   La freccia e' una sola e non cambia posto fra le pagine e il menu */
body.menu-aperto .indietro {
    color: var(--ink-dark);
}

/* Un solo disegno per tutti i versi: punta in alto, e qui guarda a sinistra */
.indietro .freccia {
    display: block;
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
    transition: transform var(--t-transform) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
    .indietro:hover .freccia {
        transform: rotate(-90deg) translateY(-4px);
    }
}

/* Ingresso --------------------------------------------------------- */

/* Lo schermo nero col marchio, al primo arrivo sulla home.

   Sopra ogni cosa, menu compreso: per il momento in cui c'e', e' la pagina.
   Si toglie in dissolvenza e poi sparisce davvero - `visibility` e non solo
   `opacity`, se no resterebbe a intercettare i clic da invisibile. */
.ingresso {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--paper-dark);
    color: var(--ink-dark);
}

/* La rete di sicurezza: il velo si dissolve DA SOLO, senza JavaScript.
   Se lo script non arriva - errore, blocco, rete morta - la pagina si vede
   lo stesso. Parte dopo l'apertura del marchio e dura quanto la dissolvenza
   di pagina; il JavaScript, quando c'e', fa la stessa cosa un attimo prima. */
.ingresso {
    animation: ingresso-via var(--t-page) var(--ease) 600ms both;
}

@keyframes ingresso-via {
    from { opacity: 1; visibility: visible; }
    to   { opacity: 0; visibility: hidden; }
}

.ingresso.e-esce {
    opacity: 0;
    visibility: hidden;
    transition:
        opacity var(--t-page) var(--ease),
        visibility 0s linear var(--t-page);
}

/* Grande e centrato: un quinto del lato corto, cosi' resta grande su un
   telefono coricato senza sfondare in altezza */
.ingresso__marchio {
    display: block;
    width: min(20vw, 20vh);
    min-width: 96px;
}

.ingresso__marchio svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* L'apertura verticale del marchio: i due tracciati salgono, il secondo in
   ritardo di 130ms. 460ms in tutto - "veloce", come chiesto.

   **Vive su `.marchio--apre` e non solo sul loader**: la stessa animazione
   serve nella testata e in cima al menu, e riscriverla due volte vorrebbe
   dire vederla divergere alla prima modifica. */
.ingresso__marchio path,
.marchio--apre path {
    transform-origin: center bottom;
    animation: ingresso-apre 460ms var(--ease) both;
}

.ingresso__marchio path:nth-child(2),
.marchio--apre path:nth-child(2) {
    animation-delay: 130ms;
}

@keyframes ingresso-apre {
    from { transform: scaleY(0); }
    to   { transform: scaleY(1); }
}

/* Tutta la riga entra insieme al marchio, sfalsata.

   Il marchio si apre in verticale perche' e' fatto di due tracciati che si
   prestano; una parola no - allungata in verticale si legge come un errore di
   rendering. Sale e si scopre, che e' lo stesso movimento visto da lontano.
   Lo scarto di 130ms fra i due tracciati diventa qui la scala: 60ms per
   posizione, cosi' la testata entra come una cosa sola e non come quattro. */
@keyframes riga-entra {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* **All'ingresso si anima SOLO il marchio.**

   Etichetta e segno del menu entravano scaglionati, e a pagina nuova era
   bello. Ma il segno del menu prende
   `animation: none` mentre il pannello e' aperto - gli serve, se no il suo
   contesto di impilamento lo rimette sotto al velo - e **chiudendolo
   l'animazione riparte da capo**: MISURATO, zero navigazioni e un'animazione
   `running` al 42%, cioe' la testata che si ricompone dopo un gesto che non ha
   cambiato pagina.

   Si poteva aggiungere una terza regola per il caso; toglierla e' meglio,
   perche' il caso non esiste piu' invece di essere previsto.

   `riga-entra` resta: la usano le voci del menu, che si aprono davvero. */

/* Si arriva da dentro: niente ingresso.

   Chiudendo il menu o tornando indietro con la freccia non si ARRIVA da
   nessuna parte - si torna dove si era, e rivedere la testata comporsi da capo
   fa sembrare la pagina piu' lenta di quanto sia. La classe la mette uno
   script nella testa, prima che il CSS venga applicato.

   Stesse regole di `prefers-reduced-motion`, e non e' un caso: sono due modi
   di dire "questa volta non animare". */
.senza-transizione .ingresso__marchio path,
.senza-transizione .marchio--apre path {
    animation: none;
}

/* Le voci del menu tacciono solo finche' la pagina si sta dipingendo: aprire
   il menu dopo e' un gesto nuovo, e deve animarsi come sempre.
   `menu-si-anima` la mette lo script della testa a disegno finito. */
.senza-transizione:not(.menu-si-anima) .menu:not([hidden]) .menu__voce {
    animation: none;
}

/* E il velo nero non compare affatto */
.senza-transizione .ingresso {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .ingresso__marchio path,
    .marchio--apre path,
    .menu:not([hidden]) .menu__voce {
        animation: none;
    }

    .indietro .freccia {
        transition: none;
    }

    .ingresso.e-esce {
        transition: none;
    }
}

/* Vetrina ---------------------------------------------------------- */

/* La landing sta in una schermata: la testata e le due meta', senza scorrere.

   `100dvh` dopo `100vh` e non al posto suo: su telefono `100vh` e' il viewport
   a barra dell'indirizzo ritratta, e promette 60-90px che non ci sono. Il
   `vh` resta come ripiego per i motori che non conoscono `dvh`. */
body.home {
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

body.home #contenuto {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.vetrina {
    flex: 1;
    min-height: 0;
    display: flex;
}

/* `isolation` perche' la foto uscente sta a `z-index: -1`: senza, finirebbe
   sotto il fondo grigio del riquadro invece che sotto la foto nuova */
.vetrina__meta {
    flex: 1;
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

/* Il grigio e' l'attesa di una fotografia, non un riquadro decorativo: si mette
   solo dove una fotografia c'e' davvero e deve ancora arrivare.
   MISURATO: su /photography/about e /architecture restava un rettangolo vuoto
   di 598x645px, mezzo schermo di niente. */
.vetrina__meta:has(img) {
    background: var(--rule);
}

/* La fotografia riempie la sua meta', sempre.

   `<picture>` e' un elemento in linea e si dimensiona sul contenuto: senza
   queste righe la foto tiene la sua proporzione e lascia una striscia vuota
   sopra o di lato. `object-fit: cover` ritaglia invece di deformare, e
   `position: absolute` toglie di mezzo le misure intrinseche che l'immagine si
   porta dietro - `width` e `height` restano nel markup perche' servono al
   browser per riservare lo spazio, ma qui non devono decidere il riquadro. */
.vetrina__foto,
.vetrina__foto img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

.vetrina__foto img {
    object-fit: cover;
    object-position: center;
}

/* Le foto si alternano a scatto secco, non in dissolvenza.

   **Nessuna `transition` qui, di proposito**: il committente ha chiesto un
   cambio netto, e una dissolvenza anche breve lo ammorbidirebbe. `visibility`
   e non `display` perche' quest'ultimo farebbe rifare il calcolo del
   riquadro a ogni scambio, dieci volte al secondo. */
.vetrina__foto {
    visibility: hidden;
}

.vetrina__foto.e-visibile {
    visibility: visible;
}

/* La foto appena lasciata resta sotto la nuova finche' questa non e' a
   video: se la nuova arriva un fotogramma tardi si vede lei, non il fondo */
.vetrina__foto.e-uscente {
    visibility: visible;
    z-index: -1;
}

/* Le parole stanno SOPRA la fotografia, e in due angoli diversi.

   Sinistra: in basso a sinistra. Destra: in alto a destra. Cosi' i due blocchi
   stanno agli estremi opposti della diagonale e non si guardano in faccia
   attraverso il confine fra le due meta'.

   `pointer-events: none` perche' sono testo, non controlli: senza, il blocco
   coprirebbe una fetta di fotografia e mangerebbe l'hover che ferma lo
   scorrimento. */
.vetrina__parole {
    position: absolute;
    z-index: 1;
    max-width: 34ch;
    padding: 24px;
    color: var(--ink-dark);
    pointer-events: none;
}

.vetrina__meta--sinistra .vetrina__parole {
    bottom: 0;
    left: 0;
    text-align: left;
}

.vetrina__meta--destra .vetrina__parole {
    top: 0;
    right: 0;
    text-align: right;
}

/* A immagine intera non c'e' una meta' da distinguere: in basso a sinistra,
   come la sinistra dello split */
.vetrina__meta--piena .vetrina__parole {
    bottom: 0;
    left: 0;
    text-align: left;
}

.vetrina__titolo {
    margin: 0;
    font-size: var(--display);
    font-weight: 700;
    line-height: 1.1;
}

/* Il titolo puo' essere un link: allora e' cliccabile, e la sottolineatura al
   passaggio lo dice. Il blocco e' `pointer-events: none` per non rubare
   l'hover alla fotografia, quindi il link se li riprende per se' */
.vetrina__titolo a {
    pointer-events: auto;
}

.vetrina__titolo a:hover,
.vetrina__titolo a:focus-visible {
    text-decoration: underline;
}

.vetrina__testo {
    margin-top: 8px;
}

.vetrina__testo p {
    margin: 0 0 4px;
}

.vetrina__testo p:last-child {
    margin-bottom: 0;
}

/* Elenco tipografico ----------------------------------------------- */

/* Margine 122px su 1440, cioe' l'8,5% misurato sui wireframe */
.elenco,
.griglia {
    padding: 64px 8.5%;
}

.about {
    padding: 64px 24px;
}

/* Gallery a tutto schermo ------------------------------------------- */

/* Si apre da `static`, al clic su una fotografia.

   Portata da UmbriaFiere `main.js:1290`: stesse azioni - Escape, frecce,
   swipe, contatore - e la stessa difesa, cioe' che **senza GSAP funziona lo
   stesso**, solo senza dissolvenza. Una lightbox che dipende da un CDN e'
   una lightbox che a volte non si apre. */
.lente {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--paper-dark);
}

.lente[hidden] {
    display: none;
}

.lente__palco {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    padding: 64px 24px;
}

.lente__foto {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    opacity: 0;
}

/* La fotografia entra in dissolvenza a ogni cambio: la classe si toglie e si
   rimette, e il `void offsetWidth` nel JavaScript forza il ridisegno in mezzo
   - se no il browser vede solo lo stato finale e non anima niente */
.lente__foto.e-dentro {
    opacity: 1;
    transition: opacity var(--t-opacity) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
    .lente__foto {
        opacity: 1;
    }

    .lente__foto.e-dentro {
        transition: none;
    }
}

/* Il velo prende il fuoco all'apertura, ma non e' un comando: l'anello
   attorno a tutto lo schermo non direbbe niente */
.lente:focus {
    outline: none;
}

.lente__chiudi,
.lente__prec,
.lente__succ {
    position: absolute;
    z-index: 1;
    padding: 12px;
    background: none;
    border: 0;
    color: var(--ink-dark);
    cursor: pointer;
}

.lente__chiudi {
    top: 16px;
    right: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
}

/* La X: due barre incrociate, come quella del menu a pannello aperto. Qui
   sono gia' due, quindi non c'e' la terza da far sparire */
.lente__barra {
    position: absolute;
    width: 2px;
    height: 18px;
    background: currentColor;
}

.lente__barra:nth-child(1) { transform: rotate(45deg); }
.lente__barra:nth-child(2) { transform: rotate(-45deg); }

.lente__prec,
.lente__succ {
    width: 44px;
    height: 44px;
    padding: 0;
}

/* Lo stesso disegno ruotato, come nelle pagine: punta in alto, e da li'
   guarda a sinistra o a destra */
.lente__prec .freccia,
.lente__succ .freccia {
    display: block;
    width: 100%;
    height: 100%;
}

.lente__prec .freccia {
    transform: rotate(-90deg);
}

.lente__succ .freccia {
    transform: rotate(90deg);
}

.lente__prec {
    left: 24px;
}

.lente__succ {
    right: 24px;
}

.lente__contatore {
    position: absolute;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    color: var(--ink-dark);
    font-size: var(--micro);
}

body.lente-aperta {
    overflow: hidden;
}

/* Pagina progetto ---------------------------------------------------- */

/* Testo a sinistra, fotografie a destra: la variante B dei wireframe.
   Il testo resta fermo mentre la gallery scorre accanto - e' la didascalia di
   tutto quello che si guarda, non della prima foto. */
.progetto {
    display: flex;
    align-items: flex-start;
    gap: 6%;
    padding: 64px 24px;
}

.progetto__testo {
    position: sticky;
    top: calc(var(--testata-h) + 64px);
    flex: 0 0 32%;
    max-width: 32%;
}

.progetto__titolo {
    margin: 0 0 24px;
    font-size: var(--display);
    font-weight: 700;
    line-height: 1.1;
    text-transform: uppercase;
}

/* Anno e luogo su una riga, separati da un filo: senza etichette, perche'
   "YEAR 2026" diceva due volte la stessa cosa */
.progetto__dati {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0 0 24px;
    color: var(--ink-60);
}

.progetto__dati span + span::before {
    content: "/";
    margin-right: 12px;
}

.progetto__descrizione {
    max-width: 46ch;
}

.progetto__descrizione p {
    margin: 0 0 12px;
}

.progetto__gallery {
    flex: 1 1 62%;
    min-width: 0;
}

.progetto__vuota {
    margin: 0;
    color: var(--ink-60);
}

/* Le tre gallery ----------------------------------------------------- */

.gallery__scatto {
    margin: 0;
}

/* La PAGINA sta ferma e scorrono le immagini dentro il loro riquadro.

   `overscroll-behavior: contain` perche' arrivati in fondo lo scorrimento non
   deve passare alla finestra: il senso di questo stile e' che la pagina non si
   muove. La barra e' nascosta, il gesto resta. */
.gallery--static {
    display: flex;
    flex-direction: column;
    gap: 0;
    height: calc(100vh - var(--testata-h) - 128px);
    height: calc(100dvh - var(--testata-h) - 128px);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
}

.gallery--static::-webkit-scrollbar {
    display: none;
}

/* Si apre a tutto schermo al clic. Un puntatore normale e non la lente: la
   lente promette uno zoom, e quello che succede e' un'altra cosa */
.gallery--static .gallery__scatto {
    cursor: pointer;
}

/* A tutta larghezza vuol dire TUTTA la finestra: qui il testo non sta in
   colonna accanto, sta sopra, e sotto le fotografie toccano i due bordi.
   Il margine negativo annulla il padding della pagina da entrambi i lati. */
.progetto[data-stile="full"] {
    display: block;
}

.progetto[data-stile="full"] .progetto__testo {
    position: static;
    flex: none;
    max-width: none;
    margin-bottom: 48px;
}

.gallery--full {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin: 0 -24px;
}

.gallery--full .gallery__scatto img {
    width: 100%;
    height: auto;
}

/* VERTICALE dentro il riquadro, non orizzontale.

   La finestra non si muove: scorrono solo le fotografie, attaccate una
   all'altra senza spazio in mezzo - un nastro continuo, non una pila di
   riquadri staccati. La barra e' nascosta. */
/* Esce dal riquadro della pagina: tocca la testata in alto, e il bordo destro
   e quello basso della finestra. Solo a sinistra resta la colonna del testo.
   I margini negativi annullano il padding della pagina invece di toglierlo -
   cosi' il resto non deve sapere che questa gallery esiste. */
.progetto[data-stile="scroll"] {
    padding-bottom: 0;
    padding-right: 0;
}

/* `100vh` MENO la testata, che sta sopra: con l'altezza piena la pagina
   eccedeva di 54px - esattamente l'altezza della testata - e allora
   trascinando scorrevano insieme la gallery E la finestra. Ecco perche' il
   gesto sembrava impuntarsi: erano due scorrimenti sovrapposti, non uno
   lento. MISURATO: `docH 957` contro `winH 903`. */
.gallery--scroll {
    display: flex;
    flex-direction: column;
    gap: 0;
    margin-top: -64px;
    height: calc(100vh - var(--testata-h));
    height: calc(100dvh - var(--testata-h));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
    scroll-snap-type: y proximity;
}

/* Il browser non si porta via la fotografia: senza, il trascinamento NATIVO
   la prende come file. Resta utile anche senza il grab, per chi ci passa
   sopra col mouse premuto mentre scorre. */
.gallery--scroll img {
    -webkit-user-drag: none;
    user-select: none;
}

.gallery--scroll::-webkit-scrollbar {
    display: none;
}

.gallery--scroll .gallery__scatto {
    scroll-snap-align: start;
}

.gallery--scroll .gallery__scatto img {
    width: 100%;
    height: auto;
}

/* Dove non c'e' un cursore le due colonne si impilano.

   **Feature query e non breakpoint**, e non e' un cavillo per aggirare la
   regola 8: i file per device usano `min-device-width`, che legge lo SCHERMO
   FISICO, e su una finestra stretta di un desktop non scatta mai - misurato
   in questa stessa sessione. Qui la condizione vera e' "niente cursore",
   perche' senza si tiene il telefono in mano e la colonna di testo diventa
   109px, cioe' poco piu' di una parola per riga. */
@media (hover: none) {
    .progetto {
        flex-direction: column;
        gap: 32px;
    }

    /* Impilati il testo sta SOPRA, quindi la gallery puo' prendere tutta la
       larghezza: il padding che le toglievo a destra qui va tolto da tutti e
       due i lati, se no il testo resta in 72px */
    .progetto[data-stile="scroll"] {
        padding-right: 24px;
    }

    .progetto[data-stile="scroll"] .progetto__gallery {
        margin: 0 -24px;
    }

    .gallery--scroll {
        margin-top: 0;
        height: 70vh;
        height: 70dvh;
    }

    .progetto__testo {
        position: static;
        flex: none;
        max-width: none;
    }

    .progetto__gallery {
        width: 100%;
    }

    /* A tutta larghezza vuol dire fino a tutti e due i bordi: impilati, non
       c'e' piu' una colonna di testo accanto */
    .gallery--full {
        margin: 0 -24px;
    }

    .gallery--static {
        gap: 0;
    }

    .gallery--scroll .gallery__scatto {
        max-width: 88%;
    }

    /* **L'elenco si impila.** Tre colonne su 390px davano il testo a 36px e la
       fotografia a 142: i titoli andavano a capo lettera per lettera.

       Sta qui e non in `responsive-phone.css` perche' quel file chiede
       `max-device-width: 568px` - la misura di un iPhone 5 - e su un telefono
       di oggi non scatta. `hover: none` e' vero ovunque manchi un cursore, ed
       e' la condizione che conta: senza hover niente scambia i gruppi, quindi
       i progetti devono stare tutti sotto la loro categoria. */
    .elenco__colonne {
        flex-direction: column;
        gap: 24px;
        height: auto;
    }

    .elenco__testo,
    .elenco__progetti,
    .elenco__vetrina {
        flex: none;
        width: 100%;
    }

    .elenco__progetti {
        position: static;
    }

    /* Due classi e non una: `.elenco__gruppo.e-visibile` pesa di piu', e con
       un solo selettore vinceva lei - si vedeva un gruppo su nove */
    .elenco__gruppo,
    .elenco__gruppo.e-visibile {
        position: static;
        opacity: 1;
        transform: none;
        pointer-events: auto;
        margin-left: 12%;
    }

    /* Impilato, `align-self: stretch` non ha piu' una riga da cui prendere la
       misura: l'altezza va detta */
    .elenco__vetrina {
        height: 60vh;
        height: 60dvh;
    }
}

/* `margin-top` e non lo shorthand `margin`: i figli hanno un `margin-left` che
   fa il rientro, e uno shorthand qui lo azzererebbe */
.elenco__voci,
.elenco__figli {
    margin-top: 0;
    padding: 0;
    list-style: none;
}

.elenco__voce + .elenco__voce {
    margin-top: 4px;
}

/* Largo quanto la parola e non quanto la riga: senza, il cursore accende la
   voce anche passando a meta' pagina, dove non c'e' scritto niente */
.elenco__link {
    display: inline-block;
    width: fit-content;
    padding: 2px 0;
}

/* Anche le voci: un `li` largo tutta la colonna intercetta il cursore ovunque.

   `max-content` e non `fit-content`: il secondo, dentro una griglia stretta,
   prende la larghezza MINIMA del contenuto e manda a capo anche quando ci
   sarebbe spazio - misurato, "Solenoide" si spezzava in "Solenoi/de".
   `max-content` prende la larghezza che il testo vorrebbe, e `max-width: 100%`
   lo tiene dentro la colonna quando e' davvero troppo lungo. */
.elenco__voce,
.elenco__figli > li {
    width: max-content;
    max-width: 100%;
    list-style: none;
}

/* `break-word` e non `anywhere`: quest'ultimo spezza dove capita, e
   "Solenoide" andava a capo in mezzo alla parola anche con spazio di avanzo.
   Cosi' si va a capo fra le parole, e si spezza solo una parola che da sola
   non ci sta. */
.elenco__link {
    overflow-wrap: break-word;
}

/* In hover niente sottolineatura: cio' che si guarda lo dice gia' il corsivo.
   Da tastiera resta un segno, se no col Tab non si sa dove si e' */
.elenco__link:focus-visible {
    outline: 1px solid var(--ink);
    outline-offset: 3px;
}

/* Due colonne: l'elenco a sinistra, il riquadro delle foto a destra.

   **Il riquadro riempie l'altezza rimasta.** `align-items: stretch` da solo non
   basta: stira i figli fino all'altezza della RIGA, e la riga e' alta quanto il
   suo contenuto - misurato, 187px. Serve un'altezza da cui partire, e qui e'
   la finestra meno la testata e i margini.

   `100dvh` dopo `100vh`: su telefono `100vh` e' il viewport a barra ritratta,
   e promette spazio che non c'e'. */
/* Il `gap` e' in pixel e non in percentuale: le colonne adesso sono tre, e
   tre intercolonne al 6% toglievano alla foto piu' di quanto le due di prima */
.elenco__colonne {
    display: flex;
    gap: 34px;
    align-items: stretch;
    min-height: calc(100vh - var(--testata-h) - var(--contatti-h) - 128px);
    min-height: calc(100dvh - var(--testata-h) - var(--contatti-h) - 128px);
}

/* Le due colonne di testo stanno nello spazio che prima ne occupava una: il
   riquadro non si restringe, era gia' la misura giusta */
.elenco__testo {
    flex: 0 0 13%;
    min-width: 0;
}

/* Il riquadro respira: staccato dal testo e dal bordo, non incollato.

   **Non ritaglia piu'**: il titolo sta oltre il bordo destro e `overflow:
   hidden` qui lo cancellava del tutto. A ritagliare sono le schede, che e'
   dove il ritaglio serve davvero - le fotografie. */
.elenco__vetrina {
    display: block;
    position: relative;
    flex: 1 1 46%;
    min-width: 0;
    align-self: stretch;
}

.elenco__vetrina:has(img) {
    background: var(--rule);
}

/* Il titolo del progetto, verticale contro il bordo destro del riquadro.

   **Sta SOTTO le fotografie**, non accanto: e' la foto stessa a coprirlo, e
   uscendo il titolo scivola dietro di lei invece di sparire. Per questo lo
   `z-index` e' piu' basso e il riquadro ha gia' `overflow: hidden`.

   In assoluto e non nel flusso: da colonna si prendeva spazio e la fotografia
   si restringeva.

   `writing-mode` e non `rotate()`: ruotando, il box resta orizzontale e
   l'ancoraggio al bordo andrebbe rifatto a ogni lunghezza di titolo. */
.elenco__titolo {
    position: absolute;
    top: 0;
    /* Fuori dal bordo destro: dentro sarebbe sempre coperto dalla foto, che
       gli sta sopra. Da qui esce del tutto scivolando dietro di lei */
    right: -1.5rem;
    z-index: 0;
    writing-mode: vertical-rl;
    padding: 4px 0;
    max-height: 100%;
    font-size: var(--micro);
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    white-space: nowrap;
    /* Piu' svelto del transform standard: il titolo fa un tragitto corto - un
       paio di centimetri dietro la foto - e a 280ms sembrava pigro */
    transition: transform 160ms var(--ease);
}

/* Le fotografie stanno sopra il titolo e lo coprono mentre rientra.
   Il ritaglio sta qui, non sul riquadro: cosi' il titolo puo' uscirne */
.elenco__scheda {
    position: relative;
    z-index: 1;
    overflow: hidden;
}

/* Nascosto vuol dire dietro la fotografia, cioe' spostato verso sinistra: e'
   la foto a coprirlo, e da li' riesce fuori col nome nuovo */
.elenco__titolo.e-fuori {
    transform: translateX(-1.5rem);
}




/* Una scheda per progetto, tutte sovrapposte: a vedersi e' quella accesa.
   Sovrapposte e non montate al momento, perche' lo scambio e' secco e
   costruirle al passaggio darebbe un riquadro vuoto per mezzo secondo. */
.elenco__scheda {
    position: absolute;
    inset: 0;
    display: none;
}

.elenco__scheda.e-attiva {
    display: block;
}

.elenco__foto,
.elenco__foto img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

.elenco__foto img {
    object-fit: cover;
    object-position: center;
}

/* Scatto secco come in home: nessuna `transition`, di proposito */
.elenco__foto {
    visibility: hidden;
}

.elenco__foto.e-visibile {
    visibility: visible;
}

/* Come in home. La scheda ha gia' `z-index`, quindi il -1 resta dentro di lei */
.elenco__foto.e-uscente {
    visibility: visible;
    z-index: -1;
}

/* I progetti della categoria puntata, nella colonna accanto.

   **Le categorie non si muovono mai.** Prima i progetti stavano DENTRO la
   categoria e aprirne una spingeva giu' tutte le altre: scendendo lungo
   l'elenco la voce puntata risaliva di 75px - misurato - e il cursore si
   trovava su un'altra. Qui i progetti sono una colonna a se', e cambiare
   categoria non tocca la colonna di sinistra.

   I gruppi sono sovrapposti nello stesso posto: si scambia quale e' visibile,
   non si ricostruisce niente. */
.elenco__progetti {
    position: relative;
    flex: 0 0 22%;
    min-width: 0;
}

.elenco__gruppo {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    list-style: none;
    margin: 0;
    padding: 0;
    opacity: 0;
    /* Scostato di poco, e rientra: il gruppo nuovo arriva, non appare */
    transform: translateY(6px);
    pointer-events: none;
    transition:
        opacity var(--t-opacity) var(--ease),
        transform var(--t-transform) var(--ease);
}

.elenco__gruppo.e-visibile {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

/* Passando su un progetto, gli altri si attenuano.

   **Mai tutti insieme**: si attenua solo cio' che NON e' puntato mentre il
   cursore e' sul gruppo, quindi o sono tutti pieni o ne resta acceso uno. */
.elenco__link {
    transition: opacity var(--t-opacity) var(--ease);
}

/* **`:has()` e non `:hover` sul gruppo.**

   Col gruppo, bastava entrare nella colonna senza toccare una parola - a
   destra del testo, o fra due righe - e si attenuavano tutti e tre. Misurato:
   `["0.4","0.4","0.4"]`. Cosi' invece si attenua solo quando un progetto e'
   davvero puntato: o sono tutti pieni, o ne resta acceso uno. */
.elenco__gruppo:has(.elenco__link:hover) .elenco__link:not(:hover),
.elenco__gruppo:has(.elenco__link:focus-visible) .elenco__link:not(:focus-visible) {
    opacity: 0.4;
}


/* Il corsivo dice QUALE progetto si sta guardando nel riquadro a destra.

   Non sulla voce aperta, che e' un'altra cosa: quella dice dove si sta
   guardando dentro, questo dice cosa si sta guardando. Sul progetto e' il
   segno che lega l'elenco alle fotografie. */
/* **`padding` e non `margin`.**

   Col margine i 10px stavano FUORI dal link: passandoci sopra si era nel
   gruppo ma su nessun progetto, e si attenuavano tutti e tre. Come padding
   appartengono al link, quindi il rientro risponde al cursore.

   Il link resta largo quanto il suo testo: l'hover finisce dove finisce la
   parola, non a fondo colonna. */
.elenco__gruppo .elenco__link {
    transition:
        opacity var(--t-opacity) var(--ease),
        padding-left var(--t-transform) var(--ease);
}

.elenco__gruppo .elenco__link {
    position: relative;
}

.elenco__gruppo .elenco__link.e-guardato {
    font-style: italic;
    padding-left: 18px;
}

/* Il quadratino segna il PROGETTO che si sta guardando, non la categoria: e'
   la cosa, non il posto. Dentro il rientro, che e' padding del link e quindi
   risponde al cursore come il resto della riga */
.elenco__gruppo .elenco__link.e-guardato::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 6px;
    height: 6px;
    background: currentColor;
    transform: translateY(-50%);
}

/* La categoria attiva fa un passo fuori dalla colonna.

   Il quadratino e' sceso al livello sotto, sul progetto: segna cio' che si
   sta guardando, e una categoria e' il posto in cui si guarda, non la cosa.
   Qui basta lo scostamento.

   `padding` e non `margin`: il margine sta FUORI dal link, e passandoci sopra
   il cursore non prenderebbe la voce. */
.elenco__voce .elenco__link {
    display: inline-block;
    transition: padding-left var(--t-transform) var(--ease);
}

.elenco__voce.e-aperto .elenco__link,
.elenco__voce:hover .elenco__link,
.elenco__voce:focus-within .elenco__link {
    padding-left: 12px;
}



/* Griglia ---------------------------------------------------------- */

/* Quattro colonne e anteprime quadrate: misurato sui wireframe, gutter 32px
   in orizzontale e 53px fra le righe */
.griglia__elenco {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 53px 32px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* **Non ritaglia**: il titolo esce sotto il bordo, e `overflow: hidden` qui
   lo cancellerebbe. A ritagliare sono le fotografie, che e' dove serve */
.griglia__link {
    display: block;
    position: relative;
    aspect-ratio: 1;
}

.griglia__foto {
    overflow: hidden;
    z-index: 1;
}

.griglia__link:has(img) {
    background: var(--rule);
}

/* La scheda e' SOLO l'immagine: riempie il quadrato, qualunque proporzione
   abbia la fotografia. Sopra il nome, che da ferme lo nascondono */
.griglia__foto,
.griglia__foto img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

.griglia__foto img {
    object-fit: cover;
    object-position: center;
}

/* Le foto del progetto scorrono al passaggio del cursore, a scatto secco come
   in home: nessuna `transition`, di proposito */
.griglia__foto {
    visibility: hidden;
}

/* Qui le foto stanno gia' a 1 per coprire il nome: la nuova sale a 2, e
   quella appena lasciata resta a 1, sotto di lei e sopra il nome */
.griglia__foto.e-visibile {
    visibility: visible;
    z-index: 2;
}

.griglia__foto.e-uscente {
    visibility: visible;
}

/* Il nome sta SEMPRE nel markup: su telefono l'hover non esiste, e una
   fotografia senza nome non dice niente a chi non ha un mouse.
   Da desktop sta nascosto DIETRO l'immagine e scende fuori al passaggio del
   cursore: la regola che lo muove e' nella feature query piu' sotto. */
/* `z-index: 0` e le fotografie a 1: cosi' e' dietro LORO, non dietro la
   cella. Con -1 finiva sotto il fondo del link e restava coperto anche da
   uscito - misurato, `elementFromPoint` dava IMG invece del nome */
.griglia__nome {
    position: absolute;
    left: 0;
    top: 100%;
    z-index: 0;
    max-width: 100%;
    padding: 8px 0 0;
    color: var(--ink);
    font-size: var(--micro);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Non trovato ------------------------------------------------------ */

.errore {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 16px;
    min-height: calc(100vh - var(--testata-h) - 128px);
    padding: 64px 24px;
}

.errore__titolo {
    margin: 0;
    font-size: var(--display);
    font-weight: 700;
    line-height: 1.1;
}

.errore__testo {
    margin: 0;
    color: var(--ink-60);
}

.errore__ritorno {
    text-decoration: underline;
}

/* Contatti --------------------------------------------------------- */

/* In fondo a destra, con la sua posizione: la freccia sta fuori e ha la
   propria, cosi' nessuno dei due stringe l'altro.
   `left` oltre la freccia (3rem di lato + 1rem di margine + un respiro):
   senza, su schermo stretto il testo ci finirebbe sotto. */
.contatti {
    position: fixed;
    right: 24px;
    bottom: 0;
    left: calc(4rem + 24px);
    z-index: 2;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 24px;
    padding: 16px 0 calc(16px + env(safe-area-inset-bottom, 0px));
    font-style: normal;
    font-size: var(--micro);
}

/* Il contenuto non finisce sotto la barra: lo spazio glielo lascia il corpo,
   non ogni pagina per conto suo.

   Lo spazio si lascia SEMPRE e si toglie sulla landing, invece di darlo solo
   dove i recapiti ci sono: `:has()` e' recente, e dove non esiste la prima
   forma non applicherebbe niente e il contenuto finirebbe sotto la barra.
   Cosi' il caso peggiore e' 76px di spazio in fondo a una pagina che non ne
   aveva bisogno. */
#contenuto {
    padding-bottom: var(--contatti-h);
}

body.home #contenuto {
    padding-bottom: 0;
}

/* Nemmeno la pagina progetto ha i recapiti: lasciarle lo spazio le farebbe
   scorrere di 76px a vuoto, e questi stili vivono di una finestra ferma */
body:has(.progetto) #contenuto {
    padding-bottom: 0;
}

/* La finestra sta ferma: qui a scorrere sono le fotografie dentro il loro
   riquadro, e una pagina che scorre sotto di loro raddoppia il gesto */
body:has(.progetto[data-stile="scroll"]),
body:has(.progetto[data-stile="static"]) {
    overflow: hidden;
}

/* Il nome compare al passaggio del cursore, dove un cursore c'e'.

   **Non e' un breakpoint**: chiede se il dispositivo ha un puntatore preciso,
   che e' esattamente la condizione che serve. La regola 8 vieta le media query
   dimensionali fuori dai file per device, non le feature query - e qui una
   feature query e' anche piu' corretta.

   MISURATO il difetto che questa regola evita: i blocchi per device copiati da
   UmbriaFiere usano `min-device-width`, che legge lo SCHERMO FISICO. Su un
   portatile con schermo 800x600 e finestra 1440 non scattano, e il nome
   resterebbe visibile anche dove il cursore c'e'. */
@media (hover: hover) and (pointer: fine) {
    /* Nascosto dietro la fotografia, allineato al suo bordo basso: l'immagine
       lo copre. In hover scende fuori, e la foto lo scopre da sopra.
       Solo `transform`, e il gap fra le righe e' 53px: c'e' spazio */
    /* A riposo risale DENTRO il quadrato, dove la fotografia lo copre: la
       sua altezza piu' il padding. In hover torna al suo posto, sotto il
       bordo, e scende da sotto l'immagine */
    .griglia__nome {
        transform: translateY(-100%);
        transition: transform var(--t-transform) var(--ease);
    }

    .griglia__link:hover .griglia__nome,
    .griglia__link:focus-visible .griglia__nome {
        transform: none;
    }

    /* **L'elenco sta nella finestra, e l'altezza non cambia mai.**

       Con i progetti veri, tenendo aperto tutto la pagina misurava 1004px
       contro 850 di finestra. Adesso se ne apre una sola - lo fa il JS - e
       qui si toglie lo scorrimento che non serve piu'.

       La colonna scorre internamente solo se nemmeno una voce aperta ci sta:
       e' la valvola per la finestra bassa, non il funzionamento normale.

       Sta qui e non nei file per device perche' quelli usano
       `min-device-width`, che legge lo schermo fisico: su una finestra
       stretta di un desktop non scattano mai. Dove non c'e' il cursore non
       c'e' nemmeno l'hover che apre, quindi il vincolo non ha senso e il
       telefono resta scrollabile. */
    body:has(.elenco) {
        overflow: hidden;
    }

    .elenco__colonne {
        height: calc(100dvh - var(--testata-h) - var(--contatti-h) - 128px);
    }

    .elenco__testo {
        overflow-y: auto;
        scrollbar-width: none;
    }

    .elenco__testo::-webkit-scrollbar {
        display: none;
    }
}

/* Movimento -------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        animation-delay: 0s !important;
        transition-delay: 0s !important;
        scroll-behavior: auto !important;
    }
}
