/* components.css — componenti di sezione e chrome del verticale food_producer.
   Tesi: produttore agricolo di famiglia, editoriale-caldo. Fondo crema, bande piene di bordeaux (il marchio)
   e arancio-zagara come unico accento. Il linguaggio della categoria Food: hero foto-cibo, eredità/tradizione,
   griglia di barattoli, passi dal raccolto al barattolo, banda sconto. Le foto grandi (agrumeto) sono lo hero;
   i barattoli, piccoli, stanno in tessere con gutter. I colori arrivano da tokens.css: qui non si dichiarano. */

/* ============================ Chrome: header ============================ */
/* Header fisso "a vetro". ⚠ backdrop-filter crea un containing-block per il position:fixed → l'overlay
   del menu mobile va forzato a 100vh (vedi .is-menu-open in fondo), altrimenti si confina all'header. */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.3) blur(10px);
  border-bottom: var(--border);
}
/* Il wrapper WP del template-part limiterebbe lo sticky: display:contents lo toglie di mezzo. */
.wp-block-template-part { display: contents; }

/* Riga header CENTRATA verticalmente: align-items:center + azzeramento dei margini di blocco WP,
   che spingerebbero nav e CTA sotto il centro. */
.site-header__row {
  display: flex; align-items: center; gap: var(--space-5);
  min-height: 84px; padding-block: var(--space-1);
}
/* La testata puo' essere piu' larga del corpo: il menu e' l'unico blocco che non si puo' accorciare. */
.site-header .container { max-width: var(--header-container); }
/* ⚠ Il menu non va a capo, e nemmeno le sue ETICHETTE: una voce spezzata a meta' («Prenota una visita /
   guidata») e' cio' che a occhio si legge come «menu a capo», anche quando le voci stanno su una riga. */
.site-header .site-nav { flex-wrap: nowrap; }
.site-header .site-nav a { white-space: nowrap; }
.site-header__row > * { align-self: center; margin-block: 0; }
/* ⚠ Il marchio non si comprime — MA SOLO DOVE C'E' SPAZIO. In un flex la prima cosa che cede e' il blocco
   piu' elastico, e il marchio lo e': con una voce in piu' nella riga andava a tre righe invece di due.
   ⚠⚠ Su telefono `flex: none` e' il difetto opposto e peggiore: misurato a 390px, il marchio prendeva 336
   dei 367 della riga, il pulsante del menu finiva a x=393 — FUORI dallo schermo — e la pagina traboccava a
   501px. Sotto i 900px il marchio deve continuare a cedere. */
@media (min-width: 900px) { .site-header .wordmark { flex: none; } }
/* Su telefono il marchio deve stare in DUE righe accanto al pulsante del menu e alle azioni del negozio:
   alla misura del desktop ne prendeva tre (74px di riga invece di 52). I due token hanno per default la
   misura di desktop, quindi chi non li ridichiara non vede nulla cambiare. */
@media (max-width: 640px) {
  .site-header .wordmark__name { font-size: var(--wordmark-size-sm, var(--wordmark-size)); min-width: var(--wordmark-min-sm, 0); }
  .site-header .wordmark__emblem { height: var(--emblem-size-sm, 66px); }
  /* ⚠ La misura del carattere da sola non basta: il marchio e' l'elemento elastico della riga e il flex lo
     comprime comunque — misurato, 115px per una scritta che ne chiede 135, quindi tre righe invece di due.
     Servono INSIEME un pavimento di larghezza sul nome e una riga meno spaziata, o il pavimento spinge
     fuori il pulsante del menu. Default: nessun pavimento e la spaziatura di prima. */
  .site-header__row { gap: var(--header-gap-sm, var(--space-5)); }
}

.wordmark { font-family: var(--font-display); font-size: 1.55rem; line-height: 1; display: flex; align-items: center; gap: var(--space-3); color: var(--brand); }
.wordmark small { display: block; font-family: var(--font-body); font-size: var(--text-sm); font-weight: 500; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-muted); margin-top: .25rem; }
/* Logo del cliente (emblema + testo, già integrato): sostituisce il wordmark testuale, nessuno span extra. */
.wordmark--logo .wordmark__logo { height: 72px; width: auto; display: block; }
/* Lockup d'intestazione: emblema del cliente (mark) + nome in Pacifico (wordmark, verde del logo). */
.wordmark--lockup { gap: var(--space-3); }
.wordmark__emblem { height: 66px; width: auto; display: block; flex: none; }
.wordmark__name { font-family: var(--font-brand); font-weight: 400; color: var(--wordmark-ink); font-size: var(--wordmark-size); line-height: 1; letter-spacing: 0; padding-top: .1em; }
@media (max-width: 640px) { .wordmark__emblem { height: 52px; } .wordmark__name { font-size: 1.5rem; } }
.wordmark__mark { flex: none; }
.wordmark__txt { display: block; }
@media (max-width: 560px) { .wordmark--logo .wordmark__logo { height: 60px; } }

.site-nav { margin-left: auto; }
/* Voci con underline d'accento animata all'hover (micro-interazione moderna, sobria). */
.site-nav a { font-size: .95rem; font-weight: 500; position: relative; padding-block: .35rem; }
.site-nav a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; border-radius: 2px; background: var(--accent-deco); transform: scaleX(0); transform-origin: left; transition: transform var(--dur) var(--ease); }
.site-nav a:hover::after, .site-nav .current-menu-item > a::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) { .site-nav a::after { transition: none; } }

/* Sotto-menu DESKTOP: il default WP è una card bianca squadrata. Qui è un pannello bordeaux col filetto
   d'arancio in testa. ⚠ SPECIFICITÀ: WP dichiara `.wp-block-navigation .wp-block-navigation__submenu-container
   {background-color:#fff}` (0,2,0) iniettato DOPO il tema → a parità vince WP e il pannello resta BIANCO.
   Serve un livello in più (`.site-header .site-nav …`). Stessa trappola del bottone header e dell'overlay. */
.site-header .site-nav .wp-block-navigation__submenu-container {
  background: var(--brand);
  border: none; border-top: 2px solid var(--accent-fill);
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: var(--shadow-md);
  padding-block: var(--space-3);
  min-width: 15rem;
}
.site-header .site-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
  color: var(--on-dark); padding: var(--space-3) var(--space-5); width: 100%;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.site-header .site-nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
  background: color-mix(in srgb, var(--on-dark) 10%, transparent); color: var(--accent-fill);
}
/* Telefono come secondario leggero (con icona): la CTA "Chiama ora" resta l'azione primaria. */
/* ⚠ La presenza del recapito in testata e' un TOKEN. Su un sito che vende solo al banco il telefono E'
   l'azione principale e sta bene in alto; su un sito che vende anche a distanza l'azione principale e'
   un'altra, e il numero in testata toglie spazio al marchio — misurato: il marchio andava a TRE righe.
   Default `inline-flex` = il comportamento di prima. */
