/* ============================================================
   FIRME.CSS — le sezioni del sito di VD Hair Specialist Experience:
   hero a binari, frase, servizi, chi sono, tricologia, trattamenti,
   confronti, lavori, fascia, prenotazioni.
   ============================================================ */

/* foto della hero leggermente più luminose; titolo staccato dal fondo */
.hero img { filter: brightness(1.15) contrast(0.9); }
h1 { text-shadow: 0 2px 24px var(--c-bg); }

/* ============================================================
   10. GRUPPO — sfondo condiviso da più sezioni contigue.
   Il velo in ::before mantiene il testo leggibile sopra la foto.
   ============================================================ */

.gruppo {
  position: relative;
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
}
.gruppo::before {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--c-bg) 55%, transparent);
  z-index: 0;
}
.gruppo > * {
  position: relative;
  z-index: 1;
}

@media (max-width: 1080px) {
  .gruppo { background-attachment: scroll; }
}

/* ============================================================
   11. HERO SFORNATA — due binari di foto in diagonale che
   scorrono in loop infinito in direzioni opposte, dietro un
   titolo centrale col velo per la leggibilità.
   avviaSfornata() in firme.js fa partire l'ingresso al caricamento.
   ============================================================ */

.hero--sfornata { overflow: hidden; }

.sfornata__binari {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(10px, 1.6vh, 22px);
  transform: rotate(-7deg) scale(1.42);
  transform-origin: center;
  pointer-events: none;
}
.sfornata__binario {
  --carta-w: clamp(180px, 20vw, 300px);
  --gap: clamp(16px, 1.6vw, 26px);
  /* --n: numero di card uniche del binario (prima dei duplicati),
     valorizzata inline da render.js — usata solo da JS per misurare
     un gruppo, non più da una formula CSS.
     --spostamento: larghezza reale di UN gruppo in pixel, misurata
     via JavaScript dopo il layout (assicuraLoopContinuo in firme.js)
     e scritta qui come proprietà inline: nessun calcolo percentuale. */
  display: flex;
  width: max-content;
  gap: var(--gap);
  will-change: transform;
  pointer-events: auto;
}
/* loop continuo: il binario contiene abbastanza gruppi identici da
   coprire almeno tre larghezze di viewport (assicuraLoopContinuo in
   firme.js li clona finché non basta), e scorre di esattamente UN
   gruppo — lo spostamento è quello misurato realmente, non derivato
   da percentuali, così il punto di giunzione è invisibile.
   Velocità fissa, non legata a --motion. */
.sfornata__binario.sb1 { animation: sfornata-sx 46s linear infinite; }
.sfornata__binario.sb2 { animation: sfornata-dx 58s linear infinite; }
@keyframes sfornata-sx {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-1 * var(--spostamento, 0px)), 0, 0); }
}
@keyframes sfornata-dx {
  from { transform: translate3d(calc(-1 * var(--spostamento, 0px)), 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}

.sfornata__scheda {
  position: relative;
  flex: 0 0 auto;
  width: var(--carta-w);
  height: clamp(210px, 40vh, 460px);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--c-surface);
  box-shadow: 0 30px 60px -30px color-mix(in srgb, var(--c-fg) 45%, transparent);
  opacity: 0;
  transform: translateY(calc(40px * var(--motion, 1))) scale(.96);
  transition: box-shadow .3s ease, filter .3s ease;
}
.sfornata__binario.sb2 .sfornata__scheda { height: clamp(190px, 36vh, 420px); }
/* animazione, non transizione: solo così avviaSfornata() può farla
   ripartire in modo affidabile togliendo e riaggiungendo .is-pronta
   sulla hero (rimuovere la classe azzera subito l'animazione, senza
   la "marcia indietro" che avrebbe una transizione) */
@keyframes sfornata-scheda-in {
  from { opacity: 0; transform: translateY(calc(40px * var(--motion, 1))) scale(.96); }
  to { opacity: 1; transform: none; }
}
.hero.is-pronta .sfornata__scheda {
  animation: sfornata-scheda-in calc(.9s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1) calc(var(--d, 0s) * var(--motion, 1)) both;
}
.sfornata__scheda:hover {
  /* nessun cambio di dimensione o posizione: solo più luce e ombra più profonda */
  filter: brightness(1.08);
  box-shadow: 0 44px 90px -28px color-mix(in srgb, var(--c-fg) 58%, transparent);
}
/* --sfornata-luminosita: manopola per tema, default 1 = invariato.
   Impostata da un tema (es. css/temi/beauty.css) per scurire le foto
   quando servono per contrasto col testo sopra, senza toccare questo
   file per ogni cliente. */
.sfornata__scheda img { width: 100%; height: 100%; object-fit: cover; display: block; filter: brightness(var(--sfornata-luminosita, 1)); }
.sfornata__scheda::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 52%, color-mix(in srgb, var(--c-fg) 45%, transparent) 100%);
}
.sfornata__etichetta {
  position: absolute;
  z-index: 1;
  left: 14px;
  bottom: 12px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-bg);
  display: none;
}

/* --sfornata-velo-forte/--sfornata-velo-debole: le due percentuali del
   velo, default 92%/72% = invariato. Un tema può alzarle per un velo
   più opaco (foto più coperte, testo sopra più leggibile) senza
   toccare questo file.
   --sfornata-velo-partenza/-scala/-transizione: di default il velo è
   sempre a piena opacità e scala 1 (transizione "none" = invariato) —
   un alone statico, presente dal primo frame. Un tema può invece farlo
   partire da opacità e raggio zero (scala ridotta) e crescere insieme
   al testo quando .hero riceve .is-pronta, così l'alone non compare
   prima del titolo che dovrebbe accompagnare. */
.sfornata__velo {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(58% 46% at 50% 50%,
    color-mix(in srgb, var(--c-bg) var(--sfornata-velo-forte, 92%), transparent) 0%,
    color-mix(in srgb, var(--c-bg) var(--sfornata-velo-debole, 72%), transparent) 42%,
    transparent 74%);
  opacity: var(--sfornata-velo-partenza, 1);
  transform: scale(var(--sfornata-velo-scala, 1));
  transition: var(--sfornata-velo-transizione, none);
}
.hero.is-pronta .sfornata__velo { opacity: 1; transform: none; }

.sfornata__centro {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding-inline: 1.5rem;
  pointer-events: none;
}
/* --sfornata-testo-ombra: ombra condivisa da occhiello, titolo e
   sottotitolo, default "none" = invariato. Un tema la imposta quando il
   testo cade su foto chiare e serve contrasto (vedi anche più sotto, le
   due regole .lead che già avevano un'ombra fissa). */
.sfornata__centro .eyebrow {
  opacity: 0;
  text-shadow: var(--sfornata-testo-ombra, none);
  transform: translateY(calc(10px * var(--motion, 1)));
  transition: opacity calc(.8s * var(--motion, 1)) ease calc(.9s * var(--motion, 1)),
              transform calc(.8s * var(--motion, 1)) ease calc(.9s * var(--motion, 1));
}
.hero.is-pronta .sfornata__centro .eyebrow { opacity: 1; transform: none; }

