/* ============================================================
   Velvet & Co. — Sistema di luce (site-wide)
   ============================================================
   TESI — Il sito e' una stanza buia e chi lo visita porta la luce
   con se'. Una sola sorgente rosa-oro governa OGNI superficie: si
   muove col puntatore, avanza con lo scroll, e non riparte mai
   cambiando pagina. La continuita' e' il meccanismo, non un effetto.

   Questo file e' il livello di sito. home-motion.css resta per i
   soli blocchi della front-page (hstrip, cine, hero).

   Custom property scritte da vc-motion.js, e nient'altro:
     --lx / --ly   su <html>  posizione della sorgente in vw/vh
     --sp          su <html>  avanzamento lettura pagina (0->1)
     --hp          su .hero--parallax  uscita hero (0->1)
     --p           su [data-vc-p]  traversata dell'elemento (0->1)
     --tx          su .hstrip  offset track pinnata (px)

   VOCABOLARIO — tre gesti, non dodici. La coerenza e' l'unica cosa
   che distingue una regia da una raccolta di effetti.
     .vc-rivela   la luce scopre        (maschera che si apre)
     .vc-deriva   contro-parallasse     (il fondo resta indietro)
     .vc-taglio   lo stacco netto       (raro, quindi forte)

   Vincoli non negoziabili:
   - additivo: senza JS o con prefers-reduced-motion la pagina e'
     completa e statica, mai a meta';
   - solo transform/opacity nel loop: la sorgente e' un disco
     dipinto una volta e traslato sul compositor, mai un gradiente
     riposizionato a ogni frame;
   - niente motion tra il dito e un bottone: le superfici che
     vendono sono escluse piu' sotto.
   ============================================================ */

:root {
  /* Intensita' della sorgente. Un solo numero per alzare o abbassare
     tutta la stanza: usato dall'orb, dal bordo delle card e dalle
     lame di luce. */
  --vc-lit: 1;
  --vc-light-size: 78vmax;
  /* --ease-out e' definita da animations.css, che carica prima: unica
     fonte di verita', non ridichiarata qui.
     Uscita esponenziale: la coda lunga e' quello che fa sembrare il
     movimento "pesante" invece che elastico. */
  --ease-cine: cubic-bezier(.16, 1, .3, 1);
}

/* ── La sorgente ───────────────────────────────────────────────
   Un disco a gradiente, dipinto UNA volta, spostato in translate3d.
   Riposizionare un radial-gradient a ogni frame ridipinge l'intera
   viewport; traslare un layer gia' dipinto no. A 60fps la
   differenza non e' un dettaglio.

   z-index 1: sopra i fondi delle sezioni (che altrimenti la
   coprirebbero: le <section> con background stanno nel flusso a
   z-index auto), sotto la navbar (--z-navbar: 100).
   L'alpha di picco e' .07: sul fondo obsidian e' un bagliore
   leggibile, sul testo crema resta sotto la soglia percettiva. */
.vc-light {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--vc-light-size);
  height: var(--vc-light-size);
  margin: calc(var(--vc-light-size) / -2) 0 0 calc(var(--vc-light-size) / -2);
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: screen;
  opacity: calc(.72 * var(--vc-lit));
  background: radial-gradient(closest-side,
    rgba(232, 213, 163, .07),
    rgba(201, 169, 110, .028) 42%,
    transparent 72%);
  transform: translate3d(calc(var(--lx, 50) * 1vw), calc(var(--ly, 38) * 1vh), 0);
  will-change: transform;
  /* Nessuna transition sul transform: l'inseguimento e' gia' smorzato
     nel JS. Qui si accompagna solo l'accensione. */
  transition: opacity 900ms var(--ease-out);
}

/* Superfici dove la luce non entra: modo Operate puro. Carrello,
   checkout, area account e reso non guadagnano niente da una stanza
   atmosferica e hanno tutto da perdere. */