.site-header__tel { font-weight: 500; font-size: .92rem; white-space: nowrap; color: var(--ink-muted); display: var(--header-tel, inline-flex); align-items: center; gap: .4rem; transition: color var(--dur) var(--ease); }
.site-header__tel:hover { color: var(--brand); }
.site-header__tel svg { flex: none; opacity: .85; }
.site-header__cta { white-space: nowrap; }
/* Su mobile telefono e CTA escono dall'header (che ha già logo + hamburger): li porta la .cta-bar fissa in
   basso. ⚠ Selettore discendente: `.site-header__cta` e `.btn` hanno pari specificità e `.btn` è dichiarato
   DOPO — la media query non aggiunge specificità, quindi una regola piatta verrebbe sovrascritta. */
@media (max-width: 820px) {
  .site-header .site-header__tel, .site-header .site-header__cta { display: none; }
}

/* ============================ Bottoni ============================ */
/* ⚠ CONTRATTO a11y (verificato): CTA primaria = bordeaux + testo --on-dark (10.2:1). CTA accento = fondo
   --accent-fill (#E08A3C) + testo --ink (6.4:1). MAI testo bianco su arancio (4.0:1) né ink su --accent-deco. */
.btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  font-family: var(--font-body); font-weight: 600; font-size: .95rem;
  border: 1px solid transparent; border-radius: var(--radius);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn--accent { background: var(--accent-fill); color: var(--ink); }
.btn--accent:hover { background: var(--accent-fill-hover); }
.btn--brand { background: var(--brand); color: var(--on-dark); }
.btn--brand:hover { background: var(--brand-deep); }
.btn--ghost { border-color: var(--brand); color: var(--brand); }
.btn--ghost:hover { background: var(--brand); color: var(--on-dark); }
/* Ghost su banda scura: bordo ed etichetta ereditano crema, l'hover inverte. */
.btn--ghost-on-dark { border-color: var(--on-dark); color: var(--on-dark); }
.btn--ghost-on-dark:hover { background: var(--on-dark); color: var(--brand); }

/* ============================ Hero ============================ */
/* L'hero si estende SOTTO l'header fisso (overlay): l'immagine arriva fino in cima allo schermo, l'header
   cream-glass ci galleggia sopra (logo/menu restano leggibili sul vetro chiaro). Solo la home ha .hero →
   le altre pagine sono intatte. Il contenuto ha un padding-top che libera l'altezza dell'header. */
.hero { position: relative; color: var(--on-dark); isolation: isolate; overflow: hidden; }
.hero__inner { position: relative; z-index: 2; display: grid; align-items: center; min-height: clamp(30rem, 24rem + 22vw, 44rem); padding-block: clamp(3.5rem, 2rem + 6vw, 7rem); }
.hero__text { max-width: 44rem; }
.hero .eyebrow--light { margin-bottom: var(--space-4); }
/* ⚠ L'occhiello dell'hero e' la riga PIU' PICCOLA su una fotografia, quindi la piu' esposta: col crema
   smorzato del verticale, misurato sui pixel resi, faceva 2,44 contro i 4,5 richiesti. E' informazione
   (dove sta il caseificio), non decorazione: prende il crema pieno. Default = il colore di prima. */
.hero--photo .eyebrow--light { color: var(--eyebrow-on-photo, var(--on-dark-muted)); }
/* ⚠ Size PROPRIA (non riuso di --text-3xl secco): l'h1 sta su colonna larga ma la copy reale del cliente
   può superare i 60 caratteri → il cap del clamp evita le 5 righe. La misura di lettura sta sulla LEAD. */
.hero h1 { color: var(--on-dark); font-size: var(--text-3xl); margin-block: 0 var(--space-5); }
.hero .lead { color: var(--on-dark); opacity: .95; max-width: 46ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }

/* Hero DESIGN (senza foto): banda bordeaux piena. È il caso limite del verticale e il fondo del demo. */
.hero--design { background: linear-gradient(160deg, var(--brand) 0%, var(--brand-deep) 100%); }
.hero--design::after { content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(120% 90% at 85% 15%, color-mix(in srgb, var(--accent-deco) 30%, transparent), transparent 60%); }

/* Hero FOTO: slideshow crossfade di foto-cibo (agrumeto/marmellata). Il testo NON dipende dal fotogramma:
   scrim bordeaux forte sotto il testo. reduced-motion → prima foto fissa. (rule 2) */
.hero--photo .hero__inner { min-height: clamp(32rem, 26rem + 22vw, 46rem); }
.hero-media { position: absolute; inset: 0; z-index: 0; background: var(--brand-deep); }
/* Effetto "video": 6 foto naturalistiche in crossfade rapido + zoom continuo (Ken Burns). Non è un mp4
   (il video non è nel materiale né gestito dalla pipeline): il movimento continuo lo simula, senza il peso. */
/* ⚠ `inset: -12% 0` invece di `inset: 0`: la parallasse trasla la diapositiva di ±5,8% della sua altezza
   (`data-parallax="5"`), e a filo del riquadro il movimento scoprirebbe una striscia di fondo sopra o
   sotto. Il 9% e' il margine, non un valore estetico. */
.hero-slide { position: absolute; inset: -12% 0; background-size: cover; background-position: center; opacity: 0; will-change: opacity, transform; animation: fp-hero-fade 27s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .hero-slide { inset: 0; transform: none !important; } }
.hero-slide:nth-child(1) { animation-delay: 0s; }
.hero-slide:nth-child(2) { animation-delay: 4.5s; }
.hero-slide:nth-child(3) { animation-delay: 9s; }
.hero-slide:nth-child(4) { animation-delay: 13.5s; }
.hero-slide:nth-child(5) { animation-delay: 18s; }
.hero-slide:nth-child(6) { animation-delay: 22.5s; }
@keyframes fp-hero-fade {
  0% { opacity: 0; transform: scale(1.0); }
  4% { opacity: 1; }
  13% { opacity: 1; }
  18% { opacity: 0; transform: scale(1.12); }
  100% { opacity: 0; transform: scale(1.0); }
}
/* Velatura dell'hero: e' un TOKEN (`--hero-scrim`), col default identico al valore cablato di prima.
   ⚠ Il velo del verticale copre TUTTA la larghezza col colore di marca — anche il bordo destro ne prende
   il 30%. Su fotografie di cibo quel velo si porta via il colore del soggetto: sotto il blu il Parmigiano
   non e' piu' paglierino. Chi ha bisogno che le fotografie restino vere ridichiara il token. */
.hero--photo::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: var(--hero-scrim); }
/* ⚠ Su telefono la geometria del velo cambia MESTIERE: su desktop il testo sta a sinistra e il velo si
   spegne verso destra; su una colonna di 390px il testo prende tutta la larghezza e un velo orizzontale
   lascia scoperta proprio la riga piu' piccola (l'occhiello). Default = lo stesso velo, quindi inerte. */
