/* ============================================================
   Guscio del portale — cornice a sinistra, canvas a destra.

   Caricato DOPO components.css, quindi quello che serve lo riscrive senza
   che components.css vada toccato: se il guscio non convince, si toglie
   questo file e la riga che lo include, e il sito torna com'era.

   Niente JavaScript, niente iframe. Ogni reparto e' una pagina vera: la
   barra non "resta ferma", si ridisegna uguale a ogni caricamento, con la
   voce corrente marcata. E' il modo in cui lo fa vibedreamup.org, misurato:
   zero <script>, zero <iframe>, link normali, 15 KB a pagina.
   ============================================================ */

:root {
  /* 120, ERANO 88 (08-09-2026). Cresce per fare posto al marchio vivo: il
     triskele che si muove col lettore audio, consegnato dal designer.

     E' UN COMPROMESSO DICHIARATO. La nota che stava qui diceva: «con un albero
     a sinistra, 144 px di testata piu' i reparti farebbero oltre 200 px di
     cornice prima del contenuto; il sito di riferimento ne usa 78 in tutto.
     Qui 88, che tiene il marchio grande senza schiacciare il canvas.» Quel
     ragionamento resta vero, e per questo 144 non si riprende.

     Ma il marchio vivo a 78 px — la misura di oggi — non si legge: e' un disegno che si apre mentre suona, e a quella scala i
     rami si impastano.

     120 sta in mezzo: il marchio passa da 78 a 96 px, cioe' un quarto piu'
     grande, e la testata resta ben sotto i 144 bocciati. Se il marchio dovesse
     ancora sembrare piccolo, le due misure si alzano insieme — sono legate. */
  --header-height: 120px;
  /* 190, era 222. Misurato sulla home: a x=110, dentro la barra, solo il 7%
     delle righe ha qualcosa sopra -- sette voci che finiscono a un terzo
     dell'altezza, e sotto il vuoto.
     L'albero NON si toglie per una barra in alto, come suggerirebbe il primo
     istinto: ha sottolivelli (Prodotti, Frequency Lab, Esercizi hanno figli) e
     apre da solo il ramo dove ti trovi. In orizzontale servirebbero tendine,
     che sul telefono sono peggio. Si restringe, e i 32 px vanno al contenuto.
     Il blocco del marchio in testata si adegua da solo, perche' la sua
     larghezza e' calcolata da qui. */
  --aside-width: 190px;
}

/* La cornice e' UNA linea sola: quella che scende lungo il bordo destro della
   barra prosegue in orizzontale a delimitare la testata. Prima erano due
   colori diversi — la testata usava --color-border (#f0ede8), la barra
   --color-border-strong (#e4dfd7) — e il punto in cui si incontrano si vedeva.
   Ora sono lo stesso tratto e formano un angolo continuo. */
.site-header {
  border-bottom-color: var(--color-border-strong);
}

/* Il marchio scende a sinistra, sopra la colonna della barra laterale.
   La testata smette di essere centrata su --container-max: in un guscio il
   marchio appartiene alla colonna della navigazione, non alla griglia del
   contenuto. Il suo bordo sinistro cade sul bordo delle pillole del menu
   (il padding della barra), cosi' i due blocchi stanno sulla stessa linea. */
.site-header .header-inner {
  max-width: none;
  padding-left: var(--space-md);
  padding-right: var(--space-lg);
}

/* LARGHEZZA MINIMA E NON FISSA. Era fissa, e serviva a far cadere il bordo
   sinistro del marchio sul bordo delle pillole del menu: quello resta, perche'
   dipende dal padding a sinistra e non dalla larghezza. Ma col marchio a 96 px
   il blocco non ci sta piu' dentro — 16 + 96 + 16 + 86 fanno 214 contro 174 —
   e una larghezza fissa lo faceva traboccare invece di adattarsi.
   Con min-width il blocco cresce quanto gli serve: a sinistra resta allineato
   com'era, a destra si prende lo spazio che gli occorre, che nella testata e'
   libero. */
.logo {
  min-width: calc(var(--aside-width) - var(--space-md));
  flex-shrink: 0;
}

.logo-wordmark {
  font-size: 1.6rem;
}

.header-actions {
  gap: var(--space-md);
}

.flag-icon {
  width: 26px;
  height: 19px;
  border-radius: 3px;
}

.lang-arrow {
  font-size: 0.7rem;
}

.lang-menu {
  padding: 0.3rem 0;
  min-width: 120px;
  margin-top: 0.3rem;
}

.lang-option {
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.9rem;
}

.user-toggle svg,
.cart-toggle svg {
  width: 26px;
  height: 26px;
}

.cart-count {
  top: -7px;
  right: -9px;
  font-size: 0.72rem;
  width: 20px;
  height: 20px;
}

.user-header-name {
  font-size: 0.9rem;
}

/* Sul desktop l'albero E' la navigazione: l'hamburger non serve piu'.
   Sotto i 900 px torna, e la tenda trasparente diventa il menu del telefono. */
@media (min-width: 901px) {
  .menu-toggle,
  .dropdown-nav {
    display: none;
  }
}

/* --- La cornice --- */

.shell {
  display: grid;
  grid-template-columns: var(--aside-width) 1fr;
  align-items: start;
  margin-top: var(--header-height);
}

/* main aveva il margine per la testata fissa: ora ce l'ha il guscio */
.shell main {
  margin-top: 0;
}

.shell-aside {
  position: sticky;
  top: var(--header-height);
  height: calc(100vh - var(--header-height));
  overflow-y: auto;
  padding: var(--space-lg) var(--space-md);
  border-right: 1px solid var(--color-border-strong);
  background: var(--color-surface);
}

.shell-canvas {
  min-width: 0; /* senza, una griglia larga dentro il canvas sfonda la colonna */
}

/* --- L'albero --- */

.tree {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tree-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--color-text);
  line-height: 1.3;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.tree-item:hover {
  background: var(--color-surface-alt);
  color: var(--color-link);
}

.tree-item.active {
  background: var(--color-primary);
  color: var(--color-surface);
  font-weight: 600;
}

.tree-item.active:hover {
  background: var(--color-primary);
  color: var(--color-surface);
}

/* --- Genitori apribili ---
   <details>/<summary>: li apre il browser, senza JavaScript e da tastiera.
   Il gruppo che contiene la pagina corrente nasce aperto (attributo `open`
   messo al build), cosi' non nascondi mai dove sei. */

.tree-summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}

/* le frecce native dei due motori, tolte: la nostra e' il chevron */
.tree-summary::-webkit-details-marker {
  display: none;
}
.tree-summary::marker {
  content: '';
}

/* Il genitore della pagina corrente si segna, ma piu' piano della voce
   attiva: altrimenti due righe scure gridano la stessa cosa. */
.tree-summary.is-current {
  color: var(--color-link);
  font-weight: 600;
}

