/* Atelier Pasticceria — foglio unico, mobile first, niente JS */

/* Niente preload: aperto come file:// il preload fa fallire il font
   e Safari ripiega su SF Pro */
@font-face {
  font-family: "Poppins";
  font-weight: 400;
  font-style: normal;
  font-display: block;
  src: url("fonts/poppins-regular.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-weight: 400;
  font-style: italic;
  font-display: block;
  src: url("fonts/poppins-italic.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-weight: 500;
  font-style: normal;
  font-display: block;
  src: url("fonts/poppins-medium.woff2") format("woff2");
}

@font-face {
  font-family: "Poppins";
  font-weight: 600;
  font-style: normal;
  font-display: block;
  src: url("fonts/poppins-semibold.woff2") format("woff2");
}

:root {
  --green: #878c69;
  --green-shadow: color-mix(in oklab, var(--green), black 30%);
  --nero: #040404;
  --ink: #ffffff;
  /* L'ombra della casa: verso il basso a sinistra, come la luce delle foto.
     In vw, così resta proporzionata su ogni schermo invece di ingrossarsi
     sui piccoli. La usa la tartelletta della prima schermata. */
  --sh-x: -2vw;
  --sh-y: 3vw;
  --sh-blur: 4vw;
  /* Due margini, non uno. --m è quello della PAGINA e lo rispetta tutto
     quello che si legge, di lato e in basso. --mc è quello della fascia in
     alto: il logo ci si appoggia col bordo superiore e le onde del menu ci
     stanno per intero, perché la testata sta più vicina al bordo di quanto
     ci stia un contenuto. Di lato invece anche il logo segue la colonna.
     Sul telefono i due coincidono e la distinzione sparisce da sé. */
  --m: 24px;
  --mc: var(--m);
  --mx: var(--m);
  --mb: var(--m);
  --logo-h: 40px;
  /* L'hamburger NON segue più il marchio. Lo seguiva quando il logo era una
     riga sola e le due cose avevano la stessa altezza ottica; adesso il logo
     è un lockup a due righe, e un'icona alta quanto tutto il lockup sarebbe
     un'icona enorme. Qui resta la misura che aveva prima. */
  --menu-h: 32px;
  /* Fascia di sicurezza in alto: margine del marchio + marchio + aria.
     Ospita anche l'hamburger; i testi delle sezioni non ci entrano mai.
     L'aria si misura dal RIQUADRO del marchio, che è quello che il foglio
     conosce, e il totale fa 100 sul telefono e 120 sul desktop — sono le due
     misure chieste. Sotto le ONDE se ne vede di più: l'icona è più bassa del
     marchio (--menu-h contro --logo-h) e il loro inchiostro finisce 4,4px
     sopra il riquadro. */
  --aria-menu: 36px;
  --safe-top: calc(var(--mc) + var(--logo-h) + var(--aria-menu));
}

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

/* IL DOCUMENTO NON SCORRE. È il principio preso da Aemme, e da solo chiude
   un'intera famiglia di guai.
   Su iOS la barra di Safari si ritira soltanto quando a scorrere è la PAGINA:
   con un contenitore interno resta dov'è, e quindi il viewport smette di
   oscillare fra svh e lvh. Da lì in poi `100svh` è davvero l'altezza dello
   schermo, e cadono tutti i rimedi che avevamo messo per inseguirla — la coda
   sul foglio, il footer alto lvh, l'aggancio dell'ultima schermata sul filo
   dello zero, il `resize` che partiva a ogni scorrimento.
   Il trucco è tutto nella propagazione: l'overflow della radice va al viewport,
   ma solo se è `visible`. Mettendolo a `hidden` la propagazione si ferma, e il
   `body` diventa un contenitore di scorrimento vero. */
html {
  height: 100svh;
  overflow: hidden;
  background: var(--green);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  height: 100svh;
  overflow-y: auto;
  margin: 0;
  color: var(--ink);
  font-family: "Poppins", system-ui, sans-serif;
  font-weight: 600;
  /* Al rilascio la pagina si assesta sulla sezione più vicina: ogni sezione è
     una tappa, il dito resta libero. `mandatory` e non `proximity`, perché con
     `proximity` la soglia la decide il browser e sul desktop la pagina smette
     di posarsi. Il prezzo è che il browser deve riposare su un aggancio: per
     questo anche il footer ne ha uno. */
  scroll-snap-type: y mandatory;
  /* niente pull-to-refresh e niente catena verso l'esterno: il rimbalzo resta */
  overscroll-behavior-y: contain;
  /* Il taglio laterale di tutta la pagina, e sta qui perché qui c'è già un
     contenitore di scorrimento: le carte della giostra sbordano di proposito
     oltre i fianchi della finestra, e senza questo la pagina scorrerebbe
     anche di lato. Metterlo sulla giostra costava un rettangolo di ritaglio
     addosso a una scena 3D viva — che è esattamente quello che la faceva
     saltare. */
  overflow-x: hidden;
}

/* Il colore del sito, l'ultimo piano della pila. La foto del footer gli sta
   sopra, il foglio delle quattro schermate sopra ancora: nessuna superficie
   sostituisce il verde, tutte ci si appoggiano. Se una foto tarda, fallisce o
   viene tolta, quello che resta è il verde e non il vuoto. */
.sfondo-base {
  position: fixed;
  inset: 0;
  z-index: -2;
  background: var(--green);
}

/* Il fondale del footer. Sta dietro a tutto (z negativo nella pila della
   pagina) e non si muove: a scoprirlo è il foglio delle quattro schermate, che
   ha un verde opaco e gli scorre sopra. Quindi l'immagine non entra da nessuna
   parte — compare perché smette di esserci qualcosa davanti. */
.sfondo-footer {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: url("img/footer.webp") center / cover no-repeat;
  /* Compare in dissolvenza mentre si lascia la quarta, come il nero della
     terza: l'opacità la scrive main.js, legata allo scorrimento, quindi va e
     torna col dito. Finché non si arriva quaggiù la foto non è dipinta
     affatto, e sopra la base verde non c'è nient'altro. */
  opacity: 0;
  will-change: opacity;
}

/* il velo che la scurisce */
.sfondo-footer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--nero) 70%, transparent);
}

/* Il foglio su cui viaggiano le quattro schermate: è lui a coprire il fondale
   e a scoprirlo scorrendo via. Il verde non sta più sul canvas ma qui, perché
   il canvas non scorre e non scoprirebbe niente.
   `position` e `z-index` fanno di questo elemento un contesto di
   impilamento: serve al velo nero della sez. 3, che è fisso e sta dentro, e
   deve dipingersi SOPRA questo verde e SOTTO il contenuto. Senza il contesto,
   il suo z negativo lo manderebbe dietro al foglio, cioè fuori vista. */
main {
  position: relative;
  z-index: 0;
  background: var(--green);
}

/* Un aggancio anche qui. Senza, con lo snap obbligatorio il footer sarebbe
   irraggiungibile: il browser riporterebbe sempre alla quarta.
   Ed è raggiungibile davvero, al contrario di quanto capitava all'ultima
   sezione prima che il footer esistesse: il footer è alto una schermata
   intera, quindi fra il suo aggancio e la fine del documento c'è tutto il
   margine che serve, anche quando la barra di Safari si ritira. */
.footer {
  scroll-snap-align: start;
  position: relative;
  /* L'ultimo aggancio di una pagina sta a (documento − altezza dell'ultimo
     elemento) e lo scroll massimo a (documento − viewport): il primo è
     raggiungibile solo se l'ultimo elemento è alto almeno quanto il viewport.
     Ora che il viewport non oscilla più, una schermata basta ed è esatta. */
  min-height: 100svh;
  /* Due fasce. Il taglio si misura sullo schermo e non sulla fascia utile,
     come nella quarta: i margini li portano le due aree, ciascuna dal suo
     lato, così la riga cade dove deve e i fondi possono arrivare ai bordi.
     La misura è dichiarata una volta sola: la legge la griglia per sapere dove
     tagliare, e il nastro per sapere quanto scrivere grande. */
  --fascia-nastro: 20svh;

  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* La fascia alta ha quella misura come MINIMO, non come gabbia: sui telefoni
     piccoli le quattro voci incolonnate non ci stanno, e invece di sfondare
     nella fascia del nastro fanno crescere il footer di quel poco. Dove ci
     stanno — cioè quasi ovunque — la riga vale esattamente la misura scritta
     e non succede niente.
     La riga del nastro invece è DICHIARATA e non `1fr`: una frazione si prende
     lo spazio che avanza, e quando sopra non ne avanza più va a zero — il
     nastro veniva ritagliato via e spariva. Così invece tiene la sua fascia
     sempre, e a crescere è il footer. */
  grid-template-rows: minmax(calc(100svh - var(--fascia-nastro)), auto) var(--fascia-nastro);
  color: var(--ink);
}

