/* ============================================================================
   home.css — foglio unico della home.

   Nato come demo.r1.css in /demo-motion/, promosso a home il 2026-09-24.
   Dipende da tokens.css e fonts.css. NON carica style.css, che resta a
   privacy.html e 404.html: le poche regole condivise davvero (lo stato del
   reveal, gli stati di errore del modulo, il bottone delle preferenze cookie)
   sono ricopiate qui sotto, e sono segnate.

   Dal riferimento si prende come si muovono le cose e quanta roba sta in una
   schermata. Restano i quattro colori del marchio, Open Sauce One, gli angoli
   vivi, le hairline e il bianco dominante: niente card, niente ombre, nessun
   colore di riempimento fuori palette. L'unico gradiente della pagina è la
   maschera ai lati del marquee, che non colora niente.

   La docroot mette Cache-Control immutable per un anno su ogni .css: qui il
   nome è fisso, e la cache la invalida il ?v= che deploy/impronta.sh aggiunge
   al <link> a ogni pubblicazione.

   Revisione 1 · 2026-09-12
   ========================================================================= */

/* ══════════════════════════════════════════════════ TOKEN DEL MOVIMENTO ═════
   Vivono solo qui: tokens.css è condiviso con la landing e non si tocca. */
:root {
  --m-micro: 180ms;   /* hairline, frecce, colore */
  --m-corto: 260ms;   /* accordion, righe dei servizi */
  --m-medio: 350ms;   /* roll-up dei bottoni */
  --m-lungo: 520ms;   /* segmenti del filo, wipe */
  --m-reveal: 820ms;  /* ingresso: invariato rispetto alla landing */

  --e-out: cubic-bezier(0.16, 0.84, 0.44, 1);    /* la curva di casa */
  --e-inout: cubic-bezier(0.65, 0, 0.35, 1);

  --hairline: #E2E2E2;
  --hairline-forte: #CFCFCF;
  /* Il bordo di un campo è l'unico segno che dice dove si scrive: deve stare
     sopra 3:1 anche sul fondo tenue, e #CFCFCF ci arrivava a 1,53:1. */
  --bordo-campo: #8A8A8A;
  /* ⚠️ Il violet della banda non è --viola. Bianco su #7B6CAE sta a 4,42:1,
     cioè sotto il minimo per il testo normale, e una banda piena è tutta testo.
     #5A4D82 non è un colore nuovo: è già nel sistema come stato premuto del
     bottone pieno, e porta il bianco a 7,2:1. */
  --viola-banda: #5A4D82;
  --d-max: 1240px;
  --d-testata: 72px;

  /* Il titolo dell'hero è più piccolo di --t-hero, e non è un
     ripensamento estetico: --t-hero è tarata su un titolo a tutta larghezza,
     qui il titolo divide la riga con il segno. Alla scala di --t-hero «Il tuo partner» andrebbe a capo da
     solo, e il <br> del marchio si perderebbe in quattro righe invece di due. */
  --t-hero-home: clamp(2.5rem, 0.4rem + 6.6vw, 7.5rem);
}

/* ═══════════════════════════════════════════════ SCORRIMENTO SMORZATO ═════
   Le tre regole che Lenis si aspetta. Sono poche e si scrivono a mano invece di
   portarsi dietro un altro foglio di stile.
   ⚠️ scroll-behavior: smooth e Lenis insieme litigano: il salto a un ancoraggio
   verrebbe animato due volte, da due motori diversi. tokens.css lo mette su
   html, quindi qui va tolto finche' Lenis e' acceso. */
html.lenis, html.lenis body { height: auto; }
/* Su .lenis e non su .lenis-smooth: la seconda classe Lenis la mette solo
   quando comincia a gestire la rotella, e fino a quel momento lo smooth nativo
   resterebbe acceso. */
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* ══════════════════════════════════════════════════════════════ BASE ═════ */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--testo);
  font-family: var(--font);
  font-size: var(--t-body);
  font-weight: var(--w-normal);
  line-height: var(--lh-larga);
  -webkit-font-smoothing: antialiased;
  /* clip e non hidden: hidden creerebbe un contenitore di scorrimento e
     romperebbe ogni position:sticky della pagina. */
  overflow-x: clip;
}

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

a { color: inherit; }

h1, h2, h3 { margin: 0; }
p { margin: 0 0 var(--s-2); }

.contenitore {
  width: min(var(--d-max), 100% - var(--gutter) * 2);
  margin-inline: auto;
}

.sezione { padding-block: var(--s-6); }
.sezione--tenue { background: var(--bianco-sporco); }

.salta {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--viola);
  color: #fff;
  padding: var(--s-1) var(--s-2);
  z-index: 100;
}
.salta:focus { left: 0; }

#contenuto:focus { outline: none; }

/* Un solo anello di focus per tutta la pagina, sempre visibile, mai rimosso
   senza sostituto. Il violet pieno su bianco sta a 4,57:1: per un bordo va
   bene, per un testo piccolo no, ed è il motivo per cui sotto si usa
   --viola-testo ovunque ci siano parole da leggere. */
:focus-visible {
  outline: 3px solid var(--viola);
  outline-offset: 3px;
}

/* ═══════════════════════════════════════════════════════ TIPOGRAFIA ═════
   Il tratto del marchio: dentro un titolo, una sola parola in Light Italic.
   Il resto in Bold su base Light. È l'unico effetto tipografico che abbiamo,
   e non si applica a nient'altro. */

.titolo-2 {
  font-size: var(--t-h2);
  font-weight: var(--w-bold);
  line-height: var(--lh-media);
  letter-spacing: var(--ls-stretta);
  margin-bottom: var(--s-4);
}

