/* components.css — le bande del verticale heavy_vehicle_workshop.
   Registro BeMechanic5: testata fotografica scura a piena larghezza, titolo grande, e un colore saturo
   in CAMPI PIENI grandi (mai filetti). Il parco fotografico del mestiere è fatto di ritratti piccoli
   scattati col telefono: il carattere lo porta il colore, non la fotografia.

   ⚠⚠ Disciplina dell'ambra, valida in TUTTO il file: `--accent` è una SUPERFICIE. Sopra ci va
   `--ink` (11,37), mai il bianco (1,62). Come inchiostro l'ambra vale solo sulle bande scure (11,98);
   sui fondi chiari l'accento testuale è `--accent-ink` (6,92). */

/* ⚠⚠ SUPERFICI SCURE — la regola che chiude un'intera classe di difetti.
   Inseguire ogni componente con un override `.banda-scura .x { color: … }` non funziona: le superfici
   scure sono CINQUE (bande, ferro, testata, piè, testata fotografica) e ogni regola scritta per una
   sola lascia le altre nere su nero — è successo tre volte di fila (menu, <strong>, recapiti del piè).
   Qui si rimappano i TOKEN dentro il sottoalbero: chi consuma `--ink`, `--ink-muted` o `--accent-ink`
   si adatta da solo, oggi e per ogni componente che verrà. */
:is(.banda-scura, .banda-ferro, .site-header, .site-footer, .hero) {
  --ink: var(--on-dark);
  --ink-muted: var(--on-dark-muted);
  /* ⚠ L'accento TESTUALE dentro una banda scura. Non può essere `--accent` grezzo: vale finché
     l'accento del verticale è chiaro (l'ambra fa 11,98 sul piè), ma un accento di marca più scuro —
     un rosso #e40613 fa 3,29 — qui sarebbe sotto AA su ogni occhiello di ogni banda scura, e nessun
     gate di rendering lo vede. Passa da `--accent-on-dark`, che per default È `--accent`: il sito del
     primo cliente rende esattamente come prima. */
  --accent-ink: var(--accent-on-dark);
  --line: rgba(255, 193, 60, .22);
  --surface: var(--brand-mid);
  --paper: var(--brand);
}

/* Altezza della testata fissa: serve alle ancore, che senza finirebbero SOTTO di essa. Un valore
   solo, consumato da entrambe: due numeri scollegati divergono al primo ritocco dell'header. */
:root { --header-h: 96px; }
@media (max-width: 720px) { :root { --header-h: 84px; } }
[id="officina"], [id="chi-siamo"], [id="servizi"], [id="gallery"], [id="contatti"], #main {
  scroll-margin-top: var(--header-h);
}

/* ============================== testata ============================== */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--brand);
  border-bottom: 3px solid var(--accent);
  /* ⚠ Senza questo, TUTTO nella testata eredita `--ink` dal body: le voci del menu e l'hamburger
     escono neri su fondo nero (1,0 di contrasto). Il difetto non si vede nel sorgente — gli elementi
     ci sono, sono in posizione e hanno la loro larghezza — solo nel colore CALCOLATO. */
  color: var(--on-dark);
}
/* ⚠ WordPress avvolge ogni parte di template in un <div>, che diventerebbe il contenitore dello
   sticky e lo renderebbe inerte: dichiarato ≠ applicato. */
.wp-block-template-part { display: contents; }

/* Barra dei recapiti: la nota del cliente chiede telefono, email e Facebook IN EVIDENZA. */
.recapiti-bar { background: var(--brand-dark); font-size: var(--t-xs); }
.recapiti-bar__row {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4);
  align-items: center; justify-content: flex-end; padding-block: .45rem;
}
.recapiti-bar a { color: var(--on-dark-muted); display: inline-flex; align-items: center; gap: .4rem; }
.recapiti-bar a:hover { color: var(--accent-on-dark); }

.site-header__row {
  display: flex; align-items: center; gap: var(--space-4);
  /* ⚠ Il marchio e' cresciuto da 34 a 48px e la riga si stringe di altrettanto: l'altezza della
     testata non deve cambiare, perche' e' quella che l'ancora deve scavalcare (--header-h). */
  padding-block: var(--space-2);
  transition: padding-block .35s var(--ease);
}
/* La testata si CONTRAE scorrendo: la barra dei recapiti si ritira, il marchio rimpicciolisce e la
   riga si stringe. Guadagna due cose insieme — l'ancora non deve più scavalcare 211px di intestazione,
   e la pagina smette di sembrare ferma. La classe `is-scrolled` la mette reveal.js (opt-in, zero JS nuovo). */
.site-header.is-scrolled .recapiti-bar { max-height: 0; overflow: hidden; padding-block: 0; }
.site-header .recapiti-bar { max-height: 4rem; transition: max-height .35s var(--ease); }
.site-header.is-scrolled .site-header__row { padding-block: var(--space-2); }
.site-header.is-scrolled .wordmark--logo img { height: 38px; }
.site-header .wordmark--logo img { transition: height .35s var(--ease); }
.site-header.is-scrolled { box-shadow: 0 10px 30px rgba(0, 0, 0, .45); }
.site-header__row > * { align-self: center; margin-block: 0; }

.wordmark { display: inline-flex; align-items: center; gap: .65rem; }
.wordmark__mark { width: 40px; height: 40px; flex: 0 0 auto; }
/* Sui siti reali il marchio È il wordmark del cliente (immagine): il testo del demo sparisce con lui.
   ⚠ Il simbolo che accompagna il wordmark sulla sorgente è 21×23 px e illeggibile: resta fuori finché
   il cliente non dice cosa raffigura — ricostruirlo a occhio sarebbe inventarlo. */
/* ⚠⚠ IL MARCHIO NON SI RESTRINGE E NON SI DEFORMA. La riga della testata e' un flex e il marchio ne e'
   un figlio: con un menu lungo (otto voci) la navigazione si prende quasi tutta la riga e l'unico figlio
   che puo' cedere e' il marchio. Misurato a 1440 su otto voci: reso 34x48 invece di 48x48 — un tondo
   diventato ovale, cioe' esattamente cio' che la regola di gusto `logo.min_size` vieta («il logo non si
   deforma: si cambia la taglia del contenitore, non le proporzioni»). Con il menu corto del primo
   cliente il marchio non cedeva, quindi il difetto e' rimasto invisibile fino a un menu piu' lungo.
   `object-fit: contain` e' la seconda difesa: se un giorno un contenitore lo stringesse comunque, il
   marchio si rimpicciolisce ma resta in proporzione invece di schiacciarsi. */
.site-header__row .wordmark { flex: 0 0 auto; }
.wordmark--logo img { height: 48px; width: auto; flex: 0 0 auto; object-fit: contain; }
.wordmark__txt {
  font-family: var(--font-display); font-weight: 700; font-size: 1.5rem;
  letter-spacing: .02em; text-transform: uppercase; color: var(--on-dark); line-height: 1;
}
.wordmark__txt em { font-style: normal; color: var(--accent-on-dark); }

.site-nav { margin-left: auto; }
.site-nav ul { display: flex; gap: var(--space-4); align-items: center; }
/* ⚠ A parità di specificità vince WordPress: il CSS dei blocchi è iniettato DOPO il tema. Per le voci
   del menu serve un livello in più della sua regola — si ricopia il suo schema di selettore invece di
   inseguirlo con `!important`. */
.site-header .site-nav a,
.site-header .site-nav .wp-block-navigation-item__content {
  font-family: var(--font-display); font-weight: 600; font-size: 1.0625rem;
  text-transform: uppercase; letter-spacing: .06em; color: var(--on-dark);
  padding-block: .3rem; border-bottom: 2px solid transparent;
}
.site-header .site-nav a:hover,
.site-header .site-nav .wp-block-navigation-item__content:hover { color: var(--accent-on-dark); border-bottom-color: var(--accent); }
/* L'hamburger è un SVG inline: prende `currentColor`, che sulla testata scura dev'essere chiaro. */
.site-header .wp-block-navigation__responsive-container-open,
.site-header .wp-block-navigation__responsive-container-close { color: var(--on-dark); }