.tree-chevron {
  width: 15px;
  height: 15px;
  margin-left: auto;
  opacity: 0.5;
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

.tree-fold[open] > .tree-summary .tree-chevron {
  transform: rotate(90deg);
}

/* I figli rientrano, e una linea sottile li lega al genitore. Fa il lavoro
   che facevano le intestazioni, senza sembrare una voce di menu. */
.tree-children {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 2px 0 var(--space-sm) 22px;
  padding-left: 10px;
  border-left: 1px solid var(--color-border-strong);
}

.tree-children .tree-item {
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

.tree-children .tree-item.active {
  color: var(--color-surface);
}

.tree-lock {
  width: 14px;
  height: 14px;
  margin-left: auto;
  opacity: 0.55;
  flex-shrink: 0;
}

/* --- Il negozio: una barra sola ---
   Le categorie sono salite nell'albero, sotto Prodotti. La colonna che il
   negozio si porta dietro diventerebbe una barra dentro una barra, quindi qui
   sparisce e la griglia prende tutto il canvas.
   SOLO da 901 px in su: sotto, l'albero e' chiuso nell'hamburger e le
   categorie devono restare raggiungibili dalla pagina. */
@media (min-width: 901px) {
  .store-sidebar {
    display: none;
  }

  .store-layout {
    display: block;
  }
}

/* --- Il canvas: il contenuto respira, ma non si allarga all'infinito --- */

.shell-canvas .container {
  max-width: 980px;
  padding: 0 var(--space-lg);
}

.shell-canvas .site-footer .container {
  max-width: var(--container-max);
}

/* --- Telefono e tablet: la cornice si richiude --- */

@media (max-width: 900px) {
  .shell {
    grid-template-columns: 1fr;
  }

  .shell-aside {
    display: none;
  }

  .shell-canvas .container {
    max-width: none;
    padding: 0 var(--space-md);
  }
}

/* ============================================================
   L'atrio
   ============================================================ */

/* L'hero smette di occupare tutto lo schermo. In un portale la prima cosa
   da vedere sono le stanze: se l'hero e' alto 100vh, le porte stanno sotto
   la piega e il portale sembra un sito con una vetrina. */
.hero {
  height: auto;
  /* La copertina e' un oggetto in posizione assoluta dentro l'hero, che ha
     overflow: hidden: se l'hero non e' piu' alto di lei, la taglia. E sopra
     la copertina ci sta il badge "In evidenza", ancorato a
     50% - cover-h/2 - 2.75rem: se l'hero e' troppo basso quel conto va in
     negativo e il badge finisce fuori dal bordo.
     Quindi l'altezza si lega alla copertina invece di essere una frazione
     dello schermo: cosi' il respiro sopra il badge resta lo stesso a
     qualsiasi altezza di finestra, invece di variare con essa. */
  min-height: calc(var(--cover-h) + 8rem);
  --cover-h: min(62vh, 560px);
  padding: var(--space-xl) var(--space-lg);
}

.hero-lead {
  font-family: var(--font-body);
  font-size: clamp(1.02rem, 1.5vw, 1.18rem);
  line-height: 1.6;
  color: var(--color-text-muted);
  max-width: 34ch;
  margin-top: var(--space-md);
}

/* L'INVERSIONE. Dove la fascia e' gia' beige, la card torna chiara: e'
   la regola letta sul mockup, non una preferenza. Non serve toccare le
   card una per una, basta ribaltare qui la variabile e chi sta dentro la
   eredita'. */
.section-doors,
.home2-advantages,
.home2-image-text {
  --color-card: var(--color-surface);
}

.section-doors {
  background: var(--color-surface-alt);
}

/* B11 - il filetto fra due sezioni CHE CONDIVIDONO IL FONDO. Dove il fondo
   cambia e' il cambio stesso a separarle, e la riga sarebbe di troppo:
   per questo le due eccezioni qui sotto.
   Sta sul .container e non sulla sezione perche' nel mockup il filetto e'
   inserito nella colonna del contenuto, non a tutta pagina. 1px in
   un valore suo.

   CORREZIONE. Quando ho scritto questa regola avevo concluso che
   --color-border (#f0ede8) fosse il token giusto perche' "da' dieci punti di
   stacco contro i dodici del mockup". Il conto era sbagliato: avevo confrontato
   il nostro colore col fondo del MOCKUP (247) invece che col NOSTRO. Sul nostro
   fondo lo stacco era di 3,9 punti, cioe' un filetto quasi invisibile.
   Con B13 il fondo si e' schiarito e lo stacco e' salito a 7,4, ancora poco.
   #ede9e0 ne da' 11,6, che e' il dodici misurato sul mockup.

   Non uso --color-border ne' --color-border-strong: il primo e' troppo debole
   qui, il secondo (21 punti) e' quasi il doppio del dovuto, e comunque
   --color-border sta in ventotto punti del sito, quasi tutti su superfici
   bianche dove separa benissimo. Cambiarlo li' per riparare qui sarebbe stato
   spostare il problema. */
.section + .section > .container {
  border-top: 1px solid #ede9e0;
}

.section + .section-doors > .container,
.section-doors + .section > .container {
  border-top: 0;
}

.doors {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-md);
  max-width: 860px;
  margin: var(--space-lg) auto 0;
}

/* Stessa costruzione delle altre card del sito: stessi token, stessa famiglia. */
.door {
  display: block;
  background: var(--color-card);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  transition: transform var(--transition-fast), border-color var(--transition-fast),
    box-shadow var(--transition-base);
}

.door:hover {
  transform: translateY(-6px);
  border-color: var(--color-lav);
  box-shadow: var(--card-shadow-hover);
}

.door-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--color-primary);
  margin-bottom: var(--space-xs);
}

.door-text {
  font-size: 0.98rem;
  line-height: 1.55;
  color: var(--color-text-muted);
  margin: 0;
}

/* ============================================================
   Reparti: app ed esercizi
   ============================================================ */

.reparto-lead {
  font-size: clamp(1.02rem, 1.6vw, 1.15rem);
  line-height: 1.65;
  color: var(--color-text-muted);
  max-width: 62ch;
  margin-bottom: var(--space-lg);
}

.reparto-empty {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Il riquadro della app — l'unico di tutto il portale. */
.app-frame {
  border: 1px dashed var(--color-lav);
  border-radius: var(--radius-lg);
  background: var(--color-surface-alt);
  min-height: 420px;
  display: grid;
  place-items: center;
  padding: var(--space-lg);
}

.app-frame-note {
  text-align: center;
  max-width: 42ch;
  color: var(--color-text-muted);
}

.app-frame-badge {
  display: inline-block;
  background: var(--color-accent);
  color: var(--color-primary);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-md);
}

/* Il cancello: e' una porta, non una serratura. Il diritto lo dice il server. */
.gate {
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
  max-width: 520px;
}

.gate-icon {
  width: 40px;
  height: 40px;
  color: var(--color-lav);
  margin: 0 auto var(--space-md);
  display: block;
}

.gate-text {
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--color-primary);
  margin-bottom: var(--space-lg);
}

.gate-note {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-top: var(--space-md);
}