@media (max-width: 760px) { .hero--photo::after { background: var(--hero-scrim-sm, var(--hero-scrim)); } }
@media (prefers-reduced-motion: reduce) {
  .hero-slide { animation: none; opacity: 0; }
  .hero-slide:nth-child(1) { opacity: 1; }
}
@media (max-width: 640px) { .hero__actions .btn { flex: 1 1 auto; justify-content: center; } }

/* ============================ Elenco degli orari ============================ */
/* ⚠ Senza questa regola i due <span> di ogni riga si toccano e si legge «Lunedi10.00 – 12.00»: il giorno
   e l'orario sembrano una parola sola. Classe NUOVA: nessun sito gia' costruito su questo verticale la usa. */
.hours-list { list-style: none; margin: 0; padding: 0; max-width: 34rem; }
.hours-list li { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-5);
  padding-block: var(--space-3); border-bottom: var(--border); }
.hours-list li:last-child { border-bottom: 0; }
.hours-list li > span:first-child { color: var(--ink); font-weight: 500; }
.hours-list li > span:last-child { color: var(--ink-muted); text-align: right; white-space: nowrap; }
@media (max-width: 480px) { .hours-list li { flex-direction: column; gap: var(--space-1); } .hours-list li > span:last-child { text-align: left; } }

/* ============================ Banda fotografica a piena larghezza ============================ */
/* Fascia d'immagine larga quanto il contenitore, per le pagine di progetto: e' la sola sede in cui una
   fotografia di questo parco arriva a una misura che si LEGGE (sopra il 18% del viewport), perche' la
   testata e' un background-image e le foto di sezione stanno in mezza colonna.
   ⚠ Classe NUOVA: nessun sito gia' costruito su questo verticale la usa, quindi l'aggiunta e' inerte.
   ⚠ Niente `.reveal` sul contenitore: con opacity:0 il browser non scarica l'immagine che contiene. */
.band-photo { margin: 0; overflow: hidden; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); background: var(--media-mat); aspect-ratio: 21 / 9; }
/* ⚠⚠ PARALLASSE. `reveal.js` trasla l'elemento di `p * amp` percento, e |p| arriva a ~1,15 mentre
   attraversa lo schermo: con `data-parallax="8"` il movimento e' ±9,2% dell'ALTEZZA DELL'IMMAGINE.
   Se l'immagine fosse alta quanto la cornice, il movimento SCOPRIREBBE il fondo sopra o sotto — difetto
   gia' pagato piu' volte in flotta. Qui l'immagine e' sovradimensionata e centrata, con margine di
   manovra 16% sopra e 16% sotto: piu' del 9,2% che serve, e il conto e' scritto perche' chi cambia
   l'ampiezza sappia dove guardare. */
.band-photo img { width: 100%; height: var(--band-oversize, 132%); position: relative; top: var(--band-offset, -16%); object-fit: cover; display: block; will-change: transform; }
@media (prefers-reduced-motion: reduce) { .band-photo img { height: 100%; top: 0; transform: none !important; } }
.band-photo figcaption { display: none; }
@media (max-width: 640px) { .band-photo { aspect-ratio: 3 / 2; } }

/* Variante A TUTTA LARGHEZZA della banda fotografica. La banda incorniciata resta una cartolina in mezzo
   al testo: bella, ma non cambia il respiro della pagina. Questa esce dalla colonna di lettura e prende
   la finestra intera — e' il gesto che l'owner ha indicato ("un po' come colazingari"), e in una pagina
   di solo testo e' l'unico punto in cui l'occhio si ferma.
   ⚠ NON si usa `100vw`: su una finestra con la barra di scorrimento visibile `100vw` la include e apre
   un trabocco orizzontale (hard gate dello scorer). La figura si mette semplicemente FUORI dal
   `.container` — la sezione non ha padding orizzontale, quindi la larghezza piena arriva da sola.
   ⚠ Il raggio e l'ombra spariscono: un rettangolo arrotondato a filo di finestra mostrerebbe quattro
   spicchi di fondo agli angoli. */
.band-photo--wide { border-radius: 0; box-shadow: none; aspect-ratio: var(--band-wide-ratio, 21 / 7); }
@media (max-width: 900px) { .band-photo--wide { aspect-ratio: 16 / 9; } }
@media (max-width: 640px) { .band-photo--wide { aspect-ratio: 4 / 3; } }

/* ============================ Pannello INCHIODATO e fotografia FERMA ============================ */
/* ⚠⚠ Il pannello inchiodato e' l'effetto che nel parlato comune si chiama «parallasse»: la fotografia
   resta appuntata allo schermo e la pagina le scorre sopra. Si fa con `position: sticky`, non con una
   traslazione — e non e' un dettaglio, e' l'unica forma che risolve ANCHE la definizione:
   la scatola e' la finestra (16:9 come le sorgenti), quindi NIENTE sovradimensionamento, niente taglio
   laterale e l'ingrandimento sullo schermo scende da ×1,95 a ×1,6.
   ⚠ La traslazione lenta paga la propria visibilita' in pixel di fotografia: per muoversi ha bisogno di
   un'immagine piu' alta della banda, e quell'eccedenza esce dai lati (misurato: 82% di larghezza visibile).
   ⚠ Su telefono il pin si spegne: un pannello alto quanto lo schermo su un telefono e' peso senza resa, e
   `sticky` dentro una colonna stretta si comporta male. Diventa una fotografia normale. */
.band-fissa { height: var(--band-fissa-h, 170vh); position: relative; }
.band-fissa__pin { position: sticky; top: 0; height: 100svh; overflow: hidden; }
.band-photo--fissa { height: 100%; aspect-ratio: auto; border-radius: 0; box-shadow: none; }
.band-photo--fissa img { width: 100%; height: 100%; top: 0; object-fit: cover; transform: none !important; }
@media (max-width: 760px) {
  .band-fissa { height: auto; }
  .band-fissa__pin { position: static; height: auto; }
  /* ⚠ Su telefono il rapporto resta quello della SORGENTE: un 4:3 su un originale 16:9 ributtava via
     un quarto della fotografia — misurato, 75% di larghezza visibile. */
  .band-photo--fissa { height: auto; aspect-ratio: var(--band-ferma-ratio, 16 / 9); }
}

/* ============================ Parallasse VERO: il fondo ancorato alla finestra ============================ */
/* ⚠⚠ E' questo che nel parlato comune si chiama parallasse: la BANDA scorre con la pagina — quindi la
   pagina non si ferma mai — e la FOTOGRAFIA sotto resta ancorata alla finestra. Si vede la banda passarci
   davanti come una finestra che scorre su un quadro appeso al muro.
   ⚠ Non e' il pannello `sticky`: quello inchioda la banda intera, e mentre e' in presa non si muove piu'
     niente sullo schermo — si legge come uno SCATTO, la pagina che si blocca e riparte. Difetto segnalato.
   ⚠⚠ Un antenato con `transform`, `filter`, `clip-path` o `will-change` ANNULLA l'ancoraggio: il fondo
     torna a scorrere e nessun errore lo dice. Per questo questa banda non porta la tendina di apertura.
   ⚠ Su iOS `background-attachment: fixed` e' rotto (salta, o dipinge l'immagine alta quanto il documento):
     sotto i 900px e sui dispositivi a tocco si torna a un fondo normale, che e' una fotografia onesta. */