/* Il telefono in testata è il punto d'azione del mestiere: campo ambra pieno, testo inchiostro. */
.header-cta {
  display: inline-flex; align-items: center; gap: .5rem;
  background: var(--accent); color: var(--on-accent);
  font-family: var(--font-display); font-weight: 700; font-size: 1.1rem;
  text-transform: uppercase; letter-spacing: .04em;
  padding: .6rem 1.1rem;
}
.header-cta:hover { background: var(--accent-dark); }

/* --- mobile: la testata porta SOLO marchio e hamburger, spinto a destra --- */
@media (max-width: 860px) {
  .site-header .header-cta { display: none; }
  .recapiti-bar__row { justify-content: center; gap: var(--space-3); }
  .site-header__row { gap: var(--space-2); }
  .site-nav { margin-left: auto; }
  .wordmark--logo img { height: 34px; }
}

/* --- il pannello del menu mobile: WP lo lascia nudo, e nudo sembra rotto --- */
.site-header .wp-block-navigation__responsive-container.is-menu-open {
  background: var(--brand-dark);
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
  /* ⚠ Il padding superiore deve superare l'ALTEZZA DELLA X più il suo margine, sennò il riquadro di
     chiusura si posa sopra la prima voce (misurato: X a 56px + 2×space-3 => 100px). */
  padding: calc(56px + var(--space-6)) var(--gutter) var(--space-8);
  align-items: stretch;
  width: 100%;
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
  gap: 0; width: 100%;
  /* ⚠⚠ L'ALLINEAMENTO A DESTRA del pannello nasce QUI, non sull'<a>. Il blocco navigazione dichiara
     `justifyContent:right`, che WP rende con la classe `items-justified-right`; nel pannello mobile il
     contenitore diventa una colonna, e in una colonna quella classe si traduce in `align-items:flex-end`.
     Ogni <li> si stringe allora sul proprio testo e si incolla a destra: il menu esce a bandiera, con il
     bordo sinistro frastagliato. La regola che c'era — `width:100%` sull'<a> — agiva un livello troppo
     in basso: l'<a> era gia' largo quanto il suo <li>, ed e' il <li> a essere corto.
     ⚠ Misurato a 390px prima della correzione: «Contatti» largo 98px a x=272, «Ricambi in vendita»
     205px a x=165, mentre la banda utile e' 350px. */
  align-items: stretch;
}
/* ⚠ L'<a> del blocco è `display:block` e in una colonna flex si stringe sul testo, finendo allineato
   a destra: con width 100% torna a sinistra e la riga intera diventa bersaglio. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  display: block; width: 100%;
  padding: var(--space-3) 0;
  font-size: 1.6rem; letter-spacing: .06em;
  border-bottom: 1px solid rgba(255, 193, 60, .22);
  border-top: 0;
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:first-child .wp-block-navigation-item__content { border-top: 1px solid rgba(255, 193, 60, .22); }
/* La X: bersaglio pieno e tratto spesso. Un glifo sottile su un pannello nero non si trova. */
.site-header .wp-block-navigation__responsive-container-close {
  width: 56px; height: 56px; inset-block-start: var(--space-3); inset-inline-end: var(--gutter);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--accent); color: var(--accent-on-dark);
}
.site-header .wp-block-navigation__responsive-container-close svg { width: 32px; height: 32px; }
.site-header .wp-block-navigation__responsive-container-close svg path { stroke: currentColor; stroke-width: 1.4; }
.site-header .wp-block-navigation__responsive-container-open { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; }
.site-header .wp-block-navigation__responsive-container-open svg { width: 30px; height: 30px; }
/* ⚠⚠ Le due superfici FISSE devono sparire quando il pannello e' aperto. La barra CTA sta a z-index 60
   e il tasto WhatsApp a 55: entrambe restano SOPRA il menu e ne coprono le ultime voci — misurato a
   390x667, «Noleggio macchine operatrici» era tagliato a meta' dalla barra. WordPress marca
   <html class="has-modal-open"> per tutta la durata dell'apertura: e' quello lo stato da guardare,
   non una classe nostra che qualcuno dovrebbe ricordarsi di aggiungere. */
html.has-modal-open .cta-bar,
html.has-modal-open .wa-flot { display: none !important; }

/* ⚠⚠ Da SETTE voci in su il pannello non ci sta in uno schermo da 667px: due voci lunghe vanno a capo e
   il contenuto arriva a 877px, cioe' le ultime due voci finiscono sotto la piega. Si compatta — e SOLO
   allora. La regola si autogatta sul numero di voci (`:has(:nth-child(7))`), quindi un sito con un menu
   corto non cambia di un pixel: e' la stessa disciplina delle bandiere di progetto, ma senza dover
   dichiarare niente. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container:has(> .wp-block-navigation-item:nth-child(7)) .wp-block-navigation-item__content {
  font-size: 1.3rem; padding: var(--space-2) 0; letter-spacing: .04em;
}

/* ============================== testata fotografica ============================== */
.hero { position: relative; isolation: isolate; background: var(--brand); overflow: hidden; }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
/* Il velo: il titolo bianco deve reggere sopra una fotografia d'officina, che è chiara a chiazze.
   ⚠ Il limite lo danno i pixel CHIARI dietro il testo, non la media dell'immagine. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(14,13,10,.62) 0%, rgba(14,13,10,.74) 55%, rgba(14,13,10,.9) 100%);
}
.hero__inner { padding-block: clamp(4.5rem, 12vw, 9rem); }
.hero__eyebrow {
  font-family: var(--font-display); font-weight: 600; font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent-on-dark);
  display: inline-flex; align-items: center; gap: .7rem;
}
.hero__eyebrow::before { content: ""; width: 42px; height: 3px; background: var(--accent); }
.hero__title {
  font-size: var(--t-3xl); color: var(--on-dark); margin-top: var(--space-3);
  max-width: var(--misura-titolo);
}
.hero__title em { font-style: normal; color: var(--accent-on-dark); }
.hero__lead {
  color: var(--on-dark-muted); margin-top: var(--space-4); max-width: var(--misura-hero-lead); font-size: var(--t-lg);
}
.hero__azioni { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-5); }

/* Variante senza fotografia hero-grade: campo ambra pieno, MAI una foto finta. */
.hero--design { background: var(--brand); }
.hero--design::after { background: none; }
.hero--design .hero__inner { position: relative; }
.hero--design .hero__inner::before {
  content: ""; position: absolute; right: 0; top: 0; bottom: 0; width: 38%;
  background: var(--accent); z-index: -1;
}
@media (max-width: 860px) { .hero--design .hero__inner::before { display: none; } }

/* ============================== bottoni ============================== */
.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  text-transform: uppercase; letter-spacing: .05em;
  padding: .8rem 1.5rem; border: 2px solid transparent;
}
.btn--primario { background: var(--accent); color: var(--on-accent); }
.btn--primario:hover { background: var(--accent-dark); }
/* ⚠⚠ Il fantasma esiste in DUE forme perché l'ambra come TESTO vale solo su scuro (11,98) e su
   chiaro fa 1,54. Il default è quello per fondo CHIARO — l'errore, se si sbaglia contesto, cade dalla
   parte sicura; la forma ambra si accende solo DENTRO una banda scura. */
.btn--fantasma { border-color: var(--accent-ink); color: var(--accent-ink); }
.btn--fantasma:hover { background: var(--accent-ink); color: var(--paper); }
.banda-scura .btn--fantasma, .banda-ferro .btn--fantasma, .hero .btn--fantasma { border-color: var(--accent); color: var(--accent-on-dark); }
.banda-scura .btn--fantasma:hover, .banda-ferro .btn--fantasma:hover, .hero .btn--fantasma:hover { background: var(--accent); color: var(--on-accent); }

