/* ============================================================
   ROOT — token di progetto
   ------------------------------------------------------------
   Solo variabili. Il reset canonico e' in reset.css, accodato
   prima di questo file.

   Ordine delle proprieta' (REGOLE CSS): custom properties,
   positioning, layout, sizing, spacing, typography, appearance,
   interaction, motion, nested/stati/media.
   ============================================================ */
:root {
  /* --- tipografia: fallback fisso, scala fluida piu' sotto --- */
  --h1: 8rem;
  --h2: 4rem;
  --h3: 3rem;
  --h4: 2rem;
  --body: 1.25rem;

  /* Dimensioni testo fuori dalla scala titoli (UI fissa). */
  --button-text: 1rem;   /* 16px — bottoni, sopracciglia */
  --tag-text: 0.75rem;   /* 12px — tag, legal */
  --pill-text: 0.75rem;  /* 12px — pill e etichette dei filtri (10px sotto i 768px) */

  /* --- scala di spaziatura semantica: fallback fisso --- */
  --xl-space: 12.5rem;
  --l-space: 5rem;
  --m-space: 2.5rem;
  --s-space: 1.5rem;
  --xs-space: 1rem;
  --gap-tight: 0.5rem;    /* gap interni cta / badge */
  --ease-button: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* rimbalzo dei bottoni (come clou.ch) */

  /* Eccezione dichiarata (REGOLE CSS/CSS_EXCEPTIONS): passi fissi,
     volutamente fuori dalla scala fluida. Non ricevono clamp() e non
     seguono la progressione xs..xl: sono i valori concordati per il
     gap verticale dei blocchi in colonna (--stack-48), per padding+gap
     della card progetto (--stack-32) e per la gutter delle gallerie
     della scheda progetto (--gallery-gap, sempre 24px nel Figma,
     orizzontale e verticale). */
  --stack-48: 3rem;
  --stack-32: 2rem;
  --gallery-gap: 1.5rem;

  /* Raggi dei pannelli con un angolo desktop diverso da --m-space
     (che darebbe 40->24): ancorati 480->1440 come il resto della
     scala. --radius-panel-40 (30->40) e' per i pannelli "normali"
     con angolo desktop a 40px ma minimo mobile 30, non 24
     (.site-footer). --radius-panel-80 (30->80) e' per i pannelli con
     angolo desktop piu' pronunciato (.services, .origini). */
  --radius-panel-40: max(clamp(1.875rem, 1.0417vw + 1.5625rem, 2.5rem), 2.0833vw);
  --radius-panel-80: max(clamp(1.875rem, 5.2083vw + 0.3125rem, 5rem), 4.1667vw);

  /* Altezza reale di .site-header (position: fixed): 2x il suo
     padding-block (--s-space) + l'altezza del contenuto piu' alto
     (48px, l'icona hamburger). Serve per calcolare quanto spazio
     lasciare sotto l'header sulle pagine dove galleggia direttamente
     sul primo blocco (nessuna hero sotto), es. .contact-page. */
  --header-height: calc(2 * var(--s-space) + var(--toggle-size));

  /* Elementi dell'header: logo, hamburger e X del menu. --toggle-size
     e' 48px fino a 1440px, poi cresce in proporzione alla larghezza
     fino a 2560px (x1.78, vedi @supports); entra in --header-height.
     Il logo ha la stessa altezza del cerchio dell'hamburger (richiesta
     del grafico): --logo-height = --toggle-size, un solo valore. */
  --logo-height: var(--toggle-size);
  --toggle-size: 3rem;

  /* --- colori: ruoli semantici (REGOLE CSS: MUST) --- */
  --color-surface: #ececec;   /* sfondo pagina chiaro */
  --color-text: #1e1e1e;      /* testo su superficie chiara */
  --color-primary: #1e1e1e;   /* sezioni scure, bottone menu */
  --color-secondary: #383838; /* cta secondaria */
  --color-muted: #a1a1a1;     /* placeholder, testo attenuato */
  --color-hairline: #d4d4d4;  /* separatori sottili su fondo scuro */
  --color-border: currentColor;
  --color-focus: #8187ff;     /* indicatore :focus-visible */

  /* Accenti delle card progetto. Eccezione dichiarata: nomi di
     colore, non di ruolo (REGOLE CSS sconsiglia i nomi
     presentazionali, ma qui i quattro accenti sono un ritmo
     visivo assegnato per POSIZIONE da elidria_work_color(), non
     ruoli riutilizzabili). Scelta confermata dal team. */
  --color-teal: #39b39d;
  --color-violet: #8187ff;
  --color-pink: #f28cb6;
  --color-yellow: #e4c445;

  /* --- font --- */
  --font-body: "Geist", sans-serif;
  --font-mono: "Geist Mono", monospace;
  /* Display: "That That New Pixel" (@font-face in fonts.css). Due
     tagli. Round: eyebrow della About. Square (usato in italic):
     domanda e titoli "ipotesi". Fallback su un serif per non
     ritrovarsi con un sans generico se il woff2 non carica. */
  --font-display-round: "That That New Pixel Round", Georgia, serif;
  --font-display-square: "That That New Pixel Square", Georgia, serif;
}

/* Scala fluida: sostituisce i fallback dove clamp() e' supportato. */
@supports (font-size: clamp(1rem, calc(1rem + ((1vw - 0.3rem) * 0.2083)), 1.125rem)) {
  :root {
    /* Scala ancorata 480px (mobile) -> 1440px (desktop, frame Figma):
       slope = (max-min)/(1440-480), intercept = min - slope*480. Ogni
       token tocca il valore esatto del Figma a 480 e a 1440.

       REGOLA: a 1440 e a 1920 i valori sono UGUALI (il massimo del
       Figma); solo OLTRE 1920px crescono in proporzione alla larghezza
       (schermi Retina/grandi, ~2560px). Forma:
         max( clamp(min, retta, MASSIMO), MASSIMO/1920 vw )
       dove MASSIMO/1920vw e' il massimo espresso in vw: vale MASSIMO a
       1920px (e quindi meno sotto, dove vince il clamp) e cresce dopo.
       Es. --m-space: 40px (2.5rem) = 2.0833vw a 1920. */
    --h1: max(clamp(3rem, 11.25vw - 0.375rem, 9.75rem), 8.125vw);
    --h2: max(clamp(3rem, 5vw + 1.5rem, 6rem), 5vw);
    --h3: max(clamp(1.5rem, 2.5vw + 0.75rem, 3rem), 2.5vw);
    --h4: max(clamp(1.5rem, 0.8333vw + 1.25rem, 2rem), 1.6667vw);
    --body: max(clamp(1.25rem, 0.4167vw + 1.125rem, 1.5rem), 1.25vw);

    --xl-space: max(clamp(9.375rem, 5.2083vw + 7.8125rem, 12.5rem), 10.4167vw);
    --l-space: max(clamp(3.5rem, 2.5vw + 2.75rem, 5rem), 4.1667vw);
    --m-space: max(clamp(1.5rem, 1.6667vw + 1rem, 2.5rem), 2.0833vw);
    --s-space: max(clamp(1rem, 0.8333vw + 0.75rem, 1.5rem), 1.25vw);
    --xs-space: max(clamp(0.5rem, 0.8333vw + 0.25rem, 1rem), 0.8333vw);

    /* Hamburger (e logo, che ha la stessa altezza): 48px fino a
       1920px, poi in proporzione (2.5vw = 48/1920). */
    --toggle-size: max(3rem, 2.5vw);
  }
}

/* Mobile: pill e etichette dei filtri d'archivio (--pill-text) a 10px
   invece di 12px. Token a parte da --tag-text, che resta 12px per le
   etichette dei form, il testo legale del footer, gli eyebrow e i
   numeri di Servizi. Soglia 768px, come gli altri passaggi mobile. */
@media (max-width: 768px) {
  :root {
    --pill-text: 0.625rem; /* 10px */
  }
}

/* ============================================================
   BASE — decisioni globali di progetto
   ------------------------------------------------------------
   Fuori dal reset canonico, che resta neutro.
   ============================================================ */
body {
  font-family: var(--font-body);
  font-size: var(--body);
  color: var(--color-text);
  background-color: var(--color-surface);
}

/* Interlinea fluida e p { margin-block: 0 } sono nel reset condiviso
   (reset.css): valgono per ogni progetto Elidria, non solo qui. */

/* Lo smooth scroll di pagina e' gestito da Lenis via JS (assets/js).
   Quando e' attivo, .lenis viene aggiunto a <html>: qui si spegne lo
   scroll nativo per non sommarsi a quello interpolato. Senza JS (o con
   reduced-motion) la classe non c'e' e vale lo scroll normale. */
.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

/* Menu overlay aperto: blocca lo scroll di pagina anche senza Lenis
   (reduced-motion, o JS di Lenis non attivo). Con Lenis attivo ci
   pensa lenis.stop() -> .lenis-stopped qui sopra. */
.is-nav-open {
  overflow: hidden;
}

/* Con lo scroll bloccato la scrollbar sparisce e il viewport si
   allarga di --scrollbar-w (misurata in main.js prima del blocco):
   header e overlay togliscono la stessa quantita' dal lato destro, cosi'
   hamburger e X (e il logo) restano esattamente dove erano. */
.is-nav-open .site-header,
.is-nav-open .site-nav__inner {
  padding-inline-end: calc(var(--m-space) + var(--scrollbar-w, 0px));
}

a {
  color: inherit;
  text-decoration: none;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

button {
  border: none;
  background: none;
}

input,
textarea {
  border: none;
  background: none;
}

/* ============================================================
   NOTA SUI BREAKPOINT
   ------------------------------------------------------------
   Approccio desktop-first (REGOLE CSS): il layout completo e'
   quello sopra, senza media query; qui sotto, nel blocco di
   OGNI componente, un gruppo @media (max-width) SEMPLIFICA la
   struttura per schermi stretti. Le media query sono co-locate
   (ultimo gruppo di ogni sezione), non raccolte a parte.

   Famiglia di breakpoint: 1200 / 992 / 768 / 480. Si usa solo
   la soglia che serve al componente, mai una "per nome device".
   768px e' il collasso principale desktop -> mobile; 480px per
   un secondo ritocco; 992px per adattare lo stacking di Work,
   che pero' NON viene disattivato — cambiano solo le variabili
   --work-card-*.

   Fluid prima del breakpoint: la scala clamp() di :root copre
   tipografia e spaziatura continue. Le media query intervengono
   solo su cambi STRUTTURALI (thumb hero ridisposte, parallax
   fermo) o per ritarare le variabili di un effetto (Work).

   NB: solo il parallax dell'hero ha un gate di larghezza in
   main.js (matchMedia 768px): sotto la soglia il CSS ferma la
   scena e il JS non aggancia il listener mousemove. Lo stacking
   di Work resta attivo ovunque.
   ============================================================ */

/* ============================================================
   NOTA SUL NESTING
   ------------------------------------------------------------
   Il nesting nativo con & NON concatena i nomi: "&__thumb" non
   produce ".hero__thumb" e il browser scarta la regola (sintassi
   Sass). Gli elementi BEM sono quindi scritti per esteso al primo
   livello: specificita' piatta (0,1,0) e nessun elemento dipende
   dal genitore.

   Il nesting resta dove e' valido: pseudo-classi (&:hover),
   pseudo-elementi (&::placeholder), discendenti (& img).
   ============================================================ */

/* ============================================================
   CONTENITORE — padding laterale, sito full-width a ogni schermo
   ------------------------------------------------------------
   Nessun tetto di larghezza: il contenuto occupa sempre tutto lo
   schermo, solo il padding laterale scala (40px desktop -> 24px
   mobile, --m-space). Sfondo e angoli arrotondati restano a tutta
   larghezza; nessuna classe BEM cambia, il markup resta identico al
   riferimento.
   ============================================================ */
.site-header,
.intro,
.work,
.contact,
.contact-page,
.services,
.projects-archive,
.project-lede,
.project-body,
.latest-projects,
.chi-hero,
.origini,
.elidri,
.servizi-teaser,
.site-footer {
  padding-inline: var(--m-space);
}

/* ============================================================
   TITOLI — text-box-trim
   ------------------------------------------------------------
   Rifila lo spazio dato dal line-height sopra/sotto il testo,
   allineandolo ai bordi tipografici reali (nel Figma questi titoli
   hanno [text-box-edge:cap_alphabetic] [text-box-trim:trim-both]).
   Molto recente (Chrome/Edge 133+): @supports come per clamp(), senza
   il quale il titolo mantiene semplicemente il line-height normale.
   Solo sui titoli brevi a riga singola confermati dal Figma — non su
   testi di più righe (u-text-lg/md), dove tagliare l'interlinea
   normale li stringerebbe.
   ============================================================ */
@supports (text-box-trim: trim-both) {
  .work-item__title,
  .contact__title,
  .contact-page__title,
  .services__title,
  .projects-archive__title,
  .project-card__title,
  .project-lede__title,
  .chi-hero__title,
  .origini__question,
  .origini__ipotesi-title,
  .elidri__title {
    text-box-trim: trim-both;
    text-box-edge: cap alphabetic;
  }
}

/* ============================================================
   UTILITY — .u-*
   ------------------------------------------------------------
   Poche, a scopo singolo (REGOLE CSS: utility vs componente).
   ============================================================ */

/* Occhielli / paragrafi introduttivi: font da titolo (--h3 / --h4)
   ma testo di più righe. Nel Figma sarebbero a line-height 1 (come
   i titoli): --leading-prose gli dà un filo d'aria in più senza
   spalancare come il testo a 24px. La classe di layout (max-width,
   margini, colore) resta separata. */
.u-text-lg,
.u-text-md {
  line-height: var(--leading-prose);
  text-wrap: pretty;
}

/* Non --h3 (48->24): confermato due volte (intro home, statement
   Servizi) che questo stile scende solo a 32px su mobile, non 24.
   Valore dedicato, ancorato 480->1440 come il resto della scala. */
.u-text-lg { font-size: clamp(2rem, 1.6667vw + 1.5rem, 3rem); }
.u-text-md { font-size: var(--h4); }

/* Raggio dei pannelli con un angolo desktop piu' pronunciato (80px)
   di quello standard (--m-space, 40px): per ora solo .services, da
   estendere ad altre sezioni quando servira'. Ancorato 480->1440
   come il resto della scala: 30px mobile -> 80px desktop. */
.u-radius-panel-80 {
  border-radius: var(--radius-panel-80) var(--radius-panel-80) 0 0;
}

/* ============================================================
   UTILITY DI COMPONENTE — cta / pill
   ------------------------------------------------------------
   Hanno elementi e modificatori propri: sono piccoli componenti
   condivisi, non utility .u-* (REGOLE CSS: distinzione
   utility/componente).
   ============================================================ */
.cta {
  display: inline-flex;
  align-items: center;
  padding: 0.75rem 1.5rem; /* 12px/24px fisso come nel Figma, non fluido */
  font-size: var(--button-text);
  color: var(--color-surface);
  background-color: var(--color-secondary);
  border-radius: 50px;
  transition: transform 0.4s var(--ease-button);
}

/* --- hover dei bottoni: il pallino ------------------------------
   Stesso comportamento di clou.ch su TUTTI i bottoni: .cta (ogni
   link-bottone del sito) e il pulsante di invio di Fluent Forms
   (.fluentform button, stesso aspetto: vedi "FORM CONTATTI").

   Il pallino (--color-teal, cerchio da 16px) e' un ::before, quindi
   funziona anche sul <button> del plugin senza toccarne il markup.
   E' un elemento del flex: da fermo larghezza e margini sono 0; in
   hover crescono (16px + margini = 24px) e spingono il testo verso
   destra, mentre il pallino passa da scala 0 a 1. Con la curva
   --ease-button (leggero rimbalzo) la scritta "scatta" e si assesta.
   Il testo finisce a 48px dal bordo (24px di padding + 24px del
   pallino), come in clou.ch (padding-left 1.5rem -> 3rem); il
   margine sinistro negativo porta il pallino a 20px dal bordo.

   Pressione (:active): il bottone si rimpicciolisce a 0.9.
   Hover solo con puntatore vero (@media hover): sul touch resterebbe
   "incollato" dopo il tocco. Il focus da tastiera mostra lo stesso
   stato (:focus-visible). Con "riduci animazioni" lo stato cambia
   ma senza transizione. */
.cta::before,
.fluentform button::before {
  content: "";
  flex: none;
  width: 0;
  height: 1rem;
  margin-inline: 0;
  background-color: var(--color-teal);
  border-radius: 50%;
  opacity: 0;
  transform: scale(0);
  transition:
    width 0.4s var(--ease-button),
    margin 0.4s var(--ease-button),
    opacity 0.4s var(--ease-button),
    transform 0.4s var(--ease-button);
}

@media (hover: hover) {
  .cta:hover::before,
  .fluentform button:hover::before {
    width: 1rem;
    margin-inline: -0.25rem 0.75rem;
    opacity: 1;
    transform: scale(1);
  }
}

.cta:focus-visible::before,
.fluentform button:focus-visible::before {
  width: 1rem;
  margin-inline: -0.25rem 0.75rem;
  opacity: 1;
  transform: scale(1);
}

.cta:active,
.fluentform button:active {
  transform: scale(0.9);
}

@media (prefers-reduced-motion: reduce) {
  .cta,
  .cta::before {
    transition: none;
  }

  .fluentform button,
  .fluentform button::before {
    transition: none !important;
  }

  .cta:active,
  .fluentform button:active {
    transform: none;
  }
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px var(--xs-space);
  font-family: var(--font-mono);
  font-size: var(--pill-text);
  text-transform: uppercase;
  border: 1px solid var(--color-border);
  border-radius: 50px;
}

/* ============================================================
   ENTRY CONTENT — output di the_content()
   ------------------------------------------------------------
   Wrapper del contenuto editoriale generato dall'editor a blocchi
   (single del blog, CPT). E' L'UNICO posto dove i paragrafi e gli
   altri blocchi riprendono un margine verticale automatico: nel
   resto del sito p ha margin-block: 0 (vedi layer BASE).

   Owl selector "> * + *": spazia SOLO fra elementi consecutivi, il
   primo figlio non prende margine superiore. Prima di un titolo
   serve piu' aria.
   ============================================================ */
.entry-content > * + * {
  margin-block-start: var(--s-space);
}

.entry-content > * + :is(h2, h3, h4) {
  margin-block-start: var(--m-space);
}

/* ============================================================
   SITE HEADER
   ------------------------------------------------------------
   Struttura (header.php):
     <header class="site-masthead">  guscio semantico, contiene il
                                     nav.
       <div class="site-header">     position: fixed, sempre visibile.
       <nav class="site-nav">        overlay del menu, sorella di
                                     .site-header.

   .site-header e' position: fixed, fuori dal flusso: logo e hamburger
   galleggiano sul primo blocco, che parte dal bordo alto del viewport
   (l'hero tiene cosi' il suo 100dvh e l'origine della griglia
   parallax). Resta SEMPRE visibile e senza sfondo: non si ritrae
   scrollando (prima c'era headroom.js, tolto) e non ha pillola.

   Colore di logo e hamburger: qui il default per pagina — scuro; con
   body.is-dark-top (primo blocco scuro) chiaro. Lungo la pagina il
   colore segue la sezione che scorre sotto: lo fa il modulo
   header-contrast (functions.php, costante ELIDRIA_HEADER_CONTRAST),
   che sovrascrive queste due regole. Senza il modulo il colore resta
   quello di partenza per tutta la pagina.
   ============================================================ */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 20;
  /* Distanza dal bordo del viewport: stesso ritmo delle sezioni
     sotto. */
  padding-block: var(--s-space);
  padding-inline: var(--m-space);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--color-primary); /* colore di mark + icona hamburger */
  transition: color 0.3s ease;
}

