/* =====================================================================
   BRIXIA FLY — clone statico
   Palette:  verde scuro #1F2521 · oro #CDA434 · crema #EFE9DC · bianco
   Font:     Fraunces (titoli, variabile: opsz/wght/WONK) · Manrope (corpo)
   ===================================================================== */

/* =====================================================================
   FONT
   Serviti da qui, non da Google Fonts. Il foglio di stile di fonts.googleapis
   era di terza parte e bloccava il rendering: due handshake in più prima che
   comparisse una lettera. Ora i file stanno in assets/fonts/ e sono subset:
   - intervallo unicode "latin" (lo stesso che serviva Google, copre àèéìòù,
     virgolette tipografiche, — · … € ™);
   - solo gli assi che il CSS usa davvero.

   Sugli assi, tre decisioni prese misurando e non a occhio:
   - `wght` limitato a 400-700: il sito non usa altro;
   - `opsz` tenuto INTERO (9-144). È l'ottico automatico che fa sembrare
     Fraunces disegnata apposta per ogni misura, cioè il motivo per cui si usa
     Fraunces. Fissarlo risparmierebbe 10 KB e appiattirebbe display e testo;
   - `SOFT` TOLTO (fissato a 0): da solo pesava 48 KB su 108, per ammorbidire
     le grazie in una sola regola (`.statement`). Confrontate a 96px le due
     versioni sono indistinguibili. `WONK` invece resta fissato a 1, che è il
     suo valore predefinito: i glifi calligrafici non costano nulla e sono la
     metà visibile di quell'effetto.

   Da 288 KB per pagina a 81 (il corsivo lo scaricano solo index e contatti,
   le uniche due pagine che hanno testo in corsivo serif).
   Per rigenerarli: `strumenti/subset-font.py` — vedi CLAUDE.md.
   ===================================================================== */
@font-face {
  font-family: "Fraunces";
  src: url(../fonts/fraunces-latin.woff2) format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fraunces";
  src: url(../fonts/fraunces-italic-latin.woff2) format("woff2");
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Manrope";
  src: url(../fonts/manrope-latin.woff2) format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
/* Fraunces ha una e-commerciale calligrafica: un doppio occhiello chiuso. A
   misura display è il glifo più bello del font — l'h1 «Termini & Condizioni»
   la merita, ed è stato guardato prima di scrivere questa regola. A 22px però,
   schiacciata fra due B, si legge come un timbro: «B&B Coco» veniva «B⊗B Coco».
   Il glifo non manca e non è sbagliato, è il disegno; e l'asse WONK che lo
   governa è stato FISSATO a 1 nel subset (vedi il blocco qui sopra), quindi da
   CSS non si può ammorbidire.

   Questa faccia non scarica niente di nuovo: punta al file Manrope che la
   pagina ha già e lo limita alla sola U+0026. Messa PRIMA di Fraunces nella
   pila dei font si prende la e-commerciale e lascia al serif tutto il resto.
   Va usata solo sui titoli serif PICCOLI — a misura display Fraunces vince. */
@font-face {
  font-family: "E-commerciale";
  src: url(../fonts/manrope-latin.woff2) format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0026;
}

/* ----- Design tokens ----- */
:root {
  --bg-dark:    #1f2521;
  --bg-darker:  #171b18;
  --bg-dark-2:  #232a25;
  --gold:       #cda434;
  --gold-dark:  #c0a123;
  /* oro per i fondi chiari: l'oro pieno su crema si ferma a 1.9:1, questo arriva
     a 5.2:1 su crema e 6.2:1 su bianco (WCAG AA richiede 4.5:1) */
  --gold-ink:   #7a5c10;
  --cream:      #efe9dc;
  --cream-dim:  #d8d2c6;
  /* rosso degli errori dei form, in coppia come tutti i colori del sito:
     --error sui fondi scuri (7.7:1 sul verde), --error-ink sui fondi chiari
     (5.4:1 su crema, 6.4:1 su bianco). Il modulo dei contatti sta su crema,
     quindi quello che si vede di norma è il secondo. */
  --error:      #f2a2a2;
  --error-ink:  #b3261e;
  --white:      #ffffff;
  --ink:        #1a1d1b;
  --ink-soft:   #4a4f4b;
  --line:       rgba(205,164,52,.28);

  --font-serif: "Fraunces", Georgia, "Times New Roman", serif;
  --font-sans:  "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Scala tipografica fluida: sette gradini, un solo posto dove regolarli.
     Ogni titolo del sito pesca da qui — niente più clamp() sparsi nel file o nell'HTML. */
  --step-0: clamp(1rem, .94rem + .3vw, 1.2rem);       /* occhiello dell'hero */
  --step-1: clamp(1.1rem, 1.02rem + .35vw, 1.35rem);  /* lead, occhielli lunghi */
  --step-2: clamp(1.4rem, 1.25rem + .6vw,  1.9rem);   /* h3: card, chip, travel, h2 legali */
  --step-3: clamp(1.6rem, 1.35rem + 1.1vw, 2.6rem);   /* h2 secondari, statement, citazione */
  --step-4: clamp(2rem,   1.6rem + 1.7vw,  3.2rem);   /* h2 di sezione, h1 pagine legali */
  --step-5: clamp(2.4rem, 1.9rem + 2.1vw,  4rem);     /* h1 pagine interne */
  --step-6: clamp(2.8rem, 1.9rem + 4vw,    5.4rem);   /* h1 hero della home */

  --container: 1200px;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  /* 86 e non 78: il marchio dell'header è cresciuto (vedi .brand) e sotto gli
     80px la barra gli stava addosso. Ogni misura che dipende dall'altezza
     dell'header — scroll-padding, hero, aggancio delle carte, colonna sticky
     dei contatti — è scritta in funzione di questo token, quindi si regola qui
     e basta. */
  --header-h: 86px;
  --radius: 30px;
  --ease: cubic-bezier(.22,.61,.36,1);

  /* colore dell'anello di focus: scuro di default, riassegnato in oro sui fondi scuri */
  --focus: var(--gold-ink);

  /* ritmo della comparsa parola per parola — vale sia per lo statement sia per l'h1 dell'hero */
  --stagger: 38ms;   /* ritardo fra una parola e la successiva */
  --lead-in: 180ms;  /* attesa prima che parta la prima parola */

  /* spazio vuoto sopra e sotto il blocco statement — unica manopola */
  --statement-space: clamp(2.5rem, 5vw, 4rem);
}

/* ----- Reset ----- */
*,*::before,*::after { box-sizing: border-box; }
* { margin: 0; }
html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  /* clip e non hidden: `hidden` trasformerebbe il body in un contenitore di
     scorrimento e romperebbe le carte `sticky` del programma. `clip` taglia
     l'eccedenza orizzontale senza creare il contenitore. */
  overflow-x: clip;
}
img { max-width: 100%; display: block; height: auto; }
picture { display: block; }
p { text-wrap: pretty; }   /* evita l'ultima riga con una parola sola */
a { color: inherit; text-decoration: none; }
ul { list-style: none; padding: 0; }
button { font: inherit; cursor: pointer; }
/* Fraunces è variabile: 600 è un semibold reale, non il grassetto sintetico di prima.
   font-optical-sizing assottiglia le grazie nei titoli grandi e le ingrossa in quelli piccoli. */
h1,h2,h3,h4 {
  font-family: var(--font-serif); font-weight: 600;
  line-height: 1.12; letter-spacing: -.01em;
  font-optical-sizing: auto;
  text-wrap: balance;   /* distribuisce le righe invece di lasciare una parola orfana */
}

/* ----- Focus da tastiera ----- */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 3px; }
/* sui fondi scuri l'anello passa all'oro pieno, sulle schede chiare torna scuro */
.dark, .darker, .hero, .site-header, .site-footer { --focus: var(--gold); }
.card--light, .card--photo, .tessera, .sponsor__corpo { --focus: var(--gold-ink); }

/* ----- Skip link ----- */
.skip-link {
  position: fixed; top: .5rem; left: var(--gutter); z-index: 100;
  transform: translateY(-250%);
  padding: .7rem 1.2rem; border-radius: 10px;
  background: var(--gold); color: #241d05;
  font-weight: 700; font-size: .9rem;
  transition: transform .25s var(--ease);
}
.skip-link:focus { transform: none; }

/* ----- Layout helpers ----- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: clamp(4rem, 9vw, 8rem); }
.section--tight { padding-block: clamp(3rem, 6vw, 5rem); }
.dark  { background: var(--bg-dark); color: var(--cream); }
.darker { background: var(--bg-darker); color: var(--cream); }
/* .dark e .darker sono due fondi scuri diversi ma con lo stesso trattamento del testo:
   ogni regola di colore va scritta per entrambi, altrimenti su .darker resta il colore
   pensato per il fondo chiaro (era il caso di .lead e .section-head p: 2.05:1). */
.dark h1, .dark h2, .dark h3,
.darker h1, .darker h2, .darker h3 { color: var(--white); }

/* Grana finissima sulle sole sezioni scure: dà il senso della carta stampata e
   maschera il banding dei gradienti. È un'immagine tassellata, non un filtro:
   costa una rasterizzazione e basta. Non tocca body.dark delle pagine legali. */
.section.dark, .section.darker { position: relative; }
.section.dark::after, .section.darker::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.section.dark > .container, .section.darker > .container { position: relative; z-index: 1; }
.eyebrow {
  font-family: var(--font-sans);
  font-size: .8rem; font-weight: 700;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--gold-ink);   /* default = fondo chiaro */
  margin-bottom: 1.1rem; display: inline-block;
}
.dark .eyebrow, .darker .eyebrow, .hero .eyebrow { color: var(--gold); }
/* le schede chiare restano chiare anche dentro una sezione scura */
.card--light .eyebrow, .card--photo .eyebrow { color: var(--gold-ink); }
.lead { font-size: var(--step-1); line-height: 1.65; color: var(--ink-soft); }
.dark .lead, .darker .lead { color: var(--cream-dim); }
/* attacco di pagina: stesso corpo del lead ma in semibold e col nero pieno,
   perché il grigio del lead in grassetto sembrerebbe solo sporco */
.lead--strong { font-weight: 600; color: var(--ink); }
.dark .lead--strong, .darker .lead--strong { color: var(--white); }
.measure { max-width: 62ch; }
.center { text-align: center; }
.mx-auto { margin-inline: auto; }
/* Blocco di testo corrente: dà aria fra un paragrafo e l'altro senza dover
   scrivere margini nell'HTML. */
.prose p + p { margin-top: 1rem; }
/* Link dentro a un paragrafo: sottolineato (il colore da solo non basta a
   distinguerlo) e con l'oro giusto per il fondo, chiaro o scuro che sia.
   Al passaggio del mouse ingrossa il filo invece di cambiare colore. */
.link { color: var(--gold-ink); text-decoration: underline; text-underline-offset: 3px; }
.dark .link, .darker .link { color: var(--gold); }
.link:hover { text-decoration-thickness: 2px; }

/* ----- Buttons ----- */
.btn {
  /* justify-content serve quando il bottone viene stirato dal contenitore —
     nel form è una cella di griglia, quindi occupa tutta la larghezza e senza
     questa riga il testo resterebbe agganciato a un lato invece che al centro */
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .85rem 1.8rem;
  border-radius: var(--radius);
  font-weight: 700; font-size: .95rem;
  letter-spacing: .02em;
  border: 1.5px solid transparent;
  transition: transform .2s var(--ease), background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
  cursor: pointer;
}
.btn--gold { background: var(--gold); color: #241d05; }
.btn--gold:hover { background: var(--gold-dark); transform: translateY(-2px); }
.btn--ghost { background: transparent; color: var(--white); border-color: rgba(255,255,255,.55); }
.btn--ghost:hover { background: rgba(255,255,255,.08); border-color: var(--white); transform: translateY(-2px); }
/* secondario su fondo CHIARO: --ghost è bianco, sulla scheda sparirebbe */
.btn--linea { background: transparent; color: var(--ink); border-color: rgba(31,37,33,.3); }
.btn--linea:hover { background: rgba(31,37,33,.05); border-color: var(--ink); transform: translateY(-2px); }
.dark .btn--linea, .darker .btn--linea { color: var(--cream); border-color: var(--line); }
.dark .btn--linea:hover, .darker .btn--linea:hover { background: rgba(255,255,255,.06); border-color: var(--gold); }
.btn--dark { background: var(--bg-dark); color: var(--cream); }
.btn--dark:hover { background: var(--bg-darker); transform: translateY(-2px); }

/* =====================================================================
   HEADER
   ===================================================================== */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  height: var(--header-h);
  display: flex; align-items: center;
  transition: background-color .35s var(--ease), box-shadow .35s var(--ease);
}
.site-header .container { display: flex; align-items: center; justify-content: space-between; }
/* Il marchio è la sola cosa che deve restare riconoscibile anche a colpo
   d'occhio: a 1.3rem con l'angelo a 3.1rem si perdeva accanto a sei voci di
   menu larghe quasi il doppio. Sopra i 960px sta a 1.55rem con l'angelo a
   3.7rem; sotto, il blocco responsive lo riporta alla misura di prima perché
   lì lo spazio in larghezza è tutto quello che c'è. */
.brand {
  display: inline-flex; align-items: center; gap: .7rem;
  font-family: var(--font-serif); font-weight: 600;
  font-size: 1.55rem; letter-spacing: .1em; color: var(--white);
  text-transform: uppercase; white-space: nowrap;
}
.brand span { color: var(--gold); }

/* Marchio e lockup sono due <img> con il colore già scritto dentro all'SVG
   (oro il marchio, crema il lockup), non maschere CSS colorate da currentColor.
   La maschera sarebbe più elegante e in HTTP funziona, ma Chrome blocca
   mask-image su file://, e questo sito deve aprirsi anche col doppio click:
   in locale il logo sparirebbe. Header e footer sono entrambi scuri, quindi
   una tinta fissa per ciascuno basta. Serve una versione su fondo chiaro?
   Si aggiunge un file, non si torna alla maschera. */
.brand__mark { flex: none; width: 3.7rem; height: auto; }
.brand__lockup { display: block; width: 200px; max-width: 100%; height: auto; }
/* .92 e non .78: a tre quarti di opacità la fotografia sotto continuava a
   trasparire e la barra sembrava sporca invece che scura, con le voci del menu
   appoggiate su un fondo che cambiava colore riga per riga mentre si scorreva. */
.site-header.scrolled { background: rgba(23,27,24,.92); backdrop-filter: blur(14px); box-shadow: 0 1px 0 var(--line); }

/* Velo scuro in cima: finché l'header è trasparente il menu bianco appoggia
   direttamente sulla foto dell'hero, e su uno scatto luminoso sparisce.
   Si dissolve quando l'header prende il suo fondo solido. */
.site-header::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 180%;
  background: linear-gradient(180deg, rgba(10,13,11,.6), transparent);
  pointer-events: none; z-index: -1;
  transition: opacity .35s var(--ease);
}
.site-header.scrolled::before { opacity: 0; }

/* Filo d'oro di avanzamento lettura, legato allo scroll e senza una riga di JS.
   Dove le scroll-driven animation non ci sono, semplicemente non compare. */
@supports (animation-timeline: scroll()) {
  .site-header::after {
    content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
    background: var(--gold); transform: scaleX(0); transform-origin: 0 50%;
    animation-name: read-progress;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-duration: auto;
    animation-timeline: scroll(root block);
  }
  @keyframes read-progress { to { transform: scaleX(1); } }
}

.nav { display: flex; align-items: center; gap: 2rem; }
/* Il bianco all'82% è quello che faceva sembrare il menu spento: su una foto
   luminosa (chi-siamo, location) le voci non selezionate sparivano quasi.
   Al 94% restano chiaramente leggibili senza gridare più della voce corrente,
   che è comunque distinta dal filo d'oro sotto. */
.nav a {
  color: rgba(255,255,255,.94); font-weight: 600; font-size: .96rem;
  letter-spacing: .02em; position: relative; padding: .3rem 0;
  /* ombra sottilissima: non si vede su fondo scuro, ma stacca le voci quando
     l'header è ancora trasparente sopra una fotografia chiara */
  text-shadow: 0 1px 3px rgba(10,13,11,.45);
  transition: color .2s var(--ease);
}
.nav a::after {
  content: ""; position: absolute; left: 0; bottom: -2px; height: 2px; width: 0;
  background: var(--gold); transition: width .25s var(--ease);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--white); }
.nav a:hover::after, .nav a[aria-current="page"]::after { width: 100%; }

/* La coda del pannello (i due recapiti) esiste solo nel menu a tutto schermo:
   da desktop il menu è una riga di voci e non c'è posto per altro. La vesto
   nel blocco responsive, qui la spengo e basta. */
.nav__coda { display: none; }
/* Comparsa delle voci del menu a tutto schermo, una dopo l'altra. Muove solo
   il `transform`: l'opacità qui non si tocca, se no un'animazione che non parte
   lascia il menu vuoto (vedi la nota nel blocco responsive). */
@keyframes voce-entra { from { transform: translateX(1.6rem); } }

/* Il pulsante è una pastiglia e non tre righe nude: sopra al cielo chiaro degli
   hero interni le righe bianche da 2px erano il punto meno visibile di tutta la
   pagina. Il fondo velato le tiene staccate ovunque e dà anche un bersaglio
   visibile ai 44px che il pulsante già occupava. */