.band-photo--parallasse {
  aspect-ratio: auto; height: var(--band-parallasse-h, 62vh);
  background-size: cover; background-position: center; background-repeat: no-repeat;
  border-radius: 0; box-shadow: none;
}
/* L'immagine resta per il caricamento, l'alt e i controlli, ma non si vede: il fondo la dipinge gia'. */
.band-photo--parallasse img { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.band-photo--parallasse { position: relative; }
@media (min-width: 900px) and (hover: hover) {
  .band-photo--parallasse { background-attachment: fixed; }
}
@media (max-width: 899px) {
  .band-photo--parallasse { height: auto; aspect-ratio: var(--band-ferma-ratio, 16 / 9); }
}

/* La fotografia FERMA: incorniciata nella colonna del testo, immobile, al rapporto della sorgente cosi'
   non si taglia niente. E' la forma giusta per una MACRO di prodotto — a tutta larghezza sarebbe
   ingrandita (×1,95 su Retina) e morbida; qui e' ×0,98, cioe' nitida. */
.band-photo--ferma { aspect-ratio: var(--band-ferma-ratio, 16 / 9); }
.band-photo--ferma img { height: 100%; top: 0; transform: none !important; }

/* ============================ Apertura e deriva della banda ============================ */
/* ⚠⚠ La maschera sta sulla FIGURA, l'osservatore guarda la SEZIONE (`[data-apertura]`). Un `clip-path`
   sull'elemento osservato lo azzera: l'IntersectionObserver non lo vede mai e la banda non si apre piu'.
   Difetto gia' pagato due volte in flotta, e non lo segnala nessun errore. */
[data-apertura] .band-photo { clip-path: inset(var(--band-mask-da, 0) 0 0 0); transition: clip-path 620ms var(--ease); }
[data-apertura].is-aperta .band-photo { clip-path: inset(0 0 0 0); }
/* La deriva di scala si somma alla parallasse: insieme leggono come una ripresa, non come un rettangolo che
   scorre. ⚠ Va sull'IMMAGINE, che la parallasse trasla con `transform`: qui si usa `scale` separato, o le
   due trasformazioni si sovrascriverebbero a vicenda. */
.band-photo--wide img { scale: var(--band-drift-da, 1); transition: scale 2600ms linear; }
[data-apertura].is-aperta .band-photo--wide img { scale: var(--band-drift-a, 1); }
@media (prefers-reduced-motion: reduce) {
  [data-apertura] .band-photo { clip-path: none; transition: none; }
  .band-photo--wide img { scale: 1; transition: none; }
}

/* ============================ Frase-firma: rivelazione parola per parola ============================ */
/* ⚠ Il testo resta INTERO nel DOM: si muove solo l'opacita'. La digitazione del verticale svuotava
   l'elemento e lo riscriveva — 17,9 secondi misurati su 163 caratteri, con la frase incompleta, non
   selezionabile e il blocco che cambiava altezza mentre si riempiva. */
.statement .parola { display: inline-block; opacity: 1; transform: none; }
.js .statement.is-rivelabile .parola { opacity: 0; transform: translateY(8px); transition-property: opacity, transform; transition-timing-function: var(--ease); }
.js .statement.is-rivelata .parola { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .statement.is-rivelabile .parola { opacity: 1; transform: none; transition: none; }
}
/* Velatura in basso: sulle foto chiare il bordo inferiore della banda sfumava nella carta e la banda
   sembrava "non finita". Il velo la chiude senza scurire la fotografia (si ferma al 38% dell'altezza). */
.band-photo--wide::after { content: ""; position: absolute; inset: auto 0 0 0; height: 38%; background: linear-gradient(to bottom, rgba(18,56,95,0) 0%, rgba(18,56,95,.28) 100%); pointer-events: none; }
.band-photo--wide { position: relative; }

/* ============================ Clausole numerate (pagine legali) ============================ */
/* Un testo legale arriva come una fila di capoversi che cominciano per «1)», «2)»…: a terra sono
   indistinguibili dal resto e la pagina e' un muro di tremila pixel. Qui ogni clausola diventa un blocco
   con un filetto d'accento, cosi' si conta con l'occhio dove comincia e dove finisce.
   ⚠ Il testo NON viene toccato: il numero resta dove il cliente l'ha scritto, dentro il capoverso. Portarlo
   fuori in un campo grafico avrebbe voluto dire togliere la parentesi, cioe' cambiare il testo di un
   documento contrattuale — che qui non si fa nemmeno di un carattere. */
.clausole { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(1rem, 2.2vw, 1.5rem); }
/* ⚠ La misura di lettura sta sulla SCHEDA, non sul capoverso dentro: con `max-width` sul <p> la scheda
   resta larga quanto la banda e si apre a destra il campo vuoto che l'owner segnala da due giri. Qui la
   scheda e' larga quanto il testo che contiene — misurato: 117 caratteri per riga prima, ~70 dopo. */
.clausola { background: var(--card-bg); border-left: 3px solid var(--accent-fill); border-radius: var(--radius-lg); padding: clamp(1.1rem, 2.4vw, 1.75rem) clamp(1.2rem, 3vw, 2rem); box-shadow: var(--shadow-sm); max-width: 74ch; }
.clausola p { max-width: none; }
.clausola p { margin: 0; }
.clausola p + p { margin-top: var(--space-4); }

/* ============================ Cornice per documenti fotografati ============================ */
/* Un attestato, un certificato, un'etichetta: sono VERTICALI e non si possono ritagliare — va letto tutto.
   Un riquadro orizzontale li lascerebbe incorniciati per meta' (misurato: 50% di fondo scoperto).
   ⚠ Classe NUOVA e generica: nessun sito gia' costruito su questo verticale la usa. */
.docs { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1.5rem, 4vw, 3rem); }
.doc { display: flex; flex-direction: column; gap: var(--space-4); }
.doc__frame { margin: 0; aspect-ratio: 3 / 4; overflow: hidden; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); background: var(--surface); }
.doc__frame img { width: 100%; height: 100%; object-fit: contain; display: block; }
.doc h3 { color: var(--brand); font-family: var(--font-display); font-weight: 400; font-size: var(--text-lg); }
.doc p { color: var(--ink-muted); }
@media (max-width: 760px) { .docs { grid-template-columns: 1fr; } }