/* Contenuti chiari: pagina con primo blocco scuro (body.is-dark-top). */
.is-dark-top .site-header__bar {
  color: var(--color-surface);
}

.site-header__logo {
  display: inline-flex;
  align-items: center;
}

.site-header__mark {
  display: block;
  width: auto;
  height: var(--logo-height);
}

.site-header__logo-img {
  width: auto;
  height: var(--logo-height);
}

/* Se il logo e' un'immagine (campo Opzioni) non si ricolora: su
   pagina con primo blocco scuro la si schiarisce con invert. Il
   modulo header-contrast la inverte poi sezione per sezione. */
.is-dark-top .site-header__logo-img {
  filter: invert(1);
}

.site-header__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Niente padding del <button> (UA: 1px 6px): l'icona riempie il
     bottone, quindi hamburger e X dell'overlay (stessa misura,
     .site-nav__close) coincidono al pixel. */
  padding: 0;
  color: inherit;
  cursor: pointer;
}

.site-header__toggle svg {
  width: var(--toggle-size);
  height: var(--toggle-size);
}

/* ============================================================
   SITE NAV — overlay del menu (le "pillole")
   ------------------------------------------------------------
   Riferimento Figma: nodo 177:2. Overlay a tutto schermo, fondo
   scuro; le voci sono pill grandi sparse a nido d'ape con una
   leggera rotazione, una in giallo (voce corrente).

   Sta dentro <header class="site-masthead"> come SORELLA di
   .site-header (non discendente): se .site-header avesse un transform
   o un filter intrapperebbe il position: fixed dell'overlay nel suo
   riquadro. .site-masthead e' un guscio senza stile e non deve mai
   ricevere transform/filter/perspective.

   Stato: [hidden] di default. Il JS toglie [hidden], forza un
   reflow e aggiunge .is-open -> l'overlay sfuma in dentro. Alla
   chiusura toglie .is-open e rimette [hidden] a transizione finita
   (o dopo un fallback a tempo).

   Disposizione: le voci hanno posizione e rotazione assegnate per
   indice con :nth-child. Non e' semantica, e' un ritmo visivo: se
   il menu cambia numero di voci, i valori oltre il 5 ricadono su
   "dritta, in colonna".
   ============================================================ */
.site-nav {
  position: fixed;
  inset: 0;
  z-index: 30;
  overflow-y: auto;
  background-color: var(--color-primary);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.site-nav.is-open {
  opacity: 1;
  visibility: visible;
}

.site-nav__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding-inline: var(--m-space);
}

.site-nav__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--s-space);
  color: var(--color-surface);
}

.site-nav__logo {
  display: inline-flex;
  align-items: center;
}

.site-nav__logo .site-header__mark {
  height: var(--logo-height);
}

.site-nav__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--toggle-size);
  height: var(--toggle-size);
  padding: 0;
  color: var(--color-primary);
  background-color: var(--color-surface);
  border-radius: 50%;
  cursor: pointer;
}

.site-nav__close svg {
  width: 50%;
  height: 50%;
}

/* Le voci: pill grandi. Su desktop sono disposte a nido d'ape con
   una rotazione; qui la base (colonna centrata), le variazioni per
   indice piu' sotto in @media (min-width: 769px). */
.site-nav__list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--m-space);
  padding-block: var(--xl-space) var(--l-space);
}

/* Il link: sia il fallback (a.site-nav__link) sia il markup WP
   (li.menu-item > a). */
.site-nav__list a {
  display: block;
  transition: transform 0.2s ease;
}

.site-nav__list a:hover,
.site-nav__list a:focus-visible {
  transform: scale(1.04);
}

/* Mobile: colonna a tutta larghezza, pill al 100%. Su desktop la
   griglia (min-width: 769px) ridefinisce larghezza e allineamento. */
.site-nav__list > li {
  width: 100%;
}

.site-nav__pill {
  width: 100%;
}

.site-nav__pill {
  /* Scollegata dal componente .pill (tag piccoli, mono, maiuscolo): la
     pillola del menu e' piu' grande e usa il font di titolo normale.
     display/align/justify centrano il testo dentro la forma, come
     faceva .pill. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1.5rem, 3vw, 3rem) clamp(2.5rem, 6vw, 6.5rem);
  font-size: clamp(2rem, 6vw, 3.75rem);
  line-height: 1.1;
  white-space: nowrap;
  color: var(--color-text);
  background-color: var(--color-surface);
  border: none;
  border-radius: 200px;
  /* Solo il colore: il transform e' di GSAP (crescita/chiusura). Una
     transition CSS su transform lo farebbe litigare a ogni frame. */
  transition: background-color 0.2s ease;
  will-change: transform;
}

/* Hover/focus: ogni pill prende il colore della sua POSIZIONE (Figma
   "open menu"): teal / giallo / viola / rosa / teal. E' un ritmo
   visivo, non un ruolo: stessa logica degli accenti delle card, per
   questo i nomi di colore. Il giallo del menu (#f4d32c) e' quello del
   Figma e differisce da --color-yellow (card progetto): resta locale
   qui, non tocca il token. Voce non prevista (6a in poi): ricade sul
   giallo. */
.site-nav__list > li:nth-child(1) .site-nav__pill { --pill-hover: var(--color-teal); }
.site-nav__list > li:nth-child(2) .site-nav__pill { --pill-hover: #f4d32c; }
.site-nav__list > li:nth-child(3) .site-nav__pill { --pill-hover: var(--color-violet); }
.site-nav__list > li:nth-child(4) .site-nav__pill { --pill-hover: var(--color-pink); }
.site-nav__list > li:nth-child(5) .site-nav__pill { --pill-hover: var(--color-teal); }

.site-nav__list a:hover .site-nav__pill,
.site-nav__list a:focus-visible .site-nav__pill {
  background-color: var(--pill-hover, #f4d32c);
}

/* Voce corrente: pill colorata anche senza hover, con lo stesso colore
   di posizione dell'hover (Home teal, Servizi giallo, ...). Copre sia il
   markup WP (.current-menu-item) sia il fallback PHP. */
.current-menu-item .site-nav__pill,
.site-nav__link[aria-current="page"] .site-nav__pill {
  background-color: var(--pill-hover, #f4d32c);
}

/* --- mobile: tutte le voci SEMPRE visibili ----------------------
   Il menu a colonna deve stare nell'altezza dello schermo, senza
   scorrere e senza tagliare l'ultima voce. L'inner prende l'altezza
   dell'overlay (fixed, inset 0); la lista riempie lo spazio sotto la
   barra e ancora le pill in fondo; ogni <li> parte da 5.5rem ma puo' restringersi
   (flex-shrink) se lo schermo e' basso. <li>, <a> e pill sono flex
   annidati: la pill si allunga a tutta l'altezza della sua voce e non
   resta la "strut" dell'interlinea sotto l'inline-flex. Sotto 22rem
   di altezza (telefono in orizzontale) l'inner smette di comprimere e
   l'overlay torna a scorrere, per non schiacciare il testo. */
@media (max-width: 768px) {
  .site-nav__inner {
    height: 100%;
    min-height: 22rem;
  }

  .site-nav__list {
    flex: 1 1 0;
    min-height: 0;
    /* Pill ancorate in fondo all'area visibile (il pollice ci arriva);
       lo spazio libero resta sopra, sotto la barra. */
    justify-content: flex-end;
    gap: var(--s-space);
    padding-block: var(--s-space)
      calc(var(--m-space) + env(safe-area-inset-bottom, 0px));
  }

  .site-nav__list > li {
    display: flex;
    flex: 0 1 5.5rem;
    min-height: 0;
  }

  .site-nav__list a {
    display: flex;
    flex: 1;
  }

  .site-nav__pill {
    padding-block: 0;
  }
}

/* --- desktop: nido d'ape con rotazioni -------------------------
   Riferimento Figma: nodo 177:2. Cinque pill su due righe, il gruppo
   centrato verticalmente nel pannello scuro.

   Riga 1: Home / Servizi / Progetti in fila, rotazioni lievi
           (-8.6 / +7 / +7 gradi come nel Figma).
   Riga 2: About e Contatti sfalsate DI MEZZA PILL negli spazi fra
           quelle di sopra (About fra Home e Servizi, Contatti fra
           Servizi e Progetti). Piccolo stacco verticale, NON si
           sovrappongono (Figma: ~17px di gap fra le righe).

   Griglia 6 colonne: ogni pill occupa 2 colonne.
   Riga 1: pill su colonne 1-2, 3-4, 5-6 (centri 1.5 / 3.5 / 5.5).
   Riga 2: pill su colonne 2-3 e 4-5 (centri 2.5 / 4.5) -> cadono
           ESATTAMENTE a meta' fra quelle di sopra.
   Le pill riempiono la cella (width: 100%), quindi lo stacco e' dato
   solo dai gap della griglia (--gap-tight): piccolo e positivo, le
   pill non si sovrappongono. */
@media (min-width: 769px) {
  .site-nav__list {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    align-content: center;
    justify-items: stretch;
    /* Gap piccoli e fissi: la pill riempie la cella, quindi lo stacco
       fra due pill e' solo questo (come nel BubbleMenu di React Bits),
       non cresce con lo schermo. */
    column-gap: var(--gap-tight);
    row-gap: var(--gap-tight);
    flex: 1; /* riempie l'altezza dell'inner -> align-content centra */
    width: 100%;
    /* Nessun max-width: il gruppo occupa tutta la larghezza dello
       schermo (meno il padding dell'inner). Il menu e' l'unica cosa che
       non si ferma ai 1440px. */
    padding-block: var(--l-space);
  }

  .site-nav__list > li {
    grid-column: span 2;
    width: auto;
  }

  .site-nav__list a {
    display: block;
  }

  /* La pill riempie la sua cella (2 colonne su 6): la larghezza la
     decide la griglia, non il testo. Il padding e' solo verticale (il
     testo e' centrato da inline-flex) ed e' in em: segue il font, cosi'
     l'altezza della pill resta proporzionata a ogni larghezza. Il font
     cresce con la larghezza dello schermo (4vw) insieme alle pill, che
     ora riempiono tutta la larghezza: tetto a 6rem per gli schermi
     molto larghi. */
  .site-nav__pill {
    width: 100%;
    padding: 1.2em 0;
    font-size: clamp(2rem, 4vw, 6rem);
  }

  /* Rotazioni per indice: vale sia per il markup WP (li.menu-item)
     sia per il fallback (li.site-nav__item). */
  .site-nav__list > li:nth-child(1) { transform: rotate(-8.6deg); }
  .site-nav__list > li:nth-child(2) { transform: rotate(7deg); }
  .site-nav__list > li:nth-child(3) { transform: rotate(7deg); }

  .site-nav__list > li:nth-child(4) {
    grid-column: 2 / span 2;
    transform: rotate(7deg);
  }
  .site-nav__list > li:nth-child(5) {
    grid-column: 4 / span 2;
    transform: rotate(-8.2deg);
  }
}

/* ============================================================
   HERO — griglia parallax controllata dal mouse
   ------------------------------------------------------------
   Ispirato a clou.ch. La griglia di miniature e' UN BLOCCO UNICO:
   al muoversi del mouse dentro la sezione si sposta tutta insieme,
   in direzione INVERSA al cursore (pana come una finestra su una
   scena ferma). Inerzia e calcolo dell'offset stanno in main.js.

   .hero            finestra ritagliata (overflow:hidden)
   .hero__parallax  scena centrata sul viewport, riceve il transform

   Ogni thumb e' ancorata al centro della scena (left/top 50% +
   transform per centrarla su se stessa) e spostata da li' con un
   OFFSET IN PX (proprieta' translate). Il centro-scena coincide col
   centro del viewport.

   DUE gruppi (le posizioni sono in px, ottimizzate per viewport
   1280-1920; oltre i ~1920 la scena si popola e tutte e 8 tendono
   a vedersi, il parallax diventa piu' effetto di profondita'):

   - thumb 1, 3, 5, 8: vicine al centro, VISIBILI in stato neutro
     (una per quadrante).
   - thumb 2, 4, 6, 7: agli angoli, FUORI CAMPO in stato neutro su
     laptop; entrano panando verso quel lato.

   Requisito: tutte e 8 raggiungibili al 100% panando. Il conto: una
   thumb col centro a `d` px dal centro, dopo un pan di OFFSET_MAX
   verso di lei ha il centro a (d - OFFSET_MAX) px dal centro
   viewport; rientra INTERAMENTE se
     d <= meta_viewport - meta_thumb + OFFSET_MAX
   Le thumb "fuori campo" stanno a ~790px dal centro: servono
   OFFSET_MAX ~550 (non 300) perche' rientrino tutte. --hero-bleed
   copre pan + sporgenza cosi' non si scopre mai lo sfondo vuoto.
   ============================================================ */
.hero {
  /* Quanto la scena sporge oltre ogni bordo del viewport, per non
     scoprire mai lo sfondo vuoto durante il pan (>= OFFSET_MAX +
     sporgenza della thumb piu' lontana: ~1270 + meta_thumb - meta_vp
     + 700). */
  --hero-bleed: 400px;

  /* Limiti di altezza delle thumb. Taglia base in dvh (scala con
     l'altezza dell'hero), clamp() la tiene in un intervallo fisso:
     sotto --thumb-min diventano illeggibili, sopra --thumb-max su
     schermi molto alti crescerebbero fino a sovrapporsi. */
  --thumb-min: 190px;
  --thumb-max: 280px;

  /* Spostamento corrente, aggiornato da main.js. Neutro = 0. */
  --hero-px: 0px;
  --hero-py: 0px;

  position: relative;
  width: 100%;

  /* Tutto schermo. dvh segue il viewport reale: su mobile la barra
     degli indirizzi si ritrae allo scroll, e con vh il contenuto
     verrebbe tagliato all'apertura.
     min-height, non height: la sezione puo' crescere se serve. */
  min-height: 100dvh;
  overflow: hidden;
  /* Non cambia il bleed del parallax: per un figlio position:absolute
     (.hero__parallax, .hero__graphic) il riferimento e' il padding-box
     del genitore, non il content-box — aggiungere padding qui non
     sposta ne' riduce l'area su cui si calcola --hero-bleed. */
  padding-inline: var(--m-space);
  padding-block-end: 3rem; /* 48px fisso, come nel Figma */
  background-color: var(--color-surface);
}

/* Fallback per browser senza dvh (Safari < 15.4, Firefox < 101). */
@supports not (min-height: 100dvh) {
  .hero {
    min-height: 100vh;
  }
}

/* La scena. Sporge di --hero-bleed su ogni lato (inset negativo) e
   riceve lo spostamento del parallax. will-change: transform
   perche' il valore cambia a ogni frame durante l'inerzia. */
.hero__parallax {
  position: absolute;
  inset: calc(-1 * var(--hero-bleed));
  translate: var(--hero-px) var(--hero-py);
  /* Su una hero piu' bassa di quella di riferimento (main.js,
     HERO_REF_HEIGHT) la scena si rimpicciolisce attorno al centro:
     stessa disposizione, in scala. translate resta fuori dalla scala. */
  scale: var(--hero-scale, 1);
  will-change: transform;
}

.hero__thumb {
  /* Ancorata al centro della scena (left/top 50%), poi:
     - transform: translate(-50%, -50%)  -> centra la thumb su se
       stessa, cosi' l'offset e' misurato dal SUO centro
     - translate: <dx> <dy>              -> offset in px dal centro
     Sono due proprieta' diverse e si sommano: separandole possiamo
     usare translate solo per la posizione, senza il limite di 3
     valori di una singola dichiarazione. */
  position: absolute;
  left: 50%;
  top: 50%;
  /* --fix-x/--fix-y: correzione anti-sovrapposizione impostata da
     main.js (spreadHeroThumbs) solo sulle thumb che si toccano;
     0 se non serve. */
  transform: translate(
    calc(-50% + var(--fix-x, 0px)),
    calc(-50% + var(--fix-y, 0px))
  );

  /* Nessun height/aspect-ratio: la misura e' quella dell'immagine. */
  width: auto;
  height: auto; /* proporzioni dell'immagine (max-width la limita) */
  max-width: var(--thumb-max-w, 400px);
  object-fit: cover;
}

/* Larghezza massima per slot: dispari 400px (base), pari 300px.
   --thumb-max-w e' impostata inline dal partial quando in admin si
   compila "Larghezza massima" della miniatura; altrimenti valgono
   questi default. */
.hero__thumb--2,
.hero__thumb--4,
.hero__thumb--6,
.hero__thumb--8,
.hero__thumb--10 {
  max-width: var(--thumb-max-w, 300px);
}

/* Thumb 5: tetto fisso a 350px. Anche se in admin si imposta una
   "Larghezza massima" maggiore (su staging e' 388px), non supera 350px;
   con un valore piu' piccolo vale quello. Su mobile vince comunque
   min(..., 40vw) (regola piu' specifica nel @media 768px), sempre sotto
   i 350px. */
.hero__thumb--5 {
  max-width: min(var(--thumb-max-w, 350px), 350px);
}

/* Offset in px dal centro-scena (centro della thumb). Tarate su
   viewport 1280-1920, non generate da una formula.

   Regola di composizione: dispari = GRANDE (400px), pari = PICCOLA
   (300px); ogni grande ha una piccola vicina e nessuna thumb ne tocca
   un'altra (stacco minimo ~40px). Le altezze indicative (immagini di
   1000px di larghezza, rapporti 0.49-0.73) sono quelle del contenuto
   attuale: se cambiano i rapporti delle foto, ricontrolla gli stacchi.

   Gruppo VISIBILE a riposo (1, 8, 3, 5): 8 (piccola) e' incastrata
   fra 1 e 3, 5 e' a sinistra con 6 accanto. Gruppo FUORI CAMPO
   (2, 6, 4, 7): entrano scorrendo lateralmente col pan (2 e 6 a
   sinistra, 4 e 7 a destra). 9 e 10 (extra) stanno ai margini alti.

   Vincolo: la scritta "elidria" (.hero__graphic) e' ancorata in
   basso: le thumb stanno nella meta' alta della scena e sconfinano
   solo leggermente nelle lettere. */
.hero__thumb--1 {
  translate: -200px -320px;
}

.hero__thumb--2 {
  translate: -900px -340px;
}

.hero__thumb--3 {
  translate: 620px -140px;
}

.hero__thumb--4 {
  translate: 1150px -250px;
}

.hero__thumb--5 {
  translate: -640px 0px;
}

.hero__thumb--6 {
  translate: -1030px 10px;
}

.hero__thumb--7 {
  translate: 1250px 0px;
}

.hero__thumb--8 {
  translate: 200px -260px;
}

/* Slot 9/10 (extra, oltre le 8 del design originale): 9 grande al
   margine sinistro alto, 10 piccola sopra la 3. Da verificare su
   schermo vero come gli altri. */
.hero__thumb--9 {
  translate: -1300px -330px;
}

.hero__thumb--10 {
  translate: 720px -390px;
}

/* Il lettering. Grande quanto tutto lo schermo (100vw): centrato
   orizzontalmente, ma non piu' verticalmente come prima — ancorato
   al 75.2% dell'altezza dell'hero (non al 50%). z-index perche' sta
   DAVANTI alle miniature. NON e' dentro .hero__parallax: resta fermo
   mentre la griglia pana.

   filter: brightness(0) — l'asset SVG e' esportato da Figma con
   fill #ECECEC (regola sbagliata: in Figma stava su una plancia
   scura). Servito come <img> il fill non e' raggiungibile da CSS;
   brightness(0) porta qualsiasi tinta a nero pieno, che e' il
   colore voluto sull'hero chiaro. Vale SOLO per l'<img> caricata in
   admin: il lettering SVG inline (hero.php) ha gia' il suo
   riempimento, var(--color-primary) = #1e1e1e come nel file del
   rebranding, e il filtro lo annullerebbe (nero #000): vedi la regola
   svg.hero__graphic piu' sotto. */
.hero__graphic {
  position: absolute;
  left: 50%;
  /* Ancorata dal basso (non centrata con top/translate-Y): la sua
     altezza segue la larghezza (height:auto), quindi centrarla
     verticalmente la farebbe sbordare nel padding-bottom quando
     cresce. bottom = stesso valore del padding-block-end di .hero,
     cosi' il margine di 48px sotto la scritta resta garantito
     qualunque sia la sua altezza. */
  bottom: 3rem;
  z-index: 1;
  /* 100% qui e' la larghezza del padding-box di .hero (piena, non
     ridotta dal SUO padding-inline: solo i figli in flusso normale
     ne risentono). Va tolto a mano per restare dentro al margine
     40px->24px della sezione invece di sbordare fino al bordo vero. */
  width: calc(100% - 2 * var(--m-space));
  height: auto;
  filter: brightness(0);
  pointer-events: none;
  translate: -50% 0;
}

/* Lettering SVG inline: tiene il suo colore (#1e1e1e), niente filtro. */
svg.hero__graphic {
  filter: none;
}

/* Reduced motion: niente parallax. La griglia resta in posizione
   neutra e il listener in main.js non viene agganciato. */
@media (prefers-reduced-motion: reduce) {
  .hero__parallax {
    translate: none;
    will-change: auto;
  }

  /* Header e overlay del menu: nessuna transizione. Il colore del
     logo cambia di colpo; l'overlay appare/sparisce di colpo (il JS
     gestisce [hidden] senza attendere transitionend). */
  .site-header__bar,
  .site-header__logo,
  .site-nav,
  .site-nav__pill {
    transition: none;
  }
}

/* --- mobile: il tocco pana la scena, 10 thumb -------------------
   Sotto 768px il parallax e' guidato dal TOCCO (main.js, come su
   clou.ch): un tap o l'inizio di uno scorrimento sposta la scena in
   direzione inversa al punto toccato, fino a HERO_TOUCH_PAN del
   viewport per asse (main.js). Le posizioni px tarate per 1280-1920
   non hanno piu' senso: le thumb si ridispongono con offset in vw/vh
   dal centro scena (riferimento Figma mobile 390px).

   Disposizione ricalcata da clou.ch (immagini sfalsate, non a
   corona), con meno strada fra una e l'altra perche' ne abbiamo 10
   e non 15:
   - 1-4 e 7: in vista a riposo. 1 e 3 sono TAGLIATE dal bordo sinistro
     e destro (come su clou), 2 in alto a destra, 4 sopra il lettering,
     7 sotto la 3 (anch'essa tagliata a destra).
   - 5-6, 8-10: fuori campo (o appena sporgenti) a riposo; entrano
     toccando dal lato corrispondente: 6 e 9 in alto, 8 a sinistra,
     5 e 10 in basso. main.js non le riporta dentro (vedi `out`).
   La scena non deve sporgere: --hero-bleed a 0 evita spazio morto
   scrollabile. */
@media (max-width: 768px) {
  .hero {
    --hero-bleed: 0px;
    --thumb-min: 96px;
    --thumb-max: 168px;
  }

  /* Lettering piu' vicino al bordo basso (base: 3rem). */
  .hero__graphic {
    bottom: 1.5rem;
  }

  /* Tutte della stessa larghezza (40vw, ~156px a 390), come su clou.ch;
     l'altezza segue il rapporto di ogni foto. Una "Larghezza massima"
     piu' stretta impostata in admin vince (min). Il resto lo riassesta
     spreadHeroThumbs (main.js) sulle misure reali. `.hero .hero__thumb`
     (0,2,0) batte le regole max-width di base, dispari e pari. */
  .hero .hero__thumb {
    max-width: min(var(--thumb-max-w, 100vw), 40vw);
  }

  .hero__thumb--1 {
    translate: -47vw -12vh;
  }

  .hero__thumb--2 {
    translate: 30vw -35vh;
  }

  .hero__thumb--3 {
    translate: 50vw -8vh;
  }

  .hero__thumb--4 {
    translate: -14vw 22vh;
  }

  /* 5 e 9 scambiate di posto: la 5 sta in basso a destra, la 9 in alto
     a sinistra (prima il contrario). */
  .hero__thumb--5 {
    translate: 40vw 66vh;
  }

  .hero__thumb--6 {
    translate: 10vw -68vh;
  }

  /* 7 in vista a riposo: sotto la 3 (BBS, tagliata a destra), nello
     spazio vuoto a destra della 4. Stacco ~40px da 3 e da 4, tagliata
     dal bordo destro come la 3. */
  .hero__thumb--7 {
    translate: 37vw 18vh;
  }

  .hero__thumb--8 {
    translate: -72vw 38vh;
  }

  .hero__thumb--9 {
    translate: -46vw -62vh;
  }

  .hero__thumb--10 {
    translate: -38vw 70vh;
  }
}

/* --- mobile: apertura delle foto (come clou.ch) -----------------
   Ogni foto parte a scala .5 e trasparente e arriva a 1 con un piccolo
   rimbalzo (cubic-bezier = easeOutBack, come "back.out" di GSAP su clou:
   0.75s). L'ordine e' sparso: ritardi diversi per thumb, distribuiti su
   ~1s. Si anima `scale` (proprieta' separata): il centraggio sta in
   `transform` e la posizione in `translate`, quindi non c'e' conflitto.

   Le classi le mette main.js: .hero--intro nasconde le foto (opacity 0,
   NON altera le misure di spreadHeroThumbs) e .is-intro-in fa partire
   l'animazione dopo il caricamento. Senza JS le foto restano visibili;
   con prefers-reduced-motion le classi non vengono messe. */
@media (max-width: 768px) {
  .hero--intro .hero__thumb {
    opacity: 0;
  }

  .hero--intro.is-intro-in .hero__thumb {
    animation: hero-thumb-pop 0.75s cubic-bezier(0.34, 1.56, 0.64, 1) both;
    animation-delay: var(--pop-delay, 0s);
  }

  .hero__thumb--1  { --pop-delay: 0.45s; }
  .hero__thumb--2  { --pop-delay: 0.8s; }
  .hero__thumb--3  { --pop-delay: 0.15s; }
  .hero__thumb--4  { --pop-delay: 0.95s; }
  .hero__thumb--5  { --pop-delay: 0.6s; }
  .hero__thumb--6  { --pop-delay: 0.3s; }
  .hero__thumb--7  { --pop-delay: 0.7s; }
  .hero__thumb--8  { --pop-delay: 0.05s; }
  .hero__thumb--9  { --pop-delay: 0.85s; }
  .hero__thumb--10 { --pop-delay: 0.5s; }
}

@keyframes hero-thumb-pop {
  from {
    opacity: 0;
    scale: 0.5;
  }

  to {
    opacity: 1;
    scale: 1;
  }
}

/* ============================================================
   INTRO
   ============================================================ */
.intro {
  /* Sovrappone la sezione successiva (Work) di 40px: senza questo
     margine negativo l'angolo arrotondato di Work non ha nulla da
     "tagliare" sotto di se' (lo sfondo pagina e' dello stesso colore
     chiaro di Work) e la giunzione sembra un bordo dritto. Valore
     fisso come nel Figma, non legato a --m-space fluido. */
  margin-bottom: -2.5rem;
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

/* Riquadro che contiene titolo e corpo: colonna, con il corpo a
   destra (align-items: flex-end). Dai laptop in su ha un max-width e
   sta al centro (vedi @media 1024px): titolo e corpo restano vincolati
   allo stesso riquadro, invece di posizionarsi ognuno per conto suo. */
.intro__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--l-space);
}

/* Statement: titolo di sezione (rilevanza SEO), font da titolo ma
   testo di più righe. Layout qui; corpo/interlinea da .u-text-lg
   (uniforme anche quando il markup è <p>). */
.intro__statement,
.servizi-teaser__lead {
  width: 100%;
  font-weight: 400;
  /* Righe che si riempiono normalmente fino al max-width: niente
     bilanciamento. Il reset da' balance a tutti gli h2 e .u-text-lg lo
     batte con pretty; qui si azzera entrambi, solo per questo titolo.
     .servizi-teaser__lead e' trattato come lo statement dell'intro:
     stesse regole, qui e nei @media sotto. */
  text-wrap: wrap;
}

.intro__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stack-48);
  max-width: 42.28%; /* 575/1360 nel Figma: proporzionale, non fisso */
}

