/* =========================================================================
   Stati del sistema di movimento.

   REGOLA: il valore scritto qui e sempre lo STATO FINALE. Lo stato di
   partenza esiste solo sotto [data-moto="attivo"], che lo mette il
   JavaScript. Senza JavaScript, o con prefers-reduced-motion, la pagina e
   gia completa e nessuna regola la nasconde.
   ========================================================================= */

/* ---- Terreno del documento ---------------------------------------------
   Il fondo e uno stato del documento, non un colore per sezione: cosi la
   testata e tutto il resto si adeguano insieme, senza regole doppie.       */

html {
  background: var(--c-bianco);
  transition: background-color 700ms var(--e-in-out);
}
html[data-terreno-attivo="grafite"] { background: var(--c-grafite); }
html[data-terreno-attivo="grafite"] body { color: var(--c-bianco); }
html[data-terreno-attivo="grafite"] .testata {
  background: color-mix(in oklab, var(--c-grafite) 82%, transparent);
  border-bottom-color: var(--c-filetto-scuro);
  color: var(--c-bianco);
}
body { background: transparent; transition: color 700ms var(--e-in-out); }

/* ---- Rivelazione per maschera -------------------------------------------
   Il testo scorre da sotto un bordo netto: si scopre, non compare.         */

[data-moto="attivo"] [data-svela] [data-riga] {
  display: block;
  transform: translateY(105%);
  opacity: 0;
  transition:
    transform 640ms var(--e-out),
    opacity 360ms linear;
  will-change: transform;
}
[data-moto="attivo"] [data-svela][data-svelato] [data-riga] {
  transform: translateY(0);
  opacity: 1;
}
/* La maschera deve essere piu alta della riga, altrimenti taglia i propri
   ascendenti: con line-height sotto 1 il Bodoni esce dal suo box. Si allarga
   il riquadro di ritaglio e si compensa con margini negativi, cosi la
   spaziatura visiva resta identica. */
.riga-maschera {
  display: block;
  overflow: hidden;
  padding-block: 0.16em 0.14em;
  margin-block: -0.16em -0.14em;
}

/* immagini: si aprono dal basso con una maschera, senza scala */
[data-moto="attivo"] [data-svela][data-svela-media] {
  clip-path: inset(100% 0 0 0);
  transition: clip-path 720ms var(--e-out);
  will-change: clip-path;
}
[data-moto="attivo"] [data-svela][data-svela-media][data-svelato] {
  clip-path: inset(0% 0 0 0);
}

/* ---- Dispersione --------------------------------------------------------
   Tre copie sovrapposte. Ferme coincidono e l immagine e pulita; in
   movimento i due strati tinti si separano e il bordo si scompone.         */

.dispersione { position: relative; overflow: hidden; isolation: isolate; }
.dispersione__strato {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}
.dispersione__strato--freddo { mix-blend-mode: screen; filter: saturate(2.4) hue-rotate(-28deg); }
.dispersione__strato--caldo  { mix-blend-mode: screen; filter: saturate(2.4) hue-rotate(24deg); }
.dispersione__base { position: relative; display: block; width: 100%; height: 100%; object-fit: cover; }

/* filo spettrale: l unico momento cromatico pieno, e spesso 1px */
.filo-spettro {
  height: 1px;
  border: 0;
  background: var(--spettro);
  background-size: 300% 100%;
  opacity: 0.85;
}
[data-moto="attivo"] .filo-spettro { animation: scorri-spettro 14s linear infinite; }
@keyframes scorri-spettro {
  to { background-position: 300% 0; }
}

/* ---- Scheda prodotto ----------------------------------------------------
   Lo scambio di fotografia passa per un lampo di dispersione: un battito,
   non una dissolvenza lenta. E il gesto che distingue il catalogo.         */

.scheda { position: relative; }
.scheda__cornice {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--c-nebbia);
  aspect-ratio: 1 / 1;
}
.scheda__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--e-out), opacity 260ms linear;
}
.scheda__foto--seconda {
  position: absolute;
  inset: 0;
  opacity: 0;
}
@media (hover: hover) {
  .scheda:hover .scheda__foto--prima { opacity: 0; }
  .scheda:hover .scheda__foto--seconda { opacity: 1; }
  .scheda:hover .scheda__foto { transform: scale(1.035); }
  .scheda__cornice--doppia::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--spettro);
    mix-blend-mode: overlay;
    opacity: 0;
    pointer-events: none;
  }
  .scheda:hover .scheda__cornice--doppia::after { animation: lampo 420ms var(--e-out); }
}
@keyframes lampo {
  0%   { opacity: 0; }
  35%  { opacity: 0.4; }
  100% { opacity: 0; }
}

.scheda__nome {
  font-family: var(--f-testo);
  font-size: var(--t-s);
  font-weight: 400;
  letter-spacing: 0.01em;
}

/* ---- Palcoscenico ------------------------------------------------------- */

.palco { position: relative; min-height: 100svh; display: grid; }
.palco__media { position: relative; overflow: hidden; }
.palco__media img { width: 100%; height: 100%; object-fit: cover; will-change: transform; }
.palco__passo { grid-area: 1 / 1; }

/* su schermo stretto il pin si disattiva: i passi tornano in colonna */
[data-palco-semplice] .palco__passo {
  grid-area: auto;
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
}

/* ---- Deriva ------------------------------------------------------------- */

.deriva { overflow: hidden; }
.deriva__nastro { display: flex; gap: var(--gutter); will-change: transform; }
.deriva__pezzo { flex: 0 0 clamp(15rem, 26vw, 26rem); }

/* ---- Puntatore ---------------------------------------------------------- */

[data-puntatore-piano] { will-change: transform; }

/* =========================================================================
   Rispetto assoluto della preferenza di sistema: nessun movimento, nessuno
   stato nascosto, nessuna trasformazione residua.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .dispersione__strato { display: none; }
  html { transition: none; }
}

/* =========================================================================
   APERTURA — rivelazione immediata, senza JavaScript.

   Il titolo sta sopra la piega: non puo aspettare un IntersectionObserver che
   vive in un modulo differito dietro GSAP. Misurato, arrivava tre secondi
   dopo il caricamento. Qui parte da solo, al primo fotogramma utile.

   Lo stato finale resta quello scritto: se l animazione non parte, o se
   l utente ha ridotto il movimento, il titolo e gia al suo posto.
   ========================================================================= */

.apertura__titolo [data-riga] {
  display: block;
  transform: translateY(0);
  opacity: 1;
}

[data-moto="attivo"] .apertura__titolo [data-riga] {
  animation: sale-maschera 1000ms var(--e-out) both;
  will-change: transform;
}
[data-moto="attivo"] .apertura__riga:nth-child(1) [data-riga] { animation-delay: 60ms; }
[data-moto="attivo"] .apertura__riga:nth-child(2) [data-riga] { animation-delay: 170ms; }
[data-moto="attivo"] .apertura__riga:nth-child(3) [data-riga] { animation-delay: 280ms; }

@keyframes sale-maschera {
  from { transform: translateY(104%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* la fotografia dell apertura entra con la stessa legge, appena dopo */
[data-moto="attivo"] .apertura__media {
  animation: apre-media 1200ms var(--e-out) 220ms both;
}
@keyframes apre-media {
  from { clip-path: inset(0 0 100% 0); }
  to   { clip-path: inset(0 0 0% 0); }
}

@media (prefers-reduced-motion: reduce) {
  [data-moto] .apertura__titolo [data-riga],
  [data-moto] .apertura__media { animation: none !important; }
}
