/* =============================================================================
   Hero: l'apertura dell'archivio progetti.

   Nodi di design 75:1855, 75:1868, 78:837 e la cima del 513:860 — quattro stati
   della stessa schermata. Annotazione sul primo: «shrink opening».

   Stessa struttura a due layout degli altri moduli-scena: il default è statico —
   la card col progetto in evidenza dentro, leggibile e cliccabile — e il layout
   animato sta dentro
   `@media (scripting: enabled) and (prefers-reduced-motion: no-preference)`.

   Il JavaScript non anima: campiona un progresso e scrive undici custom property
   su questo contenitore. I default qui sotto sono il **primo fotogramma**, quindi
   se il JS non parte mai la prima schermata è comunque composta.
   ========================================================================== */

.hero-projects {
    /* --- Valori guidati dal JS ------------------------------------------------
       Fotogramma zero: filmato a tutto schermo senza angoli, titolo della pagina
       visibile, progetto e pulsante ancora fuori. */
    --card-x: 0%;
    --card-y: 0%;
    --card-w: 100%;
    --card-h: 100%;
    --card-radius: 0px;
    --heading-o: 1;
    --heading-y: 0px;
    --title-o: 0;
    --title-y: 40px;
    --footer-o: 0;
    --cta-o: 0;

    /* Il velo all'inizio è metà del massimo: nel design è nero al 30% sul nodo
       75:1856 e al 60% sul 78:838, e il massimo è un campo ACF. Vedi la traccia
       OVERLAY nel JS, che scrive la stessa frazione.

       ⚠ **I due numeri non sono quelli di `hero-shrink-video`**, che sta a 0,2 e
       0,5. Là il rapporto fra i due estremi è 0,4; qui è 0,5. Sono due scene
       diverse e i valori vengono da due coppie di nodi diverse: copiare la
       frazione dall'altra darebbe un velo iniziale al 24% invece che al 30%. */
    --overlay-o: calc(0.5 * var(--hero-overlay-max, 0.6));

    /* Il rapporto della card d'arrivo: 1448×918 nel design. Serve al **layout
       statico**, dove la card non è il viewport ma un riquadro in flusso, e quindi
       una proporzione ce la deve avere. Nel layout animato non si usa: là
       larghezza e altezza le scrive il JS in percentuale della scena. */
    --card-ratio: 1448 / 918;

    /* Quanto scroll dura la scena, oltre alla schermata che resta in pin.

       ⚠ **Questo numero non è nel design**, che dà quattro stati e nessuna durata.
       Sono duecento come in `hero-shrink-video`, e per la stessa ragione: le
       battute sono tre da due terzi di schermata — il titolo della pagina esce, il
       progetto entra, il filmato si restringe. Le gemelle stanno a 400vh, ma la
       loro scena ha una card che attraversa lo schermo.

       È la manopola di questo modulo: se la scena sembra lunga o corta si gira
       qui, e le tracce del JS seguono da sé perché sono frazioni. */
    --scroll-length: 200vh;

    /* Il rientro dei dati e del pulsante dagli angoli del media: 24px nel design,
       misurato su entrambi gli stati — nel nodo 78:837 il media è a pieno campo e
       il riquadro dei dati ha `padding: 24`; nel 513:860 il media è la card e il
       pulsante sta a x=1332 su una card che finisce a 1480, cioè 24 dal suo bordo.
       È quindi un rientro **dal media**, non dalla pagina, e per questo i due
       elementi stanno dentro il pannello e non accanto. */
    --panel-inset: var(--space-m);

    position: relative;
    color: var(--color-scene-text);
}

/* -----------------------------------------------------------------------------
   Layout statico: nessun JavaScript, movimento ridotto, o viewport stretto.
   -------------------------------------------------------------------------- */

.hero-projects__viewport {
    padding-block: var(--space-section);
}

.hero-projects__scene {
    position: relative;
    display: grid;
    gap: var(--space-2xl);
    justify-items: center;
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--gutter);
    overflow: hidden;
}

/* Il titolo della pagina. `title-upper-xg`: 128px su 104 di interlinea, tracking
   −3%, peso 900, maiuscolo, **bianco pieno** — l'apertura non ha il riempimento
   sfumato (base.css → `.display-gradient`).

   Niente `margin` qui: il reset di base.css lo azzera già, e dichiararlo sarebbe
   l'errore documentato per chi porta `.display-gradient` — che questo elemento non
   porta, ma la regola vale come abitudine. */
.hero-projects__heading {
    position: relative;
    z-index: 2;
    font-size: var(--text-display-xl);
    line-height: var(--leading-display-xl);
    letter-spacing: var(--tracking-display-xl);
    font-weight: var(--weight-black);
    text-transform: uppercase;
    text-align: center;
    /* `lnum` e `pnum`: cifre allineate e proporzionali, come nelle altre scene. */
    font-feature-settings: "lnum", "pnum";
}

