/* components.css — freight_carrier.
   Il segno del verticale è il MOSAICO DI TESSERE che alterna fotografie e campi pieni di colore
   (linguaggio di BeCorporation2) montato sulla struttura di BeLogistics2 (testata istituzionale a
   campo pieno, fascia di tessere con icona, banda scura a schede, sezione con checklist e flotta al
   vivo, piè col recapito grande).

   ⚠⚠ Perché il mosaico e non una fascia fotografica: il parco fotografico di questo mestiere è fatto
   di scatti di piazzale e di concessionaria, spesso 960×720. Una tessera da 420×315 li regge alla loro
   misura VERA; una banda full-bleed no. E i campi pieni riempiono dove una foto non c'è — che è anche
   il rimedio alla metà vuota, perché una sezione senza immagine qui non resta mezza bianca. */

/* ============================== bottoni ============================== */
/* Spigolo vivo: la categoria non arrotonda. */
.btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  border-radius: var(--radius); border: 1px solid transparent;
  padding: 1.05rem 1.85rem;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--tracking-label);
  text-transform: uppercase; line-height: 1;
  transition: background-color .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
/* ⚠ Il primario è PETROLIO col testo BIANCO: 6,39. L'inchiostro sul petrolio farebbe 2,76 — vietato. */
.btn--primary { background: var(--brand-mid); color: var(--on-brand-mid); }
.btn--primary:hover { background: var(--brand); }
.btn--ghost { background: var(--paper); color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--brand-mid); color: var(--brand-mid); }
/* Su fondo scuro il fantasma si inverte: il bordo tenue sul near-black sparirebbe. */
.banda .btn--ghost, .site-footer .btn--ghost {
  background: transparent; color: var(--on-dark); border-color: rgba(255,255,255,.42);
}
.banda .btn--ghost:hover, .site-footer .btn--ghost:hover {
  border-color: var(--accent-on-dark); color: var(--accent-on-dark);
}
/* ⚠ `--accent` è CAMPO PIENO, e il bianco sopra fa 4,72: regge come bottone (testo piccolo ma
   grassetto e tracciato), non come corpo di testo. */
/* ⚠⚠ Il bottone d'accento sta su `--accent-dark`, NON su `--accent`: il bianco su `--accent` misura
   4,25, sotto AA per un testo di 13px. Il file dei token lo dice a chiare lettere («campo pieno, mai
   testo») e la prima stesura lo violava lo stesso — scriverlo in un commento non lo fa rispettare.
   Su `--accent-dark` il bianco fa 7,07. */