/* ============================ Storia (featured) ============================ */
/* Editoriale a due campi: eyebrow + statement display a sinistra, racconto a destra. Nessuna foto nella
   sezione (le foto vivono nell'hero e nella specialità): text-only regge sia il demo sia il sito reale.
   Il primo capoverso del racconto è l'attacco editoriale (nessun campo nuovo: è il body, trattato). */
/* ⚠ L'allineamento verticale e' un TOKEN: quando il racconto e' molto piu' corto della frase display
   (qui meta'), `start` lascia sotto la colonna destra un campo vuoto alto quanto la differenza. Il
   default resta `start`, cioe' il valore cablato di prima: chi non lo ridichiara non vede nulla cambiare. */
.storia__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem) clamp(2rem, 6vw, 5rem); align-items: var(--storia-align, start); }
/* Effetto macchina da scrivere sulla frase della storia (font ORIGINALE DM Serif via .statement; l'animazione
   la fa reveal.js digitando una lettera alla volta). Cursore lampeggiante mentre digita, poi sparisce. */
.storia .statement.is-typing::after { content: "|"; margin-left: .04em; color: var(--accent-text); font-weight: 400; animation: fp-tw-blink 1s step-end infinite; }
@keyframes fp-tw-blink { 50% { opacity: 0; } }
.storia__body > p:first-child { font-family: var(--font-display); font-size: var(--text-md); color: var(--accent-text); border-left: 3px solid var(--accent-deco); padding-left: var(--space-5); margin-bottom: var(--space-5); line-height: 1.4; }
.storia__body > p + p { margin-top: var(--space-4); }
@media (max-width: 860px) { .storia__grid { grid-template-columns: 1fr; } }

/* ============================ Prodotti (services): griglia di barattoli ============================ */
.prodotti__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--tile-gap); }
.jar { display: flex; flex-direction: column; background: var(--paper); border: var(--jar-border, var(--border)); border-radius: var(--jar-radius, var(--radius)); box-shadow: var(--jar-shadow, none); overflow: hidden; transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.jar:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
/* ⚠ Il barattolo si vede INTERO (richiesta cliente, come il sito attuale): contain, non cover. Le foto
   sono su fondo bordeaux (#691b20) → il box ha lo stesso fondo e la lettera-box è invisibile. Ratio 4/5
   = quello del formato foto, così il barattolo riempie la cella senza tagli sull'etichetta. */
.jar__media { aspect-ratio: var(--jar-ratio); overflow: hidden; background: var(--jar-media-bg, var(--media-mat)); }
.jar__media img { width: 100%; height: 100%; object-fit: var(--jar-media-fit, contain); transition: transform var(--dur) var(--ease); }
.jar:hover .jar__media img { transform: scale(1.04); }
.jar__body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.jar h3 { color: var(--ink); }
/* ⚠⚠ LA STAGIONATURA. «Parmigiano Reggiano 12 mesi» e «Parmigiano Reggiano 24 mesi» differiscono per due
   caratteri in mezzo a una riga che va a capo: a colpo d'occhio le sei schede sono identiche, e la
   stagionatura e' proprio cio' che il cliente compra. Qui i mesi diventano il campo dominante della scheda.
   ⚠ L'ORDINE DELLE PAROLE NON CAMBIA: il titolo resta «Parmigiano Reggiano» seguito da «12 mesi», solo su
   due righe e con due pesi diversi. Portare i mesi davanti al nome avrebbe voluto dire riscrivere una
   stringa dichiarata VERBATIM, e il controllo l'avrebbe (giustamente) bocciata. */
.jar h3:has(.jar__eta) { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; letter-spacing: .02em; color: var(--ink-muted); line-height: 1.3; }
.jar__eta { display: block; font-family: var(--font-display); font-weight: 400; font-size: clamp(1.5rem, 1.2rem + .9vw, 2rem); line-height: 1.05; color: var(--brand); letter-spacing: -.01em; margin-top: .15em; }
.jar__text { color: var(--ink-muted); font-size: .92rem; }
/* Link all'etichetta del prodotto (PDF, apre in nuova scheda), in fondo alla card. */
.jar__label { margin-top: auto; padding-top: var(--space-3); align-self: flex-start; display: inline-flex; align-items: center; gap: .3rem; font-size: .85rem; font-weight: 600; color: var(--accent-text); text-decoration: none; }
.jar__label:hover { text-decoration: underline; text-underline-offset: 2px; }
.spec__text-col .jar__label { margin-top: var(--space-4); }
/* Variante DESIGN (demo / nessuna foto): tessere piene, come dispensa. Nessuna foto finta. */
.jar--filled { min-height: 13rem; justify-content: center; }
/* Scheda di prodotto CLICCABILE: porta alla scheda del negozio. Classi nuove, quindi inerti per chi non
   le usa. ⚠ Il prezzo NON si scrive qui: sta nel negozio, ed e' l'unico posto in cui si aggiorna. Due
   sorgenti per lo stesso numero divergono al primo ritocco del listino. */
.jar--link { text-decoration: none; color: inherit; }
.jar--link:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.jar--link:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.jar__more { margin-top: auto; padding-top: var(--space-3); color: var(--accent-text); font-weight: 600; font-size: .92rem; display: inline-flex; align-items: center; gap: .4em; }
.jar__more::after { content: "\2192"; transition: transform var(--dur) var(--ease); }
.jar--link:hover .jar__more::after { transform: translateX(3px); }
.jar--filled .jar__body { justify-content: center; }
.jar--brand { background: var(--brand); border-color: var(--brand); }
.jar--brand h3, .jar--brand .jar__text { color: var(--on-dark); }
.jar--brand .jar__text { opacity: .9; }
.jar--accent { background: var(--accent-tint); border-color: var(--accent-tint); }
.jar--accent h3 { color: var(--brand); }
.jar--accent .jar__text { color: var(--ink-muted); }
/* ⚠ Una famiglia di DUE voci su tre colonne lascia la terza vuota (misurato: l'ultima riga copre il 64%
   della larghezza). La condizione guarda il CONTEGGIO REALE — «il secondo figlio e' anche l'ultimo» — non
   il nome della sezione, cosi' vale per qualunque catalogo e non scade al primo rinomino. */
.prodotti__grid:has(> :nth-child(2):last-child) { grid-template-columns: repeat(2, 1fr); }

/* ⚠ RIGA INCOMPLETA. Su tre colonne, un catalogo di 7 voci chiude con UNA scheda sola e due celle vuote
   accanto: a occhio si legge come «mancano dei pezzi». La scheda rimasta sola prende tutta la riga e si
   impagina in orizzontale, cosi' la griglia chiude senza celle orfane.
   ⚠ La condizione e' `:last-child:nth-child(3n+1)` — l'ultima scheda che APRE una riga, cioe' l'unica
   che resterebbe sola. Con 6 voci non scatta: inerte per un catalogo che chiude gia' pari. */
.prodotti__grid > .jar:last-child:nth-child(3n+1) { grid-column: 1 / -1; flex-direction: row; align-items: stretch; }
.prodotti__grid > .jar:last-child:nth-child(3n+1) .jar__media { flex: 0 0 34%; aspect-ratio: auto; }
.prodotti__grid > .jar:last-child:nth-child(3n+1) .jar__body { justify-content: center; }
@media (max-width: 900px) {
  .prodotti__grid > .jar:last-child:nth-child(3n+1) { grid-column: auto; flex-direction: column; }
  .prodotti__grid > .jar:last-child:nth-child(3n+1) .jar__media { flex: none; aspect-ratio: var(--jar-ratio); }
}
@media (max-width: 900px) { .prodotti__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .prodotti__grid { grid-template-columns: 1fr; } }

/* Banda sconto (device Food: "receive a 10% discount"). Arancio tenue, testo ink; il numero in display. */
.promo { margin-top: var(--space-7); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-5);
  background: var(--accent-tint); border: 1px solid color-mix(in srgb, var(--accent-deco) 40%, transparent); border-radius: var(--radius-lg); padding: var(--space-5) var(--space-6); }