/* La CTA si dimensiona sul testo (inline-flex + align-items:flex-start
   del contenitore). max-width come rete di sicurezza se il testo del
   link e' lungo: va a capo invece di sforare la colonna. */
.intro__cta {
  max-width: 100%;
}

.intro__description {
  font-size: var(--body);
}

/* --- mobile: tutto a piena larghezza, allineato a sinistra -----
   Su desktop .intro__body galleggia a destra (align-items:flex-end
   sulla sezione). Nel Figma mobile e' un'unica colonna a sinistra. */
@media (max-width: 768px) {
  .intro__inner {
    /* Gap invariato (--l-space, gia' fluido): il Figma mobile tiene
       56px fra testo e blocco CTA, quasi come su desktop. */
    align-items: stretch;
  }

  .intro__body {
    /* Gap invariato (--stack-48, fisso): 48px anche nel Figma mobile. */
    max-width: 100%;
  }
}

/* --- laptop in su: composizione "a gradini" (come la reference) -----
   Titolo e corpo stanno in UN riquadro (.intro__inner) con max-width,
   centrato: il titolo parte dal suo bordo sinistro, il corpo (42% del
   riquadro, come nel Figma) si allinea al suo bordo destro, con piu'
   aria fra i due. Il max-width (80rem = 1280px) e' poco piu' largo di quello della reference (~1180px):
   oltre, la composizione non si allarga piu' con lo schermo. Misure
   della reference: titolo 14% -> 64%, corpo 52% -> 78%, gap ~135px.
   Tra 769px e 1023px resta il layout di prima (riquadro a tutta
   larghezza). */
@media (min-width: 1024px) {
  .intro__inner {
    gap: calc(var(--l-space) * 1.6);
  }

  /* Riquadro: stessa larghezza e stesso centraggio per l'intro e per la
     vetrina Servizi della home (.servizi-teaser__inner). Il gap verticale
     resta proprio di ciascuno. */
  .intro__inner,
  .servizi-teaser__inner {
    width: 100%;
    max-width: 80rem;
    margin-inline: auto;
  }

  /* Titolo: non oltre il 75% del riquadro, attaccato a sinistra
     (margin-right: auto: il riquadro ha align-items: flex-end, che
     altrimenti lo porterebbe a destra). */
  .intro__statement {
    max-width: 75%;
    margin-right: auto;
  }

  /* Testo di Servizi: non oltre il 70% del riquadro, attaccato a
     sinistra (stesso motivo: .servizi-teaser__inner ha align-items:
     flex-end). Vale a tutte le larghezze da 1024px, anche sopra i
     2200px: li' non c'e' una regola propria. */
  .servizi-teaser__lead {
    max-width: 70%;
    margin-right: auto;
  }
}

/* Schermi grandi / display Retina (es. Mac Studio, ~2560px CSS): il
   riquadro si allarga a 100rem (1600px) e il titolo scende al 65% del
   riquadro (resta a sinistra grazie al margin-right: auto del blocco
   sopra). Soglia 2200px: sotto, il layout da laptop/desktop resta
   quello sopra. */
@media (min-width: 2200px) {
  .intro__inner,
  .servizi-teaser__inner {
    max-width: 100rem;
  }

  /* Solo lo statement dell'intro. Il testo di Servizi
     (.servizi-teaser__lead) tiene il suo 70% del blocco da 1024px. */
  .intro__statement {
    max-width: 65%;
  }
}

/* ============================================================
   WORK — progetti: STACKING DELLE CARD (metodo clou.ch, misurato)
   ------------------------------------------------------------
   Quattro livelli annidati:

     .work-item          height: --work-card-run  (la "corsa" di scroll)
       .work-item__frame  height: --work-card-run, margin-block-end
                          negativo: sovrappone le corse
         .work-item__sticky  position: sticky; top: --work-stack-top
                             height: --work-card-window (la "finestra")
                             overflow: visible
           .work-item__card  il contenuto vero: altezza naturale,
                             sfondo colore, raggio in alto. Piu' alto
                             della finestra -> sborda sotto, e la carta
                             successiva (sfondo opaco) lo copre.

   La finestra (sticky) e' piu' bassa del frame: cosi' ha un tratto
   di scroll in cui restare ancorata mentre la carta dopo sale. La
   carta interna sborda liberamente (nessun overflow: clip): il
   cerchio si vede INTERO, viene coperto dalla carta sopra o —
   all'ultima — tagliato dal bordo del viewport, come su clou.ch.

   SPROFONDAMENTO — GSAP (assets/js/main.js): mentre la carta dopo
   sale, la corrente scala 1 -> ~0.9 e opacity 1 -> ~0.5 (scrub).
   Senza JS / reduced-motion: si impilano lo stesso, senza scala.
   ============================================================ */