/* ============================== bande e testate di sezione ============================== */
.banda-scura { background: var(--brand); color: var(--on-dark); }
.banda-scura h2, .banda-scura h3 { color: var(--on-dark); }
.banda-ferro { background: var(--brand-mid); color: var(--on-dark); }
.banda-ferro h2, .banda-ferro h3 { color: var(--on-dark); }

.testa { max-width: var(--misura-testa); }
.testa__eyebrow {
  font-family: var(--font-display); font-weight: 600; font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent-ink);
  display: inline-flex; align-items: center; gap: .7rem;
}
.testa__eyebrow::before { content: ""; width: 42px; height: 3px; background: var(--accent); }
.banda-scura .testa__eyebrow, .banda-ferro .testa__eyebrow { color: var(--accent-on-dark); }
.testa h2 { font-size: var(--t-2xl); margin-top: var(--space-3); }
/* Il titolo di una pagina di progetto: token col default uguale al comportamento storico (v. tokens.css). */
.testa h1 { font-size: var(--t-testa-h1); margin-top: var(--space-3); }
.pagina-testata.section--tight { padding-block: var(--testata-y); }
.testa__lead { margin-top: var(--space-3); color: var(--ink-muted); font-size: var(--t-lead); max-width: var(--misura-lead); }
.banda-scura .testa__lead, .banda-ferro .testa__lead { color: var(--on-dark-muted); }

/* ⚠ La misura di lettura sta sul PARAGRAFO, non sul contenitore: un `ch` su un display da 40px non
   è lo stesso `ch` del corpo da 17. */
.prosa { max-width: none; }
.prosa p { max-width: var(--misura-prosa); }
.testa__lead { max-width: var(--misura-lead); }
.tessere__cella p, .servizio p, .chisiamo__blocco p { max-width: var(--misura-tessera); }
.prosa p { color: var(--ink-muted); }
.banda-scura .prosa p, .banda-ferro .prosa p { color: var(--on-dark-muted); }

/* ============================== tessere della testata (le tre schede) ============================== */
.tessere { display: grid; gap: 3px; grid-template-columns: repeat(3, 1fr); background: var(--line); }
.tessere__cella { background: var(--paper); padding: var(--space-5) var(--space-4); }
.tessere__cella h3 {
  font-size: var(--t-lg); display: inline-flex; align-items: center; gap: .6rem;
}
.tessere__cella h3::before { content: ""; width: 10px; height: 22px; background: var(--accent); flex: 0 0 auto; }
.tessere__cella p { margin-top: var(--space-2); color: var(--ink-muted); font-size: var(--t-sm); }
@media (max-width: 860px) { .tessere { grid-template-columns: 1fr; } }

/* ============================== officina (featured) ============================== */
.officina { display: grid; grid-template-columns: 1.05fr .95fr; gap: var(--space-7); align-items: start; }
.officina__quesiti { margin-top: var(--space-5); display: grid; gap: var(--space-3); }
.officina__quesito {
  display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); align-items: start;
  border-left: 4px solid var(--accent); padding-left: var(--space-3);
}
.officina__quesito span { color: var(--ink); }
.officina__media { position: relative; align-self: stretch; }
.officina__media img { width: 100%; height: 100%; min-height: 0; object-fit: cover; }
/* Il dato numerico: campo ambra pieno che INVADE la fotografia, come chiede il linguaggio della
   categoria. Il numero è inchiostro sull'ambra (11,37). */
.dato {
  position: absolute; left: 0; bottom: 0; background: var(--accent); color: var(--on-accent);
  padding: var(--space-3) var(--space-4); max-width: 62%;
}
.dato__n { font-family: var(--font-display); font-weight: 700; font-size: clamp(2.2rem, 5vw, 3.2rem); line-height: 1; }
.dato__t { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--tracking-label); }
@media (max-width: 900px) { .officina { grid-template-columns: 1fr; } .officina__media img { height: auto; } }

/* ============================== chi siamo (trust) ============================== */
/* ⚠⚠ Le due colonne devono FINIRE INSIEME. Con testo a sinistra e fotografia+schede a destra la
   destra misurava 780px contro 225: 555px di vuoto sotto il testo, il buco più vistoso del sito.
   Le schede scendono nella colonna SINISTRA sotto il testo e la fotografia prende tutta l'altezza
   della colonna destra: stessa materia, stessa griglia, nessun elemento sfalsato. */
.chisiamo { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-7); align-items: start; }
.chisiamo__testo { grid-column: 1; grid-row: 1; }
.chisiamo__media { grid-column: 2; grid-row: 1 / span 2; align-self: stretch; }
.chisiamo__blocchi { grid-column: 1; grid-row: 2; display: grid; gap: var(--space-5); margin-top: var(--space-6); align-content: start; }
.chisiamo__blocco { border-top: 3px solid var(--accent); padding-top: var(--space-3); }
.chisiamo__blocco h3 { font-size: var(--t-lg); }
.chisiamo__blocco p { margin-top: var(--space-2); color: var(--on-dark-muted); font-size: var(--t-scheda-chisiamo); }
.chisiamo__media img { width: 100%; height: 100%; min-height: 22rem; aspect-ratio: auto; object-fit: cover; }

/* Le due schede AFFIANCATE invece che impilate. Prendono l'intera larghezza della banda, una per
   colonna, quindi ognuna resta larga quanto era da sola e la misura di lettura non si stringe. La
   fotografia smette di scavalcare la seconda riga e torna alta quanto il testo che le sta a fianco:
   su uno scatto orizzontale è un taglio più vicino all'originale di quello in colonna. */
.chisiamo--affiancate .chisiamo__media { grid-row: 1; }
.chisiamo--affiancate .chisiamo__blocchi { grid-column: 1 / -1; grid-template-columns: 1fr 1fr; gap: var(--space-5) var(--space-7); }
@media (max-width: 900px) {
  /* In colonna sola l'ordine torna quello della lettura: testo, fotografia, schede. */
  .chisiamo { grid-template-columns: 1fr; gap: var(--space-5); }
  .chisiamo__testo, .chisiamo__media, .chisiamo__blocchi { grid-column: 1; grid-row: auto; }
  /* ⚠ Le regole del modificatore hanno una classe in più e batterebbero queste: qui si annullano a
     mano, sennò la fotografia resterebbe inchiodata alla prima riga e le schede si ridurrebbero a due
     strisce da 165px, dove nessun paragrafo si legge. */
  .chisiamo--affiancate .chisiamo__media { grid-row: auto; }
  .chisiamo--affiancate .chisiamo__blocchi { grid-template-columns: 1fr; }
  .chisiamo__media img { min-height: 0; aspect-ratio: 4 / 3; }
}

/* ============================== cosa facciamo (method) ============================== */
.metodo { display: grid; grid-template-columns: .95fr 1.05fr; gap: var(--space-7); align-items: center; }
.metodo__media img { width: 100%; aspect-ratio: 16 / 11; object-fit: cover; }
.metodo__nota {
  margin-top: var(--space-4); background: var(--accent); color: var(--on-accent);
  padding: var(--space-4); font-weight: 500;
}
@media (max-width: 900px) { .metodo { grid-template-columns: 1fr; } }

/* ============================== i sei servizi (NON cliccabili) ============================== */
/* ⚠ Il cliente ha chiesto ESPRESSAMENTE tessere non cliccabili: qui non esiste nessun <a>, e non
   deve comparirne uno in futuro «per comodità». */