@media (max-width: 900px) {
  .doors {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   Prodotti che si comprano altrove
   ============================================================ */

/* La nota sotto il bottone che porta fuori: dice dove stai andando prima che
   tu ci vada. Un link che apre una scheda nuova senza preavviso e' scortese. */
.product-external-note {
  margin-top: var(--space-sm);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--color-text-muted);
  max-width: 46ch;
}

/* Marcatura sulla card del catalogo: chi sfoglia deve sapere prima di aprire
   che quel titolo non finisce nel carrello. */
.product-card-external {
  display: inline-block;
  margin-top: var(--space-xs);
  padding: 3px 10px;
  border: 1px solid var(--color-lav);
  border-radius: var(--radius-pill);
  color: var(--color-link);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ============================================================
   Il prodotto in evidenza nell'eroe
   ============================================================ */

/* Quando c'e' un prodotto in evidenza, la copertina non e' piu' uno sfondo
   disegnato da ::after ma un LINK vero con dentro una immagine. Due motivi:
   uno sfondo CSS non si clicca, e non ha testo alternativo — una copertina
   che porta un significato era invisibile a chi non vede. */
.hero--has-feature::after {
  display: none;
}

.hero-feature {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  right: var(--cover-right);
  height: var(--cover-h);
  display: block;
  z-index: 2;
}

.hero-feature-img {
  height: 100%;
  width: auto;
  display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--card-shadow-hover);
  transition: transform var(--transition-base);
}

.hero-feature:hover .hero-feature-img {
  transform: translateY(-6px);
}

/* Il badge sale sopra la copertina e si muove con lei: prima era ancorato
   all'eroe e la sua posizione andava ricalcolata a mano ogni volta che la
   copertina cambiava misura. Dentro il link, invece, la segue. */
.hero--has-feature .hero-featured {
  /* IL `display` E' LA RIPARAZIONE, e senza di lui lo spagnolo non aveva il
     badge pur avendolo nell'HTML.
     `.hero-featured` nasce `display: none` in components.css, e l'UNICO posto
     che lo riaccendeva era `.hero--it .hero-featured, .hero--en .hero-featured`:
     una lista di lingue scritta a mano, di quando lo spagnolo non aveva
     copertina. Questa regola lo posizionava ma non lo mostrava, e quella lo
     mostrava ma non conosceva lo spagnolo: il badge cadeva nella fessura fra i
     due meccanismi.
     Ora la condizione e' quella giusta — «c'e' una copertina da mostrare» —
     e non nomina nessuna lingua, quindi non potra' piu' dimenticarne una.
     Sul telefono resta invisibile lo stesso: il badge sta DENTRO
     `.hero-feature`, che sotto i 769 px e' `display: none`. */
  display: block;
  position: absolute;
  top: -2.75rem;
  right: 0;
  left: auto;
  margin: 0;
}

/* Senza un prodotto in evidenza il badge non ha destinazione: non si mostra. */
.hero:not(.hero--has-feature) .hero-featured {
  display: none;
}

/* SU TELEFONO: COPERTINA SOPRA, TESTO SOTTO (05-09-2026).

   QUI C'ERANO TRE REGOLE, ed erano una pezza sopra l'altra. Sotto i 769 px la
   copertina veniva dipinta come sfondo dell'eroe; allora il link con la sua
   immagine andava nascosto, o la copertina compariva due volte accavallata;
   allora il velo sopra lo sfondo andava rinforzato, perche' il titolo cadeva
   sulla copertina e non si leggeva. Il commento di allora dichiarava anche il
   prezzo: «su telefono la copertina non e' cliccabile».

   Tutte e tre servivano a tenere in piedi una scelta che su una colonna sola
   non regge: testo e immagine nello stesso posto. Impilati non si contendono
   niente, quindi il velo non serve piu', la copertina torna a pieno contrasto
   e torna anche cliccabile — il prezzo dichiarato si smette di pagarlo.

   L'ordine e' copertina-poi-testo e non il contrario: il prodotto e' il libro,
   e chi arriva da un telefono deve vedere di che si tratta prima di leggere
   che cosa promette. Nel markup la copertina viene DOPO il testo (li' sta a
   destra), quindi qui si sposta con `order`, senza toccare l'HTML.

   L'altezza della copertina e' limitata perche' il primo bottone resti nella
   prima schermata: e' il motivo del max-height qui sotto, non un valore
   estetico. Misurato a 390x844.

   `height: auto` sostituisce il `100vh` dell'eroe: impilando due blocchi la
   somma puo' superare lo schermo, e con `overflow: hidden` ancora acceso il
   fondo verrebbe tagliato invece che scorrere. */
@media (max-width: 768px) {
  .hero {
    height: auto;
    flex-direction: column;
    justify-content: flex-start;
    gap: var(--space-md);
    padding-top: calc(var(--space-xl) + 2.75rem);
  }

  /* IL SELETTORE E' `.hero .hero-feature` E NON `.hero-feature`, apposta.
     Piu' in basso in questo stesso file c'e' una regola `.hero-feature` che
     rientra la copertina di 140 px dal bordo destro: stessa specificita' e
     scritta dopo, quindi vincerebbe anche dentro una media query — le media
     query non aggiungono peso. Con la copertina in flusso quel `right`
     diventa uno spostamento reale, e la spingeva fuori dallo schermo a
     sinistra (misurato: x = -54 su una finestra da 375). Il discendente in
     piu' basta a vincere senza spostare righe e senza !important. */
  .hero .hero-feature {
    /* Da assoluta a in-flusso: nell'impaginazione a colonna deve occupare
       spazio, non sovrapporsi. Resta `relative` perche' il badge «in
       evidenza» e' posizionato rispetto a lei.

       L'ALTEZZA RESTA UN VALORE DEFINITO, e non `auto`. Provato `auto` prima:
       la copertina e' uscita schiacciata in una barra scura. Il motivo e' la
       catena delle percentuali — .hero-book e .hero-feature-img hanno
       `height: 100%`, e una percentuale si risolve contro il genitore: se il
       genitore passa ad `auto` non c'e' piu' niente contro cui risolverla e
       il libro collassa. E' la stessa trappola annotata in base.css per il
       <picture>, in un altro punto della stessa catena.

       34vh e' scelto perche' il primo bottone resti nella prima schermata:
       misurato a 390x844. */
    position: relative;
    order: -1;
    top: auto;
    right: auto;
    transform: none;
    height: 34vh;
    margin: 0 auto;
  }
}

/* IL VELO E' STATO TOLTO, NON RINFORZATO (05-09-2026).

   Qui il velo sopra la copertina di sfondo veniva portato da .45/.20 a
   .90/.72/.85, perche' a quello piu' leggero il titolo su tre righe non si
   leggeva. Funzionava: il testo tornava leggibile. Ma per leggere il testo
   bisognava cancellare l'immagine, e alla fine sotto restava una copertina
   sbiadita che non si riconosceva piu' — «retinata di brutto», ed e' il
   difetto per cui questa riga e' stata scritta.

   Non serve piu' niente qui: impilando copertina e testo (la regola sopra)
   non si sovrappongono, quindi non c'e' nulla da schiarire e il fondo torna
   pieno in components.css. Una pezza che si toglie invece di stringerla. */

/* ============================================================
   Il telefono: guscio richiuso, stessa mappa
   ============================================================ */

/* La testata torna a 72 px sotto i 768, com'e' in produzione. Gli 88 px sono
   una misura da desktop: li' servono a reggere il marchio accanto a una barra
   laterale larga 272. Sul telefono la barra laterale non c'e', quindi non c'e'
   niente da reggere. (shell.css e' caricato dopo components.css, quindi il suo
   :root vinceva anche qui: era un effetto collaterale, non una scelta.) */
@media (max-width: 768px) {
  :root {
    --header-height: 72px;
  }
}

/* L'albero dentro il menu a tendina. Stessa struttura della barra laterale —
   stesse voci, stessi gruppi apribili — ma allineata a sinistra e larga tutta
   la tendina, perche' qui non e' una colonna: e' la pagina. */
.dropdown-nav-inner {
  align-items: stretch;
  padding: var(--space-md);
}

.dropdown-nav .tree {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
  text-align: left;
}

/* Le voci della tendina avevano un loro stile — maiuscoletto spaziato — che
   qui litigava con quello dell'albero. Vince l'albero: e' la stessa mappa,
   deve avere la stessa faccia. */
.dropdown-nav .tree a {
  font-size: 0.95rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  padding: 10px 12px;
  text-shadow: none;
}

.dropdown-nav .tree .tree-summary {
  font-size: 0.95rem;
  text-transform: none;
  letter-spacing: 0;
}

/* La tenda torna OPACA — ma solo sul telefono, ed e' bene capire perche' non
   e' un dietrofront.
   Stamattina la tenda e' stata resa trasparente guardando il DESKTOP, dove il
   menu erano cinque parole corte in mezzo allo schermo: li' il velo smorzava
   l'eroe per niente. Da quando l'albero e' la navigazione del desktop, quel
   menu sul desktop non esiste piu': l'hamburger compare solo sotto i 900 px.
   E li' il contenuto non e' piu' cinque parole ma l'albero intero, allineato a
   sinistra, sopra una copertina. Trasparente diventa illeggibile.
   Quindi: trasparente dove era stato chiesto (desktop, dove non c'e' piu'),
   opaca dove serve leggere. */
@media (max-width: 900px) {
  .dropdown-nav {
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border-strong);
  }

  /* Col fondo pieno il contorno attorno alle lettere non serve piu': era li'
     solo per sopravvivere sopra le immagini. */
  .dropdown-nav .tree a,
  .dropdown-nav .tree .tree-summary {
    text-shadow: none;
  }
}

