/* ==========================================================================
   Stili della landing — Vinci una Casa
   Trasposizione del file Figma "Landing page Concorso 2027".
   Dipende da variables.css (token) e reset.css: vanno caricati PRIMA.
   Approccio mobile first: le media query aggiungono, non correggono.

   Indice
     1. Base
     2. Utility e layout
     3. Componenti (badge, bottoni)
     4. Hero
    4b. Comparsa allo scroll
     5. Il premio
     6. Come partecipare
     7. Regolamento
     8. Invito finale
     9. Footer
    10. Media query
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Base
   -------------------------------------------------------------------------- */

/* Niente scorrimento laterale. Non serve a rimediare a un impaginato che
   sborda — non ce ne sono — ma alle animazioni di ingresso: le due
   destinazioni entrano da destra e da sinistra, e restano ferme al proprio
   punto di partenza, fuori dallo schermo, finche non le si raggiunge
   scorrendo. Su schermo stretto quella a destra sta 38px oltre il bordo, ed
   e la larghezza di scorrimento che si vedeva comparire.

   `clip` e non `hidden`: `hidden` su un solo asse costringe l'altro a
   diventare `auto`, e la pagina si ritrova con un contenitore di scorrimento
   in piu — quello che rompe `position: sticky` e fa perdere al browser il
   controllo dello scorrimento verticale. `clip` no: taglia e basta, e
   l'asse verticale resta quello della finestra.
   `hidden` resta prima come ripiego per i browser che non conoscono `clip`.

   Va dichiarato su entrambi gli elementi. Sulla radice il valore viene
   trasferito alla finestra, e la radice stessa torna a non tagliare nulla:
   se quel trasferimento non avviene come previsto, resta il corpo a farlo
   sulla propria area. Uno dei due tiene sempre.

   Resta comunque una rete, non la soluzione: cio che sborda va contenuto
   dove nasce, altrimenti il prossimo caso si presentera uguale. Vedi
   `.prize`. */
html,
body {
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-regular);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
  background-color: var(--color-bg);
}

h1,
h2,
h3 {
  font-family: var(--font-heading);
  font-weight: var(--weight-black);
  line-height: var(--leading-tight);
}

strong {
  font-weight: var(--weight-bold);
}

a {
  color: inherit;
  transition: color var(--transition-fast), opacity var(--transition-fast);
}

/* Focus sempre visibile da tastiera: requisito WCAG 2.1 AA (2.4.7).
   Il doppio contorno garantisce visibilita sia sui fondi chiari sia su quelli verdi e blu. */
:focus-visible {
  outline: 3px solid var(--color-white);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--color-blue);
  border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------------
   2. Utility e layout
   -------------------------------------------------------------------------- */

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

.section {
  padding-block: var(--space-3xl);
}

/* Intestazione centrata comune a tutte le sezioni */
.section__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-2xl);
  text-align: center;
}

.section__title {
  font-size: var(--text-5xl);
}

.section__intro {
  max-width: var(--container-narrow);
  font-size: var(--text-xl);
  line-height: var(--leading-normal);
}

/* Visibile solo agli screen reader */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Link "salta al contenuto": compare solo quando riceve il focus da tastiera */
.skip-link {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: var(--z-overlay);
  padding: var(--space-sm) var(--space-md);
  color: var(--color-blue);
  background-color: var(--color-white);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  transform: translateY(-200%);
  transition: transform var(--transition-fast);
}

.skip-link:focus {
  transform: translateY(0);
}

/* --------------------------------------------------------------------------
   3. Componenti
   -------------------------------------------------------------------------- */

/* ---- Badge: etichetta breve sopra i titoli ---- */
.badge {
  display: inline-block;
  padding: 0.4em 1em;
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  line-height: 1.4;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  border-radius: var(--radius-full);
}

.badge--yellow {
  color: var(--color-blue);
  background-color: var(--color-yellow);
}

.badge--blue {
  color: var(--color-white);
  background-color: var(--color-blue);
}

/* Etichetta senza sfondo, usata sopra il titolo della sezione "Il premio" */
.badge--plain {
  padding: 0;
  font-size: var(--text-xl);
  color: var(--color-blue);
}

/* Nota sovrapposta all'immagine del premio.
   Sfondo pieno e non velato: la sfocatura di cio che sta dietro andrebbe
   ricalcolata a ogni fotogramma mentre la foto scorre in parallasse, ed e
   una delle operazioni piu costose che si possano chiedere al browser. */
.badge--overlay {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  z-index: var(--z-raised);
  font-size: 0.625rem;
  color: var(--color-blue);
  background-color: var(--color-white);
}

/* ---- Bottoni ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-xl);
  min-height: 44px; /* area di tocco minima consigliata su mobile */
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radius-full);
  cursor: pointer;
  transition:
    background-color var(--transition-fast),
    color var(--transition-fast),
    transform var(--transition-fast);
}

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

/* Bottone bianco su fondo colorato: e l'unico stile presente nel design */
.btn--white {
  color: var(--color-blue);
  background-color: var(--color-white);
}

/* In hover il bottone si inverte: fondo blu e testo bianco */
.btn--white:hover {
  color: var(--color-white);
  background-color: var(--color-blue);
}

.btn--compact {
  padding: var(--space-sm) var(--space-lg);
  min-height: 36px;
  font-size: var(--text-base);
}

.btn__icon {
  flex-shrink: 0;
}

/* --------------------------------------------------------------------------
   4. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: grid;
  align-content: center;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh; /* su mobile esclude le barre del browser: niente salto in apertura */
  padding-block: var(--space-3xl);
  color: var(--color-white);
  background-color: var(--color-green);
}

/* Fondo dell'hero: i raggi che si irradiano dal punto in cui compare
   l'illustrazione, esportati dal file Figma.

   L'immagine porta con se il proprio verde, quindi copre il fondo della
   sezione invece di sovrapporvisi. Il `background-color` dell'hero resta
   comunque dichiarato: e cio che si vede finche l'immagine non e arrivata,
   ed e l'unica cosa che resta se non arriva affatto. */
.hero__decor {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("../img/splash.png");
  background-repeat: no-repeat;
  background-size: cover;

  /* Il fascio non e al centro dell'immagine ma al 70% della sua larghezza,
     perche nel progetto sta dietro all'illustrazione, che su due colonne e a
     destra. Su una colonna sola l'illustrazione e invece centrata, e il
     fascio le finisce di fianco: va riportato sull'asse.

     Il valore non e arbitrario. Con `cover` su un riquadro piu alto che largo
     l'immagine si ridimensiona sull'altezza e sborda ai lati; la percentuale
     dice quale punto dell'immagine allineare al corrispondente punto del
     riquadro, e l'80% e quello che porta il fascio a meta schermo. Dipende
     dalla forma del riquadro, non dalla sua misura: vale quindi per tutti i
     telefoni, che hanno proporzioni simili fra loro. Per il tablet, piu
     tozzo, il conto cambia — vedi il blocco dedicato. */
  background-position: 80% center;

  /* Un livello grande quanto la sezione che si muove per quasi tre secondi:
     senza l'avviso il browser lo ridisegna a ogni fotogramma. */
  will-change: transform;
}

.hero__inner {
  position: relative;
  z-index: var(--z-base);
  display: grid;
  gap: var(--space-2xl);
  align-items: center;
}

/* Su una colonna sola tutto sta al centro. Con l'illustrazione sopra, che e
   centrata per sua natura, un testo allineato a sinistra creerebbe due assi
   diversi nella stessa schermata. In affiancata l'asse torna a sinistra,
   perche li il testo ha una colonna propria e un margine da cui partire. */