.servizi__griglia {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5);
}
.servizio__media { position: relative; background: var(--brand-mid); overflow: hidden; }
.servizio__media img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  transition: transform .6s var(--ease), filter .6s var(--ease);
}
/* La tessera reagisce al puntatore: la fotografia avanza e schiarisce, e una lama d'ambra sale dal
   basso. Senza, la griglia è un tabellone e non un oggetto. */
.servizio:hover .servizio__media img { transform: scale(1.06); filter: saturate(1.12) contrast(1.04); }
.servizio__media::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 5px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .45s var(--ease);
}
.servizio:hover .servizio__media::after { transform: scaleX(1); }
.servizio h3 { transition: color .3s var(--ease); }
.servizio:hover h3 { color: var(--accent-ink); }
.servizio__n {
  position: absolute; left: 0; top: 0; background: var(--accent); color: var(--on-accent);
  font-family: var(--font-display); font-weight: 700; font-size: 1.25rem;
  padding: .3rem .75rem; line-height: 1.2;
}
.servizio h3 { font-size: var(--t-lg); margin-top: var(--space-3); }
.servizio p { margin-top: var(--space-2); color: var(--ink-muted); font-size: var(--t-sm); }
@media (max-width: 980px) { .servizi__griglia { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .servizi__griglia { grid-template-columns: 1fr; } }

/* ============================== mosaico dei lavori (gallery) ============================== */
/* Il parco è fatto di ritratti piccoli: il mosaico li mette in colonna 3:4 e non chiede a nessuno di
   reggere una banda a piena larghezza. */
.mosaico__griglia {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3);
}
.mosaico figure { margin: 0; background: var(--brand-mid); overflow: hidden; position: relative; }
.mosaico img {
  width: 100%; aspect-ratio: 3 / 4; object-fit: cover;
  transition: transform .7s var(--ease), filter .5s var(--ease);
  filter: saturate(.86) contrast(1.02);
}
.mosaico a.zoom:hover img, .mosaico a.zoom:focus-visible img { transform: scale(1.08); filter: saturate(1.1) contrast(1.05); }
/* Il segno «apri»: compare solo al puntatore, non ruba spazio a riposo. */
.mosaico a.zoom::after {
  content: ""; position: absolute; inset: 0; background: rgba(14, 13, 10, 0);
  transition: background .4s var(--ease);
}
.mosaico a.zoom:hover::after, .mosaico a.zoom:focus-visible::after { background: rgba(14, 13, 10, .28); }
/* Due tessere prendono doppia altezza: il mosaico non è una griglia regolare. */
/* ⚠ Le tessere a doppia altezza lasciavano buchi: con `grid-row: span 2` le righe non si richiudono e
   il mosaico diventa una scacchiera bucata. Griglia REGOLARE, righe piene, un solo rapporto. */
.mosaico figure { grid-row: auto; }
@media (max-width: 980px) { .mosaico__griglia { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .mosaico__griglia { grid-template-columns: repeat(2, 1fr); } }

/* ============================== sede e orari (contact_details) ============================== */
.sede { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-7); align-items: center; }
.sede__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.sede__dati { display: grid; gap: var(--space-4); margin-top: var(--space-5); }
.sede__dl dt {
  font-family: var(--font-display); font-weight: 600; font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent-ink);
}
.sede__dl dd { margin: .2rem 0 0; color: var(--ink); }
.banda-scura .sede__dl dt { color: var(--accent-on-dark); }
.banda-scura .sede__dl dd { color: var(--on-dark); }
.orari { display: grid; gap: .3rem; }
.orari__riga { display: flex; justify-content: space-between; gap: var(--space-3); border-bottom: 1px solid var(--line); padding-block: .35rem; }
.banda-scura .orari__riga { border-bottom-color: rgba(255, 193, 60, .28); }
@media (max-width: 900px) { .sede { grid-template-columns: 1fr; } }

/* ============================== contatti e modulo ============================== */
.contatti { display: grid; grid-template-columns: 1.05fr .95fr; gap: var(--space-7); align-items: start; }
.contact-form { display: grid; gap: var(--space-3); margin-top: var(--space-4); }
.contact-form .row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.field { display: grid; gap: .35rem; }
.field label {
  font-family: var(--font-display); font-weight: 600; font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--ink-muted);
}
/* ⚠ Il modulo vive nella banda scura: l'inchiostro tenue lì misura 2,58. */
.banda-scura .field label { color: var(--on-dark-muted); }
.banda-scura .consent { color: var(--on-dark-muted); }
.banda-scura .consent a { color: var(--accent-on-dark); }
.field input, .field textarea {
  border: 1px solid var(--line); background: var(--paper); padding: .7rem .8rem; width: 100%;
}
.field textarea { min-height: 8rem; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible { border-color: var(--accent-ink); }
/* ⚠ `.consent` è un flex: se il testo contiene un <a> si spezzerebbe in più flex-item, quindi TUTTO
   il testo (link incluso) sta dentro un solo <span>. */
.consent { display: flex; align-items: flex-start; gap: .6rem; font-size: var(--t-sm); color: var(--ink-muted); }
.consent a { color: var(--accent-ink); text-decoration: underline; }
@media (max-width: 900px) {
  .contatti { grid-template-columns: 1fr; }
  .contact-form .row { grid-template-columns: 1fr; }
}

/* ============================== piè ============================== */
.site-footer { background: var(--brand-dark); color: var(--on-dark-muted); }
/* ⚠ Tre colonne di larghezza diversa NON danno una colonna centrale centrata: il centro della
   seconda cade dove finisce la prima. Con tre frazioni UGUALI il centro della seconda coincide col
   centro della riga, e i contatti si allineano a destra dentro la propria. */
.site-footer__row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6);
  padding-block: var(--space-7);
}
.site-footer__row > :nth-child(2) { justify-self: center; text-align: center; }
.site-footer__row > :nth-child(3) { justify-self: end; text-align: right; }
.site-footer__row > :nth-child(3) .sede__dl dd { text-align: right; }
.site-footer h3 {
  color: var(--accent-on-dark); font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: var(--tracking-label);
}
.site-footer ul { margin-top: var(--space-3); display: grid; gap: .5rem; }
.site-footer a:hover { color: var(--accent-on-dark); }
.site-footer__coda {
  border-top: 1px solid rgba(255, 193, 60, .22);
  padding-block: var(--space-3);
  display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: space-between;
  font-size: var(--t-xs);
}
.dgitaly { display: inline-flex; align-items: center; gap: .45rem; }
.dgitaly img { width: 20px; height: 20px; }
@media (max-width: 860px) { .site-footer__row { grid-template-columns: 1fr; } }

/* Prima colonna del piè quando il progetto ci porta orari e social: l'etichetta riusa l'idioma della
   scheda sede, e il filetto delle righe si schiarisce perché `--line` è pensato per il fondo chiaro. */
.site-footer .sede__etichetta { color: var(--accent-on-dark); margin-top: var(--space-4); }
.site-footer .orari__riga { border-bottom-color: rgba(255, 255, 255, .14); }
.site-footer .orari { max-width: 22rem; }
/* Lo stacco serve al blocco che nella prima colonna segue gli orari, non a una voce di elenco: dentro
   un <dd> gli stemmi tengono il ritmo del proprio <dl>, come telefono, email e indirizzo. */
.site-footer div.social { margin-top: var(--space-4); }

/* ============================== stemmi social ==============================
   Il canale si dice con lo STEMMA, non con la parola: due canali scritti per esteso sono due righe di
   testo che competono coi recapiti, e il secondo non ha dove stare. Vivono solo su fondo scuro (piè e
   banda dei contatti), quindi l'inchiostro è il bianco e l'accento resta per il passaggio del mouse.
   ⚠ La maschera si risolve rispetto al FOGLIO, non al documento: questa regola deve stare nel CSS del
   verticale e non in uno style inline, dove `../assets/` non verrebbe riscritto. */
