/** Shopify CDN: Minification failed

Line 861:7 Unexpected bad string token
Line 861:74 Unterminated string token
Line 863:78 Unterminated string token
Line 869:75 Unterminated string token
Line 870:79 Unterminated string token

**/
/**
 * PIACERSI — IL SET (bundle-set)
 * =============================================================================
 * A sinistra la scena fotografica, a destra i prodotti che ci stanno dentro.
 * Dal 07/08/2026 le scene sono PIÙ D'UNA: cambiano da sole e con loro cambia
 * l'elenco a destra.
 *
 * I PANNELLI SONO IMPILATI NELLA STESSA CELLA DI GRIGLIA (`grid-area: 1/1`).
 * Così il contenitore è alto quanto il pannello più alto e il cambio di scena
 * non fa saltare la pagina. Quelli spenti sono `visibility: hidden`, che li
 * toglie anche al Tab — `display: none` avrebbe fatto collassare l'altezza,
 * `opacity: 0` li avrebbe lasciati cliccabili.
 * L'impilamento vive solo sotto `[data-set-ready]`, che scrive il JS: senza
 * JavaScript le scene stanno una sotto l'altra e si leggono tutte.
 *
 * NIENTE 3D, ED È UNA QUESTIONE DI NITIDEZZA (05/08/2026). Una `rotateX` o un
 * `preserve-3d` sopra la fotografia la fa rasterizzare in texture e rimappare:
 * arriva a schermo VISIBILMENTE sfocata. Qui il movimento è traslazione,
 * opacità e `clip-path` — che ritaglia, non ricampiona. E quando l'ingresso è
 * finito il JS mette `.is-settled`, che toglie del tutto `transform` e
 * `clip-path`: nessun livello resta appeso all'immagine.
 *
 * =============================================================================
 * REGOLE EREDITATE (le stesse di tutte le sezioni Piacersi)
 * =============================================================================
 * 1. Custom element = `display: block` dichiarato.
 * 2. MAI `:where()` in una regola che deve vincere: specificità ZERO.
 * 3. UN SOLO `transform` per elemento, composto da variabili indipendenti.
 * 4. Niente stato invisibile fuori da `.set--armed`: senza JS la sezione è
 *    leggibile e il form si invia.
 * 5. I colori vengono dai token del tema, la sezione non ha fondo proprio.
 * =============================================================================
 */

bundle-set-component {
  display: block;
}

.set {
  --set-radius: 14px;
  --set-ink: var(--pcr-text-primary);
  --set-muted: var(--pcr-text-muted);
  --set-accent: var(--pcr-accent-action);
  --set-line: var(--pcr-hairline);
  --set-rise-dist: 64px;

  /* L'INCHIOSTRO CHE VA SOPRA L'ACCENTO, e perché è un token a parte.
     Di notte `--set-accent` diventa il dusk (#ad947e), un tono CHIARO: la
     panna che ci stava sopra di giorno fa 2,1:1 e il numero dentro il pallino
     acceso smette di leggersi. L'inchiostro dell'accento non è quindi una
     costante ma il suo complemento, e piacersi-theme.css lo ribalta insieme
     alla palette. */
  --set-accent-ink: var(--pcr-white);

  /* I SEGNI SULLA FOTOGRAFIA NON SEGUONO IL TEMA, E NON È UNA DIMENTICANZA.
     Un pallino appoggiato su uno scatto prodotto sta sopra una superficie che
     il giorno e la notte non cambiano: la fotografia è quella. Legarne
     l'inchiostro a `--pcr-text-primary` — com'era — significava scrivere
     #f4efe9 su un disco bianco appena si passava alla notte, cioè far sparire
     i numeri 1-5 dalla scena (bug visto sul «Set idratante»). Questi quattro
     valori restano fissi in tutte e due le modalità perché fisso è il fondo su
     cui poggiano. */
  --set-pin-bg: #ffffff;
  --set-pin-ink: #241a1b; /* 13,96:1 sul bianco */
  --set-pin-on-bg: #8e1c2b; /* il vinaccia di casa, anche di notte */
  --set-pin-on-ink: #ffffff; /* 8,93:1 sul vinaccia */

  position: relative;
  background: transparent;
  color: var(--set-ink);
  padding-block: var(--set-pt, 5rem) var(--set-pb, 5rem);
}

/* =============================================================================
   LA TESTATA E IL SELETTORE DELLE SCENE
   ============================================================================= */
/* LARGHEZZA (25/09/2026): testata e contenuto usavano `max-width: 84rem` e a
   1920/2560 il Set stava in 1232 px con 344/664 px vuoti per lato, mentre le
   sezioni vicine arrivano a 56-96 px dal bordo. Ora la misura è quella di
   pagina del tema (`--page-width`), come scaffale, bento e Novità. */
.set__head {
  display: grid;
  justify-items: center;
  gap: var(--pcr-sp-2);
  width: 100%;
  max-width: var(--page-width, 84rem);
  margin-inline: auto;
  padding-inline: var(--pcr-gutter);
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);
  text-align: center;
}

.set__eyebrow {
  color: var(--set-muted);
}

.set__title.pcr-h2 {
  color: var(--set-ink);
  margin: 0;
}

.set__switch {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  max-width: 100%;
  margin-top: 0.6rem;
  padding: 0.3rem;
  border: 1px solid var(--set-line);
  border-radius: 999px;
  overflow-x: auto;
  scrollbar-width: none;
}

.set__switch::-webkit-scrollbar {
  display: none;
}

.set__tab {
  position: relative;
  flex: 0 0 auto;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--set-muted);
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  overflow: hidden;

  /* 44px di bersaglio: la linguetta è alta 34, il resto lo mette l'area
     invisibile del pseudo-elemento. WCAG 2.5.8 chiede 24px, le linee guida
     touch ne chiedono 44. */
  min-height: 2.125rem;
  transition:
    color 0.3s var(--pcr-ease),
    background-color 0.3s var(--pcr-ease);
}

.set__tab:hover {
  color: var(--set-ink);
}

.set__tab.is-on {
  background: var(--pcr-bg-surface);
  color: var(--set-ink);
}

.set__tab:focus-visible {
  outline: 2px solid var(--set-accent);
  outline-offset: 2px;
}

.set__tab-text {
  position: relative;
  z-index: 1;
}

/* LA BARRA CHE SI RIEMPIE È IL TEMPO CHE MANCA al cambio di scena. Senza, il
   movimento automatico arriva senza preavviso e sembra un guasto. */
/* IL ROSSO ERA DIVENTATO INVISIBILE, ed era un difetto vero (21/08/2026).
   Il riempimento stava al 14% di vinaccia sopra `--pcr-bg-surface`, che è
   panna: la differenza fra i due colori risultanti è di pochi punti di
   luminanza, e su una pillola alta 34px non si legge. La barra c'era e
   funzionava — semplicemente non si vedeva, che per un indicatore è lo stesso
   che non esserci.

   ADESSO SONO DUE COSE, e la seconda è quella che si nota:
     · il LAVAGGIO dentro la pillola sale al 26% — abbastanza da leggersi,
       abbastanza poco da non mangiarsi il testo (l'inchiostro resta
       `--set-ink` su un fondo chiaro: il rapporto di contrasto misurato
       rimane sopra 9:1);
     · una BARRA PIENA di vinaccia, spessa 3px, appoggiata al bordo inferiore
       della pillola. È il vero indicatore: pieno, saturo, e a contatto con un
       bordo, cioè nelle condizioni in cui un colore si legge meglio.
   Il lavaggio dice «sta scorrendo», la barra dice «quanto manca».

   Entrambi vivono sullo stesso elemento — il lavaggio è il fondo, la barra è
   il suo `::after` — così un'animazione sola li muove insieme e non possono
   sfasarsi. */
.set__tab-fill {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;

  /* Il ripiego prima, `color-mix` dopo: dove la funzione non c'è (Safari < 16.2)
     la dichiarazione è invalida e resta quella sopra, invece di lasciare la
     linguetta senza barra. */
  background: rgb(142 28 43 / 22%);
  background: color-mix(in srgb, var(--set-accent) 26%, transparent);
  transform-origin: left center;
  transform: scaleX(0);
  pointer-events: none;

  /* La barra piena qui sotto ha gli estremi squadrati e la pillola è tonda:
     senza ritaglio spunterebbe dagli angoli. `clip` e non `hidden` — non serve
     un contenitore di scorrimento su un elemento decorativo. */
  overflow: clip;
}

.set__tab-fill::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 3px;
  border-radius: 999px;
  background: var(--set-accent);
}

/* La barra si riempie solo quando il giro automatico è davvero acceso: senza
   `data-auto` (rotazione spenta dall'editor, movimento ridotto, oppure chi sta
   scegliendo un formato e l'ha fermata per sempre) resterebbe una barra che si
   riempie una volta e poi non torna più, cioè una bugia. */
.set__switch[data-auto='true'] .set__tab.is-on .set__tab-fill {
  animation: set-riempi var(--set-dur, 7000ms) linear;
}

.set__switch.is-paused .set__tab-fill {
  animation-play-state: paused;
}

@keyframes set-riempi {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}

/* IL COMANDO DI PAUSA NON SI VEDE — ma esiste  (25/09/2026)
   Il movimento automatico deve potersi fermare anche da tastiera (WCAG 2.2.2),
   quindi il pulsante resta nel documento: `display: none` lo toglierebbe
   anche alla tastiera. A riposo è 1x1px ritagliato e ricompare, tondo, SOLO
   arrivandoci col Tab — lo stesso schema del «Banner carosello» (.htw__play).

   Dal 21/09 su schermi a tocco (`hover: none`) era sempre a vista, 32px, a
   sinistra delle linguette. Su iPad l'utente l'ha trovato «orribile»: tolto.
   Le pause restano quelle invisibili del giro (bundle-set.js, invariato):
   scheda in secondo piano, sezione fuori campo, fuoco da tastiera dentro la
   sezione, e per sempre dopo la scelta di un formato o un'aggiunta al carrello.
   Per il lettore di schermo il pulsante c'è, col suo nome.

   `position: absolute` a riposo e non un elemento largo 1px nella fila: dentro
   la pastiglia (flex con `gap`) un figlio da 1px si prendeva comunque 1px più
   uno spazio da 0,35rem, e le linguette stavano 6-7px a destra del centro. */
.set__pause {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--set-muted);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  cursor: pointer;
}

/* L'involucro con il ruolo tablist non deve esistere per l'impaginazione:
   le linguette restano figlie dirette della pastiglia, come prima. */
.set__tabs {
  display: contents;
}

.set__pause:focus-visible {
  position: static;
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  margin-left: 0.25rem;
  border: 1px solid var(--set-line);
  background: var(--pcr-bg-surface);
  overflow: visible;
  clip-path: none;
  outline: 2px solid var(--set-accent);
  outline-offset: 2px;
}

/* `display` dichiarato qui sopra batterebbe il `[hidden]` del browser (il JS
   nasconde il comando quando il giro automatico è spento). */
.set__pause[hidden] {
  display: none;
}

/* =============================================================================
   I PANNELLI
   ============================================================================= */