.sfornata__titolo {
  margin: 0;
  text-wrap: balance;
  font-size: clamp(2.6rem, 9vw, 7.5rem);
  text-shadow: var(--sfornata-testo-ombra, none);
}
.sfornata__linea { display: block; overflow: hidden; padding-bottom: .04em; }
.sfornata__linea > span {
  display: inline-block;
  transform: translateY(114%);
  transition: transform calc(1.05s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
.hero.is-pronta .sfornata__linea:nth-child(1) > span { transition-delay: calc(1.1s * var(--motion, 1)); }
.hero.is-pronta .sfornata__linea:nth-child(2) > span { transition-delay: calc(1.25s * var(--motion, 1)); }
.hero.is-pronta .sfornata__linea > span { transform: none; }
.sfornata__titolo em { font-style: normal; color: var(--c-accent); }

.sfornata__centro .lead {
  max-width: 36ch;
  opacity: 0;
  transition: opacity calc(1s * var(--motion, 1)) ease calc(1.5s * var(--motion, 1));
}
.hero.is-pronta .sfornata__centro .lead { opacity: 1; }

.sfornata__azioni {
  justify-content: center;
  pointer-events: auto;
  opacity: 0;
  transition: opacity calc(1s * var(--motion, 1)) ease calc(1.7s * var(--motion, 1));
}
.hero.is-pronta .sfornata__azioni { opacity: 1; }

.sfornata__stato {
  position: absolute;
  left: clamp(1.25rem, 4vw, 3.5rem);
  bottom: clamp(1.25rem, 4vw, 2rem);
  z-index: 3;
  opacity: 0;
  transition: opacity calc(1s * var(--motion, 1)) ease calc(1.9s * var(--motion, 1));
}
.hero.is-pronta .sfornata__stato { opacity: 1; }

@media (max-width: 1080px) {
  .sfornata__binari { transform: rotate(-6deg) scale(1.1); }
  .sfornata__binario {
    --carta-w: clamp(150px, 42vw, 220px);
  }
  .sfornata__binario.sb1 { animation-duration: 70s; }
  .sfornata__binario.sb2 { animation-duration: 85s; }
  .sfornata__scheda,
  .sfornata__binario.sb2 .sfornata__scheda {
    height: clamp(170px, 34vh, 320px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sfornata__binario { animation: none !important; }
  .sfornata__scheda {
    opacity: 1 !important; transform: none !important; animation: none !important;
  }
  .sfornata__centro .eyebrow,
  .sfornata__linea > span,
  .sfornata__centro .lead,
  .sfornata__azioni,
  .sfornata__stato,
  .sfornata__velo {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
}
.hero--sfornata .lead {
  text-shadow: var(--sfornata-testo-ombra, 0 1px 12px var(--c-bg), 0 0 30px var(--c-bg));
}

.sfornata__centro p {
  text-shadow: var(--sfornata-testo-ombra, 0 1px 12px var(--c-bg), 0 0 30px var(--c-bg));
}

/* ---------- Nav solo sulla hero ----------
   .nav--nascosta la mette avviaNavHero() (firme.js) quando la hero è
   uscita da sotto la barra: la nav sale fuori dallo schermo e sfuma,
   torna quando si risale sulla hero. Solo transform e opacity. Le
   transizioni di base.css (sfondo, blur, padding) restano nell'elenco.
   Da tastiera la barra ricompare appena un suo link prende il focus. */
.nav {
  transition: background .4s, backdrop-filter .4s, padding .4s,
              transform calc(.45s * var(--motion, 1)) cubic-bezier(.22, .61, .36, 1),
              opacity calc(.45s * var(--motion, 1)) ease;
}
.nav.nav--nascosta:not(:focus-within) {
  transform: translate3d(0, -110%, 0);
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .nav { transition: none; }
}

/* ============================================================
   13. FRASE — una sola affermazione, composta parola per parola,
   fra due linee che si allungano.

   Nessuna coreografia scritta a mano per l'innesco: testo e linee
   portano data-anim="reveal", l'attributo generico già gestito da
   avviaReveal() in motion.js (non toccato) — un solo
   IntersectionObserver condiviso, threshold 0.15, che al primo
   ingresso in vista aggiunge .is-visibile e chiama unobserve()
   sull'elemento: un solo scatto, poi l'observer smette di guardarlo.
   Nessun listener di scroll, nessun requestAnimationFrame continuo.

   Le parole NON riusano .parola/data-anim="split" di base.css: quel
   meccanismo parte da translateY(105%) dentro un contenitore
   overflow:hidden, pensato per uno slide pieno — con la piccola
   traslazione+opacità chiesta qui rischierebbe di tagliare le lettere
   dove il line-height lascia poco margine (schermi piccoli, testo
   grande). sezioni.frase (js/render.js) le spezza invece una volta
   sola, alla costruzione della sezione, in <span class="frase__parola">
   con --i:indice scritto inline: qui sotto solo il trattamento
   visivo, sull'indice già pronto.

   data-anim="reveal" sul testo serve solo da aggancio all'observer:
   il suo effetto visivo di default (base.css) è annullato qui sotto,
   l'ingresso vero è nelle singole parole. Stesso ragionamento per le
   linee, che animano una larghezza — proprietà che [data-anim="reveal"]
   generico non tocca. Selettori scoped a .frase__testo/.frase__linea:
   non cambiano altri usi di reveal/split nel sito, base.css intatto.
   ============================================================ */
/* --frase-sfondo: default neutro var(--c-bg) (tinta piatta, come prima).
   Un tema può sostituirlo con più livelli (sfumatura, immagine, colore
   di base) senza toccare questo file — vedi css/temi/beauty.css. */
.frase {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  text-align: center;
  padding-block: clamp(6rem, 16vw, 11rem);
  padding-inline: 1.5rem;
  background: var(--frase-sfondo, var(--c-bg));
}
.frase--alt { background: var(--c-surface); }

/* Linea decorativa: larghezza 0 → larghezza piena. Azzera qui
   opacità/transform che [data-anim="reveal"] genererebbe di suo
   (base.css): l'elemento è sempre visibile, solo la larghezza cresce. */
.frase__linea[data-anim="reveal"] {
  width: 0;
  height: 1px;
  background: var(--c-accent-2, currentColor);
  opacity: 1;
  transform: none;
  transition: width calc(1.1s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
.frase__linea.is-visibile { width: clamp(48px, 10vw, 90px); }

/* Il paragrafo è solo l'aggancio all'observer (data-anim="reveal"):
   resta sempre a piena opacità, l'ingresso è tutto sulle parole. */
.frase__testo[data-anim="reveal"] {
  opacity: 1;
  transform: none;
  max-width: 20ch;
  margin: 0;
  font-family: var(--font-frase, var(--font-display));
  font-weight: 400;
  letter-spacing: normal;
  font-size: clamp(34px, 8vw, 72px);
  line-height: 1.25;
}

/* Parole: opacità 0 + leggera traslazione verso il basso, ritardo
   crescente di 90ms a parola sull'indice --i (scritto da
   sezioni.frase in js/render.js, non da JS a runtime). */
.frase__parola {
  display: inline-block;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity calc(.6s * var(--motion, 1)) ease,
              transform calc(.6s * var(--motion, 1)) cubic-bezier(.2, .85, .25, 1);
  transition-delay: calc(var(--i) * 90ms * var(--motion, 1));
}
.frase__testo.is-visibile .frase__parola { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .frase__linea { width: clamp(48px, 10vw, 90px); transition: none; }
  .frase__parola { opacity: 1 !important; transform: none !important; }
}

.frase__testo[data-anim="reveal"] { max-width: 30ch; }

.frase__testo[data-anim="reveal"] {
  max-width: 30ch;
  color: var(--c-accent-2);
}

/* ============================================================
   14. SERVIZI — OVERLAP FOTOGRAFICO
   Basata sul prototipo di design: struttura, alternanza e ingresso
   sono gli stessi. Adattamenti rispetto al prototipo:
   - i colori vengono dai token del tema (var(--c-bg), var(--c-fg),
     var(--c-accent), var(--font-display)…), non da valori fissi;
   - lo sfondo della sezione è var(--frase-sfondo) — lo stesso della
     fascia .frase (§13) — per continuità visiva fra le due sezioni;
   - il markup (sezioni.servizi, js/render.js) genera i blocchi da
     d.voci e alterna --sx/--dx sull'indice: qui sotto solo l'aspetto.

   INGRESSO: un solo IntersectionObserver one-shot (avviaServiziOverlap,
   js/firme.js) aggiunge .is-dentro al blocco quando entra in vista e
   smette subito di osservarlo — nessun listener di scroll, nessun
   requestAnimationFrame continuo, da qui in poi è tutto transizioni
   CSS. I blocchi entrano alternati (sx/dx, sul segno del transform di
   partenza), il numero e la scheda arrivano con un piccolo ritardo
   sulla fascia, così la sovrapposizione si compone davanti agli occhi
   invece di entrare come un blocco unico.
   ============================================================ */

.ovl-servizi {
  max-width: 1180px;
  margin-inline: auto;
  padding: clamp(56px, 8vw, 92px) clamp(16px, 3vw, 34px) clamp(30px, 5vw, 60px);
  /* i blocchi entrano da fuori: niente barra orizzontale. overflow-x da
     solo avrebbe un effetto collaterale non voluto: per spec, se un asse
     è "visible" e l'altro no, quello "visible" viene calcolato "auto" —
     quindi overflow-y sarebbe diventato "auto" invece di restare
     "visible". Qui è innocuo (la sezione non ha un'altezza vincolata,
     quindi non scrolla comunque), ma non era l'intento: overflow: clip
     su entrambi gli assi lo evita alla radice. */
  overflow: clip;
  background: var(--frase-sfondo, var(--c-bg));
}

/* --- Blocco --- */
.ovl { position: relative; margin-bottom: clamp(18px, 2.4vw, 26px); }

.ovl__banda {
  position: relative;
  height: clamp(240px, 30vw, 330px);
  overflow: hidden;
  background: var(--c-surface);
}
.ovl__foto {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05);
  transition: filter .8s ease;
}
.ovl:hover .ovl__foto { filter: grayscale(0) contrast(1); }
/* "La cute": la banda è molto più larga che alta, quindi il taglio
   centrato di object-fit mangerebbe la parte alta della foto — cioè
   proprio la microcamera appoggiata alla cute. Alzando il punto di
   fuoco al 30% restano in quadro la sonda con la punta illuminata, la
   riga dei capelli e lo schermo con la cute ingrandita, a ogni
   larghezza (desktop e mobile usano la stessa inquadratura). */
.ovl__foto[src$="analisi-cute-nuova.png"] { object-position: 50% 30%; }

/* numero gigante: scavalca la fotografia */
.ovl__num {
  position: absolute;
  z-index: 3;
  font-family: var(--font-display);
  font-size: clamp(96px, 13vw, 168px);
  line-height: .8;
  color: var(--c-accent);
  pointer-events: none;
}

/* pannello di testo: entra dentro la fotografia */
.ovl__card {
  position: absolute;
  z-index: 4;
  top: 50%;
  transform: translateY(-50%);
  width: clamp(240px, 32%, 330px);
  padding: clamp(22px, 2.6vw, 32px);
  background: var(--c-surface);
}

/* pannello chiaro dietro il numero, solo nei blocchi pari (--dx) */
.ovl__crema {
  position: absolute;
  z-index: 1;
  top: 0;
  bottom: 0;
  width: 26%;
  background: var(--c-fg);
}

.ovl__etichetta {
  font-family: var(--font-ui);
  font-size: 9px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin-bottom: 14px;
}
.ovl__titolo {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-size: clamp(20px, 2.4vw, 27px);
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--c-fg);
}
.ovl__corpo {
  margin: 0;
  font-family: var(--font-display);
  font-size: 14px;
  line-height: 1.75;
  color: color-mix(in srgb, var(--c-fg) 68%, transparent);
}

.ovl__scopri {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
  font-family: var(--font-ui);
  font-size: 9px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--c-accent);
  text-decoration: none;
}
.ovl__scopri::after {
  content: "";
  width: 44px;
  height: 1px;
  background: var(--c-accent);
  transition: width .45s cubic-bezier(.2, .8, .3, 1);
}
.ovl__scopri:hover::after { width: 66px; }

/* --- Disposizione alternata --- */
.ovl--sx .ovl__num { left: 4%; top: -6%; }
.ovl--sx .ovl__card { right: 0; }

.ovl--dx .ovl__num { right: 12%; top: 14%; }
.ovl--dx .ovl__card { left: 2%; }
.ovl--dx .ovl__crema { right: 0; }
.ovl--dx .ovl__banda { margin-left: auto; width: 92%; }

/* --- Ingresso: alternato sull'indice (sx/dx), un solo scatto ---
   Una sola transizione CSS su opacity e transform, innescata dalla
   classe .is-dentro (avviaServiziOverlap(), js/firme.js). Il transform
   di partenza differisce solo nel segno: è quello a decidere il lato
   da cui entra il blocco.
   will-change solo su :not(.is-dentro): una volta acceso .is-dentro
   (uno scatto solo, mai tolto) l'elemento smette di corrispondere a
   quel selettore e will-change decade da sé — non resta promosso a
   layer proprio a animazione conclusa, per ogni blocco della sezione. */
.ovl {
  opacity: 0;
  transition: opacity calc(1.15s * var(--motion, 1)) cubic-bezier(.16, .72, .24, 1),
              transform calc(1.15s * var(--motion, 1)) cubic-bezier(.16, .72, .24, 1);
}
.ovl:not(.is-dentro) { will-change: transform, opacity; }
.ovl--sx { transform: translateX(-9%); }
.ovl--dx { transform: translateX(9%); }
.ovl.is-dentro { opacity: 1; transform: translateX(0); }

/* gli elementi sovrapposti arrivano poco dopo la fascia, così la
   sovrapposizione si compone davanti agli occhi invece di entrare
   come un blocco unico */
.ovl__num, .ovl__card {
  opacity: 0;
  transition: opacity calc(.9s * var(--motion, 1)) ease calc(.28s * var(--motion, 1)),
              transform calc(.9s * var(--motion, 1)) cubic-bezier(.2, .8, .3, 1) calc(.28s * var(--motion, 1));
}
.ovl__num { transform: translateY(18px); }
.ovl__card { transform: translateY(calc(-50% + 18px)); }
.ovl.is-dentro .ovl__num { opacity: 1; transform: translateY(0); }
.ovl.is-dentro .ovl__card { opacity: 1; transform: translateY(-50%); }

/* --- Telefono --- */
@media (max-width: 1080px) {
  .ovl__banda { height: 230px; width: 100% !important; margin-left: 0 !important; }
  .ovl__crema { display: none; }
  .ovl__num { font-size: 84px; left: 5% !important; right: auto !important; top: -4% !important; }

  /* il pannello non può restare sovrapposto a 390px: scende sotto la
     fascia risalendo di 46px, così l'idea di sovrapposizione resta
     senza coprire metà fotografia */
  .ovl__card {
    position: relative;
    z-index: 5;
    top: auto;
    width: 100%;
    margin-top: -46px;
    transform: translateY(18px);
  }
  .ovl.is-dentro .ovl__card { transform: translateY(0); }
  .ovl { margin-bottom: 44px; }
  .ovl--sx, .ovl--dx { transform: translateX(0); opacity: 0; }
  .ovl--sx.is-dentro, .ovl--dx.is-dentro { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .ovl, .ovl__num, .ovl__card {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .ovl__card { transform: translateY(-50%) !important; }
}

/* ============================================================
   15. CHI SONO — tipografica, senza fotografia.
   Basata sul prototipo di design: senza un
   ritratto utilizzabile, la citazione grande fa il lavoro che farebbe
   la foto (dare un centro visivo), il logo nel bollo bianco sta dove
   l'occhio si aspetta il volto. Adattamenti rispetto al prototipo:
   - tutti i contenuti vengono da sezioni.chi (js/render.js), ogni
     blocco è opzionale nel markup;
   - i colori vengono dai token del tema (var(--c-bg), var(--c-fg),
     var(--c-accent), var(--font-display)…), non da valori fissi — le
     due eccezioni sono i fondi bianchi dietro ai loghi (sotto);
   - lo sfondo della sezione è var(--frase-sfondo), lo stesso di
     .frase (§13) e di .ovl-servizi (§14).

   FONDO BIANCO DIETRO AI LOGHI: #fff fisso, non un token del tema:
   i loghi hanno parti nere che su un fondo derivato dal tema (chiaro
   o scuro a seconda del cliente) potrebbero sparire o perdere
   contrasto. Deve restare bianco vero a prescindere dal tema.

   INGRESSO: un solo IntersectionObserver one-shot con ritardo
   progressivo per elemento (avviaChiSono(), js/firme.js) — accende
   .is-visibile su .chi__rv e smette subito di osservare l'elemento.
   Nessun listener di scroll, nessun requestAnimationFrame continuo.
   ============================================================ */

.chi {
  background: var(--frase-sfondo, var(--c-bg));
  padding: clamp(52px, 8vw, 96px) clamp(20px, 5vw, 58px) 0;
}

/* --- occhiello fra due linee --- */
.chi__occhiello {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-bottom: clamp(34px, 5vw, 54px);
}
.chi__occhiello span {
  font-family: var(--font-ui);
  font-size: 9px;
  letter-spacing: .4em;
  text-transform: uppercase;
  color: var(--c-accent);
}
.chi__occhiello i { width: 44px; height: 1px; background: var(--c-accent); }

/* --- citazione: fa il lavoro del ritratto --- */
.chi__citazione {
  margin: 0 auto clamp(32px, 5vw, 48px);
  max-width: 24ch;
  text-align: center;
}
.chi__citazione p {
  margin: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(30px, 6.6vw, 58px);
  line-height: 1.28;
  color: var(--c-accent);
}

/* --- firma con logo --- */
.chi__firma {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: clamp(48px, 7vw, 80px);
}
.chi__bollo {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: #fff;   /* fisso: vedi commento sul fondo dei loghi, sopra */
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  overflow: hidden;
}
.chi__bollo img { width: 78%; height: auto; display: block; }
.chi__nome {
  font-family: var(--font-display);
  font-size: clamp(15px, 2vw, 19px);
  letter-spacing: .14em;
  color: var(--c-fg);
}
.chi__ruolo {
  margin-top: 7px;
  font-family: var(--font-ui);
  font-size: 9px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--c-fg) 50%, transparent);
}

/* --- corpo su due colonne --- */
.chi__corpo {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(22px, 4vw, 48px);
  max-width: 1000px;
  margin: 0 auto clamp(52px, 8vw, 86px);
}
.chi__bio { grid-column: 1 / 8; }
.chi__bio p {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1.85;
  color: color-mix(in srgb, var(--c-fg) 68%, transparent);
}
.chi__bio p:last-child { margin-bottom: 0; }

.chi__nota {
  grid-column: 9 / 13;
  border-left: 1px solid color-mix(in srgb, var(--c-accent) 28%, transparent);
  padding-left: clamp(16px, 2.4vw, 26px);
}
.chi__nota-eti {
  font-family: var(--font-ui);
  font-size: 9px;
  letter-spacing: .32em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin-bottom: 14px;
}
.chi__nota-tit {
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.3;
  color: var(--c-fg);
  margin-bottom: 12px;
}
.chi__nota p {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 11.5px;
  line-height: 1.75;
  color: color-mix(in srgb, var(--c-fg) 50%, transparent);
}

/* --- fascia loghi --- */
.chi__marchi {
  border-top: 1px solid color-mix(in srgb, var(--c-accent) 20%, transparent);
  padding: clamp(34px, 5vw, 52px) 0 clamp(46px, 7vw, 68px);
}
.chi__marchi-riga {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(26px, 6vw, 72px);
  flex-wrap: wrap;
}
/* Etichetta e logo sullo stesso asse: la colonna centra entrambi, anche
   quando l'etichetta è più larga del riquadro del logo (prima il
   riquadro restava allineato a sinistra sotto un testo centrato). */
.chi__marchio {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.chi__marchio-eti {
  font-family: var(--font-ui);
  font-size: 8px;
  letter-spacing: .34em;
  /* il letter-spacing aggiunge spazio anche dopo l'ultima lettera: si
     recupera a destra, altrimenti il testo pende a sinistra dell'asse */
  margin-right: -.34em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--c-fg) 50%, transparent);
  margin-bottom: 16px;
}
.chi__marchio-box {
  width: 104px;
  height: 66px;
  background: #fff;   /* fisso: vedi commento sul fondo dei loghi, sopra */
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 8px;
  transition: transform calc(.5s * var(--motion, 1)) cubic-bezier(.2, .8, .3, 1);
}
.chi__marchio-box:hover { transform: translateY(-3px); }
.chi__marchio-box img { max-width: 100%; max-height: 100%; display: block; }
.chi__divisore {
  width: 1px;
  height: 56px;
  background: color-mix(in srgb, var(--c-accent) 28%, transparent);
}
.chi__marchi p {
  margin: 22px auto 0;
  max-width: 40ch;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 11px;
  line-height: 1.8;
  color: color-mix(in srgb, var(--c-fg) 50%, transparent);
}

/* --- comparsa: un solo scatto per elemento, ritardo scritto da
   avviaChiSono() (js/firme.js) come transition-delay inline --- */
.chi__rv {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity calc(1s * var(--motion, 1)) cubic-bezier(.2, .7, .3, 1),
              transform calc(1s * var(--motion, 1)) cubic-bezier(.2, .7, .3, 1);
}
.chi__rv.is-visibile { opacity: 1; transform: none; }

@media (max-width: 1080px) {
  .chi__bio, .chi__nota { grid-column: 1 / 13; }
  .chi__nota {
    border-left: 0;
    border-top: 1px solid color-mix(in srgb, var(--c-accent) 28%, transparent);
    padding-left: 0;
    padding-top: 24px;
    margin-top: 8px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chi__rv { opacity: 1; transform: none; transition: none; }
}
/* ============================================================
   16. TRICOLOGIA — analisi della cute.
   Dal prototipo di design. Differenze rispetto al prototipo, tutte
   volute:
   - i colori vengono dai token del tema (var(--c-bg), var(--c-fg),
     var(--c-accent), var(--font-display)…) e non dai valori fissi
     #07080a / #c9a24b del prototipo, così la sezione segue il tema
     come tutte le altre;
   - il prototipo conteneva due copie del contenuto, una per la
     cornice "desktop" e una per quella "mobile": qui è un markup
     solo, con il passaggio da sei a due colonne al breakpoint 900px;
   - l'ingresso usa .tri__rv + .is-visibile (avviaTricologia() in
     js/firme.js), la stessa meccanica di .chi__rv, invece delle
     @keyframes applicate da script del prototipo: lo stato nascosto
     è in una classe aggiunta da JS, quindi senza JS il testo resta
     visibile.
   ============================================================ */
.tri {
  position: relative;
  background: var(--c-bg);
  color: var(--c-fg);
  overflow: hidden;
}

/* grana: lo stesso velo del prototipo, reso senza <svg> e senza
   filtro (un feTurbulence a tutto schermo costa caro su mobile) */
.tri__grana {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: radial-gradient(color-mix(in srgb, var(--c-fg) 60%, transparent) .5px, transparent .5px);
  background-size: 3px 3px;
}

/* --- apertura: testo a sinistra, foto a pieno taglio sotto i veli --- */
.tri__apertura {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
  align-items: stretch;
  min-height: 600px;
}
.tri__foto {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: 38% 28%;
  filter: saturate(.72) brightness(.8) contrast(1.04);
}
/* velo laterale: copre il testo a sinistra, si apre sulla foto a destra */
.tri__velo {
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--c-bg) 97%, transparent) 0%,
    color-mix(in srgb, var(--c-bg) 95%, transparent) 36%,
    color-mix(in srgb, var(--c-bg) 74%, transparent) 52%,
    color-mix(in srgb, var(--c-bg) 32%, transparent) 72%,
    color-mix(in srgb, var(--c-bg) 16%, transparent) 100%);
}
/* velo verticale: sfuma la foto nel fondo sopra e sotto, così la
   sezione non ha bordi netti contro quelle vicine */
.tri__velo--basso {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-bg) 50%, transparent) 0%,
    transparent 22%,
    transparent 62%,
    color-mix(in srgb, var(--c-bg) 90%, transparent) 94%,
    var(--c-bg) 100%);
}
.tri__testo {
  position: relative;
  z-index: 1;
  padding: clamp(44px, 6vw, 62px) clamp(22px, 4.4vw, 56px) clamp(52px, 7vw, 74px) clamp(22px, 5vw, 64px);
}
.tri__occhiello {
  margin: 0 0 clamp(26px, 4vw, 42px);
  font-family: var(--font-ui);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .46em;
  text-transform: uppercase;
  color: var(--c-accent);
}
.tri__titolo {
  margin: 0;
  max-width: 20ch;
  font-family: var(--font-display);
  font-weight: var(--display-weight, 400);
  font-size: clamp(2.1rem, 3.5vw, 3.1rem);
  line-height: 1.16;
  letter-spacing: var(--display-tracking, -0.004em);
  text-wrap: balance;
}
.tri__corpo {
  margin: clamp(28px, 4vw, 44px) 0 0;
  max-width: 44ch;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.85;
  color: color-mix(in srgb, var(--c-fg) 86%, transparent);
  text-wrap: pretty;
}
.tri__citazione {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  margin-top: clamp(34px, 5vw, 52px);
}
.tri__trattino {
  flex: none;
  width: 42px;
  height: 1px;
  margin-top: 10px;
  background: var(--c-accent);
}
.tri__citazione p {
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.25rem, 1.9vw, 1.7rem);
  line-height: 1.34;
  color: color-mix(in srgb, var(--c-accent) 85%, var(--c-fg));
  text-wrap: pretty;
}