.btn--accent { background: var(--accent-dark); color: #fff; }
.btn--accent:hover { background: #8d1c2c; }

/* ============================== occhielli e teste ============================== */
.occhiello {
  font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--brand-mid); margin-bottom: var(--space-3);
}
/* ⚠⚠ La banda di CHIUSURA non ha classe `.banda`: senza nominarla qui, il suo occhiello restava
   `--brand-mid` su `--brand-dark` = 2,67 — un token verificato su una superficie e usato su un'altra.
   È il difetto che nessun gate vede, perché il colore è «in palette». */
.banda .occhiello,
.banda-cta .occhiello { color: var(--accent-on-dark); }
/* ⚠⚠ REGOLA 21: lo spazio SOPRA un blocco di figure e quello SOTTO devono essere UGUALI. Il difetto
   nasce da solo: sopra c'è il margine della testa (54px) e sotto il padding pieno della sezione (94px),
   e l'occhio lo vede come «la sezione cade in basso». Legando il margine della testa allo STESSO token
   del padding di sezione, i due valori non possono più divergere — non è una taratura, è un vincolo. */
.testa { margin-bottom: var(--section-y); }
.testa h2 { font-size: var(--t-2xl); }
/* ⚠ La misura sta sul PARAGRAFO, non sulla testa: metterla sul contenitore stringerebbe anche il
   titolo, e `ch` si risolverebbe sul font del contenitore invece che sul display reso. */
/* ⚠⚠ «Questi testi devono prendere tutta l'area e andare a capo da soli»: un capoverso che si ferma a
   metà con l'area libera a destra è il difetto che l'owner segnala su tutto il sito. Dove NON c'è una
   figura accanto, il lead prende la riga intera e cresce di un gradino — a parità di larghezza un corpo
   più grande fa meno caratteri per riga, quindi riempie SENZA diventare illeggibile. */
.testa .lead { font-size: var(--t-lead); color: var(--ink-muted); margin-top: var(--space-3); max-width: var(--misura-lead); }
/* ⚠⚠ QUI C'ERA `text-wrap: balance`, ED È LA CAUSA DEL DIFETTO CHE L'OWNER HA FOTOGRAFATO DUE VOLTE.
   Il capoverso era largo 1248px — `max-width: none`, misurato — ma il bilanciamento spezzava il testo
   in righe UGUALI: due righe da 669px su 1248 disponibili, cioè il testo fermo nella metà sinistra con
   metà area vuota a destra. Sembrava una colonna stretta, e non lo era: era una riga piena divisa a
   metà. `balance` va bene su un'etichetta di due parole, mai su un capoverso di apertura. */
.banda .testa .lead,
.section:not(.metodo) .testa .lead { max-width: none; font-size: clamp(1.15rem, 1.15vw + .7rem, 1.5rem); }
.banda .testa .lead { color: var(--on-dark-muted); }
.prosa p { max-width: var(--misura-prosa); }
/* ⚠⚠ NIENTE COLONNE. Le avevo messe per riempire l'area, e riempivano — ma con UN SOLO capoverso il
   testo si spezza a metà frase fra una colonna e l'altra («…merce a temperatura | controllata…»), le
   due colonne finiscono a altezze diverse e l'occhio deve risalire. L'owner: «qui i testi non vanno
   bene». Un capoverso solo vuole UNA colonna, larga quanto l'area.
   ⚠ A riga piena il corpo cresce di un gradino: a parità di larghezza un carattere più grande fa meno
   caratteri per riga, quindi il capoverso riempie SENZA diventare un nastro illeggibile. */
.banda .prosa { margin-bottom: var(--section-y); }
.banda .prosa p {
  max-width: none;
  font-size: clamp(1.0625rem, .45vw + .95rem, 1.2rem);
  line-height: 1.72;
}

/* ============================== testata del sito ============================== */
/* Campo pieno istituzionale, non trasparente: la categoria dice «ente», non «studio creativo». */
.site-header { background: var(--brand-dark); color: var(--on-dark); position: sticky; top: 0; z-index: 50;
  transition: background-color .3s var(--ease), box-shadow .3s var(--ease); }
/* La testata si RESTRINGE scorrendo: il runtime alterna `.is-scrolled`, il foglio la anima. Non è un
   vezzo — restituisce alla pagina i 40px che la barra si prende, e dice al lettore che sta scorrendo. */
.site-header__row { display: flex; align-items: center; gap: var(--space-5); min-height: 84px;
  transition: min-height .3s var(--ease); }
.site-header.is-scrolled { box-shadow: 0 1px 0 rgba(255,255,255,.10), 0 10px 30px -12px rgba(0,0,0,.55); }
.site-header.is-scrolled .site-header__row { min-height: 62px; }
.site-header .wordmark__mark { transition: height .3s var(--ease); }
.site-header.is-scrolled .wordmark__mark { height: 34px; }
.site-header.is-scrolled .wordmark__txt b,
.site-header.is-scrolled .wordmark__txt span { font-size: .95rem; }
.site-header .wordmark__txt b, .site-header .wordmark__txt span { transition: font-size .3s var(--ease); }
/* ⚠ Regola 16: nav e CTA hanno un margine di blocco da WP che li spinge sotto il centro. */
.site-header__row > * { align-self: center; margin-block: 0; }

/* ⚠⚠ IL MARCHIO INTERO NON VA IN TESTATA. Misurato sul marchio del primo cliente: il petrolio fa
   2,67 sul fondo della testata (sotto la soglia 3,0 per grafica non testuale) e a 44px di altezza la
   parola più piccola del logotipo è alta 9px — illeggibile. Regola 7: marchio COMPATTO in negativo +
   testo nel font del verticale. ⚠ Il negativo si ricava dall'ALPHA del file, non da un ricalco a
   vettore: è il ricalco che dipinge di bianco le contro-forme (Sirtel, Puglisi). */
.wordmark { display: flex; align-items: center; gap: var(--space-3); flex: 0 0 auto; }
.wordmark__mark { height: 46px; width: auto; }
.wordmark__txt { display: flex; flex-direction: column; line-height: 1; font-family: var(--font-display); color: var(--on-dark); }
.wordmark__txt b { font-size: 1.125rem; font-weight: 600; letter-spacing: .13em; }
.wordmark__txt span { font-size: 1.125rem; font-weight: 700; letter-spacing: .055em; margin-top: .18rem; }

.site-nav { margin-left: auto; }
.site-header__cta { margin-left: var(--space-3); background: var(--accent-dark); color: #fff; }
.site-header__cta:hover { background: #8d1c2c; }

/* ⚠⚠ A PARITÀ DI SPECIFICITÀ VINCE WP: il CSS dei blocchi è iniettato DOPO il tema, quindi
   `.wp-block-navigation-item__content` (0,1,0) batterebbe un selettore di pari peso dichiarato prima.
   Il colore va dichiarato sul BLOCCO e con un livello in più, altrimenti le voci restano scure sul
   fondo scuro — è il difetto più ricorrente della flotta. */
.site-header .site-nav .wp-block-navigation-item__content,
.site-header .site-nav .wp-block-navigation-item__label {
  color: var(--on-dark); font-family: var(--font-body); font-size: var(--t-base); font-weight: 600;
  letter-spacing: .01em;
}
.site-header .site-nav .wp-block-navigation-item__content:hover,
.site-header .site-nav .current-menu-item .wp-block-navigation-item__content {
  color: var(--accent-on-dark);
}

/* --- menu mobile: overlay wp:navigation --- */
/* ⚠ L'overlay di WP è tenuto BIANCO da `:not(.has-background)…:not(.disable-default-overlay)` = (0,4,0):
   si vince solo RICOPIANDO il suo schema di selettore, non aggiungendo una classe. */
.wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open),
.wp-block-navigation__responsive-container.is-menu-open {
  background-color: var(--brand-dark);
}
.site-header .wp-block-navigation__responsive-container.is-menu-open {
  color: var(--on-dark);
  /* ⚠ Se la testata avesse un backdrop-filter, quello creerebbe un containing-block e l'overlay si
     fermerebbe all'altezza della testata. Qui non c'è, ma l'altezza si fissa comunque. */
  height: 100vh; max-height: 100vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
/* ⚠ Le voci erano incollate al bordo: senza respiro laterale un menu sembra privo di foglio di stile.
   Il rientro è quello del contenitore della pagina, così il menu aperto si allinea a ciò che copre. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  color: var(--on-dark); width: 100%; text-align: left; font-size: var(--t-lg);
  font-family: var(--font-display); font-weight: 600; letter-spacing: -.01em;
  padding: var(--space-4) var(--gutter);
  border-bottom: 1px solid rgba(255,255,255,.12);
  transition: background-color .2s var(--ease), padding-left .2s var(--ease);
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover,
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:focus-visible {
  background: rgba(255,255,255,.06); padding-left: calc(var(--gutter) + var(--space-2));
}
/* ⚠⚠ IL MENU MOBILE ESCE ALLINEATO A DESTRA, e non basta correggere l'<a>: ad allineare è
   `__responsive-container-content`, largo quanto il viewport. Ma NON è una questione di specificità —
   misurato nel DOM calcolato, WP scrive `align-items: var(--navigation-layout-justification-setting)`,
   e il valore arriva da `items-justified-right` sulla nav della testata, che è giusto sul desktop.
   Un `align-items: stretch` di pari peso PERDE, perché il CSS dei blocchi è iniettato DOPO il tema.
   ⇒ Si imposta la VARIABILE, non la proprietà: la dichiarazione sta sul contenitore aperto, che è più
   vicino del `nav` da cui la variabile discende, quindi vince per eredità invece che per forza.
   Così la nav resta a destra sul desktop, dov'è voluta, e va a sinistra solo dentro l'overlay. */
.site-header .wp-block-navigation__responsive-container.is-menu-open {
  --navigation-layout-justification-setting: flex-start;
  --navigation-layout-align: flex-start;
}
/* ⚠⚠ QUESTA REGOLA VALE SOLO A MENU APERTO — senza `.is-menu-open` colpiva anche il DESKTOP.
   Lo stesso `__responsive-container-content` avvolge le voci in riga sulla testata larga, e l’aria di
   fondo dell’overlay (96px, perché l’ultima voce non finisca sotto la barra CTA fissa) diventava
   lì un buco. Aritmetica misurata: lista 26px + 96px di rientro = `nav` alto 122px, testata cresciuta
   da 84 a 122, e le voci INCOLLATE AL BORDO SUPERIORE mentre marchio e bottone restavano centrati a
   metà. È per questo che il menu «si vedeva male»: non era allineato a nulla.
   Nessun gate lo vede — il contenitore c’è, il colore è giusto, il contrasto passa. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
  width: 100%; padding-inline: 0;
  /* l'ultima voce non deve finire sotto la barra CTA fissa */
  padding-bottom: 96px;
}
/* ⚠ La variabile raddrizza il CONTENITORE ma non la lista: misurato, la `ul` resta larga quanto la
   voce più lunga (94px su 390) e le voci si centrano dentro di lei. La larghezza è un fatto di
   LAYOUT, non di allineamento, e va detta: `ul` e `li` a tutta riga, così l'<a> — che è già
   `width:100%` e `text-align:left` — parte davvero dal bordo. Il selettore ha TRE livelli e ricopia
   lo schema di WP (`…__responsive-container.is-menu-open …`), che a pari peso vincerebbe perché il
   CSS dei blocchi è iniettato dopo il tema. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
  width: 100%; align-items: flex-start;
}
.site-header .wp-block-navigation__responsive-container-close,
.site-header .wp-block-navigation__responsive-container-open {
  color: var(--on-dark);
  /* area di tocco dichiarata: chrome-mobile la esige sul bottone di chiusura */
  min-width: 44px; min-height: 44px;
}

/* ============================== TESTATA (hero): pannello + mosaico ============================== */
.hero { background: var(--surface); }
/* ⚠⚠ Due campate UGUALI col GAP COMUNE: così lo stacco fra pannello e mosaico cade su una linea del
   reticolo (misurata a 730, la settima traccia) e il mosaico può allinearsi a sua volta. L'aria fra le
   due campate NON si dà allargando il gap — sposterebbe la traccia e romperebbe il reticolo — ma col
   PADDING INTERNO del pannello, che non muove il riquadro. */
.hero__grid {
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: var(--gap-griglia); align-items: center;
  padding-block: clamp(3.5rem, 6vw, 6.5rem);
}
.hero__panel { padding-right: clamp(0rem, 3vw, 3.5rem); }
.hero__panel h1 { font-size: var(--t-3xl); max-width: var(--misura-titolo); }
/* ⚠ Il device «parte del titolo nell'accento» vive QUI, su fondo chiaro: quindi usa `--accent-ink`
   (5,58), non `--accent` (4,25, sotto AA) né `--accent-on-dark` (2,86). */
.hero__panel h1 .accento { color: var(--accent-ink); }
.hero__lead { font-size: var(--t-lead); color: var(--ink-muted); margin-top: var(--space-4); max-width: var(--misura-hero-lead); }
.hero__checks {
  margin: var(--space-5) 0 var(--space-6);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-2) var(--space-5);
}
.hero__checks li { display: flex; gap: var(--space-2); align-items: flex-start; font-size: var(--t-sm); }
.hero__checks svg { flex: 0 0 auto; margin-top: .28rem; color: var(--brand-mid); }
.hero__cta { display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* ============================== LA SCENA: le foto del cliente a tutto schermo ==============================
   Owner, 2026-09-11: «metterei un'immagine a tutto schermo qui, magari che si alternano, con un
   effetto di movimento». Le sei fotografie che stavano nel mosaico diventano la scena: stesse foto,
   stesso numero, nessuna persa — e la soglia della variante resta quella (servono SEI scatti che
   reggano la propria misura, non uno grande).
   ⚠⚠ IL RICAMBIO È DI FOGLIO, NON DI RUNTIME. Una sola animazione e sei ritardi: niente JavaScript da
   aggiungere al runtime condiviso, che è congelato — e un dispositivo «carosello» scritto per un
   cliente sarebbe l'accoppiamento verticale↔cliente che questo verticale evita per costruzione. */
.scena {
  position: relative; overflow: clip;
  /* «a tutto schermo» alla lettera: la finestra meno la testata, con un tetto perché su un monitor
     altissimo un'apertura di 1400px diventa una stanza vuota. `dvh` e non `vh`: su mobile la barra
     dell'indirizzo che si ritrae cambia `vh` e l'apertura «saltava» durante lo scorrimento. */
  min-height: min(calc(100dvh - 84px), 900px);
  display: grid; grid-template-rows: 1fr auto;
  background: var(--brand-dark); color: var(--on-dark);
}
.scena__rullo { position: absolute; inset: 0; }
.scena__foto {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* ⚠ Lo stato a riposo è INVISIBILE: se l'animazione non parte (JS assente non c'entra, ma un browser
     antico sì) resta il fondo scuro col testo leggibile, non sei foto sovrapposte. La prima però deve
     vedersi comunque: sta sotto, con opacità piena, e le altre le passano sopra. */
  opacity: 0;
  animation: fp-scena 36s linear infinite both;
}
.scena__foto:nth-child(1) { animation-delay: 0s; }
.scena__foto:nth-child(2) { animation-delay: 6s; }
.scena__foto:nth-child(3) { animation-delay: 12s; }
.scena__foto:nth-child(4) { animation-delay: 18s; }
.scena__foto:nth-child(5) { animation-delay: 24s; }
.scena__foto:nth-child(6) { animation-delay: 30s; }
/* Sei finestre da 6s in un giro da 36s: 1s di dissolvenza in entrata, 4s di posa, 1s in uscita, e il
   lento avvicinamento che dà il respiro (non uno zoom: 6 punti percentuali in sei secondi). */