.promo__big { font-family: var(--font-display); font-size: clamp(1.6rem, 1.1rem + 1.6vw, 2.2rem); color: var(--brand); line-height: 1.1; }
.promo__text { color: var(--ink); }
.promo__text strong { color: var(--accent-text); }

/* ============================ Metodo: dal raccolto al barattolo ============================ */
/* ⚠ Questa sezione NON ha fotografie: e' testo su una banda larga. Con l'introduzione ferma a 48rem la
   meta' destra restava bianca — il difetto degli «spazi vuoti» che a 1440 si nota poco e su un monitor
   largo salta agli occhi. Qui l'introduzione occupa tutta la banda su DUE campi (titolo a sinistra,
   sommario a destra): l'area si riempie e la misura di lettura del sommario resta quella di prima.
   ⚠ La regola e' scritta sulla CONDIZIONE «la sezione non ha figure», non sul nome della sezione:
   una sezione che un giorno ricevesse una fotografia tornerebbe da sola al telaio a colonna. */
.metodo:not(:has(figure)) .section-intro {
  max-width: none;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-3) clamp(1.5rem, 4vw, 4rem); align-items: start;
}
/* ⚠ Collocazione ESPLICITA: lasciata all'automatismo, la griglia metterebbe occhiello e titolo nelle due
   colonne della prima riga e il sommario da capo, cioe' l'opposto di quel che serve. */
.metodo:not(:has(figure)) .section-intro .eyebrow { grid-column: 1; grid-row: 1; margin: 0; }
.metodo:not(:has(figure)) .section-intro h2 { grid-column: 1; grid-row: 2; margin: 0; }
.metodo:not(:has(figure)) .section-intro .lead { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
@media (max-width: 860px) { .metodo:not(:has(figure)) .section-intro { grid-template-columns: 1fr; } }
.pattern-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gutter); }
.pstep { position: relative; padding-top: var(--space-6); }
.pstep__n { font-family: var(--font-display); font-size: 3.2rem; line-height: 1; color: var(--accent-text); display: block; }
.pstep h3 { margin-block: var(--space-3) var(--space-2); color: var(--ink); }
.pstep__text { color: var(--ink-muted); font-size: .92rem; }
/* Filo orizzontale che cuce gli step (si spegne a una colonna). */
.pstep::before { content: ""; position: absolute; top: var(--space-6); left: 0; right: calc(var(--gutter) * -1); height: 2px; background: var(--accent-deco); opacity: .5; }
.pstep:last-child::before { right: 0; }
@media (max-width: 980px) { .pattern-steps { grid-template-columns: repeat(2, 1fr); } .pstep::before { display: none; } }
@media (max-width: 520px) { .pattern-steps { grid-template-columns: 1fr; } }

/* ============================ Specialità (gallery): miele + Amarello ============================ */
/* Due prodotti-firma in evidenza: foto grande + testo, sfalsati (foto a lati alternati). Present solo con
   le foto reali dei due prodotti (variante asset-driven); il demo, senza foto, li omette. */
.spec { display: grid; gap: clamp(2rem, 5vw, 4rem); }
.spec__row { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
.spec__row:nth-child(even) .spec__media { order: 2; }
/* Le foto specialità (bottiglia Amarello verticale, miele orizzontale) si vedono INTERE: contain sul bordeaux
   delle foto (#691b20), box quadrato = buon compromesso per i due orientamenti. Niente tappo tagliato. */
.spec__media { border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-md); background: var(--media-mat); aspect-ratio: var(--spec-ratio); }
/* ⚠ Il riquadro e' 3:2 e le scene preparate per queste file sono 3:2 NATIVE: `cover` non taglia nulla
   piu' di quanto facesse `contain`, e permette di sovradimensionare per la parallasse. Margine 8% sopra
   e sotto contro un movimento di ±5,8% (`data-parallax="5"`).
   ⚠ Gli scatti di PRODOTTO restano `contain`: hanno il soggetto al centro su fondo chiaro e un ritaglio
   li mangerebbe. La distinzione e' sul contenitore, non sulla pagina. */
.spec__media img { width: 100%; height: 122%; position: relative; top: -11%; object-fit: cover; will-change: transform; }
@media (prefers-reduced-motion: reduce) { .spec__media img { height: 100%; top: 0; transform: none !important; } }
.spec h3 { color: var(--brand); font-family: var(--font-display); font-weight: 400; font-size: var(--text-lg); margin-bottom: var(--space-3); }
.spec__text { color: var(--ink-muted); }
@media (max-width: 760px) { .spec__row { grid-template-columns: 1fr; } .spec__row:nth-child(even) .spec__media { order: 0; } }

/* ============================ Naturale (trust) ============================ */
.trust__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.trust__items { display: grid; gap: var(--space-4); }
/* ⚠ Le schede informative erano riquadri bianchi con un filetto: nessuna gerarchia e nessun segno, e a
   fianco di un titolo grande si leggevano come spazio riempito. Ora portano un filetto d'accento sul
   fianco, il titolo nel serif di marca e una superficie con profondita'. */
.tcard { position: relative; padding: var(--space-6) var(--space-6) var(--space-6) calc(var(--space-6) + 6px);
  background: var(--card-bg); border: var(--border); border-radius: var(--radius-lg);
  box-shadow: 0 2px 10px rgba(18,56,95,.05); overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.tcard::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 5px;
  background: linear-gradient(180deg, var(--accent-fill) 0%, var(--accent-deco) 100%); }
.tcard:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(18,56,95,.10); }
@media (prefers-reduced-motion: reduce) { .tcard { transition: none; } .tcard:hover { transform: none; } }
.tcard h3 { color: var(--brand); font-family: var(--font-display); font-weight: 400; font-size: var(--text-lg); margin-bottom: var(--space-3); }
.tcard__text { color: var(--ink-muted); font-size: .96rem; }
/* Checks = pill list (device Food: "senza addensanti/coloranti/conservanti"). Arancio tenue, testo ink. */
.checks { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-5); }
.checks li { display: inline-flex; align-items: center; gap: var(--space-2); background: var(--accent-tint); color: var(--ink); font-weight: 500; font-size: .9rem; padding: var(--space-2) var(--space-4); border-radius: 999px; }
.checks li::before { content: ""; width: .55rem; height: .55rem; border-radius: 50%; background: var(--accent-deco); flex: none; }
@media (max-width: 860px) { .trust__grid { grid-template-columns: 1fr; } }