/* --- elenco delle problematiche --- */
.tri__elenco {
  position: relative;
  z-index: 1;
  padding: 0 clamp(22px, 5vw, 64px);
}
.tri__linea {
  height: 1px;
  background: color-mix(in srgb, var(--c-accent) 42%, transparent);
  transform-origin: left center;
}
.tri__griglia {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}
.tri__voce {
  position: relative;
  padding: 40px 22px 44px;
  border-left: 1px solid color-mix(in srgb, var(--c-accent) 28%, transparent);
  transition: background-color calc(.46s * var(--motion, 1)) ease;
}
.tri__voce:first-child { padding-left: 0; border-left: 0; }
.tri__voce:last-child { padding-right: 0; }
.tri__rombo {
  display: block;
  width: 9px;
  height: 9px;
  border: 1px solid var(--c-accent);
  transform: rotate(45deg);
}
.tri__num {
  display: block;
  margin-top: 26px;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: .04em;
  color: color-mix(in srgb, var(--c-accent) 62%, transparent);
  transition: color calc(.46s * var(--motion, 1)) ease;
}
.tri__nome {
  display: block;
  margin-top: 14px;
  max-width: 16ch;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.55;
  color: color-mix(in srgb, var(--c-fg) 90%, transparent);
  text-wrap: pretty;
  transition: color calc(.46s * var(--motion, 1)) ease;
}
/* filo che corre sul bordo alto della voce sotto il puntatore */
.tri__filo {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1px;
  background: color-mix(in srgb, var(--c-accent) 80%, var(--c-fg));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform calc(.52s * var(--motion, 1)) cubic-bezier(.19, .72, .2, 1);
}
@media (hover: hover) {
  .tri__voce:hover { background-color: color-mix(in srgb, var(--c-accent) 5%, transparent); }
  .tri__voce:hover .tri__num { color: color-mix(in srgb, var(--c-accent) 85%, var(--c-fg)); }
  .tri__voce:hover .tri__nome { color: var(--c-fg); }
  .tri__voce:hover .tri__filo { transform: scaleX(1); }
}