@keyframes fp-scena {
  0%     { opacity: 0; transform: scale(1.04); }
  2.8%   { opacity: 1; }
  13.9%  { opacity: 1; }
  16.7%  { opacity: 0; }
  100%   { opacity: 0; transform: scale(1.10); }
}
/* ⚠⚠ IL VELO SI TARA SUL FOTOGRAMMA PEGGIORE, non su quello medio: sei foto diverse passano sotto lo
   stesso testo, e una di esse è un piazzale al tramonto quasi bianco. Il primo gradiente porta il
   lato del testo quasi a tinta piena (il bianco ci fa 15,9 misurati dal pixel); il secondo stacca la
   testata in alto e appoggia la fascia dei dati in basso. */
.scena__velo {
  position: absolute; inset: 0;
  background:
    linear-gradient(96deg, rgba(13,31,31,.985) 0 34%, rgba(13,31,31,.93) 50%, rgba(13,31,31,.56) 78%, rgba(13,31,31,.34) 100%),
    linear-gradient(180deg, rgba(13,31,31,.62) 0, rgba(13,31,31,0) 20%, rgba(13,31,31,0) 58%, rgba(13,31,31,.80) 100%);
}
.scena__corpo { position: relative; align-self: center; padding-block: clamp(3rem, 6vw, 5.5rem); }
/* ⚠ Il pannello NON prende tutta la campata: sopra una fotografia il testo vuole un bordo di respiro,
   o sembra incollato al vetro. 58% è la misura in cui il titolo va a capo dove deve. */
.scena .hero__panel { max-width: min(58%, 46rem); }
/* --- il testo della scena vive su fondo SCURO: ogni colore tarato sul chiaro qui va rifatto --- */
.scena .occhiello { color: var(--accent-on-dark); }
.scena h1 { color: var(--on-dark); }
.scena .hero__panel h1 .accento { color: var(--accent-on-dark); }
.scena .hero__lead { color: var(--on-dark-muted); }
.scena .hero__checks svg { color: var(--accent-on-dark); }
.scena .hero__checks li { color: var(--on-dark); }
.scena .btn--ghost { background: transparent; color: var(--on-dark); border-color: rgba(255,255,255,.46); }
.scena .btn--ghost:hover { border-color: var(--accent-on-dark); color: var(--accent-on-dark); }

/* La fascia dei dati chiude la scena e le fa da piano d'appoggio: sono le stesse parole che stavano
   nelle targhe del mosaico. */
.scena__dati {
  position: relative; display: flex; align-items: flex-end; gap: clamp(2rem, 5vw, 5rem);
  padding-block: var(--space-4) var(--space-5);
  border-top: 1px solid rgba(255,255,255,.16);
}
.dato { display: flex; flex-direction: column; }
.dato__et { font-size: var(--t-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--accent-on-dark); margin-bottom: .35rem; }
.dato b { font-family: var(--font-display); font-size: clamp(1.5rem, 2.4vw, 2.25rem); line-height: 1; color: var(--on-dark); }
/* La freccia non è un vezzo: su un'apertura alta quanto la finestra dice che sotto c'è dell'altro. */
.scena__giu {
  margin-left: auto; width: 48px; height: 48px; display: grid; place-items: center;
  border: 1px solid rgba(255,255,255,.30); color: var(--on-dark);
  transition: background-color .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
  animation: fp-giu 2.6s var(--ease) infinite;
}
.scena__giu:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
@keyframes fp-giu { 0%, 72%, 100% { transform: none; } 84% { transform: translateY(5px); } }

@media (max-width: 900px) {
  .scena { min-height: min(calc(100dvh - 84px), 640px); }
  .scena .hero__panel { max-width: none; }
  /* Su schermo stretto il testo copre quasi tutta la foto: il velo diventa verticale, o il titolo
     finisce sopra la parte chiara dello scatto. */
  .scena__velo {
    background: linear-gradient(180deg, rgba(13,31,31,.93) 0 54%, rgba(13,31,31,.78) 76%, rgba(13,31,31,.86) 100%);
  }
  .scena__dati { flex-wrap: wrap; gap: var(--space-4) var(--space-5); }
  .scena__giu { display: none; }
}
/* ⚠ Chi ha chiesto meno movimento vede UNA fotografia ferma — la prima — non sei che si alternano. */
@media (prefers-reduced-motion: reduce) {
  .scena__foto { animation: none; }
  .scena__foto:nth-child(1) { opacity: 1; }
  .scena__giu { animation: none; }
}

/* --- il mosaico --- */
/* ⚠ `dense` chiude i buchi lasciati dalle tessere che scavalcano: senza, il mosaico resta sfrangiato
   in basso, e un buco col tono del fondo legge come errore di caricamento, non come tessera. */
/* ⚠ TRE colonne, non quattro: la campata vale 6 tracce del reticolo, e 6 diviso 3 fa 2 tracce esatte
   per colonna — quindi ogni tessera parte su una linea. Con quattro colonne la divisione non tornava e
   il mosaico galleggiava fuori griglia (misurato: 2 bordi su 4 fuori). Le tessere guadagnano anche
   misura, che a queste fotografie serve. */