.nav-toggle {
  display: none; width: 44px; height: 44px; position: relative;
  border: 1px solid rgba(255,255,255,.22); border-radius: 50%;
  background: rgba(23,27,24,.45); backdrop-filter: blur(6px);
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}
.nav-toggle:hover { background: rgba(23,27,24,.8); border-color: rgba(255,255,255,.5); }
/* Le due righe esterne sono pseudo-elementi della riga di mezzo, quindi il loro
   contenitore è lei e non il pulsante: `left` va azzerato su di loro, non
   ripetuto, altrimenti scivolano di lato della stessa quota. */
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
  content: ""; position: absolute; width: 21px; height: 2px; background: var(--white);
  border-radius: 2px;
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.nav-toggle span { top: 21px; left: 11px; }
.nav-toggle span::before { top: -7px; left: 0; }
.nav-toggle span::after { top: 7px; left: 0; }
body.nav-open .nav-toggle span { background: transparent; }
body.nav-open .nav-toggle span::before { transform: translateY(7px) rotate(45deg); }
body.nav-open .nav-toggle span::after  { transform: translateY(-7px) rotate(-45deg); }

/* =====================================================================
   HERO
   ===================================================================== */
/* isolation crea uno stacking context locale: sfondo e velo restano dentro l'hero
   invece di finire dietro al body (com'era con gli z-index negativi) */
.hero {
  position: relative; isolation: isolate; overflow: hidden; min-height: 100svh;
  display: flex; align-items: center;
  color: var(--white); text-align: center;
  padding-top: var(--header-h);
}
.hero--inner { min-height: 68vh; }
.hero > .container { position: relative; z-index: 2; }
/* l'8% in più sopra e sotto è il margine di manovra della parallasse:
   senza, scorrendo si scoprirebbe il bordo dello sfondo */
.hero__bg { position: absolute; inset: -8% 0; z-index: 0; }
.hero__bg picture { display: block; width: 100%; height: 100%; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }

/* Video di sfondo: sta sopra il fermo immagine e compare in dissolvenza solo
   quando ha davvero iniziato a scorrere, così non si vede mai un buco nero. */
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 1s var(--ease);
}
.hero__video.is-playing { opacity: 1; }

/* Comando di pausa del video (WCAG 2.2.2). 44px: è anche un bersaglio touch. */
.hero__motion {
  position: absolute; z-index: 3;
  right: clamp(1rem, 3vw, 2rem); bottom: clamp(1rem, 3vw, 2rem);
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(23,27,24,.55); border: 1px solid rgba(255,255,255,.35);
  color: var(--white); backdrop-filter: blur(6px);
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}
/* Quarta volta che questo file paga la stessa trappola (dopo .nastro__lista,
   .form-success e .cookie): `display: grid` è una regola d'autore e batte
   l'[hidden] dello user agent, quindi il pulsante nasceva già acceso. Da
   telefono il video non si scarica affatto (main.js lo carica solo sopra gli
   820px), quindi restava per sempre un comando da 44px sopra all'hero che
   metteva in pausa un video che non c'era. */
.hero__motion[hidden] { display: none; }
.hero__motion:hover { background: rgba(23,27,24,.85); border-color: var(--white); }
.hero__motion svg { width: 18px; height: 18px; }
.hero__motion .hero__motion-play { display: none; }
.hero__motion.is-paused .hero__motion-pause { display: none; }
.hero__motion.is-paused .hero__motion-play { display: block; }

/* Parallasse legata allo scroll: lo sfondo resta indietro rispetto al testo.
   `exit` copre esattamente il tratto in cui l'hero esce dallo schermo. */
@supports (animation-timeline: view()) {
  .hero__bg {
    animation-name: hero-parallax;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-duration: auto;
    animation-timeline: view();
    animation-range: exit 0% exit 100%;
  }
  @keyframes hero-parallax { to { transform: translateY(8%); } }
}
/* Due strati: il velo verticale di sempre più una pozza d'ombra al centro.
   Serve perché le fotografie degli hero vanno dal quasi nero della home al
   fiume in pieno sole di chi-siamo: su quest'ultima il titolo bianco scendeva
   a 2,2:1 sull'acqua schiarita dal sole, sotto il 3:1 richiesto per il testo
   grande. La pozza scurisce solo dove cade il testo e lascia vivi i bordi. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background:
    radial-gradient(62% 58% at 50% 45%, rgba(15,18,16,.45), rgba(15,18,16,0) 72%),
    linear-gradient(180deg, rgba(23,27,24,.55) 0%, rgba(23,27,24,.35) 40%, rgba(23,27,24,.85) 100%);
}
.hero__inner { max-width: 900px; margin-inline: auto; }

/* L'occhiello dell'hero è l'unico testo piccolo del sito appoggiato su una
   fotografia. Ingrandito di un gradino e posato su una targa scura: l'oro da
   solo, sull'acqua chiara di chi-siamo, stava a 0,9:1 e nessuna tinta d'oro
   può arrivare a 4,5:1 su quei bianchi. Con la targa (e la sfocatura, che
   spegne le macchie chiare sotto) arriva a 6:1 su tutte le pagine. */
.hero .eyebrow {
  font-size: var(--step-0);
  letter-spacing: .24em;
  margin-bottom: 1.4rem;
  padding: .5rem 1.15rem;
  border: 1px solid rgba(205,164,52,.38);
  border-radius: 999px;
  background: rgba(23,27,24,.82);
  backdrop-filter: blur(10px);
}
/* tracking negativo: su un serif da display la spaziatura larga sfilaccia la parola */
.hero h1 {
  font-size: var(--step-6); font-weight: 700;
  letter-spacing: -.015em; margin-bottom: 1rem;
  --stagger: 55ms; --lead-in: 150ms;
}
.hero--inner h1 { font-size: var(--step-5); letter-spacing: -.01em; }
/* L'h1 è già in viewport al caricamento, quindi qui la comparsa è un'animazione
   (parte da sola). Nello statement è invece una transizione, innescata dallo
   scroll reveal. Nessun opacity:0 statico: se le animazioni sono disattivate
   il titolo resta semplicemente visibile. */
.hero h1 .word {
  animation: word-in .9s var(--ease) both;
  animation-delay: calc(var(--lead-in) + var(--i) * var(--stagger));
}
@keyframes word-in {
  from { opacity: 0; transform: translateY(.35em); filter: blur(8px); }
}
.hero__subtitle {
  font-size: var(--step-1); font-weight: 500;
  letter-spacing: .05em; color: var(--cream-dim); margin-bottom: .6rem;
}
.hero__sponsor { font-size: .8rem; letter-spacing: .32em; color: var(--gold); text-transform: uppercase; margin-bottom: 2.2rem; }
.hero__actions { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
.scroll-cue {
  position: absolute; bottom: 26px; left: 50%; z-index: 2; transform: translateX(-50%);
  width: 24px; height: 40px; border: 2px solid rgba(255,255,255,.5); border-radius: 14px;
}
.scroll-cue::after {
  content: ""; position: absolute; left: 50%; top: 8px; width: 4px; height: 8px; border-radius: 2px;
  background: var(--white); transform: translateX(-50%); animation: cue 1.6s var(--ease) infinite;
}
@keyframes cue { 0%{opacity:0;transform:translate(-50%,0)} 40%{opacity:1} 100%{opacity:0;transform:translate(-50%,12px)} }

/* =====================================================================
   SECTION TITLES + GRIDS
   ===================================================================== */
.section-head { max-width: 760px; margin: 0 auto clamp(2.5rem,5vw,4rem); text-align: center; }
.section-head h2 { font-size: var(--step-4); margin-bottom: 1.1rem; }
.section-head p { color: var(--ink-soft); font-size: var(--step-1); }

/* Blocco di chiusura pagina: titolo + lead + bottone, centrati.
   Sostituisce i clamp() e i margini che erano scritti inline nell'HTML. */
.cta h1 { font-size: var(--step-4); margin-bottom: 1rem; }
.cta h2 { font-size: var(--step-3); margin-bottom: 1rem; }
.cta .lead { margin-bottom: 2rem; }
/* prima sezione di una pagina senza hero (404, legali): scavalca l'header fisso */
.section--top { padding-top: calc(var(--header-h) + 5rem); }
.dark .section-head p, .darker .section-head p { color: var(--cream-dim); }

.grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Pillar / value cards */
.card {
  background: rgba(255,255,255,.03); border: 1px solid var(--line);
  border-radius: 16px; padding: 2.2rem 2rem;
  transition: transform .3s var(--ease), border-color .3s var(--ease), background-color .3s var(--ease);
}
.dark .card:hover, .darker .card:hover { transform: translateY(-6px); border-color: var(--gold); background: rgba(205,164,52,.06); }
.card--light { background: var(--white); border-color: rgba(0,0,0,.06); border-radius: 16px; box-shadow: 0 10px 30px rgba(31,37,33,.06); }
.card--light:hover { transform: translateY(-6px); box-shadow: 0 18px 44px rgba(31,37,33,.12); }
.card h3 { color: var(--gold); font-size: var(--step-2); margin-bottom: .8rem; }
.card__icon {
  width: 52px; height: 52px; margin-bottom: 1.2rem; color: var(--gold);
  display: grid; place-items: center;
}
.card__icon svg { width: 34px; height: 34px; }
/* Le icone si disegnano invece di comparire. --len è la lunghezza reale del
   tracciato e la calcola main.js; se manca — perché l'utente ha chiesto meno
   animazioni o perché il JS non gira — il fallback 0 toglie il tratteggio e
   l'icona è già intera. */
.card__icon svg :is(path, circle, line, rect, polyline, polygon) {
  stroke-dasharray: var(--len, 0);
  stroke-dashoffset: var(--len, 0);
  transition: stroke-dashoffset 1.1s var(--ease) .15s;
}
.reveal.in .card__icon svg :is(path, circle, line, rect, polyline, polygon) { stroke-dashoffset: 0; }
/* dopo .card h3, altrimenti a parità di specificità vincerebbe il titolo oro */
.card--light h3 { color: var(--ink); font-size: var(--step-2); margin: .3rem 0 .8rem; }
.card--light p  { color: var(--ink-soft); }

/* Photo card — foto in alto, titolo oro, testo (sezione "Il nostro spirito") */
.card--photo {
  --card-pad: clamp(1rem, 1.6vw, 1.4rem);   /* margine tra bordo scheda, foto e testo */
  --card-ratio: 16 / 9;                     /* proporzione della foto */
  display: flex; flex-direction: column;
  background: var(--white);
  border-color: transparent;
  border-radius: 26px;
  padding: var(--card-pad) var(--card-pad) calc(var(--card-pad) + .8rem);
  box-shadow: 0 18px 40px rgba(0,0,0,.18);
}
.dark .card--photo:hover, .darker .card--photo:hover {
  background: var(--white); border-color: transparent;
  box-shadow: 0 26px 54px rgba(0,0,0,.26);
}
.card__media { border-radius: 16px; overflow: hidden; background: var(--bg-dark-2); }
.card__media img { width: 100%; aspect-ratio: var(--card-ratio); object-fit: cover; }
.card--photo h3 {
  font-family: var(--font-serif); color: var(--gold-ink);   /* scheda bianca */
  font-size: var(--step-2);
  margin: clamp(1.4rem, 2.4vw, 2rem) 0 0;
}
/* corpo in Manrope come tutto il resto del sito: il serif resta al titolo */
.card--photo p {
  color: var(--ink-soft);
  font-size: 1.02rem; line-height: 1.65;
  margin: clamp(.9rem, 1.6vw, 1.3rem) 0 0;
}

/* Split (image + text) */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.split--reverse .split__media { order: 2; }
/* proporzione fissa: riserva lo spazio prima che la foto arrivi (niente salti di layout)
   e tiene allineate le due colonne anche con sorgenti di formato diverso */
.split__media img {
  width: 100%; border-radius: 14px; box-shadow: 0 20px 50px rgba(23,27,24,.25);
  aspect-ratio: 3 / 2; object-fit: cover;
}
.split__media--tall img { aspect-ratio: 3 / 4; }   /* foto verticali */
/* La mappa è un iframe, non un'immagine: le regole di .split__media img non lo
   toccano, quindi va vestito a parte. width:100% annulla il width="600" del
   codice di incorporamento, che altrimenti sfonda la colonna. */
.split__media--map iframe {
  display: block; width: 100%; height: auto;
  aspect-ratio: 3 / 2; border: 0;
  border-radius: 14px; box-shadow: 0 20px 50px rgba(23,27,24,.25);
}
.split h2 { font-size: var(--step-3); margin-bottom: 1.2rem; }
.split .eyebrow + h2 { margin-top: 0; }
.split p + p { margin-top: 1rem; }

/* Indice degli approfondimenti del programma: numerale fantasma dietro il testo.
   È decorativo (aria-hidden nell'HTML), serve solo a rompere la monotonia di
   sei split identici uno dopo l'altro. */
.split__text { position: relative; }
.split__text > *:not(.split__num) { position: relative; z-index: 1; }
.split__num {
  position: absolute; top: -.42em; left: -.05em; z-index: 0;
  font-family: var(--font-serif); font-weight: 600;
  font-size: clamp(4.5rem, 9vw, 7.5rem); line-height: 1;
  color: var(--gold); opacity: .12;
  pointer-events: none; user-select: none;
}

/* La foto si scopre dall'alto invece di salire in dissolvenza: il contenitore
   .reveal viene neutralizzato, altrimenti sarebbero due movimenti sovrapposti.
   Stessa tendina per la foto a tutta larghezza (.bleed). */
.split__media.reveal, .bleed.reveal { opacity: 1; transform: none; transition: none; }
.split__media.reveal img, .bleed.reveal img { clip-path: inset(0 0 100% 0); transition: clip-path 1s var(--ease); }
.split__media.reveal.in img, .bleed.reveal.in img { clip-path: inset(0 0 0 0); }

/* Racconto con il marchio in filigrana — sezione di solo testo (Chi Siamo).
   La Vittoria Alata sta dietro alla colonna, non accanto: è un timbro sulla
   carta, non un'illustrazione. Nero all'8% su crema, quindi il testo resta
   sopra i 12:1 e l'immagine è decorativa (aria-hidden nell'HTML). */
/* =====================================================================
   MANIFESTO — le due sezioni di solo testo (chi-siamo, espositori)
   Erano due muri di prosa senza un attacco: si cadeva dentro ai paragrafi
   senza occhiello né titolo, e il marchio in filigrana faceva il decoro ma
   non faceva da segno. Ora l'apertura è sempre la stessa, sulle due pagine:

     ── marchio ──        emblema fra due filetti
     prima frase          in serif display, centrata
     Ttesto testo         corpo a sinistra, con capolettera

   Il testo non è stato riscritto: la frase in evidenza è la stessa che prima
   apriva il paragrafo, promossa a display, e il capolettera cade sul primo
   paragrafo del corpo.
   ===================================================================== */
.manifesto { position: relative; overflow: hidden; }
.manifesto > .container { position: relative; z-index: 1; }

/* L'emblema: il marchio fra due filetti che sfumano verso l'esterno. Sui fondi
   chiari usa marchio-brixiafly-ink.svg (oro scuro), non quello dell'header:
   l'oro pieno su crema sta sotto ai 2:1 e il disegno sembrerebbe scolorito.
   È decorativo, quindi alt="" e aria-hidden. */
.manifesto__emblema {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(.9rem, 2.5vw, 1.6rem);
  margin-bottom: clamp(1.6rem, 3vw, 2.4rem);
}
.manifesto__emblema::before, .manifesto__emblema::after {
  content: ""; flex: 1 1 0; height: 1px; max-width: 9rem;
  background: linear-gradient(90deg, transparent, rgba(122,92,16,.45));
}
.manifesto__emblema::after { background: linear-gradient(90deg, rgba(122,92,16,.45), transparent); }
.manifesto__emblema img { flex: none; width: clamp(54px, 7vw, 76px); height: auto; }

/* La frase d'attacco: serif, centrata, un gradino sotto agli h2 di sezione —
   è un attacco, non un titolo, e infatti nell'HTML resta un <p>. */
.manifesto__attacco {
  font-family: var(--font-serif); font-weight: 600;
  font-size: var(--step-3); line-height: 1.18; letter-spacing: -.01em;
  font-optical-sizing: auto;
  text-align: center; text-wrap: balance;
  color: var(--ink);
  margin-bottom: clamp(1.8rem, 3.5vw, 2.6rem);
}
.dark .manifesto__attacco, .darker .manifesto__attacco { color: var(--white); }

/* Capolettera sul primo paragrafo del corpo. `float` e non `initial-letter`:
   quest'ultima Firefox non la conosce e la lettera resterebbe della misura del
   testo. La riga di fondo è tarata a occhio su tre righe di Manrope a 17px. */
.manifesto__corpo > p:first-of-type::first-letter {
  float: left;
  font-family: var(--font-serif); font-weight: 600;
  font-size: 3.5em; line-height: .82;
  color: var(--gold-ink);
  padding-right: .09em; margin-top: .06em;
}
.dark .manifesto__corpo > p:first-of-type::first-letter,
.darker .manifesto__corpo > p:first-of-type::first-letter { color: var(--gold); }
.manifesto__corpo p + p { margin-top: 1.4rem; }

/* La filigrana: il lockup intero, nero al 7% su crema. Era centrato sulla
   sezione, cioè esattamente dove sta la colonna di testo — l'arco con la
   scritta passava in mezzo ai primi due paragrafi e l'angelo finiva dietro al
   terzo. Un timbro che cade sopra alle righe si legge come una macchia.
   Adesso è agganciato al bordo destro e ne sborda: si vede che è tagliato di
   proposito, la parte densa (ovale, angelo, canna) resta fuori dalla colonna e
   sotto al testo passano solo le code del disegno. Va in coppia con l'emblema
   in cima, che è lo stesso marchio ma piccolo, nitido e leggibile: uno fa da
   carta, l'altro da firma. */
.manifesto__filigrana {
  position: absolute; z-index: 0;
  top: 50%; right: calc(var(--gutter) * -1); left: auto;
  width: clamp(360px, 44vw, 660px);
  transform: translateY(-50%);
  opacity: .07;
  pointer-events: none; user-select: none;
}

/* Foto a tutta larghezza in chiusura di sezione: figlia diretta di .section,
   fuori dal .container, così tocca i due bordi dello schermo. z-index 1 la
   porta sopra alla grana delle sezioni scure. */
.bleed { position: relative; z-index: 1; margin-top: clamp(2.5rem, 6vw, 4.5rem); }
.bleed img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.bleed figcaption {
  margin-top: 1.1rem; padding-inline: var(--gutter); text-align: center;
  font-family: var(--font-sans); font-size: .78rem; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase; color: var(--gold);
}
/* la didascalia arriva dopo la tendina, non insieme */
.bleed.reveal figcaption { opacity: 0; transition: opacity .8s var(--ease) .45s; }
.bleed.reveal.in figcaption { opacity: 1; }

/* =====================================================================
   MAZZO DI CARTE (programma)
   Ogni carta è `sticky` e si ferma qualche pixel più in basso della
   precedente: scorrendo, la successiva sale e copre quella prima,
   lasciandone spuntare il bordo in cima. È tutto CSS, niente JS: le carte
   non si muovono da sole, si muovono perché scorre l'utente.
   Da rispettare: nessun antenato con `overflow: hidden` sull'asse verticale,
   altrimenti lo sticky non aggancia (per questo il body usa `clip`).
   ===================================================================== */
/* Il mazzo non ha stacco né sopra né sotto: la prima carta parte dal bordo
   dell'hero e l'ultima consegna direttamente alla sezione seguente. Lo spazio
   in fondo lo dà già lo spaziatore della .deck, che è coperto dall'ultima
   carta agganciata. */
.section--deck { padding-block: 0; }
/* --peek è insieme lo scalino della pila e l'altezza del segnalibro: la parte
   di carta che resta scoperta è esattamente la sua linguetta. */
.deck { --peek: clamp(26px, 3.2vh, 32px); }
.deck__card {
  position: sticky;
  top: calc(var(--header-h) + 1rem + var(--i, 0) * var(--peek));
  /* la carta si ferma sotto la pila dei segnalibri già accumulati */
  /* Alta quanto la finestra meno la pila, e un po' meno ancora: 86svh e non
     100, così la carta non riempie lo schermo e sotto resta sempre visibile
     il taglio di quella che sta salendo. Il tetto a 640px serve alle finestre
     alte, dove la stessa formula dava carte da 870px con dentro 340px di
     testo: tutta aria attorno a due paragrafi. */
  min-height: min(calc(86svh - var(--header-h) - 7 * var(--peek)), 640px);
  /* dove atterra il salto dal segnalibro */
  scroll-margin-top: calc(var(--header-h) + 1rem);
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: clamp(1.6rem, 4vw, 4rem);
  align-content: center;
  /* In alto si lascia il posto al segnalibro; il fondo ha più aria del resto,
     così il contenuto sta nella metà alta della carta, cioè nella parte che
     resta scoperta più a lungo mentre la successiva sale da sotto. */
  padding-block: calc(var(--peek) + clamp(1.2rem, 3vw, 2.4rem)) clamp(2rem, 8vh, 4.5rem);
  /* La carta è a tutta larghezza (la .deck non è più un .container), ma il suo
     contenuto resta incolonnato come il resto del sito: il padding laterale
     vale quanto il margine che centrerebbe un .container, e sotto i 1200px
     ricade sul padding normale della carta. */
  padding-inline: max(clamp(1.8rem, 4vw, 3.5rem), (100% - var(--container)) / 2 + var(--gutter));
  border: 1px solid var(--line);
  /* niente bordi laterali: a tutta larghezza toccherebbero i due lati dello
     schermo. Restano gli angoli alti tondi, che sono la parte che si vede
     quando la carta si accatasta. */
  border-inline: 0;
  border-radius: 26px 26px 0 0;
  /* ombra rivolta verso l'alto: è la carta che sale a proiettarla su quella
     che sta coprendo, ed è ciò che rende leggibile la sovrapposizione */
  box-shadow: 0 -16px 40px rgba(23,27,24,.3);
}
/* Distanza di lettura: il tratto di scorrimento in cui una carta resta ferma
   e intera prima che arrivi la successiva. Senza, la carta dopo comincia a
   coprire nello stesso istante in cui questa si aggancia.
   Va messo come margine *sopra* alla carta seguente e non sotto a questa: il
   vincolo dello sticky sottrae alla corsa di ogni carta il suo stesso
   margin-bottom, e con 46svh sottratti le carte si sganciavano una a una
   prima della fine del mazzo, sfilando via i segnalibri già impilati. */
.deck__card + .deck__card { margin-top: 46svh; }
/* L'ultima carta non ha nessuno sotto di sé che le faccia da fondo, e una carta
   `sticky` può scorrere solo fin dove arriva il *contenuto* del contenitore,
   meno il proprio margine: per l'ottava il conto fa esattamente zero, quindi
   sfiorava la quota di aggancio e ripartiva subito verso l'alto senza mai
   fermarsi. Questo spaziatore è il pezzo di scorrimento che alle altre dà la
   carta successiva. Il padding sulla .deck non servirebbe: il vincolo guarda
   il contenuto, non il padding. */
.deck::after { content: ""; display: block; height: 46svh; }
/* lo scalino di ogni carta nella pila */
.deck__card:nth-child(1) { --i: 0; }
.deck__card:nth-child(2) { --i: 1; }
.deck__card:nth-child(3) { --i: 2; }
.deck__card:nth-child(4) { --i: 3; }
.deck__card:nth-child(5) { --i: 4; }
.deck__card:nth-child(6) { --i: 5; }
.deck__card:nth-child(7) { --i: 6; }
.deck__card:nth-child(8) { --i: 7; }

/* Segnalibro: è la linguetta che resta scoperta quando la carta finisce sotto
   la pila. Mostra sempre il nome — così la pila diventa un indice di ciò che
   si è già passato — e scopre l'icona al passaggio del mouse o col focus da
   tastiera. È un semplice <a href="#id">: nessun JS, e il salto atterra dove
   dice `scroll-margin-top`. L'icona occupa il suo spazio anche da spenta,
   altrimenti il nome ballerebbe a ogni hover. */
.deck__mark {
  position: absolute; top: 0; left: 0; right: 0;
  height: var(--peek);
  display: flex; align-items: center; gap: .5rem;
  /* allineato al contenuto della carta, non al bordo dello schermo */
  padding-inline: max(clamp(1.2rem, 3vw, 2.2rem), (100% - var(--container)) / 2 + var(--gutter));
  border-radius: 25px 25px 0 0;
  border-bottom: 1px solid var(--line);
  background-color: rgba(255,255,255,.03);
  font-family: var(--font-sans);
  font-size: .72rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--cream-dim);
  transition: background-color .25s var(--ease), color .25s var(--ease);
}
.deck__mark:hover, .deck__mark:focus-visible { background-color: rgba(205,164,52,.14); color: var(--gold); }
.deck__mark svg {
  width: 17px; height: 17px; flex: none;
  opacity: 0; transform: translateX(-5px);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
}
.deck__mark:hover svg, .deck__mark:focus-visible svg { opacity: 1; transform: none; }
/* dove il mouse non c'è (touch) l'icona non può comparire al passaggio: sta accesa */
@media (hover: none) {
  .deck__mark svg { opacity: 1; transform: none; }
}