/* --- riquadro sull'approccio --- */
.tri__approccio {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 40px;
  align-items: start;
  margin: clamp(44px, 6vw, 64px) clamp(22px, 5vw, 64px) 0;
  padding: clamp(28px, 4vw, 40px) clamp(24px, 4vw, 44px) clamp(30px, 4.4vw, 44px);
  border: 1px solid color-mix(in srgb, var(--c-accent) 30%, transparent);
}
.tri__sigillo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
}
.tri__sigillo i {
  width: 14px;
  height: 14px;
  border: 1px solid var(--c-accent);
  border-radius: 50%;
}
.tri__approccio p {
  margin: 0;
  max-width: 96ch;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.9;
  color: color-mix(in srgb, var(--c-fg) 88%, transparent);
  text-wrap: pretty;
}

/* --- nota finale --- */
.tri__nota {
  position: relative;
  z-index: 1;
  margin: clamp(26px, 4vw, 34px) clamp(22px, 5vw, 64px) clamp(60px, 8vw, 84px);
  max-width: 86ch;
  font-family: var(--font-ui);
  font-size: 11.5px;
  line-height: 1.8;
  color: color-mix(in srgb, var(--c-fg) 55%, transparent);
}

/* --- ingresso --- */
.tri__rv {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity calc(.9s * var(--motion, 1)) cubic-bezier(.18, .72, .2, 1),
              transform calc(.9s * var(--motion, 1)) cubic-bezier(.18, .72, .2, 1);
}
.tri__rv.is-visibile { opacity: 1; transform: none; }
/* le due linee dell'elenco entrano allargandosi, non salendo */
.tri__linea.tri__rv { transform: scaleX(0); }
.tri__linea.tri__rv.is-visibile { transform: scaleX(1); }