.mosaico {
  display: grid; grid-template-columns: repeat(3, 1fr);
  /* ⚠⚠ Il mosaico usa il GAP COMUNE, non uno suo. Le sue quattro colonne occupano esattamente quattro
     tracce del reticolo di pagina (misurato: 733, 839, 945, 1051), quindi col gap comune le tessere
     cadono sulle stesse linee di tutte le altre griglie. Con un gap proprio galleggiavano fuori
     reticolo: un mosaico dev'essere PARTE della griglia, non un riquadro appoggiato sopra. */
  grid-auto-rows: clamp(5.5rem, 8.4vw, 8.75rem); gap: var(--gap-griglia); grid-auto-flow: row dense;
}
.mosaico > * { overflow: hidden; }
.mosaico img { width: 100%; height: 100%; object-fit: cover; }
.mosaico .t-brand { background: var(--brand-mid); }
.mosaico .t-scuro { background: var(--brand); }
.mosaico .t-neutra { background: var(--sage); }
.mosaico .s22 { grid-column: span 2; grid-row: span 2; }
.mosaico .s21 { grid-column: span 2; }
.mosaico .s12 { grid-row: span 2; }
/* ⚠⚠ Un campo di colore in un mosaico deve PORTARE qualcosa, o il cliente lo legge come «una foto che
   non si vede». La targa porta SOLO ciò che il cliente scrive di sé: nessuna frase nostra.
   ⚠ L'occhiello va SOPRA il numero — «DAL / 2013» si legge, «2013 / DAL» no. */
.targa {
  background: var(--brand); color: var(--on-dark);
  display: flex; flex-direction: column; justify-content: center; padding: var(--space-3);
}
.targa__occhiello { font-size: var(--t-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--accent-on-dark); margin-bottom: .4rem; }
.targa b { font-family: var(--font-display); font-size: clamp(1.6rem, 2.6vw, 2.5rem); line-height: 1; }
.targa__unita { font-size: var(--t-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--on-dark-muted); margin-top: .35rem; font-style: normal; }

/* --- variante design-only: nessuna fotografia regge, il mosaico resta di soli campi --- */
/* Mai foto finte: se `gallery_ok` non arriva alla soglia, le tessere sono colore e tipografia. */
.hero--design .mosaico img { display: none; }

/* ============================== filmato di testata ============================== */
/* Banda a tutta larghezza sotto l'apertura: e' il «mezzo in movimento» del riferimento di struttura.
   Nessun testo sopra il filmato — un velo su pixel che si muovono e' un contrasto che cambia a ogni
   fotogramma, e non si puo' misurare una volta sola. */
.video-testata {
  margin: 0; position: relative; overflow: hidden; will-change: transform;
  height: clamp(15rem, 42vh, 34rem); background: var(--brand-dark);
}
/* ⚠⚠ La parallasse sposta fino a |p|·amp e |p| NON si ferma a 1: arriva a ~1,15. Con amp 9% la corsa
   vale ~10,4% dell'altezza, quindi il media è alto il 124% del riquadro e parte spostato in alto: così
   la corsa non SCOPRE mai il fondo del contenitore. Senza questo sovradimensionamento si vede la banda
   nuda sotto il filmato — il difetto pagato due volte sulla flotta. */
.video-testata__media,
.video-testata__fermo { width: 100%; height: 124%; object-fit: cover; display: block;
  position: absolute; inset: -12% 0 auto 0; }
/* Il fermo-immagine e' reso ACCANTO al filmato e normalmente non si vede. */
.video-testata__fermo { display: none; }
/* ⚠ Chi ha chiesto meno animazioni vede il fotogramma fermo, non il filmato. Senza JavaScript il file
   puo' comunque essere scaricato: la richiesta riguarda il MOVIMENTO, che qui e' tolto. */
@media (prefers-reduced-motion: reduce) {
  .video-testata__media { display: none; }
  .video-testata__fermo { display: block; }
}

/* ============================== fascia dei tre pilastri ============================== */
/* Device di BeLogistics2 (le quattro tessere con icona sotto l'apertura).
   ⚠⚠ Tre parole sole su schermo largo sono aria pura: ogni pilastro porta sotto una riga del testo
   DEL CLIENTE che lo sostanzia, e i divisori verticali governano lo spazio. */
/* ⚠ I filetti verticali obbligavano la fascia a gap ZERO, e le sue colonne cadevano 8px prima di tutte
   le altre griglie della pagina. Diventano TESSERE sulla griglia comune: stesso gap, stessi bordi, e
   la separazione la dà la superficie invece di una riga di un pixel. */
.pilastri { background: var(--paper); }
.pilastri__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: var(--gap-griglia); }
.pilastro { padding: clamp(1.6rem, 2.4vw, 2.4rem); background: var(--surface); border-top: 3px solid var(--brand-mid); }
.pilastro__ico { width: 46px; height: 46px; color: var(--brand-mid); margin-bottom: var(--space-4); }
.pilastro h3 { font-size: var(--t-lg); letter-spacing: .1em; text-transform: uppercase; margin-bottom: var(--space-2); }
.pilastro p { font-size: var(--t-sm); color: var(--ink-muted); max-width: var(--misura-tessera); }


/* ============================== banda scura + schede ============================== */
.banda { background: var(--brand); color: var(--on-dark); padding-block: var(--section-y); }
.banda--profonda { background: var(--brand-dark); }
.banda h2, .banda h3 { color: var(--on-dark); }
.schede { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: var(--gap-griglia); }
.scheda { background: var(--brand-dark); display: flex; flex-direction: column; }
.scheda img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.scheda__corpo { padding: var(--space-4) var(--space-4) var(--space-5); }
.scheda h3 { font-size: var(--t-base); letter-spacing: .05em; text-transform: uppercase; color: var(--accent-on-dark); margin-bottom: var(--space-2); line-height: var(--lh-snug); }
.scheda p { font-size: var(--t-scheda); color: var(--on-dark-muted); max-width: var(--misura-tessera); }

/* ============================== metodo: checklist + flotta al vivo ============================== */
/* Device «Available routes» di BeLogistics2: testo e checklist a sinistra, la flotta che esce dal
   bordo destro. ⚠ La foto esce dal contenitore ma NON deve produrre scroll orizzontale. */
.metodo { position: relative; overflow-x: clip; }
/* ⚠⚠ QUI C'ERA `align-items: center`, ED È IL MODO IN CUI NASCE «un sacco di vuoto sopra e sotto la
   foto». La colonna di sinistra porta titolo, due capoversi e sette voci di checklist: è alta il
   doppio. Centrando, la fotografia galleggia in mezzo a due fasce di niente — misurate 214px sopra e
   214px sotto. Non è un problema di spaziatura: è la domanda sbagliata fatta alla griglia.
   ⇒ La fotografia STA CON IL LETTORE: riempie la colonna, esce dal bordo destro dello schermo e si
   ferma mentre la checklist scorre. Il vuoto sparisce perché non c'è più niente da centrare. */
.metodo__grid { display: grid; grid-template-columns: minmax(0,1.05fr) minmax(0,.95fr); gap: clamp(2rem,4vw,4rem); align-items: stretch; }
.metodo__foto { align-self: stretch; position: relative;
  /* Esce fino al bordo della finestra: è il device del riferimento di struttura, e senza di esso la
     colonna destra resta un riquadro appoggiato. La distanza dal bordo del contenitore al bordo dello
     schermo è la stessa che il contenitore si lascia ai lati. `overflow-x: clip` sulla sezione
     impedisce che ne nasca una barra orizzontale. */
  margin-right: calc(-1 * max(var(--gutter), (100vw - var(--container)) / 2));
}
/* ⚠ Lo `sticky` va sull'IMMAGINE, non sulla figure: uno sticky si muove dentro il proprio contenitore,
   e la figure è alta quanto la riga — non le resta spazio in cui muoversi. È la stessa trappola della
   testata dentro `.wp-block-template-part`. La figure fa da binario, l'immagine da carrello. */