/* ============================ Banda contatti (contact_band) ============================ */
.band--dark { background: linear-gradient(160deg, var(--brand) 0%, var(--brand-deep) 100%); color: var(--on-dark); }
.band--dark h2 { color: var(--on-dark); }
.band--dark .lead { color: var(--on-dark); opacity: .95; }
.contact-band__inner { display: flex; flex-wrap: wrap; gap: var(--space-6); align-items: center; justify-content: space-between; }
.contact-band__text { max-width: 48ch; }

/* ============================ Testata di pagina ============================ */
/* ⚠ La page-head NON riusa la size dell'hero (--text-3xl): è una testata, non un hero. È CONDIVISA da tutte
   le pagine interne: sistemala UNA volta. */
.page-head { background: var(--head-bg); padding-block: clamp(3rem, 2rem + 4vw, 5.5rem); border-bottom: var(--head-border);
  border-end-start-radius: var(--head-radius); border-end-end-radius: var(--head-radius); position: relative; overflow: hidden; }
.page-head h1 { font-size: var(--text-2xl); color: var(--brand); }
/* ⚠ TESTATA A DUE CAMPI, condizionata alla PRESENZA della fotografia (`:has(.page-head__media)`).
   Senza questa condizione la pagina Privacy del verticale — che una fotografia non ce l'ha — si
   ritroverebbe una colonna vuota. La regola guarda il contenuto, non il nome della pagina.
   ⚠ L'immagine e' sovradimensionata del 24% con 12% di margine sopra e sotto: `data-parallax="6"`
   trasla di ±6,9% dell'altezza, e senza margine il movimento scoprirebbe la cornice. */
/* ⚠⚠ TESTATA FOTOGRAFICA a tutta banda, condizionata alla PRESENZA della fotografia
   (`:has(.page-head__media)`). Senza la condizione, la pagina Privacy del verticale — che una fotografia
   non ce l'ha — diventerebbe una banda scura vuota. La regola guarda il CONTENUTO, non il nome.
   Il contrasto e' STRUTTURALE: lo da' il velo di marca, non il fotogramma, cosi' non dipende da quanto
   e' chiara la foto — lo stesso principio della testata della home. */
.page-head:has(.page-head__media) {
  color: var(--on-dark); border-bottom: 0; isolation: isolate;
  min-height: clamp(19rem, 15rem + 13vw, 27rem);
  display: grid; align-items: center;
  padding-block: clamp(3.5rem, 2.5rem + 4vw, 6rem);
}
.page-head:has(.page-head__media) .container { position: relative; z-index: 2; }
.page-head:has(.page-head__media) h1 { color: var(--on-dark); font-size: var(--text-3xl); }
.page-head:has(.page-head__media) .lead { color: var(--on-dark); opacity: .95; max-width: 46ch; }
/* ⚠ Briciole e occhiello sono testo PICCOLO: la soglia e' 4,5:1, non 3:1, e l'azzurro tenue
   (--on-dark-muted) non ci arriva sopra una fotografia — misurato 1,93-2,89 sui pixel resi. Vanno in
   bianco pieno, e il velo si rinforza dove stanno (in alto a sinistra). */
.page-head:has(.page-head__media) .crumbs,
.page-head:has(.page-head__media) .crumbs a { color: var(--on-dark); }
.page-head:has(.page-head__media) .eyebrow { color: var(--on-dark); }
.page-head:has(.page-head__media) .eyebrow::before { background: var(--accent-fill); }
/* ⚠ Il capoverso SENZA classe della testata. La privacy del verticale ne ha uno, e finche' quella testata
   non aveva fotografia prendeva --ink-muted su fondo chiaro, che era giusto. Con la fotografia diventa
   grigio su immagine. Nella testata fotografica TUTTO il testo e' chiaro — `.lead` non basta, perche'
   quel capoverso quella classe non ce l'ha. */
.page-head:has(.page-head__media) p { color: var(--on-dark); max-width: 52ch; }
/* ⚠ La fotografia e' sovradimensionata del 24% con 12% di margine sopra e sotto: `data-parallax="6"`
   trasla di ±6,9% dell'altezza, e senza margine il movimento scoprirebbe il fondo della banda. */
.page-head__media { position: absolute; inset: 0; z-index: 0; margin: 0; overflow: hidden; background: var(--brand-deep); }
.page-head__media img { width: 100%; height: 124%; position: relative; top: -12%; object-fit: cover; display: block; will-change: transform; }
.page-head:has(.page-head__media)::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--brand-deep) 96%, transparent) 0%, color-mix(in srgb, var(--brand-deep) 86%, transparent) 46%, color-mix(in srgb, var(--brand-deep) 48%, transparent) 100%),
              linear-gradient(180deg, color-mix(in srgb, var(--brand-deep) 72%, transparent) 0%, color-mix(in srgb, var(--brand-deep) 20%, transparent) 46%, color-mix(in srgb, var(--brand-deep) 62%, transparent) 100%); }
@media (prefers-reduced-motion: reduce) { .page-head__media img { height: 100%; top: 0; transform: none !important; } }
.page-head p { color: var(--ink-muted); }

/* Intro di sezione: colonna di misura leggibile, non riga piena. */
.section-intro { max-width: 48rem; margin-bottom: var(--space-7); }

/* ============================ Pagina Contatti (2 colonne) — sito reale ============================ */
.contact-cols { display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.contact-cols h2 { margin-bottom: var(--space-5); }
.contact-form { display: grid; gap: var(--space-4); }
.contact-form .row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.field { display: grid; gap: var(--space-2); }
.field label { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-muted); }
.field input, .field textarea {
  font: inherit; color: var(--ink); width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
}
.field textarea { resize: vertical; min-height: 8rem; }
.field input:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--accent-deco); }
/* ⚠ .consent è un flex: il testo (link incluso) va TUTTO in uno <span>, altrimenti l'<a> diventa un flex-item a sé. */
.consent { display: flex; align-items: flex-start; gap: var(--space-3); font-size: .92rem; color: var(--ink-muted); }
.consent input { margin-top: .25rem; flex: none; }
.consent a { color: var(--accent-text); text-decoration: underline; }
.contact-form button { justify-self: start; }
.form-note { margin-top: var(--space-1); }
.contact-info { background: var(--surface); border: var(--border); border-radius: var(--radius); padding: var(--space-6); }
.contact-info dl { display: grid; gap: var(--space-4); margin: 0; }
.contact-info dt { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--accent-text); }
.contact-info dd { margin: var(--space-1) 0 0; line-height: 1.6; }
.contact-info a { text-decoration: underline; text-underline-offset: 2px; }
.contact-info .btn { margin-top: var(--space-5); text-decoration: none; }
@media (max-width: 860px) {
  .contact-cols { grid-template-columns: 1fr; }
  .contact-form .row { grid-template-columns: 1fr; }
}