@media (max-width: 1080px) {
  .tri__apertura {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }
  .tri__foto { background-position: 40% 26%; }
  /* a colonna sola il velo laterale non serve: la foto sta dietro al
     testo per tutta la larghezza, quindi scurisce dall'alto in basso */
  .tri__velo {
    background: linear-gradient(to bottom,
      color-mix(in srgb, var(--c-bg) 30%, transparent) 0%,
      color-mix(in srgb, var(--c-bg) 45%, transparent) 26%,
      color-mix(in srgb, var(--c-bg) 92%, transparent) 62%,
      var(--c-bg) 100%);
  }
  .tri__velo--basso { display: none; }
  .tri__testo { padding-top: 190px; }
  .tri__titolo { font-size: 1.75rem; max-width: none; }
  .tri__citazione p { font-size: 1.3rem; max-width: none; }
  .tri__trattino { width: 30px; margin-top: 9px; }

  .tri__griglia { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tri__voce {
    padding: 26px 16px 30px;
    border-bottom: 1px solid color-mix(in srgb, var(--c-accent) 22%, transparent);
  }
  .tri__voce:nth-child(odd) { padding-left: 0; border-left: 0; }
  .tri__voce:nth-child(even) { padding-right: 0; }
  .tri__voce:nth-last-child(-n+2) { border-bottom: 0; }
  .tri__num { margin-top: 20px; font-size: 1.35rem; }
  .tri__nome { margin-top: 10px; max-width: none; }
  .tri__filo { display: none; }

  .tri__approccio { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .tri__sigillo { width: 44px; height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .tri__rv,
  .tri__linea.tri__rv { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   17. TRATTAMENTI — testi fermi, immagini che scorrono.
   Dal prototipo di design (sezione nanoplastia). La colonna dei testi è sticky e resta ferma; la colonna
   delle immagini è nel flusso della pagina e ogni immagine è sticky,
   quindi la successiva sale a coprirla alla stessa velocità dello
   scroll. Nessuna animazione a tempo e nessun transform scritto dal
   JS: il movimento è lo scroll stesso, e chi scorre lo controlla del
   tutto. avviaTrattamenti() (js/firme.js) sceglie solo il testo attivo.

   Altezza della sezione: uno schermo più una salita d'immagine per
   ogni voce dopo la prima. --trt-n (numero di voci) lo scrive il
   renderer, --trt-h è l'altezza di un'immagine (uno schermo sul
   desktop, il 42% su telefono).
   Niente overflow:hidden sugli antenati delle parti sticky: renderebbe
   loro il contenitore di scorrimento e lo sticky smetterebbe di
   funzionare.
   ============================================================ */
.trt {
  --trt-schermo: 100vh;
  --trt-h: var(--trt-schermo);
  position: relative;
  background: var(--c-bg);
  color: var(--c-fg);
}
/* svh: su telefono non cambia quando compare la barra del browser,
   quindi le parti incollate non saltano durante lo scroll */
@supports (height: 100svh) {
  .trt { --trt-schermo: 100svh; }
}
.trt__palco {
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* start: le colonne non si allungano sulla riga, altrimenti la
     colonna sticky sarebbe alta quanto la sezione e non avrebbe corsa */
  align-items: start;
  min-height: calc(var(--trt-schermo) + (var(--trt-n, 2) - 1) * var(--trt-h));
}

/* --- colonna dei testi --- */
.trt__lato {
  position: sticky;
  top: 0;
  z-index: 1;
  height: var(--trt-schermo);
  overflow: hidden;
  display: flex;
  align-items: center;
  padding: 0 clamp(28px, 4.4vw, 72px);
  background: color-mix(in srgb, var(--c-fg) 3%, var(--c-bg));
}
.trt__testi {
  position: relative;
  width: 100%;
  max-width: 42ch;
}
/* i testi stanno uno sopra l'altro: il primo tiene l'altezza (è in
   flusso), gli altri sono assoluti sopra di lui */
.trt__testo {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
  pointer-events: none;
  transition: opacity calc(.62s * var(--motion, 1)) ease,
              transform calc(.62s * var(--motion, 1)) cubic-bezier(.18, .72, .2, 1);
}
.trt__testo:not(:first-child) {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
}
.trt__testo.is-attivo {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  pointer-events: auto;
}
.trt__titolo {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight, 400);
  font-size: clamp(2rem, 3.4vw, 3rem);
  line-height: 1.14;
  letter-spacing: var(--display-tracking, -0.004em);
}
.trt__trattino {
  display: block;
  width: 64px;
  height: 1px;
  margin-top: 30px;
  background: var(--c-accent);
}
.trt__testo p {
  margin: 30px 0 0;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.9;
  color: color-mix(in srgb, var(--c-fg) 86%, transparent);
  text-wrap: pretty;
}
.trt__testo p + p { margin-top: 20px; }

.trt__progresso {
  position: absolute;
  left: 0;
  top: 100%;
  margin-top: clamp(34px, 5vw, 64px);
  width: 132px;
  height: 1px;
  background: color-mix(in srgb, var(--c-accent) 26%, transparent);
}
.trt__progresso-barra {
  display: block;
  height: 1px;
  background: var(--c-accent);
  transition: width calc(.5s * var(--motion, 1)) cubic-bezier(.18, .72, .2, 1);
}

/* --- colonna delle immagini ---
   Le immagini sono in fila nel flusso, ognuna sticky in cima: quella
   dopo arriva da sotto e, venendo dopo nel DOM, le passa sopra. */
.trt__pannelli {
  position: relative;
  background: var(--c-bg);
}
.trt__pannello {
  position: sticky;
  top: 0;
  height: var(--trt-h);
  overflow: hidden;
  background: color-mix(in srgb, var(--c-fg) 5%, var(--c-bg));
}
.trt__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* segnaposto finché manca la foto: stessa riga del prototipo */
.trt__manca {
  position: absolute;
  left: 26px;
  bottom: 22px;
  font-family: var(--font-ui);
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--c-accent) 75%, transparent);
}

/* --- decori oro ---
   Stessa famiglia del mirino del prima/dopo (§18) e dei filetti del
   sito: 1px, oro velato, niente riempimenti. */

/* Angoli sulla foto: uno in alto a sinistra, uno in basso a destra.
   Stanno DENTRO il pannello, quindi seguono la foto pixel per pixel
   mentre sale. Lo span è il vertice: ::before è il tratto orizzontale,
   ::after quello verticale, <i> un rombo sul vertice.
   Quando la foto arriva (.is-arrivato, da avviaTrattamenti) i tratti si
   disegnano partendo dal vertice; tornando indietro si ritirano. Si
   animano solo transform e opacity. */
.trt__angolo {
  --trt-ang-l: clamp(56px, 7vw, 112px);
  --trt-ang-c: color-mix(in srgb, var(--c-accent) 70%, transparent);
  position: absolute;
  z-index: 2;
  width: 0;
  height: 0;
  pointer-events: none;
}
.trt__angolo--as { top: clamp(14px, 2.2vw, 30px); left: clamp(14px, 2.2vw, 30px); }
.trt__angolo--bd { bottom: clamp(14px, 2.2vw, 30px); right: clamp(14px, 2.2vw, 30px); }
.trt__angolo::before,
.trt__angolo::after {
  content: "";
  position: absolute;
  background: var(--trt-ang-c);
  transition: transform calc(1s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
/* orizzontale */
.trt__angolo::before { width: var(--trt-ang-l); height: 1px; }
/* verticale: parte poco dopo, così l'angolo si "piega" invece di
   comparire tutto insieme */
.trt__angolo::after {
  width: 1px;
  height: var(--trt-ang-l);
  transition-delay: calc(.14s * var(--motion, 1));
}
/* alto-sinistra: i tratti vanno verso destra e verso il basso */
.trt__angolo--as::before { left: 0; top: 0; transform-origin: left center; }
.trt__angolo--as::after  { left: 0; top: 0; transform-origin: center top; }
/* basso-destra: speculare, verso sinistra e verso l'alto */
.trt__angolo--bd::before { right: 0; bottom: 0; transform-origin: right center; }
.trt__angolo--bd::after  { right: 0; bottom: 0; transform-origin: center bottom; }

.trt__angolo i {
  position: absolute;
  width: 5px;
  height: 5px;
  margin: -2.5px 0 0 -2.5px;
  background: var(--c-accent);
  transform: rotate(45deg);
  transition: opacity calc(.6s * var(--motion, 1)) ease,
              transform calc(.6s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
.trt__angolo--as i { left: 0; top: 0; }
.trt__angolo--bd i { left: 0; top: 0; }

/* a riposo (foto non ancora arrivata) i tratti sono ritirati nel
   vertice. Solo con JS pronto: senza, gli angoli restano disegnati. */
.trt.is-pronta .trt__pannello:not(.is-arrivato) .trt__angolo::before { transform: scaleX(0); }
.trt.is-pronta .trt__pannello:not(.is-arrivato) .trt__angolo::after  { transform: scaleY(0); }
.trt.is-pronta .trt__pannello:not(.is-arrivato) .trt__angolo i {
  opacity: 0;
  transform: rotate(45deg) scale(.2);
}

/* Numerazione sopra il testo: "01 / 02" in maiuscoletto, il numero in
   oro e il totale velato, come le note dei dati del tema. */
.trt__indice {
  display: flex;
  align-items: baseline;
  gap: .5em;
  margin: 0 0 clamp(1rem, 2.6vh, 1.6rem);
  font-family: var(--font-ui);
  font-size: .72rem;
  letter-spacing: .22em;
  color: var(--c-accent);
}
.trt__indice i {
  font-style: normal;
  color: color-mix(in srgb, var(--c-fg) 38%, transparent);
}

/* Cucitura fra testo e foto: un filetto verticale che sfuma alle due
   estremità, vicino al bordo destro della colonna dei testi. È rientrato
   quanto gli angoli sulla foto: a filo del bordo cadrebbe sul mezzo
   pixel di confine e si perderebbe contro l'immagine. Sta nella parte
   ferma, quindi resta immobile mentre le foto le scorrono accanto. */
.trt__cucitura {
  position: absolute;
  top: 18%;
  right: clamp(14px, 2.2vw, 30px);
  width: 1px;
  height: 64%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom,
    transparent,
    color-mix(in srgb, var(--c-accent) 55%, transparent) 30%,
    color-mix(in srgb, var(--c-accent) 55%, transparent) 70%,
    transparent);
}

@media (max-width: 1080px) {
  /* A colonna sola l'immagine sta sopra (42% dello schermo) e il testo
     sotto. Le due colonne occupano la STESSA cella: le immagini scorrono
     nella fascia alta, il testo è incollato subito sotto e, stando sopra
     (z-index 1, fondo pieno), nasconde l'immagine successiva finché non
     sale nella fascia. */
  .trt { --trt-h: calc(var(--trt-schermo) * .42); }
  .trt__palco { grid-template-columns: minmax(0, 1fr); }
  .trt__lato,
  .trt__pannelli { grid-area: 1 / 1; }
  /* la cucitura verticale non ha senso con il testo sotto la foto */
  .trt__cucitura { display: none; }
  .trt__lato {
    top: var(--trt-h);
    margin-top: var(--trt-h);
    height: calc(var(--trt-schermo) - var(--trt-h));
    align-items: flex-start;
    padding-top: clamp(28px, 6vw, 44px);
  }
  .trt__titolo { font-size: clamp(1.6rem, 6vw, 2.1rem); }
  .trt__trattino { margin-top: 20px; }
  .trt__testo p { margin-top: 20px; font-size: 13.5px; line-height: 1.8; }
  .trt__progresso { margin-top: clamp(20px, 4vw, 30px); }
}

@media (prefers-reduced-motion: reduce) {
  .trt__testo,
  .trt__progresso-barra { transition: none; }
  /* angoli sempre disegnati, nessuna animazione */
  .trt.is-pronta .trt__pannello .trt__angolo::before,
  .trt.is-pronta .trt__pannello .trt__angolo::after { transform: none; transition: none; }
  .trt.is-pronta .trt__pannello .trt__angolo i { opacity: 1; transform: rotate(45deg); transition: none; }
}

/* ============================================================
   18. CONFRONTI — prima/dopo con divisore trascinabile.
   Dal prototipo di design. Differenze rispetto al prototipo, tutte volute:
   - i colori vengono dai token del tema (var(--c-bg), var(--c-fg),
     var(--c-accent), var(--font-display)…) e non dai valori fissi
     #0a0908 / #c9a25f del prototipo;
   - il prototipo ripeteva la stessa coppia di foto due volte come
     segnaposto: qui le coppie sono quelle dei contenuti, nessuna in più;
   - le durate delle transizioni passano per var(--motion), come nel
     resto del sito.

   IL PUNTO CHIAVE (dal prototipo): il riquadro non supera la larghezza
   nativa della foto più piccola, così l'immagine non viene mai
   ingrandita. Il valore arriva dal contenuto via --cfr-max (default
   921px, la larghezza di assets/beauty/prima-nativa.webp).
   ============================================================ */
.cfr {
  background: var(--c-bg);
  color: var(--c-fg);
  padding: clamp(3.5rem, 10vh, 8rem) clamp(1.1rem, 5vw, 5rem);
}
/* Titolo centrato esattamente sopra la foto: è largo quanto lei e
   condivide lo stesso asse, quindi resta simmetrico a prescindere dai
   video ai lati. */
/* Titolo in corsivo, su una riga sola, centrato sull'asse della foto.
   I due sbaffi dorati ai lati lo chiudono in modo simmetrico: crescono
   con lo spazio disponibile e spariscono quando manca. */
.cfr__titolo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 3vw, 2.2rem);
  margin: 0 auto clamp(2.4rem, 7vh, 5rem);
  text-align: center;
  white-space: nowrap;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2rem, 5.4vw, 4.4rem);
  line-height: 1.05;
  letter-spacing: -.015em;
}
.cfr__sbaffo {
  flex: 0 1 clamp(2rem, 9vw, 9rem);
  height: 1px;
  background: linear-gradient(to right,
    transparent, color-mix(in srgb, var(--c-accent) 50%, transparent));
}
.cfr__sbaffo:last-child {
  background: linear-gradient(to left,
    transparent, color-mix(in srgb, var(--c-accent) 50%, transparent));
}

/* --- La riga simmetrica: video, foto, video ---
   Le due colonne laterali hanno la STESSA misura e lo stesso gap dalla
   foto, quindi il blocco è speculare rispetto all'asse centrale. La
   foto resta della sua larghezza (--cfr-max) e non si deforma. */
.cfr__riga {
  display: grid;
  /* Le colonne laterali sono larghe quanto un clip, non 1fr: con 1fr si
     allargherebbero fino al bordo e i clip, spinti verso la foto,
     finirebbero a distanze diverse dai due lati. Con la misura fissa e
     justify-content:center il blocco resta speculare.
     minmax(0, …): le misure sono dei massimi. Quando lo spazio basta
     (da ~1300px in su) le colonne sono esattamente quelle; poco sopra
     la soglia mobile si stringono invece di spingere il video di
     destra fuori dallo schermo. */
  grid-template-columns:
    minmax(0, var(--cfr-clip, 230px))
    minmax(0, min(100%, var(--cfr-max, 560px)))
    minmax(0, var(--cfr-clip, 230px));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  justify-content: center;
  /* la riga è alta quanto la foto: i clip si ancorano ai suoi bordi
     con align-self, sopra a sinistra e sotto a destra */
  align-items: start;
  /* spazio per l'etichetta centrale, che è fuori dal flusso della sua
     cella (vedi .cfr__sotto--centro) e altrimenti uscirebbe dalla
     sezione */
  padding-bottom: 4.5rem;
}

/* la figure centrale porta la foto e la sua etichetta: è lei ora a
   occupare la colonna di mezzo */
.cfr__centro {
  position: relative;
  margin: 0;
  justify-self: center;
  width: 100%;
}
/* L'etichetta centrale è posizionata sotto la foto SENZA allungare la
   cella: se restasse nel flusso, la riga si alzerebbe e il clip di
   destra, ancorato al fondo, finirebbe sotto il bordo della foto
   invece che a filo. */
.cfr__sotto--centro {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
}
.cfr__box {
  position: relative;
  overflow: hidden;
  width: 100%;
  aspect-ratio: 4 / 5;
  background: color-mix(in srgb, var(--c-fg) 5%, var(--c-bg));
  touch-action: pan-y;
  cursor: ew-resize;
}
.cfr__box img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}
/* nessun ritaglio stretto: si sposta solo il punto di ancoraggio
   verticale, che arriva dal contenuto (fuocoPrima / fuocoDopo) */
.cfr__prima { object-position: center 50%; }
/* La foto "dopo" sta sotto e si scopre da DESTRA: il ritaglio taglia via
   tutto ciò che è a sinistra del divisore, così trascinando verso
   sinistra si rivela il dopo. Il prototipo faceva l'opposto (dopo a
   sinistra); qui prima sta a sinistra e dopo a destra. */
.cfr__dopo {
  object-position: center 50%;
  clip-path: inset(0 0 0 var(--pos, 50%));
}

.cfr__maniglia {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 5;
  left: var(--pos, 50%);
  width: 44px;
  margin-left: -22px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: ew-resize;
  touch-action: none;
  min-height: 0;   /* annulla il min-height:44px di css/temi/beauty.css */
}
.cfr__maniglia::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 21px;
  width: 1px;
  background: var(--c-accent);
  box-shadow: 0 0 22px color-mix(in srgb, var(--c-accent) 50%, transparent);
}
.cfr__maniglia i {
  position: relative;
  display: block;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--c-accent);
  background: color-mix(in srgb, var(--c-bg) 35%, transparent);
  backdrop-filter: blur(3px);
  transition: transform calc(.42s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1),
              background calc(.42s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
.cfr__maniglia i::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 11px;
  height: 1px;
  background: var(--c-accent);
}
.cfr__maniglia:hover i,
.cfr__maniglia:focus-visible i {
  transform: scale(1.14);
  background: color-mix(in srgb, var(--c-accent) 16%, transparent);
}
.cfr__maniglia:focus-visible { outline: none; }
.cfr__maniglia:focus-visible i {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 35%, transparent);
}