/* L'IMPILAMENTO È LO STATO DI PARTENZA, non qualcosa che aggiunge il JS.
   Se l'avesse aggiunto il JS ci sarebbe stato un lampo, all'apertura della
   pagina, con tutte le scene aperte una sotto l'altra e la pagina che si
   accorcia di colpo appena il modulo arriva: il foglio di stile è già lì
   quando si disegna il primo fotogramma, il modulo no. A chi ha JavaScript
   spento la disposizione in colonna la restituisce il `<noscript>` in fondo
   alla sezione, che sta più in basso di questo foglio e quindi vince. */
/* L'ALTEZZA SEGUE LA SCENA ATTIVA  (21/08/2026)
   =============================================================================
   I pannelli sono impilati nella stessa cella di griglia — è così che si
   dissolvono l'uno nell'altro senza salti. Il prezzo di quella scelta è che il
   contenitore è alto quanto il pannello PIÙ ALTO: la scena «Idratante» ha
   cinque prodotti, «Colore» ne ha tre, e su «Colore» restavano quasi
   trecento pixel di niente sotto il pulsante. È una delle due ragioni per cui
   la sezione «si vedeva ancora vuota», e non si poteva risolvere aggiungendo
   contenuto: il vuoto non era in fondo alla sezione, era in fondo al
   contenitore dei pannelli.

   Ora `--set-panels-h` la scrive il JS misurando il pannello acceso, e cambia
   con una transizione insieme alla dissolvenza. Il ripiego è `auto`, cioè
   esattamente il comportamento di prima: se il JS non parte non si rompe
   niente, si torna al vuoto — che è brutto, non guasto.

   `overflow: clip` perché durante la transizione il pannello in uscita, più
   alto di quello in entrata, sporgerebbe di sotto per mezzo secondo. */
.set__panels {
  display: grid;

  /* `align-items: start` NON È COSMESI, è ciò che rende possibile la misura.
     Un elemento di griglia, per impostazione predefinita, viene STIRATO
     all'altezza della sua cella. Senza questa riga il pannello acceso
     misurerebbe sempre l'altezza del contenitore — cioè il valore che il JS
     sta cercando di calcolare — e il conto si morderebbe la coda: la misura
     confermerebbe l'altezza corrente e non cambierebbe mai.
     Con `start` ogni pannello è alto quanto il suo contenuto, e la misura
     diventa un dato vero. È anche la ragione per cui il ResizeObserver qui
     sotto non entra in ciclo: l'altezza del pannello non dipende più da quella
     del contenitore. */
  align-items: start;
  height: var(--set-panels-h, auto);
  overflow: clip;
  transition: height 0.55s var(--pcr-ease);
}

@media (prefers-reduced-motion: reduce) {
  .set__panels {
    transition: none;
  }
}

.set__panel {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.55s var(--pcr-ease),
    visibility 0s linear 0.55s;
}

.set__panel.is-on {
  opacity: 1;
  visibility: visible;
  transition:
    opacity 0.55s var(--pcr-ease),
    visibility 0s;
}

.set__inner {
  width: 100%;
  max-width: var(--page-width, 84rem);
  margin-inline: auto;
  padding-inline: var(--pcr-gutter);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

/* =============================================================================
   LA SCENA
   ============================================================================= */
.set__scene {
  position: relative;
  min-width: 0;
}

.set__stage {
  position: relative;
  aspect-ratio: var(--set-ar, 1);
  border-radius: var(--set-radius);
  overflow: hidden;
  background: var(--pcr-bg-surface);
  box-shadow: 0 1.5rem 3rem rgb(33 27 28 / 12%);

  /* MISURATO, NON DEDOTTO (07/08/2026). Il gesto per cambiare scena col dito
     non arrivava mai: con `touch-action: auto` il browser si prende il gesto
     appena il dito si muove e manda un `pointercancel`, quindi il `pointerup`
     su cui si decide lo scorrimento non veniva mai consegnato. Dichiarando
     `pan-y` si dice al browser: la verticale è tua (la pagina deve scorrere),
     l'orizzontale è mia. `pinch-zoom` resta, se no si toglierebbe alla gente
     la possibilità di ingrandire la fotografia con due dita. */
  touch-action: pan-y pinch-zoom;
}

/* QUI LA PARALLASSE NON CI VA, ED È UNA DECISIONE, NON UNA DIMENTICANZA.
   (20/08/2026) La fotografia scorrevole dentro la cornice era scritta e
   funzionava. È stata tolta perché SOPRA questa fotografia ci sono i segni
   numerati (`.set__pin`), posizionati in percentuale sul palco e puntati su
   oggetti precisi dell'immagine: un flacone, un vasetto. Facendo scorrere la
   foto di venti pixel e non i segni, ogni segno si stacca dalla cosa che
   indica; facendo scorrere anche i segni, quelli vicini al bordo escono dal
   ritaglio. Un effetto che rompe l'informazione non è un effetto migliore.
   La parallasse di questa pagina sta dove le immagini non hanno niente
   appoggiato sopra — vedi story-scroll, social-proof e bento-grid. */
.set__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;

  /* Il riquadro ha quasi le proporzioni della foto: `cover` qui ritaglia
     pochissimo, ed è il prezzo giusto per avere tutte le scene alte uguali. */
  object-fit: cover;
}

/* IL FILETTO STA SOPRA, NON DI FIANCO. Affiancato funzionava finché la
   didascalia stava su una riga; su telefono va a capo e il filetto restava
   appeso a sinistra di un blocco di due righe, centrato su niente. Sopra e
   centrato è un divisorio, e lo è a qualunque larghezza. */
.set__caption {
  display: grid;
  justify-items: center;
  gap: 0.55rem;
  margin: 0.9rem 0 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  color: var(--set-muted);
  text-align: center;
}

/* Il filetto si allunga quando la scena arriva: un dettaglio che dice «questa
   riga appartiene a questa fotografia», invece di lasciarla galleggiare. */
.set__caption-rule {
  display: block;
  width: 2.25rem;
  height: 1px;
  background: var(--set-accent);
  opacity: 0.6;

  /* Cresce dal centro: un filetto centrato che si allunga da un capo
     sembrerebbe entrare di lato, cioè un pezzo fuori posto. */
  transform-origin: center;
}

/* =============================================================================
   LA RIGA SOPRA LA FOTOGRAFIA — «01 / 03 · Idratante · 5 prodotti»
   =============================================================================
   Tre informazioni su una riga sola, separate da filetti verticali e non da
   punti: i punti mediani in questa sezione sono già usati nella nota del piede,
   e due separatori uguali con due significati diversi si leggono peggio di due
   diversi.

   Il numero di scena è in cifre tabulari (`tabular-nums`): passando da 01 a 02
   le cifre hanno larghezze diverse in questa famiglia, e senza la riga intera
   si sposterebbe di un pixel a ogni cambio — un tremolio piccolo ma continuo,
   perché la scena cambia da sola ogni sette secondi.
   ========================================================================== */
.set__scene-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 0.7rem;
  margin: 0 0 0.85rem;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--set-muted);
}

.set__scene-n {
  color: var(--set-accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}

.set__scene-n i {
  font-style: normal;
  opacity: 0.45;
  margin-inline: 0.15em;
}

.set__scene-name {
  color: var(--set-ink);
}

/* I filetti separatori nascono dai fratelli, non da un elemento in più: così
   il primo non ha mai un filetto davanti, qualunque sia il pezzo che manca
   (il numero sparisce con una scena sola, il nome se l'editor lo svuota). */
.set__scene-name::before,
.set__scene-count::before {
  content: '';
  display: inline-block;
  width: 1px;
  height: 0.75em;
  margin-inline-end: 0.7rem;
  vertical-align: -0.05em;
  background: currentcolor;
  opacity: 0.3;
}

.set__scene-bar > :first-child::before {
  display: none;
}

/* =============================================================================
   GLI ALTRI RITUALI — i collegamenti sotto le ragioni
   =============================================================================
   Il perché sta in bundle-set.liquid, accanto alla marcatura. Qui il come.

   Sono pastiglie con il contorno e non pulsanti pieni: la sezione ha già UN
   pulsante pieno, «Aggiungi tutto al carrello», ed è l'azione che deve vincere
   sulle altre. Due pieni sulla stessa schermata si contendono l'occhio, e in
   quel duello perde sempre quello che conta.

   Come le tre ragioni, solo su schermi larghi: su telefono le colonne diventano
   una, il vuoto che questo blocco riempie non esiste, e le linguette in cima
   restano a portata di pollice. Dichiarato spento per primo e riacceso nella
   media query — se il foglio arrivasse troncato è meglio che manchi piuttosto
   che comparire dove non ci sta.
   ========================================================================== */
.set__more {
  display: none;
}

@media (width >= 60rem) {
  .set__more {
    display: block;
    margin-top: clamp(1.1rem, 2vw, 1.6rem);
  }
}

.set__more-title {
  margin: 0 0 0.7rem;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--set-muted);
}

.set__more-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.set__more-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.9rem;

  /* 2,25rem è sotto i 44px consigliati per il tocco, ma questo blocco esiste
     SOLO sopra le 60rem, cioè dove il puntatore è fine. La regola dei 44px
     serve al dito; qui il bersaglio è comunque largo e in una zona senza
     nient'altro di cliccabile intorno. */
  min-height: 2.25rem;
  border: 1px solid var(--set-line);
  border-radius: 999px;
  background: transparent;
  color: var(--set-ink);
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  cursor: pointer;
  transition:
    border-color 0.35s var(--pcr-ease),
    background-color 0.35s var(--pcr-ease),
    color 0.35s var(--pcr-ease);
}

.set__more-btn svg {
  flex: 0 0 auto;
  opacity: 0.5;
  transition:
    transform 0.4s var(--pcr-ease-out),
    opacity 0.35s var(--pcr-ease);
}

.set__more-btn:is(:hover, :focus-visible) {
  border-color: var(--set-accent);
  background: color-mix(in srgb, var(--set-accent) 7%, transparent);
  color: var(--set-accent);
}

.set__more-btn:is(:hover, :focus-visible) svg {
  opacity: 1;
  transform: translate3d(2px, -2px, 0);
}

.set__more-btn:focus-visible {
  outline: 2px solid var(--set-accent);
  outline-offset: 2px;
}

/* =============================================================================
   LE TRE RAGIONI — il riquadro sotto la fotografia  (21/08/2026)
   =============================================================================
   Occupa il vuoto che la colonna di sinistra lasciava su desktop. La nota sul
   PERCHÉ sta in bundle-set.liquid, accanto alla marcatura; qui c'è solo il
   come.

   NIENTE FONDO PROPRIO, e non è una scelta di gusto: un pannello con un colore
   suo va rideciso a ogni cambio di tema, e ogni superficie a colore fisso in
   questo tema ha finito prima o poi per avere l'inchiostro sbagliato di notte.
   Un filetto in alto e basta — sopra il lino di giorno e sopra il notte
   vinaccia funziona lo stesso, perché non introduce nessun fondo nuovo.

   `display: none` sotto le 60rem è dichiarato PER PRIMO qui e riacceso nella
   media query, non il contrario: se il foglio non arrivasse per intero è
   meglio che il riquadro manchi piuttosto che comparire dove non ci sta.
   ========================================================================== */
.set__aside {
  display: none;
}