/* Il riquadro del media, che nel layout statico è la card del design con il
   contenuto dentro: il nome del progetto al centro, i dati e il pulsante appoggiati
   al fondo.

   Il fondo scuro sta **qui e non sulla sezione**: nel design le sezioni lasciano
   vedere il fondo pagina col suo pattern, e qui si vede alla fine della scena,
   quando il filmato si è ristretto e attorno c'è pagina. Sul riquadro invece serve,
   per il tempo in cui il filmato non è ancora arrivato. */
.hero-projects__panel {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-rows: 1fr auto;
    gap: var(--space-m);
    width: 100%;
    aspect-ratio: var(--card-ratio);
    padding: var(--panel-inset);
    overflow: hidden;
    border-radius: var(--radius-xl);
    background-color: var(--color-scene-bg);
}

/* `height: 100%` esplicito: il reset di base.css impone `height: auto` a video e
   img, che qui annullerebbe il riempimento del riquadro. `object-fit: cover`
   ritaglia invece di deformare, ed è la ragione per cui la card più avanti si anima
   in larghezza e altezza vere e non con uno `scale()`: fra inizio e fine le
   proporzioni cambiano — da 1512×982 a 1448×918 — e uno scale schiaccerebbe il
   filmato. */
.hero-projects__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.hero-projects__overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-color: #000;
    opacity: var(--overlay-o);
    pointer-events: none;
}

/* `title-upper-lg`: 72 su 64, peso 900, maiuscolo, bianco pieno, centrato. */
.hero-projects__title {
    position: relative;
    z-index: 2;
    align-self: center;
    font-size: var(--text-display);
    line-height: var(--leading-display);
    font-weight: var(--weight-black);
    text-transform: uppercase;
    text-align: center;
    font-feature-settings: "lnum", "pnum";
}

/* I dati a sinistra e il pulsante a destra, sulla stessa riga: nel design stanno
   ai due angoli inferiori del media.

   `flex-wrap` più `gap`: su uno schermo stretto il pulsante va sotto i dati invece
   di schiacciarli, ed è la cosa giusta perché il design di quella larghezza non
   esiste. `align-items: end` allinea le basi, non i centri, che è come stanno nel
   nodo — il pulsante è alto 48 e la colonna dei dati 40. */
.hero-projects__footer {
    position: relative;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    justify-content: space-between;
    gap: var(--space-m);
}

/* I tre campi a 32px l'uno dall'altro, come nel nodo 513:898. `<dl>` e non dei
   `<div>`: sono tre coppie etichetta/valore, che è esattamente cosa una lista di
   definizioni descrive. Il reset del browser mette un margine sul `dd`, e qui la
   griglia lo ignora — ma `margin: 0` va dichiarato perché `* { margin: 0 }` di
   base.css lo azzera già solo per gli elementi, non per gli user-agent styles dei
   browser che usano il padding. */
.hero-projects__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-l);
}

.hero-projects__field {
    display: grid;
}

/* label-sm a 10px: 10 su 16, peso 600, tracking 8%, maiuscolo, all'80%. Gli stessi
   valori della card del carosello, perché nel design è lo stesso componente. */
.hero-projects__label {
    font-size: var(--text-label-s);
    line-height: var(--leading-label-s);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-label-s);
    text-transform: uppercase;
    opacity: 0.8;
}

/* body-xs: 16 su 24, peso 500, tracking 1%. */
.hero-projects__value {
    margin: 0;
    font-size: var(--text-body-s);
    line-height: var(--leading-body-s);
    font-weight: var(--weight-medium);
    letter-spacing: var(--tracking-body-s);
    font-feature-settings: "lnum", "pnum";
}

/* -----------------------------------------------------------------------------
   Layout animato: la scena in pin.
   -------------------------------------------------------------------------- */