.footer__alto {
  grid-row: 1;
  padding: var(--safe-top) var(--mx) 0;
  display: grid;
  /* tutto appoggiato in cima: quello che avanza cade in fondo, sopra il nastro */
  align-content: start;
  min-height: 0;
}

/* Sul telefono: logo e contatti a tutta larghezza, orari e pasticceria
   affiancati sulla stessa riga. Sono i due blocchi più stretti — nessuna
   riga supera i 143px — e appaiati risparmiano 139px di altezza, che su uno
   schermo corto è la differenza fra starci e non starci.
   La gronda fra le due colonne è il margine di pagina, come ovunque. */
.footer__colonne {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--m);
  row-gap: 2em;
  align-items: start;
}

/* Sul telefono queste due prendono la riga intera: il marchio in cima (con il
   bottone al suo fianco) e i contatti in fondo. Sta scritto con una classe e
   non con un nth-child perché l'ordine delle colonne è già cambiato una volta,
   e un numero d'ordine punta alla colonna sbagliata al primo spostamento. */
.footer__col--larga {
  grid-column: 1 / -1;
}

.footer__col {
  display: grid;
  gap: .6em;
  align-content: start;
}

/* Sul telefono questa colonna prende la riga intera (vedi nth-child qui
   sopra), quindi marchio e bottone ci stanno in fila, uno per capo: il
   `space-between` li manda ai due margini della pagina senza che nessuno dei
   due debba sapere quanto è largo l'altro. */
.footer__col--marchio {
  grid-auto-flow: column;
  justify-content: space-between;
  align-items: center;
}

/* Stessa misura del marchio in testa: è lo stesso marchio, e adesso che è un
   lockup a due righe una taglia sua voleva dire la riga piccola illeggibile.
   Segue --logo-h, quindi anche la prossima volta cambia da sola. */
.footer__logo {
  display: block;
  height: var(--logo-h);
  width: auto;
}

/* L'etichetta è la stessa scrittura del testo, spenta: a distinguerla non è
   un altro carattere né un altro peso, solo la voce più bassa. */
.footer__etichetta {
  margin: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.2;
  color: color-mix(in srgb, var(--ink) 40%, transparent);
}

.footer__voci {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .7em;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.45;
}

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

.footer__voci a:hover {
  text-decoration: underline;
}

/* La fascia scorrevole. Il ritaglio sta qui e va da bordo a bordo: il testo
   entra e esce dai lati dello schermo, non da quelli di una colonna.
   `clip` e non `hidden`, ed è la stessa ragione della finestra delle
   finestra delle recensioni che stava nella quarta, qui più grave: con
   `hidden` questa fascia diventa un
   contenitore di scorrimento largo quattromila pixel, e il browser ci applica
   l'ancoraggio dello scroll — che su un contenuto in movimento perpetuo vuol
   dire correzioni continue. `clip` ritaglia senza fabbricare uno scroller. */
.footer__basso {
  grid-row: 2;
  padding-block: 24px;
  min-height: 0;
  overflow: clip;
  display: grid;
  align-content: center;
}

/* Il corpo è una misura dichiarata, non più quello che riempie la fascia.
   La ragione è che Firefox questo testo non lo sposta, lo RIDISEGNA a ogni
   fotogramma, e il costo cresce col corpo: oltre una certa misura non sta
   più dentro i sedici millesimi di secondo e il nastro scatta. Safari lo
   compone e non ha questo limite, ma il corpo lo decidiamo una volta per
   tutti e due. Qui il telefono; il desktop lo alza in fondo al foglio. */
.scorre {
  --corpo: 100px;
  --scorsa: 16s;

  position: relative;
  height: 1em;
  font-size: var(--corpo);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
}

/* Le copie non stanno più in fila dentro un unico nastro lungo: sono tre
   elementi sovrapposti, ognuno largo UNA copia, che si rincorrono.
   Due cose ci si guadagnano, e la seconda è quella che conta.
   La prima: il piano da disegnare passa da qualche migliaio di pixel a uno
   schermo scarso, sotto ogni limite di tessitura.
   La seconda: ogni copia si ribalta quando è FUORI dall'inquadratura, a
   sinistra. Prima il ribaltamento cadeva con la G in mezzo allo schermo, e
   qualunque fotogramma perso lì si vedeva. Adesso, qualunque cosa vada
   storta, va storta dove non guarda nessuno.
   Lo stacco fra una copia e l'altra fa parte della copia: se fosse un margine
   fra due, non sarebbero più identiche e la giuntura si vedrebbe passare. */
.scorre__copia {
  position: absolute;
  top: 0;
  left: 0;
  padding-inline-end: .6em;
}

/* La corsa la scrive main.js, con lunghezze in pixel ferme: un'animazione i
   cui fotogrammi contengono una percentuale o una proprietà personalizzata il
   browser non la può mandare sul compositore. */


/* segnaposto: serve solo ad avere qualcosa da scorrere */
.footer p {
  margin: 0;
  max-width: 22em;
  font-size: 20px;
  font-weight: 500;
  line-height: 1.4;
}

/* Il nero della terza sezione. Sta dietro a ogni contenuto (z negativo) e
   sopra il fondo del canvas: scurisce il verde, non le carte. Il cambio è una
   dissolvenza, non una superficie che sale — l'opacità la scrive main.js.
   Sale arrivando alla terza e se ne va arrivando alla quarta, che torna verde:
   il verde non è una superficie nuova, è il fondo di sempre che riaffiora. */
.fondo-nero {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--nero);
  opacity: 0;
  pointer-events: none;
}

/* ---------- sezioni ---------- */

/* Regola d'oro: ogni sezione è alta esattamente lo schermo, mai di più */
.s {
  scroll-snap-align: start;
  height: 100svh;
  padding: var(--safe-top) var(--mx) var(--mb);
  /* 1cqi = 1% della colonna utile (margini esclusi) */
  container-type: inline-size;
}

/* ---------- fascia in alto + hamburger ---------- */

.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--safe-top);
  z-index: 100;
  pointer-events: none;

}

/* Allineato al logo. Due onde morbide (Acquario), tratto spesso la metà
   delle aste del logo (10.134/60/2), stessa fase, distanza tra le onde = un
   tratto. Il disegno è alto 27 su 32, centrato in verticale nel box.
   Le onde sono SINUSOIDI, non catene di parabole: a parità di picco una
   parabola arriva al nodo più ripida e ci gira sopra più stretta — è da lì
   che veniva lo spigolo. Il picco vale 2 unità su 32 (era 2,7). */