.social { display: inline-flex; align-items: center; gap: var(--space-2); }
.social__link {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%; color: var(--on-dark);
  border: 1px solid rgba(255, 255, 255, .26);
  transition: color .3s var(--ease), background-color .3s var(--ease), border-color .3s var(--ease);
}
.social__ico { width: 18px; height: 18px; background: currentColor; }
.social__ico[data-social="facebook"] {
  -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;
}
.social__ico[data-social="instagram"] {
  -webkit-mask: url("../assets/img/icons/social-instagram.svg") no-repeat center / contain;
          mask: url("../assets/img/icons/social-instagram.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:nth-of-type(2)::after { animation-delay: 1.4s; }
.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; } }

/* ============================== 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(--accent); color: var(--on-accent);
  }
  .cta-bar a {
    flex: 1; text-align: center; padding: .85rem .5rem;
    font-family: var(--font-display); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  }
  .cta-bar a + a { border-left: 2px solid rgba(21, 20, 15, .28); }
  body { padding-bottom: 3.6rem; }
}

/* Etichetta autonoma: un <dt> senza <dd> non è una lista di definizioni (axe: definition-list). */
.sede__etichetta {
  font-family: var(--font-display); font-weight: 600; font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent-ink);
  margin-bottom: var(--space-2);
}
.banda-scura .sede__etichetta { color: var(--accent-on-dark); }

/* ⚠ Il contenitore responsive del blocco nav porta un proprio box che gonfia la riga della testata:
   con logo 26px e CTA 49px la riga misurava 134. A riposo (menu chiuso) non deve occupare nulla oltre
   alle voci. Misurato: 134 -> 72px, e l'ancora scende di pari passo. */
.site-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
  padding: 0; margin: 0; gap: 0;
}
.site-header .wp-block-navigation,
.site-header .wp-block-navigation__container { margin-block: 0; }
.site-header__row { align-items: center; }
.site-header__row > * { margin-block: 0; }

/* ⚠ Il blocco nav di WordPress porta un box proprio (112px) che nessun figlio giustifica: invece di
   inseguirlo, la riga della testata dichiara la PROPRIA altezza e ci centra dentro tutto. Un'altezza
   dichiarata è anche l'unica che l'ancora può conoscere in anticipo. */
/* ⚠ Un'ALTEZZA fissa sulla riga non basta: la nav resta un flex-item che va a capo, e l'hamburger del
   blocco resta visibile perché la sua soglia è il breakpoint di WP, non la nostra. La riga deve essere
   `nowrap` e l'hamburger va spento esplicitamente sopra il nostro breakpoint. */
.site-header__row { height: 86px; padding-block: 0; flex-wrap: nowrap; }
.site-header.is-scrolled .site-header__row { height: 64px; }
.site-header .site-nav { flex-wrap: nowrap; }
.site-header .site-nav ul { flex-wrap: nowrap; }
@media (min-width: 861px) {
  .site-header .wp-block-navigation__responsive-container-open { display: none !important; }
  .site-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
    display: flex !important; position: static; width: auto; background: none;
  }
}
.site-header .site-nav,
.site-header .wp-block-navigation__responsive-container:not(.is-menu-open),
.site-header .wp-block-navigation__responsive-container-content { min-height: 0; }
.site-header .site-nav { align-items: center; display: flex; }
@media (max-width: 860px) {
  .site-header__row { height: 68px; }
  .site-header.is-scrolled .site-header__row { height: 60px; }
}

/* ============================== testata con un menu LUNGO ==============================
   ⚠⚠ Otto voci non ci stanno in un contenitore da 1200px: ogni voce va a capo dentro se stessa e la
   testata diventa tre righe di testo spezzato («MACCHINE / MOVIMENTO / TERRA»). Misurato a 1440 col
   foglio di serie: la voce piu' lunga occupava TRE righe e la CTA del telefono altre tre.
   Tutte le regole qui sotto si AUTOGATTANO sul numero di voci (`:has(:nth-child(7))`): un sito con un
   menu corto non cambia di un pixel, e non deve dichiarare niente per restare com'era.
   Misura scelta: con voci a 0,92rem, spaziatura .015em e passo `--space-2` la navigazione occupa
   1027px e la riga sta su UNA riga da 1366px in su, con 41px di margine. Sotto quella soglia il menu
   orizzontale NON si stringe ancora: passa il testimone al pannello, che le otto voci le tiene tutte. */
.site-header__row:has(.wp-block-navigation-item:nth-child(7)) {
  /* La riga della testata esce dal contenitore e prende la finestra: e' l'unico modo di dare
     alla navigazione lo spazio che le serve senza rimpicciolire il testo fino a non leggerlo. */
  max-width: none; width: 100%; padding-inline: var(--gutter);
}
.site-header__row:has(.wp-block-navigation-item:nth-child(7)) .wp-block-navigation-item__content {
  /* ⚠ Il difetto e' che le voci vanno a capo DENTRO SE STESSE, non che la riga vada a capo: la riga
     era gia' `nowrap`. Il divieto va messo sulla voce. */
  white-space: nowrap; letter-spacing: .015em; font-size: .92rem;
}
.site-header__row:has(.wp-block-navigation-item:nth-child(7)) .site-nav ul { gap: var(--space-2); }
/* Anche la CTA del telefono andava a capo su tre righe: un recapito spezzato non e' un recapito. */
.site-header__row:has(.wp-block-navigation-item:nth-child(7)) .header-cta { white-space: nowrap; flex: 0 0 auto; }

/* ⚠⚠ Sotto la soglia in cui le otto voci stanno su una riga, il menu orizzontale non va COMPRESSO
   ancora: va sostituito dal pannello, che le tiene tutte e le ha gia' verificate. La soglia di WP e'
   861px e qui non basta — fra 861 e 1365 la testata resterebbe stipata. Si alza SOLO per i menu
   lunghi, e con la stessa `!important` con cui il blocco `min-width: 861px` la impone. */
@media (max-width: 1365px) {
  .site-header__row:has(.wp-block-navigation-item:nth-child(7)) .wp-block-navigation__responsive-container-open {
    display: flex !important;
  }
  .site-header__row:has(.wp-block-navigation-item:nth-child(7)) .wp-block-navigation__responsive-container:not(.is-menu-open) {
    display: none !important;
  }
}

/* La misura di lettura si dichiara sul PARAGRAFO ovunque, non solo dove ci si è ricordati. */
.officina p, .chisiamo p, .metodo p, .sede p, .contatti p, .mosaico p { max-width: var(--misura-colonna); }
.officina__quesito span:last-child { max-width: var(--misura-quesito); }
.metodo__nota { max-width: var(--misura-nota); }

/* ============================== tocchi di mestiere ============================== */
/* La fotografia dell'officina SCAVALCA il bordo della banda.
   ⚠ Una foto centrata non scavalca mai: il padding della sezione ne assorbe la sporgenza e la banda
   cresce con lei. Va ANCORATA a un bordo e tirata oltre con un margine maggiore del padding, così il
   suo contributo all'altezza cala e la riga la decide il testo. */
/* ⚠ La fotografia si allinea al CENTRO del blocco di testo, non al suo piede. Ancorata in basso
   (com'era, con lo scavalco negativo della banda) lasciava sopra di sé un vuoto pari alla differenza
   d'altezza fra le due colonne — misurato 191px su 493 — e la sezione leggeva sbilanciata.
   La colonna della figura si stira e la figura ci sta dentro centrata: due colonne che finiscono
   insieme, che è la definizione di allineato. */
.officina { align-items: stretch; }
.officina__media { align-self: stretch; display: grid; align-content: center; }
.officina__media img { box-shadow: 0 30px 70px rgba(14, 13, 10, .35); max-height: 100%; }
@media (max-width: 900px) { .officina__media { display: block; } }

/* Parallasse leggera sulla testata: la fotografia resta indietro mentre il testo sale. */
.hero__media img { will-change: transform; }