.cfr__etichetta {
  position: absolute;
  z-index: 4;
  bottom: 1rem;
  pointer-events: none;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1rem, 1.6vw, 1.35rem);
  text-shadow: 0 1px 16px rgba(0, 0, 0, .9);
}
/* Ogni etichetta sta sul lato dove si vede davvero quella foto:
   "Prima" a sinistra, "Dopo" a destra (vedi il clip-path di .cfr__dopo). */
.cfr__etichetta--prima { left: 1.1rem; color: var(--c-fg); }
.cfr__etichetta--dopo { right: 1.1rem; color: var(--c-accent); }

@media (prefers-reduced-motion: reduce) {
  .cfr__maniglia i { transition: none; }
}

/* --- 18b. CONFRONTI: i due clip ai lati del prima/dopo --- */

/* --- I due clip laterali ---
   Stessa larghezza, uno per lato. Il sinistro allinea il proprio bordo
   SUPERIORE a quello della foto, il destro il bordo INFERIORE: i due
   scostamenti sono speculari, e con i gap uguali la composizione resta
   simmetrica rispetto all'asse della foto. */
.cfr__clip {
  margin: 0;
  width: 100%;
  max-width: 230px;
}
/* la colonna è larga quanto il clip, quindi resta solo da dire a quale
   bordo della foto si allinea ciascuno */
.cfr__clip--sx { align-self: start; }  /* bordo alto = bordo alto foto */
/* A destra va allineato il bordo basso del VIDEO, non della figure:
   sotto il video c'è l'etichetta, quindi con align-self:end sarebbe
   lei a toccare il fondo della foto e il video resterebbe più in alto.
   Si sposta la figure in giù della sua etichetta, che è fuori dal
   flusso come quella centrale. */
.cfr__clip--dx {
  align-self: end;
  position: relative;
}
.cfr__clip--dx .cfr__sotto {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
}

/* --- le tre etichette ---
   Stesso trattamento per tutte e tre, così convivono come una famiglia:
   corsivo del font display, corpo piccolo, un filetto dorato sopra.
   Quella centrale è un gradino più grande, perché nomina il pezzo
   principale della composizione. */
.cfr__sotto {
  margin-top: clamp(.9rem, 2.2vh, 1.4rem);
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: .95rem;
  line-height: 1.2;
  letter-spacing: .01em;
  color: color-mix(in srgb, var(--c-fg) 62%, transparent);
}
.cfr__sotto::before {
  content: "";
  display: block;
  width: 1.6rem;
  height: 1px;
  margin: 0 auto clamp(.5rem, 1.2vh, .8rem);
  background: color-mix(in srgb, var(--c-accent) 45%, transparent);
}
.cfr__sotto--centro {
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  color: color-mix(in srgb, var(--c-fg) 85%, transparent);
}
.cfr__sotto--centro::before {
  width: 2.6rem;
  background: color-mix(in srgb, var(--c-accent) 70%, transparent);
}
/* se manca un video il posto resta, così la foto non si sposta
   dall'asse e la simmetria regge lo stesso */
.cfr__vuoto-lato { display: block; }

/* --- decori ---
   Quattro angoli dorati appena accennati attorno alla foto: la
   incorniciano senza chiuderla, e richiamano i filetti oro della
   testata dei lavori. Sta dentro .cfr__box e non aggiunge elementi al
   flusso: è un solo span con due gradienti per lato. */
.cfr__mirino {
  position: absolute;
  inset: 10px;
  z-index: 4;
  pointer-events: none;
  --a: color-mix(in srgb, var(--c-accent) 60%, transparent);
  --l: 18px;
  background:
    /* alto-sinistra */
    linear-gradient(var(--a), var(--a)) left  top    / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) left  top    / var(--l) 1px no-repeat,
    /* alto-destra */
    linear-gradient(var(--a), var(--a)) right top    / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) right top    / var(--l) 1px no-repeat,
    /* basso-sinistra */
    linear-gradient(var(--a), var(--a)) left  bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) left  bottom / var(--l) 1px no-repeat,
    /* basso-destra */
    linear-gradient(var(--a), var(--a)) right bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) right bottom / var(--l) 1px no-repeat;
}

.cfr__media {
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  background: color-mix(in srgb, var(--c-fg) 6%, var(--c-bg));
}
.cfr__media--vuoto {
  display: grid;
  place-items: center;
  padding: .8rem;
  border: 1px dashed color-mix(in srgb, var(--c-fg) 22%, transparent);
}
.cfr__vuoto-nota {
  font-family: var(--font-ui);
  font-size: .62rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.6;
  color: color-mix(in srgb, var(--c-fg) 38%, transparent);
}
.cfr__utente {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin-top: .6rem;
  font-family: var(--font-ui);
  font-size: .68rem;
  letter-spacing: .06em;
  color: color-mix(in srgb, var(--c-fg) 55%, transparent);
}
.cfr__utente i {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--c-accent) 28%, transparent);
}

/* Sotto i 900px i video non stanno ai lati: la foto occuperebbe una
   striscia troppo stretta. Si impilano sotto, affiancati fra loro, e la
   simmetria resta perché sono due di uguale larghezza. */
@media (max-width: 1080px) {
  .cfr__riga {
    grid-template-columns: repeat(2, minmax(0, 230px));
    justify-content: center;
    gap: clamp(1rem, 3vw, 1.6rem);
  }
  /* la figure centrale occupa entrambe le colonne; i due clip si
     dividono la riga sotto, uno per colonna */
  .cfr__centro { grid-column: 1 / -1; justify-self: center; }
  .cfr__clip--sx,
  .cfr__clip--dx {
    justify-self: center;
    align-self: start;
    margin-top: clamp(1rem, 3vh, 1.6rem);
  }
  .cfr__clip--sx { grid-column: 1; }
  .cfr__clip--dx { grid-column: 2; }
  .cfr__vuoto-lato { display: none; }
}