.deck__head h2 { font-size: var(--step-3); margin-top: .2rem; }
/* Il pulsante della fisarmonica lo monta main.js solo sotto gli 820px (vedi
   RESPONSIVE), ma la spoglia sta qui, fuori dal media query, di proposito: se
   lo smontaggio non avvenisse, su desktop resterebbe un pulsante di sistema —
   riquadro grigio e font di sistema — al posto del titolo. Così invece un
   pulsante rimasto per sbaglio si legge esattamente come il titolo che era. */
.deck__toggle {
  display: block; width: 100%;
  margin: 0; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: left;
}
/* il segno +/− esiste solo dove c'è qualcosa da aprire */
.deck__segno { display: none; }
.deck__icon { display: block; width: 46px; height: 46px; margin-bottom: 1.4rem; color: var(--gold); }
.deck__icon svg { width: 100%; height: 100%; }
.deck__body {
  max-width: 62ch; align-self: center;
  font-size: var(--step-1); line-height: 1.65; color: var(--cream-dim);
}
/* slot dell'orario: oggi vuoto, il giorno che ci saranno data e ora basta
   riempirlo e la carta diventa la riga di un programma vero */
.deck__when {
  display: block; margin-bottom: .6rem;
  font-size: .82rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--cream-dim);
}


/* =====================================================================
   GALLERIA A FISARMONICA (location)
   Cinque pannelli affiancati: quello aperto si prende cinque volte lo
   spazio degli altri, che restano strisce con il solo nome scritto per il
   lungo. Si apre passandoci sopra col mouse, toccandolo o arrivandoci col
   Tab — ma lo stato è uno solo, la classe .is-open, e la mette main.js.
   Scritto in CSS con :hover e :focus-within insieme, il pannello sotto al
   mouse e quello che teneva il focus restavano aperti tutt'e due.
   Senza JS resta aperto quello che ha .is-open scritto nell'HTML: la
   sezione si legge lo stesso, semplicemente non si cambia pannello.
   ===================================================================== */
/* La galleria sta FUORI dal .container, come figlia diretta di .section: va
   da un bordo all'altro dello schermo. z-index 1 la porta sopra alla grana
   delle sezioni scure, esattamente come per .bleed. */
.gallery {
  position: relative; z-index: 1;
  /* le due proporzioni della fisarmonica: aperto vale 5, chiuso 1. Con otto
     pannelli a tutta larghezza l'aperto viene 590×780 su un portatile e
     790×780 su un monitor grande, e le strisce chiuse fra 84 e 157px.
     Alzando --open il pannello aperto si allarga ma le strisce si
     assottigliano: a 6 scendevano sotto i 90px sui portatili. */
  --open: 5;
  --shut: 1;
  --gallery-gap: 4px;
  /* Respiro laterale del testo dentro al pannello. A tutta larghezza il
     primo pannello parte dal bordo dello schermo, quindi al massimo vale
     quasi quanto il --gutter del sito (48px) e al minimo esattamente
     quanto il suo minimo: la colonna di testo non stona con il resto. */
  --gallery-pad: clamp(1.25rem, 2.6vw, 2.75rem);
  /* Larghezza che il pannello aperto avrà a corsa finita. Serve al testo:
     gliela diamo subito, così le righe non si riflettono mentre il
     pannello si allarga (l'unico difetto visibile di questo effetto).
     I due numeri seguono il numero di pannelli: 7 = pannelli - 1,
     12 = --open + 7 × --shut. Cambiando quanti sono, vanno cambiati qui.
     È in unità di container query, quindi misura la .gallery — che sta
     ferma — e non il pannello, che si sta muovendo. */
  --open-w: calc((100cqi - 7 * var(--gallery-gap)) * 5 / 12);
  container-type: inline-size;

  display: flex;
  gap: var(--gallery-gap);
  height: clamp(480px, 76svh, 780px);
  /* clip e non hidden, come il body: `hidden` farebbe di galleria e pannelli
     dei contenitori di scorrimento, e quando il Tab arriva su un titolo che
     sporge dalla striscia chiusa il browser scorrerebbe il contenitore per
     portarcelo dentro — il testo resterebbe spostato di lato per sempre. */
  overflow: clip;
}
/* isolation: la pila di z-index resta dentro al pannello (foto 0, velo 1,
   testo 2) invece di misurarsi col resto della pagina */
.gallery__panel {
  position: relative; isolation: isolate; overflow: clip;
  flex-grow: var(--shut); flex-shrink: 1; flex-basis: 0%;
  /* Obbligatorio, ed è la riga che fa esistere la fisarmonica. Un flex item
     ha `min-width: auto`, cioè non si stringe sotto la misura minima del
     suo contenuto — e dentro c'è .gallery__body, largo --open-w (~590px).
     Otto pannelli chiedevano così 4700px: se ne vedevano due e mezzo, gli
     altri finivano oltre il bordo e il ritaglio se li mangiava.
     `overflow: clip` non basta ad azzerarlo (con `hidden` sì, ma `hidden`
     qui non si può usare: vedi la nota sulla .gallery). */
  min-width: 0; min-height: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  background: var(--bg-dark-2);
  transition: flex-grow .6s var(--ease);
}
.gallery__panel.is-open { flex-grow: var(--open); }
/* il pannello aperto non è cliccabile: non c'è niente da aprire */
.gallery__panel:not(.is-open) { cursor: pointer; }

.gallery__media, .gallery__video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
}
.gallery__media img { width: 100%; height: 100%; object-fit: cover; }
/* i pannelli chiusi si spengono, l'aperto torna pieno: è ciò che fa capire
   dove si sta guardando anche prima di leggere. Vale anche per il video,
   che è fratello della foto e non figlio: senza, il pannello del video da
   chiuso resterebbe l'unico acceso. */
.gallery__media, .gallery__video { filter: brightness(.62) saturate(.85); transition: filter .6s var(--ease); }
.is-open :is(.gallery__media, .gallery__video) { filter: none; }
/* Video: sopra al fermo immagine, in dissolvenza solo quando parte davvero
   (stessa regola dell'hero, così non si vede mai un buco nero). La
   transizione va riscritta per intero, filter compreso: la scorciatoia
   cancellerebbe quella della regola qui sopra. */
.gallery__video { object-fit: cover; opacity: 0; transition: opacity .8s var(--ease), filter .6s var(--ease); }
.gallery__video.is-playing { opacity: 1; }

/* Velo scuro sotto al testo. Deve essere spesso: il tag è oro, e l'oro su
   una fotografia non arriva da nessuna parte (sta scritto in cima al file).
   Sotto a un velo all'88% l'oro è di fatto appoggiato al fondo scuro delle
   sezioni e torna sopra il 7:1; il bianco del titolo sta a 15:1. */
.gallery__panel::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top,
    rgba(15,18,16,.94) 0%, rgba(15,18,16,.88) 30%,
    rgba(15,18,16,.42) 62%, rgba(15,18,16,.06) 100%);
}

/* Il nome per il lungo sulla striscia chiusa: senza, i pannelli chiusi sono
   quattro fette di fotografia e non si capisce che cosa nascondono. */
.gallery__spine {
  position: absolute; z-index: 2;
  left: 50%; bottom: 1.4rem; translate: -50% 0;
  writing-mode: vertical-rl; rotate: 180deg;   /* si legge dal basso in su */
  white-space: nowrap;
  font-family: var(--font-sans);
  font-size: .78rem; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--gold);
  transition: opacity .25s var(--ease);
}
.is-open .gallery__spine { opacity: 0; }

.gallery__body {
  position: relative; z-index: 2;
  /* larghezza fissa, vedi --open-w. Da chiuso sborda, ma il pannello taglia. */
  width: var(--open-w);
  padding: 0 var(--gallery-pad) clamp(1.4rem, 2.8vw, 2.5rem);
  opacity: 0; transition: opacity .3s var(--ease);
}
.is-open .gallery__body { opacity: 1; transition-duration: .5s; transition-delay: .16s; }
/* le tre righe salgono una dietro l'altra; i ritardi valgono solo in apertura
   (sono scritti sotto .is-open), in chiusura se ne vanno tutte insieme */
.gallery__body > * { translate: 0 16px; transition: translate .55s var(--ease); }
.is-open .gallery__body > * { translate: none; }
.is-open .gallery__body > *:nth-child(2) { transition-delay: .07s; }
.is-open .gallery__body > *:nth-child(3) { transition-delay: .14s; }

.gallery__tag {
  display: block; margin-bottom: .7rem;
  font-family: var(--font-sans);
  font-size: .78rem; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--gold);
}
.gallery__title { font-size: var(--step-2); color: var(--white); margin-bottom: .7rem; }
/* Il comando è il titolo, non tutto il pannello: così il nome del bottone
   letto dallo screen reader è una riga e non l'intera scheda. Il tocco
   invece funziona ovunque, perché il click lo ascolta il pannello. */
.gallery__btn { background: none; border: 0; padding: 0; color: inherit; text-align: left; }
/* sul pannello già aperto non c'è niente da aprire: via anche la manina */
.is-open .gallery__btn { cursor: default; }
.gallery__text { font-size: .98rem; color: var(--cream-dim); max-width: 46ch; }