/* La copertina in evidenza rientra di 50 px dal bordo destro.
   Si somma a --cover-right invece di sostituirla: quella variabile e' un
   max() che tiene conto della larghezza del container, quindi conserva il
   comportamento su schermi molto larghi e molto stretti. Il badge sta dentro
   il link e si sposta con lei, senza ritocchi. */
.hero-feature {
  /* Erano 50. Misurato il vuoto VERO fra l'inchiostro del titolo e la
     copertina — 198 px — non bastavano a farne un blocco solo: 50 spostavano
     la copertina ma il buco restava. A 140 la distanza scende a ~108 px, che
     e' una gronda normale fra due elementi affiancati invece di un'assenza.
     Questo numero sostituisce i 50 chiesti prima: e' la stessa richiesta,
     misurata. */
  right: calc(var(--cover-right) + 140px);
}

/* ============================================================
   L'evidenziazione della voce corrente si alleggerisce
   ============================================================ */

/* Era un blocco pieno di inchiostro scuro (#2d3047 con testo chiaro, 12,19:1):
   pesante, e in una colonna di voci leggere gridava.
   Ora e' una velatura della lavanda del marchio, appena piu' marcata
   dell'hover, piu' una barretta a sinistra che dice "sei qui" senza aggiungere
   massa.

   Il testo NON diventa lavanda: sulla velatura darebbe 4,59:1, che passa la
   AA ma con margine risicato. Con l'inchiostro scuro sono 10,12:1 — calcolato
   componendo prima la trasparenza sul fondo, perche' misurare il colore
   dichiarato invece di quello che si vede darebbe un numero inesistente. */
.tree-item.active,
.tree-item.active:hover {
  background: rgba(142, 125, 190, 0.18);
  color: var(--color-primary);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--color-lav);
}

/* La voce figlia attiva seguiva il vecchio schema chiaro-su-scuro: senza
   questo, sul fondo chiaro diventerebbe invisibile. */
.tree-children .tree-item.active {
  color: var(--color-primary);
}

/* ============================================================
   L'eroe: tre correzioni, non tre ritocchi di gusto
   ============================================================ */

/* 1. IL TITOLO ERA DIMENSIONATO SU UNA PAGINA CHE NON ESISTE PIU'.
   components.css lo fa clamp(2.5rem, 6vw, 4.5rem): si misura sulla larghezza
   della FINESTRA. Da quando c'e' la barra laterale il titolo vive in una
   colonna larga 1218 px ma continua a calcolarsi su 1440. Non era "troppo
   grande" per gusto: era tarato su un'altra geometria.
   Qui si aggancia alla colonna, sottraendo la barra prima di prendere la
   percentuale. Sotto i 900 px la barra non c'e' e si torna alla misura piena. */
.hero-title {
  font-size: clamp(2.2rem, calc((100vw - var(--aside-width)) * 0.052), 3.6rem);
}

@media (max-width: 900px) {
  .hero-title {
    font-size: clamp(2.2rem, 6vw, 3.6rem);
  }
}

/* 2. LE LETTERE VIOLA SPARSE NON ERANO UNA SCELTA DI COLORE.
   Il viola e' sempre stato solo su "percezione" (.hero-accent). Le lettere
   lavanda che comparivano dentro "neuroscienze" e "coscienza" venivano da
   heroLetterPulse: ogni lettera pulsa su un ciclo di 28 s con partenza
   casuale e al 92% diventa lavanda con un alone. In ogni istante un 4% delle
   lettere era viola, a caso, senza significare niente.
   Il movimento resta, ma solo sulla parola accentata: li' e' un accento che
   respira, non rumore. */
.hero-title .hero-letter {
  animation: none;
}

.hero-title .hero-accent .hero-letter {
  animation: heroLetterPulse 28s ease-in-out infinite;
}

/* 3. IL BLOCCO ERA ISOLATO DA UN VUOTO CHE NESSUNO AVEVA DECISO.
   La colonna di testo e' larga 620 px e stava CENTRATA in un canvas da ~1180,
   con la copertina agganciata a destra: in mezzo restava un vuoto morto.
   Quel centraggio serviva ad allineare l'eroe alla testata, ma da quando il
   marchio e' sceso nella colonna della barra quella ragione e' decaduta.
   Ora il testo si appoggia a sinistra e la colonna respira di piu': testo e
   libro tornano un blocco solo. */