@media (width >= 60rem) {
  .set__aside {
    display: block;
    margin-top: clamp(1.5rem, 2.6vw, 2.25rem);
    padding-top: clamp(1.1rem, 2vw, 1.6rem);
    border-top: 1px solid var(--set-line);
  }

  .set__aside-title {
    margin: 0 0 0.85rem;
    font-family: var(--pcr-font-body);
    font-size: var(--pcr-fs-eyebrow);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--set-muted);
  }

  .set__aside-list {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .set__aside-item {
    display: grid;

    /* Colonna del pallino a larghezza fissa: le righe vanno a capo su una
       stessa incolonnatura, invece di rientrare sotto il pallino. */
    grid-template-columns: 0.75rem 1fr;
    align-items: start;
    gap: 0.65rem;
    font-family: var(--pcr-font-body);
    font-size: var(--pcr-fs-small);
    line-height: 1.55;
    color: var(--set-ink);
  }

  /* Il pallino è allineato alla PRIMA RIGA di testo, non al centro della voce:
     con `align-items: start` e un margine calcolato sull'altezza di riga resta
     al posto giusto anche quando la ragione va su due righe. */
  .set__aside-dot {
    width: 0.375rem;
    height: 0.375rem;
    margin-top: calc((1.55em - 0.375rem) / 2);
    margin-inline: auto;
    border-radius: 50%;
    background: var(--set-accent);
    opacity: 0.75;
  }
}

/* =============================================================================
   IL FARO SUL PRODOTTO
   =============================================================================
   Passando su una riga a destra, la scena si abbassa di luce tranne un disco
   intorno al prodotto di quella riga. Con quattro prodotti dentro la stessa
   fotografia il numero da solo non basta più a dire quale sia.

   LE DUE COORDINATE SONO REGISTRATE CON `@property`. Senza registrazione una
   custom property è una stringa: cambiandola il disco SALTEREBBE da un
   prodotto all'altro, perché il browser non sa interpolare una stringa.
   Registrate come `<number>` si possono transire, e la maschera si ridisegna
   fotogramma per fotogramma mentre il faro scivola da un flacone all'altro.

   È UNA MASCHERA, NON UN RITAGLIO DELL'IMMAGINE: la fotografia sotto non viene
   toccata, né ridimensionata, né rasterizzata a parte.
   ============================================================================= */
@property --fx {
  syntax: '<number>';
  inherits: true;
  initial-value: 50;
}

@property --fy {
  syntax: '<number>';
  inherits: true;
  initial-value: 50;
}

.set__focus {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;

  /* 46%, non 62: misurato a schermo, il velo più scuro non «illuminava» il
     prodotto — spegneva la fotografia, e il disco chiaro si perdeva. Il faro
     deve indicare, non oscurare. Il disco chiaro arriva al 15% del raggio e il
     buio è pieno al 38%: una sfumatura lunga, se no sembra un buco ritagliato
     con le forbici. */
  background: rgb(18 13 14 / 46%);
  -webkit-mask-image: radial-gradient(
    circle at calc(var(--fx, 50) * 1%) calc(var(--fy, 50) * 1%),
    transparent 0,
    transparent 15%,
    #000 38%
  );
  mask-image: radial-gradient(
    circle at calc(var(--fx, 50) * 1%) calc(var(--fy, 50) * 1%),
    transparent 0,
    transparent 15%,
    #000 38%
  );
  transition:
    opacity 0.45s var(--pcr-ease),
    --fx 0.5s var(--pcr-ease-out),
    --fy 0.5s var(--pcr-ease-out);
}

.set__stage.is-focusing .set__focus {
  opacity: 1;
}

/* --- Grana e vignetta: due veli fissi, disegnati una volta -----------------
   La grana è un SVG in `data:` — nessuna richiesta di rete — in `multiply`, che
   scurisce appena i mezzitoni senza sporcare i bianchi. La vignetta tiene i
   numeri staccati dal fondo quando il prodotto è chiaro. */
.set__grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}

.set__vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(120% 100% at 50% 40%, transparent 52%, rgb(24 17 18 / 26%) 100%);
}

/* --- La lama di luce al cambio scena --------------------------------------
   È un livello SOPRA la foto, non una trasformazione della foto: l'immagine
   resta disegnata alla sua risoluzione vera. */
.set__sheen {
  position: absolute;
  inset-block: -20%;
  left: -35%;
  width: 28%;

  /* Sopra tutti gli altri veli: la lama deve passare anche sui numeri, se no
     sembra che scorra sotto un vetro sporco. */
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgb(255 255 255 / 42%) 45%,
    rgb(255 255 255 / 62%) 55%,
    transparent 100%
  );
  transform: translateX(0) rotate(8deg);
}

/* --- L'ALONE CHE SEGUIVA IL PUNTATORE — RIFATTO IL 21/08/2026 --------------
   L'utente: «l'effetto che segue il cursore qui non mi fa impazzire». Aveva
   ragione, e la ragione è precisa. Era una macchia bianca all'85% in
   `soft-light` che inseguiva il mouse: su una fotografia di prodotto
   professionale quello che fa è SLAVARE il colore del flacone sotto il
   puntatore — cioè peggiorare esattamente la cosa che si è andati a guardare.
   Ed era un gesto senza significato: la luce di una scena non si sposta perché
   qualcuno muove il dito.

   Al suo posto due cose che dicono qualcosa.

   1. LA LENTE. Invece di schiarire, INGRANDISCE appena la fotografia intorno
      al puntatore — un tocco di scala, non un velo. Su una foto di prodotto
      «guardare da vicino» è il gesto giusto, ed è anche quello che il pulsante
      «Guarda da vicino» promette: l'alone adesso lo anticipa invece di
      contraddirlo. Si usano le stesse due variabili `--mx`/`--my` che il JS
      scrive già, come origine della scala: nessun motore nuovo.

   2. IL VETRO. Un riflesso obliquo, tenue, che scorre col puntatore. È quello
      che fa un vetro davanti a una vetrina, e non tocca il colore: è bianco
      al 14%, non all'85%, e in `overlay` invece che in `soft-light`, così
      schiarisce le luci senza toccare i mezzitoni dove vive l'etichetta.
   -------------------------------------------------------------------------- */
.set__spot {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: overlay;
  background: linear-gradient(
    calc(70deg + var(--mx, 50) * 0.4deg),
    transparent 34%,
    rgb(255 255 255 / 14%) 50%,
    transparent 66%
  );
  transition: opacity 0.55s var(--pcr-ease);
}

.set[data-spotlight='true'] .set__stage:hover .set__spot {
  opacity: 1;
}

/* --- LA FOTOGRAFIA SI SOLLEVA, TUTTA INTERA -------------------------------
   Avevo scritto qui una «lente»: `scale` sulla sola `.set__photo` con l'origine
   sul puntatore. È SBAGLIATO in questa sezione, e vale la pena lasciarlo
   scritto perché è un errore facile da rifare.

   Sopra la fotografia ci sono i segni numerati, posizionati in percentuale
   sul PALCO e puntati su flaconi precisi. Ingrandire la sola foto del 4% su
   580px sposta i flaconi fino a 23px: i segni restano dove sono e finiscono
   a indicare il vuoto. È la stessa ragione per cui, in questa sezione, la
   parallasse sulla fotografia era stata scritta e poi tolta.

   Quello che si può muovere è il PALCO INTERO — foto e segni insieme —
   perché il rapporto fra loro non cambia. Quindi: si solleva di sei pixel e
   l'ombra si concentra sotto, come un oggetto che viene preso in mano.

   `translate` e non `transform`: la regola dell'ingresso agganciato allo
   scorrimento scrive `clip-path` e `box-shadow` sullo stesso elemento, e un
   `transform` qui entrerebbe in conflitto con quello che il palco potrebbe
   ricevere in futuro. Proprietà separate, nessuna sovrascrittura. */
   LO STATO ACCESO NON STA QUI, MA IN FONDO AL FOGLIO, subito dopo la regola
   dell'ingresso agganciato allo scorrimento. Motivo: quella regola scrive
   `box-shadow` sullo stesso elemento e pesa esattamente uguale (cinque
   selettori contro cinque). A parità di peso in CSS vince l'ULTIMA, e stando
   più in basso vincerebbe sempre lei: il sollevamento sembrerebbe funzionare
   — l'elemento si alza — ma l'ombra non cambierebbe mai. È la trappola che in
   questo tema è già costata due volte.
   Qui resta solo la transizione, che non è in conflitto con nessuno.

   La transizione dell'OMBRA vale solo a ingresso finito. Durante la salita
   l'ombra è agganciata allo scorrimento e cambia a ogni fotogramma: con mezzo
   secondo di transizione in mezzo insegue il dito con ritardo, ed è la stessa
   classe di difetto del tremolio dello scaffale — due tempi diversi sullo
   stesso numero. */
.set__stage {
  transition: translate 0.5s var(--pcr-ease-out);
}

.set:not(.set--armed) .set__stage,
.set.is-settled .set__stage {
  transition:
    translate 0.5s var(--pcr-ease-out),
    box-shadow 0.5s var(--pcr-ease);
}

/* Su un puntatore grossolano non c'è nessun dito da seguire, e sollevare al
   tocco lascerebbe la fotografia alzata finché non si tocca altrove. */
@media (hover: none), (pointer: coarse) {
  .set__spot {
    display: none;
  }

  .set__stage {
    transition: none;
  }
}

/* --- Ripiego: i prodotti al posto della fotografia ------------------------- */
.set__slot {
  position: absolute;
  top: calc(var(--y, 50) * 1%);
  left: calc(var(--x, 50) * 1%);
  width: 34%;
  margin: 0;
  transform: translate(-50%, -50%);
}

.set__slot img {
  width: 100%;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 1rem 1.5rem rgb(33 27 28 / 18%));
}

/* --- I segni sulla fotografia ---------------------------------------------
   07/08/2026: erano una fascia di numeri SOTTO la foto, e all'utente non
   piaceva. Sono tornati sopra l'immagine, piccoli: una pastiglia col numero
   che si allunga col nome del prodotto quando la si sfiora o quando si passa
   sulla riga corrispondente a destra.

   IL NOME SI APRE IN LARGHEZZA dentro la pastiglia (`max-width` + `opacity`),
   non in un elemento posizionato: un'etichetta in `position: absolute` sul
   bordo destro della foto sarebbe uscita dal riquadro. E il segno si àncora
   dal lato giusto — `justify-self` cambia in base a dove sta — così quelli a
   destra si aprono verso sinistra.
   -------------------------------------------------------------------------- */
.set__pin {
  position: absolute;
  z-index: 3;
  top: calc(var(--y, 50) * 1%);
  left: calc(var(--x, 50) * 1%);
  display: inline-flex;
  align-items: center;
  gap: 0;
  height: 1.625rem;
  min-width: 1.625rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--set-pin-bg);
  color: var(--set-pin-ink);
  font-family: var(--pcr-font-body);
  font-size: 0.75rem;
  line-height: 1;
  cursor: pointer;
  transform: translate(-50%, -50%) scale(var(--pin-s, 1));
  box-shadow: 0 0.35rem 0.9rem rgb(33 27 28 / 26%);
  transition:
    transform 0.4s var(--pcr-ease-out),
    background 0.3s var(--pcr-ease),
    color 0.3s var(--pcr-ease),
    opacity 0.4s var(--pcr-ease);
}