/* Stats */
.stats { display: grid; grid-template-columns: repeat(3,1fr); gap: 2rem; text-align: center; }
/* i numeri restano fuori dalla scala del testo: sono un elemento grafico a sé.
   tabular-nums dà a ogni cifra la stessa larghezza, così 2500 e 3000 non ballano. */
.stat__num {
  font-family: var(--font-serif); font-weight: 700; color: var(--gold);
  font-size: clamp(2.6rem, 6vw, 4.5rem); line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
}
.stat__label { margin-top: .6rem; font-size: .95rem; letter-spacing: .04em; color: var(--cream-dim); text-transform: uppercase; }
.stats--mini { grid-template-columns: repeat(5,1fr); gap: 1.2rem; }
.stats--mini .stat__num { font-size: clamp(1.8rem,4vw,2.8rem); }
.stats--mini .stat__label { font-size: .78rem; }

/* Event info blocks */
.eventinfo { display: grid; grid-template-columns: repeat(3,1fr); gap: 1.5rem; margin-top: 3rem; }
/* niente riquadri: tre colonne separate da un filetto oro, più leggere sulla pagina */
.eventinfo__item { border-left: 1px solid var(--line); padding: .4rem 1rem; text-align: center; }
.eventinfo__item:first-child { border-left: 0; }
.eventinfo__item h3 { color: var(--gold); font-size: var(--step-2); margin-bottom: .4rem; letter-spacing: .04em; }
.eventinfo__item p { color: var(--cream-dim); font-size: .95rem; }

/* Category chips grid (Espositori) */
.chips { display: grid; grid-template-columns: repeat(3,1fr); gap: 1.2rem; }
/* Il velo d'oro sale dal basso al passaggio del mouse. Resta volutamente una
   velatura e non un riempimento pieno: le chip non sono link, non devono
   promettere un clic che non c'è. */
.chip {
  border: 1px solid var(--line); border-radius: 14px; padding: 2rem 1.5rem; text-align: center;
  font-family: var(--font-serif); font-size: var(--step-2); color: var(--white);
  background-color: rgba(255,255,255,.02);
  background-image: linear-gradient(rgba(205,164,52,.18), rgba(205,164,52,.18));
  background-repeat: no-repeat;
  background-position: 50% 100%;
  background-size: 100% 0;
  transition: background-size .4s var(--ease), border-color .3s var(--ease), transform .3s var(--ease);
}
.chip:hover { background-size: 100% 100%; border-color: var(--gold); transform: translateY(-5px); }
.chips .chip--wide { grid-column: 2; }   /* la settima chip si centra nella griglia a tre */

/* =====================================================================
   CATEGORIE + VETRINA (Espositori)
   Le sette categorie erano sette riquadri in griglia; adesso sono un menu
   solo e la sezione seguente cambia contenuto in base a quello che scegli.
   Le due sezioni condividono lo stesso fondo scuro e la seconda non ha
   padding sopra: un pannello staccato dal suo menu non si legge come
   pannello di quel menu, si legge come un'altra sezione qualsiasi.
   ===================================================================== */
/* Le due sezioni si dividono lo spazio che di solito ne separerebbe due: il
   fondo è lo stesso, quindi non c'è nessuna cucitura da nascondere, serve solo
   aria fra il menu e il titolo del pannello. A padding pieno da entrambe le
   parti fra le due ci sarebbero sedici rem di vuoto. */
.section--cats    { padding-bottom: clamp(1.6rem, 3vw, 2.6rem); }
.section--vetrina { padding-top: clamp(1.8rem, 3.5vw, 3rem); }

/* --- Il menu --- */
.cats {
  display: flex; gap: .5rem;
  justify-content: center;
  /* con più voci di quante ne stiano in larghezza, `center` in un contenitore
     che scorre taglia via la prima: `safe` ripiega su flex-start solo lì */
  justify-content: safe center;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  /* da bordo a bordo: quando il menu scorre, incorniciarlo nel gutter farebbe
     sembrare tagliate le voci di testa e di coda */
  margin-inline: calc(var(--gutter) * -1);
  padding: .3rem var(--gutter) 1.4rem;
}
.cats::-webkit-scrollbar { display: none; }
.cats__voce {
  flex: 0 0 auto; scroll-snap-align: center;
  position: relative;
  /* 48px è il bersaglio minimo da toccare; il fianco è stretto quel tanto che
     basta perché tutte e sette le voci stiano dentro al container senza far
     scattare lo scorrimento (con la voce più lunga, "Arte e Letteratura",
     restano una ventina di pixel di margine) */
  min-height: 48px; padding: .7rem 1.2rem;
  border: 1px solid var(--line); border-radius: 999px;
  background-color: rgba(255,255,255,.03);
  color: var(--cream-dim);
  font-family: var(--font-serif); font-size: var(--step-1); font-weight: 600;
  transition: background-color .25s var(--ease), border-color .25s var(--ease), color .25s var(--ease);
}
.cats__voce:hover { border-color: var(--gold); color: var(--white); background-color: rgba(205,164,52,.10); }
/* La voce scelta non cambia solo colore: si riempie e mette una punta verso il
   pannello. Il colore da solo non basta come indicatore, e la punta è anche
   quello che lega visivamente il menu al contenuto della sezione sotto. */
.cats__voce[aria-selected="true"] {
  background-color: var(--gold); border-color: var(--gold);
  color: #241d05;   /* stesso inchiostro del bottone oro: 8.9:1 */
}
.cats__voce[aria-selected="true"]::after {
  content: ""; position: absolute; top: 100%; left: 50%; translate: -50% 0;
  border: 9px solid transparent; border-top-color: var(--gold);
}

/* --- La vetrina --- */
/* Cambiando categoria il pannello riappare da display:none, quindi l'animazione
   riparte da sola a ogni scelta: è la conferma visiva che qualcosa è cambiato.
   Il blocco reduced-motion in fondo al file la spegne insieme a tutte le altre. */
.vetrina__pan { animation: vetrina-entra .45s var(--ease) both; }
@keyframes vetrina-entra { from { opacity: 0; transform: translateY(14px); } }
/* Il testo del pannello era centrato: cinque righe piene, sfrangiate da tutt'e
   due i lati, con l'occhio costretto a ricercare l'attacco di ogni riga. Ora la
   colonna resta al centro della pagina ma il testo è allineato a sinistra, e il
   titolo scende di un gradino perché sopra ce n'è già uno più grande ("Chi trovi
   al festival"): due titoli quasi uguali uno sotto l'altro non fanno gerarchia. */
.vetrina__testo { margin-bottom: clamp(2.2rem, 4vw, 3.4rem); }
.vetrina__testo h3 {
  font-family: var(--font-serif); font-size: var(--step-2);
  color: var(--white); margin-bottom: .8rem;
  text-wrap: balance;
}
.dark .vetrina__testo p, .darker .vetrina__testo p { color: var(--cream-dim); }

/* --- Il nastro dei loghi ---
   Sta fuori dal .container, come figlia diretta della sezione, per correre da
   bordo a bordo; il z-index lo tiene sopra la grana delle sezioni scure (che è
   un ::after posizionato, e senza questa riga coprirebbe le tessere).
   Senza JS le tessere restano una griglia normale che va a capo: è il main.js
   a incolonnarle in righe, a duplicarle quanto basta e ad avviare lo scorrimento. */
.nastro {
  position: relative; z-index: 1;
  display: grid; gap: var(--nastro-gap, clamp(.7rem, 1.4vw, 1.1rem));
}
.nastro__lista {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--nastro-gap, clamp(.7rem, 1.4vw, 1.1rem));
  padding-inline: var(--gutter);
}
/* Il JS lascia la lista di partenza nel documento come sorgente e la nasconde
   con `hidden`. Senza questa riga resterebbe visibile: il display:none che il
   browser dà a [hidden] perde contro il display:flex qui sopra, che è una
   regola d'autore e non della UA. */
.nastro__lista[hidden] { display: none; }
/* Con il JS acceso ogni riga diventa una finestra e la lista dentro è il
   carrello che scorre. La sfumatura ai lati evita il taglio netto sul bordo
   dello schermo, che farebbe sembrare le tessere mozzate invece che in corsa. */
.nastro.is-live .nastro__riga {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.nastro.is-live .nastro__lista {
  flex-wrap: nowrap; justify-content: flex-start;
  width: max-content; padding-inline: 0;
  /* --giro è la durata di un ciclo, la calcola il JS sulla larghezza reale
     della riga: così tutte le righe corrono alla stessa velocità in pixel al
     secondo, indipendentemente da quante tessere hanno dentro */
  animation: nastro-scorre var(--giro, 60s) linear infinite;
}
/* Una riga sì e una no va nel verso opposto. La classe la mette main.js invece
   di pescare con :nth-child: fra i figli del nastro ci sono anche la lista
   sorgente nascosta e il tasto di pausa, e contarli falserebbe il conto. */
/* stessa specificità della regola `animation` qui sopra, e scritta dopo:
   la scorciatoia `animation` rimette animation-direction a normal, quindi una
   regola più debole non la scavalcherebbe mai */
.nastro.is-live .nastro__riga--rovescio .nastro__lista { animation-direction: reverse; }
/* Oltre al tasto, il nastro si ferma quando il puntatore ci passa sopra o quando
   il focus entra in una tessera. Non è un vezzo: da quando le tessere sono link,
   centrare col mouse un bersaglio che scorre è un esercizio di mira, e da tastiera
   sarebbe proprio impossibile leggere dove si è finiti. */
.nastro.is-paused .nastro__lista,
.nastro.is-live:hover .nastro__lista,
.nastro.is-live:focus-within .nastro__lista { animation-play-state: paused; }
/* metà esatta: il JS attacca in coda una copia identica del gruppo, quindi a
   -50% il nastro è tornato nella posizione di partenza e il salto non si vede */
@keyframes nastro-scorre { to { transform: translateX(-50%); } }

.tessera { flex: 0 0 auto; width: clamp(132px, 15vw, 168px); }
/* Il corpo della tessera è un <a> quando l'espositore ha un sito o un profilo, un
   <div> quando non ce l'ha: stessa classe, così la scheda è identica nei due casi
   e il CSS non si sdoppia.
   Le due righe sono `auto 1fr` e non due `auto`: in una riga del nastro le
   tessere sono stirate tutte all'altezza della più alta, e con due tracce
   automatiche lo spazio in più si spartiva fra le due — il riquadro
   dell'immagine si allungava e il logo, centrato dentro, saliva o scendeva di
   qualche pixel rispetto a quello della tessera accanto. Con `1fr` sulla
   seconda riga tutto l'avanzo va al nome e il riquadro resta quadrato sempre. */
.tessera__corpo {
  display: grid; grid-template-rows: auto 1fr; gap: .55rem; height: 100%;
  background: var(--white); border-radius: 16px;
  padding: .8rem .8rem .9rem;
  color: var(--ink-soft);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
a.tessera__corpo:hover, a.tessera__corpo:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(0,0,0,.35);
}
/* Il riquadro è il <picture>, non l'immagine: è lui a tenere il quadrato e a
   dare a ogni logo lo stesso margine interno. Senza, un logo quadrato a pieno
   fondo (ce ne sono, neri e bianchi) arrivava a filo del bordo della scheda
   mentre quello accanto, largo e basso, galleggiava in mezzo al vuoto: la
   stessa griglia sembrava avere tessere di due misure diverse. */
.tessera picture {
  display: grid; place-items: center;
  width: 100%; aspect-ratio: 1;
  padding: .45rem;
  border-radius: 10px;
  overflow: hidden;
}
.tessera img {
  width: 100%; height: 100%; object-fit: contain;
}
/* I ritratti riempiono il riquadro e non hanno margine: una faccia rimpicciolita
   dentro a una cornice bianca non si riconosce. */
.tessera--foto picture { padding: 0; }
.tessera--foto img { object-fit: cover; }
/* Il nome sta in nero pieno e in semibold: a .78rem in grigio era la parte meno
   leggibile della pagina, ed è l'unica cosa che dice chi è l'espositore.
   L'altezza di due righe è riservata sempre, così le tessere di una riga hanno
   tutte la stessa altezza anche quando i nomi no. */
.tessera span {
  font-size: .8rem; line-height: 1.3; text-align: center;
  font-weight: 600; color: var(--ink);
  align-self: center; min-height: 2.6em;
  /* gli handle di Instagram sono parole lunghissime senza spazi: senza questa
     riga sfondano la tessera invece di andare a capo */
  overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* Comando di pausa (WCAG 2.2.2): il nastro parte da solo e non si ferma mai,
   quindi deve esserci un modo per fermarlo. Lo mostra il JS, e solo quando
   l'animazione sta davvero girando. */
.nastro__motion {
  justify-self: center; margin-top: .4rem;
  min-height: 44px; padding: .5rem 1.1rem;
  display: inline-flex; align-items: center; gap: .5rem;
  border: 1px solid rgba(255,255,255,.35); border-radius: 999px;
  background: rgba(23,27,24,.55); color: var(--cream);
  font-size: .8rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}
.nastro__motion:hover { background: rgba(23,27,24,.9); border-color: var(--white); }
.nastro__motion svg { width: 15px; height: 15px; }
.nastro__motion .nastro__motion-play { display: none; }
.nastro.is-paused .nastro__motion .nastro__motion-pause { display: none; }
.nastro.is-paused .nastro__motion .nastro__motion-play { display: block; }

/* Statement — testo manifesto in oro con filetti sopra e sotto */
.section--statement { padding-block: var(--statement-space); }
.section--statement + .section { padding-top: 0; }   /* evita che il padding della sezione seguente si sommi */
.statement {
  font-family: var(--font-serif);
  font-style: italic;                              /* corsivo vero di Fraunces, non inclinato dal browser */
  /* Solo i glifi calligrafici. L'asse SOFT non c'è più nel file: pesava 48 KB
     su ogni pagina del sito per ammorbidire le grazie qui e in nessun altro
     posto, e a 96px la differenza non si vede. Vedi il blocco FONT in cima. */
  font-variation-settings: "WONK" 1;
  font-size: var(--step-3);
  line-height: 1.4;
  color: var(--gold);
  max-width: 52ch;
  margin-inline: auto;
}
.statement::before,
.statement::after {
  content: "";
  display: block;
  width: clamp(80px, 10vw, 128px);
  height: 1px;
  margin-inline: auto;
  background: var(--gold);
  opacity: .6;
}
/* Comparsa progressiva: i filetti si tracciano, le parole salgono a cascata.
   Il blocco non si anima come un tutt'uno (le parti hanno vita propria). */
.statement.reveal { opacity: 1; transform: none; transition: none; }
.statement::before,
.statement::after { transform: scaleX(0); transition: transform .9s var(--ease); }
.statement.in::before { transform: scaleX(1); }
.statement.in::after  { transform: scaleX(1); transition-delay: calc(var(--lead-in) + var(--words, 24) * var(--stagger)); }
/* .word è lo span che main.js crea per ogni parola, condiviso con l'h1 dell'hero */
.word { display: inline-block; }
.statement .word {
  opacity: 0;
  transform: translateY(.4em);
  filter: blur(6px);
  transition: opacity .75s var(--ease), transform .75s var(--ease), filter .75s var(--ease);
  transition-delay: calc(var(--lead-in) + var(--i) * var(--stagger));
}
.statement.in .word { opacity: 1; transform: none; filter: none; }

.statement::before { margin-bottom: clamp(1.8rem, 5vw, 2.6rem); }
.statement::after  { margin-top: clamp(1.8rem, 5vw, 2.6rem); }

/* Quote */
.quote { text-align: center; max-width: 780px; margin-inline: auto; }
.quote blockquote { font-family: var(--font-serif); font-size: var(--step-3); font-style: italic; line-height: 1.3; color: var(--white); text-wrap: balance; }
.quote cite { display: block; margin-top: 1.4rem; font-style: normal; font-weight: 600; letter-spacing: .1em; color: var(--gold); text-transform: uppercase; font-size: .9rem; }

/* =====================================================================
   CONTACT
   ===================================================================== */
/* 1.6 / .75 e non 1.2 / .8: il modulo di partecipazione ha ventitré campi, e
   in 624px stavano quasi tutti incolonnati. Con 774px ne entrano tre per riga e
   il modulo passa da 2745 a ~1800px. La colonna delle informazioni scende a
   362px e ci sta comodamente: sono quattro righe corte e due icone. */
.contact-grid { display: grid; grid-template-columns: 1.6fr .75fr; gap: clamp(2rem,5vw,4rem); align-items: start; }
.contact-grid h2 { font-size: var(--step-3); margin-bottom: .9rem; }
.contact-grid .lead { margin-bottom: 2rem; }

/* La scheda che contiene il modulo. Su crema il modulo era una fila di campi
   appoggiati sul fondo della pagina, senza un perimetro che dicesse dove
   comincia e dove finisce. Dentro alla scheda bianca il rapporto dei chiari si
   rovescia — scheda bianca, campi crema — se no sarebbero bianchi su bianco. */
.form-card {
  --field-bg: #f7f3ea;
  background: var(--white);
  border-radius: 26px;
  padding: clamp(1.4rem, 3.2vw, 2.6rem);
  box-shadow: 0 20px 50px rgba(31,37,33,.10);
}
.form { display: grid; gap: 1.3rem; }
.form .row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
/* Tre campi per riga, per i gruppi di campi corti (nome/cognome/ruolo,
   importo/modalità/data). Sotto i 560px tornano tutti in colonna, in fondo. */
.form .row--3 { grid-template-columns: repeat(3, 1fr); }
/* La riga dell'indirizzo: via, CAP e città non vogliono la stessa larghezza —
   il CAP sono cinque cifre e la via è la parte che si taglia se sta stretta. */
.form .row--largo { grid-template-columns: 2fr 1fr 1.4fr; }
/* In una riga a più colonne le etichette devono valere la stessa altezza: se
   una va a capo, il suo campo scende di una riga e la riga si sfalsa — è
   successo con «Data prevista del pagamento». Si riservano due righe e il testo
   si appoggia in basso, così un'etichetta corta resta comunque attaccata al suo
   campo e i controlli si allineano fra loro. Il campo fuori da una .row non ha
   vicini con cui allinearsi e resta com'era. */
/* `gap` e non lo spazio scritto nell'HTML: in un contenitore flex lo spazio
   fra due figli viene buttato via, e l'asterisco degli obbligatori finiva
   appiccicato all'ultima lettera («Ragione sociale o nome*»). */
.form .row > .field > label,
.form .row > .field > .field__label {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: 0 .34em; min-height: 2lh;
}
/* align-content: start è obbligatorio, non un vezzo. I due .field di una .row
   vengono stirati alla stessa altezza dalla griglia; senza questa riga lo spazio
   in più finisce dentro alle tracce automatiche del campo, e l'input del campo
   senza errore si allunga da 58 a 71px per pareggiare il vicino che il messaggio
   ce l'ha. Stesso effetto con le estensioni che infilano un'icona nel campo. */
.field { display: grid; gap: .45rem; align-content: start; }
/* Da qui in giù il modulo è scritto per il fondo CHIARO, che è quello su cui
   sta (crema), e ogni regola di colore ha la sua variante `.dark`/`.darker`
   scritta di seguito — la coppia è obbligatoria come in tutto il resto del
   file. Prima era il contrario, e infatti su crema il modulo sarebbe stato
   bianco su bianco. */
/* .field__label è l'etichetta del gruppo di pillole: non può essere una <label>
   perché non comanda un controllo solo, ma si veste come le altre. */
.field label, .field__label { font-size: .85rem; font-weight: 600; letter-spacing: .04em; color: var(--ink-soft); }
.dark .field label, .darker .field label,
.dark .field__label, .darker .field__label { color: var(--cream-dim); }
.field__req { color: var(--gold-ink); }
.dark .field__req, .darker .field__req { color: var(--gold); }
.field__opt { font-weight: 400; letter-spacing: 0; color: rgba(74,79,75,.8); }
.dark .field__opt, .darker .field__opt { color: rgba(216,210,198,.6); }
.field input, .field textarea, .field select {
  width: 100%; padding: .9rem 1rem; border-radius: 10px;
  /* il campo è bianco su crema: il bordo da solo non basta a farlo leggere
     come una cosa in cui si scrive. Dentro alla scheda bianca (.form-card) il
     rapporto si rovescia e --field-bg diventa crema, se no sarebbe bianco su
     bianco e i campi sparirebbero. */
  border: 1px solid rgba(31,37,33,.22); background: var(--field-bg, var(--white)); color: var(--ink);
  /* 1rem = 16px: sotto i 16px Safari su iOS zooma la pagina quando il campo prende il focus */
  font: inherit; font-size: 1rem;
  transition: border-color .2s var(--ease), background-color .2s var(--ease), box-shadow .2s var(--ease);
}
.dark .field input, .dark .field textarea, .dark .field select,
.darker .field input, .darker .field textarea, .darker .field select {
  border-color: var(--line); background: rgba(255,255,255,.04); color: var(--white);
}
.field textarea { min-height: 150px; resize: vertical; }
/* La freccia nativa del select è nera su fondo scuro in mezzo browser: la
   disegniamo noi. Il menu a tendina invece lo apre il sistema operativo,
   quindi le option restano chiare. */
.field select {
  padding-right: 2.8rem; cursor: pointer;
  appearance: none;
  /* freccia in oro scuro sul fondo chiaro (%237a5c10), in oro pieno su quello
     scuro: l'oro pieno su bianco sta sotto ai 2:1 e sparisce */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a5c10' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center; background-size: 16px;
}
.dark .field select, .darker .field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23cda434' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.field select option { background: var(--white); color: var(--ink); }
/* background-color e non background: la scorciatoia cancellerebbe la freccia.
   Al fuoco il campo si schiarisce e prende un alone d'oro: il solo cambio di
   bordo, dentro a un modulo lungo, non basta a dire dove si sta scrivendo. */
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: var(--gold-ink); background-color: var(--white);
  box-shadow: 0 0 0 3px rgba(122,92,16,.16);
}
.dark .field input:focus, .dark .field textarea:focus, .dark .field select:focus,
.darker .field input:focus, .darker .field textarea:focus, .darker .field select:focus {
  border-color: var(--gold); background-color: rgba(255,255,255,.07);
  box-shadow: 0 0 0 3px rgba(205,164,52,.22);
}

/* --- Scelta dell'argomento a pillole ---
   Era un <select>: su telefono voleva tre tocchi (apri, scorri, conferma) e
   non lasciava vedere le possibilità finché non lo aprivi. Le pillole sono lo
   stesso linguaggio del menu delle categorie in espositori, quindi il sito non
   impara un modo nuovo. Sotto restano sei <input type="radio">: la tastiera li
   percorre con le frecce e lo screen reader li annuncia come gruppo — è il
   contenitore ad avere role="radiogroup" e aria-labelledby.
   Il radio vero sta sopra alla pillola, trasparente e grande quanto lei: così
   il bersaglio è tutta la pillola e il clic non passa da nessun JS. */
.scelte { display: flex; flex-wrap: wrap; gap: .5rem; }
.scelta { position: relative; display: inline-flex; }
.scelta input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer; appearance: none;
}
.scelta span {
  display: inline-flex; align-items: center;
  min-height: 44px; padding: .5rem 1.1rem;
  border: 1px solid rgba(31,37,33,.22); border-radius: 999px;
  background: var(--field-bg, var(--white)); color: var(--ink-soft);
  font-size: .92rem; line-height: 1.25;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.scelta:hover span { border-color: var(--gold-ink); color: var(--ink); }
/* La scelta si riempie d'oro come la voce attiva del menu categorie: il solo
   cambio di colore del testo non basterebbe come indicatore. */
.scelta input:checked + span {
  background: var(--gold); border-color: var(--gold);
  color: #241d05; font-weight: 700;
}
/* il radio è invisibile, quindi l'anello di fuoco va disegnato sulla pillola */
.scelta input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 3px; }
/* Il rosso sulle pillole è mezzo tono più tenue di quello dei campi: qui i
   bordi da segnare sono sei invece di uno, e a piena intensità la sezione
   diventava un semaforo. Il messaggio sotto resta pieno, ed è lui l'indicatore
   che non dipende dal colore. */