/* Il box del titolo aderisce al testo invece di allargarsi fino al limite:
   senza, il vuoto verso la copertina si misura sul contenitore e non su cio'
   che si vede, e si finisce per correggere un numero che non esiste. */
.hero-content .hero-title {
  width: fit-content;
  /* 640 NON CI STA quando accanto c'e' la copertina, e l'inglese lo dimostrava:
     misurato a 1440, il titolo arrivava a 976 e il libro cominciava a 930 —
     quarantasei pixel di parola nascosti sotto la copertina, e non per una
     finestra stretta: il canvas e' fisso a 980, quindi il taglio era IDENTICO a
     1280, 1440, 1600 e 1920. Sempre rotto, mai a meta'.
     Non sbordava il testo: era il libro a passargli sopra. Testo 640 piu' libro
     ~314 fanno 954 in una colonna che, tolti i margini, ne offre ~890.
     540 e' il piu' largo che lascia respiro al libro: misurati, italiano 477 e
     spagnolo 524 restano intatti, l'inglese va a capo invece di sparire. */
  max-width: 540px;
}

/* ============================================================
   La copertina del blog smette di sprecare un terzo della card
   ============================================================ */

/* components.css dava al riquadro un'altezza fissa di 200 px con
   object-fit: contain. Il riquadro veniva cosi' 2,27:1 mentre le copertine
   sono 1,53:1 — molto meno schiacciate — quindi l'immagine entrava per
   altezza e lasciava fasce grigie ai lati.
   Misurato sulla card larga 434: riquadro 418x184, immagine disegnata a
   281x184, 137 px di vuoto ai lati. Un terzo della larghezza.

   E peggiorava col guscio: il canvas piu' stretto fa due colonne invece di
   tre, quindi card PIU' LARGHE mentre l'altezza restava inchiodata a 200 —
   piu' la card cresce, piu' cresce il vuoto.

   Ora il riquadro prende la forma dell'immagine (3:2) e l'altezza segue la
   larghezza. Stessa card: immagine a 418x273, fasce quasi azzerate, quasi il
   doppio di superficie.

   RESTA object-fit: contain, non cover: le copertine hanno il testo scritto
   dentro, e cover ritaglia. Su queste due il taglio sarebbe invisibile, ma su
   una copertina 16:9 futura toglierebbe il 16% in altezza e si porterebbe via
   il titolo. Con contain una copertina di forma diversa perde un po' di
   spazio, non una parola. */
.blog-card img {
  height: auto;
  aspect-ratio: 3 / 2;
}

/* ============================================================
   Il libro in evidenza prende volume — solo se e' un libro
   ============================================================ */

/* Tre pezzi, nessun motore 3D: la copertina piatta che gia' c'e', un blocco
   pagine sul fianco destro, un'ombra sotto. Il mockup di riferimento gira il
   libro cosi' che si veda il taglio delle pagine e NON la costa: e' la
   fortuna che rende inutile un render vero, perche' sul dorso non deve
   comparire nessuna scritta.

   Perche' non un'immagine generata: la copertina dell'eroe arriva dal
   PANNELLO — e' quella del prodotto in evidenza. Un PNG in 3D sarebbe
   congelato: cambi prodotto o copertina e va rifatto a mano. Cosi' il volume
   si costruisce attorno a qualunque immagine ci sia, e segue anche la lingua.

   La classe --book la mette il template solo per la categoria Editoria. */

.hero-feature--book .hero-book {
  position: relative;
  display: block;
  height: 100%;
  transform-style: preserve-3d;
  /* rotazione negativa = il bordo destro viene verso di noi, quindi la faccia
     laterale che si vede e' quella delle pagine. Con la positiva si vedrebbe
     la costa, che non abbiamo. */
  /* Tre quarti. Il commento precedente diceva che a 30 gradi "la copertina si
     accorcia troppo" e il nome dell'autrice si comprime: era una conclusione
     SBAGLIATA, tratta da un confronto viziato. Quella compressione non veniva
     dallo scorcio, veniva dal blocco pagine montato davanti (il segno della
     rotazione, corretto poco sopra) che ne copriva il bordo destro.
     Rimisurato a prospettiva COSTANTE, che l'altra volta avevo fatto variare
     insieme all'angolo confondendo le due cause:
       22 gradi -> copertina 191px  dorso 25px  ingombro 216px
       27 gradi -> copertina 184px  dorso 32px  ingombro 216px
       32 gradi -> copertina 175px  dorso 39px  ingombro 214px
     L'INGOMBRO NON CAMBIA: ruotare non allarga il libro, sposta larghezza
     dalla copertina al dorso. Quindi l'angolo non ha ricadute sul layout e la
     scelta e' di gusto: a 27 si paga il 4% di copertina e si compra il 28% di
     dorso. */
  transform: perspective(1300px) rotateY(-27deg);
  transition: transform var(--transition-base);
}

.hero-feature--book:hover .hero-book {
  transform: perspective(1300px) rotateY(-18deg);
}

.hero-feature--book .hero-feature-img {
  position: relative;
  /* niente z-index: dentro un preserve-3d l'ordine di disegno lo decide la
     posizione nello spazio, e forzarlo a mano nasconde gli errori di
     geometria invece di risolverli — e' cosi' che il blocco davanti passava
     inosservato. */
  border-radius: 2px 6px 6px 2px;
  box-shadow:
    0 26px 44px -20px rgba(45, 48, 71, 0.55),
    -1px 0 0 rgba(45, 48, 71, 0.18);
}

/* Il taglio delle pagine: incernierato sul bordo destro della copertina e
   ruotato di 90 gradi, quindi diventa la faccia laterale del volume. Le
   righe sottili sono i fogli. */
.hero-feature--book .hero-book-pages {
  position: absolute;
  top: 1.5%;
  bottom: 1.5%;
  right: 0;
  /* Raddoppiato da 42: a 84 diventa un volume rilegato invece di un
     opuscolo, e la copertina non ci perde niente perche' lo spessore
     cresce sul FIANCO, non sulla faccia. Provato anche 27 gradi con
     questo spessore: li' il fianco comincia a dominare e il nome
     dell'autrice si taglia. L'angolo resta 22. */
  width: 84px;
  transform-origin: right center;
  /* SEGNO NEGATIVO, e non e' un dettaglio: con +90 il blocco si sviluppava
     in AVANTI, davanti al piano della copertina. Non era il corpo fra le due
     facce, era una parete appiccicata sul filo — e per giunta copriva il
     bordo destro della copertina, mangiandosi il nome dell'autrice.
     Con -90 lo spessore va all'indietro, dove sta il corpo di un libro, e la
     copertina torna intera. */
  transform: rotateY(-90deg);
  border-radius: 0 3px 3px 0;
  background:
    linear-gradient(to right, rgba(45, 48, 71, 0.22), rgba(45, 48, 71, 0) 22%),
    repeating-linear-gradient(to right,
      #f4f0e6 0, #f4f0e6 1.5px,
      #d9d2c2 1.5px, #d9d2c2 2.5px);
}

/* La controcopertina: chiude il volume in fondo, alla profondita' dello
   spessore. Senza, il blocco pagine finiva nel vuoto e il libro restava una
   copertina con una parete di lato invece che un oggetto solido. */
.hero-feature--book .hero-book-back {
  position: absolute;
  inset: 0;
  background: #20223a;
  border-radius: 2px 6px 6px 2px;
  transform: translateZ(-84px);
}

/* L'ombra a terra: una macchia morbida sotto il volume, non un rettangolo. */
.hero-feature--book .hero-book::after {
  content: "";
  position: absolute;
  left: 6%;
  right: 2%;
  bottom: -22px;
  height: 26px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgba(45, 48, 71, 0.26) 0%, rgba(45, 48, 71, 0) 72%);
  transform: translateZ(-20px);
  pointer-events: none;
}