/* soglia scene: 901px — vedi base.css → "Passaggio fra scene" */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) and (min-width: 901px) {

    /* L'altezza del contenitore è ciò che crea lo scroll: la schermata che resta in
       pin, più la lunghezza della scena, più i due tratti del passaggio fra scene —
       zero se la hero non ha vicini che siano scene. */
    .hero-projects {
        height: calc(
            100vh
            + var(--scene-enter, 0px)
            + var(--scroll-length)
            + var(--scene-hold, 0px)
        );
    }

    /* Il pin. `sticky` e non `fixed`: si aggancia e si sgancia da sé ai bordi del
       contenitore, senza che nessuno debba calcolare quando. */
    .hero-projects__viewport {
        position: sticky;
        inset-block-start: 0;
        height: 100vh;
        padding-block: 0;
        overflow: hidden;
    }

    .hero-projects__scene {
        display: block;
        height: 100%;
        max-width: none;
        margin-inline: 0;
        padding-inline: 0;
    }

    /* Il riquadro. Si animano `inset` e dimensioni, non un transform, per la ragione
       nel commento su `object-fit` qui sopra. È un elemento fuori dal flusso, quindi
       il ricalcolo è confinato a lui.

       ⚠ **Niente `contain: layout paint` qui**, al contrario di
       `hero-shrink-video`. `contain: paint` ritaglia al border box, e questo
       pannello ha tre figli agganciati ai propri angoli che devono restare dentro —
       ci restano — ma soprattutto `contain` su un elemento che cambia
       `border-radius` a ogni frame costringe a un nuovo livello di ritaglio per
       fotogramma. `overflow: hidden` basta a tenere dentro il filmato, che è la sola
       cosa che sborderebbe. */
    .hero-projects__panel {
        position: absolute;
        inset-inline-start: var(--card-x);
        inset-block-start: var(--card-y);
        display: block;
        width: var(--card-w);
        height: var(--card-h);
        aspect-ratio: auto;
        gap: 0;
        padding: 0;
        border-radius: var(--card-radius);
        will-change: width, height;
    }

    /* I due titoli sono **entrambi centrati sull'asse verticale** e non si vedono
       mai insieme: il titolo della pagina esce prima che il progetto entri, e il
       progetto è già entrato quando il filmato comincia a restringersi. Sono i
       quattro stati del design, in quest'ordine.

       Il centro è lo stesso per tutti e due, e non per caso: il rientro è di 32px
       su tutti e quattro i lati, quindi il centro della card coincide col centro
       dello schermo. Nel design il nome del progetto sta alla stessa y nel nodo
       78:837 (media a pieno campo) e nel 513:860 (media nella card): non si muove.

       `translate` è una property a sé, non dentro `transform`: così il centramento
       (-50%) e lo spostamento animato dal JS convivono in una sola dichiarazione,
       senza un elemento wrapper in mezzo il cui unico compito sarebbe tenere il
       -50%. */
    .hero-projects__heading,
    .hero-projects__title {
        position: absolute;
        inset-inline-start: 50%;
        inset-block-start: 50%;
        width: 100%;
        padding-inline: var(--gutter);
        pointer-events: none;
    }

    .hero-projects__heading {
        opacity: var(--heading-o);
        translate: -50% calc(-50% + var(--heading-y));
    }

    /* Il titolo del progetto sta **dentro** il pannello, quindi il suo 100% è la
       larghezza della card e non quella della scena. È la cosa giusta: nel design è
       centrato sulla card, e quando la card rientra di 32px per lato il testo
       rientra con lei. */
    .hero-projects__title {
        opacity: var(--title-o);
        translate: -50% calc(-50% + var(--title-y));
    }

    /* Dati e pulsante, agganciati agli angoli inferiori del pannello. Restano
       `flex` — è il pannello a diventare `block`, non loro — e il rientro è quello
       del design, misurato su entrambi gli stati. */
    .hero-projects__footer {
        position: absolute;
        inset-inline: var(--panel-inset);
        inset-block-end: var(--panel-inset);
        opacity: var(--footer-o);
    }

    /* Il pulsante compare **scoprendosi dal basso**, non in dissolvenza — la stessa
       scelta, e le stesse ragioni, del pulsante di `flexible-content/case-carousel`:
       una dissolvenza di bianco su fondo scuro passa necessariamente per il grigio,
       perché ridurre l'opacità del bianco *è* fare del grigio. Con un ritaglio ogni
       pixel visibile è a colore pieno.

       `inset(X 0 0 0)` ritaglia dall'alto: portando X da 100% a 0 la parte visibile
       cresce da sotto in su, che è anche la direzione del riempimento all'hover —
       quindi il modulo ha un movimento solo invece di due.

       ⚠ Il ritaglio sta sul pulsante e **l'opacità sul contenitore**, non entrambe
       sullo stesso elemento: i dati entrano in dissolvenza (sono testo su un
       filmato, e il grigio non c'entra) e il pulsante si scopre. Se `--footer-o`
       valesse anche per lui, il bianco tornerebbe grigio proprio nel tratto in cui
       si sta scoprendo. */
    .hero-projects__cta {
        clip-path: inset(calc((1 - var(--cta-o)) * 100%) 0 0 0);
    }

    /* Finché il pulsante non è comparso del tutto non è interattivo, e l'attributo
       lo mette il JS. Questa regola è la ridondanza per i browser che leggono
       `inert` senza implementarlo. */
    .hero-projects__cta[inert] {
        pointer-events: none;
    }
}