/* Come per l'hero, la scala di --t-giga è tarata su una colonna piena: qui i
   titoloni stanno in metà griglia accanto al modulo, e «Prezzemolo» a quella
   misura uscirebbe dalla colonna e finirebbe sopra i campi. */
.titolo-giga {
  font-size: clamp(2.25rem, 0.5rem + 5.2vw, 5.5rem);
  font-weight: var(--w-light);
  line-height: var(--lh-stretta);
  letter-spacing: var(--ls-stretta);
}
.titolo-giga strong { font-weight: var(--w-bold); }
.titolo-giga em { font-style: italic; font-weight: var(--w-light); }

.occhiello {
  font-size: var(--t-eyebrow);
  font-weight: var(--w-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--viola-testo);
  margin: 0 0 var(--s-2);
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.35;
  max-width: 46ch;
}

.corpo { max-width: 62ch; }
.corpo--tenue { color: var(--testo-tenue); }

/* ══════════════════════════════════════════════════════════ BOTTONI ═════
   Pill radius 100px, bordo 1px, fondo trasparente: è la sola forma tonda
   ammessa dal marchio. */

.bottone {
  position: relative;
  overflow: clip;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.85em 1.6em;
  border: 1.5px solid currentColor;
  border-radius: var(--raggio-pill);
  font-weight: var(--w-bold);
  font-size: 0.95rem;
  text-decoration: none;
  color: var(--nero);
  background: transparent;
  cursor: pointer;
  transition: background-color var(--m-micro) var(--e-inout),
              color var(--m-micro) var(--e-inout),
              border-color var(--m-micro) var(--e-inout);
}
.bottone--piccolo { padding: 0.6em 1.2em; font-size: 0.875rem; }
.bottone--pieno {
  background: var(--viola);
  border-color: var(--viola);
  color: #fff;
}

.bottone__t { position: relative; z-index: 1; display: block; }

/* Il riempimento sale da sinistra e il testo resta leggibile per tutta la
   transizione. Il roll-up del riferimento, con l'etichetta che esce e l'eco che
   entra, a metà strada mostra due mezze parole: su una CTA è il momento in cui
   la persona sta decidendo se cliccare, e non è il momento di togliere le
   parole. */
.bottone { isolation: isolate; }
.bottone::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Dietro il contenuto: quando il testo non sta dentro uno span, come nel
     tasto Invia, un riempimento sopra lo copriva del tutto. */
  z-index: -1;
  border-radius: inherit;
  background: var(--viola);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--m-medio) var(--e-inout);
}
.bottone:hover::before,
.bottone:focus-visible::before { transform: scaleX(1); }
.bottone:hover, .bottone:focus-visible { color: #fff; border-color: var(--viola); }

/* Il bottone pieno fa il contrario: il fondo scuro entra sopra il violet. */
.bottone--pieno::before { background: #4B3F71; }
.bottone--pieno:hover, .bottone--pieno:focus-visible { border-color: #4B3F71; }

/* ══════════════════════════════════════════════════════════ TESTATA ═════ */

.testata {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  transition: transform 240ms var(--e-inout);
}
.testata::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  background: var(--hairline);
  opacity: 0;
  transition: opacity var(--m-micro) linear;
}
.testata--staccata::after { opacity: 1; }
.testata--nascosta { transform: translateY(-100%); }

.testata__interno {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--d-testata);
}
.testata__logo { margin-right: auto; display: block; }
.testata__logo img { width: 148px; height: auto; }

.testata__nav { display: none; gap: var(--s-3); }
.testata__nav a {
  position: relative;
  text-decoration: none;
  font-size: 0.9375rem;
  padding-block: 0.35em;
}
.testata__nav a::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--m-corto) var(--e-out);
}
.testata__nav a:hover::after,
.testata__nav a:focus-visible::after { transform: scaleX(1); }
/* La voce attiva resta segnata finché sei in quella sezione. */
.testata__nav a[aria-current="true"] { color: var(--viola-testo); }
.testata__nav a[aria-current="true"]::after { transform: scaleX(1); opacity: 0.45; }

@media (min-width: 860px) { .testata__nav { display: flex; } }

/* ═════════════════════════════════════════════════════════════ HERO ═════ */

.hero { padding-block: var(--s-6) var(--s-5); }

.hero__griglia {
  display: grid;
  gap: var(--s-4);
  align-items: end;
}

.hero__titolo {
  font-size: var(--t-hero-home);
  font-weight: var(--w-light);
  line-height: var(--lh-stretta);
  letter-spacing: var(--ls-stretta);
  margin: 0;
}
.hero__titolo strong { font-weight: var(--w-bold); }
.hero__titolo em { font-style: italic; font-weight: var(--w-light); }

.hero__coda { max-width: 46ch; }
.hero__azioni {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: var(--s-3) 0 0;
}

@media (min-width: 900px) {
  .hero { padding-block: var(--s-7) var(--s-6); }
  .hero__griglia {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "testo  segno"
      "coda   segno";
    column-gap: var(--s-5);
  }
  .hero__testo { grid-area: testo; }
  .hero__segno { grid-area: segno; align-self: center; }
  .hero__coda  { grid-area: coda; margin-top: var(--s-4); }
}

/* ── L'asterisco: l'unico elemento vivo della pagina ────────────────────────
   Tre tracciati indipendenti, tre periodi primi fra loro. Il segno non gira
   mai su sé stesso: sembra vivo perché le tre barre non tornano in fase.
   Le ampiezze sono volutamente piccole. Oltre i pochi gradi diventa un
   gadget, categoria che il riferimento evita e noi con lui. */

