/* ============================================================================
   motion.r1.css — il movimento condiviso fra le pagine del sito.

   Nasce dalla demo in /demo-motion/ (settembre 2026) e ne tiene solo la parte
   che non dipende da quel layout: i tempi, le curve, le maschere tipografiche,
   il riempimento delle pill. Tutto ciò che era legato a quella pagina, come il
   puntatore ad asterisco o l'anteprima dei servizi, è rimasto lì.

   Si carica DOPO tokens.css e fonts.css, e prima del foglio della pagina, che
   può sempre sovrascrivere.

       <link rel="stylesheet" href="../assets/css/tokens.css">
       <link rel="stylesheet" href="../assets/css/fonts.css">
       <link rel="stylesheet" href="../assets/css/motion.r1.css">
       <link rel="stylesheet" href="../assets/css/bando.css">

   Dipende da entrata.js per il reveal, che è già in produzione e già caricato
   dalla home. Il resto è CSS puro e non chiede niente a nessuno.

   ⚠️ Il suffisso r1 è la revisione: la docroot mette `immutable` per un anno
   sui .css, quindi un cambiamento di contenuto vuole un nome nuovo (r2) e il
   <link> aggiornato nelle pagine che lo usano. Non si modifica in silenzio un
   file che tre pagine condividono.

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

:root {
  --m-micro: 180ms;   /* hairline, frecce, colore */
  --m-corto: 260ms;   /* accordion, righe di elenco */
  --m-lungo: 520ms;   /* segmenti, 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);
  --e-posa: cubic-bezier(0.22, 1, 0.36, 1);      /* parte veloce e si posa */
}

/* ══════════════════════════════════════════════════════════ INGRESSO ═════
   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. Non è una preferenza:
   sulla landing la dissolvenza costava 1,2 s di LCP e a metà transizione
   portava il grigio del corpo a 2,79:1 di contrasto. Chi la reintroduce
   rifaccia prima quelle due misure. */

.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. */
.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 di posizione, con un tetto a cinque: sopra, la coda diventa
   attesa. Le classi invece di un attributo `style`, che vive solo finché la
   CSP concede 'unsafe-inline' sugli stili e sparirebbe senza un errore. */
.js-anima .ritardo-1 { transition-delay: 70ms; }
.js-anima .ritardo-2 { transition-delay: 140ms; }
.js-anima .ritardo-3 { transition-delay: 210ms; }
.js-anima .ritardo-4 { transition-delay: 280ms; }
.js-anima .ritardo-5 { transition-delay: 350ms; }

/* ═══════════════════════════════════════════════ MASCHERE TIPOGRAFICHE ═════
   La riga è una maschera e la parola sale da sotto: il titolo non appare,
   entra. Nessuna dissolvenza, e nessun fotogramma in cui una parola si legga
   a metà.

   Markup:
       <h2 class="titolo-2 mask">
         <span class="riga"><span class="parola">Prima riga</span></span>
         <span class="riga"><span class="parola">Seconda riga</span></span>
       </h2>

   ⚠️ Il taglio deve cadere FUORI dai glifi su tutti e quattro i lati:
   `overflow: clip` taglia anche a destra, e con letter-spacing negativo
   l'ultima lettera sborda oltre la larghezza calcolata. Da qui il padding con
   il margine negativo che lo compensa. */

.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; }

/* Il blocco non trasla più di 26px come gli altri: il movimento ce l'hanno le
   righe, e due movimenti sullo stesso testo si impastano. */
.js-anima .anima.mask { transform: none; }
.js-anima .mask .parola {
  transform: translateY(135%);
  transition: transform 1000ms var(--e-posa);
}
.js-anima .mask .riga:nth-child(2) .parola { transition-delay: 90ms; }
.js-anima .mask .riga:nth-child(3) .parola { transition-delay: 180ms; }
/* Due casi: l'elemento che ha `dentro` su di sé, e quello che lo eredita dal
   genitore. Quasi sempre è il secondo, perché `anima` sta sul contenitore. */
.js-anima .anima.mask.dentro .parola,
.js-anima .dentro .mask .parola { transform: none; }

/* ══════════════════════════════════════════════════ PILL CHE SI RIEMPIE ═════
   Il riempimento sale da sinistra e il testo resta leggibile per tutta la
   transizione. Il roll-up con l'etichetta che esce e l'eco che entra, che è il
   pattern di moda, a metà strada mostra due mezze parole: su una chiamata
   all'azione è il momento in cui la persona sta decidendo, e non è il momento
   di togliere le parole. Provato e bocciato il 2026-09-12.

   Serve solo la classe sul bottone, nessun markup interno. */

.riempi {
  position: relative;
  overflow: clip;
  isolation: isolate;
}
.riempi::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Dietro il contenuto: quando il testo non sta dentro uno span, un
     riempimento sopra lo coprirebbe del tutto. */
  z-index: -1;
  border-radius: inherit;
  background: var(--viola, #7B6CAE);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 350ms var(--e-inout);
}
.riempi:hover::before,
.riempi:focus-visible::before { transform: scaleX(1); }
.riempi:hover, .riempi:focus-visible { color: #fff; }

/* ════════════════════════════════════════════════════════ SCORRIMENTO ═════
   Le tre regole che Lenis si aspetta, per chi carica anche motion.r1.js con
   lo scorrimento smorzato acceso. Senza Lenis non fanno niente.
   ⚠️ `scroll-behavior: smooth` e Lenis insieme litigano: un salto a un
   ancoraggio verrebbe animato da due motori. tokens.css lo mette su html,
   quindi qui va spento finché Lenis è acceso. */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* ══════════════════════════════════════════════════ 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 o tagliato. */
@media (prefers-reduced-motion: reduce) {
  .riempi::before { transition: none; }
  .mask .riga { overflow: visible; }
}