/* Il filetto d'ambra sotto i titoli si DISEGNA quando la banda entra in scena. */
.testa h2::after, .officina h2::after {
  content: ""; display: block; width: 76px; height: 4px; background: var(--accent);
  margin-top: var(--space-3); transform: scaleX(0); transform-origin: left;
  transition: transform .7s var(--ease) .15s;
}
.is-visible .testa h2::after, .reveal.is-visible h2::after,
.testa.is-visible h2::after { transform: scaleX(1); }
/* Fail-visible: senza JavaScript il filetto c'è già. */
html:not(.js) .testa h2::after, html:not(.js) .officina h2::after { transform: scaleX(1); }

/* Reticolo tecnico appena percepibile sulle bande scure: superficie, non decorazione. */
.banda-scura::before, .banda-ferro::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image: linear-gradient(rgba(255,193,60,.045) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255,193,60,.045) 1px, transparent 1px);
  background-size: 64px 64px;
}
.banda-scura, .banda-ferro { position: relative; }

/* La banda della sede cambia FORMA, non solo ornamento: fondo ferro e fotografia che esce dalla
   colonna fino al bordo della finestra. È il device che il template della categoria usa per rompere
   la sequenza — e qui ha materiale vero (l'esterno del capannone). */
.sede-banda--piena { overflow: hidden; }
.sede-banda--piena .sede { align-items: center; }
.sede-banda--piena .sede__media {
  margin-right: calc(50% - 50vw); margin-block: calc(var(--section-y) * -1);
}
.sede-banda--piena .sede__media img { aspect-ratio: auto; height: 100%; min-height: 30rem; object-fit: cover; }
@media (max-width: 900px) {
  .sede-banda--piena .sede__media { margin-right: calc(50% - 50vw); margin-left: calc(50% - 50vw); margin-block: var(--space-5) 0; }
  .sede-banda--piena .sede__media img { min-height: 0; aspect-ratio: 4 / 3; }
}

/* ============================== lightbox ============================== */
/* ⚠⚠ Lo stato NASCOSTO è OBBLIGATORIO. `reveal.js` crea `.fp-lb` al caricamento e la apre con
   `.is-open`, bloccando anche lo scroll del documento: un verticale che non la stila ottiene un
   overlay invisibile che intercetta i click e una pagina che non scorre più — cioè esattamente
   «clicco sull'immagine, non si apre e si blocca tutto». Non è un difetto del motore: è una resa che
   ogni verticale deve fornire, e dimenticarla non produce nessun errore. */
.fp-lb {
  display: none; position: fixed; inset: 0; z-index: 200;
  background: rgba(14, 13, 10, .94);
  align-items: center; justify-content: center; padding: var(--space-5);
}
.fp-lb.is-open { display: flex; }
.fp-lb__img, .fp-lb img { max-width: 92vw; max-height: 86vh; object-fit: contain; box-shadow: 0 30px 80px rgba(0, 0, 0, .6); }
.fp-lb__x {
  position: absolute; top: var(--space-5); right: var(--space-5);
  width: 52px; height: 52px; border: 2px solid var(--accent); background: transparent;
  color: var(--accent-on-dark); font-size: 0; cursor: pointer;
}
.fp-lb__x::before, .fp-lb__x::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 24px; height: 3px; background: currentColor;
}
.fp-lb__x::before { transform: translate(-50%, -50%) rotate(45deg); }
.fp-lb__x::after { transform: translate(-50%, -50%) rotate(-45deg); }
.fp-lb__x:hover { background: var(--accent); color: var(--on-accent); }
.fp-lb__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 52px; height: 52px; border: 2px solid var(--accent); background: transparent; color: var(--accent-on-dark);
  display: grid; place-items: center; cursor: pointer;
}
.fp-lb__nav:hover { background: var(--accent); color: var(--on-accent); }
.fp-lb__nav svg { width: 26px; height: 26px; }
.fp-lb__prev { left: clamp(.6rem, 3vw, 2rem); }
.fp-lb__next { right: clamp(.6rem, 3vw, 2rem); }
@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%; }
}

/* ============================== bande delle pagine di progetto ==============================
   ⚠ Un blocco di testo con la figura IMPILATA sotto lascia il vuoto a destra del testo e una figura
   piccola sperduta in mezzo alla banda (misurato: Block Shaft 200px in un contenitore da 1200).
   Qui testo e figura stanno sulla STESSA RIGA, centrati fra loro: la banda si riempie, la figura ha
   una colonna sua e non deve essere ingrandita oltre la propria risoluzione per non sembrare persa.
   ⚠ Classi usate SOLO dalle pagine di progetto: un verticale a pagina unica non le emette mai. */
/* ⚠⚠ Le due colonne si STIRANO e il contenuto si centra DENTRO ognuna. Centrando le colonne (com'era)
   la più corta restava alta quanto il proprio contenuto e sotto le rimaneva un vuoto pari alla
   differenza — misurato fino a 243px su 416. Stirando i box e centrando dentro, la figura resta
   otticamente al centro del testo (che è ciò che serve) e le due colonne finiscono insieme. */
.banda-duo { display: grid; grid-template-columns: 1.15fr .85fr; gap: var(--space-7); align-items: stretch; }
.banda-duo__testo { display: grid; align-content: center; }
.banda-duo--stretta { grid-template-columns: 1.25fr .75fr; }
.banda-duo__testo > *:first-child { margin-top: 0; }
.banda-duo__testo > *:last-child { margin-bottom: 0; }
/* ⚠ Centrando il contenuto nella colonna i margini fra titolo e testo si erano persi e le due cose
   risultavano incollate: il ritmo verticale va dichiarato, non ereditato dal flusso. */
.banda-duo__testo > * + * { margin-top: var(--space-4); }
.banda-duo__testo h2 + * { margin-top: var(--space-3); }
.banda-duo__testo .btn { margin-top: var(--space-5); justify-self: start; }
.banda-duo__figura { display: grid; align-content: center; justify-items: center; }
.banda-duo__figura img { width: 100%; height: auto; max-width: 100%; display: block; }
/* Le grafiche dei partner hanno il TESTO IMPRESSO: mai ritagliate, e su fondo bianco perché sono
   nate su bianco — su una banda chiara sparirebbe il bordo, su una scura stonerebbero. */
/* ⚠ La figura si CONTIENE: senza tetto una grafica alta rende la riga alta quanto lei, e il testo —
   centrato — si ritrova aria sopra e sotto. È lo stesso vuoto di prima, spostato dentro la colonna.
   Col tetto la riga la decide il testo quando il testo è lungo, e la figura quando è corto. */
.banda-duo__figura figure { margin: 0; width: 100%; background: #fff; padding: var(--space-4); max-height: 26rem; display: grid; }
.banda-duo__figura figure img { max-height: 100%; object-fit: contain; }
.banda-scura .banda-duo__figura figure, .banda-ferro .banda-duo__figura figure { box-shadow: 0 24px 60px rgba(0, 0, 0, .35); }
@media (max-width: 900px) {
  .banda-duo, .banda-duo--stretta { grid-template-columns: 1fr; gap: var(--space-5); }
}

/* Nastro di figure a piena riga: quando le grafiche sono più di una e vanno confrontate a colpo
   d'occhio (i marchi del noleggio, le due versioni di un antifurto). Colonne UGUALI: allineate. */
.fp-strisce { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-4); align-items: stretch; }
.fp-strisce figure { margin: 0; }
.fp-strisce img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* L'indirizzo del piè è un DATO, non prosa: non deve spezzarsi lasciando «(RM)» orfano su una riga
   sua. `text-wrap: balance` distribuisce le righe invece di riempire la prima e abbandonare il resto. */
.site-footer .sede__dl dd, .sede__dl dd { text-wrap: balance; }