.work {
  /* Punto di ancoraggio delle card: sotto l'header (--header-height,
     sempre visibile) piu' una distanza, come nella reference (la card
     non si attacca all'header: lascia aria). La distanza e' il knob:
     qui --l-space (80px a 1440, fluido), piu' stretta negli schermi
     piccoli (vedi i @media sotto). In calc(): il JS non la legge piu'
     da questa variabile ma dal `top` calcolato dello sticky. */
  --work-stack-top: calc(var(--header-height) + var(--l-space));

  /* Finestra sticky: poco piu' di un viewport meno header. Titolo e
     tag in alto sempre visibili; l'illustrazione dentro .work-item__card
     puo' sbordare (la finestra non taglia). */
  --work-card-window: /*calc(100svh - var(--work-stack-top) - var(--l-space));*/ 100svh;

  /* Corsa di scroll di ogni carta: quanto a lungo resta ancorata.
     Deve superare l'overlap di un buon margine, cosi' quando la
     carta dopo la raggiunge lei e' ancora incollata (e coperta) e
     si sgancia solo dopo, dietro le quinte. */
  --work-card-run: 260svh;

  /* Distanza di scroll tra una carta e la successiva. */
  --work-card-overlap: 100svh;

  /* Sovrappone la sezione successiva (Servizi/vetrina, o Contatti se
     quel layout non e' in pagina) di 40px, stesso motivo di .intro
     qui sopra: rivela lo sfondo sotto l'angolo arrotondato invece di
     lasciare una giunzione dritta. */
  margin-bottom: -2.5rem;
  padding-block: var(--l-space) 0;
  background-color: var(--color-surface);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

.work__intro {
  display: flex;
  flex-direction: column;
  gap: var(--stack-48);
  max-width: 42.28%; /* 575/1360 nel Figma: proporzionale, non fisso */
  margin-bottom: var(--l-space);
}

.work__badge {
  align-self: flex-start;
  border-color: var(--color-text);
}

.work__description {
  font-size: var(--body);
}

.work__list {
  display: flex;
  flex-direction: column;
}

/* --- livello 1: contenitore --------------------------------
   NIENTE altezza qui: l'altezza effettiva del <li> la determina
   il frame (height - margine negativo = --work-card-overlap). Se
   mettessi height anche qui, il <li> successivo partirebbe una
   corsa intera sotto invece di un solo overlap, e la carta N si
   vedrebbe uscire dall'alto proprio mentre la N+1 arriva. */
.work-item {
  position: relative;
}

/* --- livello 2: la corsa + la sovrapposizione --------------
   height = --work-card-run: box entro cui lo sticky si incolla.
   margin negativo = (overlap - run): il contenuto successivo
   risale, cosi' il <li> dopo occupa solo --work-card-overlap e
   la carta N+1 raggiunge il top mentre la N e' ancora ancorata
   (e gia' coperta). */
.work-item__frame {
  height: var(--work-card-run);
  margin-block-end: calc(var(--work-card-overlap) - var(--work-card-run));
}

/* L'ultima "carta" (blocco CTA "Esplora tutti i progetti") E' parte
   della pila: si ancora e sprofonda come le altre. A salirle sopra e
   coprirla e' la sezione Contatti (trigger GSAP in main.js).

   Nessuna regola dedicata: eredita height/margin/sticky dalla regola
   generale .work-item__frame (margin = overlap - run), quindi il suo
   <li> occupa --work-card-overlap come una card qualsiasi e i
   Contatti lo coprono nello stesso modo. La card colorata riempie
   la finestra (min-height: 100%): sotto la CTA c'e' sfondo colore
   fino al bordo dello sticky, poi arrivano i Contatti — nessun
   tratto di sfondo pagina scoperto. */

/* --- livello 3: la finestra che si incolla ------------------
   height FISSA (piu' bassa del frame -> ha spazio per restare
   ferma). overflow VISIBLE: la carta interna sborda, il cerchio
   si vede intero. transform-origin al centro per lo scale GSAP. */
.work-item__sticky {
  position: sticky;
  top: var(--work-stack-top);

  height: var(--work-card-window);

  transform-origin: center center;
}

/* --- livello 4: il contenuto ------------------------------
   min-height 100% riempie la finestra; se il contenuto e' piu'
   alto la card cresce e sborda sotto lo sticky (overflow visible):
   sara' coperta dalla carta successiva. */
.work-item__card {
  position: relative; /* ancora del link esteso (.work-item__link::after) */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: 100%;
  padding: var(--stack-32);
  color: var(--color-text);
  background-color: var(--color-surface);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

.work-item--teal .work-item__card {
  background-color: var(--color-teal);
}

.work-item--violet .work-item__card {
  background-color: var(--color-violet);
}

.work-item--pink .work-item__card {
  background-color: var(--color-pink);
}

.work-item--yellow .work-item__card {
  background-color: var(--color-yellow);
}

/* Titolo + tag: non si comprime, resta visibile in alto anche
   quando la finestra sticky e' bassa. */
.work-item__head {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: var(--s-space);
  /* 575/1296 nel Figma: la base e' il contenuto di .work-item__card,
     gia' ridotto dal suo padding fisso (--stack-32), non i 1360 di
     .work direttamente. */
  max-width: 44.37%;
}

.work-item__title {
  font-size: var(--h4);
  font-weight:400;
}

/* Tutta la card e' cliccabile: il link e' il titolo (testo accessibile
   e semantica corretta), il ::after lo stira su .work-item__card. La
   card coperta dalla successiva non riceve click: sopra di lei sta la
   carta che la copre. */
.work-item__link {
  color: inherit;
  text-decoration: none;
}

.work-item__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

.work-item__link:focus-visible {
  outline: none;
}

.work-item__link:focus-visible::after {
  outline: 2px solid currentColor;
  outline-offset: -0.5rem;
}

.work-item__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--xs-space);
}

.work-item__tag {
  font-family: var(--font-mono);
  text-transform: uppercase;
  border-color: var(--color-text);
}

/* Area dell'illustrazione: centra il cerchio orizzontalmente. */
.work-item__visual-wrap {
  align-self: stretch;
  display: grid;
  place-items: center;
}

/* Cerchio: dimensione legata al viewport (i file sono disegnati
   molto piu' grandi del necessario). Largo quanto la card, ma con un
   tetto di 850px (il Figma) che cresce in proporzione solo sugli
   schermi molto larghi (Retina, ~2560px): max(53.125rem, 44.27vw),
   dove 44.27vw = 850/1920. 850px fino a 1920px, poi in proporzione
   (~1133px a 2560px). Sotto, il tetto non agisce: il cerchio e' largo
   quanto la card.
   SEMPRE quadrato e INTERO: nessun overflow: clip lo taglia. Se la
   carta supera il viewport e' il fondo pagina a nasconderne una parte,
   come su clou.ch. */
.work-item__visual {
  width: clamp(25svh, 100%, max(53.125rem, 44.27vw));
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
}

/* Desktop: testa e cerchio nella STESSA cella di una griglia. La card
   (tranne il blocco CTA finale, che non ha il cerchio) diventa una
   griglia a una cella; il cerchio e' spinto in basso da un margine, cosi'
   parte a 156px dal bordo alto della card come nel Figma (a 1440px;
   max(9.75rem, 8.125vw): fisso fino a 1920px, poi in proporzione come il
   cerchio) e la testa (titolo + tag, ~120px) gli sta sopra. Se il
   margine si riducesse, la testa si sovrapporrebbe al cerchio:
   z-index funziona sui figli di una griglia anche senza
   position, quindi la testa NON diventa il blocco contenitore del link
   esteso (.work-item__link::after, che resta ancorato a .work-item__card).
   Su schermi stretti resta la colonna (il cerchio riempie la larghezza
   e il titolo sopra la foto non si leggerebbe). */
@media (min-width: 769px) {
  .work-item__card:not(.work__more) {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
  }

  .work-item__card:not(.work__more) > .work-item__head {
    grid-area: 1 / 1;
    align-self: start;
    justify-self: start;
    z-index: 1;
  }

  .work-item__card:not(.work__more) > .work-item__visual-wrap {
    grid-area: 1 / 1;
    align-self: start;
    /* Distanza cerchio dal bordo alto della card: 156px (Figma) meno il
       padding della card (--stack-32), che gia' c'e'. */
    margin-block-start: calc(max(9.75rem, 8.125vw) - var(--stack-32));
  }
}

/* --- ultimo blocco: "Esplora tutti i progetti" ---------------
   Non e' una carta della pila: scorre normale (regole in cima,
   .work-item--more). Solo colore e spaziatura qui. */
.work__more {
  gap: var(--stack-48);
  color: var(--color-surface);
  background-color: var(--color-primary);
}

/* Testo del blocco CTA finale — layout. Corpo/interlinea: .u-text-md. */
.work__more-text {
  /* Stessa base di .work-item__head: dentro .work-item__card. */
  max-width: 44.37%;
}

/* Badge + testo introduttivo: gap piu' stretto su mobile (24px nel
   Figma, contro 48px di --stack-48 su desktop). */
@media (max-width: 768px) {
  .work__intro {
    gap: 1.5rem;
    max-width: 100%;
  }

  /* Card piu' larghe e piu' "piene" (come la reference): il margine
     laterale scende da --m-space (24px) a 16px con un margine
     negativo (m-space - 16px: 8px a 390, ~13px a 768), e il padding
     interno a 16px. Il titolo "PROGETTI COSTRUITI INSIEME" sopra resta
     sul margine di pagina. */
  .work-item {
    margin-inline: calc(1rem - var(--m-space));
  }

  .work-item__card {
    padding: 1rem; /* 16px: nessun token --stack-16 */
  }

  /* Piu' aria attorno al cerchio: ~56px sopra (dai tag) e ~44px sotto
     (+ 16px di padding = ~60px dal fondo della card). */
  .work-item__visual-wrap {
    margin-block: 3.5rem 2.75rem;
  }

  .work-item__head,
  .work__more-text {
    max-width: 100%;
  }
}

/* --- mobile/tablet: stesso stacking, geometria ridotta ---------
   L'effetto (ancoraggio sticky + sprofondamento GSAP) resta a ogni
   larghezza: cambiano solo le variabili --work-*. Su schermo stretto
   la card e' piu' bassa (cerchio piu' piccolo, header compatto) e
   l'header sovrapposto e' meno alto: la finestra e le corse si
   accorciano di conseguenza. La regola d'oro (run >> overlap) va
   preservata perche' le card si sgancino solo dopo essere coperte. */
@media (max-width: 992px) {
  .work {
    --work-stack-top: calc(var(--header-height) + var(--m-space));
    /* La finestra segue lo stack-top ridotto: senza questa riga
       resterebbe 100svh e sforerebbe il viewport di 72px sotto. */
    --work-card-window: calc(100svh - var(--work-stack-top));
    --work-card-run: 220svh;
    --work-card-overlap: 90svh;
  }
}

/* Schermo molto stretto: card bassa (niente illustrazione grande),
   header compatto. Finestra a 55svh (valore verificato a schermo):
   piu' bassa dello stack-top consente allo sticky di restare
   interamente nel viewport. run alzato a ~2.4x overlap: sotto quel
   rapporto una card puo' sganciarsi (uscire dall'alto) prima di
   essere coperta dalla successiva -> titolo che scappa in alto. */
@media (max-width: 480px) {
  .work {
    --work-stack-top: calc(var(--header-height) + var(--s-space));
    /* Card INTERA visibile prima che arrivi la successiva, senza
       spazio vuoto fra le due: l'overlap (distanza fra le card) e'
       uguale all'altezza della finestra/card (100svh - stack-top), cosi'
       la successiva e' a contatto col fondo della card appena questa si
       ferma. (Prima 54svh: copriva il cerchio; poi 100svh: lasciava uno
       spazio bianco di ~stack-top sotto la card.) La finestra eredita lo
       stesso calc dal @media 992px; la corsa e' ~2.5x l'overlap: sotto
       quel rapporto una card si sgancia prima di essere coperta.

       In piu' si toglie il raggio dell'angolo (--radius-panel-40): la
       successiva ha gli angoli alti arrotondati, e se partisse
       esattamente dal fondo della card negli angoli si vedrebbe lo
       sfondo della pagina. Cosi' parte --radius-panel-40 PIU' IN ALTO,
       appoggiata sul fondo (vuoto) della card, e gli angoli si
       sovrappongono al verde. Il fondo coperto e' il padding+margine
       sotto il cerchio (~60px), piu' dei ~30px di raggio. */
    --work-card-run: 250svh;
    --work-card-overlap: calc(100svh - var(--work-stack-top) - var(--radius-panel-40));
  }
}

/* ============================================================
   SERVIZI-TEASER — home, layout Flexible "servizi-teaser"
   ------------------------------------------------------------
   Riferimento Figma: nodo 1594:3457.

   Pannello grigio chiaro fra Progetti e Contatti: titolo, testo
   introduttivo, pulsante verso /servizi. Stessa struttura di .elidri
   (About, "Gli elidri"): fondo var(--color-hairline) — e' lo stesso
   grigio #d4d4d4 del Figma, non serve un token nuovo — angoli
   arrotondati e aggancio sopra/sotto con margine negativo.
   ============================================================ */
.servizi-teaser {
  position: relative;
  z-index: 1; /* sopra la pila di card di Work, che resta sticky sotto */
  /* Sovrappone Contatti di 40px, stesso motivo di .work qui sopra. */
  margin-bottom: -2.5rem;
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-text);
  background-color: var(--color-hairline);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

/* Riquadro interno: colonna, pulsante a destra, come .intro__inner.
   Larghezza massima e centraggio (dai laptop in su) sono condivisi con
   .intro__inner nei @media dell'INTRO. */
.servizi-teaser__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--l-space);
}

.servizi-teaser__title {
  width: 100%;
  font-size: var(--h2);
  font-weight: 400;
}

/* Pulsante sotto il testo, a sinistra: il riquadro ha align-items:
   flex-end (come .intro__inner, per il suo corpo a destra), che
   lascerebbe il pulsante isolato all'estremo opposto del testo. */
.servizi-teaser__cta {
  align-self: flex-start;
}

/* .servizi-teaser__lead: trattato come .intro__statement. Le regole
   (width, peso, text-wrap, max-width 75% / 65%) sono raggruppate con
   quelle dell'intro; corpo e interlinea da .u-text-lg nel markup. */

/* ============================================================
   CONTACT
   ============================================================ */
.contact {
  position: relative;
  z-index: 1; /* sopra la pila di card di Work, che resta sticky sotto */
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
}

.contact__title {
  margin-bottom: var(--l-space);
  font-size: var(--h2); /* 96px come nel Figma (desk/H2), non --h1 */
  font-weight: 400;
}

.contact__lead {
  max-width: 31.4%; /* 427/1360 nel Figma */
  margin-bottom: var(--l-space);
  font-size: var(--body);
  margin-left:auto;
}

/* ============================================================
   CONTACT-PAGE — pagina /contatti (layout Flexible "contatti")
   ------------------------------------------------------------
   Riferimento Figma: 781:1445 (desktop), 790:2069 (mobile).

   Un solo pannello scuro arrotondato, primo blocco della pagina:
   stessa impostazione di .contact (home) e .services. L'header e'
   assoluto e ci galleggia sopra: il padding superiore gli lascia
   spazio, il logo e' invertito da body.is-dark-top.

   Titolo grande a sinistra; testo introduttivo e modulo in colonna
   a destra (il modulo eredita .fluentform, condiviso con la home).
   ============================================================ */