/* L'anello che pulsa piano: dice che il segno si può toccare senza gridarlo. */
.set__pin::before {
  content: '';
  position: absolute;
  inset: -0.3rem;
  border-radius: 999px;
  border: 1px solid var(--set-pin-bg);
  opacity: 0;
  transition: opacity 0.35s var(--pcr-ease);
  pointer-events: none;
}

.set__pin-n {
  display: grid;
  place-items: center;
  width: 1.625rem;
  height: 1.625rem;
  flex: 0 0 auto;
}

.set__pin-name {
  display: block;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;

  /* LA RETE PER I NOMI LUNGHI. «Condizionante Fondente Nutriente» sono 32
     caratteri: senza questa riga la pastiglia lo tagliava a metà parola, e un
     nome mozzato si legge come un errore, non come un'abbreviazione. Con i
     puntini si capisce che continua — e il nome per esteso è comunque lì
     accanto, nella riga a destra. */
  text-overflow: ellipsis;
  opacity: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.01em;
  transition:
    max-width 0.45s var(--pcr-ease-out),
    opacity 0.3s var(--pcr-ease),
    padding-right 0.45s var(--pcr-ease-out);
}

/* =============================================================================
   APRENDOSI, IL PALLINO NON SI SPOSTA DAL PRODOTTO
   =============================================================================
   Misurato a schermo: con la pastiglia centrata sul punto, aprendo il nome
   l'etichetta cresceva da tutte e due le parti e finiva SOPRA il prodotto che
   doveva indicare — su un vasetto piccolo lo copriva quasi del tutto.

   La cura è aritmetica, non un secondo elemento: il pallino è largo 1,625rem,
   quindi ancorando il bordo sinistro della pastiglia a `x - 0,8125rem` il
   pallino resta esattamente sul punto QUALUNQUE sia la larghezza del nome, e
   il testo cresce di lato. Dalla metà destra della fotografia si specchia
   tutto (`row-reverse` + ancoraggio a destra), se no l'etichetta uscirebbe dal
   riquadro.

   E il `scale` sparisce da aperto: con la scatola diventata larga, l'origine
   della scala è il suo centro, e ingrandire sposterebbe il pallino di qualche
   pixel — cioè proprio quello che si sta cercando di evitare.
   ============================================================================= */
.set__pin.is-active,
.set__pin:hover,
.set__pin:focus-visible {
  --pin-s: 1;

  background: var(--set-pin-on-bg);
  color: var(--set-pin-on-ink);
  transform: translate(-0.8125rem, -50%);
}

.set__pin[data-side='right'] {
  flex-direction: row-reverse;
}

.set__pin[data-side='right'].is-active,
.set__pin[data-side='right']:hover,
.set__pin[data-side='right']:focus-visible {
  transform: translate(calc(-100% + 0.8125rem), -50%);
}

.set__pin[data-side='right'] .set__pin-name {
  transition:
    max-width 0.45s var(--pcr-ease-out),
    opacity 0.3s var(--pcr-ease),
    padding-left 0.45s var(--pcr-ease-out);
}

.set__pin[data-side='right'].is-active .set__pin-name,
.set__pin[data-side='right']:hover .set__pin-name,
.set__pin[data-side='right']:focus-visible .set__pin-name {
  padding-right: 0;
  padding-left: 0.7rem;
}

.set__pin.is-active::before,
.set__pin:hover::before {
  opacity: 0.8;
}

/* IL SEGNO APERTO PASSA SOPRA I VICINI.
   Tutti i segni stanno a `z-index: 3`, quindi a parità decide l'ordine nel
   documento: l'ultimo vince. Aprendo la pastiglia del 4 — che arriva a 13,5rem
   — il pallino del 5, che sul set da cinque gli sta a pochi punti percentuali,
   ci finiva SOPRA: si leggeva una cifra piantata in mezzo al nome del prodotto.
   Il segno aperto sale di un piano e si porta dietro il proprio nome. */
.set__pin.is-active,
.set__pin:hover,
.set__pin:focus-visible {
  z-index: 4;
}

/* 13,5rem = 216px, cioè il nome più lungo del catalogo a questo corpo. La
   pastiglia cresce da tutte e due i lati (è centrata sul punto), quindi ne
   sporgono al massimo 108 per parte: con i segni fra il 37% e il 64% della
   larghezza resta dentro la fotografia anche sul riquadro più stretto. */
.set__pin.is-active .set__pin-name,
.set__pin:hover .set__pin-name,
.set__pin:focus-visible .set__pin-name {
  max-width: 13.5rem;
  padding-right: 0.7rem;
  opacity: 1;
}

/* DUE ANELLI, NON UNO. Il fuoco da tastiera qui cade sopra una fotografia, e
   una fotografia può essere chiara quanto vuole: l'anello bianco da solo
   spariva sugli scatti su fondo panna — che in questo catalogo sono la norma.
   L'anello scuro esterno lo tiene visibile su qualunque scatto, e la coppia
   bianco/scuro supera i 3:1 di WCAG 1.4.11 in tutti e due i sensi. */
.set__pin:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  box-shadow:
    0 0 0 5px rgb(24 17 18 / 88%),
    0 0.35rem 0.9rem rgb(33 27 28 / 26%);
}

/* Col faro acceso gli altri segni si tirano indietro: restano leggibili (sono
   pur sempre la mappa della scena) ma smettono di contendere l'attenzione a
   quello che si sta guardando. */
/* MENTRE UNO E' APERTO, GLI ALTRI SI SPENGONO DEL TUTTO.
   Prima restavano al 42%: l'idea era tenere la mappa della scena leggibile.
   Ma aperta la pastiglia arriva a 13,5rem, e sul set da cinque il 4 e il 5
   distano pochi punti percentuali: la cifra del segno vicino cadeva DENTRO il
   nome del prodotto — «Insight Condizionante Fo(5)nte Nutrie…». Un numero in
   mezzo a una parola non si legge come una mappa, si legge come un errore.
   Alzare lo z-index del segno aperto non basta: il vicino resta comunque
   appoggiato sul bordo della pastiglia. Qui l'unica misura che chiude il caso
   e' toglierli di mezzo finche' si sta leggendo — tornano appena il puntatore
   se ne va, e il numero e' comunque scritto nella riga a destra. */
/* IL `.set` IN TESTA NON E' DECORAZIONE, E' QUELLO CHE FA VINCERE LA REGOLA.
   Piu' in basso, a riga ~1755, l'ingresso scrive
   `.set[data-entrance='true'].set--armed .set__pin { opacity: calc(1 - var(--rp)) }`:
   quattro classi, esattamente come `.set__stage.is-focusing .set__pin:not(.is-active)`.
   A parita' di peso vince l'ultima scritta — che sta dopo. Ecco perche' il 42%
   di prima non si e' MAI visto: a riposo `--rp` vale 0 e quella riga rimetteva
   l'opacita' a 1. E' la stessa trappola annotata li' accanto per il box-shadow.
   Con `.set` davanti sono cinque classi e la regola vince ovunque la si metta. */
.set .set__stage.is-focusing .set__pin:not(.is-active) {
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

/* Sul ripiego (nessuna foto) il segno si appoggia sotto al prodotto vero. */
.set__pin--slot {
  top: 100%;
  left: 50%;
}

/* =============================================================================
   L'ELENCO
   ============================================================================= */
.set__list-wrap {
  min-width: 0;
}

.set__rows {
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* `minmax(0, 1fr)` E NON `1fr`. Difetto vero, trovato misurando su 390px il
   21/08/2026: nella scena «Colore» il nome del prodotto e il menu del formato
   uscivano di 95px dallo schermo, tagliati.

   La causa è il `<select>`. La larghezza minima di un menu a tendina la decide
   la sua opzione più lunga — qui «Attivatore colore nutriente 6 volumi…» — e
   quella misura risale come minimo di contenuto fino alla traccia della
   griglia. `1fr` è la scorciatoia di `minmax(auto, 1fr)`, e quell'`auto` è
   proprio il minimo di contenuto: la colonna si allargava a 345px su una
   sezione da 390. Il `min-width: 0` su `.set__body` non basta, perché il
   problema nasce un livello più sotto, dentro il menu.

   `minmax(0, 1fr)` dice alla traccia che può scendere fino a zero, e il menu
   qui sotto è tenuto dentro con `max-width: 100%`. Le altre due scene non lo
   mostravano: hanno nomi di variante più corti. È il tipo di difetto che si
   vede solo aprendo la terza linguetta su un telefono, e per questo va chiuso
   sulla REGOLA e non sul singolo prodotto. */
.set__row {
  position: relative;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(0.75rem, 1.6vw, 1.25rem);
  padding-block: clamp(0.9rem, 1.8vw, 1.4rem);
  padding-inline: 0.75rem;
  border-top: 1px solid var(--set-line);
  border-radius: 8px;
  transition: background-color 0.3s var(--pcr-ease);
}

.set__row:last-child {
  border-bottom: 1px solid var(--set-line);
}

.set__row.is-active {
  background: rgb(142 28 43 / 5%);
  background: color-mix(in srgb, var(--set-accent) 5%, transparent);
}

/* IL SEGNALIBRO. Un filetto che cresce sul bordo sinistro della riga viva:
   dice quale riga sta comandando il faro sulla fotografia, e lo dice anche a
   chi arriva col Tab e non ha un puntatore da seguire. Cresce dal centro, così
   non sembra che scivoli dentro da fuori. */
.set__row::before {
  content: '';
  position: absolute;
  left: 0;
  top: 12%;
  bottom: 12%;
  width: 2px;
  border-radius: 2px;
  background: var(--set-accent);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform 0.4s var(--pcr-ease-out);
}

.set__row.is-active::before {
  transform: scaleY(1);
}

.set__num {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 1px solid var(--set-line);
  font-family: var(--pcr-font-body);
  font-size: 0.75rem;
  color: var(--set-muted);
  transition:
    border-color 0.3s var(--pcr-ease),
    background 0.3s var(--pcr-ease),
    color 0.3s var(--pcr-ease);
}

.set__row.is-active .set__num {
  border-color: var(--set-accent);
  background: var(--set-accent);
  color: var(--set-accent-ink);
}

/* --- La miniatura che apre la foto in grande ------------------------------- */
.set__thumb {
  position: relative;
  width: clamp(3.5rem, 7vw, 5.5rem);
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 10px;
  overflow: hidden;
  background: var(--pcr-bg-surface);
  cursor: pointer;
  transition:
    box-shadow 0.35s var(--pcr-ease),
    background 0.35s var(--pcr-ease);
}

.set__thumb:hover,
.set__thumb:focus-visible,
.set__row.is-active .set__thumb {
  box-shadow: 0 0.5rem 1.25rem rgb(33 27 28 / 16%);
}

.set__thumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 8%;
}

.set__zoom {
  position: absolute;
  right: 0.25rem;
  bottom: 0.25rem;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--pcr-shade-95);
  color: var(--pcr-white);
  opacity: 0.72;
  transition: opacity 0.3s var(--pcr-ease);
}

.set__thumb:hover .set__zoom,
.set__thumb:focus-visible .set__zoom {
  opacity: 1;
}

.set__body {
  min-width: 0;
  display: grid;
  gap: 0.35rem;
}

.set__name {
  margin: 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-body);
  line-height: 1.3;
}

.set__name a {
  color: var(--set-ink);
  text-decoration: none;
}

