/* components.css — le bande del verticale building_contractor (impresa edile che costruisce e
   ristruttura, con progettazione e consegna chiavi in mano).
   Registro BeEco3: testata fotografica a piena larghezza con titolo condensed maiuscolo, e una SCHEDA
   chiara che scavalca il bordo inferiore della fotografia. Il mestiere si dice con le persone e i
   mezzi veri; dove la fotografia non arriva, il carattere lo porta il CAMPO GIALLO PIENO — che nella
   categoria è il dispositivo strutturale contro la penuria fotografica, e nel cantiere è il colore
   della segnaletica.

   ⚠⚠ Disciplina del giallo, valida in TUTTO il file: `--accent` è una SUPERFICIE. Sopra ci va
   `--ink` (10,93), mai il bianco (1,58). Come inchiostro il giallo vale solo sulle bande scure
   (11,24); sui fondi chiari l'accento testuale è `--accent-ink` (5,91). */

/* ⚠⚠ 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, terra, testata, piè, testata fotografica) e ogni regola scritta per una
   sola lascia le altre nere su nero. 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-terra, .site-footer, .hero, .recapiti-bar, .site-header .wp-block-navigation__responsive-container.is-menu-open) {
  --ink: var(--on-dark);
  --ink-muted: var(--on-dark-muted);
  /* ⚠ L'accento TESTUALE dentro una banda scura passa da `--accent-on-dark`, che per default È
     `--accent`: un accento di marca più scuro (un rosso #e40613 fa 3,29) sarebbe sotto AA su ogni
     occhiello di ogni banda scura, e nessun gate di rendering lo vede. */
  --accent-ink: var(--accent-on-dark);
  --line: rgba(242, 203, 14, .22);
  --surface: var(--brand-mid);
  --paper: var(--brand);
}
/* ⚠⚠ Il CAMPO GIALLO è una superficie CHIARA che non dipende dal contesto: dentro una banda scura i
   token sopra diventano chiari, ma il giallo resta giallo e il bianco sul giallo fa 1,58. Qui si
   rimappa in senso opposto, così una banda gialla annidata in una scura resta leggibile. */
.banda-gialla {
  --ink: var(--on-accent);
  --ink-muted: #4a3f14;          /* 7,04 sul giallo */
  --accent-ink: var(--on-accent);
  --line: rgba(28, 27, 24, .26);
  --paper: var(--accent);
  --surface: var(--accent-dark);
  background: var(--accent); color: var(--on-accent);
}
.banda-gialla h2, .banda-gialla h3 { color: var(--on-accent); }

/* 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; } }
/* ⚠ L.elenco degli id era CHIUSO: ogni ancora nuova nasceva fuori dalla regola e atterrava SOTTO la
   testata fissa. Un ancora cieca non rompe niente di misurabile — la pagina resta 200 — e nessun
   crawl la vedrebbe. La regola vale ora su qualunque elemento con un id dentro il contenuto. */
[id="chi-siamo"], [id="servizi"], [id="mezzi"], [id="cantieri"], [id="contatti"], #main,
.servizio-esteso[id], .wp-block-post-content [id] {
  scroll-margin-top: var(--header-h);
}

/* ============================== testata ============================== */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--paper);
  border-bottom: 3px solid var(--accent);
  /* ⚠⚠ La testata è CHIARA per una ragione misurata, non per gusto: il marchio del cliente è un
     lockup corsivo bruno (#8b6b4a) e oro su fondo trasparente, disegnato per il bianco. Sul grafite
     della banda scura il bruno misura 3,58 — sotto AA — e ricolorare a mano un logo raster corsivo
     significa rifarlo. La lingua di eco3 la porta la TESTATA FOTOGRAFICA, non la barra del menu. */
  color: var(--ink);
}
/* ⚠ 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: il materiale del cliente mette mail e indirizzo IN CIMA, sopra il menu. */
.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, .recapiti-bar span { 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); }
/* La testata si CONTRAE scorrendo: la barra dei recapiti si ritira e la riga si stringe. L'ancora non
   deve più scavalcare un'intestazione alta, 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 .wordmark--logo img { height: 38px; }
.site-header .wordmark--logo img { transition: height .35s var(--ease); }
.site-header.is-scrolled { box-shadow: 0 8px 24px rgba(26, 24, 21, .16); }
.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. */
.wordmark--logo img { height: 52px; width: auto; }
.wordmark__txt {
  font-family: var(--font-display); font-weight: 700; font-size: 1.5rem;
  letter-spacing: .02em; text-transform: uppercase; color: var(--ink); line-height: 1;
}
.wordmark__txt em { font-style: normal; color: var(--accent-ink); }