.contact-page {
  position: relative;
  z-index: 1;
  /* L'header e' position:fixed e galleggia sopra questo blocco (non
     c'e' una hero sotto come su Servizi/About): senza aggiungere la
     sua altezza, il gap dei 80px/56px (--l-space) sparisce sotto la
     barra invece di stare fra la barra e il titolo. */
  padding-block: calc(var(--header-height) + var(--l-space)) var(--xl-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  /* Sovrappone il Footer di 40px, come nel Figma (mb:-40 su questo
     blocco). Stesso colore su entrambi: invisibile, ma coerente. */
  margin-bottom: -2.5rem;
}

.contact-page__title {
  max-width: 20ch;
  margin-bottom: var(--l-space);
  /* Non --h3 (48->24): come .u-text-lg, questo stile scende solo a
     32px su mobile (confermato anche qui, Figma mob/h2 32px). */
  font-size: clamp(2rem, 1.6667vw + 1.5rem, 3rem);
  font-weight: 400;
  text-wrap: balance;
}

/* Typewriter (classe messa dal JS): il titolo diventa una griglia a
   una cella. Il testo vivo e i "fantasmi" invisibili (uno per
   variante, creati dal JS) occupano la stessa cella: l'altezza e'
   quella della variante piu' lunga, a ogni larghezza, quindi niente
   salti del modulo sotto mentre si scrive.

   Il testo vivo contiene SEMPRE la frase intera: la parte scritta e'
   visibile, il resto (.contact-page__rest) e' li' ma invisibile. Cosi'
   le righe sono quelle definitive fin dalla prima lettera: nessuna
   riga che compare a meta', nessuna parola che salta a capo mentre
   si scrive. text-wrap:balance (ereditato dal titolo) puo' restare:
   si calcola sulla frase intera, che non cambia mentre si scrive. */
.contact-page__title.is-typewriter {
  display: grid;
}

.contact-page__line,
.contact-page__ghost {
  grid-area: 1 / 1;
}

.contact-page__ghost {
  visibility: hidden;
}

.contact-page__rest {
  visibility: hidden;
}

/* cursore "|": fermo mentre si scrive, lampeggia a riposo. Larghezza
   zero: la barra e' disegnata ma non sposta il testo (invisibile) che
   la segue, altrimenti a fine riga potrebbe farlo andare a capo. */
.contact-page__caret {
  display: inline-block;
  width: 0;
  overflow: visible;
  font-weight: 300;
  animation: contact-caret-blink 1s steps(1) infinite;
}

.contact-page__title.is-typing .contact-page__caret {
  animation: none;
}

@keyframes contact-caret-blink {
  0%,
  49% { opacity: 1; }
  50%,
  100% { opacity: 0; }
}

.contact-page__lead {
  max-width: 31.4%; /* 427/1360 nel Figma */
  margin-bottom: var(--l-space);
  margin-left: auto;
  font-size: var(--body);
}

/* --- mobile: tutto a piena larghezza ---------------------------- */
@media (max-width: 768px) {
  /* padding-block, margin-bottom di titolo/lead invariati (--l-space
     / --xl-space, gia' fluidi): il Figma mobile tiene 56/150px, non
     lo stretto --m-space. */

  .contact-page__title,
  .contact-page__lead {
    max-width: 100%;
  }
}

/* ============================================================
   FORM CONTATTI — Fluent Forms
   ------------------------------------------------------------
   Il markup e le classi (.ff-*) sono del plugin: qui il tema le
   sovrascrive. Gli !important servono perche' il CSS di Fluent
   Forms e' caricato dopo questo file e con selettori piu'
   specifici (eccezione dichiarata, REGOLE CSS/CSS_EXCEPTIONS:
   override di plugin di terze parti).

   Il pulsante di invio ha lo stesso hover delle altre CTA (il
   pallino che compare a sinistra: vedi "hover dei bottoni" sotto
   .cta). Nessuna freccia.

   Selettore .fluentform: classe stabile del plugin sul <form>.
   ============================================================ */
.fluentform {
  display: flex;
  flex-direction: column;
  gap: var(--stack-32);
  max-width: 65.66%; /* 893/1360 nel Figma */
  margin-left: auto;
}

/* Il plugin porta il proprio font su elementi che i selettori
   mirati qui sotto non toccano (checkbox, errori, descrizioni,
   ecc.): un tetto largo forza Geist ovunque, poi le eccezioni
   (etichette in Geist Mono) vincono per specificita'. */
.fluentform,
.fluentform * {
  font-family: var(--font-body) !important;
}

.fluentform label {
  font-family: var(--font-mono) !important;
  font-size: var(--tag-text);
  text-transform: uppercase;
}

/* L'asterisco dei campi obbligatori: il plugin lo tinge di rosso,
   qui segue il colore del testo (bianco su fondo scuro). */
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-right label::after {
  color: currentColor !important;
}

.fluentform .ff-el-group {
  margin-bottom: 1.5rem !important;
}

.fluentform :is(input, textarea) {
  width: 100%;
  padding: var(--s-space) var(--m-space);
  font-family: var(--font-body);
  font-size: var(--body);
  color: var(--color-surface) !important;
  background-color: transparent !important;
  border: none !important;
  border-bottom: 2px solid var(--color-muted) !important;
  border-radius: 0 !important;
  padding-left:0 !important;
  padding-right:0 !important;
}

.fluentform textarea {
  min-height: 10rem !important;
  resize: vertical !important;
}

.fluentform :is(input, textarea)::placeholder {
  color: var(--color-muted);
}

/* Pulsante di invio: inline-flex (il pallino dell'hover e' un
   elemento del flex, vedi "hover dei bottoni" sotto .cta). */
.fluentform button {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  align-self: flex-start;
  min-width: 15.875rem;
  padding: 0.75rem 1.5rem !important;
  color: var(--color-text) !important;
  background-color: var(--color-surface) !important;
  border-radius: 50px !important;
  margin-top:1.5rem !important;
  margin-bottom: 0 !important;
  transition: transform 0.4s var(--ease-button) !important; /* il plugin ha la sua */
}

/* --- Messaggio di conferma: popup ---------------------------------
   Il popup e' quello NATIVO di Fluent Forms: a invio riuscito il plugin
   inserisce dopo il modulo <div class="ff-message-success"
   role="status"> col testo della conferma. Il tema lo disegna e basta:
   nessun JS decide quando appare. La X (Lucide) e' aggiunta da main.js
   solo per chiuderlo; senza JS il messaggio resta, come nativo.

   TESTO E COMPORTAMENTO si impostano in Fluent Forms: Impostazioni →
   Impostazioni di conferma → "Messaggio da mostrare" e "Dopo l'invio
   del modulo" → "Modulo di ripristino". Il primo blocco del messaggio
   (un titolo o un paragrafo) e' il titolo; gli altri sono il testo; un
   messaggio di un solo blocco e' tutto testo.

   Misure dal Figma (400 di larghezza): padding 32 / 56, gap 24, angoli
   10, titolo Geist 32 (interlinea normal), testo 16 largo 231 (va a
   capo da solo), colore #f4f4f4, nessun velo. Il riquadro e' centrato
   sul modulo (.fluentform e' position: relative). La larghezza e'
   proporzionale al viewport (400/1440 = 27.78vw, fra 280px e 533px) e
   padding, gap, titolo e testo sono frazioni di --popup-w, quindi il
   riquadro scala per intero; titolo e testo hanno un minimo leggibile
   (22px / 14px).
   !important perche' il CSS del plugin e' caricato dopo (stessa
   eccezione dichiarata del resto della sezione). */
.fluentform {
  position: relative;
}

.fluentform .ff-message-success {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  --popup-w: clamp(17.5rem, 27.7778vw, 33.3333rem); /* 400/1440 del viewport */

  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: calc(var(--popup-w) * 0.06);
  align-items: center;
  width: min(var(--popup-w), 100%);
  margin: 0 !important;
  padding: calc(var(--popup-w) * 0.08) calc(var(--popup-w) * 0.14) !important;
  font-size: max(0.875rem, var(--popup-w) * 0.04) !important;
  font-weight: 400 !important;
  line-height: normal !important;
  color: #f4f4f4 !important;
  text-align: center;
  background-color: var(--color-teal) !important;
  border: 0 !important;
  border-radius: 10px !important;
  transform: translate(-50%, -50%);
}

/* tutti i blocchi del messaggio: testo (la misura del testo arriva
   dal Figma: 231px, due righe) */
.fluentform .ff-message-success > :not(.ff-message-close) {
  max-width: calc(var(--popup-w) * 0.5775); /* 231/400 */
  margin: 0 !important;
  font-size: inherit !important;
  font-weight: inherit !important;
  line-height: inherit !important;
  color: inherit !important;
}

/* il primo blocco e' il titolo, se dopo ce ne sono altri (X esclusa) */
.fluentform .ff-message-success > :first-child:nth-last-child(n+3) {
  max-width: none;
  font-size: max(1.375rem, var(--popup-w) * 0.08) !important;
  text-wrap: balance;
}

/* X di chiusura (Lucide, inserita da main.js): solo l'icona, bianca,
   in alto a destra. Non e' un bottone del sito: azzera tutto cio' che
   `.fluentform button` (pillola chiara, pallino hover, scala al click)
   le darebbe, da qui gli !important. */
.fluentform .ff-message-close {
  position: absolute;
  top: calc(var(--popup-w) * 0.04);
  right: calc(var(--popup-w) * 0.04);
  display: block !important;
  min-width: 0;
  padding: 0 !important;
  margin: 0 !important;
  color: inherit !important;
  cursor: pointer;
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  transition: none !important;
}

.fluentform .ff-message-close::before {
  content: none;
}

.fluentform .ff-message-close:active {
  transform: none;
}

.fluentform .ff-message-close svg {
  display: block;
  width: 1.5rem;
  height: 1.5rem;
}

.fluentform .ff-message-close:focus-visible {
  outline: 2px solid currentcolor;
  outline-offset: 2px;
}

/* --- Consenso privacy (GDPR) --------------------------------------
   Campo "GDPR Agreement" di Fluent Forms: <label class="ff_tc_label">
   con la casella dentro .ff_tc_checkbox e il testo in .ff_t_c. Le
   regole generali del modulo (label in mono maiuscolo, input a linea)
   non vanno bene qui: testo normale in Geist e casella quadrata con
   spunta Lucide. */
.fluentform .ff-el-tc label.ff_tc_label {
  display: flex !important; /* il plugin lo mette a table-row */
  gap: 0.75rem;
  align-items: center;
  font-family: var(--font-body) !important;
  font-size: 1rem;
  text-transform: none;
  cursor: pointer;
}

/* casella e testo erano table-cell con padding del plugin: qui sono
   due elementi del flex, distanziati dal gap */
.fluentform .ff-el-tc label.ff_tc_label.ff_tc_label > :is(span, div) {
  display: block !important;
  width: auto;
  padding: 0 !important;
}

.fluentform .ff_tc_checkbox {
  flex: none;
}

.fluentform .ff_tc_checkbox input {
  display: block;
  width: 1.5rem !important;
  height: 1.5rem;
  padding: 0 !important;
  margin: 0;
  appearance: none;
  cursor: pointer;
  background-color: transparent !important;
  background-position: center;
  background-repeat: no-repeat;
  background-size: 1rem;
  border: 2px solid var(--color-surface) !important;
  border-radius: 0.25rem !important;
}

.fluentform .ff_tc_checkbox input:checked {
  background-color: var(--color-teal) !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231e1e1e' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  border-color: var(--color-teal) !important;
}

.fluentform .ff_tc_checkbox input:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.fluentform .ff_t_c {
  line-height: 1.5;
  color: var(--color-surface);
}

.fluentform .ff_t_c a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* --- mobile: form a piena larghezza ----------------------------- */
@media (max-width: 768px) {
  .fluentform {
    max-width: 100%;
  }
}

/* --- mobile: lead a piena larghezza --------------------------- */
@media (max-width: 768px) {
  .contact__title {
    margin-bottom: var(--m-space);
  }

  .contact__lead {
    max-width: 100%;
    margin-bottom: var(--m-space);
  }
}

/* ============================================================
   SITE FOOTER
   ============================================================  */
.site-footer {
  /* Le sezioni prima del footer (.elidri, .services, .origini, ecc.)
     sono position:relative + z-index:1: senza un proprio stacking
     context il footer (altrimenti static) dipinge SOTTO di loro,
     quindi la sezione precedente lo copre nella zona di overlap
     invece di lasciarne vedere l'angolo arrotondato sopra. */
  position: relative;
  z-index: 2;
  padding-block: var(--l-space) var(--m-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  border-radius: var(--radius-panel-40) var(--radius-panel-40) 0 0;
  /* Sovrappone la sezione precedente esattamente quanto il raggio:
     senza, l'angolo taglia nel vuoto e rivela lo sfondo chiaro della
     pagina invece dello scuro (stesso meccanismo di .origini/.elidri). */
  margin-block-start: calc(-1 * var(--radius-panel-40));
}

/* Home e Contatti: il blocco prima del footer e' dello stesso colore
   scuro (rispettivamente .contact e .contact-page, quest'ultima gia'
   marcata is-dark-through). L'angolo arrotondato e la sovrapposizione
   non servono li' (nessuno sfondo chiaro da nascondere) — restano
   dritti, senza margine di sovrapposizione. */
body.home .site-footer,
body.is-dark-through .site-footer {
  border-radius: 0;
  margin-block-start: 0;
}

.site-footer__top {
  display: flex;
  justify-content: space-between;
  gap: var(--l-space);
  margin-bottom: var(--l-space);
}

.site-footer__about {
  max-width: 48.97%; /* 666/1360 nel Figma */
}

.site-footer__status {
  display: block; /* frase di stato sulla prima riga, la fissa sotto */
}

.site-footer__copyright {
  margin-bottom: var(--s-space);
  font-weight: 700;
}

.site-footer__contacts {
  width:100%;
  max-width: 23.53%; /* 320/1360 nel Figma */
}

.site-footer__contacts-title {
  margin-bottom: var(--s-space);
  font-weight: 700;
}

.site-footer__rows {
  display: flex;
  flex-direction: column;
  gap: var(--xs-space);
}

.site-footer__row {
  padding-bottom: var(--xs-space);
  font-family: var(--font-mono);
  font-size: var(--button-text);
  font-weight:300;
  text-transform: uppercase;
  border-bottom: 1px solid var(--color-surface);
}

/* Link "Assistenza" nella barra in fondo (.site-footer__legal): chiave
   inglese + etichetta. Tipografia ereditata dalla barra (mono, maiuscolo,
   --tag-text); colore = quello del footer (--color-surface, il bianco
   del sito): l'icona segue currentColor. Icona piccola, in em: segue
   il corpo del testo (12px) e resta proporzionata. */
.site-footer__support {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-tight);
}

.site-footer__support svg {
  flex-shrink: 0;
  width: 1.25em;
  height: 1.25em;
}

/* Il lettering "elidria" a tutta larghezza. display:block + height:auto
   perche' un SVG con preserveAspectRatio="none" (o senza dimensioni
   intrinseche) altrimenti collassa a 0 dentro un <img> inline. */
.site-footer__graphic {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: var(--l-space);
}

/* I fori delle lettere e / d / a sono <circle> scuri a se': seguono il
   puntatore (blocco "footer eyes" in main.js, che scrive --eye-dx /
   --eye-dy in unita' del viewBox). La transizione ammorbidisce
   l'inseguimento; con prefers-reduced-motion il JS non gira e i fori
   restano al centro della lettera. */
.site-footer__eye,
.hero__eye {
  transform: translate(var(--eye-dx, 0), var(--eye-dy, 0));
  transition: transform 0.04s linear;
}

@media (prefers-reduced-motion: reduce) {
  .site-footer__eye,
  .hero__eye {
    transition: none;
  }
}

/* --- touch: gli occhi "guardano in giro" da soli ---------------
   Su touch non c'e' un puntatore da seguire e il JS non parte (vedi
   main.js: solo con (pointer: fine)). Qui l'equivalente in CSS puro:
   un @keyframes a ciclo, la stessa animazione su tutti e tre i fori
   di hero e footer, quindi si muovono INSIEME come col mouse.

   Condizione = il COMPLEMENTO di quella del JS (pointer: coarse), cosi'
   i due non si sovrappongono mai. Con prefers-reduced-motion restano
   fermi al centro.

   --eye-run: corsa massima in unita' del viewBox, la stessa di
   data-eye-run (66: footer e hero hanno lo stesso viewBox). Ogni
   posizione del ciclo e' una frazione di --eye-run con modulo < 1,
   cosi' il bordo scuro del foro non sbordi dalla lettera.
   Versione "vivace": sguardi rapidi con piccole pause. */
@media (pointer: coarse) and (prefers-reduced-motion: no-preference) {
  .site-footer__eye,
  .hero__eye {
    --eye-run: 66;

    animation: eye-look 5s ease-in-out infinite;
    transition: none;
  }
}

@keyframes eye-look {
  0%, 6%   { transform: translate(0, 0); }
  12%, 22% { transform: translate(calc(var(--eye-run) * 0.9px), calc(var(--eye-run) * -0.3px)); }
  28%, 38% { transform: translate(calc(var(--eye-run) * -0.9px), calc(var(--eye-run) * 0.15px)); }
  44%, 50% { transform: translate(0, 0); }
  56%, 64% { transform: translate(calc(var(--eye-run) * -0.55px), calc(var(--eye-run) * -0.65px)); }
  70%, 78% { transform: translate(calc(var(--eye-run) * 0.65px), calc(var(--eye-run) * 0.6px)); }
  84%, 100% { transform: translate(0, 0); }
}

/* Barra in fondo: cinque voci, ognuna 1/5 della larghezza, ognuna
   centrata nel proprio quinto. I centri sono a distanza uguale e il
   terzo quinto e' il centro esatto della barra (li' cade "Assistenza").
   minmax(0, 1fr): le colonne restano uguali anche se un testo e' lungo
   (con 1fr semplice il contenuto potrebbe allargarne una). */
.site-footer__legal {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: center;
  justify-items: center;
  gap: var(--s-space);
  font-family: var(--font-mono);
  font-size: var(--tag-text);
  text-align: center;
  text-transform: uppercase;
}

.site-footer__legal-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--xs-space);
}

/* Prima voce a filo del bordo sinistro, ultima a filo del destro; le tre
   centrali restano centrate nel loro quinto (justify-items: center sul
   contenitore, justify-self sulle due voci d'estremita'). Solo desktop:
   su mobile la barra e' una pila a sinistra. */
@media (min-width: 769px) {
  .site-footer__legal > :first-child {
    justify-self: start;
    text-align: start;
  }

  .site-footer__legal > :last-child {
    justify-self: end;
    text-align: end;
  }
}

/* --- mobile: blocchi in colonna --------------------------------
   __top (about | contatti) e __legal (copyright | link) sono righe
   con space-between su desktop; nel Figma mobile vanno in colonna. */
@media (max-width: 768px) {
  .site-footer__top {
    /* gap/margin-bottom invariati (--l-space, gia' fluido): il Figma
       mobile tiene ~56px, non lo stretto --m-space. */
    flex-direction: column;
  }

  .site-footer__about,
  .site-footer__contacts {
    max-width: 100%;
  }

  /* In colonna: la griglia a cinque quinti diventa una pila, a sinistra. */
  .site-footer__legal {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--xs-space);
    text-align: left;
  }

  .site-footer__legal-links {
    justify-content: flex-start;
  }
}

/* ============================================================
   SERVIZI — pagina /servizi (layout Flexible "servizi")
   ------------------------------------------------------------
   Riferimento Figma: 767:558 (desktop), 306:1024 (mobile).

   Due parti:
     .services-hero  finestra con l'immagine in evidenza della
                     pagina. Nessun parallax: immagine ferma,
                     l'header (assoluto) ci galleggia sopra come
                     sull'hero della home.
     .services       pannello scuro arrotondato, stessa impostazione
                     di .intro / .contact. Contiene la dichiarazione
                     e l'elenco dei servizi a due colonne.

   L'elenco (.services__grid): a sinistra i titoli (.services__list),
   a destra il pannello di dettaglio del servizio attivo
   (.services__panel dentro la voce .is-active). Il pannello di ogni
   altra voce e' hidden e viene mostrato dal JS al click; su schermo
   stretto il pannello attivo scende sotto la sua voce (grid a una
   colonna, panel in flusso).
   ============================================================ */
.services-hero {
  position: relative;

  /* Sotto l'header assoluto. L'immagine riempie; il pannello scuro
     che segue risale di --m-space per infilarsi sotto i suoi angoli. */
  width: 100%;
  min-height: 100svh;
  overflow: hidden;
  background-color: var(--color-surface);
}

@supports not (min-height: 100svh) {
  .services-hero {
    min-height: 100vh;
  }
}

.services-hero__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.services {
  position: relative;
  z-index: 1;
  /* Sovrappone la sezione successiva (es. "Parliamone") di 40px,
     stesso motivo di .intro / .work: senza, gli angoli arrotondati
     della sezione dopo non hanno nulla di scuro da "tagliare" sotto
     di se' e si vede lo sfondo chiaro della pagina. Se .services e'
     l'ultimo blocco della pagina (nessuna sezione dopo) il margine
     e' innocuo: non c'e' nulla sotto da sovrapporre. */
  margin-bottom: -2.5rem;
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  /* border-radius: classe .u-radius-panel-80 nel markup (80px
     desktop -> 30px mobile, diverso dal --m-space standard). */
}

/* Il pannello risale sotto gli angoli arrotondati dell'hero. Solo
   quando l'hero c'e': se manca l'immagine in evidenza, .services e'
   il primo blocco e non deve sovrapporsi all'header. */
.services-hero + .services {
  margin-block-start: calc(-1 * var(--m-space));
}

/* --- intro: dichiarazione a sinistra, descrizione a destra ------ */
.services__intro {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--l-space);
  padding-block-end: var(--stack-48); /* 48px fisso, uguale nel Figma a ogni schermo */
  border-block-end: 0.5px solid var(--color-hairline);
  /* Gap mancante fra questo blocco e l'elenco servizi sotto (.services
     non e' flex, quindi non puo' darlo da solo): 80px desktop / 56px
     mobile nel Figma, uguale a --l-space gia' anacorato. */
  margin-block-end: var(--l-space);
}

/* Dichiarazione d'apertura — layout. Corpo/interlinea: .u-text-md. */
.services__statement {
  max-width: 42.28%; /* 575/1360 nel Figma */
  font-weight: 400;
}

.services__description {
  max-width: 39.34%; /* 535/1360 nel Figma */
  font-size: var(--body);
}

/* --- sopracciglio dell'elenco --------------------------------- */
.services__eyebrow {
  padding-block: var(--l-space);
  font-family: var(--font-mono);
  font-size: var(--tag-text);
  text-transform: uppercase;
}

/* --- voci (colonna sinistra) + pannello attivo (colonna destra) --
   .services__grid contiene, alternati, .services__item e
   .services__panel (ogni pannello segue la sua voce nel DOM).

   Desktop: le voci scorrono normalmente in una colonna larga max
   575px. Il pannello dell'unico servizio attivo e' tolto dal flusso
   (position: absolute) e appoggiato in alto a destra, dentro
   .services__grid (position: relative). Assoluto = non partecipa
   all'altezza delle voci: la colonna sinistra tiene la sua
   spaziatura naturale, qualunque sia l'altezza del pannello.

   I pannelli non attivi hanno [hidden] -> display:none.

   Mobile (piu' sotto): il pannello torna in flusso (position:
   static) e scorre sotto la sua voce. */