.set__name a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* Col dito la riga accesa e' anche un invito: il secondo tocco apre la scheda,
   e il filetto sotto il nome e' l'unico modo di dirlo senza scrivere una
   didascalia. Dove c'e' un puntatore vero questo non serve: ci pensa l'hover. */
@media (hover: none) {
  .set__row.is-active .set__name a {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
    text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
  }
}

.set__select {
  position: relative;
  justify-self: start;

  /* Vedi la nota lunga su `.set__row`: senza questi due, l'opzione più lunga
     del menu detta la larghezza della colonna e la riga esce dallo schermo. */
  min-width: 0;
  max-width: 100%;
}

.set__select select {
  appearance: none;
  min-height: 2.1rem;
  padding: 0.25rem 1.6rem 0.25rem 0;
  border: 0;
  background: transparent;
  color: var(--set-muted);
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  cursor: pointer;

  /* Il menu si stringe con la colonna e, se l'etichetta non ci sta, la
     tronca con i puntini invece di spingere fuori la riga. Il valore per
     esteso resta comunque leggibile: aprendo la tendina il browser mostra le
     opzioni alla loro larghezza vera. */
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.set__select select:focus-visible {
  outline: 2px solid var(--set-accent);
  outline-offset: 2px;
}

.set__select::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 0.45rem;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 1px solid var(--set-muted);
  border-bottom: 1px solid var(--set-muted);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

.set__price {
  margin: 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-body);
  white-space: nowrap;
}

/* --- Il piede -------------------------------------------------------------- */
.set__foot {
  display: grid;
  gap: 0.75rem;
  justify-items: center;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}

.set__total {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  color: var(--set-muted);
}

.set__total strong {
  color: var(--set-ink);
  font-weight: 500;

  /* Il totale cambia scena e formato: una misura fissa gli impedisce di far
     ballare la riga a ogni cifra in più. */
  font-variant-numeric: tabular-nums;
}

/* Quanti pezzi ha QUESTA scena: non tutte ne hanno tre, e il titolo della
   sezione non può dirlo per tutte. */
.set__count {
  color: var(--set-ink);
}

.set__sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentcolor;
  opacity: 0.5;
}

/* --- Il pulsante ------------------------------------------------------------
   Una lama di luce lo attraversa al passaggio del mouse. Sta dentro un
   contenitore che ritaglia, e si muove per `transform`: non tocca il testo,
   che resta nitido. */
.set__add {
  position: relative;
  min-width: min(22rem, 100%);
  overflow: hidden;
  isolation: isolate;
}

.set__add-text {
  position: relative;
  z-index: 1;
}

.set__add-sheen {
  position: absolute;
  inset-block: -50%;
  left: -30%;
  width: 22%;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(100deg, transparent, rgb(255 255 255 / 45%), transparent);
  transform: translateX(0) rotate(10deg);
}

@media (prefers-reduced-motion: no-preference) {
  .set__add:hover .set__add-sheen,
  .set__add:focus-visible .set__add-sheen {
    animation: set-lama-btn 0.75s var(--pcr-ease-out);
  }
}

@keyframes set-lama-btn {
  from {
    opacity: 0;
    transform: translateX(0) rotate(10deg);
  }

  15% {
    opacity: 1;
  }

  to {
    opacity: 0;
    transform: translateX(600%) rotate(10deg);
  }
}

.set__note {
  margin: 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  color: var(--set-muted);
  text-align: center;
}

.set__note--left {
  text-align: left;
}

.set__error {
  margin: 0;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  color: var(--set-accent);
  text-align: center;
}

/* =============================================================================
   LA FINESTRA: la foto in grande
   =============================================================================
   `<dialog>` nativo: focus trappolato, Esc, inerzia del resto della pagina e
   ritorno del fuoco all'elemento che l'ha aperta — gratis, senza una riga.
   ============================================================================= */
.set__dialog {
  width: min(52rem, 92vw);
  max-width: none;
  padding: 0;
  border: 0;
  border-radius: var(--set-radius);
  background: var(--pcr-bg-primary);
  color: var(--set-ink);
  overflow: hidden;
}

.set__dialog::backdrop {
  background: rgb(26 19 21 / 62%);
  backdrop-filter: blur(3px);
}

@media (prefers-reduced-motion: no-preference) {
  .set__dialog[open] {
    animation: set-apri 0.45s var(--pcr-ease-out);
  }
}

@keyframes set-apri {
  from {
    opacity: 0;
    transform: translate3d(0, 1.5rem, 0) scale(0.96);
  }
}

.set__dialog-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--set-line);
}

.set__dialog-title {
  margin: 0;
  font-family: var(--pcr-font-display);
  font-size: 1.15rem;
  font-weight: 300;
}

.set__close {
  border: 0;
  background: none;
  color: var(--set-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem;
}

/* Stessa ragione del palco: senza `pan-y` il browser annulla il gesto e lo
   scorrimento fra le foto del prodotto non arriva mai al `pointerup`. */
.set__viewer {
  position: relative;
  touch-action: pan-y pinch-zoom;
  aspect-ratio: 4 / 3;
  max-height: 70svh;
  background: var(--pcr-bg-surface);
  display: grid;
  place-items: center;
}

.set__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 4%;
  opacity: 0;
  transition: opacity 0.25s var(--pcr-ease);
}

.set__frame.is-on {
  opacity: 1;
}

.set__nav {
  position: absolute;
  z-index: 2;
  top: 50%;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--set-line);
  border-radius: 50%;
  background: var(--pcr-bg-primary);
  color: var(--set-ink);
  cursor: pointer;
  transform: translateY(-50%);
  transition:
    background 0.3s var(--pcr-ease),
    color 0.3s var(--pcr-ease);
}

.set__nav:hover,
.set__nav:focus-visible {
  background: var(--set-accent);
  color: var(--set-accent-ink);
}

.set__nav--prev {
  left: 0.75rem;
}

.set__nav--next {
  right: 0.75rem;
}

.set__dots {
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  min-height: 0.5rem;
  padding-block: 0.85rem 0;
}

.set__dots:empty {
  display: none;
}

.set__dot {
  width: 0.45rem;
  height: 0.45rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--set-line);
  cursor: pointer;
  transition:
    background 0.3s var(--pcr-ease),
    transform 0.3s var(--pcr-ease-out);
}

.set__dot.is-on {
  background: var(--set-accent);
  transform: scale(1.25);
}

.set__hint {
  margin: 0;
  padding: 0.6rem 1rem 1rem;
  text-align: center;
  font-family: var(--pcr-font-body);
  font-size: var(--pcr-fs-small);
  color: var(--set-muted);
  pointer-events: none;
}

.set__hint:empty {
  display: none;
}

/* =============================================================================
   L'INGRESSO AGGANCIATO ALLO SCORRIMENTO
   =============================================================================
   Il JS scrive UN SOLO numero sulla sezione — `--set-rise`, 1 = ancora
   abbassata, 0 = in posizione — e qui diventa salita, dissolvenza e sipario
   sulla fotografia. NON È UN'ANIMAZIONE: è una posizione, fotogramma per
   fotogramma. Tornando su, la sezione riscende.

   LA CASCATA IN UNA RIGA DI ARITMETICA. Ogni parte ha uno sfasamento `--sh`
   fra 0 e 0,6 e ne ricava il PROPRIO abbassamento:

       r = min(1, rise / (1 - sh))

   NON `(rise - sh) / (1 - sh)`: `rise` scende da 1 a 0, non sale, e quella
   formula farebbe partire in ritardo la parte sbagliata.

   IL VALORE DI RIPIEGO È 0, cioè «in posizione»: se il JS non gira non si
   nasconde niente. Lo stato abbassato vive solo sotto `.set--armed`.
   ============================================================================= */
/* LA TESTATA NON È PIÙ UN BLOCCO SOLO  (20/08/2026)
   Prima `.set__head` entrava tutto insieme: sopratitolo, titolo e selettore
   delle scene salivano come un unico rettangolo. Funzionava, ma era il
   movimento di un'immagine, non di una pagina che si compone. Adesso i tre
   pezzi hanno ognuno il proprio scarto — e il titolo, che è la cosa che si
   legge, ha un ingresso suo (la salita da dietro la riga, più sotto).

   L'ARRIVO È EASE-OUT, E LO FA UNA MOLTIPLICAZIONE.
   `--r` scende da 1 a 0 in modo lineare con lo scorrimento, e un'opacità
   lineare tiene la sezione slavata per mezzo schermo: a metà strada era ancora
   al 57%. `--e = r × r` è la stessa curva vista nel tempo, ma con la coda
   schiacciata: a metà strada l'opacità è già all'79% e l'ultimo tratto è un
   assestamento, non un'attesa. È la differenza fra «sta arrivando» e «è
   arrivato». (In CSS `calc()` la moltiplicazione fra due <number> è lecita:
   non serve una funzione di easing.) */
.set[data-entrance='true'].set--armed
  :is(.set__eyebrow, .set__switch, .set__scene, .set__rows, .set__foot) {
  --r: clamp(0, calc(var(--set-rise, 0) / (1 - var(--sh, 0))), 1);
  --e: calc(var(--r) * var(--r));

  transform: translate3d(0, calc(var(--e) * var(--set-rise-dist, 64px)), 0);
  opacity: calc(1 - var(--e) * 0.9);
  will-change: transform, opacity;
}

/* IL TITOLO È FUORI DALL'ELENCO QUI SOPRA, ED È VOLUTO.
   Ci era dentro nella prima stesura, e il conto non tornava: il guscio saliva
   per conto suo E l'interno saliva dentro il guscio, cioè lo stesso movimento
   contato due volte, con il ritaglio che si spostava insieme al testo — che è
   esattamente ciò che il ritaglio non deve fare. Il titolo prende quindi solo
   le due variabili; il movimento sta tutto sull'interno, e l'opacità non serve
   perché la riga che scopre È già la comparsa. */
.set[data-entrance='true'].set--armed .set__title {
  --sh: 0.06;
  --r: clamp(0, calc(var(--set-rise, 0) / (1 - var(--sh))), 1);
  --e: calc(var(--r) * var(--r));
}

.set[data-entrance='true'].set--armed .set__switch {
  --sh: 0.18;
}

.set[data-entrance='true'].set--armed .set__scene {
  --sh: 0.12;
}

.set[data-entrance='true'].set--armed .set__rows {
  --sh: 0.3;
}

.set[data-entrance='true'].set--armed .set__foot {
  --sh: 0.46;
}

/* IL TITOLO SALE DA DIETRO UNA RIGA.
   Il guscio ritaglia e l'interno scorre: è il gesto tipografico che una
   dissolvenza non sa fare, e costa zero in nitidezza perché è una traslazione
   dentro un `overflow`, non una scala.

   IL RITAGLIO HA BISOGNO DI ARIA SOTTO. Il carattere del display ha discendenti
   (la «g» di «ordine»): un `overflow: hidden` a filo di riquadro gliele
   taglierebbe anche a ingresso finito. Lo spazio si aggiunge in basso e si
   riprende con un margine negativo, così il ritaglio ha dove finire e
   l'impaginazione non si muove di un pixel.

   Qui si usa `--r` grezzo e non `--e`: il titolo deve arrivare un soffio DOPO
   il resto della testata, non insieme. È l'unico posto in cui la coda lunga
   della curva lineare è quella giusta. */