.scelte.is-invalid span { border-color: rgba(179,38,30,.5); }
.dark .scelta span, .darker .scelta span {
  border-color: var(--line); background: rgba(255,255,255,.04); color: var(--cream-dim);
}
.dark .scelta:hover span, .darker .scelta:hover span { border-color: var(--gold); color: var(--white); }
.dark .scelta input:checked + span, .darker .scelta input:checked + span {
  background: var(--gold); border-color: var(--gold); color: #241d05;
}
.dark .scelte.is-invalid span, .darker .scelte.is-invalid span { border-color: var(--error); }

/* --- Le due strade ---
   Due schede-scelta che decidono quale modulo si apre. Non sono pillole come
   l'argomento: quella è una domanda dentro a un modulo, questa è la domanda che
   sceglie il modulo, e una pillola alta 44px non ha spazio per dire che cosa
   comporta ciascuna delle due. Sotto restano due radio veri, stesi trasparenti
   sopra alla scheda, esattamente come in .scelta. */
.vie { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; margin-bottom: 2rem; }
.via { position: relative; display: flex; }
.via input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer; appearance: none;
}
.via__corpo {
  display: grid; gap: .45rem; align-content: start;
  width: 100%; padding: 1.15rem 1.25rem;
  border: 1px solid rgba(31,37,33,.2); border-radius: 16px;
  background: var(--field-bg, var(--white));
  transition: border-color .2s var(--ease), background-color .2s var(--ease), box-shadow .2s var(--ease);
}
.via:hover .via__corpo { border-color: var(--gold-ink); }
/* La scheda scelta non cambia solo colore: il bordo raddoppia (box-shadow
   interno) e il titolo passa a inchiostro pieno. Il colore da solo non
   basterebbe come indicatore. */
.via input:checked + .via__corpo {
  border-color: var(--gold-ink);
  box-shadow: inset 0 0 0 1px var(--gold-ink);
  background: rgba(205,164,52,.13);
}
/* il radio è invisibile, quindi l'anello di fuoco va disegnato sulla scheda */
.via input:focus-visible + .via__corpo { outline: 2px solid var(--focus); outline-offset: 3px; }
.via__icona { width: 26px; height: 26px; color: var(--gold-ink); }
.via__tit { font-size: var(--step-1); font-weight: 700; line-height: 1.25; color: var(--ink); }
.via__testo { font-size: .88rem; line-height: 1.5; color: var(--ink-soft); }
.dark .via__corpo, .darker .via__corpo {
  border-color: var(--line); background: rgba(255,255,255,.04);
}
.dark .via:hover .via__corpo, .darker .via:hover .via__corpo { border-color: var(--gold); }
.dark .via input:checked + .via__corpo, .darker .via input:checked + .via__corpo {
  border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); background: rgba(205,164,52,.14);
}
.dark .via__icona, .darker .via__icona { color: var(--gold); }
.dark .via__tit, .darker .via__tit { color: var(--white); }
.dark .via__testo, .darker .via__testo { color: var(--cream-dim); }

/* --- Il cambio fra i due moduli ---
   Lo stato normale del pannello è VISIBILE: la comparsa è un'animazione che
   parte da opacità zero, non un'opacità zero che qualcosa deve alzare. È la
   stessa regola del menu a schermo intero — se per qualunque motivo la classe
   non arrivasse, il caso peggiore è un modulo che compare senza dissolvenza,
   non un modulo invisibile.
   Le durate sono corte di proposito: 150ms per uscire e 220 per entrare. Il
   cambio dev'essere un battito di ciglia, non un'attesa. */
.form-pannello.is-dentro { animation: pannello-entra .22s var(--ease) both; }
@keyframes pannello-entra {
  from { opacity: 0; transform: translateY(10px); }
}
.form-pannello.is-fuori {
  opacity: 0; transform: translateY(-6px);
  transition: opacity .15s var(--ease), transform .15s var(--ease);
}
/* Va riaffermato: .form è `display: grid`, una regola d'autore, e batte
   l'[hidden] dello user agent. È la quinta volta che questo file paga la
   stessa trappola (dopo .nastro__lista, .form-success, .cookie e
   .hero__motion) — e qui il danno sarebbe stato il peggiore: i due moduli
   impilati uno sull'altro, con gli id duplicati fra loro. */
.form-pannello[hidden] { display: none; }

/* --- Il modulo di partecipazione ---
   Diciannove campi di fatturazione divisi in sei gruppi numerati. Il salto fra
   un gruppo e l'altro dev'essere il doppio di quello fra due campi (1.2rem), se
   no i sei gruppi si leggono come un elenco unico. */
.form-gruppi { display: grid; gap: 2.4rem; }
.form-intro { font-size: .92rem; line-height: 1.6; color: var(--ink-soft); }
.dark .form-intro, .darker .form-intro { color: var(--cream-dim); }

/* `min-width: 0` sul fieldset non è un vezzo: il valore implicito è min-content
   e impedisce alle griglie interne di restringersi, quindi la .row a due colonne
   sfonderebbe la scheda invece di stringersi. È la stessa trappola dei pannelli
   della galleria in location. */
.form-gruppo { border: 0; margin: 0; padding: 0; min-width: 0; }
.form-gruppo legend {
  display: block; width: 100%; padding: 0; margin-bottom: 1.1rem;
  font-family: var(--font-sans);
  font-size: .78rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  /* oro scuro: il fondo qui è bianco, l'oro pieno starebbe a 2:1 */
  color: var(--gold-ink);
}
.dark .form-gruppo legend, .darker .form-gruppo legend { color: var(--gold); }

/* --- Il modulo di partecipazione a passi ---
   Ventitré campi in una schermata sola sono un muro: la barra di scorrimento
   si vede prima ancora del primo campo. Divisi in quattro passi, in pagina non
   ce ne sono mai più di sette, e gli errori si scoprono passo per passo invece
   che tutti insieme alla fine.
   Il markup dei passi lo monta `main.js` e non sta nell'HTML: senza JS il
   modulo resta uno solo, lungo ma completo e inviabile — dei pulsanti Avanti
   scritti in pagina, senza JS, non porterebbero da nessuna parte.
   La corrispondenza con il modulo cartaceo del committente resta: passo 1 =
   sezione 1, passo 2 = sezione 2, passo 3 = sezioni 3 e 4, passo 4 = sezioni
   6 e 7. I numerini nelle legende sono spariti proprio per questo: due
   numerazioni diverse una sopra l'altra non si leggono. */
.passi__barra {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: .4rem;
  list-style: none; margin: 0; padding: 0;
}
.passi__seg {
  height: 3px; border-radius: 2px;
  background: rgba(31,37,33,.14);
  transition: background-color .3s var(--ease);
}
.passi__seg.is-fatto { background: var(--gold-ink); }
.dark .passi__seg, .darker .passi__seg { background: rgba(255,255,255,.14); }
.dark .passi__seg.is-fatto, .darker .passi__seg.is-fatto { background: var(--gold); }

.form-passo { display: grid; gap: 2.4rem; }
/* La testata sta più vicina ai suoi campi di quanto due gruppi stiano fra loro:
   è un'intestazione, non un blocco a sé. Il margine negativo accorcia il gap
   della griglia solo sotto di lei. */
.form-passo__tit { margin-bottom: -1rem; }
/* Va riaffermato: la riga qui sopra è d'autore e batte l'[hidden] dello user
   agent. È la sesta volta che questo file paga la stessa trappola, dopo
   .nastro__lista, .form-success, .cookie, .hero__motion e .form-pannello — e
   qui il danno sarebbe stato tutti e quattro i passi in pagina insieme, cioè
   esattamente il muro che i passi servono a evitare. */
.form-passo[hidden] { display: none; }
.form-passo.is-dentro { animation: pannello-entra .22s var(--ease) both; }

/* La testata del passo prende il posto della legenda quando il passo contiene
   un gruppo solo: due titoli identici uno sotto l'altro non fanno gerarchia.
   Ha tabindex="-1" perché il fuoco ci si sposta a ogni cambio di passo, ed è
   così che uno screen reader annuncia dove si è finiti. */
.form-passo__tit {
  display: flex; align-items: baseline; justify-content: space-between; gap: .6rem 1.2rem;
  flex-wrap: wrap; margin: 0;
  font-family: var(--font-sans);
  font-size: .78rem; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold-ink);
}
.dark .form-passo__tit, .darker .form-passo__tit { color: var(--gold); }
.form-passo__conta {
  font-size: .8rem; font-weight: 600; letter-spacing: .02em;
  text-transform: none; color: var(--ink-soft);
}
.dark .form-passo__conta, .darker .form-passo__conta { color: var(--cream-dim); }

/* Avanti sta a destra anche quando è solo: è la convenzione, e su un passo
   senza Indietro un pulsante appiccicato a sinistra sembra fuori posto. */
.form-nav { display: flex; flex-wrap: wrap; gap: .8rem; }
.form-nav__avanti, .form-nav [type="submit"] { margin-inline-start: auto; }
.form-nav [hidden] { display: none; }
/* messaggio e consenso: fra loro il passo di un campo, non quello fra i gruppi */
.form-coda { display: grid; gap: 1.2rem; }
.form-gruppo__campi { display: grid; gap: 1.2rem; }

/* Spiegazione sotto a un campo. Sta nell'aria-describedby DOPO l'id del
   messaggio d'errore: boxErrore() legge il primo dei due. */
.field__hint { font-size: .84rem; line-height: 1.5; color: rgba(74,79,75,.85); }
.dark .field__hint, .darker .field__hint { color: var(--cream-dim); }

/* Errori: il messaggio sta sotto al campo suo, non in cima al modulo, ed è
   legato dall'aria-describedby. Il bordo rosso da solo non basterebbe —
   il colore non può essere l'unico indicatore. */