.metodo__foto img {
  position: sticky; top: calc(84px + var(--space-4));
  width: 100%; height: min(72vh, 620px); object-fit: cover; object-position: center;
}
/* ⚠ La regola 21 lega il margine della testa al padding di sezione perché sopra e sotto una FIGURA
   l'aria dev'essere uguale. Qui sotto la testa non c'è una figura ma altra prosa, nella stessa colonna:
   quel margine diventa un buco in mezzo a un discorso. Nella colonna di testo l'aria è quella dei
   capoversi. */
.metodo .testa { margin-bottom: var(--space-5); }
@media (max-width: 980px) {
  .metodo__foto { margin-right: 0; align-self: auto; }
  .metodo__foto img { position: static; height: auto; }
}
.checklist { display: grid; gap: 0; margin-top: var(--space-5); }
.checklist li { display: flex; gap: var(--space-3); align-items: flex-start; padding-block: var(--space-3); border-bottom: 1px solid var(--line); font-size: var(--t-sm); }
.checklist li:first-child { border-top: 1px solid var(--line); }
.checklist svg { flex: 0 0 auto; margin-top: .22rem; color: var(--accent-ink); }
.banda .checklist li { border-color: rgba(255,255,255,.16); }
.banda .checklist svg { color: var(--accent-on-dark); }

/* ============================== servizi: tessere di testo ============================== */
/* ⚠ L'aria verticale fra due file di tessere si dà col padding della tessera, non con un gap più
   largo: allargare il gap sposterebbe la traccia e romperebbe l'allineamento con le altre griglie. */
/* ⚠⚠ NON UNA GRIGLIA: SEI VOCI IN QUATTRO COLONNE LASCIANO DUE CELLE VUOTE IN BASSO A DESTRA, ed è
   letteralmente «la metà destra resta bianca» — la regola 5 dell'owner. In più le sei voci hanno
   lunghezze molto diverse (14 righe contro 8) e in una griglia la riga è alta quanto la voce più
   lunga: sotto le corte restava un buco. Misurato: aria morta 28% e griglia alta 1016px.
   Con TRE colonne che IMPAGINANO (le voci si incolonnano e si bilanciano) non restano celle vuote e
   l'aria morta scende a 19%, con la fascia alta 812px. Il numero 01…06 è scritto su ogni voce, quindi
   leggere per colonne non disorienta.
   ⚠ `break-inside: avoid` QUI è giusto — è il caso opposto alla prosa della banda: tanti blocchi
   corti, ognuno dei quali deve restare intero. Su un capoverso solo sarebbe il difetto che ho tolto. */
.servizi__grid { columns: 3; column-gap: var(--gap-griglia); }
.servizio { padding-block: var(--space-3); break-inside: avoid; margin-bottom: var(--gap-griglia); }
@media (max-width: 980px) { .servizi__grid { columns: 2; } }
@media (max-width: 640px) { .servizi__grid { columns: 1; } }
.servizio h3 { font-size: var(--t-lg); margin-bottom: var(--space-2); }
.servizio p { font-size: var(--t-sm); color: var(--ink-muted); max-width: var(--misura-tessera); }
.servizio__num { font-family: var(--font-display); font-size: var(--t-sm); font-weight: 700; color: var(--accent-ink); letter-spacing: var(--tracking-label); display: block; margin-bottom: var(--space-2); }

/* ⚠⚠ SEZIONE SENZA FOTOGRAFIE: cambia TELAIO, non solo contenuto.
   Larghezza piena e DUE COLONNE di testo, mai il telaio a due colonne del testo+immagine con la metà
   destra bianca. È l'errore che nessun gate vede: axe non misura l'aria e lo scorer non conosce la
   metà vuota — e a 1440px si vede molto meno che su un monitor largo. */
/* ⚠ La classe a DUE COLONNE è stata tolta, non dimenticata: non la usa nessun pattern, e portava
   `break-inside: avoid` — cioè esattamente il modo in cui una prosa a colonne si rompe (un capoverso
   solo resta tutto nella prima e la seconda rimane vuota). Un'utilità morta che incorpora un difetto
   noto è peggio di nessuna utilità: il prossimo cliente se la ritroverebbe addosso.
   La larghezza piena, che era lo scopo, resta: `.prosa p { max-width: none }` dove non c'è figura. */

/* ============================== mosaico fotografico (gallery) ============================== */
/* ⚠ `minmax(230px,…)` dava CINQUE colonne sul contenitore da 1248px, e con sei fotografie lasciava
   una SESTA orfana su una riga da sola: legge come un errore di caricamento, non come una scelta.
   A 320px le colonne diventano tre (3×320+2×gap = 995 ≤ 1248; quattro ne chiederebbero 1333) e le sei
   tessere chiudono due righe piene. Le foto guadagnano anche misura: da ~240px a ~400px. */
.galleria { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--gap-griglia); }
.galleria figure { margin: 0; overflow: hidden; background: var(--sage); }
/* ⚠ Le tessere erano 4/3 e le grafiche di marca sono 16:9: il ritaglio TAGLIAVA il marchio del
   cliente sul bordo. Un logo mozzato e un logo sfocato sono lo stesso errore. A 16/9 le grafiche
   restano intere e le fotografie dei mezzi — soggetti larghi — reggono il ritaglio in altezza. */
.galleria img { width: 100%; aspect-ratio: 16/9; object-fit: cover; transition: transform .5s var(--ease); }
.galleria figure:hover img { transform: scale(1.04); }

/* ============================== dati: recapiti e orari ============================== */
.dati { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--gap-griglia); }
.dati dt { font-size: var(--t-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-muted); margin-bottom: var(--space-1); }
.dati dd { margin: 0 0 var(--space-3); font-size: var(--t-base); }
.banda .dati dt { color: var(--on-dark-muted); }
/* ⚠ TRE recapiti telefonici e nessun fisso: stanno come CONTENUTO, in righe distinte. Il solo
   principale è `business.contacts.phone`, che alimenta tel: e schema.org. */
.recapiti a:hover { color: var(--accent-ink); }
.banda .recapiti a:hover { color: var(--accent-on-dark); }

/* ============================== FAQ ============================== */
.faq { display: grid; gap: 0; }
.faq details { border-bottom: 1px solid var(--line); }
.faq details:first-child { border-top: 1px solid var(--line); }
.faq summary {
  display: flex; justify-content: space-between; align-items: center; gap: var(--space-3);
  padding-block: var(--space-4); cursor: pointer; list-style: none;
  font-family: var(--font-display); font-size: var(--t-lg); font-weight: 700;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-size: 1.4em; line-height: 1; color: var(--accent-ink); flex: 0 0 auto; }
.faq details[open] summary::after { content: "\2212"; }
.faq__risposta { padding-bottom: var(--space-4); color: var(--ink-muted); max-width: var(--misura-quesito); }

/* ============================== banda di chiusura ============================== */
.banda-cta { background: var(--brand-dark); color: var(--on-dark); padding-block: var(--section-y); text-align: center; }
.banda-cta h2 { color: var(--on-dark); font-size: var(--t-2xl); }
.banda-cta .lead { color: var(--on-dark-muted); margin: var(--space-3) auto var(--space-5); max-width: var(--misura-lead); }

/* ============================== piè ============================== */
.site-footer { background: var(--brand-dark); color: var(--on-dark-muted); padding-block: var(--space-7) var(--space-5); }
.site-footer__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--gap-griglia); }
.site-footer h3 { font-size: var(--t-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--on-dark-muted); margin-bottom: var(--space-3); font-family: var(--font-body); font-weight: 600; }
/* Il recapito grande: device di BeCorporation2 — chi cerca un vettore cerca chi risponde.
   ⚠ Ma TRE numeri alla stessa taglia sono tre urla uguali: a 34px l'uno occupavano il piè e nessuno
   dei tre sembrava il principale. Il primo resta grande perché è quello che alimenta tel: e
   schema.org; gli altri due scendono di un gradino e diventano una lista. È gerarchia, non sconto. */