/* Sul telefono la copertina e' lo sfondo dell'eroe e il link e' nascosto:
   niente da fare, il volume non esiste li'. */

/* ============================================================
   Le quattro cose che fanno il "vintage moderno" del mockup
   ============================================================ */

/* 1 e 2. IL PUNTO FERMO, E I TITOLI DI PAGINA AL CENTRO.
   Nel mockup i titoli sono "IL LIBRO." "BLOG." "CHI SONO." — col punto, e
   centrati. E' il tic tipografico che regge da solo quasi tutta la sensazione,
   e costa due regole.
   Il punto si mette con ::after e non nel testo: cosi' non entra nelle
   traduzioni, non finisce nei titoli della pagina o nei risultati di ricerca,
   e si toglie cancellando una riga. Ed e' aria-hidden per costruzione — i
   lettori di schermo non annunciano il contenuto generato come testo. */
/* B14 - i titoli display in MAIUSCOLO. Sul mockup le lettere di "IL LIBRO."
   sono tutte alte 28px e quelle di "TESTIMONIALS." tutte 24: e' maiuscolo
   pieno, non maiuscoletto.
   NIENTE letter-spacing, e va contro l'istinto: il maiuscolo di solito si
   allarga. Ma gli spazi fra lettera e lettera misurati sul mockup sono di 1-3px
   su un'altezza di 24-28, cioe' la spaziatura naturale del carattere. Allargarla
   sarebbe stata una mia aggiunta, non una lettura.
   Stessa lista di selettori del punto fermo qui sotto: sono gli stessi titoli.
   L'hero non c'e' dentro, e si vede dal fatto che non ha il punto. */
.section-title,
.blog-page > h1,
.store-page > h1,
.page-content > h1 {
  text-transform: uppercase;
}

.section-title::after,
.blog-page > h1::after,
.store-page > h1::after,
.page-content > h1::after {
  content: ".";
}

.blog-page > h1,
.store-page > h1,
.page-content > h1 {
  text-align: center;
}

/* 3. Il fondo piu' caldo sta in variables.css, dove vivono i token. */

/* 4. IL BOTTONE SECONDARIO DIVENTA SABBIA.
   Era un contorno lavanda su niente. Nel mockup i secondari sono pillole
   piene color sabbia: pesano meno del bottone principale ma si vedono, che e'
   il mestiere di un secondario.
   Il testo resta l'inchiostro scuro: 9,10:1 sul sabbia, il doppio abbondante
   della soglia. */
.btn-secondary {
  background: #e7d7b5;
  border: 2px solid #e7d7b5;
  color: var(--color-primary);
}

.btn-secondary:hover {
  background: #dcc79b;
  border-color: #dcc79b;
  color: var(--color-primary);
}

/* I tre richiami sotto l'hero. Vanno a capo su schermo stretto invece di
   stringersi: tre pillole schiacciate sono peggio di tre pillole su due
   righe. */
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: var(--space-lg);
}

/* CHI SIAMO — ritratto e testo affiancati, come il "chi sono" del mockup. */
.about-grid {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: var(--space-xl);
  align-items: start;
}

.about-portrait {
  margin: 0;
}

.about-portrait img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
  background: var(--color-card);
}

.about-portrait figcaption {
  margin-top: var(--space-sm);
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--color-text);
}

.about-text p {
  margin-bottom: 1rem;
  line-height: 1.8;
}

/* L'ultima riga della pagina — «non e' un dispositivo medico» — non e' una
   frase della biografia: e' una precisazione, e va letta come tale. Staccata
   da un filo e piu' piccola, cosi' non sembra la chiusa del racconto
   dell'autrice ne' si perde in fondo come se non contasse.
   Il contrasto resta quello del testo attenuato, che e' sopra soglia. */
.about-text p.about-nota {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-border);
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--color-text-muted);
}

/* Sotto i 760 del canvas la colonna da 320 e il testo non ci stanno piu':
   il ritratto va sopra e si stringe, invece di schiacciare il testo in una
   striscia. */
@media (max-width: 900px) {
  .about-grid {
    grid-template-columns: 1fr;
  }
  .about-portrait {
    max-width: 260px;
  }
}

/* L'INDICE DEL LIBRO. Nel mockup e' un pannello pieno su fondo chiaro: qui
   usa --color-card, quindi si inverte da solo se un giorno finisce dentro
   una fascia beige. */
.book-index {
  margin: var(--space-xl) 0;
  padding: var(--space-lg);
  background: var(--color-card);
  border-radius: var(--radius-lg);
}

.book-index-lead {
  color: var(--color-text-muted);
  margin-bottom: var(--space-md);
}

.book-index-list {
  /* Due colonne, come nel mockup. column-count e non grid perche' le voci
     hanno lunghezze molto diverse: cosi' il testo si distribuisce da solo
     invece di lasciare buchi. */
  column-count: 2;
  column-gap: var(--space-xl);
  list-style: none;
  margin: 0;
  padding: 0;
}

.book-index-list li {
  /* break-inside: una voce spezzata a meta' fra due colonne e' illeggibile. */
  break-inside: avoid;
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.35rem 0;
}

.book-index-n {
  flex: 0 0 1.4rem;
  font-family: var(--font-display);
  color: var(--color-link);
  text-align: right;
}

.book-index-t {
  color: var(--color-text);
  line-height: 1.45;
}

@media (max-width: 700px) {
  .book-index-list {
    column-count: 1;
  }
}


/* IL VOLUME: testo e pagine aperte affiancati. */
.book-volume {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: var(--space-xl);
  align-items: center;
  margin: var(--space-xl) 0;
}

.book-volume-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-link);
  margin-bottom: var(--space-sm);
}

.book-volume-text h2 {
  margin-bottom: var(--space-md);
}

.book-volume-lead {
  color: var(--color-text-muted);
  line-height: 1.7;
}

.book-volume-img {
  margin: 0;
}

.book-volume-img img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-md);
}

@media (max-width: 800px) {
  .book-volume {
    grid-template-columns: 1fr;
  }
}

/* LA FASCIA DEL LIBRO. Fondo beige, quindi rientra nella regola
   dell'inversione: le card che dovessero finirci dentro tornano chiare.
   L'immagine sta a SINISTRA e il testo a destra, al contrario della scheda
   prodotto: due blocchi identici uno sotto l'altro sarebbero una ripetizione,
   specchiati sono un ritmo. */