.hero__segno { display: flex; justify-content: flex-end; }

.ast {
  /* ⚠️ Il minimo era 110px e su telefono diventava il pezzo più grande dello
     schermo: 28% della larghezza a 390px e 34% a 320px, contro un titolo di
     40px. Sotto i 740px il 15vw non entra mai in gioco, quindi comandava solo
     il minimo. Adesso il segno scala con lo schermo e resta un segno: 68px a
     390 (1,7 volte il corpo del titolo, come su desktop), e sopra i 740px
     nulla cambia perché lì vince il 15vw. */
  width: clamp(68px, 15vw, 300px);
  height: auto;
  color: var(--verde);
  overflow: visible;
}
.ast__t { fill: currentColor; transform-box: fill-box; transform-origin: center; }

/* Il gruppo è ciò che il puntatore muove: i tracciati dentro continuano il
   loro respiro, e i due movimenti si sommano invece di combattersi. */
.ast__g {
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(var(--ast-rot, 0deg)) translate(var(--ast-x, 0px), var(--ast-y, 0px));
}

.ast__t--1 { animation: ast-entra 700ms var(--e-out) both, ast-respiro-1 38s ease-in-out 1.2s infinite alternate; }
.ast__t--2 { animation: ast-entra 700ms var(--e-out) 90ms both, ast-respiro-2 46s ease-in-out 1.2s infinite alternate; }
.ast__t--3 { animation: ast-entra 700ms var(--e-out) 180ms both, ast-respiro-3 54s ease-in-out 1.2s infinite alternate; }

@keyframes ast-entra {
  from { transform: scale(0.62) rotate(-9deg); }
  to   { transform: scale(1) rotate(0deg); }
}
@keyframes ast-respiro-1 { from { transform: rotate(-3deg); } to { transform: rotate(3deg); } }
@keyframes ast-respiro-2 { from { transform: rotate(2.5deg); } to { transform: rotate(-2.5deg); } }
@keyframes ast-respiro-3 { from { transform: rotate(-2deg); } to { transform: rotate(2.5deg); } }

/* L'hero si anima in CSS e non con l'osservatore, come nella landing: un
   elemento sopra la piega che aspetta il JavaScript differito lampeggia. */
.hero__coda { animation: entra 900ms var(--e-out) 620ms both; }

/* ── I titoli di sezione, con la stessa maschera dell'hero ───────────────────
   Qui il momento lo decide l'osservatore del reveal, non un ritardo fisso. Il
   blocco non trasla piu' di 26px come gli altri: il movimento ce l'hanno gia'
   le righe, e due movimenti sovrapposti sullo stesso testo si impastano. */
.mask .riga {
  display: block;
  overflow: clip;
  padding: 0.08em 0.24em 0.26em;
  margin: -0.08em -0.24em -0.26em;
}
.mask .parola { display: inline-block; }
.js-anima .anima.mask { transform: none; }
.js-anima .mask .parola {
  transform: translateY(135%);
  transition: transform 1000ms cubic-bezier(0.22, 1, 0.36, 1);
}
.js-anima .mask .riga:nth-child(2) .parola { transition-delay: 90ms; }
.js-anima .anima.mask.dentro .parola,
.js-anima .dentro .mask .parola { transform: none; }

/* ── Il titolo che si compone ────────────────────────────────────────────────
   Quattro parole, quattro tempi. La riga e' una maschera e la parola sale da
   sotto: non c'e' dissolvenza, e non c'e' nemmeno un fotogramma in cui una
   parola si legga a meta'. La curva parte veloce e si posa, che e' quello che
   distingue un movimento costoso da un movimento rapido. */