.site-footer__tel { font-family: var(--font-display); font-weight: 700; color: var(--on-dark);
  line-height: var(--lh-tight); display: block; font-size: 1.0625rem; letter-spacing: -.01em;
  transition: color .18s var(--ease); }
.site-footer__tel--principale { font-size: clamp(1.35rem, 1.9vw, 1.75rem); margin-bottom: var(--space-2); }
.site-footer__tel + .site-footer__tel { margin-top: .3rem; }
.site-footer__tel:hover { color: var(--accent-on-dark); }
.site-footer__legale { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid rgba(255,255,255,.14); font-size: var(--t-xs); display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); align-items: center; }
.site-footer a:hover { color: var(--accent-on-dark); }
/* ⚠ target-size (WCAG 2.2, 24×24): i collegamenti IMPILATI in colonna — recapiti, voci del piè,
   «Apri nelle mappe» — sono alti 20px e non sono esenti come lo sarebbe un link dentro una frase.
   Bastano due pixel di respiro sopra e sotto: l'area cresce senza muovere il testo di una riga. */
/* ⚠⚠ `:not(.social__link)` NON è pignoleria: questa regola è (0,1,1) e batteva `.social__link` (0,1,0),
   dichiarata PRIMA. Il cerchio dei social smetteva di essere un contenitore flessibile — diventava
   `inline-block` con 2px di rientro — e l'icona, invece di stare al centro, si appoggiava in alto a
   sinistra: misurato, 11px fuori asse in orizzontale e 8,3 in verticale su un cerchio da 44.
   Il collegamento social l'area di tocco ce l'ha già (44×44): questa regola non gli serve. */
.site-footer__grid a:not(.social__link),
.dati a { display: inline-block; padding-block: 2px; min-height: 24px; }
.site-footer__grid li { line-height: 1.9; }
/* ⚠ Anche il badge sta sotto i 24px di altezza: e' un collegamento come gli altri. */
.dgitaly { display: inline-flex; align-items: center; gap: .45rem; margin-left: auto;
  padding-block: 2px; min-height: 24px; }
.dgitaly img { width: 20px; height: 20px; }

/* ============================== social ============================== */
/* ⚠ SOLO Facebook: i social del sito attuale del cliente erano i SEGNAPOSTO mai configurati del tema
   (facebook.com/fanpage, instagram.com/myinstagram), non link sbagliati. Un verticale che dichiara
   più canali invita a riempirli con quelli di nessuno. */
.social { display: flex; gap: var(--space-3); }
.social__link {
  position: relative; width: 44px; height: 44px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,.3); color: var(--on-dark);
  transition: background-color .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
/* ⚠⚠ `display: block` NON è decorativo: uno <span> è `display: inline`, e su un inline `width` e
   `height` NON si applicano. La maschera era dichiarata, il computato la mostrava, e l'elemento
   misurava 0×0 — l'icona non si vedeva. La regola scritta non è la regola applicata. */
/* ⚠ 22px su un cerchio da 44 = metà esatta: il marchio riempie senza toccare il bordo. A 20px con la
   cornice larga dell'originale il glifo occupava un terzo scarso e si leggeva come un puntino. */
.social__ico { display: block; width: 22px; height: 22px; background: currentColor;
  -webkit-mask: url("../assets/img/icons/social-facebook.svg") no-repeat center / contain;
          mask: url("../assets/img/icons/social-facebook.svg") no-repeat center / contain; }
/* Il battito: un alone che si allarga e svanisce. Sta su uno pseudo-elemento perché il cerchio vero
   deve restare cliccabile e di dimensione ferma — un `transform` sul link sposterebbe il bersaglio. */
.social__link::after {
  content: ""; position: absolute; inset: -1px; border-radius: 50%; pointer-events: none;
  animation: fp-social-pulse 2.8s var(--ease) infinite;
}
.social__link:hover, .social__link:focus-visible {
  color: var(--brand-dark); background: var(--accent-on-dark); border-color: var(--accent-on-dark);
}
/* Fermo sotto il puntatore: chi sta per cliccare non ha bisogno di essere richiamato. */
.social__link:hover::after { animation-play-state: paused; }
@keyframes fp-social-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-on-dark) 55%, transparent); }
  70%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--accent-on-dark) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-on-dark) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .social__link::after { animation: none; } }

/* I corpi delle sezioni senza figura accanto riempiono l'area su due colonne, come le bande. */
.galleria-sez .prosa, .banda-cta__seconda { }
/* Stessa ragione della banda: un capoverso solo, una colonna sola, larga quanto l'area. */
.galleria-sez .prosa { margin-bottom: var(--section-y); }
.galleria-sez .prosa p {
  max-width: none;
  font-size: clamp(1.0625rem, .45vw + .95rem, 1.2rem);
  line-height: 1.72;
}
.banda-cta__seconda { max-width: none; margin-top: var(--space-2); }

/* ============================== moto ==============================
   ⚠ «Moderno» non è «animato»: è RISPONDENTE e COERENTE. Ogni movimento qui ha un compito — dire che
   una sezione è entrata, che un elemento è toccabile, che il mestiere è il movimento — e tutti usano
   la stessa curva e tempi vicini, perché è l'uniformità a leggere come cura.
   Tutto sotto `.js` (fail-visible senza JavaScript) e tutto spento da prefers-reduced-motion. */

/* Il filetto che si DISEGNA sotto l'occhiello quando la sezione entra: piccolo segnale di soglia. */
.occhiello { position: relative; padding-bottom: .55rem; }
.occhiello::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
  background: currentColor; opacity: .55;
}
.js .reveal.is-visible .occhiello::after,
.js .reveal.is-visible.occhiello::after { animation: fp-filetto .7s var(--ease) .15s forwards; }
@keyframes fp-filetto { from { width: 0; } to { width: 2.75rem; } }

/* I campi pieni del mosaico non sono buchi: un lampo lentissimo li attraversa e dice che sono vivi.
   ⚠ Nessun `filter` e nessun `backdrop-filter`: creerebbero un containing-block e romperebbero lo
   sticky della testata — è la stessa famiglia di trappola già pagata. */
.mosaico .t-brand, .mosaico .t-scuro { position: relative; overflow: hidden; }
.mosaico .t-brand::after, .mosaico .t-scuro::after {
  content: ""; position: absolute; inset: -50%;
  background: linear-gradient(115deg, transparent 42%, rgba(255,255,255,.13) 50%, transparent 58%);
  animation: fp-lampo 7s linear infinite;
}
.mosaico .t-scuro::after { animation-delay: 2.3s; }
@keyframes fp-lampo { 0% { transform: translateX(-60%); } 55%, 100% { transform: translateX(60%); } }

/* Le targhe entrano dal basso con la cifra che si assesta: è il dato del cliente, merita un ingresso. */
.js .targa b { display: block; transform: translateY(.18em); transition: transform .6s var(--ease) .2s; }
.js .reveal.is-visible .targa b, .js .targa b { transform: none; }

/* Il bottone primario: l'alone che si allarga UNA volta all'ingresso in vista, poi tace. Un invito che
   insiste è rumore; uno che si annuncia e smette è un invito. */
.btn--primary { position: relative; overflow: hidden; }
.btn--primary::after {
  content: ""; position: absolute; inset: 0; background: rgba(255,255,255,.18);
  transform: translateX(-101%);
}
.btn--primary:hover::after { animation: fp-scia .55s var(--ease) forwards; }
@keyframes fp-scia { to { transform: translateX(101%); } }

/* La freccia della lista dei servizi complementari avanza al passaggio. */
.checklist li { transition: padding-left .25s var(--ease), background-color .25s var(--ease); }
.checklist li:hover { padding-left: var(--space-2); background: var(--surface); }
.banda .checklist li:hover { background: rgba(255,255,255,.05); }