.section-book {
  background: var(--color-surface-alt);
  --color-card: var(--color-surface);
}

.book-band {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: var(--space-xl);
  align-items: center;
}

.book-band-img {
  margin: 0;
}

.book-band-img img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-md);
}

.book-band-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-link);
  margin-bottom: var(--space-sm);
}

.book-band-text h2 {
  margin-bottom: var(--space-md);
}

.book-band-lead {
  color: var(--color-text-muted);
  line-height: 1.7;
  margin-bottom: var(--space-lg);
}

@media (max-width: 800px) {
  .book-band {
    grid-template-columns: 1fr;
  }
}

/* I SEGNAPOSTO. Si devono vedere per quello che sono: un segnaposto che
   sembra contenuto definitivo resta online per mesi. */
.footer-social .is-segnaposto {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Il cerchio e' vuoto invece che pieno: si legge "qui ci andra' qualcosa"
     invece di "c'e' qualcosa che non funziona". */
  border: 1px dashed var(--color-border-on-dark);
  color: var(--color-lav-on-dark);
  opacity: 0.65;
}

.footer-social .is-segnaposto svg {
  width: 13px;
  height: 13px;
}

.footer-social-nota {
  margin-top: var(--space-sm);
  font-size: 0.75rem;
  font-style: italic;
  color: var(--color-lav-on-dark);
}

.dato-segnaposto {
  font-style: italic;
  color: var(--color-text-muted);
}

/* LA FASCIA DELL'APPROCCIO. Testo a sinistra, immagine a destra. Fondo
   chiaro: sta fra l'eroe (chiaro) e le porte (beige), quindi non introduce
   una terza fascia colorata di fila. */
.approccio {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-xl);
  align-items: center;
}

.approccio-text h2 {
  margin-bottom: var(--space-md);
}

.approccio-text p {
  color: var(--color-text-muted);
  line-height: 1.8;
  margin-bottom: 1rem;
}

.approccio-img img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
}

/* SENZA IMMAGINE: una colonna sola. Qui stava .is-segnaposto-box, il
   riquadro tratteggiato con scritto "Immagine da inserire" — tolto il
   31-08-2026 perche' era un appunto di lavorazione lasciato in produzione.

   Il testo non si allarga fino al bordo del contenitore: a piena larghezza
   la riga arriva oltre i 120 caratteri e si perde il capo quando si torna a
   capo. 62ch e' la stessa misura che tiene la colonna di sinistra quando
   accanto c'e' la foto, quindi la fascia si legge uguale nei due casi. */
.approccio-solo-testo {
  grid-template-columns: 1fr;
}

.approccio-solo-testo .approccio-text {
  max-width: 62ch;
}

@media (max-width: 800px) {
  .approccio {
    grid-template-columns: 1fr;
  }
}

/* IL PERCORSO DEGLI ESERCIZI. */
.ex-heading {
  margin: var(--space-xl) 0 var(--space-md);
}

.ex-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-md);
}

.ex-card {
  background: var(--color-card);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}

.ex-title {
  margin-bottom: var(--space-xs);
}

.ex-text {
  color: var(--color-text-muted);
  line-height: 1.7;
}

.ex-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: var(--space-md);
}

/* La pillola della durata, col quadrante. Il glifo e' 14px dentro una riga
   da 0.78rem: piu' grande sovrasterebbe il numero che deve accompagnare. */
.ex-dur {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-size: 0.78rem;
}

.ex-dur svg {
  width: 14px;
  height: 14px;
}

/* L'attesa dell'audio non e' una pillola: e' una nota. Una pillola accanto
   a un'altra pillola si legge come un secondo dato, e questo non e' un
   dato, e' uno stato provvisorio. */
.ex-attesa {
  font-size: 0.78rem;
  font-style: italic;
  color: var(--color-text-muted);
}

/* L'ATTERRAGGIO DEL QR. Colonna stretta e centrata: chi arriva qui ha appena
   inquadrato un codice col telefono, deve capire in tre secondi dove e'
   finito e che cosa fare. */
.qr-landing {
  max-width: 46rem;
  text-align: center;
}

.qr-lead {
  font-size: 1.15rem;
  color: var(--color-text);
  margin-bottom: var(--space-md);
}

.qr-text {
  color: var(--color-text-muted);
  line-height: 1.8;
  margin-bottom: var(--space-lg);
}

.qr-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  margin-bottom: var(--space-lg);
}

.qr-note {
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* La riga che sostituisce il cancello per chi arriva dal libro. */
.ex-sbloccato {
  padding: 0.9rem 1.2rem;
  border-left: 3px solid var(--color-lav);
  background: var(--color-card);
  color: var(--color-text);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

/* ============================================================
   FREQUENCY LAB — gli strumenti sonori
   ============================================================ */

.lab-hub, .lab { max-width: 46rem; }

.lab-lead, .lab-headphones {
  color: var(--color-text-muted);
  line-height: 1.8;
  margin-bottom: var(--space-lg);
}

.lab-headphones strong { color: var(--color-text); }

.lab-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.lab-tile {
  display: block;
  padding: var(--space-lg);
  border-radius: var(--radius-lg);
  background: var(--color-card);
  color: inherit;
  text-decoration: none;
  transition: transform var(--transition-fast);
}

.lab-tile:hover { transform: translateY(-3px); }
.lab-tile h2 { font-size: 1.2rem; margin-bottom: var(--space-xs); }
.lab-tile p { color: var(--color-text-muted); font-size: 0.9rem; line-height: 1.6; }

.lab-badge {
  display: inline-block;
  margin-top: var(--space-md);
  padding: 0.2rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-link);
  font-size: 0.72rem;
}

.lab-back { margin-bottom: var(--space-md); }
.lab-back a { color: var(--color-text-muted); font-size: 0.9rem; }

/* Il pannello dei comandi: una card sola, cosi' i cursori stanno insieme
   invece di galleggiare sulla pagina. */
.lab-panel {
  background: var(--color-card);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}

.lab-label { display: block; margin-bottom: var(--space-sm); }

.lab-select {
  width: 100%;
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-field-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-family: inherit;
  font-size: 1rem;
}

.lab-play { width: 100%; margin-top: var(--space-md); }

.lab-slider { margin-top: var(--space-lg); }

.lab-slider-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.4rem;
}

/* tabular-nums: senza, il numero balla mentre si trascina il cursore, perche'
   le cifre hanno larghezze diverse. */