body.woocommerce-cart .vc-light,
body.woocommerce-checkout .vc-light,
body.woocommerce-account .vc-light,
body.vc-nolight .vc-light { display: none; }

/* Mobile: niente mix-blend-mode. Un elemento fisso che si fonde col
   fondo obbliga il browser a comporre l'intera pagina a ogni frame di
   scroll — su un telefono di fascia media e' la voce di costo piu'
   alta di tutto il sistema. Senza blend l'aspetto sul fondo obsidian
   e' quasi identico, e senza puntatore la sorgente qui segue solo la
   lettura: si perde pochissimo. */
@media (max-width: 899px) {
  .vc-light {
    mix-blend-mode: normal;
    --vc-light-size: 110vmax;
    opacity: calc(.5 * var(--vc-lit));
  }
}

/* ── Avanzamento lettura ───────────────────────────────────────
   Era legato alla sola front-page. Ora e' la traccia della luce
   lungo il documento, su ogni pagina lunga. */
.vc-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(var(--sp, 0));
  transform-origin: 0 50%;
  background: linear-gradient(90deg, transparent, var(--color-gold) 35%, var(--color-gold-light));
  z-index: calc(var(--z-navbar) + 1);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--transition-fast);
}
.vc-progress.is-visible { opacity: .9; }

/* ── GESTO 1 — Rivelazione ─────────────────────────────────────
   La luce scopre: l'elemento sale di poco, esce dalla sfocatura e si
   accende. Non e' il fade-up di .reveal (che sposta e basta): qui la
   messa a fuoco fa il lavoro, ed e' cio' che lo lega al resto del
   sistema di luce.

   PERCHE' NON PIU' clip-path — la prima versione armava con
   `clip-path: inset(0 0 100% 0)`, che e' una maschera piu' bella. Ma un
   elemento clippato ad altezza zero non produce alcuna notifica
   dall'IntersectionObserver: verificato in produzione su /chi-siamo/,
   11 elementi su 11 armati e ZERO accesi — l'intera pagina era bianca
   sotto l'apertura. opacity e transform, invece, l'osservatore li
   ignora del tutto: l'elemento resta sempre "visibile" per lui, e il
   blocco non puo' ripetersi.

   REGOLA GENERALE, non un dettaglio di questo file: non far mai
   dipendere la visibilita' del contenuto dal fatto che un osservatore
   riesca a vedere qualcosa che abbiamo appena nascosto. */
@media (prefers-reduced-motion: no-preference) {
  .vc-rivela.vc-armed {
    opacity: 0;
    transform: translate3d(0, 18px, 0);
    filter: blur(7px);
    transition:
      opacity 900ms var(--ease-out),
      transform 1100ms var(--ease-cine),
      filter 900ms var(--ease-out);
    /* Scaglionamento dentro un gruppo: --i scritto dal JS in ordine di
       documento. 90ms e' il passo piu' lento che non sembra lento, ma il
       ritardo e' CAPPATO a 5 posizioni: su una griglia shop da dodici card
       uno scaglionamento lineare farebbe aspettare l'ultima piu' di un
       secondo, e chi arriva sullo shop sta scansionando, non guardando. */
    transition-delay: calc(min(var(--i, 0), 5) * 90ms);
  }
  .vc-rivela.vc-armed.is-lit {
    opacity: 1;
    transform: none;
    filter: blur(0);
  }
}

/* ── GESTO 2 — Deriva ──────────────────────────────────────────
   Il fondo resta indietro rispetto al testo. --p e' la traversata
   dell'elemento (0 = entra dal basso, 1 = uscito in alto): e' uno
   scrub, si torna indietro e la deriva torna indietro.
   --vc-drift e' l'ampiezza in px, decisa per-elemento. */
.vc-deriva[data-vc-p] {
  transform: translate3d(0, calc((var(--p, .5) - .5) * (var(--vc-drift, 40) * -1px)), 0);
  will-change: transform;
}

