/* =================================================================
   /agency — "Il reel" (layouts/partials/agency/reel.html)
   Isola BIANCA dentro la pagina scura: una timeline da videoeditor
   (stage + capitoli + asticelle + playhead) che scorre da sola.
   I token chiari sono scopati su .ag-reel, non su :root: il resto
   della pagina resta sul tema scuro di main.css.
   ================================================================= */
.ag-reel {
  --ink: #0c0b09;
  --paper: #ffffff;
  --panel: #f1f0ed;          /* fondo dello stage e dei box capitolo */
  --panel-on: #d9d7d1;       /* box capitolo attivo */
  --edge: rgba(12, 11, 9, 0.1);
  --dim: #8b8880;
  --glide: cubic-bezier(0.65, 0, 0.2, 1);   /* movimento "camera": parte deciso, si posa */

  /* Dimensionamento dello stage su MOBILE — vedi .rl-stage e il @media in fondo.
     --rl-ar = proporzione del box. --rl-chrome = quanto della sezione NON è lo
     stage (padding + testata + gap + timeline), MISURATO a schermo: se cambi
     testata, timeline o padding, rimisuralo. */
  --rl-ar: 0.8;
  --rl-chrome: 340px;

  /* Altezza reale della top bar: .nav è `fixed` e alta quanto il suo contenuto
     (44px) più il proprio padding verticale — stessa formula di
     assets/shared/topbar.css. Serve perché la sezione, una volta agganciata,
     parte dal bordo alto del viewport: senza questo spazio il titolo finirebbe
     sotto la barra. ⚠️ Se cambia il padding di .nav, va cambiato anche qui. */
  --rl-topbar: calc(44px + 2 * clamp(14px, 2vw, 24px));

  position: relative;
  /* Fondo di ripiego: vale se il JS non parte o con reduced-motion. Quando
     reel.js c'è, marca html.rl-fade e il fondo passa al pannello .rl-backdrop
     in dissolvenza (vedi sotto) — la sezione diventa trasparente. */
  background: var(--paper);
  color: var(--ink);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* ⚠️ Padding e gap in px FISSI, non in vh. Sembra un dettaglio di gusto, non lo
     è: --rl-chrome deve valere a ogni altezza di viewport, e con i `clamp(…vh…)`
     il chrome si restringeva sui viewport bassi. Il risultato era il peggiore
     possibile — su uno schermo basso il tetto restava tarato sul chrome grande e
     lo stage veniva rimpicciolito proprio dove lo spazio già mancava.
     Ogni px tolto qui è un px che va allo stage. */
  gap: 24px;
  /* In alto lo spazio della top bar + aria: è una garanzia, non un'estetica —
     la sezione si aggancia al bordo alto del viewport, quindi il titolo ci
     finirebbe sotto. Vale anche se il contenuto è più corto di 100svh e viene
     centrato, perché il padding resta comunque il minimo. */
  padding: calc(var(--rl-topbar) + 20px) 0 32px;
  /* ⚠️ NIENTE `overflow: hidden` qui. Contro l'intuizione (il containing block di
     un `fixed` è il viewport, non l'antenato), un antenato con overflow:hidden
     CLIPPA comunque il disegno di un discendente `fixed`: .rl-backdrop restava
     grande quanto il viewport ma veniva dipinto solo dentro il box della
     sezione, e sopra il suo bordo lo sfondo restava nero — cioè esattamente il
     bordo netto che la dissolvenza deve togliere. Il taglio orizzontale della
     pagina ce l'ha già `body.agency { overflow-x: hidden }` in main.css, e lo
     stage si clippa da solo. */
}
/* ⚠️ .ag-wrap porta `margin: 0 auto`, e un margine auto sull'asse trasversale di
   un flex column BATTE align-items:stretch: il wrap si dimensionerebbe a
   fit-content, che qui (figli in absolute + immagini lazy) vale zero → stage e
   timeline larghi 0. Il width esplicito ridà una base su cui max-width e i
   margini auto possono lavorare. Serve finché .ag-reel è un flex container. */
.ag-reel > .ag-wrap { width: 100%; }