/* ================================================================
   19. LAVORI — testata statica di "I nostri lavori"
   Niente sticky, niente
   fixed, niente sfondo fotografico: una testata nel flusso, alta quanto
   il suo contenuto, con il titolo centrato. Subito sotto
   c'è il titolo dei confronti ("Prima e dopo"), ridotto a sottotitolo:
   i due si leggono come un blocco solo.
   L'unico movimento è la rivelazione una tantum di [data-rivela]
   (js/lavori.js): si parte poco più in basso e trasparenti, si arriva a
   transform:none — non translateY(0), così a fine corsa l'elemento non
   tiene aperto un contesto di impilamento.
   ================================================================ */

.lvr {
  --lvr-margine: clamp(1.1rem, 5vw, 5rem);   /* lo stesso di .cfr */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;   /* in basso, attaccato al sottotitolo */
  align-items: center;
  text-align: center;
  /* Alta quanto il suo contenuto: niente vuoto fra i trattamenti e il
     titolo. scroll-margin-top tiene il titolo sotto la nav fissa quando
     ci si arriva dal link "Lavori", senza aggiungere spazio nel layout. */
  padding: clamp(2.5rem, 6vh, 4rem) var(--lvr-margine) clamp(1rem, 3vh, 2rem);
  scroll-margin-top: clamp(3rem, 8vh, 5rem);
  background: var(--c-bg);
  color: var(--c-fg);
}
.lvr__titolo {
  margin: 0;
  max-width: 14ch;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(3rem, 9vw, 7.5rem);
  line-height: .98;
  letter-spacing: -.025em;
}

/* "Prima e dopo" diventa il sottotitolo della testata: corpo ridotto,
   stacco sopra minimo. Vale solo quando i confronti seguono la testata;
   altrove .cfr__titolo resta com'è. */
.lvr + .cfr { padding-top: clamp(1rem, 2.5vh, 1.6rem); }
.lvr + .cfr .cfr__titolo {
  /* dritto: il corsivo resta al solo titolo, così i due livelli si
     distinguono anche per stile e non solo per corpo */
  font-style: normal;
  font-size: clamp(1.25rem, 2.2vw, 1.8rem);
  gap: clamp(.8rem, 2vw, 1.4rem);
  margin-bottom: clamp(2.4rem, 7vh, 4.5rem);
  color: color-mix(in srgb, var(--c-fg) 80%, transparent);
}

/* --- fondo e linee del gruppo "lavori" ---
   Testata e confronti sono in un solo .gruppo--lavori (contenuti), così
   il tessuto è un'unica immagine continua: lo stesso --frase-sfondo di
   .frase, .ovl-servizi e .chi. Rispetto a .gruppo (§ inizio file) si
   tolgono il background-attachment:fixed e il velo del ::before, che
   qui servono ad altro: i due pseudo-elementi disegnano le linee.
   Tutto statico, nessuna animazione, pointer-events: none. */
.gruppo.gruppo--lavori {
  --lvr-oro: color-mix(in srgb, var(--c-accent) 45%, transparent);
  background: var(--frase-sfondo, var(--c-bg));
}
.gruppo--lavori > .lvr,
.gruppo--lavori > .cfr { background: transparent; }

/* Due binari verticali ai margini, a metà del margine laterale: fanno
   da cornice alla composizione e sfumano alle due estremità. */
.gruppo.gruppo--lavori::before {
  inset: clamp(3rem, 9vh, 6rem) calc(clamp(1.1rem, 5vw, 5rem) / 2);
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, transparent, var(--lvr-oro) 18%, var(--lvr-oro) 82%, transparent)
      left top / 1px 100% no-repeat,
    linear-gradient(to bottom, transparent, var(--lvr-oro) 18%, var(--lvr-oro) 82%, transparent)
      right top / 1px 100% no-repeat;
}
/* In cima: un filo orizzontale centrato che sfuma ai lati e, dal suo
   centro, un tratto sull'asse che scende verso il titolo. Sta tutto
   dentro il padding alto della testata. */
.gruppo.gruppo--lavori::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 0;
  width: min(62%, 44rem);
  height: clamp(1.4rem, 3.2vh, 2.2rem);
  transform: translateX(-50%);
  pointer-events: none;
  background:
    linear-gradient(to right, transparent, var(--lvr-oro), transparent)
      center top / 100% 1px no-repeat,
    linear-gradient(to bottom, var(--lvr-oro), transparent)
      center top / 1px 100% no-repeat;
}
/* su telefono il margine è stretto: i binari toccherebbero le foto */
@media (max-width: 1080px) {
  .gruppo.gruppo--lavori::before { display: none; }
}

/* --- rivelazione una tantum ---
   .js-rivela la mette js/lavori.js sull'<html> nello stesso istante in
   cui marca gli elementi: senza JS non c'è e tutto resta visibile.
   Solo opacity e transform. Il ritardo di sfalsamento (multipli di
   100ms) arriva inline da --rivela-ritardo.
   "html.js-rivela" e non ".js-rivela": un gradino di specificità in
   più, perché alcuni elementi rivelati (i testi dei trattamenti su
   telefono) hanno nel foglio mobile opacity/transform/transition
   imposti, e quel foglio è caricato dopo. */
html.js-rivela [data-rivela] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity calc(.8s * var(--motion, 1)) cubic-bezier(.22, .61, .36, 1),
    transform calc(.9s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--rivela-ritardo, 0ms);
}
html.js-rivela [data-rivela].is-rivelato {
  opacity: 1;
  transform: none;
}

/* --- decori disegnati all'ingresso ---
   Il contenitore di un gruppo porta data-rivela-gruppo finché è in
   attesa e riceve .e-rivelato quando entra in vista (js/lavori.js).
   Le regole "a riposo" valgono solo in attesa: senza JS, o con meno
   animazioni, l'attributo non c'è e i decori sono già al loro posto. */

/* tricologia: la foto di sfondo si posa, da appena più vicina e velata */
.tri[data-rivela-gruppo] .tri__foto {
  transition:
    opacity calc(1.4s * var(--motion, 1)) cubic-bezier(.22, .61, .36, 1),
    transform calc(2.2s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1);
}
.js-rivela .tri[data-rivela-gruppo]:not(.e-rivelato) .tri__foto {
  opacity: 0;
  transform: scale(1.06);
}

/* gruppo lavori: i binari laterali scendono dall'alto, il filo in cima
   si apre dal centro */
.gruppo.gruppo--lavori[data-rivela-gruppo]::before {
  transform-origin: center top;
  transition: transform calc(1.8s * var(--motion, 1)) cubic-bezier(.65, 0, .35, 1) calc(.2s * var(--motion, 1));
}
.gruppo.gruppo--lavori[data-rivela-gruppo]::after {
  transform-origin: center top;
  transition:
    transform calc(1.2s * var(--motion, 1)) cubic-bezier(.16, 1, .3, 1),
    opacity calc(1s * var(--motion, 1)) ease;
}
.js-rivela .gruppo--lavori[data-rivela-gruppo]:not(.e-rivelato)::before { transform: scaleY(0); }
.js-rivela .gruppo--lavori[data-rivela-gruppo]:not(.e-rivelato)::after {
  transform: translateX(-50%) scaleX(0);
  opacity: 0;
}

/* trattamenti (desktop): il filetto verticale scende e gli angoli oro
   della prima foto si disegnano quando la sezione arriva in vista, non
   al caricamento della pagina */
.trt[data-rivela-gruppo] .trt__cucitura {
  transform-origin: center top;
  transition: transform calc(1.6s * var(--motion, 1)) cubic-bezier(.65, 0, .35, 1) calc(.3s * var(--motion, 1));
}
.js-rivela .trt[data-rivela-gruppo]:not(.e-rivelato) .trt__cucitura { transform: scaleY(0); }
.js-rivela .trt[data-rivela-gruppo]:not(.e-rivelato) .trt__angolo::before { transform: scaleX(0); }
.js-rivela .trt[data-rivela-gruppo]:not(.e-rivelato) .trt__angolo::after  { transform: scaleY(0); }
.js-rivela .trt[data-rivela-gruppo]:not(.e-rivelato) .trt__angolo i {
  opacity: 0;
  transform: rotate(45deg) scale(.2);
}

@media (prefers-reduced-motion: reduce) {
  html.js-rivela [data-rivela] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ================================================================
   20. FASCIA — striscia informativa compatta
   Non è una sezione a tutta altezza: il padding verticale è una
   frazione di quello di .sezione, e l'altezza la detta il contenuto.
   Testo a sinistra e invito a destra su una riga sola; sotto i 760px
   vanno in colonna. Tutti gli stili del bottone e dell'occhiello
   arrivano dal tema (.btn--ghost, .eyebrow): qui c'è solo impaginazione.
   ================================================================ */

.fascia {
  padding-block: clamp(2rem, 5vw, 3.2rem);
  background: var(--c-bg);
  color: var(--c-fg);
  border-top: 1px solid color-mix(in srgb, var(--c-fg) 10%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--c-fg) 10%, transparent);
}
.fascia--alt { background: var(--c-surface, var(--c-bg)); }

.fascia__riga {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  flex-wrap: wrap;
}
/* La base flex vale sull'asse principale: in riga è larghezza, ma
   quando .fascia__riga passa a colonna (sotto i 760px) diventerebbe
   ALTEZZA, gonfiando la fascia di 32rem di vuoto. Si dichiara solo
   nella disposizione in riga. */
.fascia__testo { min-width: 0; }
@media (min-width: 1081px) {
  .fascia__testo { flex: 1 1 32rem; }
}
/* l'occhiello qui sta stretto sopra il testo, non staccato come nelle
   sezioni grandi */
.fascia__testo .eyebrow { margin-bottom: .5rem; }
.fascia__testo p {
  margin: 0;
  max-width: 62ch;
  font-size: clamp(.95rem, 1.2vw, 1.05rem);
  line-height: 1.7;
  color: color-mix(in srgb, var(--c-fg) 78%, transparent);
}
.fascia__azione { flex: none; }

@media (max-width: 1080px) {
  .fascia__riga { flex-direction: column; align-items: flex-start; }
  .fascia__azione { align-self: stretch; justify-content: center; }
}