/* ── GESTO 3 — Taglio ──────────────────────────────────────────
   Lo stacco: una lama di luce che chiude una scena e ne apre
   un'altra, accesa nel punto in cui si trova la sorgente. E' l'unico
   gesto duro del sistema, e vale solo perche' gli altri due non lo
   sono. */
.vc-taglio {
  position: relative;
  height: 1px;
  border: 0;
  margin: 0;
  background: var(--color-border);
  overflow: visible;
}
.vc-taglio::after {
  content: '';
  position: absolute;
  inset: -1px 0;
  background: radial-gradient(60% 100% at calc(var(--lx, 50) * 1%) 50%,
    rgba(232, 213, 163, calc(.55 * var(--vc-lit))),
    transparent 70%);
  pointer-events: none;
}

/* ── Oggetti illuminati ────────────────────────────────────────
   La luce non e' solo foschia globale: cade sugli oggetti. Il bordo
   superiore delle card raccoglie la sorgente in base a dov'e', cosi'
   una griglia smette di essere una serie di rettangoli identici e
   diventa una superficie con una direzione. */
.vc-lit-edge { position: relative; }
.vc-lit-edge::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  z-index: 2;
  background: linear-gradient(90deg,
    transparent,
    rgba(232, 213, 163, calc(.55 * var(--vc-lit))),
    transparent);
  opacity: 0;
  transition: opacity 600ms var(--ease-out);
  pointer-events: none;
}
.vc-lit-edge:hover::before,
.vc-lit-edge:focus-within::before { opacity: 1; }

/* ── Profondita' continua sulle immagini ───────────────────────
   Dove il browser supporta animation-timeline: view(), ogni immagine
   di card si muove dentro la propria cornice per tutta la traversata
   dello schermo: profondita' vera, a costo zero per il main thread
   (gira sul compositor, nessun listener).

   Stava in home-motion.css, quindi valeva solo in front-page: la
   griglia dello shop — dove le card sono dodici invece di tre — non
   l'ha mai avuta. Ora e' site-wide, che e' dove serve. */
/* Registrata: senza @property una custom property non e' interpolabile
   e l'animazione scatterebbe a meta' invece di scorrere. */