.hero__titolo .riga {
  display: block;
  overflow: clip;
  /* La maschera deve stare FUORI dai glifi: con line-height 0.82 un clip a
     filo taglierebbe accenti e discendenti. */
  /* Il taglio deve cadere FUORI dai glifi su tutti i lati: sotto per le
     discendenti, a destra perche' con letter-spacing negativo l'ultima lettera
     sborda di qualche pixel oltre la larghezza calcolata. */
  padding: 0.1em 0.28em 0.3em;
  margin: -0.1em -0.28em -0.3em;
}
.hero__titolo .parola {
  display: inline-block;
  transform: translateY(135%);
  animation: sale 1100ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.hero__titolo .riga:nth-child(1) .parola:nth-child(1) { animation-delay: 120ms; }
.hero__titolo .riga:nth-child(1) .parola:nth-child(2) { animation-delay: 220ms; }
.hero__titolo .riga:nth-child(2) .parola:nth-child(1) { animation-delay: 320ms; }
.hero__titolo .riga:nth-child(2) .parola:nth-child(2) { animation-delay: 420ms; }

@keyframes sale { to { transform: translateY(0); } }

@keyframes entra { from { transform: translateY(26px); } }

/* ══════════════════════════════════════════════════════════ MARQUEE ═════ */

.marquee {
  overflow: hidden;
  border-block: 1px solid var(--hairline);
  padding-block: var(--s-2);
  font-size: clamp(1.5rem, 1rem + 2.4vw, 3rem);
  font-weight: var(--w-light);
  letter-spacing: var(--ls-stretta);
  /* Le maschere ai lati, larghe il 5% come nel riferimento: il testo non
     finisce contro il bordo, sfuma. */
  mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
}
.marquee__pista {
  display: flex;
  width: max-content;
  animation: scorri 90s linear infinite;
}
.marquee__gruppo {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding-right: 0.5em;
  white-space: nowrap;
}
.marquee__ast { width: 0.5em; height: auto; }

@keyframes scorri { to { transform: translateX(-33.3333%); } }

/* ═══════════════════════════════════════════════════════════ LAVORI ═════ */

.lavori__griglia { display: grid; gap: var(--s-4); }

.lavori {
  display: grid;
  gap: var(--s-5) var(--s-4);
}

@media (min-width: 1000px) {
  .lavori__griglia { grid-template-columns: minmax(18rem, min-content) minmax(0, 1fr); gap: var(--s-5); }
  .lavori { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lavoro--largo { grid-column: 1 / -1; }
  /* La colonna del titolo resta ferma mentre le schede scorrono. */
  .lavori__sticky { position: sticky; top: calc(var(--d-testata) + var(--s-3)); }
}

/* L'immagine porta allo stesso indirizzo del link sotto: è il primo posto dove
   si prova a cliccare. */
.lavoro__figura-link { display: block; text-decoration: none; }

/* ── Il puntatore che diventa asterisco ──────────────────────────────────────
   Il disco bianco non è decorazione: sopra una fotografia il verde del marchio
   sta a 1,70:1 e sul chiaro sparisce. Il disco è la stessa forma delle pill,
   l'unica curva che l'identità ammette, e tiene il segno leggibile su qualunque
   immagine. */
.cursore {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  /* 52px invece di 72: il disco deve bastare a tenere leggibile il segno sopra
     una fotografia, non a farsi guardare. */
  inline-size: 52px;
  block-size: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  background: #fff;
  display: grid;
  place-items: center;
  pointer-events: none;
  will-change: transform;
  /* L'entrata è lenta e parte da piccolo, l'uscita è più corta e torna
     piccola: il segno cresce sotto il puntatore invece di comparire. */
  transition: opacity 320ms var(--e-out), scale 420ms var(--e-out);
  opacity: 0;
  scale: 0.25;
}
.cursore--vivo { opacity: 1; scale: 1; }
.cursore--preme { scale: 0.86; transition-duration: 160ms; }
.cursore svg { inline-size: 22px; block-size: auto; }
.cursore__g {
  fill: var(--verde);
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(var(--giro, 0deg));
}
/* Il puntatore di sistema si toglie solo quando il nostro è davvero acceso: se
   il JavaScript non gira, la freccia resta dov'è. */
.js-cursore .lavoro__figura-link { cursor: none; }

@media (prefers-reduced-motion: reduce) {
  .cursore { display: none; }
  .js-cursore .lavoro__figura-link { cursor: pointer; }
}
/* Piu' aria fra l'immagine e cio' che la spiega: attaccate, sembrano una
   scheda di catalogo. */
.lavoro__figura { margin: 0 0 var(--s-3); overflow: clip; }

/* Le schede che hanno una fotografia vera prendono un taglio piu' alto: una
   foto regge il ritaglio e ci guadagna, uno screenshot di sito tagliato in
   verticale perde proprio la parte che lo rende leggibile. Gli screenshot
   restano nel loro 16:10 naturale. */
.lavoro--foto .lavoro__figura { aspect-ratio: 4 / 3; }
.lavoro--largo .lavoro__figura { aspect-ratio: 16 / 11; }
.lavoro--foto .lavoro__figura img {
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}
.lavoro__testo { padding-top: var(--s-1); }
.lavoro__figura img {
  width: 100%;
  transition: transform 600ms var(--e-out), clip-path 700ms var(--e-out);
}
/* L'immagine si scopre dal basso restando sempre a piena opacità. La
   dissolvenza sulla landing era già stata scartata per due ragioni misurate:
   l'LCP passava da 2,0 a 3,2 secondi, e a metà transizione il grigio del corpo
   scendeva a 2,79:1 di contrasto. */
.js-anima .lavoro .lavoro__figura img { clip-path: inset(0 0 12% 0); }
.js-anima .lavoro.dentro .lavoro__figura img { clip-path: inset(0); }
.lavoro:hover .lavoro__figura img { transform: scale(1.04); }


/* Il nome del cliente e' la cosa piu' grande della scheda. Prima lo era la
   riga dei servizi, che urlava in maiuscolo violet mentre il nome stava
   modesto sotto l'immagine: nei siti che abbiamo guardato il rapporto e'
   sempre l'opposto, ed e' quello che fa la differenza di tono. */
.lavoro__testo p:not(.lavoro__cosa) { display: none; }
/* Senza il paragrafo le schede hanno altezze diverse: si allineano in alto,
   o la griglia le stira tutte a quella piu' alta. */
.lavori .lavoro { align-self: start; }

.lavoro__testo h3 {
  font-size: clamp(1.5rem, 1.1rem + 1.1vw, 2.25rem);
  font-weight: var(--w-bold);
  line-height: 1.05;
  letter-spacing: -0.035em;
}

/* I servizi tornano a essere una didascalia: minuscoli, tenui, su una riga
   sola dove ci stanno. Il maiuscolo spaziato resta agli occhielli di sezione,
   che e' il posto dove dice qualcosa. */
.lavoro__cosa {
  font-size: 0.75rem;
  font-weight: var(--w-bold);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  line-height: 1.5;
  /* --viola-testo e non --viola: 5,81:1 contro 4,57:1, e qui il testo è a
     12px. Il violet pieno lo userebbe solo chi non deve leggerlo. */
  color: var(--viola-testo);
  margin-block: 0.55em 0;
  max-width: 40ch;
}

/* ══════════════════════════════════════════════════════════ SERVIZI ═════ */

.griglia-2 { display: grid; gap: var(--s-5); }
@media (min-width: 1000px) {
  .griglia-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-6); }
  .colonna-sticky { position: sticky; top: calc(var(--d-testata) + var(--s-4)); }
}