.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`. Il colore va anche sullo `__label`. */
.site-header .site-nav a,
.site-header .site-nav .wp-block-navigation-item__content,
.site-header .site-nav .wp-block-navigation-item__label {
  font-family: var(--font-display); font-weight: 600; font-size: 1.0625rem;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink);
}
.site-header .site-nav .wp-block-navigation-item__content { 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-ink); 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 { color: var(--ink); }
.site-header .wp-block-navigation__responsive-container-close { color: var(--accent-on-dark); }

/* Il telefono in testata è il punto d'azione del mestiere: campo giallo 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 ---
   ⚠⚠ WP tiene l'overlay BIANCO con `:not(.has-background) … :not(.disable-default-overlay)` = (0,4,0):
   si vince solo RICOPIANDO il suo schema di selettore, non aggiungendo un livello a caso. È il difetto
   più ricorrente della flotta: menu bianco su bianco. */
.site-header .wp-block-navigation__responsive-container.is-menu-open,
.wp-block-navigation__responsive-container:not(.has-background).is-menu-open:not(.disable-default-overlay) {
  background: var(--brand-dark); color: var(--on-dark);
}
/* ⚠ Se la testata avesse un `backdrop-filter`, quel filtro creerebbe un containing-block per il
   `position:fixed` e l'overlay si limiterebbe all'altezza dell'header. L'altezza si dichiara. */
.site-header .wp-block-navigation__responsive-container.is-menu-open {
  height: 100vh; max-height: 100vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.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. Il padding INFERIORE è generoso perché l'ultima voce non
     finisca sotto la barra CTA fissa del mobile. */
  padding: calc(56px + var(--space-6)) var(--gutter) var(--space-10);
  align-items: stretch; width: 100%;
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container { gap: 0; width: 100%; }
/* ⚠ 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,
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__label {
  display: block; width: 100%; text-align: left; color: var(--on-dark);
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  padding: var(--space-3) 0; font-size: 1.6rem; letter-spacing: .06em;
  border-bottom: 1px solid rgba(242, 203, 14, .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(242, 203, 14, .22); }
/* I sotto-menu restano INLINE: il default di WP li rende come card-dropdown, illeggibili su mobile. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
  position: static !important; border: 0 !important; box-shadow: none !important;
  background: none !important; padding-left: var(--space-4); width: 100%;
}
/* 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; }

/* ⚠ Il contenitore responsive del blocco nav porta un proprio box che gonfia la riga della testata.
   A riposo (menu chiuso) non deve occupare nulla oltre alle voci. */
.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; }
/* ⚠ 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. */
.site-header__row { height: 86px; padding-block: 0; flex-wrap: nowrap; align-items: center; }
.site-header.is-scrolled .site-header__row { height: 64px; }
.site-header .site-nav, .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 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 di cantiere, che è chiara a chiazze
   (cielo, pietrisco calcareo). ⚠ Il limite lo danno i pixel CHIARI dietro il testo, non la media. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(26,24,21,.58) 0%, rgba(26,24,21,.72) 55%, rgba(26,24,21,.9) 100%);
}
/* ⚠ Con lo slideshow le fotografie cambiano e una sola può essere molto chiara: il velo si rinforza
   SOLO quando c'è lo slideshow, senza toccare quello della variante a scatto singolo. */
.hero:has(.hero-media)::after {
  background: linear-gradient(180deg, rgba(26,24,21,.66) 0%, rgba(26,24,21,.78) 55%, rgba(26,24,21,.93) 100%);
}
.hero__inner { padding-block: clamp(4.5rem, 12vw, 9rem); }
/* ⚠⚠ L.occhiello della testata è BIANCO, non giallo. Misurato dai PIXEL sotto il testo, a testo
   nascosto e su tutti e tre i fotogrammi dello slideshow: il giallo su fotografia velata scende a
   4,16 (desktop, 1° scatto) e 4,08 (mobile, 3° scatto), sotto AA per un testo di 15px. Il giallo
   resta sul FILETTO, che è decoro e non deve portare significato — è la disciplina del verticale:
   il giallo è superficie, mai inchiostro. Il bianco sugli stessi pixel misura 6,4.
   ⚠ Il velo NON si irrobustisce per questo: annerirebbe la fotografia per una riga di 15px. */
.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(--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); }

/* Lo slideshow: N fotografie in dissolvenza incrociata dietro il velo. `isolation:isolate` sul .hero
   e le slide a z-index -2 le tengono DIETRO lo scrim. Con reduced-motion resta ferma la prima. */
.hero-media { position: absolute; inset: 0; z-index: -2; }
/* ⚠⚠ MISURATO: con 32s di ciclo e tre fotografie sfalsate di 8s, fra t=24s e t=31s NESSUNA slide era
   visibile — la testata restava il velo nudo per sette secondi a ogni giro. La cadenza era tarata su
   QUATTRO slide (0/8/16/24) mentre l'IR ne dichiara tre: il ciclo scende a 24s e le finestre si
   sovrappongono, così l'ultima rientra mentre la prima riparte. Chi userà quattro fotografie cambia
   la durata, non i tempi: la regola è ciclo = 8s × numero di slide. */
.hero-slide {
  position: absolute; inset: 0; opacity: 0;
  background-size: cover; background-position: center;
  animation: fp-hero-fade 24s var(--ease) infinite;
}
.hero-slide:nth-child(1) { animation-delay: 0s; }
.hero-slide:nth-child(2) { animation-delay: 8s; }
.hero-slide:nth-child(3) { animation-delay: 16s; }
@keyframes fp-hero-fade {
  0%, 28% { opacity: 1; transform: scale(1.045); }
  36%, 92% { opacity: 0; transform: scale(1); }
  100% { opacity: 1; transform: scale(1.045); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-slide { animation: none; opacity: 0; transform: none; }
  .hero-slide:nth-child(1) { opacity: 1; }
}

/* La SCHEDA che scavalca il bordo inferiore della testata: è la firma di eco3. Non chiede una
   fotografia migliore — chiede solo che il fondo sotto sia chiaro. */
.hero-scheda {
  background: var(--paper); color: var(--ink);
  padding: var(--space-5) var(--space-5) var(--space-5);
  max-width: 34rem; margin-top: var(--space-6); margin-bottom: calc(var(--section-y) * -0.5);
  position: relative; z-index: 2;
  border-left: 6px solid var(--accent);
}
.hero-scheda h2 { font-size: var(--t-lg); color: var(--ink); }
.hero-scheda p { margin-top: var(--space-2); color: var(--ink-muted); font-size: var(--t-sm); }
@media (max-width: 860px) { .hero-scheda { margin-bottom: 0; max-width: none; } }

/* Variante senza fotografia hero-grade: campo giallo 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é il giallo come TESTO vale solo su scuro (11,24) e su
   chiaro fa 1,58. Il default è quello per fondo CHIARO — l'errore, se si sbaglia contesto, cade dalla
   parte sicura; la forma gialla 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-terra .btn--fantasma, .hero .btn--fantasma { border-color: var(--accent); color: var(--accent-on-dark); }
.banda-scura .btn--fantasma:hover, .banda-terra .btn--fantasma:hover, .hero .btn--fantasma:hover { background: var(--accent); color: var(--on-accent); }
/* Dentro il campo giallo il fantasma è INCHIOSTRO: il giallo su giallo non esiste. */
.banda-gialla .btn--fantasma { border-color: var(--on-accent); color: var(--on-accent); }
.banda-gialla .btn--fantasma:hover { background: var(--on-accent); color: var(--accent); }
.banda-gialla .btn--primario { background: var(--brand); color: var(--on-dark); }
.banda-gialla .btn--primario:hover { background: var(--brand-dark); }

/* ============================== 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-terra { background: var(--brand-mid); color: var(--on-dark); }
.banda-terra h2, .banda-terra h3 { color: var(--on-dark); }

/* ⚠ La testata di sezione non è affiancata da NULLA: il telaio è una riga intera. Tenerla dentro una
   misura di lettura lasciava metà riga bianca a destra — è la regola owner sul testo senza fotografia,
   e qui il sommario è una frase sola che a piena larghezza sta su una riga. Il titolo conserva la
   propria misura: un display lungo su 1200px diventerebbe illeggibile. */
.testa { max-width: none; }
.testa h2 { 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-terra .testa__eyebrow { color: var(--accent-on-dark); }
.banda-gialla .testa__eyebrow { color: var(--on-accent); }
.banda-gialla .testa__eyebrow::before { background: var(--on-accent); }
.testa h2 { font-size: var(--t-2xl); margin-top: var(--space-3); }
.testa__lead { margin-top: var(--space-3); color: var(--ink-muted); font-size: var(--t-lead); max-width: none; }
.banda-scura .testa__lead, .banda-terra .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); color: var(--ink-muted); }

/* ============================== il campo giallo che porta solo tipografia ==============================
   È il dispositivo strutturale della categoria contro la penuria fotografica: una banda piena di solo
   COLORE che porta SOLO carattere. Nel cantiere è anche il colore della segnaletica. */
/* ⚠⚠ Era una griglia «1fr auto»: il testo a sinistra e UN pulsante solo, orfano, a destra. Un bottone
   isolato in mezzo a un campo di colore non è una gerarchia, è un avanzo — e la metà destra restava
   vuota per due terzi. Ora la banda è una CHIAMATA: il claim al centro della fascia, e sotto una riga
   di azioni vere (telefono grande, WhatsApp, preventivo) che è il motivo per cui la banda esiste. */
.claim { display: grid; gap: var(--space-5); justify-items: center; text-align: center; }
.claim__testo { font-family: var(--font-display); font-weight: 700; font-size: var(--t-2xl);
  text-transform: uppercase; line-height: var(--lh-heading); color: var(--on-accent); max-width: 20ch; }
.claim__nota { margin-top: var(--space-3); font-family: var(--font-body); font-weight: 400;
  font-size: var(--t-base); text-transform: none; line-height: var(--lh-body); color: var(--ink-muted);
  max-width: var(--misura-nota); margin-inline: auto; }
.claim__azioni { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; justify-content: center; }
/* Il numero è l'azione principale del mestiere: si scrive grande, non si nasconde in un bottone. */
.claim__tel {
  font-family: var(--font-display); font-weight: 700; font-size: var(--t-xl);
  color: var(--on-accent); letter-spacing: .01em; display: inline-flex; align-items: center; gap: .6rem;
  border-bottom: 3px solid rgba(28, 27, 24, .3); padding-bottom: .15rem;
}
.claim__tel:hover { border-bottom-color: var(--on-accent); }
/* Il campo giallo prende una TRAMA diagonale appena percepibile: un campo piatto grande legge come
   un buco di colore, e il cantiere la trama ce l'ha addosso (segnaletica, casseri). */
.banda-gialla { position: relative; isolation: isolate; overflow: hidden; }
.banda-gialla::before {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: .32;
  background-image: repeating-linear-gradient(135deg, rgba(28,27,24,.14) 0 2px, transparent 2px 14px);
}
/* E una vignettatura calda che le dà profondità invece del piatto. */
.banda-gialla::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.34), transparent 62%);
}
@media (max-width: 860px) { .claim__tel { font-size: var(--t-lg); } }

/* ============================== chi siamo ============================== */
/* La colonna della fotografia pesa piu di quella del testo: in questo mestiere lo scatto della
   squadra e il contenuto piu forte della sezione, e a meta riga si leggeva come una miniatura. */
.chisiamo { display: grid; grid-template-columns: 1fr 1.25fr; gap: var(--space-7); align-items: center; }
.chisiamo__media img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.chisiamo p { max-width: var(--misura-colonna); }
/* ⚠ Senza fotografia la colonna singola NON resta stretta a metà pagina: prende tutta l'area e va a
   capo da sola (regola owner). Il telaio CAMBIA, non si svuota una metà. */
.chisiamo--senza-foto { grid-template-columns: 1fr; }
.chisiamo--senza-foto p { max-width: var(--misura-prosa); }
@media (max-width: 900px) { .chisiamo { grid-template-columns: 1fr; } }

/* ============================== i tre servizi ============================== */
.servizi__griglia { margin-top: var(--space-6); display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.servizio {
  background: var(--paper); border-top: 5px solid var(--accent);
  padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
a.servizio:hover, a.servizio:focus-visible { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(26, 24, 21, .16); }
/* Le icone del materiale sono PNG neri su trasparente: usate come MASCHERA prendono `currentColor` e
   si ricolorano col contesto. Un <img> non erediterebbe il colore, e un filtro non darebbe il bronzo.
   ⚠ La maschera si risolve rispetto al FOGLIO: la regola deve stare qui, non in uno style inline. */
/* ⚠ `display:block` sta sulla regola BASE, non sulla variante: uno <span> è inline e ignora
   width/height. Nella tessera il difetto non si vedeva perche `.servizio` e un flex container e ne
   blockificava i figli; fuori di li l.icona usciva 0x0 — maschera presente, superficie nessuna. */
.servizio__ico { display: block; width: 56px; height: 56px; background: var(--accent-ink); flex: 0 0 auto; }
.servizio__ico[data-ico="chiavi-in-mano"] {
  -webkit-mask: url("../assets/img/icons/chiavi-in-mano.png") no-repeat center / contain;
          mask: url("../assets/img/icons/chiavi-in-mano.png") no-repeat center / contain;
}
.servizio__ico[data-ico="progettazione"] {
  -webkit-mask: url("../assets/img/icons/progettazione.png") no-repeat center / contain;
          mask: url("../assets/img/icons/progettazione.png") no-repeat center / contain;
}
.servizio__ico[data-ico="professionalita"] {
  -webkit-mask: url("../assets/img/icons/professionalita.png") no-repeat center / contain;
          mask: url("../assets/img/icons/professionalita.png") no-repeat center / contain;
}
.servizio h3 { font-size: var(--t-lg); margin-top: var(--space-2); }
.servizio p { color: var(--ink-muted); font-size: var(--t-sm); max-width: var(--misura-tessera); }
.servizio__vai {
  margin-top: auto; padding-top: var(--space-3);
  font-family: var(--font-display); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--accent-ink); display: inline-flex; align-items: center; gap: .4rem;
}
a.servizio:hover .servizio__vai { gap: .8rem; }
@media (max-width: 900px) { .servizi__griglia { grid-template-columns: 1fr; } }

/* ============================== parco mezzi ============================== */
/* I mezzi sono un ELENCO di fatti (uno di questi, due di quelli): la forma è una riga di schede con
   il numero grande, non un mosaico di fotografie che il materiale non ha. */
.mezzi__griglia { margin-top: var(--space-6); display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.mezzo { border: 1px solid var(--line); padding: var(--space-4); display: grid; gap: var(--space-2); }
.mezzo__n {
  font-family: var(--font-display); font-weight: 700; font-size: var(--t-xl);
  color: var(--accent-ink); line-height: 1;
}
.banda-scura .mezzo__n, .banda-terra .mezzo__n { color: var(--accent-on-dark); }
.mezzo__nome { font-family: var(--font-display); font-weight: 600; font-size: var(--t-lg); text-transform: uppercase; }
.mezzi__foto { margin-top: var(--space-6); display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }
.mezzi__foto img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
@media (max-width: 900px) { .mezzi__griglia, .mezzi__foto { grid-template-columns: 1fr; } }

/* ============================== i cantieri (gallery) ============================== */
/* ⚠ Il mosaico non promette più fotografie di quante ce ne siano: con poche foto la griglia regolare
   a tessere grandi è più onesta (e più bella) di una scacchiera con i buchi. */
.cantieri__griglia { margin-top: var(--space-6); display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-4); }
/* ⚠ Il fondo scuro sta sull.IMMAGINE, non sulla figura: serve solo a non far lampeggiare il vuoto
   mentre lo scatto carica. Sulla FIGURA copriva anche la didascalia, che eredita `--ink-muted` —
   token tarato sui fondi chiari — e la portava a 1,6 su grafite. È la stessa famiglia del token
   verificato su una superficie e usato su un.altra: qui la superficie la creava il componente. */
.cantieri figure { margin: 0; overflow: hidden; position: relative; }
.cantieri img { background: var(--brand-mid); }
.cantieri img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
  transition: transform .7s var(--ease), filter .5s var(--ease);
  filter: saturate(.92) contrast(1.02);
}
.cantieri a.zoom:hover img, .cantieri a.zoom:focus-visible img { transform: scale(1.06); filter: saturate(1.06) contrast(1.04); }
.cantieri figcaption {
  padding: var(--space-3) 0 0; font-size: var(--t-sm); color: var(--ink-muted);
}
@media (max-width: 700px) { .cantieri__griglia { grid-template-columns: 1fr; } }

/* ============================== sede e recapiti ============================== */
.sede { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-7); align-items: start; }
.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 var(--space-3); color: var(--ink); }
.banda-scura .sede__dl dt { color: var(--accent-on-dark); }
.banda-scura .sede__dl dd { color: var(--on-dark); }
/* 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); }
@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);
}
.banda-scura .field label, .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; }
/* Aside dei recapiti su fondo CHIARO: non riusa la scheda della banda scura, che lì si invertirebbe. */
.contact-info { background: var(--surface); padding: var(--space-5); border-left: 6px solid var(--accent); }
@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: con tre frazioni UGUALI
   il centro della seconda coincide col centro della riga. */
/* ⚠ Tre colonne UGUALI con la terza allineata a destra: i recapiti uscivano a bandiera, l'indirizzo
   andava a capo lasciando «(SR)» orfano su una riga sua, e la prima colonna restava mezza vuota. Ora
   le colonne sono proporzionate al contenuto e tutte allineate a SINISTRA: una riga di recapiti si
   legge in colonna, non a specchio. */
.site-footer__row {
  display: grid; grid-template-columns: 1fr .85fr 1.5fr;
  gap: var(--space-6) var(--space-7); padding-block: var(--space-8);
  align-items: start;
}
/* ⚠ Una GRIGLIA a due colonne su un <dl> mette i <dt> in una colonna e i <dd> nell'altra: le
   etichette finiscono staccate dal proprio valore, con metri di vuoto in mezzo. È stato il primo
   tentativo, ed era peggio del difetto. La coppia etichetta+valore resta IMPILATA — è così che si
   legge un recapito — e la colonna si allarga quanto basta perché l'indirizzo non spezzi «(SR)». */
.site-footer .sede__dl { display: block; }
.site-footer .sede__dl dt { margin-top: var(--space-3); }
.site-footer .sede__dl dt:first-child { margin-top: 0; }
.site-footer .sede__dl dd { margin: .2rem 0 0; text-wrap: balance; }
.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(242, 203, 14, .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; } .site-footer__row > :nth-child(3) { justify-self: start; text-align: left; } .site-footer__row > :nth-child(3) .sede__dl dd { text-align: left; } }

/* ============================== WhatsApp e stemmi ==============================
   Il canale si dice con lo STEMMA, non con la parola. Vivono su fondo scuro (piè e testata), quindi
   l'inchiostro è il bianco e l'accento resta per il passaggio del mouse. */
.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="whatsapp"] {
  -webkit-mask: url("../assets/img/icons/social-whatsapp.svg") no-repeat center / contain;
          mask: url("../assets/img/icons/social-whatsapp.svg") no-repeat center / contain;
}
.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;
}
/* Il pulsante WhatsApp: verde di canale, bianco sopra (5,03 AA). Il battito è un alone che si allarga
   su uno pseudo-elemento, così il bersaglio resta fermo e cliccabile. */
.wa-btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  background: #0b8043; color: #ffffff; width: 42px; height: 42px; border-radius: 50%;
}
.wa-btn .social__ico { width: 22px; height: 22px; }
.wa-btn::after {
  content: ""; position: absolute; inset: -2px; border-radius: 50%; pointer-events: none;
  animation: fp-wa-pulse 2.6s var(--ease) infinite;
}
.wa-btn:hover::after, .wa-btn:focus-visible::after { animation-play-state: paused; }
@keyframes fp-wa-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(11, 128, 67, .55); }
  70%  { box-shadow: 0 0 0 12px rgba(11, 128, 67, 0); }
  100% { box-shadow: 0 0 0 0 rgba(11, 128, 67, 0); }
}
@media (prefers-reduced-motion: reduce) { .wa-btn::after, .social__link::after { animation: none; } }
@media (max-width: 860px) { .site-header .wa-btn { display: 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;
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  }
  .cta-bar a + a { border-left: 2px solid rgba(28, 27, 24, .28); }
  /* Il canale WhatsApp tiene il suo verde anche nella barra: è un marchio, non un accento nostro. */
  .cta-bar a.cta-bar--wa { background: #0b8043; color: #ffffff; }
  body { padding-bottom: 3.6rem; }
}

/* ============================== testata di pagina ============================== */
/* ⚠ La page-head NON riusa la size della testata (`--t-3xl`): è una testata di pagina, non un hero,
   e a quella misura «occupa mezza schermata». Un gradino più piccolo, padding contenuto. */
.page-head { background: var(--brand); color: var(--on-dark); padding-block: clamp(2.6rem, 6vw, 4.2rem); }
.page-head h1 { font-size: var(--t-2xl); color: var(--on-dark); }
.page-head__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);
}
.page-head__lead { margin-top: var(--space-3); color: var(--on-dark-muted); max-width: var(--misura-lead); }

/* La misura di lettura si dichiara sul PARAGRAFO ovunque, non solo dove ci si è ricordati. */
.chisiamo p, .mezzi p, .sede p, .contatti p, .cantieri p { max-width: var(--misura-colonna); }

/* ⚠⚠ MENU MOBILE ALLINEATO A SINISTRA — il difetto sta nei GENITORI, non nell'ancora.
   La nav dichiara `justifyContent:right` per stare a destra sul desktop; nell'overlay il contenitore
   diventa una COLONNA e quel `justify` si traduce in `align-items:flex-end` su `__container` e sulla
   voce. Ogni <li> si stringe allora sul proprio testo (misurato: 37px a x=333), e il `width:100%`
   dell'ancora è il 100% di 37px — cioè niente. Correggere l'ancora non serviva: si rimette a
   `stretch` la catena, e la riga intera torna bersaglio. (Regola 23: risalire i genitori misurando.) */
.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 {
  align-items: stretch;
  text-align: left;
}

/* Un sottotitolo di sezione VUOTO non lascia un capoverso fantasma: dove il materiale del cliente non
   porta un sommario non si inventa, e la banda non deve nemmeno aprire lo spazio di una riga vuota. */
.testa__lead:empty, .hero__lead:empty, .page-head__lead:empty { display: none; }

/* ============================== servizio ESTESO (indice auto-contenuto) ==============================
   Tre tessere con due righe di testo e un «leggi tutto» sono un indice che promette e non mantiene:
   il materiale di questo mestiere porta due o tre capoversi per servizio, cioè abbastanza per stare
   nella pagina. Qui ogni servizio è una riga intera — testo COMPLETO e fotografia — e le righe si
   alternano di lato, così la pagina non diventa una colonna con la metà destra sempre uguale. */
.servizio-esteso {
  /* ⚠ La colonna della fotografia pesa di piu di prima (1,25 contro 1,05) per COMPENSARE il rientro
     laterale: col padding a parita di proporzioni l.immagine scendeva sotto la soglia di impatto —
     misurato, 2,0 → 1,8 immagini grandi per pagina. Respiro e impatto non sono in conflitto: va
     spostata la proporzione, non tolto il padding. */
  display: grid; grid-template-columns: 1fr 1.25fr; gap: var(--space-6);
  align-items: center; padding-block: var(--space-7);
  /* ⚠ Il padding LATERALE non è decorazione: le righe pari hanno un fondo proprio, e senza respiro
     il pannello tinto arriva a filo del testo e della fotografia — si legge come un ritaglio, non
     come una scheda. Il rientro vale su tutte le righe, così pari e dispari restano allineate. */
  padding-inline: clamp(1.25rem, 3vw, 2.75rem);
}
.servizio-esteso + .servizio-esteso { border-top: 1px solid var(--line); }
/* ⚠ L'alternanza si dichiara sull'ORDINE nel DOM, non su una classe per riga: una classe in più su
   ogni riga si dimentica al primo servizio aggiunto, e l'alternanza si romperebbe in silenzio. */
.servizio-esteso:nth-of-type(even) .servizio-esteso__media { order: -1; }
.servizio-esteso__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.servizio-esteso .servizio__ico { width: 52px; height: 52px; background: var(--accent-ink); margin-bottom: var(--space-3); }
.servizio-esteso h2 { font-size: var(--t-xl); }
.servizio-esteso p { margin-top: var(--space-3); color: var(--ink-muted); max-width: var(--misura-colonna); }
@media (max-width: 900px) {
  .servizio-esteso { grid-template-columns: 1fr; gap: var(--space-4); padding-block: var(--space-6); }
  /* Su una colonna la fotografia sta SEMPRE sotto il testo: l'alternanza è un fatto di riga, e in
     colonna manderebbe una foto prima del titolo che la spiega. */
  .servizio-esteso:nth-of-type(even) .servizio-esteso__media { order: 0; }
}


/* ============================== WhatsApp flottante ==============================
   Il docx del cliente lo dichiara alla lettera: «WhatsApp flottante  +39 329 726 4664». Sta sopra ogni
   pagina, in basso a destra, e PULSA — il battito è il motivo per cui un pulsante flottante esiste.
   ⚠ Sopra la barra CTA fissa del mobile: senza l'offset si sovrapporrebbe all'ultima azione. */
.wa-float {
  position: fixed; right: clamp(1rem, 3vw, 2rem); bottom: clamp(1rem, 3vw, 2rem); z-index: 70;
  width: 58px; height: 58px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: #0b8043; color: #ffffff;
  box-shadow: 0 10px 26px rgba(11, 128, 67, .38);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.wa-float .social__ico { width: 30px; height: 30px; }
.wa-float:hover, .wa-float:focus-visible { transform: scale(1.08); box-shadow: 0 14px 34px rgba(11, 128, 67, .5); }
/* Due anelli sfasati: uno solo legge come un errore di resa, due come un battito. */
.wa-float::before, .wa-float::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  border: 2px solid rgba(11, 128, 67, .55);
  animation: fp-wa-ring 2.4s var(--ease) infinite;
}
.wa-float::after { animation-delay: 1.2s; }
@keyframes fp-wa-ring {
  0%   { transform: scale(1); opacity: .85; }
  100% { transform: scale(1.85); opacity: 0; }
}
/* ⚠ Su MOBILE il flottante sparisce: misurato, il suo riquadro (x322-374, y545-597) cadeva SOPRA il
   sommario della testata (x20-370, y498-594) e ne copriva la fine. Ed era anche ridondante — la barra
   CTA fissa porta gia WhatsApp. Il battito si sposta li, cosi il pulsante che pulsa c e su OGNI
   viewport senza coprire una riga di testo. */
@media (max-width: 720px) { .wa-float { display: none; } }
/* ⚠ Con reduced-motion il battito si FERMA ma il pulsante resta (e resta verde e cliccabile): chi
   chiede meno movimento non deve perdere un canale di contatto. */
@media (prefers-reduced-motion: reduce) { .wa-float::before, .wa-float::after { animation: none; opacity: 0; } }

/* ============================== profondità delle superfici ==============================
   ⚠ Il sito «triste e piatto» non è un problema di palette: è che ogni banda era un campo di colore
   UNIFORME. Qui le superfici prendono una pendenza appena percepibile (2-5% di luminosità) — non si
   vede come gradiente, si vede come profondità. I fondi restano i token verificati: la pendenza parte
   e finisce dentro la coppia già misurata, quindi nessun contrasto cambia.
   ⚠ La pendenza sta sull'ELEMENTO, non su uno pseudo: uno pseudo dipinge ma non è la superficie. */
.section--chiara {
  background-image: linear-gradient(168deg, var(--sage-light) 0%, var(--sage-tint) 58%, var(--sage) 100%);
}
.banda-scura {
  background-image: linear-gradient(158deg, var(--brand) 0%, var(--brand-dark) 62%, var(--brand-mid) 100%);
}
.banda-terra {
  background-image: linear-gradient(158deg, var(--brand-mid) 0%, var(--brand) 100%);
}
.page-head {
  background-image: linear-gradient(140deg, var(--brand) 0%, var(--brand-dark) 55%, var(--brand-mid) 100%);
}
.site-footer {
  background-image: linear-gradient(180deg, var(--brand-dark) 0%, #141210 100%);
}
.banda-gialla {
  background-image: radial-gradient(120% 92% at 50% 0%, #ffdb3d 0%, var(--accent) 48%, var(--accent-dark) 100%);
}
/* Le tessere e le schede si staccano dal fondo con una pendenza propria, non con un'ombra grigia. */
.servizio, .hero-scheda, .contact-info {
  background-image: linear-gradient(165deg, var(--paper) 0%, var(--sage-tint) 100%);
}
.mezzo {
  background-image: linear-gradient(160deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,0) 70%);
}
/* La banda dei recapiti in cima chiude la testata con un filo di pendenza. */
.recapiti-bar {
  background-image: linear-gradient(90deg, var(--brand-dark) 0%, var(--brand) 50%, var(--brand-dark) 100%);
}

/* La cascata la fa il MOTORE: `fp-stagger` sul contenitore, e reveal.js mette `.reveal` + `--reveal-i`
   su ogni figlio — indice che il ritardo di `.js .reveal` consuma già. Nessun secondo meccanismo. */

/* Hover più vivi: le fotografie respirano, le tessere si sollevano. */
.cantieri figure, .mezzi__foto figure, .chisiamo__media, .servizio-esteso__media { overflow: hidden; }
.cantieri img, .mezzi__foto img, .chisiamo__media img, .servizio-esteso__media img {
  transition: transform .8s var(--ease), filter .6s var(--ease);
}
.cantieri figure:hover img, .mezzi__foto figure:hover img,
.chisiamo__media:hover img, .servizio-esteso__media:hover img { transform: scale(1.045); }

/* ============================== testata di pagina FOTOGRAFICA ==============================
   Le pagine interne si aprivano su una lastra di colore piatta: è lì che il sito legge «triste».
   Qui la testata porta una fotografia sotto un velo, come la home — ma più bassa, perché è una
   testata di pagina e non un hero (regola 6: la page-head non riusa la misura dell'hero).
   ⚠ Il velo è tarato sui pixel CHIARI dietro il testo, non sulla media: si misura, non si stima. */
.page-head--foto { position: relative; isolation: isolate; overflow: hidden; }
.page-head--foto .page-head__media { position: absolute; inset: 0; z-index: -2; }
.page-head--foto .page-head__media img { width: 100%; height: 100%; object-fit: cover; }
.page-head--foto::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  /* ⚠ Lo stop CENTRALE era il punto debole: sul piazzale (cielo chiaro) il sommario misurava 4,44
     contro 4,5. Portato a .84 lascia margine invece di sfiorare la soglia — un velo al limite si
     rompe al primo cambio di fotografia. */
  background: linear-gradient(160deg, rgba(26,24,21,.90) 0%, rgba(26,24,21,.84) 45%, rgba(26,24,21,.90) 100%);
}
.page-head--foto { padding-block: clamp(3.4rem, 8vw, 6rem); }
/* Il filetto giallo chiude la testata sul contenuto, come nella barra del menu. */
.page-head--foto { border-bottom: 4px solid var(--accent); }

/* La prima tessera della gallery prende TUTTA la riga: una griglia regolare di sei uguali è un
   catalogo, non una galleria — e la fotografia migliore merita la misura che ha. */
.cantieri__griglia > figure:first-child { grid-column: 1 / -1; }
.cantieri__griglia > figure:first-child img { aspect-ratio: 21 / 9; }
@media (max-width: 700px) { .cantieri__griglia > figure:first-child img { aspect-ratio: 3 / 2; } }

/* Superfici: le righe di servizio alternate prendono un fondo proprio, così la pagina non è una
   sequenza di bianchi separati da un filetto. */
.servizio-esteso:nth-of-type(even) {
  background-image: linear-gradient(100deg, var(--sage-tint) 0%, var(--paper) 70%);
  border-radius: 0;
}
.cantieri figcaption { background-image: linear-gradient(90deg, var(--sage-tint) 0%, transparent 60%); padding-inline: var(--space-2); }

/* ============================== pagina dei download ==============================
   La pagina è GENERATA da build-downloads (non da pages.json): porta un markup proprio
   (`.page-head` con `.eyebrow`, `.container--narrow`, `.cat-row`, `.cat`) che il verticale deve
   vestire, altrimenti esce nuda — ed era la riga peggiore del punteggio. */
.page-head .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);
}
.page-head h1 { font-size: var(--t-2xl); color: var(--on-dark); }
.page-head p { color: var(--on-dark-muted); max-width: var(--misura-lead); }
.container--narrow { width: min(62rem, 100% - var(--gutter) * 2); margin-inline: auto; }
.stack > * + * { margin-top: var(--space-3); }

.cat-row { margin-top: var(--space-5); display: grid; grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); gap: var(--space-4); }
.cat {
  display: grid; gap: var(--space-3); padding: var(--space-4);
  background-image: linear-gradient(165deg, var(--paper) 0%, var(--sage-tint) 100%);
  border-top: 5px solid var(--accent);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
.cat:hover, .cat:focus-visible { transform: translateY(-6px); box-shadow: 0 18px 40px rgba(26, 24, 21, .16); }
/* La copertina è il documento stesso: a questa misura dice «è una tabella», che è quanto serve. */
.cat__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: top; border: 1px solid var(--line); }
.cat__name { font-family: var(--font-display); font-weight: 700; font-size: var(--t-lg); text-transform: uppercase; color: var(--ink); }
.cat__dl {
  font-family: var(--font-display); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--accent-ink); display: inline-flex; align-items: center; gap: .4rem;
}
.cat:hover .cat__dl { gap: .8rem; }

/* Il WhatsApp della barra mobile PULSA: il fondo va e viene fra il verde di canale e uno più profondo.
   ⚠ Il battito va verso lo SCURO, mai verso il chiaro: il bianco sul verde di canale misura 5,03, e
   schiarendo scenderebbe sotto AA a metà animazione — lo stesso errore del testo che sfuma. */
@media (max-width: 720px) {
  .cta-bar a.cta-bar--wa { animation: fp-wa-bar 2.4s var(--ease) infinite; }
  @keyframes fp-wa-bar {
    0%, 100% { background-color: #0b8043; }
    50%      { background-color: #08602f; }
  }
  @media (prefers-reduced-motion: reduce) { .cta-bar a.cta-bar--wa { animation: none; } }
}

/* ============================== la fotografia che si APRE (wipe) ==============================
   Le fotografie delle righe di servizio non compaiono: si SCOPRONO, come se venissero renderizzate.
   Il velo scorre dal lato interno verso il bordo, seguendo l'alternanza delle righe — la foto a
   destra si apre verso destra, quella a sinistra verso sinistra. È la tecnica del pannello di
   K Edilizia (`clip-path: inset(...)` animato), non una dissolvenza.

   ⚠ `clip-path` e NON `opacity`: un elemento trasparente può non far scaricare l'immagine che
     contiene, e qui l'immagine è tutto il contenuto.
   ⚠ Gated su `.js` — la classe la mette reveal.js. Senza JavaScript la fotografia è già aperta:
     fail-visible, mai una foto invisibile per un'animazione che non è partita.
   ⚠ Il taglio sta sul CONTENITORE, lo zoom al passaggio del mouse resta sull'<img>: sullo stesso
     elemento si contenderebbero la stessa proprietà. */
/* ⚠⚠ IL TAGLIO NON PUÒ STARE SULL'ELEMENTO OSSERVATO. Ci era finito, e l'animazione impediva a se
   stessa di partire: `clip-path` azzera l'area di intersezione, quindi l'IntersectionObserver non
   vedeva mai entrare l'elemento e `.is-visible` non arrivava — misurato, 26 `.reveal` sulla pagina e
   23 con la classe, i tre mancanti erano esattamente queste fotografie. È la stessa famiglia
   dell'elemento a `opacity:0` che non fa scaricare le immagini che contiene: lo stato iniziale di
   un'animazione non deve nascondere l'elemento a chi deve farla partire.
   L'elemento osservato (`__media`) resta di area piena; il taglio vive sull'involucro interno. */
.servizio-esteso__wipe { display: block; }
.js .servizio-esteso__media.reveal { transform: none; }
.js .servizio-esteso__media.reveal .servizio-esteso__wipe {
  clip-path: inset(0 100% 0 0);
  transition: clip-path .95s var(--ease);
  transition-delay: calc(var(--reveal-i, 0) * 70ms);
}
.js .servizio-esteso__media.reveal.is-visible .servizio-esteso__wipe { clip-path: inset(0 0 0 0); }
/* Righe pari: la fotografia sta a sinistra, quindi il taglio parte dal bordo opposto. */
.js .servizio-esteso:nth-of-type(even) .servizio-esteso__media.reveal .servizio-esteso__wipe { clip-path: inset(0 0 0 100%); }
.js .servizio-esteso:nth-of-type(even) .servizio-esteso__media.reveal.is-visible .servizio-esteso__wipe { clip-path: inset(0 0 0 0); }
@media (prefers-reduced-motion: reduce) {
  .js .servizio-esteso__media.reveal .servizio-esteso__wipe,
  .js .servizio-esteso__media.reveal.is-visible .servizio-esteso__wipe,
  .js .servizio-esteso:nth-of-type(even) .servizio-esteso__media.reveal .servizio-esteso__wipe {
    clip-path: none; transition: none;
  }
}