/* ============================== testata di pagina con fotografia ============================== */
/* Una pagina interna che apre su una banda scura piatta è un cartello, non una testata: il titolo
   galleggia su un rettangolo e la pagina comincia dopo. Con la fotografia sotto il velo la banda
   diventa superficie, e il tema scuro resta quello di prima perché a cambiare è il fondo, non i colori.
   ⚠ Il velo NON è quello della testata di home, che si fa scuro scendendo: lì il testo occupa tutta
   l'altezza, qui è una banda bassa con le parole a sinistra. Degrada quindi in ORIZZONTALE — pieno
   dove stanno occhiello, titolo e apertura, più sottile sul bordo destro, che è l'unico punto dove la
   fotografia può respirare senza mettersi sotto a una riga di testo.
   ⚠ Il velo si tinge col TOKEN della marca: un rgba() cablato porterebbe su ogni progetto il
   near-black del primo cliente, che ha un'altra palette. */
.pagina-testata { isolation: isolate; overflow: hidden; }
.pagina-testata__media { position: absolute; inset: 0; z-index: -2; }
.pagina-testata__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; }
.pagina-testata::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--brand-dark) 95%, transparent) 0%,
    color-mix(in srgb, var(--brand-dark) 93%, transparent) 46%,
    color-mix(in srgb, var(--brand-dark) 86%, transparent) 100%);
}
/* Stretta la finestra il testo occupa TUTTA la banda, e la parte sottile del velo finirebbe sotto le
   parole: torna uniforme e pieno. */
@media (max-width: 900px) {
  .pagina-testata::after { background: color-mix(in srgb, var(--brand-dark) 93%, transparent); }
}

/* ============================== WhatsApp flottante ============================== */
/* Reso da `withFloatingWhatsapp` (cli/build.mjs) e acceso dal progetto con `whatsapp_floating` in
   canonical/chrome.json: un progetto che non lo dichiara non riceve il markup, quindi queste regole
   restano inerti sui siti gia' consegnati. E' un LINK a wa.me — nessuna richiesta di rete, nessun
   cookie, zero-live salvo.
   ⚠ Il battito NON e' un'animazione nuova: e' `fp-social-pulse`, lo stesso degli stemmi social qui
   sopra, e ne eredita anche la guardia `prefers-reduced-motion`. L'alone si tinge di
   `--accent-on-dark`; su questo bottone il campo e' il verde di WhatsApp, quindi il token si RIMAPPA
   localmente sul verde invece di duplicare i fotogrammi. */
.wa-flot {
  position: fixed; right: var(--gutter); bottom: clamp(1rem, 3vw, 2rem); z-index: 55;
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 50%;
  background: #25d366; box-shadow: 0 6px 20px rgb(0 0 0 / .3);
  --accent-on-dark: #25d366;
}
.wa-flot svg { width: 30px; height: 30px; }   /* il riempimento e' dichiarato dentro il marchio */
.wa-flot::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  animation: fp-social-pulse 2.8s var(--ease) infinite;
}
/* Fermo sotto il puntatore: chi sta per cliccare non ha bisogno di essere richiamato. */
.wa-flot:hover::after { animation-play-state: paused; }
.wa-flot:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
/* ⚠ Su telefono la barra CTA fissa occupa lo stesso angolo (`.cta-bar`, sotto i 720px): senza questo
   scarto i due bersagli si sovrappongono e il pollice ne colpisce uno a caso. */
@media (max-width: 720px) { .wa-flot { bottom: calc(clamp(1rem, 3vw, 2rem) + 3.9rem); } }
@media (prefers-reduced-motion: reduce) { .wa-flot::after { animation: none; } }
@media print { .wa-flot { display: none; } }

/* ============================== striscia dei marchi trattati ============================== */
/* I marchi dei costruttori che l'officina tratta. Sono grafiche di TERZI: non si ricolorano e non si
   ritagliano — si posano su una targa chiara, che è l'unico modo di mostrarle intere su una banda
   scura senza toccarle. Additiva e usata solo da chi la cita: un progetto che non la porta non cambia.
   ⚠ `object-fit: contain` e non `cover`: un marchio tagliato non è più quel marchio. */
.marchi-riga {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--space-3);
  align-items: stretch;
}
.marchi-riga figure {
  margin: 0; background: var(--paper); padding: var(--space-3) var(--space-4);
  display: flex; align-items: center; justify-content: center;
}
.marchi-riga img { width: 100%; height: auto; max-height: 64px; object-fit: contain; }
@media (max-width: 900px) { .marchi-riga { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .marchi-riga { grid-template-columns: repeat(2, 1fr); } }

/* ============================== recensioni ============================== */
/* Parole di TERZI: si riportano com'è stato scritto, col nome e la piattaforma, e non si accorciano.
   ⚠ Vivono su banda scura, quindi l'inchiostro è il chiaro e il nome prende `--accent-on-dark`, che è
   l'accento nel ruolo di inchiostro (l'accento pieno su fondo scuro non sempre regge: v. tokens.css). */
.recensioni {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4);
  /* ⚠ `align-items: start` faceva scendere ogni tessera all'altezza del proprio testo: tre recensioni di
     lunghezza molto diversa diventavano tre riquadri di altezza molto diversa, e la riga si leggeva come
     un errore invece che come una griglia. `stretch` (il default della griglia) le pareggia. */
  align-items: stretch;
}
/* ⚠ Pareggiare le altezze non basta: senza una colonna interna la firma resta attaccata al testo e
   «galleggia» a mezz'aria nelle tessere corte. La citazione occupa lo spazio disponibile e la firma
   scende in fondo, cosi' le tre firme si allineano fra loro. */
.recensione {
  margin: 0; background: var(--brand-mid); padding: var(--space-5) var(--space-4);
  border-left: 4px solid var(--accent);
  display: flex; flex-direction: column;
}
.recensione blockquote { margin: 0; }
.recensione blockquote p { color: var(--on-dark-muted); font-size: var(--t-sm); }
.recensione figcaption {
  margin-top: auto; padding-top: var(--space-4); font-family: var(--font-display); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--accent-on-dark);
}
.recensione figcaption span { color: var(--on-dark-muted); font-family: var(--font-body); font-weight: 400; letter-spacing: 0; text-transform: none; }
@media (max-width: 980px) { .recensioni { grid-template-columns: 1fr; } }

/* ============================== figura che apre una banda ==============================
   Una fotografia di PRODOTTO su fondo bianco — un macchinario ritratto in studio — non regge la colonna
   di fianco al testo: verticale e stretta diventa altissima, e il testo le corre a lato per mezzo schermo.
   Qui apre la banda, sopra le parole, alla propria proporzione e con un tetto d'altezza.
   ⚠ `object-fit: contain` e non `cover`: un macchinario ritagliato non e' piu' quel macchinario. */
.figura-sopra { margin: 0 0 var(--space-6); display: flex; justify-content: center; align-items: flex-start; }
/* ⚠⚠ `box-sizing: border-box` NON e' un dettaglio qui: la targa bianca e' un `padding` sull'immagine, e
   senza di esso `max-width: 100%` cappa il solo riquadro del contenuto — la targa sborda oltre il
   contenitore. Misurato a 390: riquadro 371px dentro un contenitore da 350, cioe' 21px di traboccamento
   orizzontale che nessuna delle due misure dichiarate faceva sospettare. */
.figura-sopra img {
  box-sizing: border-box;
  width: auto; height: auto; max-width: 100%; max-height: 40rem;
  object-fit: contain; background: var(--paper); padding: var(--space-4);
}
@media (max-width: 620px) { .figura-sopra img { max-height: 26rem; padding: var(--space-3); } }