/* IL RITAGLIO NON STA PIU' QUI. (02/09/2026)
   L'`overflow: hidden` sul titolo serviva al vecchio effetto — una riga sola
   che scopriva il testo intero. Adesso il titolo si svela a PAROLE, e ogni
   parola porta la sua finestrella (`.pcr-word`): un secondo ritaglio sopra
   tutta la riga taglierebbe le lettere discendenti delle parole che salgono e
   non aggiungerebbe niente. Via il ritaglio, e con lui i due valori che ne
   compensavano il taglio. */


/* IL SOPRATITOLO SI METTE A FUOCO invece di limitarsi a salire: parte con le
   lettere più larghe e le stringe fino alla spaziatura di riposo. È un
   dettaglio da mezzo secondo che si nota solo se manca. */
.set[data-entrance='true'].set--armed .set__eyebrow {
  letter-spacing: calc(0.14em + var(--e, 0) * 0.26em);
}

/* IL SIPARIO SULLA FOTOGRAFIA. `clip-path` ritaglia, non ricampiona: a
   differenza di una `scale` non costa un grammo di nitidezza. La foto si
   scopre dal basso mentre la sezione arriva.

   RIFATTO IN TRE TEMPI IL 21/08/2026. Prima era un tempo solo: il sipario
   correva su tutta la corsa (`/ 0.9`) e finiva insieme a tutto il resto. Il
   risultato era che la fotografia «c'era» dal primo istante — coperta a metà,
   ma già arrivata — e non compariva mai davvero.

   Adesso i tempi sono tre:
     1. il sipario ha una FINESTRA sua — chiuso fino a rise 0,85, aperto del
        tutto già a rise 0,35. Serve la sottrazione (`rise − 0,35`) e non una
        semplice divisione: dividendo, il sipario finirebbe per forza a rise
        zero, cioè insieme a tutto il resto, ed è esattamente il difetto che si
        stava correggendo. Così invece la fotografia è INTERA mentre la sezione
        sta ancora salendo, e il resto della corsa serve a posarla;
     2. l'ombra cresce lungo tutta la corsa: la foto passa da appoggiata sulla
        pagina a staccata da essa — è quello che si legge come «è arrivata»;
     3. i segni numerati arrivano per ULTIMI, uno dopo l'altro (regola più in
        basso). Prima si vede la scena, poi si scopre che è comprabile.

   L'OMBRA È CLIPPATA DAL SIPARIO, ed è giusto così: una fotografia che sta
   ancora uscendo da dietro una tenda non può proiettare ombra fuori dalla
   tenda. A ingresso finito `.is-settled` toglie il ritaglio e l'ombra si apre.
   I tre valori a `--r: 0` coincidono al pixel con quelli scritti nella regola
   di base di `.set__stage` (1,5rem / 3rem / 12%): l'ultimo fotogramma di un
   ingresso deve valere esattamente quanto lo stato di riposo, se no a fine
   corsa c'è uno scatto. */
.set[data-entrance='true'].set--armed .set__scene .set__stage {
  --r: clamp(0, calc((var(--set-rise, 0) - 0.35) / 0.5), 1);
  --rs: clamp(0, calc(var(--set-rise, 0) / 0.9), 1);

  clip-path: inset(calc(var(--r) * 100%) 0 0 0 round var(--set-radius));
  box-shadow:
    0 calc(0.4rem + (1 - var(--rs)) * 1.1rem) calc(0.9rem + (1 - var(--rs)) * 2.1rem)
    rgb(33 27 28 / calc(4% + (1 - var(--rs)) * 8%));
}

/* LA LAMA DI LUCE, AGGANCIATA ALLO SCORRIMENTO E NON A UN CRONOMETRO.
   La stessa lama esiste già per il cambio scena (`set-lama`), ma lì è
   un'animazione: parte, dura un secondo, finisce. Qui non andava bene, perché
   l'ingresso di questa sezione è REVERSIBILE — si torna su e la sezione
   riscende. Un'animazione a tempo si sarebbe riavviata a ogni passaggio sul
   confine, e chi si ferma proprio lì avrebbe visto un lampeggio.

   Legata a `--set-rise` invece la lama è una POSIZIONE: attraversa la foto
   mentre la si porta in campo e torna indietro se si risale. L'opacità è il
   prodotto `(1 − r) · r`, cioè una campana: zero ai due capi della corsa,
   massima a metà. Così la lama non compare dal nulla né resta accesa alla
   fine — e a corsa finita vale esattamente zero, come nel foglio.

   La finestra (`rise − 0,3` su 0,6) è scelta perché il massimo cada a rise 0,6,
   cioè a metà dell'apertura del sipario: la lama deve passare MENTRE la
   fotografia si scopre, non prima su una tenda chiusa né dopo su una foto già
   ferma. */
.set[data-entrance='true'].set--armed .set__scene .set__sheen {
  --rl: clamp(0, calc((var(--set-rise, 0) - 0.3) / 0.6), 1);

  opacity: calc((1 - var(--rl)) * var(--rl) * 3.4);
  transform: translateX(calc((1 - var(--rl)) * 520%)) rotate(8deg);
}

/* I SEGNI ARRIVANO PER ULTIMI, UNO DOPO L'ALTRO.
   `--riga` è l'indice che il Liquid scrive già su ogni segno per lo scarto del
   cambio scena: qui viene riusato per lo scarto dell'ingresso, invece di
   inventare un secondo contatore che potrebbe scollarsi dal primo.

   `scale` è la PROPRIETÀ, non la funzione dentro `transform`: il segno ha già
   `transform: translate(-50%, -50%) scale(var(--pin-s))` e riscriverlo qui
   significherebbe perdere il centraggio o litigare con lo stato al passaggio
   del puntatore. */
.set[data-entrance='true'].set--armed .set__pin {
  --rp: clamp(0, calc((var(--set-rise, 0) - var(--riga, 0) * 0.045) / 0.34), 1);

  opacity: calc(1 - var(--rp));
  scale: calc(1 - var(--rp) * 0.45);
}

/* Durante la corsa i segni INSEGUONO lo scorrimento, quindi le transizioni
   vanno spente: con `opacity 0.4s` in mezzo, il segno arriverebbe quattro
   decimi di secondo dopo il dito e sembrerebbe scollegato dalla pagina.
   Quando `.is-settled` arriva, `--rp` vale già 0 e i valori sono già a riposo:
   riaccendere le transizioni in quell'istante non muove niente. */
.set[data-entrance='true'].set--armed:not(.is-settled) .set__pin {
  transition: none;
}

/* ============================================================================
   LA FOTOGRAFIA SI SOLLEVA AL PASSAGGIO DEL PUNTATORE
   ============================================================================
   Sta QUI, e non accanto alle altre regole del palco, per una ragione di
   cascata: la regola dell'ingresso qui sopra scrive `box-shadow` sullo stesso
   elemento e pesa esattamente uguale (cinque selettori). A parità di peso
   vince l'ultima — quindi questa deve stare dopo, o l'ombra non cambierebbe
   mai. Il sollevamento si vedrebbe lo stesso, e sembrerebbe tutto a posto:
   è per questo che l'errore è insidioso.

   Si muove il PALCO INTERO, non la fotografia: sopra ci sono i segni numerati
   puntati su flaconi precisi, e muovere solo la foto li scollerebbe
   dall'oggetto che indicano. Muovendo il palco il rapporto fra i due non
   cambia di un pixel.
   ========================================================================== */
.set[data-spotlight='true'] .set__scene .set__stage:hover {
  translate: 0 -6px;
  box-shadow: 0 2rem 3.5rem -1rem rgb(33 27 28 / 22%);
}

/* Il filetto della didascalia si allunga con la salita, come il sipario. */
.set[data-entrance='true'].set--armed .set__caption-rule {
  --rf: clamp(0, calc(var(--set-rise, 0) / 0.3), 1);

  transform: scaleX(calc(1 - var(--rf)));
}

/* Le tre ragioni si posano una dopo l'altra, in coda a tutto il resto: sono la
   lettura, e la lettura viene dopo che si è visto. `translate` e non
   `transform` — la voce non ha altri trasformi propri, ma tenerli separati
   costa niente e lascia libera la strada a chi domani volesse aggiungerne uno.
   Il riquadro sta dentro `.set__scene`, che ha già la sua salita: questo è uno
   scarto SOPRA quella, non un secondo ingresso. */
.set[data-entrance='true'].set--armed .set__aside-item {
  --ri: clamp(0, calc((var(--set-rise, 0) - var(--ra, 0) * 0.05) / 0.26), 1);

  opacity: calc(1 - var(--ri));
  translate: 0 calc(var(--ri) * 0.65rem);
}

/* I collegamenti agli altri rituali, in coda alle ragioni. */
.set[data-entrance='true'].set--armed .set__more-btn {
  --rp2: clamp(0, calc((var(--set-rise, 0) - var(--fs, 1) * 0.035) / 0.22), 1);

  opacity: calc(1 - var(--rp2));
  scale: calc(1 - var(--rp2) * 0.14);
}

/* La riga sopra la fotografia arriva con la fotografia, non dopo: è la sua
   didascalia in alto. */
.set[data-entrance='true'].set--armed .set__scene-bar {
  --rb: clamp(0, calc(var(--set-rise, 0) / 0.45), 1);

  opacity: calc(1 - var(--rb));
  translate: 0 calc(var(--rb) * 0.5rem);
}

/* FINITO L'INGRESSO NON RESTA NIENTE APPESO ALL'IMMAGINE. Un `transform` o un
   `clip-path` residuo, anche se a valore neutro, tiene la fotografia dentro un
   livello composito — ed è esattamente la causa dell'immagine sfocata trovata
   il 05/08/2026. `.is-settled` la mette il JS quando `rise` tocca lo zero. */
/* MISURATO, non dedotto (07/08/2026): la prima stesura era `.set.is-settled
   .set__stage`, tre classi, e NON vinceva — la regola del sipario qui sopra ne
   ha cinque. A ingresso finito il palco restava con `clip-path: inset(0%)`:
   invisibile a occhio, ma è comunque un livello di ritaglio appeso alla
   fotografia. Il selettore va ripetuto per intero, con `.is-settled` in più. */
.set[data-entrance='true'].set--armed.is-settled .set__scene .set__stage {
  clip-path: none;
}

.set.is-settled
  :is(.set__eyebrow, .set__title, .set__switch, .set__scene, .set__rows, .set__foot) {
  will-change: auto;
}