@property --vc-depth { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --vc-zoom  { syntax: '<number>'; inherits: false; initial-value: 1.12; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Si anima una custom property, NON la transform: le animazioni
       battono le dichiarazioni normali, quindi animare direttamente
       `transform` spegnerebbe lo zoom-hover gia' presente sulle card.
       Cosi' le due cose si compongono nella stessa transform. */
    .product-card__img-wrap img,
    .product-card:hover .product-card__img-wrap img,
    .velvet-guide-card__thumb img,
    .velvet-guide-card:hover .velvet-guide-card__thumb img {
      transform: scale(var(--vc-zoom, 1.12)) translate3d(0, calc(var(--vc-depth, 0) * 1%), 0);
    }
    .product-card__img-wrap img,
    .velvet-guide-card__thumb img {
      animation: vc-depth linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      transition: --vc-zoom 700ms var(--ease-out, cubic-bezier(.22,.61,.36,1));
    }
    .product-card:hover .product-card__img-wrap img,
    .velvet-guide-card:hover .velvet-guide-card__thumb img { --vc-zoom: 1.19; }

    @keyframes vc-depth {
      from { --vc-depth: 3.4; }
      to   { --vc-depth: -3.4; }
    }

    /* Intestazioni di sezione: salgono e si mettono a fuoco entrando,
       invece di comparire di scatto a soglia superata. */
    .section-header > *:not(.section-header__ghost) {
      animation: vc-rise linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 60%;
    }
    @keyframes vc-rise {
      from { opacity: 0; transform: translate3d(0, 24px, 0); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* Sollevamento su hover: unico per tutto il sito. */
.card-lift { transition: transform 500ms var(--ease-out, cubic-bezier(.22,.61,.36,1)); }
.card-lift:hover { transform: translateY(-6px); }

/* ── Superfici del browser ─────────────────────────────────────
   Le parti che non abbiamo disegnato arrivano coi default del
   browser, che non appartengono a nessun design system. Selezione,
   caret, scrollbar, anello di focus e cifre tabulari sono il segnale
   piu' economico che una pagina e' stata costruita e non assemblata. */
::selection {
  background: rgba(201, 169, 110, .3);
  color: var(--color-text);
  text-shadow: none;
}

html {
  caret-color: var(--color-gold);
  scrollbar-color: rgba(201, 169, 110, .3) var(--color-bg);
  scrollbar-width: thin;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--color-bg); }
::-webkit-scrollbar-thumb {
  background: rgba(201, 169, 110, .22);
  border: 3px solid var(--color-bg);
  border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(201, 169, 110, .42); }

/* Anello di focus unico per tutto il sito: oro pieno, staccato, cosi'
   resta leggibile anche sopra un'immagine. */
:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 3px;
  border-radius: 1px;
}
/* Sui bottoni gia' oro l'anello deve cambiare colore, altrimenti
   sparisce dentro il proprio fondo. */
.btn--gold:focus-visible {
  outline-color: var(--color-text);
  outline-offset: 4px;
}

/* Sottolineature del testo corrente: staccate dalla linea di base e
   sottili. Il default del browser taglia le discendenti di un serif. */
p a:not(.btn):not(.product-card):not([class*="__"]),
.velvet-guide__body a:not(.btn) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .22em;
  text-decoration-color: var(--color-gold-dim);
  transition: text-decoration-color var(--transition-fast);
}
p a:not(.btn):not(.product-card):not([class*="__"]):hover,
.velvet-guide__body a:not(.btn):hover {
  text-decoration-color: var(--color-gold);
}

/* Cifre a larghezza fissa ovunque un numero possa cambiare sotto gli
   occhi. Senza questo un prezzo che passa da 1 a 2 sposta di un pixel
   tutto cio' che ha accanto. */
.price, .amount, .woocommerce-Price-amount,
.pdp-info__price, .counter, .stat-band__num,
.cart-item__price, .mini-cart__total, .order-total {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ── Continuita' tra pagine ────────────────────────────────────
   Le View Transition sono il punto in cui il sito smette di essere
   una raccolta di pagine. Le regole stanno qui e non in
   animations.css perche' sono parte del sistema di luce: la sorgente
   NON riparte, e' il contenuto che si scambia sotto. */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vc-vt-out 240ms var(--ease-out) both;
  }
  ::view-transition-new(root) {
    animation: vc-vt-in 420ms var(--ease-cine) both;
  }
  @keyframes vc-vt-out { to   { opacity: 0; transform: translate3d(0, -1.2vh, 0); } }
  @keyframes vc-vt-in  { from { opacity: 0; transform: translate3d(0, 1.6vh, 0); } }

  /* L'immagine prodotto che vola dalla griglia alla scheda: IL momento
     che fa sembrare il sito un'unica cosa. Curva propria e piu' lunga
     del resto della pagina. */
  ::view-transition-group(vc-hero-img) { animation-duration: 620ms; }
  ::view-transition-old(vc-hero-img),
  ::view-transition-new(vc-hero-img) {
    animation-timing-function: var(--ease-cine);
    /* Ritaglio identico ai due capi: senza questo il browser sfuma tra
       due aspect ratio e l'immagine "respira" a meta' volo. */
    height: 100%;
    object-fit: cover;
  }

  /* Navbar e barra annunci non partecipano: restano ferme mentre il
     contenuto cambia sotto. E' quello che rende la transizione una
     carrellata invece di un taglio. */
  .site-header { view-transition-name: vc-header; }
  .announcement-bar { view-transition-name: vc-announce; }
  ::view-transition-old(vc-header), ::view-transition-new(vc-header),
  ::view-transition-old(vc-announce), ::view-transition-new(vc-announce) {
    animation: none;
    mix-blend-mode: normal;
  }
}