/* ---- fondo bianco a dissolvenza ----
   Pannello fisso grande quanto il viewport: scrollando, tutto lo schermo passa
   da nero a bianco e ritorno. È `fixed` e non il fondo della sezione perché un
   fondo di sezione entrerebbe con un bordo netto che sale; così invece non c'è
   nessun bordo da nessuna parte, e a piena opacità il bianco riempie davvero
   l'intero viewport (che è la condizione richiesta a sezione agganciata).
   Le sezioni vicine sbiancano insieme allo sfondo: la dissolvenza è di tutta la
   pagina, non solo di questo box.
   ⚠️ z-index 2 e non 0: le card di .ag-worlds sono `position: relative`, quindi
   con z-index 0 il pannello sarebbe finito SOTTO di loro (stesso livello di
   pittura, vince l'ordine nel DOM, e .ag-worlds viene dopo) — la sezione sopra
   sbiancava e quella sotto no. Sotto la top bar, che è fixed a z-index 100. */
.rl-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 2;
  background: var(--paper);
  pointer-events: none;
}
html.rl-fade .ag-reel { background: transparent; }
html.rl-fade .rl-backdrop { display: block; opacity: var(--rl-bg, 0); }

/* ---- la top bar segue lo sfondo ----
   .nav è `fixed` e sta FUORI dalla sezione (è sorella di <main>), quindi sopra
   il bianco restava col tema scuro della pagina: testo chiaro e pill traslucide
   chiare, cioè illeggibile. Qui i suoi token vengono miscelati tra scuro e
   chiaro usando --rl-bg (che il JS scrive su <html>) come percentuale: così
   scorrono INSIEME allo sfondo, senza una soglia che scatta e senza transizioni
   da tenere in sincrono con la dissolvenza. A --rl-bg 0 il risultato è identico
   ai valori scuri di main.css.
   `html.js` batte per specificità il `:root` di agency/main.css che li definisce.
   ⚠️ --tb-accent no: lo scrive topbar.html inline per-pagina (accento della
   sezione attiva) e uno stile inline vincerebbe comunque su questa regola. */