.services__grid {
  position: relative;
  max-width: 100%;
}

.services__item {
  border-block-end: 0.5px solid var(--color-hairline);
  max-width: 42.28%; /* 575/1360 nel Figma */
}

.services__item:first-of-type {
  border-block-start: 0.5px solid var(--color-hairline);
}

/* Riga cliccabile: numero + titolo. Bottone a piena larghezza,
   testo a sinistra, cursore a mano. */
.services__trigger {
  display: flex;
  align-items: center;
  gap: var(--s-space);
  width: 100%;
  padding-block: var(--l-space);
  color: inherit;
  text-align: start;
  cursor: pointer;
}

.services__number {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--tag-text);
  text-transform: uppercase;
}

.services__title {
  /* 64px desktop -> 48px mobile: valore specifico di questo elenco
     (Figma "desk/H3 64px"), fuori dalla scala H1-H4 del sito.
     Ancorato 480->1440 come gli altri token fluidi. */
  font-size: clamp(3rem, 1.6667vw + 2.5rem, 4rem);
  font-weight: 400;
  line-height: var(--leading-tight);

  /* Parola piu' larga della riga (es. "accompagnamento" a 48px su un
     telefono): min-width 0 perche' e' figlio flex (senza, la
     larghezza minima e' quella della parola e sborda dal bottone);
     overflow-wrap la spezza se serve. Niente hyphens: auto (tolto): la
     parola non viene sillabata, va a capo solo quando non ci sta. */
  min-width: 0;
  overflow-wrap: break-word;
}

.services__item.is-active .services__title {
  color: var(--color-teal);
}

/* --- pannello di dettaglio ----------------------------------- */
.services__panel {
  /* Fuori dal flusso: ancorato in alto a destra di .services__grid.
     left calcolato dalla larghezza della griglia + un gutter, cosi'
     il pannello occupa lo spazio a destra della colonna delle voci.
     Non tocca l'altezza delle voci. */
  position: absolute;
  right:0;
  top: 0;
  width: 37.65%; /* 512/1360 nel Figma */
  display: flex;
  flex-direction: column;
  /* 24px mobile -> 48px desktop nel Figma, non --m-space (24->40).
     Ancorato 480->1440 come il resto della scala. */
  gap: clamp(1.5rem, 2.5vw + 0.75rem, 3rem);
}

.services__panel[hidden] {
  display: none;
}

.services__panel-visual-wrap {
  display: flex;
}

.services__panel-visual {
  /* 304px mobile -> 400px desktop, ancorato 480->1440 come il resto
     della scala: un solo clamp continuo, niente override mobile. */
  width: clamp(19rem, 10vw + 16rem, 25rem);
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
}

.services__panel-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--tag-text);
  text-transform: uppercase;
}

.services__panel-body {
  font-size: var(--body);
}

.services__panel-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-space); /* 16->24 nel Figma, non --xs-space (8->16) */
}

.services__panel-tag {
  font-family: var(--font-mono);
  text-transform: uppercase;
  border-color: var(--color-surface);
}

/* --- mobile: una colonna, pannello in flusso sotto la voce -----
   Sotto 768px l'elenco e il pannello non stanno affiancati: la
   griglia e' a piena larghezza e ogni pannello attivo torna in
   flusso (position: static) subito sotto la sua voce, come nel
   Figma mobile. */
@media (max-width: 768px) {
  .services__intro {
    /* gap invariato (--l-space, gia' fluido): il Figma mobile tiene
       56px fra statement e descrizione, non lo stretto --m-space. */
    flex-direction: column;
  }

  .services__statement,
  .services__description,
  .services__item {
    max-width: 100%;
  }

  /* Voce attiva: niente bordo (ne' proprio ne' di first-of-type),
     il pannello segue subito sotto senza una linea in mezzo. */
  .services__item.is-active,
  .services__item.is-active:first-of-type {
    border-block-end: none;
    border-block-start: none;
  }

  /* padding-block invariato (--l-space, gia' fluido, ~56px):
     il Figma mobile tiene lo stesso respiro py-56 del desktop
     per eyebrow e righe servizio, non lo stretto --m-space. */

  .services__grid {
    max-width: 100%;
  }

  .services__panel {
    position: static;
    width: 100%;
    padding-block-end: var(--m-space);
  }
}

/* ============================================================
   ARCHIVIO PROGETTI — /progetti/ e /servizio/<slug>/
   ------------------------------------------------------------
   Riferimento Figma: nodo 523:1872. Fondo chiaro (--color-surface),
   header scuro di default. Dall'alto:
     .projects-archive__head    titolo grande + testo introduttivo
                                allineato a destra della colonna
                                (come .intro / .contact-page__lead).
     .projects-archive__filters label "Filtri" + le pill dei facet
                                di WP Grid Builder (.pill riusata).
     .projects-archive__grid    due colonne di .project-card, gap
                                --s-space in orizzontale, --l-space
                                fra le righe (Figma: 24 / 80px).
     .projects-archive__pagination

   Il markup del blocco condiviso e' in
   template-parts/component/projects-archive.php.
   ============================================================ */
.projects-archive {
  /* L'header e' position:fixed e galleggia sopra questo blocco (primo
     della pagina, nessuna hero sotto): serve la sua altezza reale in
     aggiunta al gap di 80px/56px, come su .contact-page. */
  padding-block: calc(var(--header-height) + var(--l-space)) var(--xl-space);
  background-color: var(--color-surface);
}

.projects-archive__head {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--l-space);
  margin-bottom: var(--l-space);
}

/* Titolo di pagina: nel Figma e' grande a piena larghezza,
   interlinea stretta. --h1 fluido arriva a 9.75rem (156px) come nel
   design. */
.projects-archive__title {
  width: 100%;
  font-size: var(--h1);
  font-weight: 400;
  text-wrap: pretty;
}

/* Testo introduttivo: colonna a destra, come .intro__body /
   .contact-page__lead. */
.projects-archive__intro {
  max-width: 50.59%; /* 688/1360 nel Figma: proporzionale, non fisso */
  font-size: var(--body); /* 24px/36 a desktop, come nel Figma */
}

.projects-archive__filters {
  display: flex;
  flex-direction: column;
  gap: var(--s-space);
  margin-bottom: var(--l-space);
}

/* Desktop: 80px fissi (Figma). --l-space e' fluido e oltre i 1440px
   cresce (92px a 1920, 108px a 2560): qui non deve. */
@media (min-width: 769px) {
  .projects-archive__filters {
    margin-bottom: 5rem;
  }
}

.projects-archive__filters-label {
  font-size: var(--button-text);
}

/* Filtri dell'archivio Progetti — facet "Buttons" di WP Grid Builder,
   resi come le pill del Figma (nodo 523:2112).

   WPGB rende: .wpgb-facet > fieldset > .wpgb-button-facet >
   ul.wpgb-inline-list > li > .wpgb-button[role=button] >
   .wpgb-button-label (con uno <span> per il contatore).

   Il grosso della resa (raggio, spessore e colore del bordo, colore
   della pill attiva) passa dalle CUSTOM PROPERTIES del plugin:
   ridefinite qui sul .wpgb-facet vincono senza guerre di specificita'
   ne' !important. Il resto (padding, tipografia) sta su selettori
   allineati a quelli del plugin. */
.projects-archive__facets {
  display: flex;
  flex-wrap: wrap;
  gap: var(--xs-space);
}

.projects-archive__facets .wpgb-facet {
  /* pill: bordo 1px, angoli tondi, accento = nero del sito */
  --wpgb-border-radius: 50px;
  --wpgb-border-width: 1px;
  --wpgb-grey-500: var(--color-border);
  --wpgb-accent-scheme-1: var(--color-primary);

  width: 100%;
}

/* fieldset e lista: contenitori trasparenti, le pill vanno a capo. */
.projects-archive__facets .wpgb-facet fieldset {
  margin: 0;
  padding: 0;
  border: 0;
}

/* Il plugin mette `.wpgb-facet > fieldset:last-child { margin-bottom:
   40px }` (facets.css): a parita' di specificita' con la regola qui
   sopra vince chi e' caricato dopo. Il distacco dalla griglia lo da'
   .projects-archive__filters (margin-bottom --l-space), non il facet. */
.projects-archive__facets .wpgb-facet > fieldset:last-child {
  margin-bottom: 0;
}

.projects-archive__facets .wpgb-button-facet {
  flex-direction: row;
}

.projects-archive__facets .wpgb-inline-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--xs-space);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* La singola pill. Selettore allineato a `.wpgb-facet ul .wpgb-button`
   del plugin (stessa specificita' + una classe): vince. */
.projects-archive__facets .wpgb-facet ul .wpgb-button {
  justify-content: center;
  padding: 4px var(--xs-space);
  color: var(--color-primary);
  background-color: transparent;
  transition: color 0.2s ease, background-color 0.2s ease;
}

.projects-archive__facets .wpgb-facet ul .wpgb-button:hover {
  color: var(--color-surface);
  background-color: var(--color-primary);
}

/* Filtro attivo: pill piena, come .current della paginazione. */
.projects-archive__facets .wpgb-facet ul .wpgb-button[aria-pressed="true"] {
  color: var(--color-surface);
  background-color: var(--color-primary);
}

.projects-archive__facets .wpgb-facet ul .wpgb-button:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Etichetta: stessa misura delle pill dei tag delle card (.pill):
   Geist Mono maiuscolo a --pill-text (12px, 10px su mobile), stessa
   interlinea (--leading-text, 1.5, quella che .pill eredita dal body) e
   stesso padding della pill (lo da' il bottone), cosi' filtro e tag
   delle card hanno la stessa altezza. Il plugin la forza a
   16px / line-height 26px / padding 0 8px con `.wpgb-facet
   .wpgb-button-label` (0,2,0) caricato DOPO main.css: qui il selettore
   ha la classe in piu' (0,3,0) per vincere a prescindere dall'ordine. */
.projects-archive__facets .wpgb-facet .wpgb-button-label {
  flex: 0 0 auto;
  padding: 0;
  font-family: var(--font-mono);
  font-size: var(--pill-text);
  line-height: var(--leading-text);
  text-transform: uppercase;
}

/* Il contatore fra parentesi: piu' leggero. */
.projects-archive__facets .wpgb-button-label span {
  opacity: 0.6;
}

@media (prefers-reduced-motion: reduce) {
  .projects-archive__facets .wpgb-facet ul .wpgb-button {
    transition: none;
  }
}

/* Due colonne. gap orizzontale piu' stretto del verticale, come nel
   Figma (24 / 80px): row-gap sulla scala --l-space. */
.projects-archive__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: var(--s-space);
  row-gap: var(--l-space);
}

.projects-archive__pagination {
  display: flex;
  justify-content: center;
  margin-block-start: var(--l-space);
  font-size: var(--button-text);
}

.projects-archive__pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.5rem;
  padding: var(--gap-tight) var(--xs-space);
  border: 1px solid var(--color-border);
  border-radius: 50px;
}

.projects-archive__pagination .page-numbers.current {
  color: var(--color-surface);
  background-color: var(--color-primary);
}

.projects-archive__empty {
  font-size: var(--body);
}

/* --- la card ------------------------------------------------------ */
.project-card {
  /* nessuna altezza propria: la definisce l'immagine + il corpo */
}

.project-card__link {
  display: flex;
  flex-direction: column;
  gap: var(--s-space);

  & img {
    /* zoom morbido all'hover del link */
    transition: transform 0.4s ease;
  }

  &:hover img,
  &:focus-visible img {
    transform: scale(1.03);
  }
}

/* Cornice dell'immagine: rapporto ~668x445 del Figma, angoli 15px,
   ritaglia lo zoom. */
.project-card__visual-wrap {
  display: block;
  overflow: hidden;
  aspect-ratio: 668 / 445;
  border-radius: 15px;
}

.project-card__visual {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Archivio progetti (come clou.ch): all'hover o col focus da tastiera
   gli angoli dell'immagine si arrotondano fino a pillola (50rem, oltre
   meta' del lato corto: il browser lo limita alla pillola). Solo
   nell'archivio: la stessa card negli "ultimi progetti" resta a 15px. */
.projects-archive .project-card__visual-wrap {
  transition: border-radius 0.6s var(--ease-button);
}

@media (hover: hover) {
  .projects-archive .project-card__link:hover .project-card__visual-wrap {
    border-radius: 50rem;
  }
}

.projects-archive .project-card__link:focus-visible .project-card__visual-wrap {
  border-radius: 50rem;
}

.project-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-space);
}

/* Titolo card: Figma "desk/H5 32px". --h4 fluido arriva a 2rem (32px). */
.project-card__title {
  font-size: var(--h4);
  font-weight: 400;
  line-height: var(--leading-tight);
}

.project-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--xs-space);
}

/* --- mobile: una colonna, titolo piu' contenuto ----------------- */
@media (max-width: 768px) {
  /* .projects-archive padding-block invariato (--header-height +
     --l-space / --xl-space, gia' fluidi): stesso bug ricorrente,
     --m-space stringeva sia il distacco dall'header sia il fondo. */

  /* gap e margin-bottom di .projects-archive__head restano --l-space
     (come desktop): qui cambia solo l'allineamento. */
  .projects-archive__head {
    align-items: stretch;
  }

  .projects-archive__intro {
    max-width: 100%;
  }

  .projects-archive__grid {
    grid-template-columns: 1fr;
    row-gap: var(--l-space);
  }
}

/* Riduci animazioni: niente zoom sull'immagine. */
@media (prefers-reduced-motion: reduce) {
  .project-card__link img {
    transition: none;
  }

  .project-card__link:hover img,
  .project-card__link:focus-visible img {
    transform: none;
  }

  /* gli angoli cambiano all'hover, ma senza transizione */
  .projects-archive .project-card__visual-wrap {
    transition: none;
  }
}

/* ============================================================
   SCHEDA PROGETTO — /progetti/<slug>/
   ------------------------------------------------------------
   Riferimento Figma: nodo 540:1007 (apertura + corpo), nodo
   1002:1471 ("ultimi progetti"). Markup: single-progetto.php +
   template-parts/flexible/project-*.php + component/latest-projects.php.

   Dall'alto:
     .project-lede    pannello colorato pieno (colore libero per
                      progetto, color picker "lede_color" /
                      "lede_text_color" in style inline): titolo + pill
                      dei servizi + descrizione breve. body.is-dark-top
                      (functions.php) inverte il logo dell'header, che
                      ci galleggia sopra. Niente immagine in evidenza
                      automatica sotto: se serve un'immagine di apertura
                      del racconto, si aggiunge a mano nel Flexible
                      (Galleria "piena" o Media a tutto schermo).
     .project-body    contenitore del Flexible "project_sections":
                      .project-body__text (testo centrato ~900px),
                      .project-gallery (griglia immagini, 6 disposizioni),
                      .project-media (testo + immagine affiancati),
                      .project-media-pieno (immagine o video, riga
                      intera ma contenuta nella colonna),
                      .project-cta (bottone singolo, posizione libera).
     .latest-projects fascia grigia arrotondata in alto: eyebrow, due
                      .project-card, CTA all'archivio.
   ============================================================ */
.project-lede {
  position: relative;

  /* Come .intro / .contact-page: pannello pieno, primo blocco, l'header
     assoluto ci galleggia sopra. Colore di fondo/testo dai color picker
     "lede_color" / "lede_text_color" (style inline in single-progetto.php);
     qui solo il fallback per un progetto senza colori impostati.
     Tutto schermo (lvh, non dvh: qui non deve "respirare" con la barra
     degli indirizzi che si ritira, il pannello resta stabile) con
     titolo ancorato in alto e pill/descrizione in basso. */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--l-space);
  min-height: 100lvh;
  /* --header-height + --l-space, non --xl-space: stesso fix di
     .contact-page / .projects-archive, per lo stesso motivo
     (header fixed sopra, nessuna hero). */
  padding-block: calc(var(--header-height) + var(--l-space)) var(--l-space);
  background-color: var(--color-teal);
  color: var(--color-text);
}

/* Fallback per browser senza lvh (Safari < 15.4, Firefox < 101). */
@supports not (min-height: 100lvh) {
  .project-lede {
    min-height: 100vh;
  }
}

/* Titolo grande, interlinea stretta, come .projects-archive__title.
   --h1 fluido arriva a 156px come nel Figma. max-width forza il wrap
   anche su nomi di due parole che a piena larghezza ci starebbero su
   una riga sola (es. "Cooperativa Ruah"); "balance" (non "pretty",
   pensato per paragrafi) distribuisce poi le parole fra le righe cosi'
   non resta una riga lunga + un avanzo corto. 55vw e' relativo al
   viewport (non al carattere): un nome di una sola parola lunga puo'
   comunque andare a capo da solo, o un nome di due parole molto corte
   restare su una riga — verificare con nomi progetto reali e aggiustare
   qui se serve. A piena larghezza sotto 768px (mobile, qui sotto):
   niente spazio per bilanciare due parole comunque affiancate. */
.project-lede__title {
  font-size: var(--h1);
  font-weight: 400;
  max-width: 60vw;
  text-wrap: balance;
}

/* Riga sotto il titolo: pill a sinistra, descrizione a destra
   (Figma: allineate in basso, con spazio fra i gruppi). max-width sui
   due figli (sopra/sotto) evita che space-between li allontani troppo
   quando l'h1 e' stretto. */
.project-lede__meta {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--l-space);
}

.project-lede__tags {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  /* 473px del Figma convertiti in ch, come .project-lede__excerpt (sotto):
     stima sul carattere del tema a font-size: var(--body), non un valore
     esatto (i font proporzionali variano). font-size qui esplicito perche'
     ch si calcola sulla dimensione DELL'ELEMENTO che lo usa, non della
     pill dentro (che ha il suo --tag-text piu' piccolo) — verificare a
     schermo e aggiustare se serve. */
  max-width: 40ch;
  font-size: var(--body);
  gap: var(--xs-space);
}

/* La pill sul pannello colorato: bordo e testo scuri (ereditati da
   currentColor via .pill), non il chiaro di default su fondo scuro. */
.project-lede__excerpt {
  width: 100%;
  max-width: 43ch;
  font-size: var(--body);
}