/* Il documento e' in volo: hover e click spenti finche' il vecchio
   contenuto e' ancora a schermo. */
html.vc-navigating,
html.vc-navigating * { pointer-events: none !important; }

/* ── Reduced motion ────────────────────────────────────────────
   No-op totale, non una versione ridotta. */
@media (prefers-reduced-motion: reduce) {
  .vc-light,
  .vc-progress { display: none; }
  .vc-rivela { clip-path: none; }
  .vc-deriva[data-vc-p] { transform: none; }
  .vc-lit-edge::before { display: none; }
}

/* ── Il palcoscenico: la luce cade sull'oggetto ────────────────
   Il problema reale del catalogo, che nessuna quantita' di motion
   risolve: le foto arrivano dai feed fornitore come packshot ritagliati
   su fondo BIANCO. Su un fondo obsidian non sono cinematici, sono
   ritagli — un rettangolo luminoso che finisce di netto.

   Qui la cornice diventa una stanza. Tre livelli, tutti in CSS sopra
   l'immagine del feed: niente ritocco di migliaia di file, niente
   modifica alla pipeline fornitore, nessun costo di banda.

     1. il fondo della cornice e' un piano illuminato dall'alto, non
        un grigio piatto;
     2. ::before  = vignettatura + luce direzionale presa da --lx, cosi'
        i bordi dell'immagine rientrano nel buio invece di tagliare;
     3. ::after   = l'ombra portata a terra, che da' peso all'oggetto.

   NON e' un ritaglio del soggetto: nessuna maschera prova a indovinare
   il contorno della foto (sarebbe la versione cheap dell'effetto, e si
   vede). E' vignettatura e luce di scena, la stessa che userebbe un
   fotografo con un pannello nero ai lati. */
.product-card__img-wrap,
.pdp-gallery__main {
  background:
    radial-gradient(120% 90% at 50% -10%, #1c1c1c 0%, var(--color-bg-3) 55%, #0d0d0d 100%);
  isolation: isolate;
}

/* L'OGGETTO DEVE RIEMPIRE LA CORNICE, altrimenti la stanza si vede
   sotto. main.css dichiara `.product-card__img-wrap img { height: 100% }`
   (0,1,1), ma woocommerce.css — che carica dopo — ha
   `.woocommerce ul.products li.product a img { height: auto }` (0,3,4) e
   vince. Dentro OGNI griglia WooCommerce l'immagine restava quindi alta
   quanto il suo rapporto naturale: misurato in produzione, 280px in un
   riquadro da 350, cioe' 54px di buco in fondo.

   Il difetto e' preesistente e valeva per shop, categoria, correlati e
   up-sell; con il fondo piatto di prima si notava poco, con la
   vignettatura del palcoscenico diventa un taglio netto. Qui si ripara
   con la specificita' minima che serve a battere quella regola (0,4,3),
   senza !important e senza toccare woocommerce.css. */
.woocommerce ul.products li.product .product-card__img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 2 — vignettatura + luce direzionale. z-index 2: sopra l'immagine,
   sotto i badge (z-index 3) e il quick-add (z-index 2 → gli sta sotto
   perche' dichiarato dopo nel documento; per sicurezza il bottone
   riceve z-index 4 piu' giu'). */
.product-card__img-wrap::before,
.pdp-gallery__main::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  /* TARATO SULLE FOTO VERE, non a occhio sul codice: i valori
     precedenti (115% x 105%, buio dal 46%) dimensionavano il gradiente
     BEN oltre il riquadro, quindi la parte scura cadeva fuori campo e
     sui packshot su fondo bianco non si vedeva niente. Verificato in
     produzione sulle immagini ORION: serve che la caduta avvenga DENTRO
     i bordi visibili. */
  background:
    /* la luce entra da dove sta la sorgente */
    radial-gradient(78% 70% at calc(var(--lx, 50) * 1%) 6%,
      rgba(232, 213, 163, .14), transparent 55%),
    /* i bordi rientrano nel buio: e' questo che toglie il "ritaglio" */
    radial-gradient(82% 76% at 50% 44%,
      transparent 24%, rgba(10, 10, 10, .5) 72%, rgba(10, 10, 10, .78) 100%);
  mix-blend-mode: multiply;
}
/* Il livello luce va in screen, quello d'ombra in multiply: separati,
   perche' un solo layer non puo' fare entrambe le cose. */