html.js {
  --tb-pill: color-mix(in srgb, rgba(12, 11, 9, 0.06) calc(var(--rl-bg, 0) * 100%), rgba(244, 242, 234, 0.08));
  --tb-pill-hover: color-mix(in srgb, rgba(12, 11, 9, 0.12) calc(var(--rl-bg, 0) * 100%), rgba(244, 242, 234, 0.15));
  --tb-fg: color-mix(in srgb, #0c0b09 calc(var(--rl-bg, 0) * 100%), #f4f2ea);
  --tb-fg-dim: color-mix(in srgb, rgba(12, 11, 9, 0.45) calc(var(--rl-bg, 0) * 100%), rgba(244, 242, 234, 0.5));
  --tb-cta-bg: color-mix(in srgb, #0c0b09 calc(var(--rl-bg, 0) * 100%), #f4f2ea);
  --tb-cta-fg: color-mix(in srgb, #f4f2ea calc(var(--rl-bg, 0) * 100%), #0c0b09);
}
/* Il contenuto della sezione deve stare SOPRA il pannello, o sparisce sotto. */
.ag-reel > .ag-wrap { position: relative; z-index: 3; }

.ag-reel__head { text-align: center; }
.ag-reel__body { display: flex; flex-direction: column; gap: 20px; }

/* ============================ STAGE ============================ */
.rl-stage {
  position: relative;
  width: 100%;
  /* DESKTOP: piena larghezza, altezza a tetto. Il box vuole restare panoramico e
     grande — largo quanto il wrap. Qui NON lego la larghezza all'altezza (come
     invece faccio su mobile): su un portatile basso il box diventerebbe più
     piccolo di prima, che è l'opposto di quel che serve, e sul desktop non ci
     sono barre del browser che possano mangiarsi la timeline — al massimo la
     sezione supera di poco il viewport e si scorre.
     ⚠️ Conseguenza da conoscere: la proporzione del box cambia con l'altezza del
     viewport (~2.1 a 900px, ~2.7 a 700px), e le geometrie per capitolo sono % di
     questo box → i ritagli si muovono un po'. Sono tarate sul caso comune (~2.1). */
  height: clamp(320px, 56svh, 580px);
  margin: 0 auto;
  border-radius: clamp(18px, 2vw, 28px);
  background: var(--panel);
  overflow: hidden;
  /* Le geometrie della cornice cambiano left/top/width/height: `contain` tiene
     il reflow dentro lo stage invece di farlo risalire alla pagina. */
  contain: layout paint;
}

/* ---- la cornice-piano-sequenza ----
   Un solo elemento per tutta la sezione: cambia posizione/forma a ogni
   capitolo (le geometrie stanno più sotto, per [data-ch]) e le immagini
   dentro si dissolvono. È la continuità della sequenza — non smontarla
   in un elemento per capitolo. */
.rl-morph {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  margin: 0;
  border-radius: var(--r, 14px);
  overflow: hidden;
  background: #e3e1dc;
  transform: rotate(var(--rot, 0deg));
  box-shadow: 0 18px 50px -18px rgba(12, 11, 9, 0.4);
  transition:
    left 1.15s var(--glide), top 1.15s var(--glide),
    width 1.15s var(--glide), height 1.15s var(--glide),
    border-radius 1.15s var(--glide), transform 1.15s var(--glide),
    opacity 0.7s var(--ease);
}
.rl-morph__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 0.9s var(--ease), transform 1.4s var(--glide);
}
.rl-morph__img.is-on { opacity: 1; transform: scale(1); }
.rl-morph__edge {
  position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  pointer-events: none;
}

/* ---- satelliti ---- */
.rl-sats { position: absolute; inset: 0; pointer-events: none; }
.rl-sat {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  border-radius: 10px;
  overflow: hidden;
  background: #e3e1dc;
  box-shadow: 0 12px 34px -14px rgba(12, 11, 9, 0.45);
  opacity: 0;
  transform: translateY(26px) scale(0.94) rotate(var(--rot, 0deg));
  transition: opacity 0.6s var(--ease), transform 0.95s var(--glide);
  transition-delay: 0ms;
}
.rl-sat img { width: 100%; height: 100%; object-fit: cover; }
.rl-sats.is-on .rl-sat {
  opacity: 1;
  transform: translateY(0) scale(1) rotate(var(--rot, 0deg));
  transition-delay: calc(360ms + var(--j) * 130ms);   /* entrano DOPO che la cornice si è posata */
}

/* ---- copy ----
   Tutti i capitoli occupano la stessa zona; il reveal è a maschera (le righe
   salgono da dietro il proprio ritaglio), non un fade.
   Due tipi (vedi il partial): il capitolo "titolo" (about) mostra sempre
   eyebrow + titolo + sottotitolo; i capitoli "galleria" hanno .rl-copy--name e
   mostrano il solo nome della sezione, SOLO su mobile — su desktop lo stage è
   tutto immagini e il nome è già scritto per esteso nel box attivo qui sotto. */
.rl-copy {
  position: absolute;
  left: clamp(18px, 3.5%, 40px);
  bottom: clamp(18px, 5%, 40px);
  width: min(34%, 380px);
  pointer-events: none;
}
.rl-copy--name { display: none; }
.rl-copy__tag, .rl-copy__t, .rl-copy__b { margin: 0; overflow: hidden; }
.rl-copy__tag span, .rl-copy__t span, .rl-copy__b span {
  display: block;
  transform: translateY(105%);
  transition: transform 0.85s var(--glide);
}
.rl-copy__tag {
  font-family: var(--font-mono);
  font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--dim);
  margin-bottom: 0.7rem;
}
.rl-copy__t {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.15rem, 2.1vw, 1.85rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.rl-copy__b {
  margin-top: 0.6rem;
  font-size: clamp(0.85rem, 1.1vw, 0.98rem);
  line-height: 1.5;
  color: #514e47;
}
/* Il capitolo non attivo è fuori dal flusso di lettura E dallo schermo: senza
   `visibility` le sue righe (tradotte al 105%, non clippate in altezza) restano
   leggibili dagli screen reader e dalla ricerca del browser. */
.rl-copy { visibility: hidden; }
.rl-copy.is-on { visibility: visible; }
.rl-copy.is-on .rl-copy__tag span { transform: none; transition-delay: 260ms; }
.rl-copy.is-on .rl-copy__t span { transform: none; transition-delay: 340ms; }
.rl-copy.is-on .rl-copy__b span { transform: none; transition-delay: 420ms; }

/* ---- link del capitolo ---- */
.rl-go {
  position: absolute;
  right: clamp(16px, 2.6%, 30px);
  bottom: clamp(16px, 4%, 30px);
  z-index: 3;
  display: inline-flex; align-items: center; gap: 0.5em;
  padding: 0.62em 1.05em;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(10px);
  font-family: var(--font-display); font-weight: 600; font-size: 0.86rem;
  color: var(--ink);
  box-shadow: 0 8px 24px -10px rgba(12, 11, 9, 0.5);
  transition: transform 0.4s var(--ease), background 0.3s var(--ease), opacity 0.5s var(--ease);
}
.rl-go i { font-style: normal; transition: transform 0.4s var(--ease); }
@media (hover: hover) {
  .rl-go:hover { transform: translateY(-2px); background: #fff; }
  .rl-go:hover i { transform: translateX(4px); }
}

/* Tap sull'intero box → pagina del capitolo. Solo mobile (vedi @media): su
   desktop lo stesso lavoro lo fa la pill, e un link a tutto schermo lì
   ruberebbe l'hover alle foto. */
.rl-tap { display: none; position: absolute; inset: 0; z-index: 4; }

/* ============================ CAPITOLO 1: asterisco → cardinali.studio/ ============================
   Le 3 aste partono a ±60° dall'angolo dello slash (19°) e vi convergono; poi
   il glifo "/" reale riappare in crossfade e il nome scorre fuori da dietro.
   --bw (larghezza del nome, misurata dal JS) tiene lo SLASH al centro finché il
   nome è nascosto: è l'unico numero che il CSS non può conoscere da solo. */
.rl-word {
  position: absolute;
  left: 50%; top: 50%;
  z-index: 2;
  display: flex; align-items: baseline;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 3.6vw, 3rem);
  letter-spacing: -0.03em;
  white-space: nowrap;
  color: var(--ink);
  opacity: 0;
  /* Il box è [nome][/]: lo slash sta all'estremità DESTRA, quindi centrare il
     box (translate -50%) lascia lo slash sbilanciato a destra di mezzo nome.
     --wx compensa: -bw/2 mentre il nome è nascosto (slash al centro esatto,
     perno dell'asterisco) → 0 quando il nome è uscito e il wordmark intero si
     centra. Il segno conta: +bw/2 spinge tutto fuori a destra. */
  transform: translate(calc(-50% + var(--wx, 0px)), -50%) scale(var(--ws, 1));
  transform-origin: 50% 50%;
  transition: transform 1.25s var(--glide), opacity 0.6s var(--ease);
  pointer-events: none;
}
.rl-word__base {
  display: inline-block;
  /* Il ritaglio è FISSO sul lato destro (= fianco sinistro dello slash): il
     nome è visibile solo a sinistra dello slash. La maschera è clip-path e non
     overflow perché overflow sposterebbe la baseline. */
  clip-path: inset(-0.2em 0 -0.2em -0.2em);
}
.rl-word__inner {
  display: inline-block;
  font-style: normal;
  transform: translateX(101%);   /* nascosto dietro lo slash */
  transition: transform 1.5s var(--glide);
}
.rl-word__sep { position: relative; color: transparent; transition: color 0.5s var(--ease); }
.rl-arm {
  position: absolute; left: 52%; top: 53%;
  width: 0.13em; height: 0.92em;
  background: var(--ink);
  transform-origin: 50% 50%;
  transform: translate(-50%, -50%) rotate(var(--a));
  transition: transform 1.5s cubic-bezier(0.24, 1.6, 0.36, 1), opacity 0.45s var(--ease);
}
.rl-arm:nth-child(1) { --a: -41deg; }
.rl-arm:nth-child(2) { --a: 19deg; }
.rl-arm:nth-child(3) { --a: 79deg; }

/* fasi (data-phase, pilotate dal JS in base al tempo del capitolo) */
.rl-stage[data-ch="about"][data-phase="a0"] .rl-word,
.rl-stage[data-ch="about"][data-phase="a1"] .rl-word,
.rl-stage[data-ch="about"][data-phase="a2"] .rl-word { opacity: 1; }
/* a0 = l'asterisco compare, con un filo di pop */
.rl-stage[data-ch="about"][data-phase="a0"] .rl-word { --wx: calc(var(--bw, 0px) / -2); --ws: 1.06; }
/* a1 = le aste convergono sullo slash */
.rl-stage[data-ch="about"][data-phase="a1"] .rl-word { --wx: calc(var(--bw, 0px) / -2); --ws: 1; }
.rl-stage[data-ch="about"][data-phase="a1"] .rl-arm { transform: translate(-50%, -50%) rotate(19deg); }
/* a2 = crossfade barre→glifo, il nome scorre fuori, il wordmark si ricentra */
.rl-stage[data-ch="about"][data-phase="a2"] .rl-word { --wx: 0px; --ws: 1; }
.rl-stage[data-ch="about"][data-phase="a2"] .rl-arm { transform: translate(-50%, -50%) rotate(19deg); opacity: 0; }
.rl-stage[data-ch="about"][data-phase="a2"] .rl-word__sep { color: var(--ink); }
.rl-stage[data-ch="about"][data-phase="a2"] .rl-word__inner { transform: translateX(0); }
/* a3 = il wordmark svanisce e la cornice sboccia dalla sua posizione */
.rl-stage[data-ch="about"][data-phase="a3"] .rl-word { opacity: 0; --ws: 0.92; }
.rl-stage[data-ch="about"][data-phase="a3"] .rl-word__sep { color: var(--ink); }
.rl-stage[data-ch="about"][data-phase="a3"] .rl-word__inner { transform: translateX(0); }
.rl-stage[data-ch="about"][data-phase="a3"] .rl-arm { opacity: 0; }

/* Prima di a3 lo stage è ancora "vuoto": cornice, satelliti, copy e link
   aspettano che il wordmark abbia finito. La cornice nasce scalata dal centro
   → sembra sbocciare dallo slash. */
.rl-stage[data-ch="about"]:is([data-phase="a0"], [data-phase="a1"], [data-phase="a2"]) :is(.rl-morph, .rl-copy, .rl-go, .rl-sats) {
  opacity: 0;
}
.rl-stage[data-ch="about"]:is([data-phase="a0"], [data-phase="a1"], [data-phase="a2"]) .rl-morph {
  transform: rotate(var(--rot, 0deg)) scale(0.3);
}
.rl-stage[data-ch="about"]:is([data-phase="a0"], [data-phase="a1"], [data-phase="a2"]) .rl-copy span { transform: translateY(105%); }

/* ============================ GEOMETRIE PER CAPITOLO ============================
   Percentuali dello stage (desktop: 1104×513 a piena larghezza — proporzione
   FISSA --rl-ar, quindi questi valori valgono a ogni viewport). Ogni `key` di
   data/agency.yml → un blocco qui; una key senza blocco resta senza geometria
   (cornice a 0).

   Due impianti diversi, perché i capitoli sono di due tipi:
   • "titolo" (about): la copy occupa il basso-sinistra fino al ~37.5%, quindi la
     cornice sta oltre, nella metà destra.
   • "galleria" (gli altri): su desktop non c'è testo → la cornice si porta a
     sinistra e i tre satelliti riempiono tutta la larghezza. Sono le uniche
     quattro immagini a schermo, quindi si distribuiscono su tutto il box.

   ⚠️ Le proporzioni dei box NON sono libere: con `object-fit: cover` un box
   lontano dal rapporto nativo del file ritaglia via il soggetto. I valori qui
   sono tarati sui file veri (misurati a schermo), tenendo visibile ≥ ~80%
   dell'immagine:
     portrait.webp 1:1 · food/ritratti 2:3 · corp 3:2 (rovagnati 2:3)
     dev/week-34 9:16 (screenshot d'app) · dev/cover-8, utile ~3:4
   Cambiando un'immagine in data/agency.yml, ricontrolla il rapporto del suo box.
   Formula: --w = rapporto × --h ÷ --rl-ar. */

/* 01 — chi sono: capitolo "titolo". La cornice nasce dallo slash come ritratto
   verticale e resta a destra, lasciando il basso-sinistra ai testi.
   (È l'unica volutamente fuori rapporto: portrait.webp è quadrata e il box la
   ritaglia in verticale — il volto resta intero, la posa guadagna.) */
.rl-stage[data-ch="about"] .rl-morph { --x: 45%; --y: 9%; --w: 30%; --h: 82%; --r: 16px; --rot: 0deg; }

/* 02 — food: la cornice si stringe in verticale e scivola tutta a sinistra */
.rl-stage[data-ch="food"] .rl-morph { --x: 3%; --y: 8%; --w: 26%; --h: 84%; --r: 14px; --rot: -1.2deg; }
.rl-sats[data-ch="food"] .rl-sat:nth-child(1) { --x: 32%; --y: 16%; --w: 19%; --h: 62%; --rot: 2.4deg; }
.rl-sats[data-ch="food"] .rl-sat:nth-child(2) { --x: 54.5%; --y: 30%; --w: 16%; --h: 52%; --rot: -1.8deg; }
.rl-sats[data-ch="food"] .rl-sat:nth-child(3) { --x: 73.5%; --y: 6%; --w: 21%; --h: 68%; --rot: 1.4deg; }

/* 03 — ritratti: la cornice si alza quasi a tutta altezza */
.rl-stage[data-ch="portraits"] .rl-morph { --x: 3%; --y: 6%; --w: 27%; --h: 88%; --r: 14px; --rot: 0deg; }
.rl-sats[data-ch="portraits"] .rl-sat:nth-child(1) { --x: 33%; --y: 22%; --w: 19%; --h: 60%; --rot: -2.6deg; }
.rl-sats[data-ch="portraits"] .rl-sat:nth-child(2) { --x: 55%; --y: 10%; --w: 22%; --h: 70%; --rot: 1.6deg; }
.rl-sats[data-ch="portraits"] .rl-sat:nth-child(3) { --x: 80%; --y: 30%; --w: 17%; --h: 54%; --rot: -1.2deg; }

/* 04 — corporate: la cornice si corica in panoramica. I satelliti orizzontali
   sono larghi a parità di altezza → due impilati al centro, il verticale a destra. */
.rl-stage[data-ch="corp"] .rl-morph { --x: 3%; --y: 21%; --w: 40%; --h: 58%; --r: 12px; --rot: 0.8deg; }
.rl-sats[data-ch="corp"] .rl-sat:nth-child(1) { --x: 46%; --y: 8%; --w: 26.5%; --h: 38%; --rot: -2deg; }
.rl-sats[data-ch="corp"] .rl-sat:nth-child(2) { --x: 76%; --y: 6%; --w: 20.5%; --h: 66%; --rot: -1deg; }
.rl-sats[data-ch="corp"] .rl-sat:nth-child(3) { --x: 46%; --y: 52%; --w: 26.5%; --h: 38%; --rot: 1.4deg; }

/* 05 — sviluppo: ultima trasformazione — la cornice smette di essere una foto e
   diventa un dispositivo (9:16, raggio da telefono) con dentro un'app vera. */
.rl-stage[data-ch="dev"] .rl-morph { --x: 3%; --y: 6%; --w: 23%; --h: 88%; --r: 22px; --rot: 0deg; }
.rl-sats[data-ch="dev"] .rl-sat:nth-child(1) { --x: 29%; --y: 14%; --w: 20%; --h: 58%; --rot: -2.4deg; }
.rl-sats[data-ch="dev"] .rl-sat:nth-child(2) { --x: 52.5%; --y: 28%; --w: 19%; --h: 50%; --rot: 3deg; }
.rl-sats[data-ch="dev"] .rl-sat:nth-child(3) { --x: 74%; --y: 8%; --w: 23%; --h: 66%; --rot: -1.4deg; }

/* ============================ TIMELINE ============================ */
.rl-timeline {
  position: relative;
  --p: 0;                     /* progresso 0→1, scritto dal JS */
  padding-top: 26px;          /* spazio per la testina del playhead */
}
/* ---- box dei capitoli ---- */
.rl-track { display: flex; align-items: stretch; height: 76px; }   /* px fissi: entra in --rl-chrome */
.rl-chip {
  position: relative;
  flex: var(--dur) 1 0%;      /* larghezza = durata → i bordi cadono sull'istante esatto */
  min-width: 0;
  padding: 0; margin: 0; border: 0; background: none;
  font: inherit; color: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.rl-chip__in {
  position: absolute; inset: 0 3px;   /* il distacco è QUI: un gap sul track sfaserebbe il playhead */
  display: flex; align-items: center; justify-content: center;
  padding: 0 0.6em;
  border-radius: 10px;
  background: var(--panel);
  transition: background 0.45s var(--ease), transform 0.45s var(--ease);
}
.rl-chip__lab {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(0.72rem, 1.15vw, 1rem);
  line-height: 1.15;
  text-align: center;
  color: #6d6a63;
  transition: color 0.45s var(--ease);
  overflow-wrap: anywhere;
}
.rl-chip__short { display: none; }
.rl-chip.is-on .rl-chip__in { background: var(--panel-on); }
.rl-chip.is-on .rl-chip__lab { color: var(--ink); }
@media (hover: hover) {
  .rl-chip:hover .rl-chip__in { background: #e6e5e1; transform: translateY(-2px); }
}
.rl-chip:focus-visible .rl-chip__in { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---- asticelle: una ogni mezzo secondo, più alta a ogni secondo ----
   La spaziatura viene da --total (durata in secondi, iniettata dal template):
   cambiare le durate in data/agency.yml ri-tara il righello da solo. */
.rl-ticks {
  position: relative;
  height: 24px;
  margin-top: 14px;
  cursor: pointer;
  background-image:
    linear-gradient(to right, rgba(12, 11, 9, 0.22) 0 1px, transparent 1px),
    linear-gradient(to right, rgba(12, 11, 9, 0.4) 0 1px, transparent 1px);
  background-size:
    calc(100% / (var(--total, 28) * 2)) 9px,
    calc(100% / var(--total, 28)) 16px;
  background-position: 0 100%, 0 100%;
  background-repeat: repeat-x;
}

/* ---- playhead ---- */
.rl-playhead {
  position: absolute;
  top: 18px; bottom: 0;
  left: calc(var(--p) * 100%);
  width: 0;
  pointer-events: none;
  z-index: 2;
}
.rl-playhead__line {
  position: absolute; top: 8px; bottom: 0; left: -0.5px;
  width: 1px;
  background: var(--ink);
}
.rl-playhead__dot {
  position: absolute; top: 0; left: 0;
  width: 9px; height: 9px; margin: -4px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--ink);
}
.rl-playhead__time {
  position: absolute; top: -4px; left: 10px;
  padding: 0.2em 0.5em;
  border-radius: 5px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
  white-space: nowrap;
}
/* A fine timeline il badge uscirebbe dal gutter: oltre la soglia (vedi is-tail
   in reel.js) passa a sinistra del playhead. */
.rl-timeline.is-tail .rl-playhead__time { left: auto; right: 10px; }

/* ============================ MOBILE ============================ */
@media (max-width: 860px) {
  /* MOBILE: qui il modello si ribalta. Lo stage è verticale, quindi il vincolo
     naturale è la larghezza, e soprattutto la sezione DEVE stare tra la barra
     degli indirizzi e quella di navigazione: se sfora, la timeline finisce sotto
     le barre. Quindi l'altezza dello stage è quel che AVANZA del viewport piccolo
     (100svh, cioè barre mostrate = il caso peggiore: se ci sta così, ci sta
     sempre) una volta tolto il resto della sezione (--rl-chrome).
     Il tetto agisce sulla LARGHEZZA e non sull'altezza, così il box rimpicciolisce
     restando in scala: --rl-ar resta un rapporto vero e le geometrie qui sotto,
     che sono % del box, continuano a valere. Sui telefoni bassi lo stage scende
     sotto la piena larghezza e si centra. */
  .rl-stage {
    height: auto;
    aspect-ratio: var(--rl-ar);
    max-width: calc((100svh - var(--rl-chrome)) * var(--rl-ar));
  }
  /* La copy passa a fascia bassa a piena larghezza, su una velatura: nella
     colonna stretta il 34% laterale sarebbe illeggibile. Qui compare anche il
     nome dei capitoli "galleria": i box della timeline mostrano solo il numero,
     quindi senza questo il nome della sezione non si leggerebbe da nessuna parte. */
  .rl-copy { left: 16px; right: 16px; bottom: 16px; width: auto; z-index: 2; }
  .rl-copy--name { display: block; }
  /* La pill lascia il posto al tap sull'intero box: stessa destinazione. */
  .rl-go { display: none; }
  .rl-tap { display: block; }
  /* Velatura corta: deve rendere leggibile una riga sola sopra le foto, non
     sbiancare mezzo stage (i satelliti arrivano fin quasi al 78%). */
  .rl-stage::after {
    content: ""; position: absolute; inset: auto 0 0; height: 26%;
    background: linear-gradient(to top, rgba(241, 240, 237, 0.97) 38%, rgba(241, 240, 237, 0));
    pointer-events: none; z-index: 1;
  }

  /* 3 immagini invece di 4: il terzo satellite sparisce. In 335px una banda di
     quattro darebbe francobolli — qui la cornice tiene la sinistra e i due
     satelliti scendono in diagonale a destra.
     ⚠️ I rapporti NON si ereditano dal desktop: là il vincolo è l'altezza dello
     stage, qui la larghezza (stage 4:5). Ogni box è ricalcolato sul rapporto
     del suo file, non riscalato. */
  .rl-sat:nth-child(3) { display: none; }

  /* about — capitolo "titolo": la cornice sta in alto e lascia sotto lo spazio
     per eyebrow + titolo + sottotitolo (tre blocchi, non una riga). */
  .rl-stage[data-ch="about"] .rl-morph { --x: 22%; --y: 4%; --w: 56%; --h: 45%; --rot: 0deg; }

  /* ⚠️ I due satelliti sono in diagonale e si sfiorano: le --rot ereditate dal
     desktop allargano il loro ingombro reale di qualche px per lato, quindi tra
     il fondo del primo e la cima del secondo serve un margine (45%, non 42%) o
     gli angoli inclinati si accavallano. */
  .rl-stage[data-ch="food"] .rl-morph { --x: 3%; --y: 6%; --w: 42%; --h: 50%; }
  .rl-sats[data-ch="food"] .rl-sat:nth-child(1) { --x: 50%; --y: 5%; --w: 30%; --h: 36%; }
  .rl-sats[data-ch="food"] .rl-sat:nth-child(2) { --x: 65%; --y: 45%; --w: 30%; --h: 36%; }

  .rl-stage[data-ch="portraits"] .rl-morph { --x: 3%; --y: 6%; --w: 42%; --h: 50%; }
  .rl-sats[data-ch="portraits"] .rl-sat:nth-child(1) { --x: 50%; --y: 5%; --w: 30%; --h: 36%; }
  .rl-sats[data-ch="portraits"] .rl-sat:nth-child(2) { --x: 65%; --y: 45%; --w: 30%; --h: 36%; }

  /* corp: cornice e satellite 1 sono orizzontali (3:2) → box larghi e bassi;
     il satellite 2 (rovagnati) è verticale. */
  .rl-stage[data-ch="corp"] .rl-morph { --x: 3%; --y: 8%; --w: 66%; --h: 35%; }
  .rl-sats[data-ch="corp"] .rl-sat:nth-child(1) { --x: 26%; --y: 48%; --w: 45%; --h: 24%; }
  .rl-sats[data-ch="corp"] .rl-sat:nth-child(2) { --x: 74%; --y: 20%; --w: 22%; --h: 26%; }

  .rl-stage[data-ch="dev"] .rl-morph { --x: 4%; --y: 5%; --w: 33%; --h: 47%; }
  .rl-sats[data-ch="dev"] .rl-sat:nth-child(1) { --x: 42%; --y: 5%; --w: 27%; --h: 29%; }
  .rl-sats[data-ch="dev"] .rl-sat:nth-child(2) { --x: 60%; --y: 40%; --w: 30%; --h: 29%; }

  /* Cinque etichette per intero non ci stanno: i box mostrano il numero, e il
     nome della sezione lo dice lo stage qui sopra. */
  .rl-track { height: 46px; }
  .rl-chip__lab { display: none; }
  .rl-chip__short {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: #6d6a63;
    transition: color 0.45s var(--ease);
  }
  .rl-chip.is-on .rl-chip__short { color: var(--ink); }
  .rl-ticks { height: 16px; background-size: calc(100% / (var(--total, 28) * 2)) 6px, calc(100% / var(--total, 28)) 11px; }
}

/* ============================ REDUCED MOTION ============================
   Niente playhead che corre: il JS non avvia il clock e mostra il primo
   capitolo già montato. I box restano cliccabili per cambiare capitolo. */
@media (prefers-reduced-motion: reduce) {
  .rl-morph, .rl-morph__img, .rl-sat, .rl-copy span, .rl-word, .rl-arm, .rl-word__inner {
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }
  .rl-playhead { display: none; }
}
