/* ============================================================
   VELUM — motion.css
   Le primitive del movimento: veli, preloader, maschere di riga,
   cursore, header in blend mode.

   Regola di sopravvivenza: tutto ciò che nasconde qualcosa è
   dentro `.motion-on`, classe che JS aggiunge SOLO se GSAP è
   arrivato e l'utente non ha chiesto meno movimento. Senza JS,
   senza CDN o con reduced-motion il sito resta interamente
   leggibile.
   ============================================================ */

/* ---- Lenis ------------------------------------------------
   Le poche righe che la libreria richiede, inlineate invece di
   caricare un secondo file dal CDN. */
html.lenis,
html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* ---- Stato iniziale dei reveal ----------------------------
   Invertito rispetto alla prima versione: il contenuto è
   visibile di default e il movimento lo nasconde, non il
   contrario. */
.motion-on [data-reveal] {
  opacity: 0;
  transform: translateY(1.75rem);
  will-change: transform, opacity;
}

/* Le righe spezzate da splitLines(): ogni riga è una feritoia,
   il testo entra da sotto come scoperto da un velo che passa.
   Il nome è .vline e non .line perché .line è già la riga di
   prodotto del carrello — una griglia con padding e bordo. */
.vline {
  display: block;
  overflow: hidden;
  padding: 0.08em 0 0.22em;
  margin: -0.08em 0 -0.22em;
}
.vline__inner {
  display: block;
  transform-origin: 0 100%;
}
/* Nessuno stato iniziale qui dentro: lo stato di partenza lo mette
   gsap.set() nello stesso istante in cui crea le righe. Dichiararlo
   anche in CSS significava far leggere a GSAP un translateY(110%)
   già presente, che finiva incatenato al suo — e il testo restava
   fuori dalla feritoia per sempre. */
.motion-on .vline__inner { will-change: transform; }

/* ---- Il velo tra le pagine --------------------------------
   Tre pannelli fissi che scendono dall'alto, coprono, e
   risalgono sulla pagina nuova. */
.veil {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  pointer-events: none;
}
.veil__panel {
  background: var(--bone);
  transform: translateY(-101%);
  will-change: transform;
}
.veil[data-state="covering"] { pointer-events: all; }

/* Senza JS il velo non deve mai esistere sullo schermo. */
html:not(.motion-on) .veil { display: none; }

/* ---- Preloader: il primo velo ----------------------------- */
.intro {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  pointer-events: all;
}
.intro__panel { background: var(--bone); will-change: transform; }

.intro__mark {
  position: fixed;
  inset: 0;
  z-index: 1001;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.intro__word {
  font-family: var(--ff-display);
  font-weight: 300;
  font-size: clamp(2.5rem, 9vw, 7rem);
  line-height: 1;
  text-transform: lowercase;
  letter-spacing: 0.4em;
  /* il tracking parte largo e si stringe: compensato a destra
     così la parola resta otticamente centrata */
  text-indent: 0.4em;
  color: var(--ink);
}
.intro__count {
  position: fixed;
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: 1001;
  font-family: var(--ff-mono);
  font-size: var(--fs-small);
  color: var(--stone);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
/* L'intro esiste sullo schermo solo mentre sta girando davvero.
   Guardia su .intro-running e non su .motion-on: così copre anche la
   seconda visita nella sessione, quando il preloader non parte ma il
   markup è ancora nella pagina. */
html:not(.intro-running) .intro,
html:not(.intro-running) .intro__mark,
html:not(.intro-running) .intro__count { display: none; }

/* Mentre l'intro è in scena la pagina non si scrolla */
html.intro-running { overflow: hidden; }

/* ---- Cursore ----------------------------------------------
   Due elementi, non uno: un punto pieno che segue quasi subito e un
   anello che arriva dopo. Non e' un vezzo — e' lo scarto fra le due
   velocita' a dare la sensazione di peso e di morbidezza; con un
   elemento solo resta un bollo che insegue.

   Disegnati alla dimensione MASSIMA e rimpiccioliti: ingrandire con
   transform stira il bitmap e sgrana bordo e testo.

   In `difference` restano leggibili sia sul Bone sia sul Depth senza
   che nessuno debba misurare cosa c'e' sotto.

   Solo su puntatori fini: su touch non esistono affatto. */
.cursor,
.cursor__dot {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 950;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: difference;
  will-change: transform;
}

.cursor {
  width: 5rem;
  height: 5rem;
  margin: -2.5rem 0 0 -2.5rem;
  /* 2px alla dimensione piena; a riposo la scala 0.5 lo riporta a un
     pixel esatto, invece di una frazione che il browser sgrana. */
  border: 2px solid #ffffff;
  border-radius: 50%;
  display: grid;
  place-items: center;
}

.cursor__dot {
  width: 1rem;
  height: 1rem;
  margin: -0.5rem 0 0 -0.5rem;
  border-radius: 50%;
  background: #ffffff;
}

@media (pointer: coarse), (hover: none) {
  .cursor, .cursor__dot { display: none; }
}

/* Il puntatore di sistema non si vede: c'e' gia' il nostro, e due
   puntatori sono uno di troppo. Vale solo dove il nostro esiste
   davvero — con il motore acceso e su un puntatore fine — perche'
   nasconderlo altrove lascerebbe la pagina senza niente da seguire. */
@media (pointer: fine) and (hover: hover) {
  .motion-on,
  .motion-on body,
  .motion-on a,
  .motion-on button,
  .motion-on label,
  .motion-on summary,
  .motion-on [role="button"],
  .motion-on .flip,
  .motion-on .preview__track,
  .motion-on .garment__strip { cursor: none; }

  /* I campi di testo no: la forma a I dice dove si sta per scrivere,
     e il nostro anello non sa dirlo. */
  .motion-on input,
  .motion-on textarea,
  .motion-on select { cursor: auto; }
}

/* ---- Header sopra i campi di colore ------------------------
   Bianco in `difference`: sul Bone diventa quasi nero, sul Depth
   diventa chiaro. L'header si inverte da solo passando sopra i
   campi, senza JS che misuri niente. */
.motion-on .site-header {
  mix-blend-mode: difference;
}
.motion-on .site-header__inner { color: #ffffff; }
/* Col menu aperto il blend va spento: il pannello Bone che copre lo
   schermo, visto in differenza, diventerebbe nero. */
.motion-on.menu-open .site-header { mix-blend-mode: normal; }
.motion-on.menu-open .site-header__inner { color: var(--ink); }

/* ---- Rispetto per chi ha chiesto meno movimento ------------
   `.motion-on` non viene proprio aggiunta sotto reduced-motion,
   quindi qui si tratta solo di neutralizzare ciò che è nel CSS
   di base. */
@media (prefers-reduced-motion: reduce) {
  .intro, .intro__mark, .intro__count, .veil, .cursor, .cursor__dot { display: none !important; }
  .vline__inner { transform: none !important; }
}