.menu {
  --bar: calc(var(--menu-h) * 10.134 / 60 / 2);

  position: absolute;
  top: var(--mc);
  right: var(--mc);
  display: block;
  width: var(--menu-h);
  height: var(--menu-h);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  pointer-events: auto;
  /* niente lampo grigio di iOS al tocco; il focus resta per la tastiera */
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.menu:focus:not(:focus-visible) {
  outline: none;
}

/* area di tocco da 44px */
.menu::before {
  content: "";
  position: absolute;
  inset: calc((44px - var(--menu-h)) / -2);
}

.menu svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.menu path {
  fill: none;
  stroke: currentColor;
  stroke-width: var(--bar);
  stroke-linecap: round;
  /* onde → X: main.js appiattisce le onde, qui le due rette ruotano
     di ±45° e si portano al centro (16,16). Origine = centro di ogni linea */
  transform-box: view-box;
  transition: transform 300ms ease;
}

.menu path:first-child {
  transform-origin: 16px 7.9px;
}

.menu path:last-child {
  transform-origin: 16px 24.1px;
}

.menu[aria-expanded="true"] path:first-child {
  transform: translateY(8.1px) rotate(45deg);
}

.menu[aria-expanded="true"] path:last-child {
  transform: translateY(-8.1px) rotate(-45deg);
}

/* ---------- menu aperto ---------- */

/* Copre tutta la pagina, nero al 90%. Sta sotto la fascia (z 100)
   così le onde restano visibili e chiudono il menu */
.panel {
  /* Metriche di Poppins SemiBold, prese dal file: "Panettoni" è la voce più
     larga e il suo inchiostro misura 4.796em, la spalla sinistra della P vale
     0.069em. Stanno qui e non sulle parole perché il corpo lo usano anche i
     due marchi, che ne prendono una frazione e devono crescere con lui. */
  --ink-width: 4.796;
  --lsb: 0.069em;
  /* Il 90 è quello del claim: la riga più lunga prende nove decimi della
     colonna, non tutta. Un blocco che arriva esatto su tutti e due i margini
     sembra incastrato; lasciandogli un decimo si posa. */
  --voce-menu: calc(90cqi / var(--ink-width));

  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgb(0 0 0 / 0.88);
  opacity: 1;
  /* Il velo va e viene invece di scattare. `allow-discrete` è quello che
     permette di mettere in transizione anche il `display`: senza, alla
     chiusura il pannello sparirebbe al primo fotogramma e la dissolvenza in
     uscita non si vedrebbe mai. `@starting-style` qui sotto dà il punto di
     partenza all'andata, a un elemento che un attimo prima non era disegnato.
     I 300ms sono quelli delle onde che diventano una X: il menu si apre con
     un gesto solo. */
  transition: opacity 300ms ease, display 300ms allow-discrete;
  /* Il pannello è fisso e non scorre: il dito che lo trascina andrebbe a
     cercare il primo contenitore di scorrimento sotto di sé, che è il body, e
     il foglio scorrerebbe dietro al menu aperto. `pinch-zoom` gli toglie le
     trascinate e lascia lo zoom, che è di chi legge. */
  touch-action: pinch-zoom;
  /* Il blocco delle voci si appoggia in fondo a sinistra. `align-content` e
     non `align-items`: a posarsi in fondo è il blocco intero, non ogni riga
     dentro la sua.
     I margini sono quelli delle sezioni: la fascia in alto, che tiene le voci
     lontane dal logo e dalle onde, e il margine di pagina sotto e di lato —
     lo stesso del logo, che ci si appoggia sopra.
     I 40 fra le parole e i due marchi sono l'unica misura scelta a mano qui
     dentro, e sono una richiesta. */
  display: grid;
  align-content: end;
  justify-items: start;
  gap: 40px;
  padding: var(--safe-top) var(--mx) var(--mb);
  /* 100cqi = la colonna, margini esclusi: è la riga su cui si misurano le voci */
  container-type: inline-size;
}

.panel[hidden] {
  display: none;
  opacity: 0;
  /* mentre se ne va è ancora disegnato per 300ms: che non si mangi un tocco */
  pointer-events: none;
}

@starting-style {
  .panel:not([hidden]) {
    opacity: 0;
  }
}

/* Stessa posizione del logo della hero: --mc dall'alto, che è il margine
   della fascia, e --mx dal fianco, che è la colonna. Fuori dal flusso, così
   le voci si appoggiano in fondo allo schermo senza sapere che il marchio
   esiste. */
.panel__logo {
  position: absolute;
  top: var(--mc);
  left: var(--mx);
  display: block;
  -webkit-tap-highlight-color: transparent;
}

.panel__logo img {
  display: block;
  height: var(--logo-h);
  width: auto;
}

/* Il blocco è trattato come il claim della hero, e per le stesse ragioni: si
   misura l'INCHIOSTRO e non l'avanzo, perché quello che si vede è il nero, e
   ad arrivare sui margini dev'essere lui. La spalla sinistra si toglie col
   margine negativo. */
.panel__voci {
  margin: 0;
  margin-inline-start: calc(var(--lsb) * -1);
  padding: 0;
  list-style: none;
  font-size: var(--voce-menu);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  /* il riquadro del blocco è l'inchiostro: dalla cima della A alla linea di
     base della l di Mail. Da lì i 40 sotto sono 40 veri. */
  text-box: trim-both cap alphabetic;
}

/* senza text-box-trim: stesso risultato dalle metriche verticali */
@supports not (text-box: trim-both cap alphabetic) {
  .panel__voci {
    margin-block: -0.149em -0.15em;
  }
}

/* Ogni voce è un blocco suo. Non è un vezzo: da riga inline il browser la
   rimisura quando la tocchi, e siccome il blocco è ancorato in basso quel
   ricalcolo si vede come un saltello della prima riga. */
.panel__voci a {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: color 200ms ease;
  -webkit-tap-highlight-color: transparent;
}

/* I due marchi sono due voci su una riga. La loro altezza è l'occhio del
   carattere (la x di Poppins SemiBold, 0.554em) meno un quinto: 0.443.
   Il perché è ottico e non tipografico — un marchio pieno pesa più di una
   lettera alta uguale, e qui sono due — quindi questo numero è una scelta
   dichiarata, non una regola del carattere. Resta legato al corpo delle voci,
   così cresce e cala con loro. */
.panel__social {
  display: flex;
  gap: 24px;
}

.panel__social a {
  display: block;
  color: inherit;
  transition: color 200ms ease;
  -webkit-tap-highlight-color: transparent;
}

.panel__social svg {
  display: block;
  height: calc(.443 * var(--voce-menu));
  width: auto;
  fill: currentColor;
}

/* senza text-box-trim: stesso risultato dalle metriche di Poppins Medium
   (interlinea 1.15, ascendente 1.05, discendente 0.35, maiuscola 0.697) */
@supports not (text-box: trim-both cap alphabetic) {
  .titolo {
    margin-block: -0.228em -0.225em;
  }
}

/* Il verde della casa, e solo dove c'è un puntatore vero: sul telefono un
   :hover resta appiccicato alla voce toccata. I marchi si tingono con le
   parole, perché il loro disegno è dipinto con `currentColor`. */
@media (hover: hover) {
  .panel__voci a:hover,
  .panel__social a:hover {
    color: var(--green);
  }
}

/* ---------- pagine interne (per ora segnaposto) ---------- */

/* Il telaio che ogni pagina ha comunque: il marchio appoggiato alla fascia in
   alto, come nella hero, e il margine di pagina intorno. Il titolo si posa in
   fondo alla schermata, dove stanno le voci del menu da cui si è arrivati.
   Quando queste pagine avranno un contenuto vero questa regola sparisce: non
   è un impianto, è un punto di atterraggio. */
.pagina {
  /* 1cqi = 1% della colonna utile: lo chiede il claim qui sotto */
  container-type: inline-size;
  min-height: 100svh;
  padding: var(--mc) var(--mx) var(--mb);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

/* PROVVISORIO: la foto di sfondo della pagina Panettoni.
   I due veli non sono decorazione, sono due conti. In alto: su mobile lì c'è
   il CIELO (luminanza 0.830) e il marchio bianco sopra farebbe 1.19:1 —
   invisibile; col nero al 65% scende a 0.29 e sale a 3:1, la soglia per un
   segno grafico. In basso: dove cade il claim la foto è già scura (0.305,
   cioè 2.96:1, giusto sotto il 3:1 che serve al testo grande) e basta un velo
   leggero per portarlo a 4.2:1.
   Sul desktop si vede la fascia centrale della foto, che lì è già scura: il
   velo alto non gli serve ma non gli fa male — le percentuali sono sulla
   SCHERMATA, non sulla fotografia, quindi una regola sola serve le due viste. */
.pagina--foto {
  background:
    linear-gradient(180deg, rgb(0 0 0 / .65) 0%, rgb(0 0 0 / .15) 22%,
                    rgb(0 0 0 / 0) 40%, rgb(0 0 0 / .45) 100%),
    url("img/panettoni.webp") center / cover no-repeat;
}

.pagina__marchio {
  display: block;
  justify-self: start;
  -webkit-tap-highlight-color: transparent;
}

.pagina__marchio img {
  display: block;
  height: var(--logo-h);
  width: auto;
}

.pagina__titolo {
  align-self: end;
  margin: 0;
  /* la scala dei titoli di sezione, in attesa del disegno vero */
  font-size: 40px;
  font-weight: 600;
  line-height: 1;
  text-box: trim-both cap alphabetic;
}

/* Il claim della hero, altre parole. Metriche di Poppins SemiBold prese dal
   file: "Coming" è la riga più larga e il suo inchiostro misura 3.968em, la
   spalla sinistra della C vale 0.035em, e sotto la linea di base dell'ultima
   riga ("Soon") sborda solo l'occhiello della o, 0.009em.
   In altezza: un'interlinea, una maiuscola e quella coda = 1.710. */
.pagina__claim {
  --ink-width: 3.968;
  --lsb: 0.035em;
  --desc: 0.009em;
  --ink-height: 1.710;

  align-self: end;
  margin: 0;
  margin-inline-start: calc(var(--lsb) * -1);
  margin-block-end: var(--desc);
  font-size: calc(90cqi / var(--ink-width));
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  text-box: trim-both cap alphabetic;
}

/* senza text-box-trim: stesso risultato dalle metriche verticali */
@supports not (text-box: trim-both cap alphabetic) {
  .pagina__claim {
    margin-block: -0.149em calc(var(--desc) - 0.15em);
  }
}

.pagina__claim span {
  display: block;
}

@media (min-width: 860px) {
  .pagina__titolo {
    font-size: min(3.4vw, 48px);
  }

  /* come nella hero, ma più basso: l'inchiostro è alto 40svh e il corpo se ne
     ricava. Nella hero sono 60 perché il claim è la prima cosa che si vede e
     riempie la schermata; qui sotto c'è una fotografia da lasciar respirare. */
  .pagina__claim {
    font-size: calc(40svh / var(--ink-height));
  }
}

/* ---------- pagina di testo: cookie e privacy ---------- */

/* Un testo da leggere dall'alto in basso: nessuna tappa su cui posarsi. */
body.testo-lungo {
  scroll-snap-type: none;
}

/* Il marchio sta dove sta in ogni pagina, e il titolo parte dove partono i
   contenuti della home: sotto la fascia alta (--safe-top). */
.legale {
  padding: var(--mc) var(--mx) var(--mb);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
}

/* fuori da una griglia il link sarebbe largo tutta la riga: cliccabile
   solo il marchio */
.legale .pagina__marchio {
  width: fit-content;
}

.legale h1 {
  margin: var(--aria-menu) 0 1em;
  font-size: 24px;
  font-weight: 500;
  line-height: 1.2;
}

.legale h2 {
  margin: 2em 0 0.5em;
  font-size: inherit;
  font-weight: 500;
  line-height: 1.3;
}

.legale p {
  margin: 0 0 1em;
}

/* gli indirizzi dei browser sono lunghissimi e senza spazi: senza questo
   sfondano la colonna sul telefono */
.legale a {
  color: inherit;
  overflow-wrap: anywhere;
}

@media (min-width: 860px) {
  .legale {
    font-size: 20px;
  }

  /* sul desktop il testo si stacca di altri 40 dalla fascia alta */
  .legale h1 {
    margin-top: calc(var(--aria-menu) + 40px);
    font-size: 40px;
  }
}

/* ---------- 1. hero: logo, tartelletta, claim ---------- */

/* Riga 1: logo (dentro la fascia: unica eccezione).
   Riga 2: tartelletta in alto e claim in basso nella STESSA cella,
   se lo schermo è basso si sovrappongono (voluto) invece di allungare
   la sezione */
.hero {
  padding-top: var(--mc);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
}

.logo {
  grid-row: 1;
  display: block;
  height: var(--logo-h);
  width: auto;
  /* Sul margine della pagina, come tutto il resto: --mc lo tiene solo in
     alto, dove il logo e le onde stanno più vicini al bordo di quanto ci
     stiano i contenuti. Di lato seguono la colonna. */
  justify-self: start;
}

/* FERMA sullo schermo (fixed): 80vw, centrata, crosta a 60px sotto il
   logo (margine + logo + 60), sopra il claim.
   Ombra verso il basso a sinistra come la luce della foto.
   Safari ritaglia il filtro sul box dell'elemento: un padding trasparente
   grande quanto l'ombra la contiene e il top lo compensa */
.king {
  --sh-pad: calc(var(--sh-y) + 1.5 * var(--sh-blur));

  position: fixed;
  /* Trasparente al dito e alla rotellina, come ogni altra cosa fissa e
     decorativa qui dentro. Serve perché a scorrere è il body e non il
     documento: un elemento fisso sta fuori dal contenitore che scorre, e la
     rotellina che gli finisce sopra va a cercare un contenitore risalendo
     fino al documento, che è fermo per costruzione. Su WebKit lo scroll
     ripiega sul body da solo e non si vede niente; su Gecko la tartelletta
     diventa un buco largo 80vw in cui la pagina non si muove. */
  pointer-events: none;
  top: calc(var(--mc) + var(--logo-h) + 60px - var(--sh-pad));
  left: 0;
  right: 0;
  margin-inline: auto;
  z-index: 1;
  display: block;
  box-sizing: content-box;
  width: 80vw;
  height: auto;
  padding: var(--sh-pad);
  filter: drop-shadow(var(--sh-x) var(--sh-y) var(--sh-blur) var(--green-shadow));
  /* si riduce con lo scroll (main.js) tenendo fermo l'angolo in alto a
     sinistra della crosta: l'origine salta il padding dell'ombra.
     Ridurre non sgrana, ingrandire sì: disegnata alla misura grande */
  transform-origin: var(--sh-pad) var(--sh-pad);
  will-change: translate, rotate, scale, transform, opacity;
  /* L'entrata: scende dall'alto schiarendosi. --in va da 0 a 1 e lo scrive il
     tempo (main.js), non lo scroll.
     La corsa sta in `transform`, che qui è libera: `translate`, `rotate` e
     `scale` se le prende già il viaggio verso la sez. 2, e sono proprietà
     distinte — si compongono invece di sovrascriversi. A pagina ferma le
     altre tre valgono l'identità, quindi la caduta è pulita. */
  --caduta: 10svh;
  opacity: var(--in, 0);
  transform: translateY(calc((var(--in, 0) - 1) * var(--caduta)));
  /* misura d'arrivo in sez. 2 rispetto a quella a riposo (la legge main.js) */
  --king-end: 0.75; /* 60vw / 80vw */
}

/* Metriche di Poppins SemiBold: "Calories" = 4.125em di inchiostro,
   spalla sinistra di C/G/O = 0.035em, coda della y = 0.262em.
   "Calories" occupa il 90% della colonna, le tre righe toccano il
   margine sinistro, la coda della y si appoggia sul margine basso */
.claim {
  --ink-width: 4.125;
  --lsb: 0.035em;
  --desc: 0.262em;

  grid-row: 2;
  grid-column: 1;
  align-self: end;
  margin: 0;
  margin-inline-start: calc(var(--lsb) * -1);
  margin-block-end: var(--desc);
  font-size: calc(90cqi / var(--ink-width));
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  text-box: trim-both cap alphabetic;

  /* L'entrata: il claim SALE mentre si accende, cioè al contrario della
     tartelletta, che scende. Stessa corsa (--in, che arriva dalla hero) e
     stessa misura della sua caduta, segno opposto: le due cose entrano una
     incontro all'altra.
     Sta in `transform` e non in `translate` per la ragione della tartelletta:
     `translate` se lo prende già lo scroll, e sono proprietà distinte, quindi
     si compongono invece di sovrascriversi. A pagina ferma lo scroll vale
     l'identità e la salita è pulita. */
  --salita: 10svh;

  transform: translateY(calc((1 - var(--in, 0)) * var(--salita)));
  /* main.js: lo scroll lo porta su di 1×, lo script aggiunge il resto
     e lo dissolve mentre esce */
  will-change: transform, translate, opacity;
}

.claim span {
  display: block;
}

/* senza text-box-trim: stesso risultato dalle metriche verticali */
@supports not (text-box: trim-both cap alphabetic) {
  .claim {
    margin-block: -0.149em calc(var(--desc) - 0.15em);
  }
}

/* ---------- 2. atelier: testo ---------- */

/* Il blocco sta in fondo, a tutta larghezza, ed è alto quanto resta tra
   la tartelletta arrivata (angolo a --m, larga 60vw) più 80 di spazio e
   il margine basso. La misura del carattere la trova main.js: la più
   grande con cui il testo riempie il blocco (gli a capo dipendono
   dalla misura, il CSS da solo non può saperlo) */
.about {
  --king-w: 60vw;
  /* arriva ruotata di 90°: l'altezza è la sua larghezza */
  --king-h: var(--king-w);
  --gap: 80px;

  display: grid;
  align-content: end;
}

.about__text {
  height: calc(100svh - var(--mc) - var(--king-h) - var(--gap) - var(--mb));
  margin: 0;
  font-weight: 400;
  /* ascendente (~0.74) + coda di q/p/g (0.27) fanno ~1: sotto 1.1 le righe si toccano */
  line-height: 1.1;
  text-box: trim-both cap alphabetic;
  /* compare mentre entra (opacità da main.js, legata allo scroll) */
  opacity: 0;
  will-change: translate, opacity;
}

/* senza text-box-trim, dalle metriche di Poppins Regular
   (ascender 1.05, descender 0.35, cap 0.698, interlinea 1.1) */
@supports not (text-box: trim-both cap alphabetic) {
  .about__text {
    margin-block: -0.202em -0.2em;
  }
}

/* ---------- 3. la giostra ---------- */

/* Carosello cilindrico guardato da DENTRO: le carte sono spinte indietro di
   un raggio (translateZ negativo), così l'arco si incava verso di noi invece
   di gonfiarsi, e la metà vicina del cilindro dà le spalle
   (backface-visibility). A girare è il cilindro intero, non le carte una per
   una. Componente riusabile, documentato in
   ~/Documents/Lavoro/Design/2026/gebelia-outreach/GIOSTRA.md: nessuna delle
   misure qui sotto è scelta a occhio, discendono tutte dal raggio.
   Per ora niente titolo e niente foto: tre tinte piatte. */

/* La colonna va dichiarata quanto le righe: una traccia `auto` si dimensiona
   sul contenuto, e allora si prende più della cella e sfonda la schermata.
   Riga 1: il titolo. Riga 2: la giostra, che si prende tutto il resto.
   L'altezza della riga del titolo è dichiarata e non `auto`, perché la deve
   sapere anche la giostra: è quella che le toglie dalla fascia, e da lì
   dipende il tetto sul raggio. Una traccia `auto` la saprebbe solo il
   browser, a conti già fatti. */
.giostra-sez {
  /* Sul telefono il titolo è fisso a 40px su DUE righe, uguale su ogni
     apparecchio: la frase si spezza `Mai provato i / nostri dolci?` e la riga
     più larga misura 6,442 em — misurata sul file. */
  --titolo: 40px;
  /* L'inchiostro del titolo, in em, per quante righe fa: n−1 interlinee più
     una maiuscola. Due righe = 1.15 + 0.697. È la misura VERA, quella che si
     vede: il riquadro del testo invece ne conterrebbe 0.228 di vuoto sopra la
     maiuscola e 0.225 sotto la linea di base, e sono quelli che facevano
     sembrare il bottone lontano. Li taglia `text-box` qui sotto. */
  --titolo-ink: 1.847;
  /* L'aria fra il titolo e il bottone. Ha un nome suo e non è più --mc: non è
     un margine di pagina ma il respiro fra due elementi interni, e adesso che
     in mezzo c'è il bottone vale 40 su tutte e due le viste. Sul desktop il
     numero non cambia — lì --mc era già 40 — quindi una dichiarazione sola
     basta per entrambe.
     Sono 40 VERI: il riquadro del titolo finisce sulla linea di base
     (text-box) e il bottone è tutto inchiostro. */
  --titolo-aria: 40px;
  --titolo-h: calc(var(--titolo) * var(--titolo-ink) + var(--titolo-aria));
  /* Il bottone sotto il titolo: 17 di corpo × 1.2 di interlinea + 14 e 14 di
     imbottitura. Sta scritto qui perché la giostra deve poterselo togliere
     dalla fascia: è la stessa ragione per cui --titolo-h è dichiarata. */
  --bottone-h: calc(17px * 1.2 + 28px);
  /* Di quanto la giostra risale sotto il bottone. È uno stacco NEGATIVO: la
     corona cresce verso l'alto dal suo filo di base, e in cima ha aria per
     costruzione — toglierne fa avvicinare il disegno al bottone e insieme lo
     fa crescere, perché quei pixel tornano nella fascia da cui si ricava il
     raggio. Va in due posti, e devono restare d'accordo: il margine che tira
     su l'elemento e la fascia che detta il raggio. */
  --avvicina: 40px;

  /* Lo stacco fra il titolo e lo spigolo alto del disegno: dichiarato, non
     avanzato da due centrature indipendenti come prima.
     Sotto l'inchiostro del titolo, dentro la sua riga, resta già metà del
     respiro della riga meno la coda della p — che sborda di 0,037 em sotto la
     riga di testo (interlinea 1,15 contro 1,187 em di inchiostro, misurati sul
     file). Quel pezzo è gratis: alla fascia della giostra si chiede solo il
     resto, e glielo si toglie dal tetto.
     Morde solo dove il tetto morde, cioè su desktop e sulle finestre basse:
     sul telefono la carta è ferma sulla larghezza e la fascia le avanza. */
  --stacco: 20px;
  /* la coda vale per il desktop, dove l'ultima riga è quella con la p di
     "provato"; sul telefono l'ultima è "nostri dolci?", che non scende sotto
     la linea di base — ma lì il tetto non morde e il conto non serve */
  /* Era la coda della p del titolo, che sbordava sotto la sua riga e regalava
     spazio allo stacco. Adesso sopra la giostra non c'è più il titolo ma il
     BOTTONE, il cui riquadro è tutto inchiostro: non regala niente, e il conto
     riparte da zero. */
  --sotto-testo: 0px;
  --respiro: calc(2 * (var(--stacco) - var(--sotto-testo)));

  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: var(--titolo-h) var(--bottone-h) minmax(0, 1fr);
}

/* Sotto il titolo, in mezzo, appoggiato in cima alla sua riga: l'aria sopra
   gliela dà già il titolo (--titolo-aria, dentro --titolo-h). */
.giostra-sez > .bottone {
  grid-row: 2;
  grid-column: 1;
  justify-self: center;
  align-self: start;
  /* Sopra la giostra, e non per estetica: --avvicina tira su la scatola di
     .giostra-fuori fin dentro questa riga, e quella scatola — vuota lassù, le
     carte stanno molto più in basso — verrebbe comunque prima nel disegno
     perché viene dopo nel markup. Si prendeva il puntatore, e il bottone
     sembrava spento. */
  z-index: 1;
}

/* Il bottone della terza schermata: nero come il fondo su cui sta, e un
   anello verde che gli gira intorno con un punto luce che ci passa sopra.
   I verdi discendono tutti da --green: il chiaro e la luce sono lo stesso
   colore schiarito, non tre verdi scelti a mano. */
/* Due classi nel selettore e non una: questa regola sta PRIMA di `.bottone`
   nel foglio (la terza schermata viene prima della quarta), e a parità di
   peso vincerebbe quella scritta dopo — cioè il bianco. Scritta così è una
   variante vera e non dipende dall'ordine. */
.bottone.bottone--anello {
  --luce: color-mix(in oklab, var(--green), white 80%);
  --spessore: 2px;

  position: relative;
  background: var(--nero);
  color: var(--green);
  transition: background-color 200ms ease, color 200ms ease;
}

/* Solo dove c'è un puntatore vero: sul telefono un :hover resta appiccicato.
   Il bottone si riempie del verde di casa e la scritta passa al bianco —
   gli stessi due colori che aveva prima, scambiati di posto. */
@media (hover: hover) {
  .bottone.bottone--anello:hover {
    background: var(--green);
    color: var(--ink);
  }
}

/* L'ANELLO, verde pieno. Resta un riquadro col centro tolto da una maschera
   invece di diventare un `border` vero per una ragione di conti: un bordo
   aggiungerebbe 4px all'altezza del bottone, e quell'altezza è dichiarata in
   --bottone-h perché la giostra ci ricava il suo raggio. Così invece l'anello
   sta dentro il riquadro e non sposta niente.
   Due strati identici, uno grande quanto il contenuto e uno quanto tutto il
   riquadro, e si tiene solo quello che NON sta in tutti e due: resta la
   cornice, spessa quanto il padding.
   La maschera fa anche da forbice: quello che sborda dal riquadro non si
   dipinge, e per questo il punto luce qui sotto non ha bisogno di nessun
   `overflow` — che fabbricherebbe uno scroller per niente. */
.bottone--anello::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: var(--spessore);
  /* Due punti soli, da sinistra a destra: a destra il verde di casa, a
     sinistra lo stesso verde scurito. Non è un verde nuovo — è --green-shadow,
     quello che già fa l'ombra della tartelletta. */
  background: linear-gradient(90deg, var(--green-shadow), var(--green));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  pointer-events: none;
}

/* IL PUNTO LUCE. Stessa cornice dell'anello (stessa maschera), e dentro una
   macchia chiara che la attraversa. A muoversi è un `transform`, non lo sfondo:
   una traslazione se la porta via il compositore e non ridipinge niente —
   e qui accanto sta girando una scena in 3D, che di ridisegni non ne vuole.
   Vedi [[lampi-e-saltelli-sono-scatole]]. */
.bottone__luce {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: var(--spessore);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  pointer-events: none;
}

.bottone__luce::before {
  content: "";
  position: absolute;
  /* più alta del bottone: così accende anche i fianchi dell'anello, non solo
     il filo sopra e quello sotto */
  top: -50%;
  bottom: -50%;
  left: 0;
  width: 40%;
  background: radial-gradient(closest-side, var(--luce), transparent);
  /* passa, poi aspetta: il movimento sta nella prima metà del giro e nella
     seconda la macchia è ferma fuori dal riquadro, invisibile */
  animation: passa-luce 3.4s ease-in-out infinite;
}

@keyframes passa-luce {
  0% {
    transform: translateX(-140%);
  }
  55%,
  100% {
    transform: translateX(320%);
  }
}


/* Poppins Medium — un peso più leggero del claim della prima schermata, che è
   SemiBold. Il verde è quello del fondo delle prime due sezioni: qui sotto è
   già nero, e la frase si porta dietro il colore da cui si arriva. */
.titolo {
  grid-row: 1;
  grid-column: 1;
  /* Il titolo si appoggia in CIMA alla sua riga, e l'aria della riga (--mc,
     dentro --titolo-h) si raccoglie tutta sotto di lui.
     Prima stava in fondo, e serviva a farlo scendere verso la giostra che
     introduce; adesso fra i due c'è il bottone, e quell'aria messa sopra
     staccava il titolo dalla fascia e lo incollava al bottone. Messa sotto fa
     le due cose giuste insieme: il titolo attacca la fascia di sicurezza e
     respira prima del bottone. */
  align-self: start;
  margin: 0;
  text-align: center;
  font-size: var(--titolo);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -.01em;
  text-wrap: balance;
  color: var(--ink);
  /* Il riquadro del titolo è il suo inchiostro, dalla cima della maiuscola
     alla linea di base — come il claim e come il testo della seconda
     schermata. Senza, la scatola si porta dietro mezza interlinea vuota sopra
     e sotto (0.228 e 0.225em), e l'aria dichiarata non è quella che si vede. */
  text-box: trim-both cap alphabetic;

  /* La colonna del titolo è larga quanto la sua riga più larga: così la
     spezzatura cade dove deve per costruzione, non per gentilezza del
     browser. A corpo fisso serve davvero — sopra i 427px di finestra la
     colonna piena starebbe larga 9,5 em, e un a capo ingordo (Safari senza
     text-wrap:balance) ci infilerebbe "Mai provato i nostri" lasciando
     "dolci?" da solo. */
  max-width: calc(var(--titolo) * 6.45);
  margin-inline: auto;
}

.titolo span {
  color: var(--green);
}

/* Sopra gli 860 la frase torna su una riga sola: la colonna è larga e due
   righe la lascerebbero a metà. */
@media (min-width: 860px) {
  .giostra-sez {
    --titolo: min(3.4vw, 48px);
    /* una riga sola: solo la maiuscola */
    --titolo-ink: .697;
  }

  /* su una riga sola la colonna torna intera; l'appoggio in cima vale qui
     come sul telefono, e lo eredita dalla regola di sopra */
  .titolo {
    max-width: none;
  }
}

/* Due `min` a zero per la stessa ragione sui due assi: la giostra è più larga
   della sua cella (le carte devono sbordare) e il minimo automatico di un
   elemento di griglia la rimetterebbe dentro allargando la cella.
   Il margine negativo la riporta ai bordi della finestra.
   Qui NON c'è nessun ritaglio, ed è una scelta pagata: `overflow-x: clip` con
   `overflow-y: visible` è, sulla carta, un taglio su un asse solo — ma il
   browser stabilisce comunque un rettangolo, e in verticale tagliava le carte
   più vicine. Peggio: ogni volta che una carta cresceva abbastanza da
   sfondarne il bordo alto, il piano di disegno della scena 3D cambiava
   confini e si riagganciava alla griglia dei pixel. Era il saltello.
   Lo sbordo laterale lo ferma il `body`, che è il contenitore di scorrimento
   e taglia una volta sola per tutta la pagina. */
.giostra-fuori {
  grid-row: 3;
  /* risale nella riga del bottone: il bordo di sotto resta dov'è, quello di
     sopra sale, e la scatola cresce di --avvicina */
  margin-top: calc(var(--avvicina) * -1);
  grid-column: 1;
  position: relative;
  min-height: 0;
  min-width: 0;
  margin-inline: calc(var(--mx) * -1);
  /* La sfumatura ai fianchi sta nel blocco desktop: sul telefono non serve,
     perché lì in inquadratura c'è una carta sola più una scheggia da 8px, e a
     tagliare basta il bordo dello schermo.
     Qui invece sta l'USCITA (main.js): la giostra risale a 2× mentre arriva la
     quarta, e si dissolve. L'entrata sta su .giostra-centro — due elementi per
     due momenti, così le trasformazioni non si sovrappongono. E dove la
     maschera c'è, viaggia con l'elemento: la sfumatura resta incollata ai
     fianchi delle carte anche mentre se ne vanno.
     Niente `will-change` qui dentro: promuovere a piano fisso un antenato di
     una scena 3D viva significa farla ridisegnare in quel piano, e ogni tanto
     la si vede saltare. Un `transform` animato il browser lo promuove da sé,
     quando serve e per il tempo che serve. */
}

/* Il centro è geometria, non allineamento: un elemento che sborda, se lo si
   allinea al centro, il browser lo riporta all'inizio — non nasconde niente
   oltre il bordo da cui si comincia a leggere.
   E lo spostamento sta SOPRA la scena, non dentro: la prospettiva ha il punto
   di fuga nel centro dell'elemento che la dichiara, e muovendo solo le carte
   il punto di fuga resterebbe indietro storcendo l'arco.

   Qui sta anche l'entrata: sale dal basso schiarendosi. --e va da 0 a 1 e lo
   scrive il TEMPO (main.js), non lo scroll, e parte quando la schermata si
   posa — un'entrata legata al dito non si vedrebbe, perché la giostra sta
   entrando proprio per via di quello scroll.
   Il centraggio è scritto in `translate` e l'entrata in `transform`: sono due
   proprietà diverse, quindi si compongono invece di sovrascriversi. È il
   motivo per cui il centro non poteva essere un allineamento.
   La corsa è un decimo di schermata: sopra la scena e non dentro, altrimenti
   si muoverebbero le carte lasciando fermo il punto di fuga. */
.giostra-centro {
  --entrata: 10svh;

  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  opacity: var(--e, 0);
  transform: translateY(calc((1 - var(--e, 0)) * var(--entrata)));
}

/* La LARGHEZZA della carta è la corda dell'arco, 2·R·tan(passo/2): a corda
   piena le carte si toccano esatte, --aria è la frazione lasciata libera.
   Il passo è 360° diviso il numero delle carte: l'anello è pieno, fa il giro
   intero, e non ci sono poste vuote da nascondere. Con quattordici carte sono
   25,714°, e a quel passo la fila esce dalla finestra invece di fermarsi a
   metà strada — le sette immagini stanno due volte ciascuna, a mezzo giro di
   distanza, e non possono mai vedersi insieme.
   Il raggio non si sceglie: si ricava dalla carta che si vuole vedere. Si
   dichiara quanto dev'essere larga a video la carta di fronte e la si riporta
   indietro dividendo per la proiezione — così il numero scritto nel codice è
   quello che si misura sullo schermo. */
.giostra-scena {
  --passo: 25.714deg;
  --aria: .93;
  /* Quanto sta lontano l'occhio, in raggi. È questo numero a decidere il peso
     della carta di fronte, ma è anche l'unica prova che la carta STA GIRANDO:
     lo spigolo vicino più alto di quello lontano. Senza quella prova lo
     schiacciamento di una carta di fianco non si legge come una rotazione ma
     come una foto stirata, ed è quello che succedeva a 8,3 raggi: 104% di
     spanciamento sulla seconda posta contro il 142% di Bending Spoons.
     A 1,7 lo spanciamento torna al 115%. Il conto lo paga la vicina, che
     svetta dell'8% sulla centrale — quando il passo era di 50° pagava il 34%,
     ed era troppo: è il passo fitto ad aver ricomprato la profondità.
     La scena resta in scala su ogni schermo perché la distanza è legata al
     raggio invece che a un numero fisso. */
  --profondita: 1.7;
  /* raggi per ogni unità di carta a video:
     (profondità + 1)/profondità diviso la corda (2 tan25° · aria) */
  --inversa: 3.7412;
  /* la scala a video dello spigolo più vicino di una carta laterale, cioè il
     punto più alto del disegno:
     profondità / (profondità + cos(p·passo) − tan(passo/2)·aria·sin(p·passo)),
     presa sulla SECONDA posta, a 51°. Con la prospettiva profonda le carte si
     allontanano fra loro a video — la vicina arriva già al bordo — e dalla
     terza in poi sono fuori inquadratura: tenerle nel conto rimpicciolirebbe
     la carta di un terzo per una cosa che nessuno vede. Quando su uno schermo
     molto largo la terza si affaccia, sta comunque dentro la sfumatura.
     La carta di fronte, che è il punto più basso, sta a 0,6296 */
  --proiezione-max: .7879;

  --riga: calc(100svh - var(--safe-top) - var(--mb) - var(--titolo-h)
               - var(--bottone-h) + var(--avvicina));
  /* La carta di fronte, misurata a video. Non una frazione fissa di vw: su un
     telefono un terzo di schermo sarebbe un francobollo. È la retta che passa
     per i due casi che contano — un terzo di schermo a finestra larga, sette
     decimi sul telefono. */
  --larghezza: max(calc(20.2vw + 194px), 25vh);
  /* Il tetto non è più una frazione della fascia: è la fascia meno il respiro
     che lo stacco richiede, riportato indietro in raggi.
     2,3915 = 1 / (proiezione-max · corda · 1,25), cioè l'ingombro per raggio. */
  --raggio: min(calc(var(--larghezza) * var(--inversa)),
                calc((var(--riga) - var(--respiro)) * 2.3915));
  --carta-w: calc(var(--raggio) * .45648 * var(--aria)); /* .45648 = 2 tan(12.857deg) */
  --carta-h: calc(var(--carta-w) * 1.25);                /* 4:5, come le foto */
  /* quello che si vede, dalla linea di base allo spigolo più alto */
  --ingombro: calc(var(--carta-h) * var(--proiezione-max));

  perspective: calc(var(--raggio) * var(--profondita));
  /* Il punto di fuga sul FONDO della scatola, invece che al suo centro.
     Le carte ruotano attorno a Y, e una rotazione attorno a Y non tocca la
     quota dei punti: chi si trova esattamente all'altezza del punto di fuga
     proietta su sé stesso comunque sia profondo. Il bordo inferiore di tutte
     le carte cade quindi su UNA riga dritta — non per approssimazione, per
     costruzione — e la profondità esce tutta dal lato di sopra.
     Il disegno che ne viene: base rettilinea, cima che si alza verso i
     fianchi, dove il cilindro si fa vicino. */
  perspective-origin: 50% 100%;
  /* Sotto la linea di base la scatola sporge ancora (la carta di fronte è
     rimpicciolita, la scatola no). Si alza di metà di quello che sporge,
     così a stare in mezzo alla fascia è il disegno e non il contenitore. */
  translate: 0 calc((var(--ingombro) - var(--carta-h)) / 2);
}

.giostra {
  position: relative;
  width: var(--carta-w);
  height: var(--carta-h);
  transform-style: preserve-3d;
  /* Gira da solo, un giro intero a passo costante: è il moto di Bending
     Spoons. Un giro e non un andirivieni, così non c'è nessun punto in cui
     si ferma o torna indietro. */
  --giro: 60s;
  animation: gira var(--giro) linear infinite;
}

@keyframes gira {
  to { transform: rotateY(360deg); }
}

.carta {
  position: absolute;
  inset: 0;
  margin: 0;
  /* `clip` e non `hidden`: con `hidden` ognuna delle carte diventa un
     contenitore di scorrimento, e sono quattordici, dentro una scena che
     ruota. I rettangoli trasformati cadono su misure frazionarie: basta mezzo
     pixel di sbordo perché il browser ci metta mano per conto suo, ed è da lì
     che possono venire i saltelli. `clip` ritaglia e non fabbrica niente. */
  overflow: clip;
  border-radius: calc(var(--carta-w) * .035);
  /* Un fondo sotto la foto: una carta la cui immagine non è ancora arrivata
     deve essere una carta scura, non un buco trasparente. */
  background: color-mix(in oklab, var(--nero), var(--ink) 8%);
  /* la casa sull'anello la scrive main.js una volta sola e non cambia più:
     qui resta il solo arretramento, che vale per tutte */
  transform: translateZ(calc(var(--raggio) * -1));
  backface-visibility: hidden;
}

/* Le foto sono 1080x1350, cioè 4:5 come la carta: `cover` non ha niente da
   tagliare, sta lì per i ritagli futuri. */
.carta img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--fuoco, center);
}