/* ============================== schede dei ricambi ============================== */
/* Stessa forma delle tessere di servizio, ma queste PORTANO un invito: una richiesta di disponibilità.
   ⚠ Sono una famiglia a parte di proposito. Le tessere `.servizio` non devono contenere `<a>` — è un
   vincolo esplicito del primo cliente, presidiato da un gate — e riusarle qui lo aggirerebbe di fatto.
   ⚠ Non è un catalogo di vendita: non esistono prezzo, carrello né acquisto. Il codice è il codice del
   cliente, e l'azione è «chiedi informazioni». */
.ricambi__griglia {
  margin-top: var(--space-6);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5);
}
.ricambio { position: relative; }
.ricambio__media { position: relative; background: var(--brand-mid); overflow: hidden; }
.ricambio__media img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  transition: transform .6s var(--ease), filter .6s var(--ease);
}
.ricambio:hover .ricambio__media img { transform: scale(1.05); filter: saturate(1.1) contrast(1.03); }
.ricambio__media::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 5px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .45s var(--ease);
}
.ricambio:hover .ricambio__media::after { transform: scaleX(1); }
.ricambio h3 { font-size: var(--t-lg); margin-top: var(--space-3); }
.ricambio__cod {
  margin-top: var(--space-1); font-family: var(--font-display); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--tracking-label);
  font-size: var(--t-xs); color: var(--accent-ink);
}
.ricambio p:not(.ricambio__cod) { margin-top: var(--space-2); color: var(--ink-muted); font-size: var(--t-sm); max-width: var(--misura-tessera); }
.ricambio .btn { margin-top: var(--space-3); }
@media (max-width: 980px) { .ricambi__griglia { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .ricambi__griglia { grid-template-columns: 1fr; } }

/* ============================== dinamica: i modificatori di rivelazione ==============================
   ⚠⚠ `reveal.js` AGGIUNGE le classi `reveal--<modo>` (da `data-stagger`) e le rende visibili con
   `is-visible`, ma la RESA la deve dare il verticale: finora questo foglio non ne dichiarava NESSUNA, e
   ogni `reveal--left`/`--wipe`/`--rise` scritto nel markup era inerte. È la stessa famiglia del difetto
   della lightbox su Arnone — il motore porta il COMPORTAMENTO, non la resa, e dimenticarla non produce
   nessun errore in console né in nessun gate.
   ⚠⚠ SOLO `transform`, mai `opacity`: un elemento in opacità può impedire il download delle immagini che
   contiene, e axe coglie il fotogramma intermedio di una dissolvenza dichiarandolo testo a basso
   contrasto. Nessuna di queste regole nasconde mai un elemento, quindi le lazy dentro si caricano.
   La guardia `prefers-reduced-motion` è quella già dichiarata in base.css per `.reveal`; qui si ripete
   per i modificatori, perché una regola nuova non eredita la guardia di un'altra. */
.js .reveal--rise { transform: translateY(34px); }
.js .reveal--left { transform: translate3d(-26px, 10px, 0); }
.js .reveal--rise.is-visible,
.js .reveal--left.is-visible { transform: none; }

/* La figura si «posa»: l'immagine entra appena ingrandita e si assesta dentro il proprio riquadro.
   ⚠ Non è un `clip-path`: un ritaglio a zero rende l'elemento di area nulla e BLOCCA il caricamento
   delle immagini lazy che contiene (difetto già pagato su law_firm). Qui l'immagine è sempre intera e
   sempre visibile: si muove soltanto. */
.js .reveal--wipe { overflow: hidden; }
.js .reveal--wipe img { transform: scale(1.06); transition: transform 1.1s var(--ease); }
.js .reveal--wipe.is-visible img { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal--rise, .js .reveal--left,
  .js .reveal--rise.is-visible, .js .reveal--left.is-visible { transform: none; }
  .js .reveal--wipe img, .js .reveal--wipe.is-visible img { transform: none; transition: none; }
}

/* ============================== dinamica: reazione al puntatore ==============================
   Tessere che rispondono al passaggio del mouse. Il verticale lo fa già per i servizi e per il mosaico;
   qui lo estende alle famiglie nate con questo sito, così la pagina risponde ovunque allo stesso modo.
   ⚠ Sollevamento di 3px e ombra: sotto questa soglia non si percepisce, sopra diventa un rimbalzo. */
.recensione, .marchi-riga figure, .ricambio__media {
  transition: transform var(--dur, .3s) var(--ease), box-shadow var(--dur, .3s) var(--ease);
}
.recensione:hover { transform: translateY(-3px); box-shadow: 0 12px 28px rgb(0 0 0 / .3); }
.marchi-riga figure:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgb(0 0 0 / .28); }
/* Il filetto d'oro sotto la citazione cresce da sinistra: lo stesso gesto del filetto sotto gli h2. */
.recensione { position: relative; }
.recensione::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 4px; height: 0;
  background: var(--accent-on-dark); transition: height .8s var(--ease);
}
.recensione.is-visible::after { height: 100%; }
@media (prefers-reduced-motion: reduce) {
  .recensione:hover, .marchi-riga figure:hover { transform: none; }
  .recensione::after, .recensione.is-visible::after { height: 100%; transition: none; }
}

/* ============================== dinamica: parallasse delle testate di pagina ==============================
   La fotografia di fondo scorre più lenta della pagina: la testata smette di sembrare un'immagine
   incollata. ⚠⚠ Il fattore `p` di reveal.js arriva a ±1,15 (non a ±1: il `rootMargin` è 15%), quindi con
   `data-parallax="4"` lo spostamento massimo è il 4,6% dell'altezza del media. Il riquadro si allarga
   quindi del 6% sopra e sotto, o la parallasse SCOPRE il fondo della banda — difetto già visto su tre
   siti della flotta. ⚠ Si applica SOLO a chi dichiara l'attributo: una testata senza parallasse resta
   esattamente com'era, quindi i siti già consegnati non si muovono. */
.pagina-testata__media[data-parallax] { inset: -6% 0; will-change: transform; }

/* ============================== dinamica: le fotografie di banda si POSANO ==============================
   ⚠ Governata dal token `--foto-entrata`, il cui default è `1`: senza preset la scala non cambia, la
   transizione non ha nulla da animare e i siti già consegnati restano identici. `overflow: hidden` è
   inerte a scala 1 (non c'è niente che sporga da contenere).
   ⚠ SOLO transform: nessuna opacità, o le immagini dentro rischiano di non scaricarsi e axe coglie il
   fotogramma intermedio. L'immagine è sempre intera e sempre visibile: si muove soltanto. */
.js :is(.chisiamo__media, .metodo__media, .sede__media, .officina__media, .banda-duo__figura) { overflow: hidden; }
.js :is(.chisiamo__media, .metodo__media, .sede__media, .officina__media, .banda-duo__figura) img {
  transform: scale(var(--foto-entrata, 1));
  transition: transform 1.2s var(--ease);
}
.js :is(.chisiamo__media, .metodo__media, .sede__media, .officina__media, .banda-duo__figura).is-visible img { transform: none; }

/* Le tre schede sotto la testata rispondono al puntatore: il marcatore d'oro si allunga e la scheda si
   solleva. È il solo stato che cambia — a riposo la scheda è identica a prima. */
.tessere__cella { transition: transform var(--dur, .3s) var(--ease), box-shadow var(--dur, .3s) var(--ease); }
.tessere__cella h3::before { transition: height .35s var(--ease); }
.tessere__cella:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgb(0 0 0 / .12); }
.tessere__cella:hover h3::before { height: 30px; }

@media (prefers-reduced-motion: reduce) {
  .js :is(.chisiamo__media, .metodo__media, .sede__media, .officina__media, .banda-duo__figura) img,
  .js :is(.chisiamo__media, .metodo__media, .sede__media, .officina__media, .banda-duo__figura).is-visible img { transform: none; transition: none; }
  .tessere__cella, .tessere__cella:hover { transform: none; transition: none; }
  .tessere__cella h3::before, .tessere__cella:hover h3::before { transition: none; }
}