.servizi { list-style: none; margin: 0; padding: 0; }
.servizi li {
  padding: var(--s-3) 0;
  border-top: 1px solid var(--hairline);
  transition: transform var(--m-corto) var(--e-out),
              border-color var(--m-corto) linear;
}
.servizi li:last-child { border-bottom: 1px solid var(--hairline); }
.servizi li:hover, .servizi li:focus-within {
  border-top-color: var(--viola);
  transform: translateX(12px);
}
.servizi h3 {
  font-size: 1.125rem;
  font-weight: var(--w-bold);
  margin-bottom: 0.15em;
}
.servizi p { margin: 0; color: var(--testo-tenue); }

/* ═══════════════════════════════════════════════════════════ METODO ═════
   I numeri restano solo qui, e diventano quelli grandi che l'identità
   prescrive per i dati: Bold, crenaggio stretto. Erano tre elenchi numerati in
   pagina, adesso è uno solo e conta.

   La sezione sta su una banda piena, che il brand prevede e che in tutta la
   pagina non usavamo mai: il bianco dominante ha bisogno di un punto in cui si
   interrompe, o diventa vuoto invece che aria.

   Il filo attraversa i quattro passi e si colora un segmento alla volta
   all'ingresso. Al passaggio del mouse il passo sotto il puntatore resta
   pieno e gli altri si ritirano: è l'unica interazione della sezione, e dice
   «uno alla volta», che è poi come si lavora. */

.passi {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s-5);
}
.passo {
  position: relative;
  padding-top: var(--s-3);
  transition: opacity 640ms var(--e-out), transform 640ms var(--e-out);
}
.passo__filo {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: rgba(255,255,255,0.28);
}
.passo__filo::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--verde);
  transform-origin: left;
  transition: transform var(--m-lungo) var(--e-out), height var(--m-corto) var(--e-inout);
}
.js-anima .passo .passo__filo::before { transform: scaleX(0); }
.js-anima .passo.dentro .passo__filo::before { transform: scaleX(1); }

.passo__numero {
  display: block;
  font-size: clamp(3rem, 1rem + 5.4vw, 7.5rem);
  font-weight: var(--w-bold);
  line-height: 1;
  letter-spacing: -0.06em;
  color: #fff;
  margin-bottom: 0.15em;
  transition: color 640ms var(--e-out);
}
.passo h3 {
  font-size: 1.25rem;
  font-weight: var(--w-bold);
  margin-bottom: 0.35em;
}
.passo p { color: rgba(255,255,255,0.82); margin: 0; max-width: 34ch; }

/* Il passo sotto il puntatore resta pieno, gli altri arretrano. Solo dove un
   puntatore esiste: su un dito questo stato non si può nemmeno esprimere, e
   una sezione a metà opacità senza motivo è solo un difetto. */
@media (hover: hover) and (pointer: fine) {
  /* 0,55 e non 0,4: deve sembrare che gli altri passi arretrino, non che si
     spengano. E la salita del passo attivo e' di quattro pixel, cioe' quanto
     basta perche' si senta senza che si veda. */
  .passi:hover .passo:not(:hover) { opacity: 0.55; }
  .passi:hover .passo:not(:hover) .passo__numero { color: rgba(255,255,255,0.6); }
  .passi:hover .passo:hover { transform: translateY(-4px); }
  .passo:hover .passo__filo::before { height: 2px; }
}

@media (min-width: 1000px) {
  .passi { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
  .passo { padding-right: var(--s-3); }
  .passo__filo { right: var(--s-3); }
}

/* La banda: fondo pieno, testo bianco, e il verde solo sul filo che avanza.
   Un accento per sezione, come dice l'identità. */
#metodo.sezione--banda {
  background: var(--viola-banda);
  color: #fff;
}
#metodo.sezione--banda .occhiello { color: var(--verde); }

/* ══════════════════════════════════════════════════════════ PERSONE ═════ */

.fascia { padding-block: var(--s-7); }
.fascia__interno { display: grid; gap: var(--s-5); }
@media (min-width: 900px) {
  .fascia__interno { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: center; gap: var(--s-6); }
}

.soci { list-style: none; margin: var(--s-4) 0 0; padding: 0; display: grid; gap: var(--s-3); }
.soci li { display: flex; align-items: center; gap: var(--s-2); }
.soci img {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  object-fit: cover;
  transition: transform 420ms var(--e-out), outline-color 220ms linear;
  outline: 1px solid transparent;
  outline-offset: 4px;
}
.soci li:hover img { transform: scale(1.04); outline-color: var(--viola); }
.soci span { display: flex; flex-direction: column; font-size: var(--t-small); color: var(--testo-tenue); }
.soci strong { font-size: 1rem; color: var(--testo); }

/* ══════════════════════════════════════════════════════════ DOMANDE ═════
   <details> nativi. Tastiera, lettori di schermo e funzionamento senza
   JavaScript arrivano gratis, e non c'è un attributo ARIA da tenere allineato
   a mano. Dove ::details-content non è supportato l'apertura è istantanea:
   la pagina funziona, manca solo la transizione. */

.domande { display: grid; }
.domanda { border-top: 1px solid var(--hairline); }
.domanda:last-child { border-bottom: 1px solid var(--hairline); }

.domanda summary {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  padding: var(--s-3) 0;
  cursor: pointer;
  list-style: none;
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.375rem);
  font-weight: var(--w-bold);
  letter-spacing: var(--ls-stretta);
  transition: color var(--m-micro) linear;
}
.domanda summary::-webkit-details-marker { display: none; }
.domanda summary:hover { color: var(--viola-testo); }
.domanda summary span { flex: 1; }
.domanda summary::after {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 0.35em;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 1.5px no-repeat,
    linear-gradient(currentColor, currentColor) center / 1.5px 100% no-repeat;
  transition: transform var(--m-corto) var(--e-inout);
}
.domanda[open] summary::after { transform: rotate(45deg); }