.product-card__img-wrap::after,
.pdp-gallery__main::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(70% 60% at calc(var(--lx, 50) * 1%) 6%,
    rgba(232, 213, 163, .09), transparent 58%);
  mix-blend-mode: screen;
}

/* Il quick-add deve restare sopra i livelli di scena. */
.product-card__quick-add,
.product-card__atc,
.product-card__badges,
.pdp-gallery__main .sale-badge { z-index: 4; }

/* 3 — l'ombra a terra sulla scheda prodotto: e' quello che fa sembrare
   l'oggetto appoggiato invece che incollato. Sotto la cornice, quindi
   fuori dall'overflow:hidden dell'img-wrap. */
.pdp-gallery { position: relative; }
.pdp-gallery__main {
  position: relative;
  box-shadow:
    0 24px 60px -24px rgba(0, 0, 0, .85),
    0 2px 0 0 rgba(232, 213, 163, .06) inset;
}

/* Su hover la stanza si accende appena: la card risponde alla presenza
   senza muoversi piu' di quanto gia' faccia. */
.product-card:hover .product-card__img-wrap::after { opacity: 1.35; }
.product-card__img-wrap::after { transition: opacity 600ms var(--ease-out, cubic-bezier(.22,.61,.36,1)); }

@media (prefers-reduced-motion: reduce) {
  .product-card__img-wrap::after,
  .pdp-gallery__main::after { transition: none; }
}

/* La lama sulla scheda prodotto ha bisogno d'aria attorno: separa due
   modi di leggere la pagina, non due paragrafi. */
.vc-taglio--pdp { margin: 5rem 0 0; }
@media (max-width: 860px) { .vc-taglio--pdp { margin-top: 3.5rem; } }

/* ── Loop video silenziosi ─────────────────────────────────────
   L'aspect-ratio sta QUI e non sul file: e' quello che impedisce il
   salto di layout mentre il video (o il poster) arriva. Il contenitore
   ha sempre la sua altezza, anche a rete spenta. */
.vc-video {
  position: relative;
  margin: 0;
  aspect-ratio: var(--vc-video-ratio, 16/9);
  overflow: hidden;
  background: var(--color-bg-3);
  isolation: isolate;
}
.vc-video__el,
.vc-video__poster {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Il video entra in scena quando comincia davvero a girare: senza questa
   dissolvenza si vede lo stacco fra poster e primo fotogramma. */
.vc-video__el {
  opacity: .001;
  transition: opacity 900ms var(--ease-out, cubic-bezier(.22,.61,.36,1));
}
.vc-video__el.is-live { opacity: 1; }

/* La stessa stanza delle immagini prodotto: il video non e' un rettangolo
   incollato, e' materia dentro una cornice illuminata. */
.vc-video::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(70% 60% at calc(var(--lx, 50) * 1%) 6%,
      rgba(232, 213, 163, .08), transparent 58%),
    radial-gradient(118% 108% at 50% 45%,
      transparent 52%, rgba(10, 10, 10, .34) 92%, rgba(10, 10, 10, .55) 100%);
}

@media (prefers-reduced-motion: reduce) {
  /* Il poster resta: il <video> senza sorgente mostra il proprio attributo
     poster, quindi la composizione e' completa e ferma. */
  .vc-video__el { opacity: 1; transition: none; }
}