.hero__content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  text-align: center;
}

.hero__title {
  margin: 0;
}

/* Il lettering e un'immagine: cresce con la finestra invece di restare
   inchiodato alla misura del file Figma, che su schermi ampi risulta minuta.

   Il tetto di 480px non e estetico ma geometrico: oltre i 1600px di finestra
   il contenitore smette di allargarsi (--container-max), quindi la colonna di
   sinistra si ferma a ~571px. Un lettering da 560px la riempirebbe tutta e
   l'ingrandimento di apertura finirebbe addosso all'illustrazione. Fermandosi
   a 480px resta il margine per l'ingrandimento. Sotto i 1600px il tetto non
   entra mai in gioco: comanda il 30vw. */
.hero__lettering {
  width: clamp(260px, 30vw, 480px);
  height: auto;
  margin-top: var(--space-lg);
}

.hero__subtitle {
  font-size: clamp(1.0625rem, 0.95rem + 0.45vw, 1.375rem);
  line-height: var(--leading-normal);
  margin-top: var(--space-lg)
}

.hero__figure {
  display: flex;
  justify-content: center;

  /* Esplicito, non decorativo: ora che l'illustrazione ha altezza `auto`, lo
     stiramento predefinito dei contenitori flessibili la allungherebbe fino
     al bordo del contenitore ogni volta che questo risulta piu alto di lei. */
  align-items: center;
}

.hero__illustration {
  width: min(100%, 620px);
  height: auto;

  /* L'illustrazione e il file piu pesante della pagina e in apertura viene
     rimpicciolita da oltre il doppio: senza questo avviso il browser la
     ridimensiona da capo a ogni fotogramma, ed e li che si vedono gli scatti.
     Cosi invece la prepara una volta sola su un livello dedicato. */
  will-change: transform;
}

/* ---- Animazione di apertura ----
   Parte da sola al caricamento della pagina, senza JavaScript.

   Le sequenze sono due, perche sono due le disposizioni.

   SU UNA COLONNA (fino a 1024px) — l'illustrazione sta sopra e apre da sola,
   il testo si compone sotto nell'ordine in cui va letto:

     0      l'illustrazione parte ingrandita e inclinata, quasi ferma;
            dietro di lei il fascio di raggi fa lo stesso, in tono minore
     0,8s   compare l'etichetta, mentre l'illustrazione sta ancora rientrando
     0,95s  scende il lettering, alla sua misura definitiva
     1,1s   sale il claim
     1,1s   illustrazione e raggi si fermano
     1,25s  sale il bottone
     1,85s  il bottone e a posto: l'apertura e conclusa

   IN AFFIANCATA (da 1024px) — illustrazione e lettering stanno uno accanto
   all'altro e si compongono in parallelo, una colonna per parte:

     0      partono insieme illustrazione e raggi
     0,5s   dall'alto scende il lettering, alla sua misura piu grande
     1,4s   illustrazione e raggi si fermano; nello stesso istante il
            lettering tocca terra e comincia a ridursi
     1,6s   scende il badge
     1,75s  sale il claim
     1,9s   sale il bottone
     2,4s   il lettering e alla misura definitiva
     2,5s   il bottone e a posto: l'apertura e conclusa

   La differenza non e di velocita ma di ruolo: impilata, l'illustrazione fa
   da sipario e il testo la aspetta; affiancata, non ha nulla da scoprire e i
   due procedono insieme. L'ingrandimento del lettering esiste solo nel
   secondo caso — vedi la regola nel blocco dei 1024px.

   Tre criteri tengono insieme i tempi:

   - Le tre entrate del testo sono scandite a 150ms l'una dall'altra. Un passo
     costante si legge come ritmo; intervalli disuguali si leggono come ritardi.
   - Tutto si posa nell'arco di 100ms (2,4 -> 2,5s). L'illustrazione dura meno
     delle altre proprio perche parte per prima: chiudere insieme conta piu
     che durare uguale. Quando invece una sola cosa continua a muoversi dopo
     che le altre si sono fermate, quel movimento non si legge come coda ma
     come qualcosa rimasto indietro.
   - I momenti si toccano invece di susseguirsi: l'illustrazione finisce
     nell'istante esatto in cui il lettering atterra, e la sua riduzione parte
     da li. Sono giunzioni, non coincidenze: chi cambia una durata sposta
     anche il ritardo che le sta attaccato, altrimenti si apre un vuoto.

   Le proporzioni contano piu dei valori assoluti: per rendere l'apertura piu
   rapida o piu lenta si moltiplica tutto per uno stesso fattore, durate e
   ritardi insieme. Toccare un solo numero rompe le giunzioni qui sopra.

   Lo stato di partenza vive SOLO dentro i @keyframes: `backwards` lo applica
   durante il ritardo iniziale. Se le animazioni non partono, gli elementi
   restano visibili al posto giusto invece di sparire. */

/* Un unico movimento senza tappe intermedie: la curva parte quasi ferma,
   prende velocita a meta e frena a lungo in chiusura. Sono quei tre tempi
   della stessa curva a dare il ritmo, non tre animazioni incollate. */
/* Lo spostamento e dichiarato per primo di proposito. Nella catena delle
   trasformazioni l'ultima scritta agisce per prima, quindi qui la casa viene
   prima ingrandita e ruotata e solo dopo spostata: i 7% restano 7% della sua
   misura a riposo, non moltiplicati per l'ingrandimento. Invertendo l'ordine
   lo scostamento verrebbe amplificato tre volte e cambierebbe a ogni
   fotogramma, perche l'ingrandimento cala mentre l'animazione procede.

   L'arrivo porta `translateX(0)` anche se non sposta nulla: due fotogrammi
   chiave si fondono per funzioni corrispondenti, e se gli elenchi non
   coincidono il browser ripiega su una matrice unica, con una traiettoria
   diversa da quella descritta qui. */
@keyframes intro-hero-image {
  from {
    transform: translateX(-7%) scale(3.3) rotate(18deg);
  }
  to {
    transform: translateX(0) scale(1.2) rotate(-18deg);
  }
}

/* I raggi dietro l'illustrazione si assestano insieme a lei: stessa durata,
   stessa curva, stessa partenza. Le proporzioni sono pero un decimo delle sue
   (1.6 -> 1 contro 3 -> 1.2, 6 gradi contro 36), perche un fondo che si muove
   quanto l'oggetto in primo piano smette di leggersi come fondo. Il verso e
   lo stesso, ed e quello a far sembrare i due movimenti un gesto solo.

   Si chiude a `scale(1) rotate(0)` e non a una posizione qualsiasi: e l'unica
   in cui l'immagine copre esattamente il riquadro. Ogni rotazione scopre gli
   angoli, e per rimediare serve un ingrandimento almeno pari a
   cos(a) + r * sen(a), dove r e il rapporto fra il lato lungo e il corto
   della sezione. Qui ingrandimento e rotazione calano insieme, quindi la
   condizione regge per tutta la durata: chi ritocca l'uno rifaccia il conto
   sull'altro. */