/* =============================================================================
   L'INGRESSO LEGATO ALLO SCORRIMENTO, FATTO DAL COMPOSITORE          23/09/2026
   =============================================================================
   «Il sito va a scatti.» Misurato: scrivere `--set-rise` sulla sezione a ogni
   fotogramma faceva ricalcolare lo stile di tutta la sezione (variabile
   ereditata, centinaia di nodi) e ridisegnare il sipario `clip-path` della foto
   e l'ombra. `.set--sdt` (la mette il JS dove il browser lo supporta) rifà LO
   STESSO ingresso — stessa corsa, stesse finestre, stessi scarti, sempre
   agganciato allo scorrimento e reversibile — con animazioni di sole
   `transform` e `opacity` legate alla vista della sezione.

   Come si traduce una finestra: una parte si muove mentre `rise` va da w0 a
   w1; il bordo alto della sezione sta allora a a1 + (a0 − a1)·w (a0/a1 = linee
   dell'editor, in `--set-a0`/`--set-a1`), e nel riferimento `cover` una
   posizione `a` del bordo alto sta a (1 − a)·100vh dall'inizio.

   Cosa cambia a vedersi, di proposito: il sipario sulla foto è un velo che si
   ritira (`::before`) invece di un ritaglio; l'ombra del palco è già quella di
   riposo invece di crescere; il sopratitolo non stringe più la spaziatura
   (animare `letter-spacing` rifà l'impaginazione del testo a ogni fotogramma).

   Selettori a due classi APPOSTA: le animazioni del cambio scena
   (`.set__panel.is-fresh …`, tre classi) devono vincere quando ci sono.
   ============================================================================= */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .set.set--sdt {
      view-timeline-name: --set-vista;
    }

    /* 23/09/2026 — SOLO LA SCENA ACCESA. Le scene spente (invisibili, una sopra
       l'altra nella stessa cella) avevano le stesse animazioni legate allo
       scorrimento di quella accesa: una settantina in tutto, e ognuna costa un
       ricalcolo di stile a ogni fotogramma mentre la sezione entra. Adesso le
       ha solo la scena accesa (`:where` non aggiunge peso: le animazioni del
       cambio scena, `.set__panel.is-fresh …`, vincono come prima). Quando la
       scena cambia, la nuova prende l'animazione nel punto in cui è lo
       scorrimento: a ingresso finito, cioè ferma a riposo. */
    .set--sdt :is(.set__eyebrow, .set__switch),
    .set--sdt :where(.set__panel.is-on) :is(.set__scene, .set__rows, .set__foot, .set__sheen, .set__pin, .set__caption-rule, .set__aside-item, .set__more-btn, .set__scene-bar),
    .set--sdt :where(.set__panel.is-on) .set__stage::before {
      --w1: 0;
      --set-da: calc(var(--set-a1, 0.42) + (var(--set-a0, 0.92) - var(--set-a1, 0.42)) * var(--w0, 1));
      --set-a: calc(var(--set-a1, 0.42) + (var(--set-a0, 0.92) - var(--set-a1, 0.42)) * var(--w1, 0));

      animation-duration: auto;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: --set-vista;
      animation-range:
        cover calc((1 - var(--set-da)) * 100vh)
        cover calc((1 - var(--set-a)) * 100vh);
    }

    /* I blocchi: salita + dissolvenza con la curva «r²» di prima, che è
       esattamente un'uscita quadratica. */
    .set--sdt :is(.set__eyebrow, .set__switch),
    .set--sdt :where(.set__panel.is-on) :is(.set__scene, .set__rows, .set__foot) {
      animation-name: set-sdt-blocco;
      animation-timing-function: cubic-bezier(0.3333, 0.6667, 0.6667, 1);
    }

    .set--sdt .set__eyebrow { --w0: 1; }
    .set--sdt .set__switch { --w0: 0.82; }
    .set--sdt :where(.set__panel.is-on) .set__scene { --w0: 0.88; }
    .set--sdt :where(.set__panel.is-on) .set__rows { --w0: 0.7; }
    .set--sdt :where(.set__panel.is-on) .set__foot { --w0: 0.54; }

    .set--sdt :where(.set__panel.is-on) .set__stage::before {
      --w0: 0.85;
      --w1: 0.35;

      animation-name: set-sdt-velo;
    }

    .set--sdt :where(.set__panel.is-on) .set__sheen {
      --w0: 0.9;
      --w1: 0.3;

      animation-name: set-sdt-lama;
    }

    .set--sdt :where(.set__panel.is-on) .set__pin {
      --w0: calc(var(--riga, 0) * 0.045 + 0.34);
      --w1: calc(var(--riga, 0) * 0.045);

      animation-name: set-sdt-segno;
    }

    .set--sdt :where(.set__panel.is-on) .set__caption-rule {
      --w0: 0.3;

      animation-name: set-sdt-filetto;
    }

    .set--sdt :where(.set__panel.is-on) .set__aside-item {
      --w0: calc(var(--ra, 0) * 0.05 + 0.26);
      --w1: calc(var(--ra, 0) * 0.05);

      animation-name: set-sdt-voce;
    }

    .set--sdt :where(.set__panel.is-on) .set__more-btn {
      --w0: calc(var(--fs, 1) * 0.035 + 0.22);
      --w1: calc(var(--fs, 1) * 0.035);

      animation-name: set-sdt-pastiglia;
    }

    .set--sdt :where(.set__panel.is-on) .set__scene-bar {
      --w0: 0.45;

      animation-name: set-sdt-barra;
    }
  }

  @keyframes set-sdt-blocco {
    from {
      transform: translate3d(0, var(--set-rise-dist, 64px), 0);
      opacity: 0.1;
    }

    to {
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }

  @keyframes set-sdt-velo {
    from { transform: scaleY(1); }
    to { transform: scaleY(0); }
  }

  @keyframes set-sdt-lama {
    0% {
      opacity: 0;
      transform: translateX(0) rotate(8deg);
    }

    50% {
      opacity: 0.85;
      transform: translateX(260%) rotate(8deg);
    }

    100% {
      opacity: 0;
      transform: translateX(520%) rotate(8deg);
    }
  }

  @keyframes set-sdt-segno {
    from {
      opacity: 0;
      scale: 0.55;
    }

    to {
      opacity: 1;
      scale: 1;
    }
  }

  @keyframes set-sdt-filetto {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }

  @keyframes set-sdt-voce {
    from {
      opacity: 0;
      translate: 0 0.65rem;
    }

    to {
      opacity: 1;
      translate: 0 0;
    }
  }

  @keyframes set-sdt-pastiglia {
    from {
      opacity: 0;
      scale: 0.86;
    }

    to {
      opacity: 1;
      scale: 1;
    }
  }

  @keyframes set-sdt-barra {
    from {
      opacity: 0;
      translate: 0 0.5rem;
    }

    to {
      opacity: 1;
      translate: 0 0;
    }
  }
}

/* =============================================================================
   IL CAMBIO DI SCENA
   =============================================================================
   `.is-fresh` la mette il JS sul pannello appena acceso e la toglie dopo. Le
   animazioni hanno `animation-fill-mode: backwards` e MAI `forwards`/`both`:
   con `both` l'ultimo fotogramma resta appiccicato e batte per sempre le
   transizioni successive (lezione del 30/07/2026 sul carosello dei banner).
   L'ultimo fotogramma qui vale esattamente quanto il valore di foglio, quindi
   quando l'animazione si spegne non c'è nessuno scatto.
   ============================================================================= */
/* DURATE E SCARTI ALLUNGATI il 21/08/2026 («gli effetti della sezione il set
   sono troppo veloci»). Il cambio di scena è una CORREOGRAFIA: sipario, lama,
   righe, segni, piede. Con i tempi vecchi l'intera sequenza si chiudeva in
   1,1s — cioè i cinque momenti si sovrapponevano quasi tutti, e quello che si
   percepiva era un lampo unico. Ora dura circa 2s e i momenti si distinguono.

   Il tetto è il tempo di permanenza della scena (7s di serie): la coreografia
   non deve mai avvicinarsi a quella soglia, se no una scena finisce di
   comporsi mentre la successiva sta già partendo. 2s su 7 è comodo. */
@media (prefers-reduced-motion: no-preference) {
  /* 23/09/2026: il sipario del cambio scena non è più un `clip-path`
     animato (ridisegnato a ogni fotogramma sul thread principale) ma un velo
     del colore del palco che si ritira verso sinistra con `transform`: stessa
     finestra (dal 62% al bordo), stessi tempi, lo esegue la scheda grafica. */
  .set__panel.is-fresh .set__stage::after {
    animation: set-scopri-velo 1.4s var(--pcr-ease-out) backwards;
  }

  .set__panel.is-fresh .set__sheen {
    animation: set-lama 1.6s var(--pcr-ease-out) 0.18s backwards;
  }

  .set__panel.is-fresh .set__row {
    animation: set-riga 1.05s var(--pcr-ease-out) calc(var(--riga, 0) * 0.16s + 0.24s) backwards;
  }

  .set__panel.is-fresh .set__pin {
    animation: set-segno 0.85s var(--pcr-ease-out) calc(var(--riga, 0) * 0.14s + 0.75s) backwards;
  }

  .set__panel.is-fresh .set__foot {
    animation: set-riga 0.95s var(--pcr-ease-out) 0.78s backwards;
  }

  .set__panel.is-fresh .set__caption {
    animation: set-riga 0.95s var(--pcr-ease-out) 0.52s backwards;
  }

  .set__panel.is-fresh .set__caption-rule {
    animation: set-filetto 1.1s var(--pcr-ease-out) 0.58s backwards;
  }

  /* Le tre ragioni entrano in coda a tutto il resto, una dopo l'altra: sono
     la lettura, e la lettura viene dopo che si è visto. `--ra` è l'indice che
     il Liquid scrive già su ogni voce. */
  .set__panel.is-fresh .set__aside-item {
    animation: set-riga 0.9s var(--pcr-ease-out) calc(var(--ra, 0) * 0.12s + 0.95s) backwards;
  }

  /* La riga sopra la fotografia entra per PRIMA, prima del sipario: annuncia
     quale scena sta arrivando, e un annuncio che arriva dopo la cosa annunciata
     non serve a niente. */
  .set__panel.is-fresh .set__scene-bar {
    animation: set-riga 0.8s var(--pcr-ease-out) backwards;
  }

  /* I collegamenti agli altri rituali si accendono in sequenza. */
  .set__panel.is-fresh .set__more-btn {
    animation: set-passo 0.7s var(--pcr-ease-out) calc(var(--fs, 1) * 0.09s + 1.15s) backwards;
  }

  .set__panel.is-fresh .set__more-title {
    animation: set-riga 0.8s var(--pcr-ease-out) 1.1s backwards;
  }
}

/* La pastiglia non trasla di lato come le righe: si apre sul posto. Sono
   oggetti affiancati in orizzontale — farli arrivare da destra li farebbe
   scavalcare a vicenda, ed è brutto proprio perché sono vicini. */
@keyframes set-passo {
  from {
    opacity: 0;
    transform: scale(0.86);
  }
}

@keyframes set-filetto {
  from {
    transform: scaleX(0);
  }
}

/* Nota di cascata: la regola del sipario ha specificità più alta di queste, ma
   non conta — le dichiarazioni che vengono da un'animazione stanno in un
   gradino più alto della cascata e battono comunque le dichiarazioni normali,
   qualunque sia il selettore. Quindi un cambio di scena mentre la sezione sta
   ancora entrando si vede lo stesso, e non serve nessuna regola in più. */

@keyframes set-scopri {
  from {
    clip-path: inset(0 0 0 62% round var(--set-radius));
  }
}

@keyframes set-scopri-velo {
  from {
    transform: scaleX(0.62);
  }

  to {
    transform: scaleX(0);
  }
}

/* I due veli del palco (23/09/2026): `::after` per il cambio di scena (si
   ritira verso sinistra), `::before` per l'ingresso legato allo scorrimento
   (si ritira verso l'alto, cioè la foto si scopre dal basso). A riposo sono a
   scala zero: non coprono niente e non costano niente. Stanno sopra la foto,
   la luce e i segni (che comunque arrivano dopo) e non prendono i clic. */
.set__stage::before,
.set__stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 6;
  background: var(--pcr-bg-surface);
  pointer-events: none;
  transform: scaleX(0);
  transform-origin: left center;
}