.domanda__corpo { padding-bottom: var(--s-3); }
.domanda__corpo p { margin: 0; color: var(--testo-tenue); max-width: 68ch; }

@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }
  .domanda::details-content {
    block-size: 0;
    overflow: clip;
    transition: block-size var(--m-corto) var(--e-inout),
                content-visibility var(--m-corto) allow-discrete;
  }
  .domanda[open]::details-content { block-size: auto; }
}

/* ═════════════════════════════════════════════════════════ CONTATTI ═════ */

.contatti__asterisco { width: 44px; margin-bottom: var(--s-2); }
/* Il titolo giga ha line-height 0.82: senza un respiro esplicito la riga
   successiva gli finisce addosso. */
.contatti .titolo-giga { margin-bottom: var(--s-3); }
@media (min-width: 1000px) { .contatti .griglia-2 { align-items: start; } }

.modulo { display: grid; gap: var(--s-2); }
.campo { display: grid; gap: 0.35rem; position: relative; }
.campo label { font-size: var(--t-small); font-weight: var(--w-bold); }
.campo__nota { font-weight: var(--w-normal); color: var(--testo-tenue); }

.campo input, .campo textarea {
  font: inherit;
  color: inherit;
  background: #fff;
  border: 0;
  border-bottom: 1.5px solid var(--bordo-campo);
  border-radius: 0;
  padding: 0.7em 0.1em;
  width: 100%;
}
.campo textarea { resize: vertical; }

/* ── Le etichette flottanti ────────────────────────────────────────────────
   ⚠️ BLOCCO GEMELLO, e la copia è il punto: questo pezzo esiste identico
   qui, in demo-motion/demo.r1.css e in lavori/caso.css. Il modulo della
   chiusura è LO STESSO oggetto sulle due pagine (docs 17.2), e due copie che
   divergono sono un modulo che si comporta in due modi. Chi tocca una riga qui
   la tocca anche di là.

   COSA FA: l'etichetta parte al posto del testo, dentro al campo, e quando il
   campo prende il fuoco o contiene qualcosa si rimpicciolisce e sale nello
   spazio che il padding le tiene libero in cima.

   ZERO JAVASCRIPT, ed è una misura e non un risparmio: lo stato «contiene
   qualcosa» il browser lo sa già (`:placeholder-shown`), e saperlo da CSS vuol
   dire che è giusto anche nei tre casi in cui una classe scritta a mano dal
   JavaScript arriva tardi o non arriva — il riempimento automatico, il
   ricaricamento con i campi ripescati dal browser, e il ritorno indietro dalla
   cache di navigazione. Una versione a JavaScript avrebbe dovuto riascoltare
   tutti e tre; questa non ha niente da riascoltare.

   L'ETICHETTA RESTA UNA `<label for>` e non diventa un `placeholder`: un
   segnaposto sparisce mentre scrivi e non è un nome accessibile affidabile. Il
   `placeholder=" "` del markup accende solo `:placeholder-shown`: è uno spazio
   e non dice niente a nessuno.

   `campo--flottante` È UNA CLASSE CHE DICE SÌ. Il modo ovvio sarebbe stato
   escludere («tutti i campi tranne il consenso»), e regge finché il modulo non
   cambia: un controllo senza segnaposto — spunta, radio, select — soddisfa
   `:not(:placeholder-shown)` sempre, e con la logica per esclusione erediterebbe
   lo stato flottante in silenzio il giorno che lo si aggiunge. Qui un campo
   entra nel meccanismo solo se qualcuno ce lo ha scritto.

   `pointer-events: none` È DELIBERATO: senza, l'etichetta sta sopra il campo e
   il clic se lo prende lei. Con, il clic attraversa e arriva al campo — che è
   tutta l'area cliccabile che serve, perché l'etichetta ci sta sopra.

   `font-size: 1rem` (16 px) sui controlli NON È DECORATIVO: sotto i 16 px iOS
   ingrandisce la pagina da sé quando il campo prende il fuoco, e poi non la
   rimpicciolisce più. Era già così per eredità (`font: inherit` da `--t-body`);
   adesso è scritto, perché adesso è un vincolo.

   NIENTE SALTI DI ALTEZZA: l'etichetta è fuori dal flusso e fra i due stati
   cambiano solo `top`, `font-size` e colore. E l'etichetta è ancorata IN ALTO
   con un valore fisso, mai a `top: 50%`: quando la validazione appende
   `.campo__errore` il contenitore cresce, e con `50%` l'etichetta scenderebbe
   insieme a lui.

   CONTRASTI, sul bianco del campo: a riposo `--testo-tenue` #6B6B6B sta a
   5,33:1, da flottante `--viola-testo` #6B5C99 a 5,81:1. Tutti e due sopra il
   4,5:1, e il secondo conta doppio perché da flottante l'etichetta è a 12 px. */