.field__error { font-size: .85rem; line-height: 1.45; color: var(--error-ink); }
.dark .field__error, .darker .field__error { color: var(--error); }
.field__error:empty { display: none; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"], .field select[aria-invalid="true"],
.consent input[aria-invalid="true"] { border-color: var(--error-ink); background-color: rgba(179,38,30,.06); }
.dark .field input[aria-invalid="true"], .dark .field textarea[aria-invalid="true"],
.dark .field select[aria-invalid="true"], .dark .consent input[aria-invalid="true"],
.darker .field input[aria-invalid="true"], .darker .field textarea[aria-invalid="true"],
.darker .field select[aria-invalid="true"], .darker .consent input[aria-invalid="true"] {
  border-color: var(--error); background-color: rgba(242,162,162,.07);
}

/* Consenso privacy — casella da 24px (il minimo di WCAG 2.5.8), ma è cliccabile
   tutta l'etichetta, quindi il bersaglio reale è molto più grande. */
.consent { display: grid; grid-template-columns: auto 1fr; gap: .7rem 1rem; align-items: start; }
.consent input {
  appearance: none; width: 24px; height: 24px; margin: .1rem 0 0;
  /* stesso fondo dei campi: dentro alla scheda bianca una casella bianca si
     riduce a un filo di bordo e non si legge più come casella */
  border: 1.5px solid rgba(31,37,33,.3); border-radius: 6px; background-color: var(--field-bg, var(--white));
  cursor: pointer;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.dark .consent input, .darker .consent input {
  border-color: var(--line); background-color: rgba(255,255,255,.04);
}
.consent input:hover { border-color: var(--gold-ink); }
.dark .consent input:hover, .darker .consent input:hover { border-color: var(--gold); }
.consent input:checked {
  background-color: var(--gold); border-color: var(--gold);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23241d05' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 15px;
}
.consent label { font-size: .92rem; line-height: 1.55; color: var(--ink-soft); cursor: pointer; }
.dark .consent label, .darker .consent label { color: var(--cream-dim); }
.consent .field__error { grid-column: 1 / -1; }

.form-note { font-size: .85rem; color: var(--ink-soft); }
.dark .form-note, .darker .form-note { color: var(--cream-dim); }
.form-success {
  display: flex; align-items: center; gap: .8rem;
  padding: 1rem 1.2rem; border-radius: 10px;
  background: rgba(122,92,16,.09); border: 1px solid var(--gold-ink); color: var(--ink);
}
.dark .form-success, .darker .form-success {
  background: rgba(205,164,52,.15); border-color: var(--gold); color: var(--white);
}
/* va riaffermato: la regola qui sopra è d'autore e batte l'[hidden] del browser,
   senza questa riga la conferma resterebbe visibile a modulo vuoto */
.form-success[hidden] { display: none; }
.form-success svg { width: 22px; height: 22px; flex: none; color: var(--gold); }

/* La colonna delle informazioni è molto più corta del modulo: da desktop resta
   agganciata mentre si scorre, invece di lasciare mezzo schermo vuoto a destra.
   Sotto gli 820px la griglia va a colonna singola e lo sganciamo (in fondo). */
/* La colonna delle informazioni è una scheda verde scuro, non testo appoggiato
   sul crema: fa da contrappeso alla scheda bianca del modulo e dà alla pagina
   l'unico punto scuro fra la citazione e il footer. Si veste da sé, come
   `.card--photo` che è sempre bianca ovunque stia, quindi qui non servono le
   varianti `.dark`/`.darker`: il fondo se lo porta dietro.
   Resta agganciata mentre si scorre — è molto più corta del modulo. */
.contact-info {
  display: grid; gap: 1.6rem;
  position: sticky; top: calc(var(--header-h) + 2rem);
  background: var(--bg-dark); color: var(--cream-dim);
  border-radius: 26px;
  padding: clamp(1.4rem, 2.6vw, 2rem);
  box-shadow: 0 20px 50px rgba(31,37,33,.16);
  --focus: var(--gold);
}
.contact-info .block h4 { font-family: var(--font-sans); font-size: .8rem; letter-spacing: .2em; text-transform: uppercase; color: var(--gold); margin-bottom: .35rem; }
.contact-info .block p, .contact-info .block a { color: var(--cream-dim); }
.contact-info .block a:hover { color: var(--white); }
.contact-info .socials a { border-color: var(--line); color: var(--cream-dim); }
.contact-info .socials a:hover { border-color: var(--gold); color: var(--gold); }

/* =====================================================================
   SEDE + COME ARRIVARE (location)
   I tre modi per arrivare stanno sotto alla mappa, nella stessa sezione:
   erano tre schede bianche in mezzo a una sezione vuota, con dentro una riga
   di testo a testa. Adesso sono tre colonne divise da un filetto d'oro — lo
   stesso trattamento di .eventinfo — appese al blocco della sede da un filetto
   orizzontale. Nessun riquadro: non sono tre cose da cliccare, sono tre righe
   di informazioni pratiche.
   ===================================================================== */
.venue__nome { font-size: var(--step-3); margin-bottom: .9rem; }
.travel {
  display: grid; grid-template-columns: repeat(3,1fr); gap: 2rem;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--line);
}
.travel__item { text-align: center; padding: .4rem 1rem; border-left: 1px solid var(--line); }
.travel__item:first-child { border-left: 0; }
.travel__item .card__icon { margin-inline: auto; margin-bottom: .9rem; }
/* sui fondi chiari anche l'icona passa all'oro scuro: l'oro pieno su crema si
   ferma sotto ai 2:1 e un tratto da 1.7px sparisce (vedi la nota su --gold-ink) */
.travel__item .card__icon { color: var(--gold-ink); }
.dark .travel__item .card__icon, .darker .travel__item .card__icon { color: var(--gold); }
.travel__item h3 { color: var(--gold-ink); font-size: var(--step-2); margin-bottom: .6rem; }
.dark .travel__item h3, .darker .travel__item h3 { color: var(--gold); }
.travel__item p { color: var(--ink-soft); font-size: .98rem; }
.dark .travel__item p, .darker .travel__item p { color: var(--cream-dim); }

/* --- Strutture convenzionate (location) ---
   Le sette strutture che fanno uno sconto agli ospiti del festival. I dati
   vengono dal PDF del committente; i link ai siti sono stati verificati uno
   per uno (quattro su sette ce l'hanno, vedi CLAUDE.md).

   Sezione .dark e non crema: la pagina arrivava al footer con sede, mappa e
   modi di arrivare tutti su fondo chiaro, e questo blocco ci si sarebbe
   sciolto dentro senza stacco. Le schede sono --bg-dark-2, un gradino sopra
   al fondo, come le carte del programma sul loro piano.

   Niente loghi nelle schede, e non per pigrizia: delle sette strutture una
   sola (Aspro) ha un logo utilizzabile su fondo chiaro, due ce l'hanno
   inservibile (uno bianco su bianco, uno che è la foto di un'insegna con
   dentro indirizzo e telefono) e quattro non ne hanno affatto. Un muro di
   loghi con un marchio su sette non è un muro di loghi. Qui contano nome,
   indirizzo e numero da chiamare, che ci sono tutti e sono verificati. */
.alloggi {
  display: grid; gap: clamp(1rem, 2vw, 1.5rem);
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  list-style: none;
}
/* auto-fill e non auto-fit: con auto-fit, quando le schede sono meno delle
   colonne disponibili, le tracce vuote collassano e le poche rimaste si
   stirano a tutta larghezza — sette schede su quattro colonne darebbero tre
   schede lunghe il doppio nell'ultima riga. Con auto-fill la griglia resta
   una griglia e l'ultima riga si allinea alla prima. */

.alloggio {
  position: relative;                    /* per il filetto, che è in assoluto */
  display: flex; flex-direction: column;
  gap: .55rem;
  padding: 1.4rem 1.3rem 1.2rem;
  background: var(--bg-dark-2);
  border: 1px solid var(--line);
  border-radius: 16px;
  transition: background-color .25s var(--ease), border-color .25s var(--ease),
              box-shadow .25s var(--ease);
}

/* --- Il fuoco sulla scheda ---
   **La scheda non è cliccabile**: cliccabili sono i tre link che ha dentro.
   Da qui discendono due assenze volute.
   - Niente `cursor: pointer`: mentirebbe. Un puntatore a mano su una superficie
     che non fa niente si clicca, e non succede nulla.
   - **Niente sollevamento.** È la scelta che distingue questa scheda dalle
     tessere degli espositori e degli sponsor, dove il `translateY(-4px)` c'è:
     lì la tessera *è* il link, quindi si muove il bersaglio insieme alla
     scheda. Qui i bersagli sono tre e stanno dentro: alzare il contenitore li
     sposterebbe sotto al puntatore, e chi entra dal bordo basso innesca il
     tremolio classico — la scheda sale, il puntatore le esce da sotto, la
     scheda ridiscende, il puntatore rientra, e via così.
   Quello che si accende è un'evidenziazione, non un pulsante: filetto d'oro che
   scende lungo il fianco, bordo pieno, fondo di un tono, pillola e icone che
   passano all'oro. **Nessuna misura cambia**, quindi nessuna riga si sposta.
   `:focus-within` accanto a `:hover` perché da tastiera si deve vedere
   esattamente la stessa cosa. */
.alloggio::before {
  content: ""; position: absolute;
  top: -1px; left: 16px; right: 16px; height: 2px;
  background: var(--gold); border-radius: 2px;
  transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease);
}
/* Il filetto corre in CIMA e non lungo il fianco, e non è una questione di
   gusto: al fianco cadeva esattamente sopra al bordo, che nello stesso momento
   passa all'oro, quindi si leggeva come un bordo più spesso invece che come un
   accento (verificato: c'era, due pixel di oro pieno, e non si vedeva). In cima
   ha tutta la larghezza della scheda per farsi notare, ed è il segno che il
   sito usa già — i filetti d'oro dello .statement, quello che regge .travel
   poche righe più su in questa stessa pagina.
   Rientra di 16px per lato, che è il raggio degli angoli: così sta nel tratto
   dritto del bordo e non deve inseguire la curva. */
.alloggio:hover, .alloggio:focus-within {
  /* --bg-dark-2 schiarito di un tono: il salto si vede senza che la scheda
     sembri un'altra superficie */
  background: #28312a;
  border-color: rgba(205,164,52,.55);
  box-shadow: 0 10px 30px rgba(0,0,0,.3);
}
.alloggio:hover::before, .alloggio:focus-within::before { transform: scaleY(1); }
/* La pillola del tipo è l'unica cosa che distingue un hotel da un B&B a
   colpo d'occhio, e il colore da solo non basterebbe: la parola c'è scritta. */
.alloggio__tipo {
  align-self: flex-start;
  padding: .22rem .6rem;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: .7rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold);
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}
.alloggio:hover .alloggio__tipo, .alloggio:focus-within .alloggio__tipo {
  background: rgba(205,164,52,.14); border-color: rgba(205,164,52,.6);
}
/* "E-commerciale" prima del serif: due strutture su sette si chiamano B&B
   (vedi la nota accanto al @font-face in cima al file) */
.alloggio__nome { font-family: "E-commerciale", var(--font-serif);
  font-size: var(--step-1); line-height: 1.25; margin: 0; }
.dark .alloggio__nome, .darker .alloggio__nome { color: var(--white); }

/* `auto` e non `1fr` sulla prima traccia: l'icona ha una misura sua e non deve
   spartirsi lo spazio col testo. `start` sull'allineamento perché su due righe
   l'icona deve restare appesa alla prima, non centrarsi sul blocco. */
.alloggio__dati { list-style: none; display: grid; gap: .5rem; margin-top: .3rem; }
.alloggio__dato { display: grid; grid-template-columns: auto 1fr; gap: .6rem; align-items: start; }
.alloggio__dato svg {
  width: 17px; height: 17px; margin-top: .18rem;
  color: rgba(205,164,52,.6); flex: 0 0 auto;
  transition: color .25s var(--ease);
}
/* decorative (aria-hidden), quindi il loro contrasto non è un requisito:
   possono permettersi di stare smorzate finché la scheda non si accende */
.alloggio:hover .alloggio__dato svg,
.alloggio:focus-within .alloggio__dato svg { color: var(--gold); }
.alloggio__dato a {
  color: var(--cream-dim); font-size: .94rem; line-height: 1.45;
  text-decoration: underline; text-decoration-color: rgba(205,164,52,.4);
  text-underline-offset: 3px;
  transition: color .2s var(--ease), text-decoration-color .2s var(--ease);
}
.alloggio__dato a:hover, .alloggio__dato a:focus-visible {
  color: var(--white); text-decoration-color: var(--gold);
}
/* Il numero non va a capo in mezzo alle cifre, e resta leggibile come numero */
.alloggio__dato--tel a { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* `margin-top: auto` incolla il link al fondo della scheda: tre strutture su
   sette non hanno un sito, quindi senza questa riga le schede con il link e
   quelle senza avrebbero il piede a due altezze diverse nella stessa riga. */
.alloggio__sito {
  margin-top: auto; padding-top: .9rem;
  display: inline-flex; align-items: center; gap: .45rem;
  min-height: 44px;                      /* bersaglio touch (WCAG 2.5.8) */
  color: var(--gold); font-weight: 600; font-size: .9rem;
  letter-spacing: .04em;
  transition: color .2s var(--ease), gap .2s var(--ease);
}
.alloggio__sito svg { width: 15px; height: 15px; }
.alloggio__sito:hover, .alloggio__sito:focus-visible { color: var(--white); gap: .75rem; }
/* La freccia si sposta, la scheda no: un transform sulla scheda sposterebbe
   anche i due link dentro, e centrare col mouse un bersaglio che si muove è
   un esercizio di mira. Stessa regola del nastro dei loghi. */

/* Senza sito il piede resta vuoto ma alto uguale, se no in una riga la scheda
   senza link finirebbe più corta e il bordo inferiore si sfalserebbe. */
.alloggio__sito--vuoto {
  margin-top: auto; padding-top: .9rem; min-height: 44px;
  display: flex; align-items: center;
  color: var(--cream-dim); font-size: .88rem; font-style: italic;
}

/* =====================================================================
   SPONSOR (solo home)
   Un nastro solo, tutti i marchi allo stesso livello e senza nome scritto
   sotto: su un muro sponsor il logo È il nome, e una riga di testo sotto a
   sei marchi già diversissimi fra loro aggiungeva solo rumore. Il nome sta
   nell'alt dell'immagine — e nell'aria-label del link, dove c'è un link.

   Sta su fondo CREMA e non scuro, per due motivi che si sommano: la home
   arrivava al footer con quattro fasce scure di fila (manifesto, pilastri,
   evento, footer), e soprattutto i marchi sono disegnati per il bianco — il
   giallo di Studio Target su crema starebbe sotto ai 2:1, esattamente come
   l'oro pieno. Da qui la targa bianca sotto a ogni logo: è lei a dare a tutti
   lo stesso fondo, non il colore della sezione. Il che vuol dire anche che
   spostare questa sezione su .dark non basta: andrebbero rigenerate le tessere.

   Come .nastro e .gallery sta FUORI dal .container, figlia diretta della
   sezione, per correre da bordo a bordo.
   ===================================================================== */
.sponsor { --sponsor-gap: clamp(.8rem, 1.6vw, 1.3rem); display: grid; }

/* Senza JS — e con reduced motion — le tessere restano la griglia centrata
   che va a capo scritta nell'HTML. Non è un ripiego: è già la forma giusta,
   e sei marchi fermi si leggono meglio di sei marchi in corsa. */
.sponsor__lista {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--sponsor-gap);
  padding-inline: var(--gutter);
}
/* Settima volta che questo file paga la stessa trappola (dopo .nastro__lista,
   .form-success, .cookie, .hero__motion, .form-pannello e .form-passo): il
   display:flex qui sopra è una regola d'autore e batte il display:none che lo
   user agent dà a [hidden]. Il JS lascia la lista di partenza nel documento
   come sorgente per le ricostruzioni al resize, e la nasconde proprio così. */
.sponsor__lista[hidden] { display: none; }

/* .is-scorre la mette main.js appena la pagina è pronta, sempre: il nastro
   scorre a ogni larghezza. C'era una versione che lo teneva fermo quando i
   marchi ci stavano tutti in riga, ed è stata tolta — sopra ai ~2100px di
   viewport si bloccava, e un carosello fermo si legge come rotto, non come una
   scelta. La nota lunga sta nel blocco sponsor di main.js. */