/* ================================================================
   21. PRENOTAZIONI — variante "atelier" della sezione contatti
   Markup in contattiAtelier() (js/render.js). Sulla stessa seta scura
   di frase, servizi e chi sono. Tre piani:
   - testata centrata: occhiello fra due fili, titolo, e una pillola
     con lo stato di apertura dal vivo ("Aperto ora · fino alle 18:00");
   - a sinistra la settimana come sette colonne uguali — sigla del
     giorno, apertura, filo, chiusura — con oggi incorniciato d'oro e i
     giorni di chiusura in corsivo velato; sotto, i recapiti;
   - a destra il modulo in una cornice con gli angoli oro del sito.
   Nessuna misura fissa che non stia a 390px: le colonne dei giorni e i
   campi del modulo si adattano da soli (clamp, auto-fit), quindi c'è
   una sola media query, la soglia comune a 1080px.
   ================================================================ */
.pren {
  --pren-oro: color-mix(in srgb, var(--c-accent) 70%, transparent);
  --pren-filo: color-mix(in srgb, var(--c-accent) 28%, transparent);
  position: relative;
  padding-block: clamp(4.5rem, 10vw, 8rem);
  background: var(--frase-sfondo, var(--c-bg));
  color: var(--c-fg);
}
/* filo oro in cima, centrato e sfumato: stacca la sezione dalla fascia
   sopra senza un bordo pieno */
.pren::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: min(62%, 44rem);
  height: 1px;
  transform: translateX(-50%);
  background: linear-gradient(to right, transparent, var(--pren-oro), transparent);
  pointer-events: none;
}
.pren__cornice {
  width: min(1180px, 100% - 2.5rem);
  margin-inline: auto;
}

/* --- testata --- */
.pren__testata {
  max-width: 46rem;
  margin: 0 auto clamp(2.8rem, 6vw, 4.5rem);
  text-align: center;
}
.pren__occhiello {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-ui);
  font-size: .68rem;
  letter-spacing: .4em;
  text-transform: uppercase;
  color: var(--c-accent);
}
.pren__occhiello::before,
.pren__occhiello::after {
  content: "";
  width: 44px;
  height: 1px;
  background: var(--c-accent);
}
/* il letter-spacing lascia spazio dopo l'ultima lettera: si recupera
   perché fili e testo restino simmetrici sull'asse */
.pren__occhiello::after { margin-left: -.4em; }
.pren__titolo {
  margin: clamp(1.1rem, 2.5vw, 1.6rem) 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.1rem, 4.6vw, 3.7rem);
  line-height: 1.08;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.pren__stato {
  display: inline-flex;
  align-items: center;
  gap: .7em;
  max-width: 100%;
  margin: clamp(1.4rem, 3vw, 2rem) 0 0;
  padding: .6em 1.2em;
  border: 1px solid var(--pren-filo);
  border-radius: 999px;
  font-family: var(--font-ui);
  font-size: .74rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--c-fg) 82%, transparent);
}
.pren__stato i {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #F87171;
}
.pren__stato.is-aperto i {
  background: #4ADE80;
  animation: pulsa 2s infinite;   /* stesso battito del pallino della hero (base.css) */
}

/* --- corpo: settimana e recapiti | modulo --- */
.pren__corpo {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
  gap: clamp(2.5rem, 5vw, 5.5rem);
  align-items: start;
}

/* la settimana: sette colonne uguali fra due fili oro */
.pren__settimana {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  border-block: 1px solid var(--pren-filo);
}
.pren__giorno {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(.6rem, 1.4vw, .9rem);
  padding: clamp(1rem, 2.4vw, 1.5rem) .15rem clamp(1.1rem, 2.6vw, 1.6rem);
  text-align: center;
}
.pren__giorno + .pren__giorno { border-left: 1px solid color-mix(in srgb, var(--c-fg) 8%, transparent); }
.pren__sigla {
  font-family: var(--font-ui);
  font-size: clamp(.62rem, 1.9vw, .7rem);
  letter-spacing: .2em;
  margin-right: -.2em;
  text-transform: uppercase;
  text-decoration: none;
  color: color-mix(in srgb, var(--c-fg) 62%, transparent);
}
/* apertura, filo verticale, chiusura: si legge dall'alto in basso */
.pren__ore {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .35rem;
  font-family: var(--font-display);
  font-size: clamp(.82rem, 2.2vw, 1.12rem);
  font-variant-numeric: lining-nums tabular-nums;
  line-height: 1;
  color: var(--c-fg);
}
.pren__ore b { font-weight: 400; }
.pren__ore i {
  width: 1px;
  height: clamp(.7rem, 1.8vw, 1.1rem);
  background: var(--pren-oro);
}
.pren__ore--chiuso {
  justify-content: center;
  min-height: calc(2em + clamp(.7rem, 1.8vw, 1.1rem) + .7rem);
  font-style: italic;
  font-size: clamp(.72rem, 2vw, .92rem);
  color: color-mix(in srgb, var(--c-fg) 40%, transparent);
}
.pren__giorno.is-chiuso .pren__sigla { color: color-mix(in srgb, var(--c-fg) 38%, transparent); }

/* oggi: cornice oro sottile, un velo caldo e la parola "oggi" sotto */
.pren__giorno.is-oggi {
  background: color-mix(in srgb, var(--c-accent) 7%, transparent);
  box-shadow: inset 0 0 0 1px var(--pren-oro);
}
.pren__giorno.is-oggi .pren__sigla { color: var(--c-accent); }
.pren__giorno::after {
  content: "oggi";
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(.66rem, 1.8vw, .8rem);
  line-height: 1;
  color: var(--c-accent);
  visibility: hidden;   /* lo spazio c'è sempre: le colonne restano alte uguali */
}
.pren__giorno.is-oggi::after { visibility: visible; }

.visivamente-nascosto {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* recapiti: etichetta in maiuscoletto oro, valore nel font dei titoli */
.pren__recapiti {
  display: grid;
  gap: 1.3rem;
  margin: clamp(2rem, 4vw, 2.8rem) 0 0;
}
.pren__recapito {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 1rem;
  align-items: baseline;
  padding-bottom: 1.3rem;
  border-bottom: 1px solid color-mix(in srgb, var(--c-fg) 9%, transparent);
}
.pren__recapito dt {
  font-family: var(--font-ui);
  font-size: .66rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--pren-oro);
}
.pren__recapito dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.pren__recapito a {
  color: inherit;
  text-decoration: none;
  background: linear-gradient(var(--c-accent), var(--c-accent)) left bottom / 0 1px no-repeat;
  transition: background-size calc(.45s * var(--motion, 1)) cubic-bezier(.2, .8, .2, 1), color .3s;
}
.pren__recapito a:hover,
.pren__recapito a:focus-visible { background-size: 100% 1px; color: var(--c-accent); }
.pren__azioni { margin-top: clamp(1.8rem, 3.5vw, 2.4rem); }

/* --- modulo in cornice --- */
.pren__modulo {
  position: relative;
  padding: clamp(1.8rem, 4vw, 3rem);
  background: color-mix(in srgb, var(--c-bg) 62%, transparent);
  border: 1px solid color-mix(in srgb, var(--c-accent) 20%, transparent);
}
/* quattro angoli oro, come il mirino del prima/dopo (§18) */
.pren__angoli {
  position: absolute;
  inset: 10px;
  pointer-events: none;
  --a: var(--pren-oro);
  --l: 22px;
  background:
    linear-gradient(var(--a), var(--a)) left  top    / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) left  top    / var(--l) 1px no-repeat,
    linear-gradient(var(--a), var(--a)) right top    / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) right top    / var(--l) 1px no-repeat,
    linear-gradient(var(--a), var(--a)) left  bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) left  bottom / var(--l) 1px no-repeat,
    linear-gradient(var(--a), var(--a)) right bottom / 1px var(--l) no-repeat,
    linear-gradient(var(--a), var(--a)) right bottom / var(--l) 1px no-repeat;
}
.pren__modulo-titolo {
  margin: 0 0 clamp(1.4rem, 3vw, 2rem);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.35rem, 2.4vw, 1.7rem);
  line-height: 1.2;
  color: color-mix(in srgb, var(--c-accent) 85%, var(--c-fg));
}
/* due campi per riga quando c'è posto, uno sotto l'altro quando no */
.pren__campi {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: 1.5rem 1.6rem;
}
.pren .campo { margin: 0; gap: .5rem; }
.pren .campo label {
  font-size: .66rem;
  letter-spacing: .2em;
  opacity: 1;
  color: color-mix(in srgb, var(--c-fg) 60%, transparent);
}
.pren__obbl { color: var(--c-accent); }
/* campi a filo: solo la linea sotto, che si accende d'oro */
.pren .campo input {
  width: 100%;
  min-height: 44px;
  padding: .55em 0;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-fg) 24%, transparent);
  border-radius: 0;
  background: transparent;
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--c-fg);
  color-scheme: dark;   /* calendario e icone del campo data in chiaro */
  transition: border-color .3s;
}
.pren .campo input:focus { border-bottom-color: var(--c-accent); outline: none; }
.pren .campo input:focus-visible { box-shadow: 0 1px 0 0 var(--c-accent); }
.pren__nota-data {
  min-height: 1.4em;
  font-family: var(--font-ui);
  font-size: .76rem;
  line-height: 1.4;
  color: color-mix(in srgb, var(--c-fg) 55%, transparent);
}
.pren__nota-data.is-avviso { color: var(--c-accent); }
.pren__invio {
  width: 100%;
  margin-top: clamp(1.6rem, 3vw, 2.2rem);
}
/* sotto il pulsante: cosa succede premendolo, e dopo l'esito */
.pren__nota-invio,
.pren__esito {
  margin: .9rem 0 0;
  max-width: none;
  font-family: var(--font-ui);
  font-size: .78rem;
  line-height: 1.5;
  text-align: center;
  color: color-mix(in srgb, var(--c-fg) 55%, transparent);
}
.pren__esito {
  padding-top: .9rem;
  border-top: 1px solid var(--pren-filo);
  color: color-mix(in srgb, var(--c-fg) 82%, transparent);
}
.pren__esito a {
  color: var(--c-accent);
  text-underline-offset: .2em;
}

/* telefono e tablet: una colonna centrata */
@media (max-width: 1080px) {
  .pren__corpo {
    grid-template-columns: minmax(0, 1fr);
    max-width: 680px;
    margin-inline: auto;
  }
}