.campo.campo--flottante > label {
  position: absolute;
  left: 0.1em;
  /* 1.6rem è il padding in cima del campo, cioè esattamente il punto in cui
     comincia quello che scrivi: a riposo l'etichetta sta sulla riga del testo. */
  top: 1.6rem;
  max-width: calc(100% - 0.2em);
  font-size: 1rem;
  font-weight: var(--w-normal);
  line-height: var(--lh-larga);
  color: var(--testo-tenue);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  transition: top var(--m-corto) var(--e-out),
              font-size var(--m-corto) var(--e-out),
              color var(--m-corto) var(--e-out);
}
.campo.campo--flottante > input,
.campo.campo--flottante > textarea {
  font-size: 1rem;
  line-height: var(--lh-larga);
  /* Lo spazio in cima è quello in cui l'etichetta sale: senza, si
     sovrapporrebbe a quello che stai scrivendo. */
  padding: 1.6rem 0.1em 0.5rem;
}
.campo.campo--flottante > input:focus + label,
.campo.campo--flottante > input:not(:placeholder-shown) + label,
.campo.campo--flottante > textarea:focus + label,
.campo.campo--flottante > textarea:not(:placeholder-shown) + label {
  top: 0.15rem;
  font-size: 0.75rem;
  font-weight: var(--w-bold);
  color: var(--viola-testo);
}
/* ⚠️ I due pseudo del riempimento automatico stanno in DUE regole separate e
   non in coda alla virgolata qui sopra: un selettore sconosciuto invalida TUTTO
   l'elenco in cui si trova, e `:autofill` senza prefisso i motori vecchi non lo
   conoscono. Separati, chi non lo conosce butta via solo la riga sua.
   A cosa servono, visto che un valore riempito fa già scattare
   `:not(:placeholder-shown)`: all'ANTEPRIMA. Mentre si passa sopra una voce del
   menù di riempimento il testo si vede già nel campo ma `value` è ancora vuoto,
   quindi il segnaposto risulta ancora mostrato e l'etichetta grande resterebbe
   sopra il testo in anteprima. Il riempimento vero, quello confermato, funziona
   anche senza queste due regole: è stato provato. */
.campo.campo--flottante > input:-webkit-autofill + label {
  top: 0.15rem;
  font-size: 0.75rem;
  font-weight: var(--w-bold);
  color: var(--viola-testo);
}
.campo.campo--flottante > input:autofill + label {
  top: 0.15rem;
  font-size: 0.75rem;
  font-weight: var(--w-bold);
  color: var(--viola-testo);
}
/* Un campo riempito dal browser resta un campo di questo modulo: senza questa
   riga Chrome gli dipinge sopra il suo fondo azzurrino, che sotto una hairline
   viola si legge come un errore. Il testo resta il nostro, non il suo. */
.campo.campo--flottante > input:-webkit-autofill,
.campo.campo--flottante > input:-webkit-autofill:hover,
.campo.campo--flottante > input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--bianco) inset;
  -webkit-text-fill-color: var(--testo);
  caret-color: var(--testo);
}
/* In errore l'etichetta prende il rosso del messaggio che le sta sotto: #A5281B
   sta a 7,19:1 sul bianco del campo. La virgolata nomina `input`/`textarea` non
   per vezzo ma per peso: le regole dello stato flottante qui sopra hanno una
   specificità di (0,3,2), e un `.campo--errore > label` secco (0,3,1) perderebbe
   proprio sul campo pieno, che è l'unico caso in cui un errore si vede. */
.campo.campo--flottante.campo--errore > input + label,
.campo.campo--flottante.campo--errore > textarea + label { color: #A5281B; }

@media (prefers-reduced-motion: reduce) {
  .campo.campo--flottante > label { transition: none; }
}
/* La hairline del campo si colora da sinistra quando il campo prende il
   fuoco: è l'unico movimento del modulo, e dice dove stai scrivendo. */
.campo::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1.5px;
  background: var(--viola);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 220ms var(--e-out);
  pointer-events: none;
}
.campo:focus-within::after { transform: scaleX(1); }

/* Sui campi il rettangolo di focus è di troppo: il campo è già un rettangolo,
   e l'anello ne disegna un secondo appena fuori. L'indicatore qui è la barra
   sotto al campo, che si colora da sinistra e si ingrossa: sta sopra il 3:1
   richiesto e occupa più area di un bordo da 1px, che è la soglia di WCAG. */
.campo input:focus-visible,
.campo textarea:focus-visible { outline: none; }
.campo:focus-within::after { block-size: 3px; }
.campo:focus-within input,
.campo:focus-within textarea { border-bottom-color: var(--viola); }
/* La casella del consenso non ha una barra sotto: lì l'anello resta. */
.campo--consenso input:focus-visible { outline: 3px solid var(--viola); outline-offset: 3px; }
.campo--consenso::after { display: none; }

.campo--consenso {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--s-1);
  margin-top: var(--s-2);
}
.campo--consenso input {
  /* 24px netti: sotto, il bersaglio non rispetta il minimo di WCAG 2.5.8. */
  inline-size: 24px;
  block-size: 24px;
  margin: 0;
  accent-color: var(--viola);
}
/* Il messaggio di errore prende tutta la riga: dentro la colonna della
   checkbox ridisegnerebbe la griglia e staccherebbe la casella dalla sua
   etichetta. */
.campo--consenso .campo__errore { grid-column: 1 / -1; }
.campo--consenso label { font-weight: var(--w-normal); font-size: var(--t-small); color: var(--testo-tenue); }

/* L'esca per i bot: fuori dallo schermo, mai display:none, che alcuni bot
   riconoscono. */