.sponsor.is-scorre .sponsor__pista {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.sponsor.is-scorre .sponsor__lista {
  flex-wrap: nowrap; justify-content: flex-start;
  width: max-content; padding-inline: 0;
  /* --giro è la durata di un giro, la calcola il JS sulla larghezza reale:
     a durata fissa un nastro corto sfreccerebbe e uno lungo striscerebbe */
  animation: sponsor-scorre var(--giro, 60s) linear infinite;
}
/* Il nastro si ferma col puntatore sopra e col focus dentro. Da quando le
   tessere sono link non è un vezzo: centrare col mouse un bersaglio che scorre
   è un esercizio di mira, e da tastiera non si leggerebbe dove si è finiti.
   Sono anche le uniche due pause rimaste — il tasto è stato tolto su richiesta
   del committente, vedi la nota nel blocco sponsor di main.js. */
.sponsor.is-scorre:hover .sponsor__lista,
.sponsor.is-scorre:focus-within .sponsor__lista { animation-play-state: paused; }
/* metà esatta: il JS attacca in coda una copia identica del gruppo, quindi a
   -50% il nastro è tornato al punto di partenza e il salto non si vede */
@keyframes sponsor-scorre { to { transform: translateX(-50%); } }

/* La tessera è larga il doppio dell'altezza perché l'immagine È la targa: il
   file arriva già normalizzato su una tela 600x300 da
   strumenti/tessere-sponsor.py, che rifila ogni logo e poi lo scala perché
   copra la stessa AREA degli altri. È lì che si risolve il divario di forma
   fra un gonfalone verticale (0,74:1) e un marchio lungo nove volte la sua
   altezza: lasciando fare a object-fit, la stessa riga sembrerebbe avere
   loghi di due misure diverse. Quindi la misura fissa qui non è un vezzo, è
   ciò che permette al JS di misurare il nastro prima che le foto arrivino. */
.sponsor__voce { flex: 0 0 auto; width: clamp(190px, 21vw, 280px); }
.sponsor__corpo {
  display: block; background: var(--white);
  border-radius: 14px; overflow: hidden;
  box-shadow: 0 2px 12px rgba(26,29,27,.07);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
/* Solo gli <a>: una tessera senza link non è un bersaglio e non deve muoversi
   sotto al mouse. È la stessa scelta di a.tessera__corpo. */
a.sponsor__corpo:hover, a.sponsor__corpo:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(26,29,27,.18);
}
/* aspect-ratio e non l'altezza presa dal file: se un giorno una tessera
   arrivasse con proporzioni sbagliate il riquadro resta comunque allineato
   agli altri, e il nastro non si sfalsa. */
.sponsor__corpo img { display: block; width: 100%; height: auto; aspect-ratio: 2 / 1; }
/* L'unica targa scura, ed è una deroga con una data di scadenza: il logo
   Golduck esiste in una sola versione e ha la scritta BIANCA, quindi su targa
   bianca resterebbero l'anatra e "consulting" senza il nome. Il verde è dentro
   al file; questa riga serve solo al fondo dietro all'immagine, per il momento
   in cui non è ancora arrivata — con il bianco si vedrebbe un lampo chiaro al
   posto della tessera. Si toglie, insieme alla riga nel PIANO di
   strumenti/tessere-sponsor.py, appena arriva la versione per fondi chiari.
   Il --focus NON va cambiato qui: l'anello ha outline-offset 3px, quindi si
   disegna fuori dalla targa, sulla crema della sezione — e lì l'oro pieno sta
   a 1.9:1. Vale l'oro scuro ereditato da .sponsor__corpo, come per le altre. */
.sponsor__corpo--scuro { background: var(--bg-dark); }
/* Stessa storia di Golduck, colore diverso: il marchio Peterman arriva come un
   blocco di arancione pieno con la scritta nera dentro. Lì l'arancione è la
   targa, non il marchio — lo script lo rifila e lo rimette come fondo della
   tessera (vedi rifila() in strumenti/tessere-sponsor.py). Il valore è
   campionato dal file del committente, non scelto: non è un colore del sito e
   infatti non è un token. */
.sponsor__corpo--arancio { background: #ff3900; }

/* =====================================================================
   FOOTER
   ===================================================================== */
.site-footer { background: var(--bg-darker); color: var(--cream-dim); padding-block: clamp(3rem,6vw,5rem) 2rem; border-top: 1px solid var(--line); }
.footer-top { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 2.5rem; margin-bottom: 3rem; }
/* Nel footer c'è spazio per il lockup intero, scritta compresa: lì il marchio
   da solo non servirebbe a identificare niente. */
.footer-brand .brand { display: inline-block; margin-bottom: 1rem; color: var(--cream); }
.footer-brand p { max-width: 34ch; font-size: .95rem; }
.footer-col h4 { font-family: var(--font-sans); font-size: .78rem; letter-spacing: .2em; text-transform: uppercase; color: var(--gold); margin-bottom: 1rem; }
.footer-col li { margin-bottom: .6rem; }
.footer-col a { font-size: .95rem; transition: color .2s var(--ease); }
.footer-col a:hover { color: var(--white); }
.socials { display: flex; gap: .8rem; margin-top: 1.4rem; }
.socials a { width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 50%; display: grid; place-items: center; color: var(--cream-dim); transition: all .25s var(--ease); }
.socials a:hover { border-color: var(--gold); color: var(--gold); transform: translateY(-3px); }
.socials svg { width: 18px; height: 18px; }
.footer-bottom { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; padding-top: 1.6rem; border-top: 1px solid rgba(255,255,255,.08); font-size: .85rem; }
.footer-bottom nav { display: flex; gap: 1.4rem; flex-wrap: wrap; }
.footer-bottom a:hover { color: var(--white); }
/* "Preferenze cookie" è un <button> perché riapre il banner, non porta da
   nessuna parte: qui si limita a vestirsi da link come i suoi vicini. */
.footer-pref {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: inherit; color: inherit;
}
.footer-pref:hover { color: var(--white); }

/* =====================================================================
   LEGAL PAGES
   ===================================================================== */
/* 70ch ≈ 65-75 caratteri per riga: oltre, l'occhio fatica a ritrovare il capo riga */
.legal { padding-top: calc(var(--header-h) + 4rem); max-width: 70ch; }
.legal h1 { font-size: var(--step-4); margin-bottom: 1.5rem; color: var(--white); }
.legal h2 { font-size: var(--step-2); margin: 2.2rem 0 .8rem; color: var(--gold); }
.legal p, .legal li { color: var(--cream-dim); line-height: 1.75; }
.legal h3 { font-size: var(--step-0); margin: 1.6rem 0 .5rem; color: var(--white); font-family: var(--font-sans); font-weight: 700; }
.legal table { width: 100%; border-collapse: collapse; margin: 1rem 0 1.4rem; font-size: .92rem; }
.legal th, .legal td { text-align: left; padding: .6rem .7rem; border-bottom: 1px solid var(--line); color: var(--cream-dim); vertical-align: top; }
.legal th { color: var(--white); font-family: var(--font-sans); font-size: .78rem; letter-spacing: .12em; text-transform: uppercase; }
/* le tabelle dei cookie non stanno in 360px: scorrono da sole invece di
   allargare la pagina */
.legal .tabella { overflow-x: auto; }

/* Segnaposto dei dati che solo il committente può fornire (ragione sociale,
   P.IVA, sede…). Vistoso di proposito: deve essere impossibile pubblicare
   il sito senza accorgersene. Si trovano tutti con una ricerca di "dacompletare". */
.dacompletare {
  background: rgba(255,107,107,.14); color: var(--error);
  padding: .05em .4em; border-radius: 4px;
  border-bottom: 1px dashed currentColor; font-style: normal;
}
.legal ul { list-style: disc; padding-left: 1.3rem; }
.legal li { margin-bottom: .5rem; }
.legal .updated { font-size: .85rem; color: var(--gold); letter-spacing: .1em; text-transform: uppercase; margin-bottom: 2rem; }

/* =====================================================================
   BANNER COOKIE
   Il markup lo costruisce main.js: qui c'è solo la veste. Sta in fondo
   allo schermo ma in cima al <body>, per l'ordine di tabulazione.
   ===================================================================== */
.cookie {
  position: fixed; z-index: 90;                  /* sopra all'header (50), sotto a niente */
  inset: auto 0 0 0; padding: var(--gutter);
  display: flex; justify-content: flex-start;
  animation: cookie-entra .45s var(--ease) both;
}
/* Vanno riaffermate tutt'e due: il `display` qui sopra e quello di .cookie__dettagli
   sono regole d'autore e battono l'[hidden] del browser, che è di user agent.
   Senza, il banner non si chiude e il pannello nasce già aperto. */
.cookie[hidden], .cookie__dettagli[hidden] { display: none; }
@keyframes cookie-entra { from { opacity: 0; transform: translateY(1.5rem); } }

/* Scheda stretta in basso a sinistra, non una fascia larga quanto il container.
   Il banner deve farsi notare abbastanza da essere una scelta vera, non tenere
   in ostaggio mezzo schermo: a tutta larghezza copriva i pulsanti dell'hero e
   la riga legale del footer. Così occupa un angolo e lascia leggere la pagina. */
.cookie__box {
  width: min(30rem, 100%);
  background: var(--bg-darker); color: var(--cream-dim);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 50px rgba(0,0,0,.45);
  padding: clamp(1.1rem, 2.5vw, 1.5rem);
  display: grid; gap: .75rem;
}
.cookie__tit { font-family: var(--font-serif); font-weight: 600; font-size: var(--step-1); color: var(--white); }
.cookie__tit:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.cookie__txt { font-size: .92rem; line-height: 1.55; }

.cookie__azioni { display: flex; flex-wrap: wrap; align-items: center; gap: .7rem; }

/* Accetta e Rifiuta condividono la classe apposta: stessa dimensione, stesso
   colore, stesso peso. Dare più risalto all'accettazione è il difetto per cui
   il Garante ha sanzionato di più. "Personalizza" è la terza via, non un ripiego,
   e resta un comando testuale per non fare tre bottoni identici. */
.cookie__btn {
  flex: 0 1 auto; min-height: 44px; padding: .7rem 1.6rem;
  border: 1px solid var(--gold); border-radius: 999px;
  background: var(--gold); color: #241d05;
  font-family: var(--font-sans); font-weight: 700; font-size: .95rem;
  cursor: pointer; transition: background-color .2s var(--ease), color .2s var(--ease);
}
.cookie__btn:hover { background: var(--gold-dark); border-color: var(--gold-dark); }
.cookie__btn--vuoto { background: transparent; color: var(--gold); justify-self: start; margin-top: .3rem; }
.cookie__btn--vuoto:hover { background: rgba(205,164,52,.14); border-color: var(--gold); color: var(--gold); }

.cookie__pers {
  min-height: 44px; padding: .7rem .4rem; margin-inline-start: .3rem;
  background: none; border: 0; cursor: pointer;
  color: var(--cream); font-family: var(--font-sans); font-size: .95rem;
  text-decoration: underline; text-underline-offset: 3px;
}
.cookie__pers:hover { color: var(--white); }

.cookie__dettagli {
  display: grid; gap: 1rem;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding-block: 1.1rem;
}
.cookie__riga { display: grid; gap: .3rem; }
.cookie__sw { display: inline-flex; align-items: center; gap: .6rem; cursor: pointer; }
.cookie__riga--fissa .cookie__sw { cursor: default; }
.cookie__sw input { position: absolute; opacity: 0; width: 0; height: 0; }
.cookie__leva {
  flex: none; width: 42px; height: 24px; border-radius: 999px;
  background: rgba(255,255,255,.16); border: 1px solid var(--line);
  position: relative; transition: background-color .2s var(--ease);
}
.cookie__leva::after {
  content: ""; position: absolute; inset: 2px auto 2px 2px; width: 18px;
  border-radius: 50%; background: var(--cream);
  transition: transform .2s var(--ease);
}
.cookie__sw input:checked + .cookie__leva { background: var(--gold); }
.cookie__sw input:checked + .cookie__leva::after { transform: translateX(18px); background: #241d05; }
.cookie__sw input:disabled + .cookie__leva { opacity: .55; }
.cookie__sw input:focus-visible + .cookie__leva { outline: 2px solid var(--focus); outline-offset: 3px; }
.cookie__nome { font-weight: 600; color: var(--white); font-size: .95rem; }
.cookie__desc { font-size: .88rem; line-height: 1.55; padding-inline-start: calc(42px + .6rem); }

/* =====================================================================
   SCROLL REVEAL
   ===================================================================== */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: .08s; }
.reveal[data-delay="2"] { transition-delay: .16s; }
.reveal[data-delay="3"] { transition-delay: .24s; }
.reveal[data-delay="4"] { transition-delay: .32s; }

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width: 960px) {
  /* Fra 821 e 960 la scheda del modulo è la più stretta di tutta la scala: sta
     ancora accanto alla colonna delle informazioni ma il container si è già
     ristretto, quindi scende a ~490-570px. Tre campi per riga lì diventano tre
     colonne da 135px. Sotto gli 820 la scheda va a piena larghezza e le tre
     colonne tornano (vedi il blocco seguente): questa regola segue la larghezza
     della scheda, non quella della finestra. */
  .form .row--3, .form .row--largo { grid-template-columns: 1fr 1fr; }
  .grid-4 { grid-template-columns: repeat(2,1fr); }
  .stats--mini { grid-template-columns: repeat(3,1fr); }
  .footer-top { grid-template-columns: 1fr 1fr; }
  /* Fra 820 e 960 il menu è ancora in orizzontale ma lo spazio si stringe:
     il marchio torna alla misura di prima e le voci si avvicinano, così le
     sei voci e il marchio continuano a stare su una riga sola senza che il
     menu scivoli verso il bordo. */
  .brand { font-size: 1.3rem; gap: .55rem; }
  .brand__mark { width: 3.1rem; }
  .nav { gap: 1.35rem; }
}
@media (max-width: 820px) {
  /* La barra scende da 86 a 66px. Su un telefono da 844 di altezza, 86px sono
     un decimo dello schermo occupato da una riga con dentro due cose. Essendo
     un token, tutto quello che ci si appende — hero, scroll-padding, aggancio
     delle carte, colonna sticky — segue da solo. */
  :root { --header-h: 66px; }
  .brand { font-size: 1.2rem; gap: .5rem; }
  .brand__mark { width: 2.6rem; }
  .nav-toggle { display: block; z-index: 60; }
  /* Il marchio resta sopra al pannello invece di finirci sotto: era l'unica
     cosa che identificava la pagina e a menu aperto spariva, lasciando uno
     schermo nero con sei parole in mezzo. */
  .site-header .brand { position: relative; z-index: 56; }
  /* A menu aperto la barra prende il suo fondo pieno e spegne il velo: senza,
     sopra al pannello restava una fascia più chiara larga quanto l'header. */
  body.nav-open .site-header { background: var(--bg-dark); }
  body.nav-open .site-header::before { opacity: 0; }

  /* --- Il pannello ---
     Voci grandi, centrate, senza numeri e senza filetti: era un elenco, adesso
     è un menu. Il gruppo (voci + recapiti) sta al centro dell'altezza come un
     blocco solo, così l'aria si divide sopra e sotto invece di raccogliersi
     tutta in fondo; dietro c'è il marchio in filigrana. */
  .nav {
    position: fixed; inset: 0;
    /* dvh e non solo vh: su iOS `inset: 0` misura il viewport senza la barra
       del browser, e la coda con i recapiti finiva sotto di essa. `height` con
       il fallback in vh per chi non conosce dvh; il padding in fondo rispetta
       anche la tacca dei telefoni senza tasto casa. */
    height: 100vh; height: 100dvh;
    flex-direction: column;
    justify-content: center; align-items: stretch; gap: 0;
    padding:
      calc(var(--header-h) + clamp(1rem, 3vh, 2rem))
      var(--gutter)
      calc(clamp(1rem, 3vh, 2rem) + env(safe-area-inset-bottom, 0px));
    /* non più una lastra nera piatta: è il verde del sito che degrada verso il
       fondo delle sezioni scure, cioè gli stessi due colori di tutto il resto */
    background:
      url("../img/marchio-brixiafly.svg") no-repeat center bottom -22% / 128% auto,
      linear-gradient(165deg, var(--bg-dark-2) 0%, var(--bg-dark) 45%, var(--bg-darker) 100%);
    transform: translateX(100%);
    /* visibility toglie il menu chiuso dal tab order: senza, con Tab si finiva
       dentro un menu invisibile. Il ritardo la spegne solo a scivolamento finito. */
    visibility: hidden;
    transition: transform .4s var(--ease), visibility 0s linear .4s;
    z-index: 55;
    /* se un giorno le voci non ci stessero (schermo corto, testo ingrandito),
       il pannello scorre invece di tagliarle */
    overflow-y: auto; overscroll-behavior: contain;
  }
  /* La filigrana è dentro al `background` del pannello, quindi non si può
     velare con `opacity` senza spegnere anche il degradé: ci pensa un velo
     dello stesso colore steso sopra all'immagine e sotto alle voci. */
  .nav::before {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    /* più coprente in alto, dove ci sono le voci, e più sottile in basso, dove
       c'è solo il marchio: così la filigrana si vede dove non dà fastidio */
    background: linear-gradient(165deg, rgba(35,42,37,.97) 0%, rgba(31,37,33,.95) 45%, rgba(23,27,24,.88) 100%);
  }
  body.nav-open .nav {
    transform: none; visibility: visible;
    transition: transform .4s var(--ease), visibility 0s;
  }
  body.nav-open { overflow: hidden; }   /* la pagina non scorre più dietro al menu */

  /* Le voci: grandi, centrate, niente filetti fra una e l'altra. Il bersaglio
     resta largo quanto lo schermo perché sono blocchi a piena larghezza — è il
     testo a essere centrato, non il riquadro a restringersi. */
  .nav > a {
    position: relative; z-index: 1;
    display: block; text-align: center;
    font-size: clamp(1.75rem, 8vw, 2.3rem); font-family: var(--font-serif);
    line-height: 1.1; color: var(--white); text-shadow: none;
    padding: clamp(.45rem, 1.5vh, .85rem) .1rem;
  }
  /* Senza filetti, la voce corrente si segna con l'oro e un trattino corto
     sotto, centrato: il filo lungo quanto lo schermo tornerebbe a fare la
     riga di una tabella. Il colore da solo non basta come indicatore. */
  .nav > a::after {
    left: 50%; translate: -50% 0; bottom: .1rem;
    width: 0; height: 2px;
  }
  .nav > a:hover::after, .nav > a[aria-current="page"]::after { width: 2.4rem; }
  .nav > a[aria-current="page"] { color: var(--gold); }

  /* Le voci entrano una dopo l'altra quando il pannello si apre.
     **Si muove solo il `transform`, non l'opacità**: un'animazione con
     `fill: both` e un ritardo tiene l'elemento nello stato iniziale finché non
     parte, quindi se per qualunque motivo non partisse — un browser che la
     salta, una scheda in secondo piano — le voci resterebbero invisibili e il
     menu sarebbe vuoto. È già successo. Animando solo lo scivolamento, il caso
     peggiore è una voce spostata di un centimetro: si legge comunque. */
  body.nav-open .nav > a { animation: voce-entra .4s var(--ease) both; }
  /* Il selettore va ripetuto per intero, non accorciato a `.nav > a:nth-...`:
     la scorciatoia `animation` qui sopra rimette `animation-delay` a 0 ed è più
     specifica, quindi una regola più debole non la scavalcherebbe mai e le sei
     voci entrerebbero tutte insieme. È la stessa trappola del nastro dei loghi
     in espositori. */
  body.nav-open .nav > a:nth-of-type(1) { animation-delay: .06s; }
  body.nav-open .nav > a:nth-of-type(2) { animation-delay: .11s; }
  body.nav-open .nav > a:nth-of-type(3) { animation-delay: .16s; }
  body.nav-open .nav > a:nth-of-type(4) { animation-delay: .21s; }
  body.nav-open .nav > a:nth-of-type(5) { animation-delay: .26s; }
  body.nav-open .nav > a:nth-of-type(6) { animation-delay: .31s; }

  /* Coda del pannello: chiude la colonna e dà al menu un'azione, non solo sei
     rimandi. Da telefono "scrivi" e "chiama" sono l'azione più probabile di
     tutto il menu, e qui costano un tocco. L'email è la pillola d'oro, il
     telefono resta un link: due bottoni identici non farebbero scegliere. */
  .nav__coda {
    position: relative; z-index: 1;
    margin-top: clamp(1.4rem, 4.5vh, 2.6rem);
    display: grid; justify-items: center; gap: .35rem;
  }
  .nav__coda span {
    font-family: var(--font-sans); font-size: .7rem; font-weight: 700;
    letter-spacing: .24em; text-transform: uppercase; color: var(--gold);
    margin-bottom: .35rem;
  }
  /* la pillola si veste da sé invece di prendersi la classe .btn: il markup del
     menu è duplicato in dieci file, meglio tenercelo minimo */
  .nav__coda a[href^="mailto"] {
    display: inline-flex; align-items: center; min-height: 48px;
    padding: .7rem 1.7rem; border-radius: 999px;
    background: var(--gold); color: #241d05;
    font-family: var(--font-sans); font-weight: 700; font-size: .95rem;
    text-shadow: none;
    transition: background-color .2s var(--ease);
  }
  .nav__coda a[href^="mailto"]:hover { background: var(--gold-dark); }
  .nav__coda a[href^="tel"] {
    display: inline-flex; align-items: center; min-height: 44px;
    font-size: 1rem; color: var(--cream-dim); text-shadow: none;
  }
  .nav__coda a[href^="tel"]:hover { color: var(--white); }
  .nav__coda a::after { display: none; }   /* niente filo d'oro: non sono voci di menu */
  .split, .contact-grid { grid-template-columns: 1fr; }
  .contact-info { position: static; }   /* in colonna singola non deve appiccicarsi */
  /* la scheda ha ripreso tutta la larghezza del container: le tre colonne ci
     stanno di nuovo, e annullano la regola del blocco 960 qui sopra */
  .form .row--3 { grid-template-columns: repeat(3, 1fr); }
  .form .row--largo { grid-template-columns: 2fr 1fr 1.4fr; }
  /* --- Il mazzo su schermo stretto: una fisarmonica ---
     La pila non si può tenere (otto schermate piene sarebbero otto schermate
     quasi vuote), ma scioglierla in otto carte in colonna buttava via proprio
     ciò che la rende utile: su desktop i segnalibri si accatastano e diventano
     l'indice di dove sei e di cosa hai già passato, su mobile restavano otto
     cassoni scuri indistinguibili — 5177px, il 73% della pagina.
     Qui le otto attività diventano righe richiudibili: chiuse stanno tutte in
     una schermata, cioè la vista d'insieme che al mazzo sciolto mancava, e il
     testo si apre al tocco. È lo stesso patto della galleria di location, e
     infatti il comando è fatto allo stesso modo: il titolo, non la riga.
     Il markup lo rimaneggia main.js e solo qui: da 821px in su la carta resta
     la carta del mazzo, con tutto il testo in chiaro. */
  .deck { display: grid; gap: 0; }
  /* lo spaziatore dell'ultima carta serve solo alla pila: qui sarebbe mezzo
     schermo di vuoto in fondo (e per giunta una riga della griglia) */
  .deck::after { display: none; }
  /* relative e non static: lo sticky si spegne lo stesso, ma la carta resta il
     riferimento di ciò che le sta dentro in posizione assoluta */
  .deck__card, .deck__card + .deck__card {
    position: relative; min-height: 0; margin-block: 0;
    /* `top` va azzerato: da relative non aggancia più niente, sposta e basta,
       e ogni carta scivolerebbe in basso della sua quota nella pila (fino a
       296px), sovrapponendosi alla sezione dopo. */
    top: auto;
    grid-template-columns: 1fr;
    gap: 0;
    /* Via il cassone: niente fondo (lo dà la sezione `darker`), niente angoli
       tondi, niente ombra. Fra una riga e l'altra resta il filetto, che è ciò
       che rende leggibile una fisarmonica. Il fondo va spento a mano: la carta
       porta anche la classe `dark`, che gliene assegna uno. */
    background: none;
    border: 0; border-top: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
    padding-block: 0;
    padding-inline: var(--gutter);
    scroll-margin-top: calc(var(--header-h) + .4rem);
  }
  /* il primo filetto cadrebbe a filo dell'hero, dove c'è già uno stacco */
  .deck__card:first-child { border-top: 0; }
  /* Il nome dell'attività ora è l'etichetta della riga, che se lo prende da
     qui: il segnalibro come linguetta non ha più senso senza la pila. Sparendo
     esce anche dall'ordine di tabulazione, e con lui il suo <a> che puntava
     alla carta su cui si trovava già. */
  .deck__mark { display: none; }

  /* La riga: icona, nome, segno. Il comando è il titolo — un <button> attorno
     all'intera riga avrebbe come nome accessibile icona, nome e segno di fila,
     ed è la stessa ragione per cui nella galleria di location il pulsante è
     l'<h3>. Il tocco funziona comunque su tutta la riga: il click lo ascolta
     anche la testata. */
  .deck__head {
    display: flex; align-items: center; gap: .85rem; margin: 0;
  }
  .deck__icon { width: 24px; height: 24px; margin: 0; flex: none; }
  .deck__head h2 { flex: 1; margin: 0; font-size: var(--step-1); }
  .deck__toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    min-height: 64px;   /* bersaglio touch abbondante */
    cursor: pointer;
    transition: color .2s var(--ease);
  }
  .deck__toggle[aria-expanded="true"] { color: var(--gold); }
  /* Il segno: una croce che perde la stanghetta verticale e diventa un meno.
     Non è l'unico indicatore — c'è anche `aria-expanded` per chi non vede il
     segno, e il colore del titolo che passa all'oro. */
  .deck__segno { display: block; position: relative; width: 15px; height: 15px; flex: none; }
  .deck__segno::before, .deck__segno::after {
    content: ""; position: absolute; top: 50%; left: 0; right: 0; height: 1.5px;
    background: var(--gold); translate: 0 -50%;
    transition: opacity .25s var(--ease), rotate .25s var(--ease);
  }
  .deck__segno::after { rotate: 90deg; }
  .deck__toggle[aria-expanded="true"] .deck__segno::after { rotate: 0deg; opacity: 0; }

  /* Il titolo lungo non sta nella riga chiusa: lì ci va il nome breve, che
     tiene la riga su una riga sola. Ricompare aprendo, in cima al testo. */
  .deck__titolo {
    font-family: var(--font-serif); font-size: var(--step-2);
    line-height: 1.15; color: var(--white); margin-bottom: .8rem;
  }
  .deck__body { padding-bottom: 1.9rem; }
  /* La riga chiusa. Sta qui dentro e non fuori: è la riga che rende innocuo
     uno smontaggio mancato — sopra gli 820px `.is-chiusa` non nasconde niente
     e il testo c'è tutto comunque. */
  .deck__card.is-chiusa .deck__body { display: none; }
  /* La fisarmonica non si scioglie, si gira di 90°: otto strisce da 57px su
     un telefono non sarebbero né guardabili né toccabili, mentre in colonna
     il pannello aperto resta grande e i sette chiusi diventano linguette da
     toccare. È lo stesso componente, stessa classe .is-open, altro asse.
     Le tre misure qui sotto sono legate fra loro: con otto pannelli e
     --open a 7, la linguetta chiusa va da 46px (galleria a 660) a 58px
     (galleria a 840) — sempre sopra i 44px del bersaglio touch — e il
     pannello aperto da 319 a 410px, che bastano a foto e testo. */
  .gallery {
    flex-direction: column;
    height: clamp(660px, 88svh, 840px);
    --open: 7;
    --gallery-gap: 3px;
    --open-w: 100%;   /* in colonna il pannello è già largo quanto la galleria */
  }
  .gallery__spine {
    writing-mode: horizontal-tb; rotate: none;
    left: var(--gallery-pad); bottom: auto; top: 50%; translate: 0 -50%;
  }
  /* Su schermo stretto non c'è un "fianco destro" dove mettere il timbro: torna
     centrato e sbordante da tutt'e due i lati, ma più tenue, perché lì la
     colonna occupa tutta la larghezza e ci passa comunque sopra. */
  .manifesto__filigrana {
    top: 50%; left: 50%; right: auto;
    width: clamp(340px, 115vw, 880px);
    transform: translate(-50%, -50%);
    opacity: .05;
  }
  /* il capolettera scende a due righe e mezzo: a 3.5em, su una colonna stretta,
     si mangiava metà della prima riga di testo */
  .manifesto__corpo > p:first-of-type::first-letter { font-size: 2.9em; }
  .split--reverse .split__media { order: 0; }
  .grid-2, .grid-3, .grid-4, .chips, .travel, .eventinfo, .stats { grid-template-columns: 1fr; }
  .grid-3, .chips { grid-template-columns: 1fr 1fr; }
  .stats { grid-template-columns: 1fr 1fr; }
  .chips .chip--wide { grid-column: 1 / -1; }
  /* in colonna il filetto passa da sinistra a sopra */
  .eventinfo__item, .travel__item { border-left: 0; border-top: 1px solid var(--line); padding-top: 1.2rem; }
  .eventinfo__item:first-child, .travel__item:first-child { border-top: 0; }
  /* In riga il testo centrato sotto ogni filetto verticale è giusto; in colonna
     no: le tre voci finivano incolonnate al centro fra l'occhiello, il titolo e
     la lead a sinistra sopra, e l'indirizzo col pulsante a sinistra sotto —
     tre isole centrate in mezzo a un blocco allineato a sinistra. Il padding
     laterale se ne va con loro, se no la prima riga risulta rientrata di 1rem
     rispetto al testo che le sta sopra.
     .travel__item resta centrato di proposito: lì sopra a ogni voce c'è
     l'icona, anch'essa centrata, e insieme fanno una fascia deliberata. */
  .eventinfo__item { text-align: left; padding-inline: 0; }
  /* i tre modi per arrivare restano in colonna singola anche qui: su due
     colonne l'ultimo resterebbe spaiato sotto agli altri due */
  .travel { gap: 1.4rem; }
}
/* Bersagli touch: su schermo tattile un link deve arrivare a 44px, da mouse no.
   Con (pointer: coarse) la correzione vale dove serve senza slabbrare il footer
   sul desktop. */