/* --- corpo: contenitore dei blocchi Flexible ----------------------
   Lo spazio fra un blocco e l'altro e' del CONTENITORE, non dei
   blocchi: --project-gap (80px a 1440, fluido, come --l-space) e' il
   gap fra due blocchi, e anche il padding sopra il primo e sotto
   l'ultimo (stacco dall'apertura colorata e da "Ultimi progetti").
   Cosi' lo stacco e' SEMPRE un solo valore e non la somma di due
   padding (prima: 5rem + 5rem = 160px). I blocchi non hanno padding
   verticale proprio, tranne la Galleria con sfondo (il suo e' dentro
   il colore). Eccezione: i blocchi "attaccati" (vedi sotto) riportano
   il gap a 24px con un margine negativo. */
.project-body {
  --project-gap: var(--l-space);

  display: flex;
  flex-direction: column;
  gap: var(--project-gap);
  padding-block: var(--project-gap);
}

.project-body__hint {
  font-size: var(--body);
}

/* Blocco Testo: colonna centrata, larga ~900px come nel Figma. */
.project-body__text {
  display: flex;
  justify-content: center;
}

.project-body__text-inner {
  width: min(100%, 56rem);
  font-size: var(--body);
}

/* --- blocco Galleria -------------------------------------------------
   Sei disposizioni. Le immagini in piu' rispetto alla disposizione
   vanno a capo nella stessa griglia (grid ripete le tracce). */
.project-gallery {
  display: grid;
  gap: var(--gallery-gap); /* 24px fisso, orizzontale e verticale (Figma) */
}

/* Con un colore di sfondo (campo "background_color"), la Galleria
   diventa un pannello: padding anche in orizzontale (senza, le celle
   sarebbero a filo del pannello colorato) e angoli arrotondati. 80px/
   40px = --l-space/--m-space al loro massimo fluido (5rem/2.5rem). */
.project-gallery--panel {
  padding-block: var(--l-space);
  padding-inline: var(--m-space);
  border-radius: 16px;
}

.project-gallery--piena {
  grid-template-columns: 1fr;
}

.project-gallery--due {
  grid-template-columns: repeat(2, 1fr);
}

/* Due colonne asimmetriche (Figma 1329:4356: grande 824x900 + piccola
   512x900, gap 24, su 1360). Le colonne stanno in proporzione 824:512
   e la RIGA ha l'altezza della grande (aspect-ratio 824/900): la
   piccola si stira alla stessa altezza, quindi le due celle hanno
   sempre i rapporti del Figma (0.916 e 0.569) a ogni larghezza.

   I rapporti valgono ANCHE su mobile (celle in colonna, a tutta
   larghezza): la grande resta 824/900, la piccola 512/900, immagini e
   video riempiono la cella con object-fit/cover. La forma non cambia
   fra desktop e mobile. */
.project-gallery--due-grande-sx {
  grid-template-columns: 824fr 512fr;
}

.project-gallery--due-grande-dx {
  grid-template-columns: 512fr 824fr;
}

.project-gallery--due-grande-sx .project-gallery__item:first-child,
.project-gallery--due-grande-dx .project-gallery__item:last-child {
  aspect-ratio: 824 / 900;
  --cell-ratio: 0.9156; /* 824/900 come numero: lo legge il fallback mobile della cella video */
}

/* la piccola: solo quando le celle sono due (il caso del Figma) */
.project-gallery--due-grande-sx .project-gallery__item:last-child:nth-child(2),
.project-gallery--due-grande-dx .project-gallery__item:first-child:nth-last-child(2) {
  aspect-ratio: 512 / 900;
  --cell-ratio: 0.5689; /* 512/900 come numero */
}

.project-gallery--due-grande-sx .project-gallery__image,
.project-gallery--due-grande-dx .project-gallery__image {
  height: 100%;
  object-fit: cover;
}

/* Flex, non grid: con 3 colonne fisse un resto di 1-2 celle nell'ultima
   riga si piazzerebbe a sinistra (grid non ha un modo semplice di
   centrare "quello che resta" — richiederebbe selettori :nth-last-child
   legati al numero esatto di celle, fragili). justify-content: center
   su un flex-wrap centra l'ultima riga incompleta per qualsiasi numero
   di celle, senza selettori aggiuntivi. */
.project-gallery--tre {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.project-gallery--tre .project-gallery__item {
  flex: 0 0 calc((100% - 2 * var(--gallery-gap)) / 3);
}

/* Galleria a tre con colore di sfondo (--panel): ombra su immagini e
   video, per staccarli dal colore. Valori dal Figma (drop shadow
   x 7, y 8, blur 8.6, nero 25%): la card del Figma e' larga 412px, come
   la cella a tre colonne dentro il pannello a 1440px. */
.project-gallery--tre.project-gallery--panel .project-gallery__item {
  box-shadow: 7px 8px 8.6px rgb(0 0 0 / 0.25);
}

/* "Una grande a sinistra + due impilate a destra": due colonne, la
   prima immagine occupa due righe, le due successive una ciascuna. */
.project-gallery--una-piu-due {
  grid-template-columns: repeat(2, 1fr);
}

.project-gallery--una-piu-due .project-gallery__item:first-child {
  grid-row: span 2;
}

/* Cornice: solo ritaglio e angoli 15px. NESSUN aspect-ratio, ne' qui
   ne' sull'immagine dentro: ogni immagine/video mantiene la propria
   proporzione naturale, l'altezza della riga la decide il contenuto
   (nessun valore fisso imposto dal tema). */
.project-gallery__item {
  position: relative; /* ancora del testo sopra la cella (.project-gallery__text) */
  overflow: hidden;
  margin: 0; /* <figure> ha un margine di default nell'UA */
  border-radius: 15px;
}

.project-gallery__image {
  display: block;
  width: 100%;
  height: auto;
}

/* Testo facoltativo sopra l'immagine/video: in alto a sinistra a
   --s-space (24px desktop -> 16px mobile, fluido). Corpo --body (24 ->
   20px). Non intercetta i click (il video sotto resta raggiungibile). */
.project-gallery__text {
  position: absolute;
  top: var(--s-space);
  left: var(--s-space);
  z-index: 1;
  max-width: calc(100% - 2 * var(--s-space));
  color: var(--color-secondary); /* #383838 */
  font-size: var(--body);
  line-height: var(--leading-tight);
  pointer-events: none;
}

/* Desktop: l'immagine riempie l'altezza della cella (la riga la decide
   la cella piu' alta, o le due impilate di "una-piu-due"). Senza, le
   immagini piu' basse lasciano vuoti. object-fit: cover per non
   deformarle: le piu' basse vengono ritagliate ai bordi. */
@media (min-width: 769px) {
  .project-gallery__image {
    height: 100%;
    object-fit: cover;
  }
}

/* Cella video: stesso ingombro/angoli di .project-gallery__item.
   Nessun aspect-ratio imposto: l'embed oEmbed (add_theme_support(
   'responsive-embeds') in functions.php) avvolge l'iframe in
   .wp-embed-responsive, che mantiene DA SOLO il rapporto naturale del
   video (di norma 16:9) col padding-hack — non lo forziamo noi. */
.project-gallery__item--video {
  position: relative;
}

.project-gallery__item--video .wp-embed-responsive {
  display: block;
}

/* La cella video ha la STESSA forma su desktop e su mobile e il video
   la "copre" (come object-fit: cover): niente bande, ritaglio ai
   bordi. Forma della cella (--cell-ratio, larghezza/altezza):
     - layout "grande + piccola": i rapporti fissi 824/900 e 512/900
       (regole sopra, vincono per specificita');
     - altri layout: la mette il partial (elidria_gallery_cell_ratio),
       uguale a quella delle immagini della stessa riga, cosi' il video
       e' alto quanto loro anche quando su mobile vanno in colonna;
     - altrimenti: il rapporto naturale del video (--video-ratio).
   --video-ratio e' il rapporto vero del video, letto dall'oEmbed
   (aspect-ratio che elidria_video_embed_params scrive sull'iframe):
   serve al calcolo del "cover" qui sotto. align-self: stretch: se la
   riga e' piu' alta (celle vicine) la cella la riempie, come prima. */
.project-gallery__item--video {
  container-type: size;
  aspect-ratio: var(--cell-ratio, var(--video-ratio, 16 / 9));
  align-self: stretch;
}

.project-gallery__item--video iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  display: block;
  width: max(100cqw, 100cqh * var(--video-ratio, 1.7778));
  height: max(100cqh, 100cqw / var(--video-ratio, 1.7778));
  border: 0;
  transform: translate(-50%, -50%);
  /* Il video e' "di sfondo" (autoplay, muto, in loop, senza controlli:
     vedi elidria_video_embed_params): non c'e' nulla da cliccare. Un
     iframe di un altro dominio riceve da solo rotella e touch quando il
     puntatore e' sopra, e Lenis non li vede: lo scroll passa da
     interpolato a nativo e fa un "saltino" quando si entra/esce dalla
     cella. Con pointer-events: none gli eventi restano alla pagina. */
  pointer-events: none;
}

/* --- blocco Testo con immagine ------------------------------------- */
.project-media {
  display: flex;
  align-items: center;
  gap: var(--l-space);
  /* Larghezza massima libera (campo "max_width", custom property
     --block-max-w impostata inline dal partial): senza campo vale 100%
     (nessun limite). width: 100% serve perche' con margin-inline: auto
     l'elemento, in un contenitore flex a colonna (.project-body), non
     si allarga piu' da solo. */
  width: 100%;
  max-width: min(100%, var(--block-max-w, 100%));
  margin-inline: auto;
}

.project-media--right {
  flex-direction: row-reverse;
}

/* --- blocco Bottone -------------------------------------------------
   Un solo link (.cta, stile gia' condiviso con le altre CTA del sito),
   centrato nella sezione. Posizione libera nell'ordine dei blocchi. */
.project-cta {
  display: flex;
  justify-content: center;
}

.project-media__visual {
  flex: 1 1 0;
  overflow: hidden;
  margin: 0; /* <figure> ha un margine di default nell'UA */
  border-radius: 15px;
}

.project-media__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.project-media__text {
  flex: 1 1 0;
  font-size: var(--body);
}

/* --- blocco Media a tutto schermo -----------------------------------
   Contenuto nella colonna di pagina come .project-gallery/.project-media
   (NON full-bleed: .project-body ha gia' il suo padding-inline dalla
   lista container in cima al file, riga ~213). A differenza di
   .project-hero (immagine in evidenza, sempre in cima, fissa) questo
   blocco e' posizionabile ovunque nel racconto, anche piu' volte, e
   accetta anche un video esterno (embed oEmbed). */
.project-media-pieno {
  /* Larghezza massima libera: vedi .project-media (campo "max_width",
     custom property --block-max-w). Vuoto = 100%, nessun limite. */
  width: 100%;
  max-width: min(100%, var(--block-max-w, 100%));
  margin-inline: auto;
}

.project-media-pieno__image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 15px;
}

/* L'embed oEmbed (add_theme_support('responsive-embeds') in
   functions.php) avvolge l'iframe in .wp-embed-responsive, che gia'
   mantiene il rapporto 16:9 via padding-hack; qui solo la larghezza e
   l'angolo (overflow:hidden per ritagliare l'iframe sotto l'angolo). */
.project-media-pieno__frame {
  width: 100%;
  overflow: hidden;
  border-radius: 15px;
}

/* --- blocchi attaccati: 24px fisso, non lo stacco di sezione
   -------------------------------------------------------------------
   Un "Media a tutto schermo" seguito da un altro Media o da una
   Galleria (senza un blocco Testo in mezzo) fa gruppo con il blocco che
   lo segue (Figma: gap 24px invece dello stacco di sezione). Il gap di
   .project-body e' --project-gap: un margine negativo di (24px - gap)
   sul blocco che segue lo porta a 24px. La regola e' VOLUTAMENTE
   asimmetrica: una Galleria seguita da un Media NON si attacca — il
   Media dopo una Galleria apre una nuova sezione e tiene lo stacco
   normale (es. le card a tre colonne e il pannello verde che le segue).
   Se serve decidere caso per caso, la strada e' un campo in admin per
   blocco. Niente :has(): basta il selettore adiacente. */
.project-media-pieno + .project-media-pieno,
.project-media-pieno + .project-gallery {
  margin-block-start: calc(var(--gallery-gap) - var(--project-gap));
}

.project-media-pieno__frame iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
  /* Come nella Galleria: video di sfondo, niente da cliccare; l'iframe
     non deve rubare rotella/touch a Lenis (vedi
     .project-gallery__item--video iframe). */
  pointer-events: none;
}

/* Video con autoplay bloccato (iOS in risparmio energetico, Chrome per
   iOS): main.js ricarica l'iframe come player normale (anteprima + tasto
   play di Vimeo) e mette .is-video-manual. Solo in quel caso l'iframe
   deve tornare cliccabile; negli altri resta pointer-events: none (vedi
   sopra e .project-gallery__item--video iframe). Specificita' piu' alta
   delle due regole base. */
.project-gallery__item--video iframe.is-video-manual,
.project-media-pieno__frame iframe.is-video-manual {
  pointer-events: auto;
}

/* ============================================================
   ULTIMI PROGETTI — coda della scheda
   ------------------------------------------------------------
   Riferimento Figma: nodo 1002:1471. Fascia grigia (--color-hairline),
   angoli alti arrotondati, come .contact / .services della home.
   ============================================================ */
.latest-projects {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--m-space);
  /* 200px di spazio VISIBILE sotto le card: il footer sale sopra
     questa fascia di --radius-panel-40 (margin-top negativo), quindi
     lo si somma al padding. */
  padding-block: var(--l-space) calc(12.5rem + var(--radius-panel-40));
  background-color: var(--color-hairline);
  border-radius: var(--l-space) var(--l-space) 0 0;
}

.latest-projects__eyebrow {
  font-family: var(--font-mono);
  text-transform: uppercase;
}

.latest-projects__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: var(--s-space);
  row-gap: var(--l-space);
  width: 100%;
}

.latest-projects__cta {
  margin-block-start: var(--s-space);
}

/* --- mobile: blocchi in colonna --------------------------------- */
@media (max-width: 768px) {
  .project-lede {
    /* Sotto: 3.5rem (56px) fissi, non --m-space (24px, troppo poco). */
    padding-block: calc(var(--header-height) + var(--l-space)) 3.5rem;
  }

  .project-lede__title {
    max-width: 100%;
  }

  .project-lede__meta {
    flex-direction: column;
    align-items: stretch;
    gap: var(--m-space);
  }

  .project-lede__excerpt {
    max-width: 100%;
  }

  /* Corpo: su schermo stretto lo spazio e' quello di prima — 2 x
     --m-space fra due blocchi (era --m-space di padding su ognuno) e
     --m-space dall'apertura colorata e da "Ultimi progetti". */
  .project-body {
    --project-gap: calc(2 * var(--m-space));

    padding-block: var(--m-space);
  }

  .project-gallery--due,
  .project-gallery--due-grande-sx,
  .project-gallery--due-grande-dx,
  .project-gallery--una-piu-due {
    grid-template-columns: 1fr;
  }

  .project-gallery--una-piu-due .project-gallery__item:first-child {
    grid-row: auto;
  }

  /* --tre e' flex (sopra): su mobile diventa una griglia a colonna
     singola. Con flex-direction: column il flex-basis dei figli
     sarebbe un'ALTEZZA (100% di un'altezza indefinita), e le celle
     video — aspect-ratio + container-type: size — non prendevano la
     forma voluta come nelle altre disposizioni (che sono grid). */
  .project-gallery--tre {
    display: grid;
    grid-template-columns: 1fr;
  }

  /* Cella video su mobile: forma data dal padding-top, non da
     aspect-ratio + container-type: size. Su iPhone (WebKit, qualunque
     browser) quella combinazione dentro una griglia faceva collassare la
     cella a altezza 0: il video e la sua etichetta sparivano del tutto.
     Il padding in % e' relativo alla LARGHEZZA della cella, quindi la
     forma (--cell-ratio, o quella naturale del video) e' garantita
     ovunque. L'iframe copre la cella (come object-fit: cover) con
     percentuali invece delle unita' cq: con ratio video v e ratio cella
     c, larghezza = 100% * max(1, v/c), altezza = 100% * max(1, c/v).
     Stessa forma e stesso ritaglio del desktop. */
  .project-gallery__item--video {
    container-type: normal;
    height: 0;
    padding-top: calc(100% / var(--cell-ratio, var(--video-ratio, 1.7778)));
    aspect-ratio: auto;
  }

  .project-gallery__item--video iframe {
    width: calc(100% * max(1, var(--video-ratio, 1.7778) / var(--cell-ratio, var(--video-ratio, 1.7778))));
    height: calc(100% * max(1, var(--cell-ratio, var(--video-ratio, 1.7778)) / var(--video-ratio, 1.7778)));
  }

  .project-gallery--panel.project-gallery--panel {
    padding-block: var(--m-space);
  }

  .project-media,
  .project-media--right {
    flex-direction: column;
    align-items: stretch;
    gap: var(--m-space);
  }

  .latest-projects__grid {
    grid-template-columns: 1fr;
    row-gap: var(--m-space);
  }
}

/* ============================================================
   ABOUT — pagina /about (layout Flexible chi-hero / origini-nome /
   gli-elidri)
   ------------------------------------------------------------
   Riferimento Figma: 832:871 (chiuso) e 752:950 (aperto) desktop,
   302:166 mobile. Tre pannelli full-bleed impilati, angoli alti
   arrotondati, alternanza chiaro/scuro come il resto del tema.
   ============================================================ */

/* --- 1. APERTURA ("Chi è") ------------------------------------
   Fondo chiaro: primo blocco, l'header ci galleggia sopra (logo
   scuro). Titolo gigante, wordmark, testo introduttivo grande. */
.chi-hero {
  display: flex;
  flex-direction: column;
  gap: calc(var(--xl-space)*1.5);

  /* Spazio sopra per non finire sotto l'header assoluto. */
  padding-block: calc(var(--xl-space)*1.5) calc(var(--xl-space)*1.25);
  background-color: var(--color-surface);
}