/* Le laterali si allontanano annegando nel nero del fondo. Il velo non lo
   pilota più un conto a ogni scatto: l'anello gira a velocità costante, quindi
   la distanza dal fronte è una funzione nota del tempo. Ogni carta corre la
   stessa animazione sfasata della sua fetta di giro (--fase, scritta da
   main.js): a fase zero è di fronte e il velo è spento, a mezzo giro è dietro
   e il velo è pieno. */
.carta::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--nero);
  opacity: 0;
  animation: velo var(--giro) linear infinite;
  animation-delay: var(--fase, 0s);
}

@keyframes velo {
  0%, 100% { opacity: 0; }
  50% { opacity: .72; }
}

/* La soglia è il formato, non una larghezza: il problema che si risolve qui è
   verticale. La retta non serve più: non c'è nessun caso largo da raggiungere, e
   la carta si può dire per quello che è — sette decimi e mezzo dello
   schermo, netti. */
@media (max-aspect-ratio: 1/1) {
  .giostra-scena {
    --larghezza: 78vw;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* le dissolvenze restano, i movimenti no */
  .king {
    transform: none;
  }

  /* l'anello resta, il punto luce no */
  .bottone__luce {
    display: none;
  }

  .giostra,
  .carta::after {
    animation: none;
  }

  /* le dissolvenze restano, i movimenti no */
  .giostra-centro,
  .chiamata {
    transform: none;
  }

  .scorre {
    animation: none;
  }

  
}

/* ---------- 4. la foto ---------- */

/* La schermata è una fotografia sola: Riccardo col panettone, camice bianco,
   muro salvia. Quel muro è un verde a un soffio da --green — la schermata
   cambia materia senza cambiare colore, e la foto non ha bisogno di essere
   annunciata da niente.
   DUE TAGLI, non uno ridimensionato: il verticale (1600×2400) per il telefono,
   con Riccardo al centro; il quadrato (2000×2000) per il desktop, dove sta a
   destra e lascia il muro libero a sinistra — che è dove verrà l'About.
   Sono due `background-image` in due regole diverse, e non un `srcset`: il
   browser scarica soltanto quella della regola che vale, quindi il telefono
   non si porta a casa la foto del desktop. 168 KB contro 228.
   Qui sopra verrà l'About: la griglia resta pronta, la schermata per ora è
   solo la foto. Le recensioni che stavano qui sono uscite dal sito e vivono
   in componenti/recensioni.html. */
.s4 {
  /* Il VELO, e qui serve più forte che sul desktop: nella metà alta della foto
     verticale il muro sta a 0.566 di luminanza e il bianco sopra fa 1.70:1.
     Il testo qui viene sui 22px, cioè sotto i 24 che contano come "grande":
     la soglia è 4.5:1 e non 3, e ci si arriva col nero al 70%. Si spegne al
     68% dell'altezza, appena sotto la riga del testo, così la faccia di
     Riccardo resta nella sua luce. */
  background:
    linear-gradient(180deg, rgb(0 0 0 / .72) 0%, rgb(0 0 0 / .68) 45%,
                    rgb(0 0 0 / 0) 68%),
    url("img/ricky-mobile.webp") center / cover no-repeat;
  /* Due righe uguali: sopra il racconto, sotto la fotografia libera. Il
     padding torna quello delle altre schermate — la fascia in alto e il
     margine in basso — perché adesso qui dentro c'è del testo, e il 50/50 si
     misura su quello che resta. */
  padding-block: var(--safe-top) var(--mb);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: repeat(2, minmax(0, 1fr));
}

/* Il racconto riempie l'area utile: il corpo non è scritto, lo cerca
   main.js — la misura più grande con cui il testo ci sta in larghezza e in
   altezza. Il riquadro è l'inchiostro (text-box), così "riempire" vuol dire
   dalla cima della A all'ultima linea di base e non fino a un'interlinea
   vuota.
   La comparsa è quella del claim: sale mentre si accende. --e lo scrive il
   tempo quando la schermata si posa (main.js). */
.racconto {
  --entrata: 10svh;

  display: block;
  grid-row: 1;
  grid-column: 1;
  margin: 0;
  font-weight: 400;
  line-height: 1.35;
  color: var(--ink);
  text-box: trim-both cap alphabetic;
  opacity: var(--e, 0);
  transform: translateY(calc((1 - var(--e, 0)) * var(--entrata)));
  will-change: transform, opacity;
}

/* senza text-box-trim, dalle metriche di Poppins Regular
   (interlinea 1.35, ascendente 1.05, discendente 0.35, maiuscola 0.698) */
@supports not (text-box: trim-both cap alphabetic) {
  .racconto {
    margin-block: -0.327em -0.325em;
  }
}

.chiamata {
  /* La comparsa, la stessa della giostra: sale dal basso schiarendosi quando
     la sua schermata si posa. --e va da 0 a 1 e lo scrive il tempo. */
  --entrata: 10svh;

  display: grid;
  justify-items: start;
  align-content: start;
  min-height: 0;
  text-align: left;
  opacity: var(--e, 0);
  transform: translateY(calc((1 - var(--e, 0)) * var(--entrata)));
}


.bottone {
  font: inherit;
  font-size: 17px;
  font-weight: 500;
  /* Dichiarata e non lasciata a `normal`: l'altezza del bottone entra nel
     conto della giostra (vedi --bottone-h), e un conto non può dipendere da
     quello che il browser decide per sé. 17 × 1.2 + 14 + 14 = 48.4px. */
  line-height: 1.2;
  padding: 14px 26px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--green);
  /* l'etichetta sta in maiuscolo nel foglio e non nel testo: così quello che
     si legge nel markup resta una parola, non un acronimo da sillabare */
  text-transform: uppercase;
  /* adesso è un link: niente sottolineatura, e inline-block perché il
     padding verticale conti anche fuori da una griglia */
  display: inline-block;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.bottone:focus:not(:focus-visible) {
  outline: none;
}

/* ---------- desktop ---------- */

@media (min-width: 860px) {
  :root {
    --logo-h: 60px;
    --menu-h: 40px;
    --m: 80px;
    --mc: 40px;
    --aria-menu: 20px;
  }

  /* Sul desktop la colonna è larga il doppio e riempirla vorrebbe dire voci
     alte 150px: qui il menu torna alla scala dei titoli di sezione, e allora
     torna anche il margine di pagina — un corpo che non tocca più i bordi
     appoggiato al bordo sembra caduto lì. */
  /* Qui il corpo non nasce dalla larghezza ma dall'altezza, come il claim
     della hero: le tre parole sono alte 40svh in tutto, dalla cima della A
     alla linea di base della l di Mail — due interlinee più una maiuscola.
     Il secondo termine è il freno: su una finestra alta e stretta (un monitor
     girato, un iPad in piedi) quell'altezza chiederebbe un corpo che in
     larghezza non ci sta, e allora torna a comandare la colonna. */
  .panel {
    /* Due righe di parole, non più tre: un'interlinea più una maiuscola.
       E il bersaglio scende da 40svh a 27.4 — 27.4/1.851 fa lo stesso
       14.8svh di corpo di prima, che è il punto: a togliere una voce il
       blocco si accorcia, le lettere no. Due parole a 40svh sarebbero
       diventate enormi. */
    --ink-height: 1.851;
    --voce-menu: min(27.4svh / var(--ink-height), 90cqi / var(--ink-width));
  }

  /* la tartelletta a riposo: alta 60svh, centrata in verticale e al
     centro della colonna destra (metà destra dell'area utile: dal centro
     pagina al margine destro). Il padding dell'ombra si compensa */
  .king {
    --king-rest-h: 60svh;
    --king-rest-w: calc(var(--king-rest-h) * 1293 / 1279);
    --col-center: calc(75vw - var(--mx) / 2);

    top: calc((100svh - var(--king-rest-h)) / 2 - var(--sh-pad));
    left: calc(var(--col-center) - var(--king-rest-w) / 2 - var(--sh-pad));
    right: auto;
    margin-inline: 0;
    width: var(--king-rest-w);
    height: var(--king-rest-h);
    /* in sez. 2 arriva a 40svh */
    --king-end: 0.6667; /* 40svh / 60svh */
  }

  /* il claim è alto 60svh dall'alto delle maiuscole alla coda della y:
     due interlinee + maiuscola (0.701em) + coda (0.262em) = 2.963em */
  .claim {
    --ink-height: 2.963;

    font-size: calc(60svh / var(--ink-height));
  }

  /* sez. 2: arriva ridotta a 40svh e ruotata di 90°: l'altezza è la
     larghezza ridotta */
  .about {
    --king-h: calc(40svh * 1293 / 1279);
  }

  /* --- 4: due colonne invece di due fasce --- */
  /* Sparita la riga orizzontale del 70/30, il padding verticale torna dove
     sta per tutte le altre sezioni — sulla sezione — e le due aree se lo
     tolgono. La gronda fra le colonne è il margine di pagina: fra due
     contenuti vale quanto fra un contenuto e il bordo. */
  /* Due colonne uguali: a sinistra il racconto, a destra Riccardo — che nel
     taglio quadrato sta appunto a destra.
     Il VELO non è un vezzo: quel muro ha luminanza 0.737 e il bianco sopra ci
     fa 1.33:1, cioè illeggibile. Con il nero al 62% scende a 0.28 e il
     contrasto sale a ~3:1, che è la soglia per il testo grande — e questo lo
     è, il corpo lo cerca il codice e arriva sui 37px. Il velo si spegne prima
     della metà, così Riccardo resta nella sua luce.
     Sta come STRATO del fondo e non come elemento: una superficie in meno da
     impilare, e viaggia con la foto. */
  .s4 {
    background-image:
      linear-gradient(90deg, rgb(0 0 0 / .62) 0%, rgb(0 0 0 / .58) 42%,
                      rgb(0 0 0 / 0) 72%),
      url("img/ricky-desktop.webp");
    padding-block: var(--safe-top) var(--mb);
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* qui le due metà sono di lato, non sopra e sotto: una riga sola */
    grid-template-rows: minmax(0, 1fr);
    column-gap: var(--m);
  }

  /* Il blocco della chiamata sul desktop è ancora da rifare: adesso vive nel
     footer e le regole che stavano qui descrivevano la quarta schermata a due
     colonne, che non esiste più. */

  

  

  

  /* la fascia scorrevole si prende il doppio */
  .footer {
    --fascia-nastro: 40svh;
  }

  /* il corpo del nastro non la segue più: è dichiarato, e qui vale 180 */
  .scorre {
    --corpo: 180px;
  }

  /* Quattro colonne uguali, con in mezzo la gronda della pagina: fra due
     contenuti vale quanto fra un contenuto e il bordo, come nella quarta.
     Le colonne si appoggiano tutte in alto: hanno contenuti di altezza
     diversa e allinearle in mezzo le farebbe ballare l'una rispetto
     all'altra. */
  /* Sul desktop le quattro colonne tornano al centro della loro area: lì lo
     spazio avanza parecchio, e appoggiate in cima resterebbero sospese sopra
     un vuoto. Sul telefono invece stanno in cima, perché lo spazio è appena
     quello che serve. */
  .footer__alto {
    align-content: center;
  }

  .footer__colonne {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: var(--m);
    row-gap: 0;
  }

  /* qui le colonne sono quattro davvero: nessuno si prende la riga intera */
  .footer__col--larga {
    grid-column: auto;
  }

  /* e il bottone torna sotto il marchio, nella sua stessa colonna, a sinistra */
  .footer__col--marchio {
    grid-auto-flow: row;
    justify-items: start;
    align-items: start;
    gap: 40px;
  }

  /* I fianchi della giostra si sfumano invece di essere tagliati netti: la
     maschera toglie opacità alle carte, quindi funziona su qualunque fondo —
     e il fondo lì cambia colore mentre si arriva. Un decimo di finestra per
     lato basta a bere la seconda carta, che entra al 95% della semifinestra.
     Serve solo qui: sul telefono di carte in inquadratura ce n'è una sola, e
     quello che sborda lo taglia lo schermo.

     La maschera sta sulla SCHERMATA e non sulla fascia della giostra, e non è
     un dettaglio: una maschera non vela soltanto, RITAGLIA — la sua area vale
     `border-box` e non si può spostare, perché `mask-clip: no-clip` Safari non
     lo conosce. Sulla fascia, le carte più vicine che su finestra larga
     crescono oltre la loro riga venivano tagliate in alto. Sulla schermata ci
     stanno dentro comunque.
     Il gradiente è orizzontale e uniforme in verticale, quindi lavora
     identico; e il titolo, che è centrato e stretto, resta lontano dai due
     decimi sfumati. */
  .giostra-sez {
    --sfumatura: 10%;
    /* sul desktop la giostra risale la metà: lì il raggio è già limitato
       dall'altezza, e ogni pixel che le si dà si vede diventare carta */
    --avvicina: 20px;

    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--sfumatura),
                        #000 calc(100% - var(--sfumatura)), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 var(--sfumatura),
                        #000 calc(100% - var(--sfumatura)), transparent 100%);
  }
}