/* ============================ Footer ============================ */
.site-footer { background: var(--brand-deep); color: var(--on-dark); padding-block: var(--space-8) var(--space-6); }
.site-footer a:hover { color: var(--accent-fill); }
.site-footer__grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: var(--gutter); }
/* Voci di servizio (condizioni di vendita, recesso…) sotto i recapiti: e' dove un cliente le cerca, e il
   piè e' l'unico posto che compare su OGNI pagina. */
.site-footer__servizi { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: grid; gap: var(--space-2); }
.site-footer__servizi a { color: var(--on-dark); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--on-dark) 28%, transparent); padding-bottom: 1px; }
.site-footer__servizi a:hover { border-bottom-color: var(--accent-fill); color: var(--accent-fill); }
.site-footer .wordmark { color: var(--on-dark); }
.site-footer h4 { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--accent-fill); margin-bottom: var(--space-4); }
/* Il wordmark è condiviso con l'header (fondo chiaro), dove il suo <small> è --ink-muted: sul fondo scuro
   del footer quel valore scende sotto soglia → qui va il testo secondario da fondo scuro. */
.site-footer .wordmark small { color: var(--on-dark-muted); }
.site-footer p { color: var(--on-dark); opacity: .92; font-size: .95rem; }
.site-footer__tag { margin-top: var(--space-4); max-width: 34ch; }
.site-footer__demo { margin-top: var(--space-4); color: var(--on-dark-muted); font-size: var(--text-sm); }
/* ⚠ TRE CAMPI, non `space-between`: con la distribuzione automatica la posizione di «Powered by Dgitaly»
   dipende da quante voci le stanno accanto, e aggiungerne una la sposta. Il campo centrale la ancora al
   centro della riga qualunque cosa ci sia ai lati. */
.site-footer__legal { margin-top: var(--space-7); padding-top: var(--space-5); border-top: 1px solid color-mix(in srgb, var(--on-dark) 18%, transparent); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-4); color: var(--on-dark-muted); font-size: var(--text-sm); }
.site-footer__legal > :first-child { justify-self: start; }
.site-footer__legal > :last-child { justify-self: end; }
.site-footer__dgitaly { justify-self: center; }
@media (max-width: 720px) { .site-footer__legal { grid-template-columns: 1fr; justify-items: center; text-align: center; } .site-footer__legal > :first-child, .site-footer__legal > :last-child { justify-self: center; } }
.site-footer__dgitaly { display: inline-flex; align-items: center; gap: var(--space-2); }
.site-footer__dgitaly img { display: inline-block; }
@media (max-width: 860px) { .site-footer__grid { grid-template-columns: 1fr; } }

/* ============================ CTA bar mobile ============================ */
.cta-bar { display: none; }
@media (max-width: 820px) {
  .cta-bar {
    position: fixed; inset: auto 0 0 0; z-index: 40;
    display: grid; grid-template-columns: 1fr 1fr;
    background: var(--brand-deep); border-top: 1px solid color-mix(in srgb, var(--on-dark) 18%, transparent);
  }
  .cta-bar a { padding: var(--space-4); text-align: center; color: var(--on-dark); font-weight: 600; font-size: .95rem; }
  .cta-bar__call { background: var(--accent-fill); color: var(--ink); }   /* contratto: su arancio chiaro, testo ink (6.4:1) */
  body { padding-bottom: 56px; }
}

/* ============================ Menu mobile (overlay wp:navigation) ============================ */
/* ⚠ L'header ha backdrop-filter → containing-block per il fixed: senza questo, l'overlay si confina
   all'altezza dell'header e il menu risulta "rotto". ⚠ SPECIFICITÀ: WP dichiara l'overlay bianco con
   (0,4,0) → va ripreso lo stesso schema di selettore. */
.site-nav:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay),
.wp-block-navigation__responsive-container.is-menu-open {
  height: 100vh; max-height: 100vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--brand); color: var(--on-dark);
}
/* Le voci a SINISTRA: va messo su TUTTA la catena (è il padre largo quanto il viewport che spinge a destra). */
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item,
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
  align-items: flex-start; justify-content: flex-start;
}
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content { padding-left: var(--gutter); padding-bottom: 96px; }
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
  top: var(--space-4); right: var(--space-4); padding: var(--space-3); color: var(--on-dark); border-radius: var(--radius);
}
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:hover { background: color-mix(in srgb, var(--on-dark) 12%, transparent); }
.site-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close svg { width: 28px; height: 28px; stroke: currentColor; stroke-width: 1.4; }
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container { align-items: flex-start; }
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item { width: 100%; }
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content { width: 100%; text-align: left; }
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-icon { margin-left: auto; }
/* I sotto-menu su mobile stanno INLINE, non come card-dropdown desktop. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
  position: static !important; border: none !important; box-shadow: none !important; background: none !important; padding-left: var(--space-5);
}

/* ============================ Scroll-reveal (micro-JS IntersectionObserver) ============================ */
/* Fail-visible: senza JS il contenuto è già visibile. reduced-motion rivela tutto.
   ⚠ MAI `.reveal` su un contenitore di IMMAGINI: con opacity:0 il browser NON scarica le img che contiene.
   Il reveal MUOVE (transform), non tocca l'opacity dei testi vicino alla soglia AA. */
.js .reveal { opacity: 0; transform: translateY(24px); }
.js .prodotti__grid, .js .spec, .js .hero-media { opacity: 1; transform: none; }
.js .reveal.is-visible { opacity: 1; transform: none; transition: opacity 620ms var(--ease), transform 620ms var(--ease); transition-delay: calc(var(--reveal-i, 0) * 90ms); }
/* Il metodo "dal raccolto al barattolo" appare uno step alla volta, ogni ~1,2 secondi (richiesta cliente).
   Ogni step ha .reveal + --reveal-i (0..3); il container NON è .reveal. */
/* ⚠ Il passo dello scaglionamento e' un TOKEN. A 1200ms il quarto passo parte a 3,6s e finisce a 4,2s:
   chi scorre oltre la banda vede tre riquadri vuoti per qualche secondo, e non legge una narrazione,
   legge una pagina rotta. Il default resta 1200ms — il valore cablato di prima — quindi il primo
   cliente del verticale non cambia di un millisecondo. */
.js .pstep.reveal.is-visible { transition-delay: calc(var(--reveal-i, 0) * var(--pstep-stagger, 1200ms)); }
@media (prefers-reduced-motion: reduce) { .js .reveal { opacity: 1; transform: none; } }