/* Titolo dell'About: mai sotto i 100px (a mobile il token --h1 e' 48px).
   Si ridefinisce --h1 qui, non solo il font-size del titolo, perche' il
   margine negativo del lettering (.chi-hero__mark) e' legato a --h1:
   cosi' il lettering segue la nuova altezza del titolo.
   max() fra 100px e la STESSA curva del token (:root, riga ~98): sta a
   100px finche' la curva e' sotto (fino a ~940px) e poi la segue, senza
   un breakpoint e senza salto. Se cambi la curva di --h1 in :root,
   cambiala anche qui. */
@supports (font-size: clamp(1rem, 1vw, 2rem)) {
  .chi-hero {
    --h1: max(100px, clamp(3rem, 11.25vw - 0.375rem, 17.625rem));
  }
}

.chi-hero__head {
  display: flex;
  flex-direction: column;
  gap: var(--m-space);
}

.chi-hero__title {
  font-size: var(--h1);
  font-weight: 400;
}

/* Il lettering "elidria" sotto il titolo: 7 wordmark diversi
   (SVG scuri, fondo chiaro) sovrapposti nello stesso riquadro. Ne
   è visibile uno per volta (.is-current); il blocco "chi-hero
   mark" in main.js li alterna in loop infinito, a passo costante.

   I frame occupano width:100% del riquadro e nient'altro
   agisce sulla loro dimensione. Ma gli SVG hanno rapporti molto
   diversi (dal corsivo basso al condensato alto): per non far
   ballare il testo sotto, il riquadro tiene il rapporto del frame
   più alto (#4: 303.789 × 145.726). Così l'altezza è fissa a ogni
   larghezza e i frame più bassi si centrano in quello spazio.

   Il margine negativo tira il riquadro sotto il titolo. E' legato a
   --h1 (non un valore fisso): il frame #4 riempie tutto il riquadro,
   quindi il suo bordo alto coincide con quello del riquadro e può
   rientrare nel titolo solo per lo spazio vuoto sotto le sue lettere
   (~0.2 x --h1) + il gap. 0.35 x --h1 tiene il frame #4 appena fuori
   dal titolo a ogni larghezza; se lo alzi, ricontrolla il frame #4.

   Sopra ~1500px il titolo e' fermo a 156px ma il riquadro continua a
   crescere (e con lui lo spazio vuoto sopra i frame bassi): il
   3.9% (percentuale = larghezza del genitore) prende il sopravvento
   e tira il lettering un po' più su man mano che lo schermo si
   allarga. Sotto, vince il termine legato a --h1.

   Il secondo addendo (0.06 x l'eccesso di viewport oltre 96rem =
   1536px) e' zero fino a 1920@125% e spinge in più solo sugli
   schermi più larghi (1920@100%: ~23px in più). Con 0.1 su Chrome
   era troppo (Firefox andava bene): e' un compromesso, dipende dalla
   larghezza reale del viewport, che varia fra browser/scrollbar. */
.chi-hero__mark {
  position: relative;
  width: 100%;
  max-width: 49.26%; /* 670/1360 nel Figma: fallback senza clamp() */
  /* A tutta larghezza fino a 480px, poi si restringe in modo graduale
     fino a 1024px, dove arriva al 49.26% (Figma) e da li' in su resta
     li' (il minimo del clamp). La percentuale dipende dal genitore, che
     cambia con lo schermo, quindi si interpola in px: 432px a 480
     (480 - 2 x 24 di --m-space) -> 472px a 1024 (49.26% x 958). Pendenza
     = (472 - 432) / (1024 - 480) = 0.0735. Sotto 480 il valore e' sopra
     il 100% del genitore e vince il massimo. Se cambi --m-space o i due
     estremi, ricalcola. */
  max-width: clamp(49.26%, calc(432px + (100vw - 480px) * 0.0735), 100%);
  aspect-ratio: 303.789 / 145.726;
  margin-top: calc(-1 * (max(var(--h1) * 0.35, 3.9%) + max(0px, (100vw - 96rem) * 0.06)));
}

.chi-hero__mark-frame {
  position: absolute;
  top: 50%;
  left: 0;
  display: block;
  width: 100%;
  transform: translateY(-50%);
  visibility: hidden;
}

.chi-hero__mark-frame.is-current {
  visibility: visible;
}

/* Senza JS resta visibile solo il primo. */

/* Testo introduttivo — layout. Corpo e interlinea: .u-text-lg. */
.chi-hero__intro {
  max-width: 807px; /* come nel Figma; sotto ~870px riempie la colonna */
  margin: 0 auto;
}

.chi-hero__intro p + p {
  margin-block-start: 1em;
}

/* --- 2. ORIGINI DEL NOME ------------------------------------
   Pannello scuro, angoli marcati (--l-space). In alto sopracciglio +
   domanda a TUTTA larghezza; il "+" in alto a destra. Nessuna foto,
   ne' da chiuso ne' da aperto. Il "+" apre le ipotesi (colonna destra,
   sotto la domanda) e il blocco finale "per certo".
   Riferimento Figma: 832:1045 (chiuso), 752:950 (aperto). */
.origini {
  position: relative;
  z-index: 1;
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-surface);
  background-color: var(--color-primary);
  /* border-radius: classe .u-radius-panel-80 nel markup (80px
     desktop -> 30px mobile, non var(--l-space) che darebbe 56). */

  /* risale sotto gli angoli del blocco precedente (chi-hero, chiaro) */
  margin-block-start: calc(-1 * var(--m-space));
}

.origini__inner {
  display: flex;
  flex-direction: column;
}

/* sopracciglio + domanda: tutta la larghezza, sopra le ipotesi */
.origini__ask {
  display: flex;
  flex-direction: column;
  /* 32px mobile -> 48px desktop nel Figma, non --m-space (24->40). */
  gap: clamp(2rem, 1.6667vw + 1.5rem, 3rem);
}

/* etichetta breve (<p>, ma non testo di lettura): interlinea stretta */
.origini__eyebrow {
  font-family: var(--font-display-round);
  font-size: var(--h4);
  line-height: var(--leading-tight);
  color: var(--color-yellow);
}

.origini__question {
  font-family: var(--font-display-square);
  font-style: italic;
  font-weight: 400;
  /* 96px desktop -> 32px mobile: la vecchia scala di --h2, che ora e'
     96 -> 48 (questo titolo tiene il minimo mobile piu' basso). */
  font-size: clamp(2rem, 6.6667vw, 6rem);
  text-transform: uppercase;
  color: var(--color-violet);
}

/* --- disclosure: colonna destra, sotto la domanda -------------
   Meta' della riga meno meta' del gap (--xl-space) usato dal blocco
   "per certo": stessa colonna di quello. */
.origini__disclosure {
  width: calc(50% - var(--xl-space) / 2);
  margin-inline-start: auto;
}

.origini__details {
  margin: 0;
}

/* il "+" / "−": ancorato in alto a destra della sezione */
.origini__summary {
  position: absolute;
  top: var(--l-space);
  right: var(--m-space);
  z-index: 3;
  display: block;
  list-style: none;
  cursor: pointer;
}

.origini__summary::-webkit-details-marker {
  display: none;
}

.origini__summary:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 4px;
}

/* il "+" / "−": icona Lucide "plus" inline (elidria_lucide('plus')),
   colore da currentColor come le altre icone del sito. La seconda
   <path> (la barra verticale) ruota via all'apertura, lasciando solo
   la prima (orizzontale) -> si legge come "−". */
.origini__summary svg {
  display: block;
  width: 56px;
  height: 56px;
  color: var(--color-hairline);
}

.origini__summary svg path:last-child {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

/* aperto: la barra verticale ruota a orizzontale -> "−" */
.origini.is-open .origini__summary svg path:last-child {
  transform: rotate(90deg);
}

/* la finestra: contiene le ipotesi. Da chiusa alta 0 (il JS pilota
   l'altezza), da aperta cresce. */
.origini__window {
  overflow: hidden;
}

.origini--enhanced .origini__window {
  height: 0;
}

/* le ipotesi: colonna destra, in flusso sotto la domanda (quando aperto).
   Da chiuse hanno [hidden] -> display:none. Il JS toglie [hidden]
   e le anima. */
.origini__ipotesi {
  display: flex;
  flex-direction: column;
  gap: var(--l-space);
  /* aria fra la domanda e la prima ipotesi: sta qui dentro (non nel
     gap del genitore) cosi' da chiuso, con la finestra alta 0, non
     aggiunge vuoto sotto la domanda. */
  padding-block-start: calc(var(--l-space) * 1.5);
  list-style: none;
}

.origini__ipotesi-item {
  display: flex;
  flex-direction: column;
  gap: var(--stack-32);
}

.origini__ipotesi-figure {
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
  background-color: var(--color-secondary);
}

.origini__ipotesi-img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}

/* segnaposto: dà un'altezza alla figure vuota (l'img la darebbe) */
.origini__ipotesi-figure--placeholder {
  aspect-ratio: 3 / 2;
  background-image: repeating-linear-gradient(
    -45deg,
    var(--color-hairline) 0 2px,
    transparent 2px 22px
  );
}

.origini__ipotesi-title {
  font-family: var(--font-display-square);
  font-style: italic;
  /* 32px mobile -> 48px desktop nel Figma ("H4 alternativo"), non
     --h4 (24->32): la scala del font display non coincide con
     quella del Geist regolare a questa taglia. */
  font-size: clamp(2rem, 1.6667vw + 1.5rem, 3rem);
  text-transform: uppercase;
}

.origini__ipotesi-item--teal .origini__ipotesi-title { color: var(--color-teal); }
.origini__ipotesi-item--pink .origini__ipotesi-title { color: var(--color-pink); }
.origini__ipotesi-item--yellow .origini__ipotesi-title { color: var(--color-yellow); }
.origini__ipotesi-item--violet .origini__ipotesi-title { color: var(--color-violet); }

.origini__ipotesi-text {
  font-size: var(--body);
}

/* --- blocco finale: "Scherzi a parte / Quello che sappiamo per certo" ---
   Fratello di .origini__inner (non dentro il disclosure): il titolo da
   96px e' piu' largo della colonna destra, deve poter scavalcarla. Si
   apre con le ipotesi: con JS ne pilota l'altezza la stessa timeline
   (height 0 -> auto); senza JS lo mostra :has(details[open]).
   Riferimento Figma: 752:950 (stato aperto). */
.origini__certo {
  display: none;
}

.origini:has(.origini__details[open]) .origini__certo {
  display: block;
}

.origini--enhanced .origini__certo {
  display: block;
  height: 0;
  overflow: hidden;
}

.origini__certo-inner {
  display: flex;
  flex-direction: column;
  gap: calc(var(--l-space) * 1.5);
  padding-block-start: var(--xl-space);
}

/* sopracciglio + titolo: stessa pila (e stesso gap) di .origini__ask */
.origini__certo-head {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 1.6667vw + 1.5rem, 3rem);
}

.origini__certo-title {
  color: var(--color-teal);
}

/* immagine + testo nella colonna destra: meta' della riga meno meta'
   del gap di .origini__inner (--xl-space), cosi' coincide con le ipotesi */
.origini__certo-body {
  display: flex;
  flex-direction: column;
  gap: var(--stack-32);
  width: calc(50% - var(--xl-space) / 2);
  margin-inline-start: auto;
}

.origini__certo-text {
  font-size: var(--body);
}

/* nel Figma il secondo paragrafo e' separato da una riga vuota (36px
   = 1.5 x 24px), non dai --s-space di .entry-content */
.origini__certo-text > * + * {
  margin-block-start: 1.5em;
}

/* --- 3. GLI ELIDRI (team) ------------------------------------
   Fondo grigio chiaro. Titolo, testo grande, blocco secondario
   con CTA, poi la fascia di foto che sborda. */
.elidri {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--l-space);
  overflow: hidden;
  padding-block: var(--l-space) var(--xl-space);
  color: var(--color-text);
  background-color: var(--color-hairline);
  /* 40px fisso a ogni schermo nel Figma (mobile e desktop uguali),
     non --m-space che scenderebbe a 24 su mobile. */
  border-radius: 2.5rem 2.5rem 0 0;
  /* Overlap fisso quanto il raggio (non --m-space, che su mobile
     vale solo 24px): sotto quella soglia la parte alta della curva
     non ha nulla di scuro dietro e si vede lo sfondo chiaro pagina. */
  margin-block-start: -2.5rem;
}

.elidri__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--l-space);
}

.elidri__title {
  width: 100%;
  /* 48px mobile -> 96px desktop nel Figma, non --h2 (32->96): sul
     mobile chiuso il titolo "Gli elidri" e' 48px, non 32. */
  font-size: clamp(3rem, 5vw + 1.5rem, 6rem);
  font-weight: 400;
}

/* Testo grande — layout. Corpo e interlinea: .u-text-lg. */
.elidri__lead {
  width: 100%;
}

.elidri__aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stack-48);
  max-width: 42.28%; /* 575/1360 nel Figma */
}

.elidri__body {
  font-size: var(--body);
}

.elidri__cta {
  max-width: 100%;
}

/* la griglia di foto: masonry come reactbits.dev/components/masonry.
   Il JS (blocco "Gli elidri" in main.js) misura la larghezza, prende
   il numero di colonne e il gap da qui, e mette ogni foto nella
   colonna piu' bassa; qui solo il layout di base e il fallback.

   --elidri-cols e' l'unica fonte del numero di colonne (CSS e JS la
   leggono entrambi). Le foto non hanno larghezza fissa: ogni colonna
   e' (larghezza griglia - gap) / colonne, quindi la dimensione segue
   lo schermo. 4 colonne da 310px a 1440 nel Figma = 1360 con gap 40.
   Il gap e' --m-space (40px desktop, fluido verso 24).

   Senza JS: column-count, stesso numero di colonne, foto dall'alto in
   basso colonna per colonna (nessun scorrimento, nessun calcolo). */
.elidri__grid {
  --elidri-cols: 4;

  column-gap: var(--m-space);
  column-count: var(--elidri-cols);
  list-style: none;
}

@media (max-width: 1023px) {
  .elidri__grid { --elidri-cols: 3; }
}

@media (max-width: 767px) {
  .elidri__grid { --elidri-cols: 2; }
}

.elidri__photo {
  margin-block-end: var(--m-space);
  break-inside: avoid;
}

/* angoli 15px fissi nel Figma (non --radius-panel-*, che sono 30+) */
.elidri__photo-frame {
  overflow: hidden;
  border-radius: 15px;
}

.elidri__photo-img {
  display: block;
  width: 100%;
  height: auto;
}

/* masonry attivo (classe messa dal JS): le foto escono dal flusso e
   il JS le posiziona con transform; la griglia prende l'altezza dal JS. */
.elidri__grid.is-masonry {
  position: relative;
  column-count: auto;
}

.elidri__grid.is-masonry .elidri__photo {
  position: absolute;
  top: 0;
  left: 0;
  margin: 0;
  will-change: transform;
}

/* hover: la foto si rimpicciolisce un po' (scaleOnHover 0.95 della
   reference). Solo con puntatore vero e movimento consentito. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .elidri__grid.is-masonry .elidri__photo-frame {
    transition: transform 0.3s ease;
  }

  .elidri__grid.is-masonry .elidri__photo:hover .elidri__photo-frame {
    transform: scale(0.95);
  }
}

/* segnaposto: riquadri vuoti finche' non ci sono foto, con altezze
   diverse a ritmo cosi' la griglia si legge come masonry */
.elidri__grid--placeholder .elidri__photo-frame {
  aspect-ratio: 310 / 283;
  background-color: var(--color-hairline);
  background-image: repeating-linear-gradient(
    -45deg,
    var(--color-muted) 0 2px,
    transparent 2px 22px
  );
}

.elidri__grid--placeholder .elidri__photo:nth-child(3n + 2) .elidri__photo-frame { aspect-ratio: 310 / 414; }
.elidri__grid--placeholder .elidri__photo:nth-child(3n + 3) .elidri__photo-frame { aspect-ratio: 310 / 233; }

/* --- mobile --------------------------------------------------- */
@media (max-width: 768px) {
  /* .chi-hero gap/padding-block invariati (--xl-space fluido, gia'
     ancorato): dal wordmark al paragrafo introduttivo il Figma
     mobile tiene ~218px (misurato dalle coordinate), non i 24px di
     --m-space che l'override forzava qui. */


  /* .origini padding-block e border-radius invariati (--l-space/
     --xl-space fluidi, .u-radius-panel-80): il Figma mobile tiene
     56/150px e 30px di raggio, non lo stretto --m-space. */

  /* Icona "+": 56px e' la misura desktop, il Figma mobile la vuole
     a 32px. */
  .origini__summary svg {
    width: 32px;
    height: 32px;
  }

  /* Le ipotesi occupano tutta la larghezza sotto la domanda. */
  .origini__disclosure {
    width: 100%;
    margin-inline-start: 0;
  }

  /* .origini__summary top/right invariati (--l-space/--m-space):
     essendo un elemento assoluto si misurano dal bordo del padding-
     box dell'antenato, non da dove il contenuto normale (l'eyebrow)
     comincia davvero — i valori di default (gia' fluidi) allineano
     gia' correttamente l'icona all'eyebrow anche su mobile. Un
     override a top:0/right:0 la sposterebbe fuori posto (ignora il
     padding della sezione). */

  /* .origini__ipotesi gap invariato (--l-space, 56px nel Figma
     mobile, non lo stretto --m-space). Fra domanda e prima ipotesi
     5rem fissi, non il 1.5 x --l-space del desktop. */
  .origini__ipotesi {
    padding-block-start: 5rem;
  }

  /* .elidri gap/padding-block invariati (--l-space/--xl-space
     fluidi): il Figma mobile tiene 56px di gap e 56/150px di
     padding, non lo stretto --m-space. */

  .elidri__intro {
    /* gap invariato (--l-space): 56px anche nel Figma mobile. */
    align-items: stretch;
  }

  .elidri__aside {
    /* gap invariato (--stack-48): 48px anche nel Figma mobile,
       non --stack-32. */
    max-width: 100%;
  }

  /* il blocco "per certo" e' a una colonna: immagine e testo a
     tutta larghezza sotto il titolo (le colonne della griglia delle
     foto del team le gestisce --elidri-cols, non serve qui). */
  .origini__certo-body {
    width: 100%;
    margin-inline-start: 0;
  }
}

/* --- motion ridotto: disclosure istantaneo ------------------ */
@media (prefers-reduced-motion: reduce) {
  .origini__summary svg path:last-child {
    transition: none;
  }
}