/* La FAQ: il segno che ruota invece di scambiarsi, e la risposta che scende. */
.faq summary::after { transition: transform .3s var(--ease); }
.faq details[open] summary::after { content: "+"; transform: rotate(45deg); }
.faq summary:hover { color: var(--accent-ink); }

@media (prefers-reduced-motion: reduce) {
  .occhiello::after { width: 2.75rem; animation: none; }
  .mosaico .t-brand::after, .mosaico .t-scuro::after { animation: none; }
  .js .targa b { transform: none; transition: none; }
  .btn--primary::after, .checklist li, .faq summary::after { animation: none !important; transition: none !important; }
}

/* ============================== stati e vita ==============================
   ⚠ «Il sito sembra vecchio» non si cura con un'animazione vistosa: si cura con la RISPOSTA. Ogni cosa
   toccabile reagisce, e la reazione è breve e uguale ovunque — è la coerenza a leggere come cura. */
.scheda, .servizio, .galleria figure, .pilastro {
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), background-color .35s var(--ease);
}
/* ⚠ LE TRE TESSERE NON SI MUOVONO PIÙ AL PASSAGGIO DEL MOUSE. Owner, 2026-09-11: «meglio se rimangono
   fisse, quando si muovono hanno un effetto strano». Il sollevamento resta a ciò che si può APRIRE (la
   galleria, che porta il lightbox): lì il moto annuncia un'azione, qui annunciava niente.
   La risposta al passaggio non sparisce — la porta l'ombra, che non sposta nulla. */
.scheda:hover { box-shadow: 0 18px 40px -22px rgba(0,0,0,.7); }
.pilastro:hover { background: var(--surface); }

/* ⚠⚠ L'ENTRATA DA SINISTRA, e la trappola che le sta dentro.
   Owner: «al massimo puoi farle uscire dal lato sinistro dello schermo per creare dinamismo».
   La via ovvia — tenere la tessera a `translateX(-100vw)` e toglierlo a rivelazione — NON FUNZIONA e
   si blocca in silenzio: l'osservatore del runtime condiviso guarda la tessera STESSA, e calcola
   l'intersezione sul riquadro TRASFORMATO. Una tessera spinta fuori schermo non interseca mai la
   finestra, quindi non riceve mai `.is-visible` e resta fuori PER SEMPRE. Il difetto non dà errori:
   la fascia sembra semplicemente vuota.
   ⇒ A riposo la tessera sta al suo posto (l'osservatore la vede) e non si vede (`visibility`, che NON
   cambia la geometria e quindi non acceca l'osservatore). Il viaggio lo fa un'ANIMAZIONE, che parte
   quando la rivelazione è già scattata. `both` tiene la tessera fuori campo anche durante il ritardo
   della cascata, altrimenti la seconda e la terza lampeggerebbero in posizione prima di partire.
   ⚠ `-100vw` è la distanza MINIMA che garantisce il fuori-schermo per tutte e tre: il bordo destro di
   un elemento in pagina è ≤ 100vw, quindi traslando di -100vw finisce a ≤ 0. Un valore in pixel
   andrebbe bene per la prima tessera e lascerebbe le altre due a scorrere in mezzo alla pagina.
   ⚠ Le sezioni CLIPPANO sull'asse x, o le tessere fuori bordo allargano il documento e compare la
   barra orizzontale. `clip` e non `hidden`: `hidden` creerebbe un contenitore di scorrimento e
   ucciderebbe lo `position: sticky` della testata (trappola già pagata). */
.pilastri, .banda { overflow-x: clip; }
.js .pilastri__grid > .reveal,
.js .schede > .reveal { visibility: hidden; transform: none; transition: none; }
.js .pilastri__grid > .reveal.is-visible,
.js .schede > .reveal.is-visible {
  visibility: visible;
  animation: fp-entra-sinistra .8s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: calc(var(--reveal-i, 0) * 110ms);
}
@keyframes fp-entra-sinistra { from { transform: translateX(-100vw); } to { transform: none; } }
/* ⚠ Senza questa guardia il moto resterebbe anche a moto ridotto: le regole qui sopra hanno TRE
   livelli e batterebbero la neutralizzazione generica di base.css, che ne ha due. */
@media (prefers-reduced-motion: reduce) {
  .js .pilastri__grid > .reveal,
  .js .schede > .reveal,
  .js .pilastri__grid > .reveal.is-visible,
  .js .schede > .reveal.is-visible { visibility: visible; transform: none; animation: none; transition: none; }
}
.galleria figure { cursor: zoom-in; position: relative; }
.galleria figure::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 55%, rgba(13,31,31,.55));
  opacity: 0; transition: opacity .35s var(--ease);
}
.galleria figure:hover::after { opacity: 1; }
.galleria figure:hover { transform: translateY(-3px); box-shadow: 0 16px 34px -20px rgba(0,0,0,.55); }
/* Il filetto che cresce sotto la voce attiva del menu: piccolo, ma è ciò che distingue un sito curato. */
/* ⚠ Il rientro verticale non è estetica: senza, la voce è alta quanto la riga di testo (26px) e
   l’area di tocco resta sotto i 44px raccomandati. Il selettore è a (0,3,0) e sta SOTTO quello
   dell’overlay (0,4,0): il menu aperto conserva il suo rientro di riga. */
.site-header .site-nav .wp-block-navigation-item__content {
  position: relative; padding-block: .55rem; transition: color .2s var(--ease);
}
/* Il filetto si misura dal BORDO DEL TESTO, non dal riquadro: col rientro appena aggiunto un
   `bottom: -6px` finirebbe 15px sotto la parola, staccato da ciò che sottolinea. */
.site-header .site-nav .wp-block-navigation-item__content::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: .2rem; height: 2px;
  background: var(--accent-on-dark); transition: right .28s var(--ease);
}
.site-header .site-nav .wp-block-navigation-item__content:hover::after { right: 0; }
/* Le tessere del mosaico respirano all'ingresso: la scala parte appena sotto e si assesta. */
.js .mosaico .reveal { transform: translateY(18px) scale(.985); }
.js .mosaico .reveal.is-visible { transform: none; }
.mosaico img { transition: transform .6s var(--ease); }
.mosaico > div:hover img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .scheda, .servizio, .galleria figure, .pilastro, .mosaico img,
  .site-header, .site-header__row, .wordmark__mark { transition: none !important; }
  .scheda:hover, .galleria figure:hover, .mosaico > div:hover img { transform: none; }
}

/* ============================== il modulo di contatto ==============================
   ⚠ Il modulo sta SOTTO i recapiti, a tutta area: una colonna stretta accanto alla griglia dei dati
   avrebbe rimesso il telaio a due campate con la metà destra magra, ed è il difetto che l'owner
   segnala da tre giri. I campi si dispongono su DUE colonne sulla riga corta (nome + e-mail), una
   sola per messaggio e telefono, che vogliono respiro.
   ⚠⚠ Nessun `outline: none` sui campi: il focus visibile è la sola cosa che dice a chi naviga da
   tastiera dove si trova, e toglierlo è il difetto di accessibilità più comune dei moduli. */