@keyframes intro-hero-splash {
  from {
    opacity: 0;
    transform: scale(1.6) rotate(6deg);
  }
  to {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

/* La discesa e il rimpicciolimento del lettering sono due animazioni distinte
   su due elementi annidati: il titolo scende, l'immagine dentro si rimpicciolisce.
   I due movimenti sono in fila, non sovrapposti: prima la discesa, poi la
   riduzione. Sovrapporli faceva percorrere al lettering una traiettoria curva,
   perche scendeva mentre si contraeva verso il proprio margine sinistro:
   due spostamenti su assi diversi nello stesso istante si sommano in diagonale. */
@keyframes intro-lettering-drop {
  from {
    opacity: 0;
    transform: translateY(-140px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes intro-lettering-shrink {
  from {
    transform: scale(var(--intro-lettering-scale));
  }
  to {
    transform: scale(1);
  }
}

@keyframes intro-from-top {
  from {
    opacity: 0;
    transform: translateY(-48px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes intro-from-bottom {
  from {
    opacity: 0;
    transform: translateY(32px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Su una colonna sola l'illustrazione sale in cima. Non e solo estetica: e
   l'unico elemento che si legge a colpo d'occhio, e su un telefono la prima
   schermata e tutto quello che si ha. Il testo si compone sotto, nell'ordine
   in cui va letto.

   Lo scambio avviene qui e non nel documento: nel documento il titolo resta
   il primo elemento, che e cio che leggono i motori di ricerca e i lettori di
   schermo. Spostare l'immagine davanti al titolo nel documento avrebbe
   anteposto una figura decorativa all'intestazione della pagina.
   Nessun elemento dell'immagine riceve il fuoco da tastiera, quindi lo
   scambio non crea disallineamenti nell'ordine di navigazione. */
.hero__figure {
  order: -1;
}

/* Avvio lento, allungo centrale, frenata lunga: e la curva a scandire i tempi
   dell'ingresso, in un movimento solo.
   Su una colonna sola l'illustrazione apre, quindi corre piu breve che in
   affiancata: il testo la aspetta, e ogni decimo speso qui e un decimo in cui
   sotto non succede nulla. */
.hero__illustration {
  animation: intro-hero-image 1100ms cubic-bezier(0.62, 0.02, 0.2, 1) forwards;
}

/* Stessa durata e stessa curva dell'illustrazione, e nessun ritardo per
   nessuna delle due: i raggi e la casa partono e si fermano insieme, che e
   quello che li fa leggere come un movimento solo invece che come due. */
.hero__decor {
  animation: intro-hero-splash 1100ms cubic-bezier(0.62, 0.02, 0.2, 1) forwards;
}

/* Le quattro parti del testo entrano a 150ms l'una dall'altra, nell'ordine in
   cui si leggono: etichetta, lettering, claim, bottone. La prima parte mentre
   l'illustrazione sta ancora rientrando, cosi i due momenti si toccano.

   Il passo e costante di proposito — bastano 50ms di scarto fra un intervallo
   e l'altro perche la sequenza smetta di sembrare una cascata e cominci a
   sembrare una serie di piccoli ritardi. */
.hero__content > .badge {
  animation: intro-from-top 600ms cubic-bezier(0.22, 0.9, 0.3, 1) 800ms backwards;
}

/* Su colonna singola il lettering entra come le altre tre parti: scende e
   basta, senza la fase di ingrandimento che ha in affiancata. Due ragioni.
   La prima e di misura: a 390px di schermo il lettering ingrandito e largo
   quanto il telefono e verrebbe tagliato dal bordo. La seconda e di ritmo: in
   affiancata l'ingrandimento ha 1,2 secondi per svolgersi, qui la cascata
   intera ne dura poco piu di uno e quel movimento non avrebbe respiro.
   La regola che lo esegue vive nel blocco dei 1024px, dove torna utile. */
.hero__title {
  animation: intro-lettering-drop 600ms cubic-bezier(0.22, 0.9, 0.3, 1) 950ms backwards;
}

.hero__subtitle {
  animation: intro-from-bottom 600ms cubic-bezier(0.22, 0.9, 0.3, 1) 1100ms backwards;
}

.hero__content .btn {
  animation: intro-from-bottom 600ms cubic-bezier(0.22, 0.9, 0.3, 1) 1250ms backwards;
}

/* Chi ha disattivato le animazioni nel sistema vede subito la pagina
   composta: il ritardo di apertura verrebbe percepito come un blocco. */
@media (prefers-reduced-motion: reduce) {
  .hero__decor,
  .hero__illustration,
  .hero__content > .badge,
  .hero__title,
  .hero__lettering,
  .hero__subtitle,
  .hero__content .btn {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   4b. Comparsa allo scroll
   -------------------------------------------------------------------------- */

/* Gli elementi marcati con .reveal entrano quando compaiono nella finestra.
   A decidere il momento e assets/js/app.js, che aggiunge loro `is-visible`;
   qui si descrive solo il movimento, con durate proprie.

   Lo stato di partenza vale SOLO sotto `.js`, la classe che lo script mette
   sulla pagina appena parte: se JavaScript e disattivato nessun elemento
   viene nascosto e la pagina resta interamente leggibile.
   Il blocco @media rispetta poi chi ha disattivato le animazioni nel sistema. */

/* Comparsa a sipario: il contenuto si scopre dall'alto mentre sale.
   Il taglio con clip-path fa emergere il testo da dietro un bordo netto,
   invece di limitarsi a farlo apparire. */
@keyframes reveal-curtain {
  from {
    clip-path: inset(0 0 100% 0);
    transform: translateY(28px);
  }
  to {
    clip-path: inset(0 0 0 0);
    transform: translateY(0);
  }
}

/* Le schede si sollevano ruotando: partono inclinate all'indietro,
   come appoggiate al piano, e si raddrizzano verso chi guarda. */
@keyframes reveal-tilt {
  from {
    opacity: 0;
    transform: perspective(1000px) rotateX(18deg) translateY(60px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: perspective(1000px) rotateX(0) translateY(0) scale(1);
  }
}

/* Riquadri ampi: si scoprono dal basso allargandosi ai lati, schiarendo.

   Due accortezze, entrambe per non restare appesi al solo `clip-path`:

   1. Niente `round` qui dentro. Gli angoli arrotondati li fa gia il ritaglio
      del contenitore (`border-radius` + `overflow: clip` su .prize__figure),
      quindi ripeterli nel ritaglio e superfluo — e obbligherebbe a una
      variabile. Una variabile dentro un fotogramma chiave e il punto in cui
      i browser divergono: dove non viene risolta, la riga cade e il ritaglio
      salta da un capo all'altro invece di scorrere.
   2. `opacity` accompagna il movimento. Se il ritaglio non venisse animato,
      la comparsa resta comunque graduale invece di apparire di colpo. */
@keyframes reveal-unveil {
  from {
    opacity: 0;
    clip-path: inset(0 12% 100% 12%);
  }
  to {
    opacity: 1;
    clip-path: inset(0 0 0 0);
  }
}

/* Le due destinazioni entrano da lati opposti */
@keyframes reveal-from-left {
  from {
    opacity: 0;
    transform: translateX(-70px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes reveal-from-right {
  from {
    opacity: 0;
    transform: translateX(70px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Parallasse: la foto scorre piu lentamente della pagina. L'ingrandimento
   del 12% serve a coprire lo spostamento, altrimenti si vedrebbero i bordi. */
@keyframes reveal-parallax {
  from {
    transform: scale(1.12) translateY(-4%);
  }
  to {
    transform: scale(1.12) translateY(4%);
  }
}

/* Caduta del segnaposto sulla mappa, con lo schiacciamento all'impatto e
   due rimbalzi che si smorzano. */
@keyframes pin-drop {
  0% {
    opacity: 0;
    transform: translateY(-40px) scale(0.94, 1.12);
  }
  12% {
    opacity: 1;
  }
  34% {
    transform: translateY(0) scale(1.16, 0.82);
  }
  50% {
    transform: translateY(-13px) scale(0.96, 1.06);
  }
  64% {
    transform: translateY(0) scale(1.07, 0.94);
  }
  76% {
    transform: translateY(-4px) scale(1);
  }
  88%,
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@media (prefers-reduced-motion: no-preference) {
  /* L'animazione e assegnata subito ma tenuta in pausa: con `both`
     l'elemento resta fermo sul primo fotogramma, cioe nel suo stato di
     partenza. Non serve nasconderlo a parte, e ogni effetto porta con se
     il proprio inizio, che sia un ritaglio o una trasparenza.
     Tutto sotto `.js`: senza JavaScript nulla viene nascosto. */
  .js .reveal {
    animation: reveal-curtain 900ms cubic-bezier(0.22, 0.9, 0.3, 1) both paused;
  }

  .js .reveal.is-visible {
    animation-play-state: running;
  }

  .js .reveal--tilt {
    animation-name: reveal-tilt;
  }

  .js .reveal--unveil {
    animation-name: reveal-unveil;
  }

  .js .reveal--from-left {
    animation-name: reveal-from-left;
  }

  .js .reveal--from-right {
    animation-name: reveal-from-right;
  }

  /* Gli elementi di uno stesso gruppo entrano in fila invece che insieme.
     `--pin-attesa` accompagna ogni scheda: e il momento in cui il suo
     ingresso e concluso, cioe attesa + durata (900ms), e da li parte il
     segnaposto. Se cambia una delle due misure va aggiornata anche questa. */
  .js .reveal--delay-1 {
    animation-delay: 150ms;
    --pin-attesa: 800ms;
  }

  .js .reveal--delay-2 {
    animation-delay: 300ms;
    --pin-attesa: 1000ms;
  }

  /* Cade il solo segnaposto giallo. Il pallino scuro sotto la punta segna il
     luogo esatto sulla mappa e resta dov'e: e il bersaglio, non il proiettile.

     La caduta parte a scheda ferma, cioe quando la card ha finito di scorrere
     fino al suo posto: altrimenti il segnaposto atterrerebbe su una mappa
     ancora in movimento. */
  .js .place-card__pin-shape {
    animation: pin-drop 1300ms cubic-bezier(0.33, 1, 0.68, 1) both paused;
    /* Dichiarato a parte e non dentro la scorciatoia: li una variabile non
       ancora risolta invaliderebbe l'intera regola. */
    animation-delay: var(--pin-attesa, 1080ms);
  }

  .js .place-card.is-visible .place-card__pin-shape {
    animation-play-state: running;
  }
}

/* La foto del premio scorre piu lentamente della pagina per tutto il tempo in
   cui attraversa lo schermo. Questo e l'unico movimento davvero legato alla
   posizione di scorrimento, non a un ingresso: resta quindi affidato al CSS,
   che lo calcola senza far girare codice a ogni pixel. Dove non e supportato
   (Firefox) la foto e semplicemente ferma. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .prize__figure img {
      animation-name: reveal-parallax;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      /* Qui l'avviso resta per sempre, a differenza degli altri elementi:
         il movimento non si esaurisce, prosegue per tutto il tempo in cui la
         foto attraversa lo schermo. */
      will-change: transform;
    }
  }
}

/* --------------------------------------------------------------------------
   5. Il premio
   -------------------------------------------------------------------------- */

.prize {
  background-color: var(--color-white);

  /* Qui nasce l'unico sbordo laterale della pagina. Le due destinazioni
     entrano da destra e da sinistra, e prima di entrare restano ferme al
     proprio punto di partenza — 70px oltre il posto che occuperanno — per
     tutto il tempo in cui non le si e ancora raggiunte scorrendo. Su schermo
     stretto quella di destra arriva a 38px oltre il bordo.

     Il taglio va messo qui e non sulla pagina: contenuto dove nasce, il
     movimento continua a partire da fuori campo come deve, e il resto del
     documento non porta le conseguenze di un effetto che riguarda una
     sezione sola.

     Solo `clip`, e senza ripiego su `hidden`. Su un asse solo, `hidden`
     costringe l'altro a diventare `auto`: la sezione diventerebbe un
     contenitore di scorrimento verticale e taglierebbe i cerchi delle mappe,
     che sporgono sopra i riquadri di proposito. `clip` taglia il solo asse
     dichiarato e lascia passare l'altro — e l'unico valore che sa farlo.
     Dove non e supportato resta la rete su html e body. */
  overflow-x: clip;
}

.prize__showcase {
  position: relative;
}

.prize__figure {
  position: relative;
  margin: 0;

  /* `clip` e non `hidden`: taglia allo stesso modo, ma NON crea un contenitore
     di scorrimento. La differenza conta per la parallasse della foto qui
     dentro: `animation-timeline: view()` si aggancia al primo contenitore di
     scorrimento che trova salendo, e con `hidden` quel contenitore sarebbe
     questa stessa figura — che non scorre mai. La linea del tempo resterebbe
     ferma e la foto immobile. Con `clip` la ricerca prosegue fino alla pagina,
     che e cio che scorre davvero.
     `hidden` resta prima come ripiego per i browser che non conoscono `clip`. */
  overflow: hidden;
  overflow: clip;
  border-radius: var(--radius-lg);
}

/* Il rapporto dell'immagine cambia con lo schermo, la fotografia no: e
   `object-fit: cover` a ritagliarla di volta in volta, senza deformarla e
   senza servire file diversi.

   Su telefono il 4/5 verticale: una fascia larga e bassa, su uno schermo
   stretto, si riduce a una striscia di poche decine di pixel in cui non si
   riconosce piu nulla. Il 3/5 verticale le fa invece occupare la porzione di
   schermo che le compete e, soprattutto, le da l'altezza per reggere le due
   destinazioni appoggiate sopra. Il ritaglio parte dal centro, dove sta la
   veduta sul mare. */
.prize__figure img {
  width: 100%;
  aspect-ratio: 3 / 5;
  object-fit: cover;

  /* Ancoraggio in basso. Quale dei due valori conti dipende da quale lato
     della fotografia eccede il riquadro, e cambia con lo schermo: dove il
     riquadro e piu stretto della fotografia (telefono e tablet) l'eccedenza
     e laterale e a spostare il ritaglio sarebbe il primo valore, non questo;
     dove il riquadro e piu largo (la fascia del desktop) l'eccedenza e
     verticale ed e qui che `bottom` decide cosa si vede.
     Vale per entrambi i casi senza doverlo differenziare: il valore inerte
     semplicemente non fa nulla. */
  object-position: center bottom;
}

/* Le due destinazioni si appoggiano sul fondo della fotografia invece di
   seguirla: sono una didascalia del premio, non un elenco a parte, e
   sovrapporle lo dice senza bisogno di scriverlo. E' anche cio che tiene
   insieme il blocco su schermo stretto, dove impilare immagine e riquadri
   uno sotto l'altro produceva una colonna lunga e slegata.

   Uscendo dal flusso non allungano piu il contenitore: e la fotografia a
   dettare l'altezza dell'intero blocco. Lo scostamento dai bordi e lo stesso
   su tutti e tre i lati, cosi il gruppo risulta appoggiato dentro la
   fotografia e non incollato al suo margine. */
.prize__places {
  position: absolute;
  inset-inline: var(--space-md);
  bottom: var(--space-md);
  display: grid;
  gap: var(--space-md);
}

.place-card {
  /* La card si dichiara misurabile: da qui in giu `cqw` vale l'1% della SUA
     larghezza. E' il riferimento giusto perche il cerchio deve stare in
     proporzione al riquadro che lo contiene, e quel riquadro cambia natura
     con la disposizione: su telefono e largo quanto lo schermo, su desktop
     quanto meta schermo meno i margini a scavalco e lo spazio fra le due
     colonne. Una percentuale della finestra non puo valere per entrambi —
     ed e per questo che il 24vw di prima funzionava su telefono e lasciava
     il desktop scoperto. */
  container-type: inline-size;

  /* Diametro del cerchio con la mappa. E' l'unica misura fissa della riga:
     il titolo va a capo, il sottotitolo sparisce, il padding e proporzionato,
     la card si allarga con la colonna. Solo il cerchio, a 150px, resta
     identico e si prende lo spazio che manca al titolo — che a quel punto
     non contiene piu "FERRARESI" su una riga e la spezza a meta.

     Il 30% della card e il valore che lascia al titolo abbastanza spazio in
     ogni disposizione. Il tetto riporta il cerchio alla misura di progetto
     appena la card supera i 500px, cioe su desktop dai 1380px di finestra. */
  --place-map-size: clamp(84px, 30cqw, 150px);

  /* Non c'e piu un'altezza minima dichiarata, e non e una dimenticanza: la
     dettava il cerchio, e continua a dettarla senza bisogno di scriverlo.
     Il cerchio risale del 43% della propria misura, quindi ne occupa nel
     flusso il 57%, e sommato allo spazio interno da esattamente l'altezza
     che la regola precedente imponeva — 150px alla misura piena.
     Dichiararla di nuovo qui non si potrebbe comunque: `cqw` misura il
     contenitore piu vicino fra gli antenati, e nessun elemento e antenato di
     se stesso. Un'altezza espressa cosi cercherebbe un contenitore piu in
     alto, e leggerebbe la misura sbagliata. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);

  /* Spaziatura asimmetrica: piu stretta sopra e sotto che ai lati. Il motivo
     e che le due direzioni servono a cose diverse. Ai lati regge la distanza
     fra il titolo e il bordo, e togliere li vorrebbe dire avvicinare il testo
     al margine. Sopra e sotto invece non trattiene nulla: l'altezza del
     riquadro la detta il cerchio, che ne occupa 56px, mentre il titolo su due
     righe ne chiede 48. Lo spazio verticale si somma e basta.
     Da 640px in su torna simmetrica, dove l'altezza non e un problema. */
  padding: var(--space-md) var(--space-lg);
  color: var(--color-white);
  background-color: var(--color-green);
  border-radius: var(--radius-md);
}

/* Il testo occupa lo spazio residuo, il cerchio con la mappa resta di misura fissa */
.place-card__text {
  flex: 1;
  min-width: 0;
}

.place-card__title {
  font-size: var(--text-3xl);
  color: var(--color-white);
  text-transform: uppercase;
}

/* Su telefono il sottotitolo sparisce del tutto. Appoggiati sopra la
   fotografia i due riquadri devono restare bassi, altrimenti la coprono; ed
   e la riga che si puo togliere senza perdere nulla, perche l'introduzione
   della sezione dice gia dove sono le due localita.

   E' `display: none` e non un nascondere solo visivo: sottrarlo alla vista
   lasciandolo ai lettori di schermo creerebbe due versioni diverse della
   stessa pagina, e qui non c'e informazione che giustifichi lo scarto.

   Torna visibile da 640px, dove la fotografia e larga abbastanza. */
.place-card__subtitle {
  display: none;
  margin-top: var(--space-xs);
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
}

/* Il cerchio blu e gia dentro l'immagine: qui serve solo la misura.
   150px e il diametro del cerchio nel file Figma. */
/* I margini negativi stanno sul contenitore, non sull'immagine: il cerchio
   sporge oltre il bordo come nel design, invece di far crescere la card, e
   il contenitore assume la stessa area dell'immagine, su cui va a
   sovrapporsi il segnaposto. Quello che esce viene tagliato dall'overflow
   di .place-card. */
.place-card__map {
  position: relative;
  flex-shrink: 0;
  height: var(--place-map-size);

  /* Lo sconfinamento verso l'alto e espresso in frazione del cerchio, non in
     pixel: cosi resta la stessa porzione a ogni misura. Alla misura piena
     vale i -64px di prima, quindi da tablet in su nulla cambia. */
  margin-top: calc(var(--place-map-size) * -0.43);
}

.place-card__map img {
  width: auto;
  height: 100%;
}

/* Il segnaposto e un disegno a parte, sovrapposto alla mappa. Condivide il
   viewBox dell'immagine, quindi le coordinate del file Figma valgono tali e
   quali e il pin cade esattamente dove deve. */
.place-card__pin {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Il tracciato giallo e l'unica parte che si muove. Dentro un SVG le
   trasformazioni prendono per riferimento il sistema di coordinate del
   disegno: `fill-box` le riporta all'ingombro del tracciato stesso, cosi
   l'origine cade sulla punta del segnaposto e lo schiacciamento all'impatto
   avviene da li, non dal centro dell'immagine. */
.place-card__pin-shape {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}

/* --------------------------------------------------------------------------
   6. Come partecipare
   -------------------------------------------------------------------------- */

.how {
  position: relative;
  /* Il colore resta sotto l'immagine: se il file non arriva, la sezione
     non cambia aspetto in modo evidente. */
  background-color: var(--color-white);
  background-image: url("../img/how-bg.png");
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.how__paths {
  display: grid;
  gap: var(--space-xl);
  margin-bottom: var(--space-2xl);
}

/* ---- Card a forma di biglietto ----
   Struttura in tre parti affiancate, come un tagliando da staccare:
   la matrice con l'icona, la linea di strappo, il corpo del testo.

   Su mobile le tre parti si impilano e lo strappo diventa orizzontale.
   Da tablet in su la card assume la forma piena, con gli incavi ai due
   capi della linea di strappo. */
/* L'ombra sta sul contenitore esterno, il ritaglio sulla sagoma interna.
   Tenerli separati e necessario: una maschera taglia tutto cio che esce dal
   riquadro dell'elemento, ombra inclusa, e il risultato sarebbe un alone
   mozzato lungo i bordi. Cosi invece drop-shadow disegna l'ombra della
   sagoma gia ritagliata, incavi compresi. */
.ticket {
  /* Misure dello strappo, riprese piu sotto dalla maschera degli incavi */
  --ticket-rip: 24px;
  --ticket-notch: 24px;
  --ticket-border: rgb(28 28 26 / 0.08);

  position: relative;

  /* Il contorno NON e un border: un bordo si fermerebbe ai lati del
     riquadro e lascerebbe scoperti i due incavi, che sono un ritaglio.
     Quattro ombre secche di un pixel nelle quattro direzioni disegnano
     invece il profilo della sagoma vera, curve comprese. L'ombra morbida
     viene per ultima, cosi cade anche sotto il contorno. */
  filter: drop-shadow(1px 0 0 var(--ticket-border)) drop-shadow(-1px 0 0 var(--ticket-border))
    drop-shadow(0 1px 0 var(--ticket-border)) drop-shadow(0 -1px 0 var(--ticket-border))
    drop-shadow(0 8px 20px rgb(28 28 26 / 0.1));
}

.ticket__shape {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* La matrice: ospita l'icona ed e la parte che "si stacca" */
.ticket__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  padding: var(--space-xl);
  background-color: var(--color-white);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.ticket__icon img {
  width: 56px;
  height: auto;
}

/* La linea di strappo: fascia piena con la tratteggiatura al centro.
   Il colore di fondo e lo stesso della card, cosi la fascia sembra parte
   del biglietto e non un elemento appoggiato sopra. */
.ticket__rip {
  flex-shrink: 0;
  height: var(--ticket-rip);
  background-color: var(--color-white);
  background-image: repeating-linear-gradient(
    to right,
    rgb(28 28 26 / 0.22) 0 6px,
    transparent 6px 12px
  );
  background-repeat: repeat-x;
  background-position: center;
  background-size: 100% 2px;
}

.ticket__body {
  flex: 1;
  padding: var(--space-xl);
  background-color: var(--color-white);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.ticket__title {
  margin-bottom: var(--space-md);
  font-size: var(--text-2xl);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.ticket__text {
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--color-text-muted);
}

/* ---- Riquadro blu dell'estrazione ---- */
.draw {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-2xl) var(--space-xl);
  text-align: center;
  color: var(--color-white);
  background-color: var(--color-blue);
  border-radius: var(--radius-lg);
  margin-top: var(--space-2xl);
}

.draw__title {
  font-size: var(--text-4xl);
}

.draw__text {
  max-width: 70ch;
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
}

/* --------------------------------------------------------------------------
   7. Regolamento
   -------------------------------------------------------------------------- */

.rules {
  padding-block: var(--space-2xl);
  background-color: var(--color-white);
}

.rules__box {
  /* Lo spazio interno in verticale e dichiarato come variabile perche non
     serve solo qui: l'icona lo usa per calcolare di quanto risalire. */
  --rules-padding-block: var(--space-xl);

  /* Quanto l'icona sporge sopra il bordo del riquadro. Separarlo dal calcolo
     lo rende leggibile: `-1rem` scritto sull'icona diceva solo "risali di
     16px", e a quel punto non era piu chiaro se dipendesse dal padding o no
     — infatti smetteva di funzionare appena il padding cambiava. */
  --rules-icon-overflow: 1rem;

  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  max-width: 880px;
  margin-inline: auto;
  padding: var(--rules-padding-block) var(--space-lg);
  text-align: center;
  color: var(--color-white);
  background-color: var(--color-green);
  border-radius: var(--radius-md);
}

.rules__icon {
  flex-shrink: 0;

  /* Deve annullare lo spazio interno e poi risalire ancora: e la somma dei
     due a portare l'icona oltre il bordo. Cambiando il padding la sporgenza
     resta quella dichiarata sopra, senza rimettere mano a questo numero. */
  margin-top: calc((var(--rules-padding-block) + var(--rules-icon-overflow)) * -1);
}

.rules__text {
  flex: 1;
}

.rules__title {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
}

.rules__subtitle {
  margin-top: var(--space-xs);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
}

/* --------------------------------------------------------------------------
   8. Invito finale
   -------------------------------------------------------------------------- */

.final-cta {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-3xl);
  color: var(--color-white);
  background-color: var(--color-green);
}

/* Gli stessi raggi dell'hero, che chiudono la pagina come l'hanno aperta.
   E il file gia scaricato per l'hero: qui non costa un secondo download.

   L'immagine porta con se il proprio verde e copre il fondo della sezione
   invece di sovrapporvisi, come nell'hero. Il `background-color` della
   sezione resta comunque dichiarato: e cio che si vede finche l'immagine
   non e arrivata, ed e l'unica cosa che resta se non arriva affatto.

   Qui il riquadro e largo e basso, l'opposto dell'hero: con `cover`
   l'immagine si ridimensiona sulla larghezza e sborda in altezza, quindi
   la posizione orizzontale non ha effetto e a decidere il taglio e quella
   verticale. `center` tiene nella banda visibile il punto da cui i raggi
   si irradiano, che nell'immagine sta al 40% dell'altezza. */
.final-cta__decor {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("../img/splash.png");
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}

.final-cta__inner {
  position: relative;
  z-index: var(--z-base);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  text-align: center;
}

.final-cta__title {
  font-size: var(--text-4xl);
}

.final-cta__text {
  max-width: 60ch;
  font-size: var(--text-xl);
  line-height: var(--leading-normal);
}

/* --------------------------------------------------------------------------
   9. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding-block: var(--space-3xl) var(--space-2xl);
  color: var(--color-white);
  background-color: var(--color-ink);
}

.site-footer__top {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  align-items: flex-start;
  justify-content: space-between;
}

.site-footer__logo {
  width: 203px;
  max-width: 60%;
  height: auto;
}

.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  color: var(--color-footer-text);
}

.site-footer__nav a {
  text-decoration: none;
}

.site-footer__nav a:hover {
  color: var(--color-white);
}

.site-footer__line {
  margin-block: var(--space-xl);
  border: 0;
  border-top: 1px solid var(--color-border);
}

.site-footer__disclaimer {
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-xl);
}

/* Blocco legale: dati societari e informative, raggruppati a sinistra */
.site-footer__legal {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.site-footer__copyright {
  font-size: var(--text-xs);
  line-height: 1.6;
  color: var(--color-footer-text);
}

.site-footer__legal-link {
  align-self: flex-start;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--color-footer-text);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.site-footer__legal-link:hover {
  color: var(--color-white);
}

.site-footer__top-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
}

.site-footer__top-link:hover {
  opacity: 0.8;
}

/* --------------------------------------------------------------------------
   10. Media query — tablet (>= 640px)
   -------------------------------------------------------------------------- */

@media (min-width: 640px) {
  :root {
    --container-padding: var(--space-xl);
  }

  .section {
    padding-block: var(--space-4xl);
  }

  /* Da qui lo spazio c'e: la card torna alla spaziatura di progetto, che su
     telefono era stata ridotta per lasciare respiro al titolo. */
  .place-card {
    padding: var(--space-xl) var(--space-2xl);
  }

  /* Passo intermedio verso la fascia larga del progetto. Il verticale qui
     non serve piu — lo schermo e abbastanza largo — ma la fascia da 1226/553
     non ancora: su un tablet in verticale sarebbe alta poco piu di 300px,
     con la fotografia ridotta a un ritaglio. */
  .prize__figure img {
    aspect-ratio: 3 / 2;
  }

  /* Qui le destinazioni tornano sotto la fotografia, e non e un ripensamento:
     la sovrapposizione regge finche la fotografia e alta e i riquadri bassi.
     Da questa soglia si inverte tutto — la fotografia diventa orizzontale e
     i riquadri riprendono il sottotitolo, quindi crescono. A 640px i due
     insieme occuperebbero 332px dei 405 disponibili, lasciandone 73: non e
     piu una didascalia appoggiata sopra, e una coperta.
     Tornera una sovrapposizione da 1024px, ma di tipo diverso: li i riquadri
     scavallano il bordo inferiore invece di posarsi dentro. */
  .prize__places {
    position: static;
    margin-top: var(--space-md);
  }

  .place-card__subtitle {
    display: block;
    font-size: var(--text-xl);
  }

  /* Da qui il biglietto si dispone in orizzontale: matrice a sinistra,
     strappo verticale, corpo a destra. */
  .ticket {
    /* Distanza della linea di strappo dal bordo sinistro: e il centro
       della fascia, e serve anche a posizionare i due incavi. */
    --ticket-rip-x: 132px;
  }

  .ticket__shape {
    flex-direction: row;
    align-items: stretch;

    /* Gli incavi sono ritagli veri: la maschera toglie due cerchi ai capi
       della linea di strappo, quindi si vede lo sfondo della sezione, non
       un cerchio dipinto sopra la card. Cosi funzionano anche sopra la
       trama di how-bg.png, che non e a tinta unita. */
    mask-image:
      radial-gradient(
        circle var(--ticket-notch) at var(--ticket-rip-x) 0,
        transparent 98%,
        #000 100%
      ),
      radial-gradient(
        circle var(--ticket-notch) at var(--ticket-rip-x) 100%,
        transparent 98%,
        #000 100%
      );
    /* Safari usa ancora la forma con prefisso e un nome diverso per la
       stessa operazione: va dichiarata prima di quella standard. */
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }

  .ticket__icon {
    width: calc(var(--ticket-rip-x) - var(--ticket-rip) / 2);
    border-radius: var(--radius-lg) 0 0 var(--radius-lg);
  }

  /* La stessa fascia, ruotata: tratteggio verticale invece che orizzontale */
  .ticket__rip {
    width: var(--ticket-rip);
    height: auto;
    background-image: repeating-linear-gradient(
      to bottom,
      rgb(28 28 26 / 0.22) 0 6px,
      transparent 6px 12px
    );
    background-repeat: repeat-y;
    background-size: 2px 100%;
  }

  .ticket__body {
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  }

  /* Da qui il riquadro si dispone in orizzontale, e con l'incolonnamento
     cambia anche chi tiene il contenuto lontano dai bordi: in riga sono
     l'icona, alta piu di tutti, e l'allineamento al centro a creare il
     margine sopra e sotto. Lo spazio interno in verticale tornerebbe quindi a
     sommarsi a quello, alzando il riquadro senza motivo: qui si azzera e
     resta la sola spaziatura orizzontale, come era prima.
     In colonna, su telefono, quel meccanismo non esiste — il primo e l'ultimo
     elemento toccano il bordo — ed e li che lo spazio interno serve. */
  .rules__box {
    --rules-padding-block: 0px;

    flex-direction: row;
    text-align: left;
    padding-inline: var(--space-2xl);
  }

  .site-footer__top {
    flex-direction: row;
    align-items: flex-end;
  }
}

/* --------------------------------------------------------------------------
   Media query — tablet in verticale (640px - 1024px, piu alto che largo)
   -------------------------------------------------------------------------- */

/* E' l'unica regola dell'intero foglio delimitata sopra e sotto, e non per
   distrazione: qui non si aggiunge nulla al caso generale, si descrive un
   caso a se. Sotto i 640px l'illustrazione e piccola e non avanza spazio;
   sopra i 1024px le due parti sono affiancate e non c'e nulla da
   sovrapporre. Solo in mezzo, e solo in verticale, l'illustrazione arriva a
   620px e lascia sotto di se un vuoto che il testo puo occupare.

   Il vincolo sull'orientamento serve: un telefono coricato rientra nella
   stessa fascia di larghezza ma e alto 390px, e li risalire di 10rem
   porterebbe il testo sopra il bordo dello schermo. */
@media (min-width: 640px) and (max-width: 1024px) and (orientation: portrait) {
  /* Il testo risale dentro l'illustrazione invece di seguirla. I due
     smettono di essere due blocchi in fila e diventano una scena sola: il
     lettering si legge sopra la parte bassa del pacco, dove il fondo e
     compatto e non ruba leggibilita.

     Il livello va alzato perche la risalita da sola non basta: sovrapposti,
     a stare davanti sarebbe l'illustrazione, che viene dopo nel documento.
     Funziona senza dichiarare una posizione perche gli elementi di una
     griglia rispondono al livello anche da fermi. */
  .hero__content {
    margin-top: -10rem;
    z-index: var(--z-raised);
  }

  /* Stesso ragionamento del caso generale, conto diverso: qui il riquadro e
     tozzo — i tablet in verticale stanno tutti intorno a 3:4 — e il fascio
     va spostato piu in la per finire sull'asse. Vale per l'intera fascia
     perche dipende dalle proporzioni, che fra i tablet non cambiano. */
  .hero__decor {
    background-position: 93% center;
  }

  /* L'ombra sta sul lettering e non sull'illustrazione sotto, perche il
     problema e il contrasto fra due chiari: il lettering e bianco e passa
     sopra i nastri, che sono altrettanto chiari. Scurire attorno
     all'illustrazione non tocca quel punto — i nastri resterebbero chiari
     comunque. Scurire il bordo del lettering si: gli da un contorno che lo
     stacca da qualunque fondo si trovi ad attraversare.

     Sono due ombre e non una perche fanno due lavori distinti. La prima e
     stretta e quasi opaca: e il contorno vero, quello che separa il bianco
     dal chiaro. La seconda e larga e tenue: da profondita, e da sola non
     basterebbe perche su un fondo chiaro una sfocatura ampia si diluisce
     senza mai definire un bordo.

     `drop-shadow` e non `text-shadow`: il lettering e un'immagine, non del
     testo, quindi l'ombra deve seguire la sagoma del disegno.

     Nessuno dei quattro token di ombra e adatto: sono tarati per riquadri
     chiari su fondo bianco e qui sparirebbero. Se il trattamento verra
     esteso ad altri elementi sovrapposti, il valore va promosso a token. */
  .hero__lettering {
    filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.5))
      drop-shadow(0 8px 16px rgb(0 0 0 / 0.3));
  }

  /* ---- Le due destinazioni affiancate ----
     A colonna intera i due riquadri sono larghi 700px e ne usano meno di
     300: fra il titolo e il cerchio resta una fascia vuota che non dice
     nulla, e i due si allungano uno sotto l'altro per un'altezza che la
     fotografia sopra ha gia impegnato. Affiancandoli lo spazio inutilizzato
     diventa la seconda colonna.

     Non serve nessuna nuova misura per il cerchio: la sua regola e gia
     espressa in frazione della card, quindi dimezzando la card si dimezza
     da se. E' il vantaggio di averla legata al contenitore invece che alla
     finestra. */
  .prize__places {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Torna la spaziatura del telefono: in mezza colonna quella da tablet
     lascerebbe al titolo meno spazio del cerchio accanto. */
  .place-card {
    padding: var(--space-lg);
  }

  /* Titolo e sottotitolo scendono ciascuno di un gradino nella scala. Non
     e una riduzione a occhio: a 640px — il caso piu stretto della fascia —
     al titolo restano 116px e "FERRARESI" a questo corpo ne occupa 111.
     Il gradino sopra sforerebbe. */
  .place-card__title {
    font-size: var(--text-2xl);
  }

  .place-card__subtitle {
    font-size: var(--text-lg);
  }
}

/* --------------------------------------------------------------------------
   Media query — due colonne (oltre 1024px, oppure in orizzontale)
   -------------------------------------------------------------------------- */

/* Due condizioni alternative, perche a decidere non e la sola larghezza.

   La prima: oltre i 1024px. La soglia passa subito sopra e non subito sotto
   perche il tablet in verticale piu diffuso e largo esattamente 1024px, e a
   quella misura va servito a colonna singola.

   La seconda: in orizzontale, da 640px in su. Uno schermo coricato e basso, e
   impilare illustrazione e testo uno sull'altro chiede un'altezza che li non
   c'e — un telefono coricato ne ha 390. Affiancarli e l'unico modo di far
   stare la scena in una schermata. Il pavimento a 640px esclude i telefoni
   piu piccoli, dove due colonne sarebbero troppo strette.

   Non e una regola sulla forma del dispositivo ma sull'altezza disponibile;
   l'orientamento e solo il modo piu diretto per esprimerla. */
@media (min-width: 1025px), (min-width: 640px) and (orientation: landscape) {
  .hero {
    padding-block: var(--space-4xl);
  }

  /* Il lettering e il testo a sinistra, l'illustrazione del premio a destra */
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  }

  /* Il testo ha una colonna propria: l'asse torna a sinistra, dove il
     lettering trova il margine da cui crescere. */
  .hero__content {
    align-items: flex-start;
    text-align: left;
  }

  /* Da qui le due parti sono affiancate e non piu impilate, quindi lo scambio
     fatto per la colonna singola va disfatto: lasciato attivo manderebbe
     l'illustrazione nella prima colonna della griglia, cioe a sinistra, al
     posto del testo. */
  .hero__figure {
    order: 0;
    justify-content: flex-end;
  }

  /* Due tetti, nessuna misura imposta: l'illustrazione cresce quanto puo e si
     ferma contro il primo dei due che incontra — la larghezza della colonna
     oppure l'altezza della finestra. Quale dei due comandi dipende dalla forma
     dello schermo, ed e voluto: su schermi bassi e larghi la trattiene
     l'altezza, su schermi alti e stretti la larghezza.

     Vanno dichiarati come tetti (`max-*`) e non come misure. Con un'altezza
     imposta piu un tetto di larghezza il browser stringe la larghezza ma
     tiene l'altezza: per le immagini il rapporto viene ricalcolato solo se
     l'altra dimensione e `auto`, quindi il disegno si schiaccia. Con due
     tetti prevale il piu stretto e l'altra dimensione lo segue. */
  .hero__illustration {
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: min(72svh, 780px);
  }

  /* ---- Apertura in affiancata ----
     Con due colonne cambia chi apre. L'illustrazione non e piu sopra il
     testo ma accanto, quindi non fa piu da sipario: parte insieme al
     lettering e i due si compongono in parallelo, uno per colonna.
     I tempi sono percio piu distesi di quelli della colonna singola, dove
     invece il testo doveva aspettare. */

  .hero__illustration,
  .hero__decor {
    animation-duration: 1400ms;
  }

  /* La discesa e piu lunga e comincia prima: qui il lettering non e in coda a
     una cascata, e la prima cosa che si muove insieme all'illustrazione. */
  .hero__title {
    animation-duration: 900ms;
    animation-delay: 500ms;
  }

  /* L'ingrandimento del lettering esiste solo in affiancata: e qui che c'e la
     larghezza per contenerlo e il tempo per svolgerlo. Attacca dove finisce
     la discesa, a 1,4s, e chiude a 2,4s.
     Il valore non puo eccedere la colonna di sinistra, altrimenti il
     lettering entrerebbe nell'illustrazione. Fra 1024 e 1280px i margini
     laterali sono stretti (--space-md) e la colonna e larga rispetto al
     lettering: c'e spazio fino a ~1.46. */
  .hero__lettering {
    --intro-lettering-scale: 1.45;

    /* Cresce verso destra restando ancorato al margine sinistro del testo */
    transform-origin: left center;

    animation: intro-lettering-shrink 1000ms cubic-bezier(0.4, 0.05, 0.25, 1) 1400ms backwards;
  }

  /* Le tre parti restanti entrano mentre il lettering si sta riducendo,
     sempre a 150ms l'una dall'altra ma piu tardi: aspettano che la colonna
     accanto abbia finito di assestarsi. */
  .hero__content > .badge {
    animation-delay: 1600ms;
  }

  .hero__subtitle {
    animation-delay: 1750ms;
  }

  /* Il bottone principale segue la scala del resto dell'hero */
  .hero__content .btn {
    padding: var(--space-md) var(--space-xl);
    font-size: var(--text-xl);
    animation-delay: 1900ms;
  }

  .how__paths {
    grid-template-columns: repeat(2, 1fr);
  }

  .draw {
    padding: var(--space-3xl);
  }
}

/* --------------------------------------------------------------------------
   Media query — il premio in affiancata (>= 1025px, larghezza reale)
   -------------------------------------------------------------------------- */

/* Queste regole restano legate alla sola larghezza, senza la scorciatoia
   dell'orientamento che vale per la hero. La ragione e che le due sezioni
   chiedono cose diverse allo schermo: la hero affianca due blocchi elastici,
   che si adattano a quello che trovano; il premio affianca due riquadri che
   contengono una mappa di misura fissa, e sotto una certa larghezza il testo
   accanto non ha piu dove stare.

   In cifre, con questa disposizione: a 844px — un telefono coricato — al
   titolo resterebbero -9px, cioe la mappa da sola eccede il riquadro. */
@media (min-width: 1025px) {
  /* Le due destinazioni scavallano il bordo inferiore dell'immagine e
     sporgono al di sotto, come nel design.

     Lo scostamento dai lati e meta di quello di progetto (48px invece di 96).
     Non e una scelta di aspetto ma di capienza: dentro ciascun riquadro la
     mappa occupa 195px che non si restringono mai, e a finestra ridotta al
     titolo accanto restano meno degli 82px che servono a contenere
     "FERRARESI" su una riga. I 96px recuperati vanno tutti li.

     Con questo valore la parola sta intera da 1034px in su. Sotto quella
     misura resta stretta, ma sono nove pixel di finestra: chi ci capita ha
     ridimensionato la finestra a mano fin quasi al confine. */
  .prize__places {
    position: absolute;
    inset-inline: var(--space-2xl);
    bottom: calc(var(--space-3xl) * -1);
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-lg);
    margin-top: 0;
  }

  /* Recupera lo spazio occupato dalla parte di card che esce dall'immagine,
     altrimenti si avvicinerebbe troppo alla sezione seguente. */
  .prize__showcase {
    margin-bottom: var(--space-3xl);
  }

  /* Qui torna la fascia larga del file Figma, e qui ha una ragione che prima
     non aveva: da questa soglia le due destinazioni escono dal flusso e si
     appoggiano sopra l'immagine. La fascia bassa serve a lasciarle scavallare
     il bordo inferiore senza coprire la fotografia. */
  .prize__figure img {
    aspect-ratio: 1226 / 553;
  }
}

/* --------------------------------------------------------------------------
   Media query — schermi larghi (>= 1280px)
   -------------------------------------------------------------------------- */

@media (min-width: 1280px) {
  /* Oltre questa soglia il contenuto puo respirare di piu: il riquadro
     centrale si allarga invece di lasciare bande vuote ai lati. */
  :root {
    --container-max: 1440px;
    --container-padding: var(--space-4xl);
  }

  /* I margini laterali passano da 16 a 96px per lato: il contenuto perde
     160px e la colonna di sinistra si stringe rispetto al lettering, che
     invece continua a crescere col 30vw. Il margine per l'ingrandimento
     scende a ~1.19 nel punto peggiore (finestre oltre i 1600px). */
  .hero__lettering {
    --intro-lettering-scale: 1.18;
  }
}

/* --------------------------------------------------------------------------
   Media query — schermi molto larghi (>= 1600px)
   -------------------------------------------------------------------------- */

/* La soglia non e tonda per abitudine: e il punto oltre il quale il riquadro
   centrale ha smesso di crescere (--container-max: 1440px) e restano almeno
   80px di verde per lato. Da li in poi a trattenere il contenuto basta il
   tetto di larghezza, e i margini interni diventano spazio sprecato. */
@media (min-width: 1600px) {
  /* Solo nell'hero, e solo qui. Nelle altre sezioni i margini interni
     reggono la misura di lettura del testo, che non deve allargarsi con lo
     schermo; nell'hero invece il contenuto sono due colonne affiancate che
     dallo spazio in piu traggono vantaggio entrambe. Effetto voluto: su
     questi schermi l'hero risulta piu largo delle sezioni sottostanti. */
  .hero__inner {
    padding-inline: 0;
  }

  /* I 192px recuperati si dividono fra le due colonne: quella del lettering
     passa da ~571 a ~663px. Il margine per l'ingrandimento di apertura torna
     a ~1.38, quindi si puo alzare la scala rimasta bassa per mancanza di
     spazio. */
  .hero__lettering {
    --intro-lettering-scale: 1.35;
  }
}