.lab-readout {
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.lab-slider input[type="range"] {
  width: 100%;
  accent-color: var(--color-lav);
}

.lab-rule {
  margin: var(--space-xl) 0 var(--space-lg);
  border: 0;
  border-top: 1px solid var(--color-border);
}

.lab-music-title { font-size: 1.05rem; margin-bottom: var(--space-sm); }

/* Il campo file nativo e' inservibile da vestire: si nasconde e si usa la
   sua etichetta come bottone. Non display:none, o sparisce dal percorso di
   tabulazione e chi naviga da tastiera non lo raggiunge piu'. */
.lab-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.lab-file-input:focus-visible + label {
  outline: 2px solid var(--color-lav);
  outline-offset: 2px;
}

.lab-file-name {
  margin-top: var(--space-sm);
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.lab-free { margin-top: var(--space-lg); line-height: 1.8; }

/* L'avvertenza: piccola ma non nascosta. Parla di epilessia e pacemaker, non
   e' una formalita'. */
.lab-disclaimer {
  margin-top: var(--space-xl);
  font-size: 0.85rem;
  line-height: 1.7;
  color: var(--color-text-muted);
}

/* Il lettore dell'esercizio. Compare solo a chi e' sbloccato E ha un file
   da ascoltare: finche' non c'e', al suo posto resta la nota. */
.ex-player {
  margin-top: var(--space-md);
}

.ex-player audio {
  width: 100%;
  display: block;
}

/* Il paragrafo che segue la riga dei dati non deve lasciare un buco quando
   e' vuoto. */
.ex-nascondi:empty {
  display: none;
}

/* Quello che non esiste. Gli stili stavano scritti dentro l'attributo style:
   qui almeno seguono i colori del sito e cambiano con lui. */
.pagina-assente {
  text-align: center;
  padding: var(--space-xl) 0;
}

.pagina-assente h1 {
  margin-bottom: var(--space-md);
}

.pagina-assente p {
  color: var(--color-text-muted);
  margin-bottom: var(--space-lg);
}

/* Il terzo peso dei bottoni: solo contorno.
   `btn-secondary` non serviva allo scopo — in base.css sarebbe un contorno, ma
   qui sopra e' riempito di sabbia, ed e' il «Catalogo». Servivano tre pesi
   distinti, non due.
   Il contorno e' l'inchiostro attenuato, il testo l'inchiostro pieno: cosi' il
   bottone si legge come i suoi fratelli ma pesa meno di tutti. */
.btn-ghost {
  background: transparent;
  border: 2px solid var(--color-field-border);
  color: var(--color-primary);
  border-radius: var(--radius-pill);
}

.btn-ghost:hover {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-surface);
}

/* --- Le risorse audio --- */

/* L'avviso delle cuffie sta in evidenza perche' senza cuffie il prodotto non
   funziona: non e' una raccomandazione, e' la condizione d'uso. */
.risorse-cuffie {
  margin: 0 0 var(--space-lg);
  padding: 0.7rem 1rem;
  border-left: 3px solid var(--color-primary);
  background: var(--color-surface-alt);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  color: var(--color-text);
  font-size: 0.95rem;
  line-height: 1.5;
}

/* La nota sul colore sta sotto quella delle cuffie e pesa meno: la prima e'
   una condizione d'uso, questa e' una spiegazione. Stesso rientro, nessun
   bordo, corpo piu' piccolo — si legge come una didascalia, che e' quello
   che e'. */
.risorse-colore {
  margin: calc(-1 * var(--space-md)) 0 var(--space-lg);
  padding: 0 1rem;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  line-height: 1.5;
}

/* IL COLORE DEL BATTIMENTO, che si vede solo mentre la traccia suona.
   `--tinta` arriva dalla scheda, calcolata in costruzione; la classe
   `risorsa--accesa` la mette e la toglie risorse-colore.js sui soli eventi
   play/pause/ended. A riposo qui non si vede niente: dieci schede colorate in
   fila sarebbero una tassonomia, e questo colore non classifica nulla.

   LA TRANSIZIONE STA SULLA SCHEDA e non sulla classe, cosi' vale in tutte e
   due le direzioni. Un secondo e due decimi: spegnersi di colpo somiglia a un
   guasto, dissolvere somiglia alla coda di un suono. */
.risorsa {
  transition: background-color 1.2s ease, box-shadow 1.2s ease;
}

/* Il fondo prende un dodicesimo di tinta — abbastanza da vedersi contro il
   crema delle altre schede, troppo poco per mettere in difficolta' il testo
   che ci sta sopra. */
.risorsa--accesa {
  background-color: color-mix(in oklab, var(--tinta) 12%, var(--color-card));
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--tinta) 45%, transparent),
              0 10px 34px -14px var(--tinta);
}

/* IL LETTORE E' LA COSA CHE SUONA, quindi e' la cosa che si tinge di piu'.
   `accent-color` colora i controlli nativi sui browser che lo rispettano; dove
   non li tocca resta l'alone, che il risultato lo da' comunque. */
.risorsa--accesa .risorsa-player {
  accent-color: var(--tinta);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--tinta) 55%, transparent),
              0 0 22px -4px var(--tinta);
  transition: box-shadow 1.2s ease;
  animation: risorsa-respiro 6s ease-in-out infinite;
}

/* IL RESPIRO NON SEGUE IL BATTIMENTO, ed e' una rinuncia voluta: pulsare a
   14 Hz vorrebbe dire lampeggiare dentro la banda che scatena le crisi
   fotosensibili. Sei secondi, uguali per tutte le tracce. */
@keyframes risorsa-respiro {
  0%, 100% { box-shadow: 0 0 0 2px color-mix(in oklab, var(--tinta) 55%, transparent),
                         0 0 22px -4px var(--tinta); }
  50%      { box-shadow: 0 0 0 2px color-mix(in oklab, var(--tinta) 30%, transparent),
                         0 0 10px -6px var(--tinta); }
}

/* Chi ha chiesto meno movimento al sistema operativo tiene il colore e perde
   solo il respiro: la tinta e' l'ornamento, il moto era il di piu'. */
@media (prefers-reduced-motion: reduce) {
  .risorsa--accesa .risorsa-player { animation: none; }
}

.risorsa-banda,
.risorsa-variante {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--color-surface-alt);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
}

.risorsa-banda {
  background: var(--color-primary);
  color: var(--color-surface);
  font-weight: 600;
}

/* Il bottone spento deve SEMBRARE spento: senza questo si preme e non succede
   niente, che si legge come un guasto invece che come «non hai il libro». */
.risorsa-scarica[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.risorsa-stato {
  margin-left: 0.6rem;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

/* Il lettore di una risorsa: largo quanto la scheda, staccato dai metadati. */
.risorsa-player {
  display: block;
  width: 100%;
  margin-top: var(--space-sm);
}

.ex-audio {
  display: block;
  width: 100%;
  margin-top: var(--space-sm);
}

/* --- Il selettore di ottava del generatore --- */

.lab-ottave {
  border: 0;
  padding: 0;
  margin: var(--space-sm) 0 0;
}

.lab-ottave-scelte {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.lab-ottava {
  flex: 1 1 auto;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.lab-ottava:hover {
  background: var(--color-surface-alt);
}

/* Lo stato attivo si vede dal RIEMPIMENTO, non da un bordo piu' spesso: con
   tre bottoni affiancati un bordo diverso si nota poco, e chi guarda deve
   capire a colpo d'occhio quale ottava sta suonando. */
.lab-ottava.is-attiva {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-surface);
  font-weight: 600;
}

.lab-ottave-nota {
  margin: 8px 0 0;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--color-text-muted);
}