.modulo { margin-top: var(--section-y); max-width: 56rem; }
.modulo__titolo { font-size: var(--t-xl); margin-bottom: var(--space-2); }
.modulo__nota { font-size: var(--t-xs); color: var(--ink-muted); letter-spacing: .02em; margin-bottom: var(--space-4); }
.modulo__riga { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--gap-griglia); }
.campo { display: flex; flex-direction: column; gap: .45rem; margin-bottom: var(--space-4); }
.campo label { font-size: var(--t-xs); font-weight: 600; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--ink-muted); }
.campo label span { color: var(--accent-ink); }
.campo input, .campo textarea {
  border: 1px solid var(--line); background: var(--paper); color: var(--ink);
  padding: .85rem 1rem; font-size: var(--t-base); border-radius: var(--radius);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.campo input:hover, .campo textarea:hover { border-color: var(--brand-mid); }
.campo input:focus-visible, .campo textarea:focus-visible {
  border-color: var(--brand-mid); box-shadow: 0 0 0 3px rgba(52,103,104,.18);
}
.campo textarea { resize: vertical; min-height: 8rem; }
/* ⚠ La riga di consenso è un `label` con dentro la casella: l'area cliccabile è tutta la frase, non
   il quadratino da 13px — che da solo è sotto la soglia di bersaglio di WCAG 2.2. */
.consenso { display: flex; gap: var(--space-2); align-items: flex-start; margin-bottom: var(--space-3);
  font-size: var(--t-sm); color: var(--ink-muted); cursor: pointer; }
.consenso input { flex: 0 0 auto; width: 18px; height: 18px; margin-top: .18rem; accent-color: var(--brand-mid); }
.consenso a { text-decoration: underline; text-underline-offset: .2em; }
.modulo__azioni { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-4); }
/* L'avviso di modulo non disponibile arriva dal progetto (`form-disabled.json`), non dal verticale:
   è markup, e porta `role="status"` perché chi non vede sappia perché il pulsante è spento. */
.form-avviso {
  margin-top: var(--space-3); padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--accent-ink); background: var(--paper);
  font-size: var(--t-sm); color: var(--ink); max-width: 46rem;
}
.form-avviso a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: .2em; }

/* ============================== lightbox ==============================
   ⚠⚠ IL RUNTIME CONDIVISO INIETTA `div.fp-lb` IN FONDO AL BODY appena trova un `a.zoom`, e il tema DEVE
   stilarlo. Senza queste regole il difetto è triplo e sembra tre difetti diversi:
     · il div resta nel FLUSSO in fondo alla pagina → la «×» compare in basso a sinistra e aggiunge
       una fascia vuota sotto il piè (l'owner l'ha fotografata);
     · al click `is-open` non dipinge niente → «la foto non si apre»;
     · ma il runtime scrive comunque `overflow: hidden` sull'<html> → «il sito si blocca, non scrolla più»,
       e non c'è modo di chiudere perché la × invisibile è altrove.
   Nessun gate lo vedeva: il markup è giusto, il JS è giusto, axe non guarda un overlay chiuso, e il crawl
   non clicca le foto. Il collaudo è CLICCARE. */
.fp-lb {
  display: none; position: fixed; inset: 0; z-index: 200;
  background: rgba(13, 31, 31, .95);
  align-items: center; justify-content: center; padding: var(--space-5);
  /* la sfumatura d'ingresso è dell'overlay, non dell'immagine: l'immagine non deve mai stare a
     un'opacità intermedia mentre la si guarda */
  animation: fp-lb-entra .22s var(--ease) both;
}
.fp-lb.is-open { display: flex; }
@keyframes fp-lb-entra { from { opacity: 0; } to { opacity: 1; } }
.fp-lb__img, .fp-lb img {
  max-width: 92vw; max-height: 86vh; object-fit: contain;
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .8);
  animation: fp-lb-foto .34s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes fp-lb-foto { from { transform: scale(.965); } to { transform: none; } }
.fp-lb__x, .fp-lb__nav {
  position: absolute; width: 52px; height: 52px; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .34); background: rgba(255, 255, 255, .06);
  color: var(--on-dark); display: grid; place-items: center;
  transition: background-color .2s var(--ease), border-color .2s var(--ease);
}
.fp-lb__x:hover, .fp-lb__nav:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.fp-lb__x { top: var(--space-5); right: var(--space-5); font-size: 0; }
/* ⚠ La × si disegna, non si scrive: il glifo «×» dei font cambia peso e centratura da famiglia a
   famiglia, e in un bottone da 52px si vede. */
.fp-lb__x::before, .fp-lb__x::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 22px; height: 2px; background: currentColor;
}
.fp-lb__x::before { transform: translate(-50%, -50%) rotate(45deg); }
.fp-lb__x::after { transform: translate(-50%, -50%) rotate(-45deg); }
.fp-lb__nav { top: 50%; transform: translateY(-50%); }
.fp-lb__nav svg { width: 24px; height: 24px; }
.fp-lb__prev { left: clamp(.6rem, 3vw, 2.4rem); }
.fp-lb__next { right: clamp(.6rem, 3vw, 2.4rem); }
/* Su uno schermo stretto le frecce ai lati coprirebbero la foto: scendono in fondo, dove il pollice è. */
@media (max-width: 620px) {
  .fp-lb__nav { top: auto; bottom: var(--space-5); transform: none; }
  .fp-lb__prev { left: 22%; } .fp-lb__next { right: 22%; }
  .fp-lb__x { top: var(--space-3); right: var(--space-3); }
}
@media (prefers-reduced-motion: reduce) {
  .fp-lb, .fp-lb__img, .fp-lb img { animation: none; }
}

/* ============================== barra CTA mobile ============================== */
.cta-bar { display: none; }
@media (max-width: 720px) {
  .cta-bar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    background: var(--brand-mid); color: var(--on-brand-mid);
  }
  /* Il landmark è l'unico figlio della barra: la disposizione passa a lui, o i due comandi
     smetterebbero di dividersi la riga a metà. */
  .cta-bar__nav { display: flex; flex: 1; }
  .cta-bar a {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    min-height: 56px; font-size: var(--t-sm); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  }
  .cta-bar a + a { border-left: 1px solid rgba(255,255,255,.24); }
  /* la pagina non deve finire sotto la barra */
  body { padding-bottom: 56px; }
}

/* ============================== 404 ============================== */
.errore { padding-block: var(--space-9); text-align: center; }
.errore h1 { font-size: var(--t-2xl); margin-bottom: var(--space-3); }
.errore p { color: var(--ink-muted); margin-bottom: var(--space-5); }

/* ============================== responsive ============================== */
/* ⚠⚠ La CTA della testata sparisce su mobile: accanto al wordmark e all'hamburger non ci sta, e
   sborda di 43px su un viewport da 390. La chiamata resta comunque a un pollice di distanza, nella
   barra fissa in fondo, che su mobile e' la vera CTA — quindi qui non si perde nulla, si toglie un
   doppione che rompeva la riga.
   ⚠ Il selettore ha DUE livelli (`.site-header .site-header__cta`, 0,2,0) e non uno: una media query
   NON aggiunge specificita', e `.btn { display: inline-flex }` (0,1,0) dichiarato piu' sopra batterebbe
   un `.site-header__cta { display: none }` di pari peso. E' il difetto che lascia il bottone visibile
   mentre il foglio «dice» di nasconderlo. */
@media (max-width: 720px) {
  .site-header .site-header__cta { display: none; }
}

/* ⚠⚠ IL MENU A RIGA NON ARRIVA FINO A 600px, dove WP passa all’hamburger. Misura del contenuto della
   testata: marchio 150 + gap 38 + voci 432 + gap 38 + bottone 128 = 786px di larghezza necessaria.
   A 860px di finestra il contenitore ne offre 764: le voci vanno a CAPO su due righe e la testata
   cresce da 84 a 114px (misurato a 820 e a 640). Una testata che si sfalda è esattamente il «menu che
   si vede male», solo un’ottava più in basso.
   ⇒ La soglia dell’overlay si alza a 1023px (la barra sta comoda fino a 1024). Si ricopia lo schema di
   selettore di WP con un livello in più (0,4,0 contro 0,3,0 e 0,2,0): il CSS dei blocchi è iniettato
   DOPO il tema, e a pari peso vincerebbe lui. */
@media (max-width: 1023px) {
  .site-header .site-nav .wp-block-navigation__responsive-container:not(.is-menu-open) { display: none; }
  .site-header .site-nav .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
}

@media (max-width: 980px) {
  .hero__grid { grid-template-columns: 1fr; padding-block: var(--space-6); }
  .hero__panel { padding-right: 0; }
  .metodo__grid { grid-template-columns: 1fr; }
  .mosaico { grid-auto-rows: clamp(4rem, 17vw, 6rem); }
}