.esca { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ⚠️ Ricopiate da style.css: sono le classi che modulo.js scrive a runtime.
   Senza, un errore di validazione non si vedrebbe. */
.campo--errore input, .campo--errore textarea { border-bottom-color: #C0392B; }
.campo__errore { color: #A5281B; font-size: var(--t-small); margin: 0.2rem 0 0; }
.modulo__esito { margin: var(--s-2) 0 0; font-size: var(--t-small); }
.modulo__esito--ok { color: #1E7A4C; }
.modulo__esito--ko { color: #A5281B; }

.modulo .bottone { justify-self: start; margin-top: var(--s-2); }

/* ══════════════════════════════════════════════════════════════ PIÈ ═════ */

.pie { padding-block: var(--s-5) var(--s-4); border-top: 1px solid var(--hairline); }
.pie__alto { display: flex; flex-wrap: wrap; gap: var(--s-3); padding-bottom: var(--s-3); border-bottom: 1.5px solid var(--verde); }
.pie__alto p { margin: 0; }
.pie__dati { display: grid; gap: var(--s-3); padding-top: var(--s-3); font-size: var(--t-small); color: var(--testo-tenue); }
.pie__dati strong { color: var(--testo); }
.pie__dati a { color: inherit; }
@media (min-width: 720px) { .pie__dati { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.social { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-3); margin: var(--s-4) 0 0; padding: var(--s-3) 0 0; border-top: 1px solid var(--hairline); }
.social a { display: inline-flex; align-items: center; gap: 0.5em; text-decoration: none; font-size: var(--t-small); font-weight: var(--w-bold); }
.social a:hover { color: var(--viola-testo); }

/* ═════════════════════════════════════════════════════════ INGRESSO ═════
   ⚠️ Ricopiate verbatim da style.css, perché la home non carica più quel foglio.
   Lo stato nascosto esiste SOLO se il JavaScript gira e ha aggiunto
   `js-anima`: senza JS la pagina è ferma e completa, non invisibile.
   E il movimento è solo traslazione, mai dissolvenza: la dissolvenza era
   costata 1,2 s di LCP e portava il grigio del corpo sotto il 3:1 a metà
   transizione. Non si reintroduce. */

.js-anima .anima {
  transform: translateY(26px);
  transition: transform var(--m-reveal) var(--e-out);
}
.js-anima .anima.dentro { transform: none; }

/* Dentro un blocco che entra, le parti non partono insieme e non partono in
   fila: partono per quello che sono. Il titolo per primo, il testo dopo un
   sospiro, l'immagine per ultima. Vale dove gli elementi hanno ruoli diversi;
   dove sono tutti uguali, come le sette schede dei lavori, conta la posizione
   e si usa lo stagger qui sotto. */
.js-anima [data-entra="titolo"] { transition-delay: 0ms; }
.js-anima [data-entra="testo"]  { transition-delay: 150ms; }
.js-anima [data-entra="media"]  { transition-delay: 200ms; }
.js-anima [data-entra="coda"]   { transition-delay: 400ms; }

/* Lo stagger: 70 ms l'uno, con un tetto a cinque posizioni. Su sette schede la
   differenza fra un ritmo e un'attesa sta tutta in quel tetto.
   ⚠️ L'indice arrivava da un attributo style="--i:N" in HTML. Non si fa più:
   quell'attributo vive solo finché la CSP concede 'unsafe-inline' sugli stili,
   e il giorno che la si stringe lo stagger sparirebbe senza un errore. Le
   posizioni le contano i selettori, che nessuna policy può togliere. */
.js-anima .lavoro:nth-child(2)  { transition-delay: 70ms; }
.js-anima .lavoro:nth-child(3)  { transition-delay: 140ms; }
.js-anima .lavoro:nth-child(4)  { transition-delay: 210ms; }
.js-anima .lavoro:nth-child(5)  { transition-delay: 280ms; }
.js-anima .lavoro:nth-child(n+6) { transition-delay: 350ms; }
.js-anima .domanda:nth-child(2) { transition-delay: 70ms; }
.js-anima .domanda:nth-child(3) { transition-delay: 140ms; }
.js-anima .domanda:nth-child(4) { transition-delay: 210ms; }
.js-anima .domanda:nth-child(5) { transition-delay: 280ms; }
.js-anima .domanda:nth-child(n+6) { transition-delay: 350ms; }
.js-anima .passo:nth-child(2)   { transition-delay: 70ms; }
.js-anima .passo:nth-child(3)   { transition-delay: 140ms; }
.js-anima .passo:nth-child(4)   { transition-delay: 210ms; }

/* ════════════════════════════════════════════ MOVIMENTO RIDOTTO ═════════
   tokens.css azzera già transizioni e animazioni con !important. Qui restano
   le cose che quel blocco non può sistemare: ciò che senza movimento
   resterebbe nascosto, tagliato o irraggiungibile. */

@media (prefers-reduced-motion: reduce) {
  /* Senza scorrimento le voci oltre il bordo andrebbero perse. Non si mette
     uno scroller: il marquee è aria-hidden, e un elemento che scorre entra nel
     giro di tabulazione portando il fuoco dove nessun lettore di schermo
     annuncia niente. Si manda a capo, e si tiene un gruppo solo. */
  .marquee__pista { animation: none; transform: none; flex-wrap: wrap; }
  .marquee__gruppo { white-space: normal; }
  .marquee__gruppo + .marquee__gruppo { display: none; }
  .marquee { mask-image: none; }
  .testata--nascosta { transform: none; }
  .bottone::before { transition: none; }
  .js-anima .lavoro .lavoro__figura img { clip-path: inset(0); }
  .js-anima .passo .passo__filo::before { transform: none; }
  .ast__t { animation: none; }
  .ast__g { transform: none; }
}

/* ── Il bottone delle preferenze cookie, copiato da style.css ──────────────
   Riapre il pannello di cookieconsent (data-cc="show-preferencesModal"). La
   scelta sui cookie si deve poter cambiare in ogni momento: senza questo
   bottone il consenso dato una volta non si ritira più. */
.pie__preferenze {
  display: inline-block;
  margin-top: 4px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.pie__preferenze:hover { text-decoration-thickness: 2px; }
.pie__preferenze:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