@media (pointer: coarse) {
  .footer-col a, .footer-bottom nav a, .footer-pref { display: inline-flex; align-items: center; min-height: 44px; }
  .footer-col li { margin-bottom: 0; }
}

@media (max-width: 560px) {
  .grid-3, .chips, .travel, .stats, .stats--mini, .eventinfo { grid-template-columns: 1fr; }
  /* il 16:9 su schermo stretto diventa una striscia di 220px: la foto della
     sala si taglia ai lati e recupera altezza */
  .bleed img { aspect-ratio: 4 / 3; }
  .form .row, .form .row--3, .form .row--largo { grid-template-columns: 1fr; }
  /* in colonna singola non c'è nessuno con cui allinearsi: due righe riservate
     per ogni etichetta sarebbero solo vuoto */
  .form .row > .field > label,
  .form .row > .field > .field__label { display: block; min-height: 0; }
  /* affiancate sarebbero due colonne da 155px: il titolo andrebbe a capo
     due volte e la descrizione tre */
  .vie { grid-template-columns: 1fr; }
  .footer-top { grid-template-columns: 1fr; }
  /* i tre comandi del banner in fila non ci stanno: a colonna piena restano
     bersagli larghi, e Accetta/Rifiuta continuano ad avere lo stesso peso */
  .cookie__azioni { display: grid; gap: .6rem; }
  .cookie__pers { margin-inline-start: 0; }
  .cookie__desc { padding-inline-start: 0; }
  body { font-size: 16px; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; scroll-behavior: auto !important; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .statement { --stagger: 0ms; --lead-in: 0ms; }
  .word { opacity: 1; transform: none; filter: none; transition: none; }
  .statement::before,
  .statement::after { transform: none; transition: none; }
  .scroll-cue::after { animation: none; }
  /* il cambio fra i due moduli dei contatti diventa istantaneo:
     l'animazione d'ingresso la spegne già la riga `*` qui sopra, la
     transizione d'uscita no (e main.js salta comunque l'attesa) */
  .form-pannello.is-fuori { transition: none; }
  .passi__seg { transition: none; }
  /* senza questa riga la tendina resterebbe chiusa e le foto degli split
     sparirebbero del tutto */
  .split__media.reveal img, .bleed.reveal img { clip-path: none; transition: none; }
  .bleed.reveal figcaption { opacity: 1; transition: none; }
  /* Il mazzo sta più sotto, in un blocco suo: sotto gli 821px è già sciolto
     in elenco dal blocco RESPONSIVE, e queste regole — che stanno in fondo al
     file, quindi vincono per ordine — glielo rimetterebbero a metà (il gap
     delle carte, l'ombra sotto a un fondo trasparente). */
  /* La fisarmonica resta: non si muove da sola, si apre solo perché
     l'utente ci passa sopra, la tocca o ci arriva col Tab. Sparisce la
     corsa, il pannello cambia misura di colpo. Il video di un pannello
     non viene nemmeno scaricato (se ne occupa main.js). */
  .gallery__panel, .gallery__media, .gallery__video, .gallery__body, .gallery__spine { transition: none; }
  .gallery__body > * { translate: none; transition: none; }
  /* Il nastro dei loghi qui non esiste proprio: main.js non lo costruisce e
     resta la lista dell'HTML, cioè una griglia di tessere centrata che va a
     capo. Niente righe che scorrono, niente copie, nessun tasto di pausa.
     Serve solo spegnere la comparsa del pannello al cambio di categoria. */
  .vetrina__pan { animation: none; opacity: 1; transform: none; }
  .card__icon svg :is(path, circle, line, rect, polyline, polygon) {
    stroke-dasharray: none; stroke-dashoffset: 0; transition: none;
  }
  /* La fisarmonica del programma resta: non si muove da sola, si apre solo
     perché l'utente la tocca. Sparisce la corsa del segno +/−, che cambia
     di colpo, e la sfumatura di colore del titolo. */
  .deck__toggle { transition: none; }
  .deck__segno::before, .deck__segno::after { transition: none; }
  /* Le schede delle strutture restano: non si muovono da sole, si accendono
     solo al passaggio del puntatore o col focus. Sparisce la corsa — il filetto
     e i colori cambiano di colpo — e niente altro, perché l'evidenziazione è
     l'unica cosa che dice quale scheda si sta leggendo. */
  .alloggio, .alloggio::before, .alloggio__tipo,
  .alloggio__dato svg, .alloggio__sito { transition: none; }
}

/* Le carte impilate non sono un'animazione (si muovono perché scorre l'utente),
   ma la sovrapposizione continua può disorientare chi soffre di vertigini: con
   reduced motion diventano una semplice fila di carte.
   Vale **solo da 821px in su**: sotto, il blocco RESPONSIVE ha già sciolto il
   mazzo nell'elenco editoriale, che di sovrapposizioni non ne ha nessuna e non
   va toccato — ed essendo questo blocco più in basso nel file, senza il limite
   di larghezza gli rimetterebbe il gap fra le carte e un'ombra sospesa sotto a
   un fondo ormai trasparente. */
@media (prefers-reduced-motion: reduce) and (min-width: 821px) {
  .deck { display: grid; gap: 1.5rem; }
  /* relative, non static: vedi la nota nel blocco a 820px */
  .deck__card, .deck__card + .deck__card {
    position: relative; min-height: 0; margin-block: 0; top: auto;
    box-shadow: 0 18px 40px rgba(23,27,24,.25);
  }
  .deck::after { display: none; }
  .deck__mark svg { display: none; }
}