.set__stage::before {
  transform: scaleY(0);
  transform-origin: center top;
}

@keyframes set-lama {
  from {
    opacity: 0;
    transform: translateX(0) rotate(8deg);
  }

  12% {
    opacity: 1;
  }

  to {
    opacity: 0;
    transform: translateX(520%) rotate(8deg);
  }
}

@keyframes set-riga {
  from {
    opacity: 0;
    transform: translate3d(1.25rem, 0, 0);
  }
}

@keyframes set-segno {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.4);
  }
}

/* =============================================================================
   SCHERMI STRETTI
   ============================================================================= */
@media (width < 60rem) {
  .set__inner {
    grid-template-columns: 1fr;
  }

  .set__row {
    grid-template-columns: auto auto minmax(0, 1fr);
    grid-template-areas:
      'num thumb body'
      '.   .     price';
    row-gap: 0.35rem;
  }

  .set__num {
    grid-area: num;
  }

  .set__thumb {
    grid-area: thumb;
  }

  .set__body {
    grid-area: body;
  }

  .set__price {
    grid-area: price;
    justify-self: start;
  }

  /* Su telefono il nome dentro il segno non ci sta: la foto è larga quanto lo
     schermo e un'etichetta da 11rem uscirebbe dal riquadro. Resta il numero,
     e toccarlo porta alla riga del prodotto. */
  .set__pin-name {
    display: none;
  }

  /* Senza nome la pastiglia torna a essere solo il pallino: l'ancoraggio di
     lato non serve più (i due conti coincidono) e si può rimettere la crescita,
     che qui è l'unico modo di far vedere quale segno è vivo — non c'è un
     puntatore che ci passi sopra. */
  .set__pin.is-active,
  .set__pin[data-side='right'].is-active {
    --pin-s: 1.14;

    transform: translate(-50%, -50%) scale(var(--pin-s));
  }

  .set__switch {
    align-self: stretch;
    justify-content: flex-start;
  }
}

@media (width < 30rem) {
  .set__tab {
    padding-inline: 0.85rem;
  }
}

/* =============================================================================
   MOVIMENTO RIDOTTO
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
  .set__stage,
  .set__thumb,
  .set__pin,
  .set__slot,
  .set__frame,
  .set__dot,
  .set__panel {
    transition: none;
  }

  .set__tab.is-on .set__tab-fill {
    animation: none;
  }

  .set__sheen,
  .set__add-sheen {
    display: none;
  }

  /* Il faro resta — non è un movimento, è un'informazione: dice quale prodotto
     è quale. Sparisce solo lo scivolamento da un flacone all'altro. */
  .set__focus {
    transition: opacity 0.2s linear;
  }

  .set__row::before,
  .set__caption-rule {
    transition: none;
    transform: none;
  }

  /* I BLOCCHI NUOVI DEL 21/08/2026, spenti per nome.
     `opacity` e `scale`/`translate` qui sopra non sono toccati da
     `transform: none`: senza queste righe la riga sopra la fotografia e i
     passi del rituale resterebbero invisibili proprio a chi ha chiesto meno
     movimento — che è togliergli contenuto, non movimento. */
  .set__scene-bar,
  .set__more-btn,
  .set__more-title,
  .set__aside-item {
    animation: none;
    opacity: 1;
    translate: none;
    scale: none;
    transform: none;
  }

  .set__row::before {
    opacity: 0;
  }

  .set__row.is-active::before {
    opacity: 1;
  }
}

/* =============================================================================
   «IL SET» SU TELEFONO — SECONDA PASSATA (28/08/2026)
   =============================================================================
   Guardata la sezione su 390x844 sono venuti fuori quattro difetti, tutti
   misurati in pagina e non dedotti dal foglio:

   1. LA QUARTA LINGUETTA ERA TAGLIATA. Le quattro scene misurano 82+110+64+109
      piu' gli spazi = 382px in una barra larga 350: «Ricostruzione» finiva
      SOTTO il bordo arrotondato della pastiglia, mezza parola e nient'altro.
      La barra scorre (`overflow-x: auto`) ma la barra di scorrimento e'
      nascosta: su un telefono non c'e' niente che dica che la' dietro c'e'
      un'altra scena. Sotto le 30rem le linguette vanno a capo e si vedono
      tutte e quattro insieme; sopra ci stanno in fila per conto loro.
      (Il JS in piu' tiene la linguetta viva dentro la vista quando la barra
      scorre davvero — serve al giro automatico, che cambia scena da solo.)

   2. LA LENTINA STAVA ADDOSSO AL PRODOTTO. Il pallino dello zoom e' 20px su
      una miniatura di 56: un terzo della larghezza, appoggiato proprio
      sull'angolo in basso a destra del flacone. Miniatura piu' grande,
      pallino piu' piccolo.

   3. LE MINIATURE ERANO TROPPO PICCOLE PER RICONOSCERE IL PRODOTTO. 56px meno
      l'8% di rientro fanno ~48: un flacone da 900ml, che e' alto e stretto,
      ci arriva largo venti pixel. Non si legge l'etichetta e non si distingue
      uno shampoo da un condizionante — che e' esattamente il lavoro che deve
      fare quella figura.

   4. IL PREZZO ERA ORFANO SU UNA RIGA SUA. La griglia stretta metteva il
      prezzo in una seconda riga rientrata sotto il nome, e il numero e la
      miniatura non stavano piu' insieme: 117px per riga, 585 per cinque
      prodotti. Numero e miniatura scavalcano le due righe e il prezzo torna
      accanto al formato: stessa informazione, ~30px in meno per riga.
   -------------------------------------------------------------------------- */
@media (width < 48rem) {
  /* 12/09/2026 — IL PREZZO TORNA IN LINEA, COME SU DESKTOP.
     Il punto 4 qui sopra aveva gia' tolto il prezzo dalla sua riga rientrata,
     ma restava sotto il nome: con quattro prodotti l'elenco faceva ~800px e
     la sezione superava una schermata e mezza sul telefono. Su desktop la
     riga e' una sola — numero, miniatura, nome, prezzo a destra — e sul
     telefono ci sta: il prezzo e' corto (max «€119,50») e il nome puo'
     andare su due righe, con la terza tagliata (il nome intero e' a un tocco,
     sulla scheda). Misurato a 390px: riga da 199px a 100px, sezione da 1357px
     a ~950px. */
  .set__row {
    grid-template-columns: 1.4rem 3.5rem minmax(0, 1fr) auto;
    grid-template-areas: 'num thumb body price';
    align-items: center;
    row-gap: 0;
    column-gap: 0.6rem;
    padding-block: 0.5rem;
    padding-inline: 0.35rem;
  }

  .set__num,
  .set__thumb {
    align-self: center;
  }

  .set__num {
    width: 1.4rem;
    height: 1.4rem;
    font-size: 0.6875rem;
  }

  /* 3,5rem: il testo a fianco sta in due righe e la riga e' alta quanto la
     miniatura, non piu' del testo. Sotto i 3rem il flacone non si riconosce
     piu' (vedi il punto 3 qui sopra). */
  .set__thumb {
    width: 3.5rem;
  }

  /* Due righe al massimo: la terza e' quasi sempre una sola parola e costa
     altezza a tutte le righe dell'elenco. */
  .set__name {
    font-size: 0.8125rem;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .set__select select,
  .set__note--left {
    font-size: 0.75rem;
  }

  .set__price {
    grid-area: price;
    justify-self: end;
    align-self: center;
    font-size: 0.8125rem;
    white-space: nowrap;
  }

  /* Testata e piede: la stessa aria del desktop su uno schermo alto un terzo
     costa mezza schermata. Qui si stringe, senza toccare i corpi del testo. */
  .set__head {
    margin-bottom: 1.25rem;
  }

  .set__foot {
    gap: 0.5rem;
    margin-top: 1.1rem;
  }

  .set__zoom {
    width: 1rem;
    height: 1rem;
    right: 0.15rem;
    bottom: 0.15rem;
    opacity: 0.6;
  }

  .set__zoom svg {
    width: 0.62rem;
    height: 0.62rem;
  }

}

/* Le quattro linguette, tutte in fila come su desktop -----------------------
   Prima andavano a griglia 2x2 sotto le 30rem per via di una quarta linguetta
   tagliata a meta' dallo scorrimento senza alcun segnale. La barra resta
   orizzontale (stessa riga, come su PC) e il taglio adesso lo dice una
   sfumatura sul bordo destro, cosi' non serve piu' spezzare la fila. */
@media (width < 30rem) {
  .set__switch {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent 100%);
  }

  .set__tab {
    padding-inline: 0.6rem;
  }
}


/* =============================================================================
   IL TITOLO PRENDE L'EFFETTO DI «VENT'ANNI PASSATI A SCEGLIERE»  (03/09/2026)
   =============================================================================
   Terza richiesta sullo stesso titolo, e le prime due volte avevo sbagliato
   bersaglio. Il titolo di Chi siamo NON usa il motore comune del tema: ha il
   suo, in piacersi-about.css, con quattro valori diversi — e quello che si
   vede davvero e' l'opacita', che nel motore comune non c'e' proprio.

                          Chi siamo        tema (prima)
     parte da             translateY 105%  translateY 110%
     durata               0,85 s           1 s
     ritardo per parola   55 ms            50 ms
     opacita'             da 0 a 1, 0,5 s  nessuna

   Si riportano qui i quattro valori, sul solo titolo del set. Il motore comune
   resta com'e' per tutti gli altri titoli del sito.
   ============================================================================= */
@media (prefers-reduced-motion: no-preference) {
  .set__title .pcr-word {
    /* le code di g, p, q: stessa correzione di Chi siamo, stesso valore */
    padding-bottom: 0.12em;
    margin-bottom: -0.12em;
  }

  .set__title .pcr-word__in {
    transform: translate3d(0, 105%, 0);
    opacity: 0;
    transition:
      transform 0.85s var(--pcr-ease, cubic-bezier(0.22, 1, 0.36, 1)),
      opacity 0.5s linear;
    transition-delay: calc(var(--w, 0) * 55ms);
  }

  .set__title.is-revealed .pcr-word__in {
    transform: none;
    opacity: 1;
  }
}

/* =============================================================================
   iPad: BERSAGLI DA DITO  (25/09/2026)
   =============================================================================
   Sopra le 60rem questi comandi erano pensati per il mouse («dove il puntatore
   è fine», nota su .set__more-btn). Un iPad in orizzontale è largo 1024-1194px
   e si usa col dito: «Gli altri set» erano alti 36px, i menu dei formati 34,
   i numeri sulla foto 26. Con un dito come puntatore e da 48rem in su salgono
   a 44. Ai numeri sulla foto si allarga solo l'area che risponde al tocco
   (un ::after trasparente): il segno visibile resta di 26px. Telefono e
   computer invariati. Le linguette delle scene restano di 34px dentro la
   pastiglia da 46: alzarle cambierebbe la pastiglia, e superano comunque i
   24px chiesti da WCAG 2.5.8. */
@media screen and (width > 48rem) and (pointer: coarse) {
  .set__more-btn,
  .set__select select {
    min-height: 2.75rem;
  }

  .set__pin::after {
    content: '';
    position: absolute;
    inset: -0.5625rem;
    border-radius: 50%;
  }
}
