/* hochzeit-v3 — chassis. Tokens from direction.lock.json */
:root{
  /* --- palette SCURA (Camera Oscura). Non si tocca: la usano ancora il
         loader e l'hero b01, che restano bui apposta (b04 è passata al
         chiaro il 17/08). */
  --bg:      #0B0A09;
  --shadow:  #1A140E;
  --wood:    #6B4A2E;
  --gold:    #C9A050;
  --paper:   #F2ECE3;

  /* --- palette CHIARA (LEGGE-DANIEL-2026-08-17 §L1/L2) --------------------
     «Il nero è bello però nella sezione matrimoni troppo scuro» (detto 2×).
     Il ground della pagina diventa carta; il nero sopravvive solo come
     momento dichiarato. I sette valori sono quelli estratti dal CSS del
     build Higgsfield di Daniel — sono i SUOI, non una nostra derivazione. */
  --cream:     #f7f2e9;
  --sand:      #e5dcc7;
  --line:      #d8cdb4;
  --gold2:     #c8a96e;
  --gold-deep: #a5824a;
  --ink:       #2e2c28;
  --muted:     #6b6156;

  /* La CARTA VERA — le stampe di b05, le polaroid di b09, l'Abzug di b07.
     Sono oggetti fisici appoggiati sulla pagina: su fondo crema devono
     restare più chiari del fondo, se no la pila sparisce. Separata da
     --paper proprio perché in zona chiara --paper cambia mestiere. */
  --print:     #fffdf8;

  /* GROUND UNICO — owner 17/08, screenshot dello stacco sabbia→crema fra
     b03 e b04: «il background deve essere SIMILE in tutte le sezioni».
     Da qui la sabbia NON è più un fondo di sezione: resta la superficie
     degli ELEMENTI (le vaschette delle immagini, le targhette) e, al
     massimo, questa velatura. È crema con il 12% di sabbia dentro:
     #f7f2e9 → ~#f5efe5, cioè 1,5 punti di luminanza relativa — sotto la
     soglia dei 2-3% che l'owner ha fissato, quindi niente gradino. */
  --ground-2: color-mix(in srgb, var(--sand) 12%, var(--cream));

  /* Testo che, DENTRO una sezione chiara, poggia su un'immagine scura (le
     macro della fotobox, la didascalia sul ritratto, il fumetto «Ziehen»
     sul girato). `.theme-light` ripunta --paper sull'inchiostro: questi
     casi hanno bisogno di un token che NON si ripunti mai. */
  --on-dark:   #F2ECE3;

  /* TYPE SYSTEM v2 — LEGGE §TYPE. DM Serif Display non ha pesi: è 400 e
     basta, quindi ogni `font-weight:700` ereditato da Barlow va corretto a
     400 o diventa un finto grassetto sintetico. */
  --font-display: "DM Serif Display", Georgia, "Times New Roman", serif;
  --font-body:    "Jost", system-ui, sans-serif;
  --font-mono:    "IBM Plex Mono", ui-monospace, monospace;

  /* scala delle durate — MOTION-HANDOFF-2026-08-13.md §Duration scale */
  --d-utility:  100ms;
  --d-snap:     250ms;
  --d-photo:    400ms;
  --d-flow:     800ms;
  --d-ambient: 1200ms;
}

/* ---- ZONA CHIARA ----------------------------------------------------
   Il flip non riscrive 60 dichiarazioni: RIPUNTA i token semantici dentro
   le sezioni marcate `.theme-light` (b03, b05, b06, b07, b09 e l'overlay
   del menu mobile). Tutto ciò che dentro quelle sezioni diceva
   `var(--paper)` diceva in realtà «colore del testo»: qui quel colore
   diventa l'inchiostro. Stesso ragionamento per --bg (fondo), --shadow
   (superficie rialzata), --gold (accento) e --wood (filetto).
   Le ECCEZIONI sono quelle in cui --paper voleva dire carta davvero:
   stanno più sotto, sezione per sezione, e usano --print.
   Restano DARK e fuori da questo blocco: SOLO il loader e b01 (tutto il
   pin). b04 è passata al chiaro il 17/08 (owner: «same color chiaro delle
   altre») e col flip è caduto anche il suo dimmer ai bordi. */
.theme-light{
  --bg:     var(--cream);
  --shadow: var(--sand);
  --wood:   var(--line);
  --gold:   var(--gold-deep);   /* su crema l'oro chiaro non passa AA sul corpo */
  --paper:  var(--ink);
  background:var(--cream);
  color:var(--ink);
}

*,*::before,*::after{ box-sizing:border-box; }

html{ background:var(--cream); }

body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:var(--font-body);
  font-weight:300;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

/* Il fondo dell'hero è la CARTA (18/08): col piano sequenza della reflex è
   uscita anche l'unica sezione scura del sito. --bg è già crema, la regola
   resta perché l'immagine è cover-fit e ai rapporti estremi scopre i bordi. */
[data-beat="01"]{ background:var(--bg); }

/* ---- Beats ---------------------------------------------------------- */
.beat{
  position:relative;
  min-height:calc(var(--h,100) * 1svh);
  width:100%;
}

/* Sticky pin wrapper — canvases fill it 100%. Beat tasks own the real
   ScrollTrigger pin; sticky just keeps the canvas on-screen in the chassis. */
.pin{
  position:sticky;
  top:0;
  /* 100lvh, non svh (legge banda-bianca 18/08): a toolbar Safari collassata
     un pin svh lascia scoperta una striscia sotto la scena */
  height:100lvh;
  width:100%;
  overflow:hidden;
}

/* === section:b01-ring — HERO «DER RING» (18/08 sera-3) ================
   Il concept di Daniel, col SUO girato (2 clip Seedance web-app montate a
   movimento uniforme): mappa Alto Adige di carta → anello che cade, tac →
   la camera passa DENTRO l'anello → carta bianca. Poi le stampe vere
   atterrano sulla carta (motore Tisch). La sezione è la traccia; il .pin
   sopra è la scena incollata. reduced-motion/no-JS: hero statico di carta
   come prima (il canvas non parte, lo stage resta a opacity 0). */
[data-beat="01"]{
  /* V2 «Il terremoto» (Daniel 17:37): due clip (caduta 6s + crollo 7s),
     niente più coda-stampe — il freeze sul legno rustico consegna
     direttamente a b03 («si vede subito chi sono»). */
  --rdolly:200;   /* testa: il volo (svh di corsa) */
  /* coda (08/09, owner: «il video hero dopo fine scroll dovrebbe rimanere
     e non sparire»): il freeze su Daniel resta incollato e b03 — tirato
     su di 100lvh, §b03-cream — gli scorre SOPRA come un foglio di carta.
     La coda è quindi ≈ un viewport: 108 svh e non 100 perché su iPhone il
     foglio parte a −100lvh (toolbar collassata) e la traccia è in svh —
     gli 8 in più coprono il delta, così il foglio non entra prima che il
     volo sia finito. Pagina: la coda è RIUSATA dal foglio, non si somma. */
  --rdrop:108;
  height:calc(100lvh + (var(--rdolly) + var(--rdrop)) * 1svh);
}
@media (min-width:768px){
  [data-beat="01"]{ --rdolly:215; --rdrop:104; }
}
.b01ring__scrub{
  position:absolute;
  inset:0;
  z-index:1;
  overflow:hidden;
  pointer-events:none;
  opacity:0;              /* il ponte-frame la accende in js/ring.js */
  will-change:opacity;
}
.b01ring__scrub > canvas{
  display:block;
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
}
/* L'USCITA V2: nessun gradient crema — il freeze sul LEGNO RUSTICO è il
   piano su cui b03 si appoggia (il suo ::before è l'ultimo frame del
   girato: stesso pixel, zero cucitura). */
/* lo stage delle stampe: stessa geometria percentuale del Tisch — riusa
   .tprint/.tshadow/.tprint--wide così come sono */
.b01ring__stage{
  position:absolute;
  left:50%; top:50%;
  transform:translate(-50%,-50%);
  z-index:2;
  width:min(100% - 26px, 1320px, calc(88svh * 1.6));
  height:88svh;
  pointer-events:none;
  opacity:0;              /* senza JS le stampe non coprono il titolo */
}
@media (min-width:768px){
  .b01ring__stage{ width:min(100% - 96px, 1320px, calc(88svh * 1.6)); }
}
.b01-overlay{ z-index:3; }
/* LE STAMPE VIVE: un loop muted dei film veri dentro la cornice di carta.
   Nasce invisibile sopra la foto (che È il poster): compare solo quando
   il file esiste ed è decodificato (is-on da js/ring.js) — senza file la
   stampa resta una stampa, zero stati rotti. */
.tprint__media .rlive{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  opacity:0;
  transition:opacity .6s ease;
}
.tprint__media .rlive.is-on{ opacity:1; }
/* mobile (owner 16:40): sottotitolo mezzo trasparente sulle creste —
   inchiostro pieno e velo più alto. 22/08: pieno davvero (.86 → 1), che è
   la stessa regola dell'alone di carta in §b01-overlay — su un fondo che
   cambia di 70 livelli dentro una parola, ogni punto di trasparenza è una
   lettera in meno. */
.b01-sub .b01-line{ color:var(--ink); }
@media (max-width:767px){
  .b01-holder::after{ height:66%; }
}
@media (prefers-reduced-motion:reduce){
  [data-beat="01"]{ height:auto; }
  .pin{ height:100svh; }
  .b01ring__scrub,
  .b01ring__stage{ display:none; }
}

/* HERO DI CARTA (18/08) — al posto del canvas #cv-dive, rimosso col piano
   sequenza della reflex. Solo transform: la scala la scrive beats.js. */
.b01-paper{
  position:absolute;
  inset:0;
  display:block;
  overflow:hidden;
}
.b01-paper img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  transform-origin:50% 60%;
  will-change:transform;
  backface-visibility:hidden;
}

/* Placeholder structural labels — small + dim so the skeleton is legible */
.scene-label{
  position:absolute;
  left:clamp(16px, 4vw, 48px);
  bottom:clamp(16px, 4vw, 48px);
  z-index:2;
  font-family:var(--font-mono);
  font-size:12px;
  letter-spacing:.22em;
  color:rgba(242,236,227,.28);
  pointer-events:none;
}

/* ---- Beat 01 — dive title overlay ----------------------------------- */
/* Skeleton scene-label was scaffolding; the pinned canvas owns beat01 now */
[data-beat="01"] .scene-label{ display:none; }

.b01-overlay{
  position:absolute;
  inset:0;
  z-index:3;
  pointer-events:none;
}

/* Title block — lower-left over the canvas */
.b01-title{
  position:absolute;
  left:clamp(20px, 5vw, 72px);
  bottom:clamp(40px, 9vh, 104px);
  max-width:min(92vw, 900px);
  will-change:transform, opacity;
}
.b01-kicker{
  display:block;
  margin:0 0 clamp(10px, 1.4vh, 18px) 2px;
  font-family:var(--font-mono);
  font-size:clamp(10px, 1.15vw, 13px);
  letter-spacing:.34em;
  text-transform:uppercase;
  color:rgba(46,44,40,.72);
}
.b01-h1{
  margin:0;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.06;
  letter-spacing:-.005em;
  font-size:clamp(2.2rem, 7.5vw, 6rem);
  color:var(--ink);
  text-shadow:none;
}
.b01-dot{ color:var(--gold); }

/* Scroll cue — bottom-center hairline + mono label */
.b01-cue{
  position:absolute;
  left:50%;
  bottom:clamp(20px, 3.4vh, 40px);
  transform:translateX(-50%);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
}
.b01-cue__line{
  width:1px;
  height:clamp(28px, 5vh, 52px);
  background:linear-gradient(180deg, transparent, rgba(46,44,40,.55));
}
.b01-cue__label{
  font-family:var(--font-mono);
  font-size:11px;
  letter-spacing:.3em;
  color:rgba(46,44,40,.62);
}

@media (max-width:820px){
  .b01-title{
    left:clamp(16px, 5vw, 32px);
    bottom:clamp(64px, 12vh, 120px);
  }
  .b01-h1{ font-size:clamp(2.6rem, 15vw, 5rem); }
}

/* CTA pill rimossa (owner 2026-07-15) */

/* ---- Loader — osmo dropping-cards-loading-animation (port verbatim) ----
   Differenza dal crisp: il guscio `.loader` NON ha più `background`.
   Il fondo è un figlio (`[data-loading-background]`) perché deve scendere
   con yPercent:100 — se il colore stesse sul guscio non si scoprirebbe
   niente. Il fade di `.is-hidden` resta come rete di sicurezza e come
   unica uscita nel ramo reduced-motion. */
.loader{
  position:fixed;
  inset:0;
  z-index:100;
  pointer-events:none;              /* osmo: .loading-container */
  transition:opacity .6s ease, visibility .6s ease;
}
.loader.is-hidden{
  opacity:0;
  visibility:hidden;
  pointer-events:none;
}
/* scroll lock while loading (invariato) */
body:has(.loader:not(.is-hidden)){ overflow:hidden; }

/* RESKIN CARTA (owner 18/08 sera-4: «il preloader adattalo al nuovo tema»):
   via il buio Camera Oscura — il sipario è CREMA e le card che cadono sono
   STAMPE con il bordo di carta, la stessa grammatica di .tprint. Il
   meccanismo osmo dropping-cards resta identico. */
.loading-screen{
  pointer-events:auto;
  color:var(--ink);
  justify-content:center;
  align-items:center;
  width:100%;
  height:100%;
  display:flex;
  position:absolute;
  top:0;
  left:0;
  overflow:clip;                    /* card ruotate + fondo che scende */
}

.loading-screen__background{
  background-color:var(--cream);    /* la carta della pagina, non il buio */
  width:100%;
  height:100%;
  position:absolute;
  will-change:transform;
}

/* IL LOGO — centrato, rivelato in clip e poi ZOOMATO all'uscita
   (loader v3, owner 18/08 sera-4). Il transform lo scrive il JS. */
.loading-screen__logo{
  position:absolute;
  inset:0;
  display:grid;
  place-items:center;
  will-change:transform, opacity;
  pointer-events:none;
}
.loading-screen__logo img{
  display:block;
  width:clamp(120px, 18vw, 220px);
  height:auto;
  /* COME IN NAVBAR (owner 18/08 sera-8): logo.webp è oro + scritta BIANCA,
     nato per il fondo nero — sul sipario crema la scritta spariva. Stessa
     silhouette d'inchiostro della .dsnav (brightness 0 + opacity .82). */
  filter:brightness(0) saturate(0);
  opacity:.82;
  /* stato iniziale del reveal: chiuso a sinistra, il JS lo apre */
  clip-path:inset(0 100% 0 0);
}

.loader-pct{
  position:absolute;
  right:calc(20px + env(safe-area-inset-right, 0px));
  bottom:calc(18px + env(safe-area-inset-bottom, 0px));
  z-index:3;
  font-family:var(--font-mono);
  font-size:.78rem;
  letter-spacing:.22em;
  color:var(--gold-deep);           /* su crema l'oro chiaro non passa */
  font-variant-numeric:tabular-nums;
  pointer-events:none;
  will-change:transform, opacity;
}
.loader-pct::after{
  content:"%";
  margin-left:.28em;
  opacity:.55;
}
@media (max-width:820px){
  .loader-pct{ font-size:.7rem; right:14px; bottom:14px; }
}

/* nav + hero copy live BEHIND the loader until it finishes (invariato —
   cambia solo il selettore: .mega-nav è diventata .dsnav in Fase A2).
   Le transizioni di opacity/transform stanno sul guscio in §section:nav
   insieme a quella della scala, qui restano solo i due stati. */
.dsnav{
  opacity:0;
  transform:translateY(-14px);
}
.loader.is-hidden ~ .dsnav{
  opacity:1;
  transform:none;
}

/* reduced-motion: nessuna card, il fondo sfuma e via.
   NB: il build oggi ha `.loader{transition:none}` qui dentro; va tolto,
   altrimenti «sfuma» diventa «sparisce di scatto». */
@media (prefers-reduced-motion:reduce){
  .loader{ transition:opacity .4s linear, visibility .4s linear; }
  .loading-screen__logo img{ clip-path:none; }
  .dsnav{ opacity:1; transform:none; transition:none; }
}


/* ==================================================================
   SECTION FRAGMENTS (studio-page loop assembly)
   ================================================================== */


/* === section:nav === */
/* ======================================================================
   NAV — FASE A2 (2026-08-17). La meganav (Home / Für Unternehmen / Für
   Brautpaare / Kontakt + dropdown + overlay sala buia) è STATA BUTTATA.
   Al suo posto, porting osmo — niente scritto a mano:

     · desktop ≥769  → osmo `centered-scaling-navigation-bar`
                       (card centrata con lo strato di fondo separato
                       .dsnav__bg, header in em, toggle a due barre)
                       in variante STICKY COMPATTA.
     · mobile  ≤768  → osmo `scaling-hamburger-navigation`
                       (il pannello CRESCE dal bottone: il fondo passa
                       dall'altezza dell'header al 100% e il gruppo da
                       scale(.15) con origine 100% 0 a scale(1)).
     · CTA           → osmo `button-062` (bg che scala in hover, onda dei
                       caratteri; lo split dei char è fatto a mano in
                       js/meganav.js, SplitText non è nel vendor).

   LA SCALA, CIOÈ IL «SCALING» DELLA RICETTA
   La ricetta osmo è interamente in em. Quindi la barra non si "compatta"
   riscrivendo venti misure: cambia UN font-size (--dsnav-fs) sul guscio e
   tutto dentro rimpicciolisce insieme, transizione compresa. È lo stesso
   meccanismo dello scaling osmo, agganciato allo scroll invece che al
   toggle.

   I DUE STATI (LEGGE §NAV)
     18/08: l'hero non è più scuro (il piano sequenza della reflex è uscito,
     al suo posto il diorama di carta), quindi lo stato «link bianchi sul
     buio» non ha più un buio su cui stare. I DUE STATI ora si distinguono
     per SCALA e per peso del fondo, non per colore del testo:
     · sopra l'hero (b01)           → card larga, fondo carta appena velato,
       testo --ink, nessuna hairline: la barra galleggia sulla carta.
     · dopo l'hero (html.nav-past)  → card compatta, fondo crema pieno con
       blur leggero, hairline --line sotto.
   L'interruttore è la fine di b01 misurata da ScrollTrigger, non un
   numero di pixel (js/meganav.js § initNavState).

   ALTEZZA DELLA PAGINA: zero (L11). Tutto è position:fixed dentro un
   guscio che non entra nel flusso.
   ====================================================================== */

.dsnav{
  /* --- la scala e i colori dello STATO SOPRA L'HERO ------------------ */
  --dsnav-fs:      16px;
  --dsnav-top:     1.15em;
  --dsnav-radius:  .75em;
  --dsnav-w:       min(72em, calc(100vw - 2.5em));
  --dsnav-pad:     .85em 1em .85em 1.25em;
  --dsnav-logo-h:  2.5em;
  --dsnav-fg:      var(--ink);
  --dsnav-fg-dim:  var(--muted);
  --dsnav-surface: rgba(247,242,233,.55);
  --dsnav-hair:    transparent;
  --dsnav-shadow:  none;

  position:fixed;
  inset:0;
  z-index:100;
  pointer-events:none;          /* il guscio è tutto lo schermo: i figli si riprendono gli eventi */
  font-size:var(--dsnav-fs);
  color:var(--dsnav-fg);
  transition:font-size .55s var(--ease-osmo),
             color     .35s linear,
             opacity   .7s  var(--ease-osmo),
             transform .7s  var(--ease-osmo);
}

/* --- STATO «DOPO L'HERO» ---------------------------------------------
   La card scende di scala (16px → 14.5px = tutto il resto con lei), il
   fondo diventa carta e il testo inchiostro. */
html.nav-past .dsnav{
  --dsnav-fs:      14.5px;
  --dsnav-top:     .6em;
  --dsnav-w:       min(66em, calc(100vw - 1.6em));
  --dsnav-pad:     .5em .6em .5em 1em;
  --dsnav-logo-h:  2em;
  --dsnav-fg:      var(--ink);
  --dsnav-fg-dim:  var(--muted);
  /* .92 e non .88: la card attraversa foto scure a tutta larghezza (il
     ritratto di b03, i poster di b04) e sotto gli .88 la barra si legge a
     due toni — metà carta, metà foto. Il vetro resta, il bicolore no. */
  --dsnav-surface: rgba(247,242,233,.92);
  --dsnav-hair:    var(--line);
  --dsnav-shadow:  0 10px 30px rgba(46,44,40,.10);
}

/* A menu aperto la card è carta a prescindere da dove sta la pagina:
   dentro ci sono sei righe d'inchiostro, non due glifi sul buio. */
.dsnav[data-navigation-status="active"]{
  --dsnav-fg:      var(--ink);
  --dsnav-fg-dim:  var(--muted);
  --dsnav-surface: rgba(247,242,233,.97);
  --dsnav-hair:    var(--line);
  --dsnav-shadow:  0 24px 60px rgba(46,44,40,.18);
}

/* scrim osmo (.navigation__dark-bg) — vive solo col menu aperto */
.dsnav__dark-bg{
  position:absolute;
  inset:0;
  background-color:#0B0A09;
  opacity:0;
  visibility:hidden;
  pointer-events:auto;
  transition:all .7s cubic-bezier(.5,.5,0,1);
}
.dsnav[data-navigation-status="active"] .dsnav__dark-bg{
  opacity:.34;
  visibility:visible;
}

/* --- la card (osmo .centered-nav) ------------------------------------ */
.dsnav__card{
  position:absolute;
  top:var(--dsnav-top);
  left:50%;
  transform:translateX(-50%);
  width:var(--dsnav-w);
  display:flex;
  flex-flow:column;
  align-items:stretch;
  border-radius:var(--dsnav-radius);
  transition:top   .55s var(--ease-osmo),
             width .55s var(--ease-osmo);
}

/* strato di fondo separato: è quello che nella ricetta hamburger CRESCE
   dal bottone. Qui è il fondo della card e cambia pelle coi due stati. */
.dsnav__bg{
  position:absolute;
  inset:0;
  border-radius:var(--dsnav-radius);
  background-color:var(--dsnav-surface);
  box-shadow:var(--dsnav-shadow);
  transition:background-color .45s linear,
             box-shadow       .45s linear;
}
/* il blur costa a ogni frame del gesto: si accende solo dove c'è un
   puntatore (desktop), sul telefono il fondo è più pieno e basta. */
@media (hover:hover) and (pointer:fine){
  html.nav-past .dsnav__bg{
    -webkit-backdrop-filter:blur(14px) saturate(125%);
            backdrop-filter:blur(14px) saturate(125%);
  }
}
/* hairline sotto la barra (bordo inferiore della card) */
.dsnav__bg::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:0;
  height:1px;
  background:var(--dsnav-hair);
  transition:background-color .45s linear;
}

/* --- header (osmo .centered-nav__header) ------------------------------ */
.dsnav__header{
  position:relative;
  z-index:1;
  display:flex;
  align-items:center;
  gap:1em;
  padding:var(--dsnav-pad);
  transition:padding .55s var(--ease-osmo);
}

.dsnav__logo{
  pointer-events:auto;
  display:flex;
  align-items:center;
  flex:none;
  text-decoration:none;
  border-radius:.35em;
  /* target ≥44px: l'immagine resta della sua altezza, è la zona
     cliccabile a crescere (audit touch-target 390pt, 17/08). */
  min-height:44px;
}
.dsnav__logo img{
  display:block;
  width:auto;
  height:var(--dsnav-logo-h);
  transition:height .55s var(--ease-osmo), filter .35s linear, opacity .35s linear;
}
/* IL LOGO SULLA CARTA — assets/logo.webp è oro + scritta BIANCA, nato per
   il fondo nero: su crema la metà bianca sparisce. Finché non c'è la
   variante monocroma, in stato chiaro si legge come silhouette
   d'inchiostro (sulla carta i marchi si stampano in un colore solo).
   L'opacità .82 è il valore che su #f7f2e9 restituisce ~#2e2c28 = --ink.
   TODO — CHIEDERE A DANIEL: logo one-color / versione scura. */
/* 18/08: vale ANCHE sopra l'hero, che ora è carta e non più buio — la metà
   bianca del marchio ci sparirebbe dentro. */
.dsnav__logo img,
html.nav-past .dsnav__logo img,
.dsnav[data-navigation-status="active"] .dsnav__logo img{
  filter:brightness(0) saturate(0);
  opacity:.82;
}

/* --- rail desktop (le quattro ancore) --------------------------------- */
.dsnav__rail{
  display:flex;
  align-items:center;
  gap:.35em;
  margin:0 auto 0 1.5em;
  padding:0;
  list-style:none;
}
.dsnav__rail li{ margin:0; padding:0; }

/* .dsnav__a = osmo .hamburger-nav__a: link + hairline che si disegna
   (::after scaleX) e testo che scorre dentro la maschera. */
.dsnav__a{
  pointer-events:auto;
  position:relative;
  display:flex;
  align-items:center;
  gap:.6em;
  padding:.5em .7em;
  color:inherit;
  text-decoration:none;
  border-radius:.3em;
}
.dsnav__a::after{
  content:"";
  position:absolute;
  left:.7em; right:.7em; bottom:.28em;
  height:1px;
  background:currentColor;
  opacity:.25;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform .6s cubic-bezier(.65,0,0,1);
}
.dsnav__a[aria-current]::after{ transform:scaleX(1); opacity:1; }
@media (hover:hover) and (pointer:fine){
  .dsnav__a:hover::after{ transform:scaleX(1); opacity:.45; }
}
.dsnav__a:focus-visible{ outline:2px solid var(--gold2); outline-offset:2px; }

.dsnav__p{
  margin:0;
  font-family:var(--font-body);
  font-weight:400;
  font-size:.94em;
  letter-spacing:.09em;
  text-transform:uppercase;
  line-height:1.2;
  white-space:nowrap;
}
.dsnav__num{
  font-family:var(--font-mono);
  font-size:.62em;
  letter-spacing:.14em;
  color:var(--dsnav-fg-dim);
  transition:color .35s linear;
}

/* --- CTA — osmo button-062 skin oro ----------------------------------- */
.dsnav__cta{
  --button-062-color:            var(--ink);
  --button-062-color-background: var(--gold2);
  --button-062-color-focus:      var(--gold-deep);
  --button-062-padding:          .95em 1.5em .85em;
  min-height:44px;                 /* target pollice, audit 390pt 17/08 */
  --button-062-border-radius:    999px;
  --button-062-focus-inset:      -.2em;
  --button-062-hover-scale:      1.045 1.09;
  --button-062-click-scale:      .965, .93;
  --button-062-ease-click:       cubic-bezier(.4,0,.2,1);
  --button-062-ease-hover:       cubic-bezier(.625,.05,0,1);
  --button-062-ease-focus:       cubic-bezier(.32,.72,0,1);

  pointer-events:auto;
  flex:none;
  margin-left:auto;
  -webkit-user-select:none; user-select:none;
  color:var(--button-062-color);
  background-color:transparent;
  outline-style:none;
  padding:0;
  line-height:1;
  text-decoration:none;
  display:inline-grid;
  position:relative;
  -webkit-tap-highlight-color:transparent;
  transition:opacity .3s linear;
}
.dsnav__cta::after{
  content:"";
  display:block;
  position:absolute;
  inset:var(--button-062-focus-inset);
  border-radius:var(--button-062-border-radius);
  transition:box-shadow .3s var(--button-062-ease-focus),
             scale      .45s var(--button-062-ease-hover);
  pointer-events:none;
  z-index:1;
}
.dsnav__cta:is(:focus-visible)::after{
  box-shadow:0 0 0 .125em var(--button-062-color-focus);
  scale:var(--button-062-hover-scale);
}
.dsnav__cta:active .button-062__bg{ transform:scale(var(--button-062-click-scale)); }
.button-062__bg{
  grid-area:1/1;
  width:100%; height:100%;
  padding:0;
  border-radius:var(--button-062-border-radius);
  background-color:var(--button-062-color-background);
  transition:scale .45s var(--button-062-ease-hover),
             transform .15s var(--button-062-ease-click);
}
.button-062__inner{
  grid-area:1/1;
  z-index:1;
  display:flex;
  align-items:center;
  justify-content:center;
  gap:.125em;
  width:100%; height:100%;
  padding:var(--button-062-padding);
  pointer-events:none;
  overflow:clip;               /* l'onda dei char non deve uscire dalla pillola */
}
.button-062__text{
  font-family:var(--font-body);
  font-weight:500;
  font-size:.8em;
  letter-spacing:.14em;
  text-transform:uppercase;
  white-space:nowrap;
}
.button-062__split-char{ display:inline-block; }
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .dsnav__cta:is(:hover,:focus-visible) .button-062__bg{ scale:var(--button-062-hover-scale); }
}
/* due etichette, una sola pillola: sul telefono il tedesco lungo non ci sta */
.dsnav__cta-short{ display:none; }

/* --- toggle (osmo due barre) ------------------------------------------ */
.dsnav__toggle{
  display:none;                /* desktop: le voci sono già a vista */
  pointer-events:auto;
  cursor:pointer;
  position:relative;
  flex:none;
  align-items:center;
  justify-content:center;
  width:2.75em; height:2.75em;
  min-width:44px; min-height:44px;   /* target touch (L10) */
  padding:0;
  border:0;
  border-radius:50%;
  background-color:rgba(200,169,110,.16);
  -webkit-tap-highlight-color:transparent;
  transition:background-color .35s linear, transform .7s cubic-bezier(.5,.5,0,1);
}
.dsnav__toggle-bar{
  position:absolute;
  width:38%;
  height:1.5px;
  background-color:currentColor;
  transition:transform .7s cubic-bezier(.5,.5,0,1);
  transform:translateY(-.18em) rotate(.001deg);
}
.dsnav__toggle-bar:nth-child(2){ transform:translateY(.18em) rotate(.001deg); }
@media (hover:hover) and (pointer:fine){
  .dsnav__toggle:hover .dsnav__toggle-bar{ transform:translateY(.18em) rotate(.001deg); }
  .dsnav__toggle:hover .dsnav__toggle-bar:nth-child(2){ transform:translateY(-.18em) rotate(.001deg); }
}
[data-navigation-status="active"] .dsnav__toggle-bar{ transform:translateY(0) rotate(45deg); }
[data-navigation-status="active"] .dsnav__toggle-bar:nth-child(2){ transform:translateY(0) rotate(-45deg); }
.dsnav__toggle:focus-visible{ outline:2px solid var(--gold2); outline-offset:2px; }

/* --- pannello (drawer osmo: grid-template-rows 0fr → 1fr) -------------- */
.dsnav__panel{
  position:relative;
  display:grid;
  grid-template-rows:0fr;
  overflow:hidden;
  border-bottom-left-radius:var(--dsnav-radius);
  border-bottom-right-radius:var(--dsnav-radius);
  transition:grid-template-rows .6s cubic-bezier(.625,.05,0,1);
}
[data-navigation-status="active"] .dsnav__panel{ grid-template-rows:1fr; }

.dsnav__panel-inner{ overflow:hidden; min-height:0; }

/* il GRUPPO è il pezzo della ricetta scaling-hamburger: cresce dal
   bottone (origine in alto a destra) invece di comparire. */
.dsnav__group{
  pointer-events:auto;
  display:flex;
  flex-flow:column;
  gap:1em;
  padding:.25em 1.15em 1.15em;
  transform-origin:100% 0;
  transform:scale(.15) rotate(.001deg);
  opacity:0;
  visibility:hidden;
  transition:opacity .5s cubic-bezier(.5,.5,0,1),
             visibility .5s cubic-bezier(.5,.5,0,1),
             transform .7s cubic-bezier(.5,.5,0,1);
}
[data-navigation-status="active"] .dsnav__group{
  transform:scale(1) rotate(.001deg);
  opacity:1;
  visibility:visible;
}

.dsnav__panel-label{
  margin:0;
  font-family:var(--font-mono);
  font-size:.66em;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--dsnav-fg-dim);
}

.dsnav__list{
  display:flex;
  flex-flow:column;
  gap:.1em;
  margin:0;
  padding:0;
  list-style:none;
}
.dsnav__list li{ margin:0; padding:0; }
/* riga del menu: target 52px pieni, il numero fa da indice di pagina e il
   pallino osmo marca dove si è. */
.dsnav__list .dsnav__a{
  justify-content:space-between;
  min-height:52px;
  padding:.35em .1em;
  gap:.75em;
}
.dsnav__list .dsnav__a::after{ left:.1em; right:.1em; bottom:.2em; }
.dsnav__list .dsnav__p{
  font-family:var(--font-display);
  font-weight:400;
  font-size:1.75em;
  letter-spacing:0;
  text-transform:none;
}
.dsnav__list .dsnav__num{ font-size:.7em; }
.dsnav__row{ display:flex; align-items:baseline; gap:.9em; }

.dsnav__dot{
  flex:none;
  width:.5em; height:.5em;
  border-radius:50%;
  background-color:currentColor;
  opacity:.5;
  transform:scale(0) rotate(.001deg);
  transition:transform .7s cubic-bezier(.5,.5,0,1);
}
.dsnav__a[aria-current] .dsnav__dot{ transform:scale(1) rotate(.001deg); opacity:1; }

/* banner CTA del menu (osmo .centered-nav__banner + marquee CSS) */
.dsnav__banner{
  pointer-events:auto;
  display:block;
  overflow:hidden;
  max-width:100%;
  padding:1.1em 0;
  border-radius:.4em;
  color:var(--ink);
  background-color:var(--gold2);
  text-decoration:none;
  min-height:48px;
  transition:background-color .15s;
}
.dsnav__banner:active{ background-color:var(--gold-deep); }
.dsnav__banner-row{ display:flex; align-items:center; }
.dsnav__banner-item{ flex:none; display:flex; align-items:center; }
.dsnav__banner-inner{ flex:none; display:flex; align-items:center; padding-right:2em; }
.dsnav__banner-text{
  margin:0;
  font-family:var(--font-mono);
  font-size:.78em;
  font-weight:400;
  line-height:1;
  letter-spacing:.14em;
  text-transform:uppercase;
}
@keyframes dsnavMarquee{ to{ transform:translateX(-100%); } }
[data-dsnav-marquee]{
  /* 1s di ritardo: all'apertura la CTA si legge ferma per un secondo e
     POI parte. Senza, il pannello si apre su una scritta già tagliata a
     metà — la prima cosa che si legge è mezza parola. */
  animation:dsnavMarquee 22s linear 1s infinite;
  animation-play-state:paused;
}
[data-navigation-status="active"] [data-dsnav-marquee]{ animation-play-state:running; }

/* --- progress hairline oro (scroll della pagina) ---------------------- */
.dsnav__progress{
  position:absolute;
  left:0; right:0; bottom:0;
  height:2px;
  overflow:hidden;
  border-bottom-left-radius:var(--dsnav-radius);
  border-bottom-right-radius:var(--dsnav-radius);
  pointer-events:none;
  z-index:2;
}
.dsnav__progress i{
  display:block;
  width:100%; height:100%;
  background:linear-gradient(90deg, var(--gold2), var(--gold-deep));
  transform:scaleX(var(--nav-progress, 0));
  transform-origin:left center;
}
/* la hairline esce di scena: il progresso ora lo racconta L'ANELLO (sotto).
   Due indicatori della stessa cosa nella stessa barra = rumore. Per
   tornare indietro basta togliere questa riga. */
.dsnav__progress{ display:none; }

/* ==== L'ANELLO DI SCROLL =============================================
   Il filo rosso della pagina è l'anello dell'hero; qui si disegna in oro
   col progresso di scroll: 0 in cima, cerchio chiuso in fondo. NESSUN JS
   NUOVO: legge --nav-progress, che js/meganav.js scrive già sul root per
   la vecchia hairline. pathLength=1 rende la dasharray unitless, il
   -90deg fa partire il tratto da ore 12. Su mobile vive sul bordo del
   burger (che è già un cerchio); su desktop, dove il burger non c'è,
   sta da solo accanto alla CTA. */
.dsnav__ring{
  position:absolute; inset:0;
  width:100%; height:100%;
  transform:rotate(-90deg);
  pointer-events:none;
}
.dsnav__ring circle{
  fill:none;
  stroke:var(--gold-deep);
  stroke-width:2;
  stroke-linecap:round;
  stroke-dasharray:1;
  stroke-dashoffset:calc(1 - var(--nav-progress, 0));
}
.dsnav__ring-solo{
  position:relative;
  flex:none;
  width:20px; height:20px;
  margin-right:clamp(10px, 1.1vw, 16px);
  /* la traccia spenta sotto il tratto: si vede dove l'anello arriverà */
}
.dsnav__ring-solo::before{
  content:"";
  position:absolute; inset:0;
  border-radius:50%;
  border:2px solid color-mix(in srgb, var(--gold-deep) 22%, transparent);
}
@media (max-width:768px){ .dsnav__ring-solo{ display:none; } }

/* ======================================================================
   MOBILE ≤768 — osmo scaling-hamburger-navigation
   Barra: logo + pillola ANFRAGE + hamburger (stessa terna dello stato
   precedente, vedi qa/shots-20260817-faseA/mob-01-top.png). Le quattro
   ancore vivono nel pannello, con indice numerato: sul telefono la pagina
   è lunga e l'unico wayfinding era lo scroll (feedback Daniel).
   ====================================================================== */
@media (max-width:768px){
  .dsnav{
    --dsnav-top:  .75em;
    --dsnav-w:    calc(100vw - 1.5em);
    --dsnav-pad:  .55em .6em .55em .85em;
  }
  html.nav-past .dsnav{
    --dsnav-top:  .5em;
    --dsnav-w:    calc(100vw - 1.1em);
    --dsnav-pad:  .45em .5em .45em .8em;
  }
  .dsnav__rail{ display:none; }
  .dsnav__toggle{ display:flex; }
  .dsnav__cta{
    --button-062-padding:.9em 1.15em .8em;
    min-height:44px;
    margin-left:auto;
    margin-right:.5em;
  }
  .dsnav__cta-full{ display:none; }
  .dsnav__cta-short{ display:inline; }
  /* a menu aperto la pillola sparisce: due uscite sovrapposte (X e CTA)
     nello stesso angolo sono un bersaglio ambiguo per il pollice, e la
     CTA riappare come banner in fondo al pannello. */
  .dsnav[data-navigation-status="active"] .dsnav__cta{
    opacity:0;
    pointer-events:none;
  }
}

/* LE ALTRE PAGINE DEL SITO (24/09): mono piccolo dopo una hairline, colore
   dim → pieno in hover; nel pannello mobile diventano pillole. */
.dsnav__site{
  display:flex; align-items:center; gap:.15em;
  margin:0 0 0 .5em; padding:0 0 0 .8em;
  list-style:none;
  border-left:1px solid color-mix(in srgb, currentColor 18%, transparent);
}
.dsnav__site li{ margin:0; padding:0; }
.dsnav__site-a{
  display:inline-flex; align-items:center;
  min-height:44px; padding:.5em .55em;
  font-family:var(--font-mono); font-size:.62em; letter-spacing:.16em; text-transform:uppercase;
  color:var(--dsnav-fg-dim); text-decoration:none; white-space:nowrap;
  pointer-events:auto;
  transition:color .25s linear;
}
.dsnav__site-a:hover, .dsnav__site-a:focus-visible{ color:var(--dsnav-fg); }
@media (max-width:1119px){ .dsnav__site{ display:none; } }
.dsnav__group--site{ padding-top:0; }
.dsnav__site-list{ display:flex; flex-flow:row wrap; gap:.35em .4em; margin:0; padding:0; list-style:none; }
.dsnav__site-list li{ margin:0; padding:0; }
.dsnav__site-list .dsnav__site-a{
  font-size:.66em; padding:.6em .85em; min-height:40px;
  border:1px solid color-mix(in srgb, currentColor 22%, transparent); border-radius:999px;
}
.dsnav__site-list .is-current{ color:var(--dsnav-fg); border-color:currentColor; cursor:default; }

/* desktop: il pannello non esiste (le voci sono nel rail) */
@media (min-width:769px){
  .dsnav__panel{ display:none; }
}

/* LA FASCIA STRETTA DEL DESKTOP (769–1119)
   Misura, non gusto: a 769px la card vale ~743px e dentro ci devono stare
   logo (~85) + quattro voci (~430) + CTA «Wunschtermin anfragen» (~237)
   + i gap. Fa 770 e straborda. Qui la CTA torna corta come sul telefono e
   il rail si stringe: sono le stesse due leve, non un layout terzo. */
@media (min-width:769px) and (max-width:1119px){
  .dsnav__cta-full{ display:none; }
  .dsnav__cta-short{ display:inline; }
  .dsnav__cta{ --button-062-padding:.9em 1.25em .8em; }
  .dsnav__rail{ margin-left:1em; gap:0; }
  .dsnav__a{ padding:.5em .55em; }
  .dsnav__p{ font-size:.86em; letter-spacing:.07em; }
  .dsnav__num{ font-size:.58em; }
}

/* schermi bassi: le voci si stringono, il pannello non deve mai scrollare */
@media (max-width:768px) and (max-height:680px){
  .dsnav__list .dsnav__p{ font-size:1.45em; }
  .dsnav__list .dsnav__a{ min-height:46px; }
  .dsnav__group{ gap:.75em; }
}

/* blocco scroll senza salto (menu aperto): la posizione resta dov'era e il
   gutter della scrollbar viene restituito come padding. */
html.nav-locked, html.nav-locked body{
  overflow:hidden;
  touch-action:none;
}
html.nav-locked body{ padding-right:var(--nav-lock-gutter, 0px); }

/* ---- REDUCED MOTION --------------------------------------------------
   La nav deve FUNZIONARE senza animazioni: niente opacity:0 che resta
   appeso a una transizione mai partita. Qui si azzerano le durate (gli
   stati finali sono comunque scritti in CSS, quindi il menu apre e chiude
   di scatto) e si spegne il marquee. */
@media (prefers-reduced-motion:reduce){
  .dsnav, .dsnav *{
    transition-duration:.001ms !important;
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
  }
  .dsnav__group{ transform:none; }
  [data-dsnav-marquee]{ animation:none; }
}

/* === section:b01-overlay === */
/* ---- Beat 01 — dive title overlay (restyle) ------------------------- */
[data-beat="01"] .scene-label{ display:none; }

/* Lo z-index:6 sul pin è RIMOSSO (2026-08-13): serviva a tenere l'hero SOPRA
   b03 mentre b03 saliva dietro il pin durante l'handoff. Senza handoff — e
   con il pin che ora finisce a 'bottom bottom' — le due sezioni non si
   sovrappongono mai, e un pin sopra il flusso era esattamente ciò che si
   leggeva come «b03 parte da sotto la sezione». */

/* pointer-events:none sul pin: dentro non c'è niente di cliccabile (canvas,
   copy di volo e cue sono decorativi) e così non può mai rubare un click alle
   sezioni vicine. Non tocca lo scroll: pointer-events non intercetta il gesto
   di scorrimento. */
[data-beat="01"] .pin{ pointer-events:none; }

/* ---- LA FASCIA NERA IN BASSO SU IPHONE: tentativo RITIRATO ------------
   2026-08-14, provato e tolto lo stesso giorno (owner: «prima era più
   figo»). Il pin dell'hero passava a 100lvh su touch, con l'overlay tenuto
   a 100svh, per coprire i ~60-90px che Safari scopre quando ritrae le
   barre. Tappava la fascia nera ma cambiava l'inquadratura dell'hero sul
   telefono: il canvas è cover-fit, quindi un box più alto ritaglia più
   larghezza e il piano sequenza si legge diverso.
   Il pin resta quindi 100svh (regola generica .pin, in testa al file).
   Se la fascia nera va ripresa in mano, il prossimo tentativo NON è
   rialzare il pin: è tenere il canvas a 100lvh DENTRO un pin da 100svh
   (overflow visibile solo in basso), così l'inquadratura non si muove. */

.b01-holder{
  position:absolute;
  inset:0;
  z-index:2;
  overflow:hidden;
  will-change:transform, opacity;
  backface-visibility:hidden;
}

/* VELO DI BASE — il lockup vive in basso a sinistra, e lì il diorama ha il
   primo piano scuro (la carta bruna in ombra): l'inchiostro del titolo ci
   moriva sopra a 390. Un velo crema, non un'ombra scura: si schiarisce la
   carta sotto il testo invece di annerirla, e la coppia ritagliata resta
   visibile perché il velo si ferma a .58. Sta sotto l'overlay (z 3) e sopra
   l'immagine. */
/* owner 18/08 sera-4 («testo andrà sistemato per essere letto»): sul girato
   della mappa le creste brune passano sotto l'H1 — il velo sale di corpo
   (.42→.60 / .72→.86) e SEGUE il titolo: --titleveil la scrive js/ring.js
   sullo stesso progresso con cui l'H1 esce, così durante il volo il video
   non resta velato a vuoto. */
.b01-holder::after{
  content:"";
  position:absolute;
  inset:0 0 auto 0;
  /* SOPRA il canvas dello scrub (z1): con z auto il girato dipingeva
     sopra il velo e il titolo restava nudo sulle creste */
  z-index:2;
  height:58%;
  background:linear-gradient(180deg, rgba(247,242,233,.9), rgba(247,242,233,.55) 52%, rgba(247,242,233,0));
  opacity:var(--titleveil, 1);
  pointer-events:none;
}

.b01-overlay{
  position:absolute;
  inset:0;
  z-index:3;
  pointer-events:none;
  --b01-pad-x: clamp(20px, 5vw, 72px);
}

/* Exit group — beats.js fades/scales THIS block (both selectors resolve here) */
.b01-title,
.b01-title-wrap{
  position:absolute;
  inset:0;
  max-width:none;        /* la regola base la teneva a 900px: con il titolo
                            nuovo (30 caratteri sulla riga lunga) andava a
                            capo già a 1440. Il limite ora è il padding. */
  transform-origin:0% 100%;
  will-change:transform, opacity;
}

.b01-kicker{
  position:absolute;
  top:clamp(22px, 4.2vh, 44px);
  left:var(--b01-pad-x);
  margin:0;
}
.b01-kicker .b01-line{
  font-family:var(--font-mono);
  font-weight:400;
  font-size:clamp(11px, 0.86vw, 12px);
  letter-spacing:.18em;
  text-transform:uppercase;
  color:rgba(46,44,40,.74);
}

.b01-headline{
  position:absolute;
  left:var(--b01-pad-x);
  right:var(--b01-pad-x);
  /* IN ALTO, non più in basso (owner 18/08 sera-4: «come sistemiamo il
     testo?»): al frame 1 del girato la mappa sta al centro-basso e il
     CIELO di carta in alto è vuoto — il titolo vive lì e non lotta più
     con le creste. Il clamp tiene la riga sotto la meganav. */
  top:clamp(104px, 16lvh, 190px);
  bottom:auto;
  max-width:none;
}
/* ==== IL TITOLO IN BASSO — variante A/B (owner 22/08) ==================
   «Spacca così, solo che il testo non saprei dove posizionarlo».
   Le due posizioni che la misura del fotogramma 1 ammette sono la fascia
   ALTA (media 242, dev 1) e la fascia BASSA (media 225, dev 3): sono le
   uniche due strisce di carta vuota: in mezzo ci sono le creste, dove il
   fondo cambia di ~70 livelli dentro una parola.
   Di default vale quella alta (com'è ora). Aprendo la pagina con `?t=b`
   il titolo scende nella fascia bassa e il velo si ribalta con lui: due
   inquadrature vere da confrontare sul telefono, senza due deploy.
   Quando l'owner sceglie, resta una sola regola e questa esce. */
[data-title-pos="bottom"] .b01-headline{
  top:auto;
  /* sopra le pill, che restano dove sono: (fondo pill) + altezza + aria */
  bottom:calc((100lvh - 100svh) + clamp(96px, 14svh, 170px));
}
[data-title-pos="bottom"] .b01-holder::after{
  inset:auto 0 0 0;
  height:62%;
  background:linear-gradient(0deg, rgba(247,242,233,.92), rgba(247,242,233,.55) 46%, rgba(247,242,233,0));
}
@media (max-width:767px){
  [data-title-pos="bottom"] .b01-headline{
    bottom:calc((100lvh - 100svh) + clamp(120px, 18svh, 210px));
  }
  [data-title-pos="bottom"] .b01-holder::after{ height:70%; }
}

.b01-h1{
  margin:0;
  font-family:var(--font-display);
  font-weight:400;
  /* DM Serif rende ~30% più largo di Barlow Condensed a parità di corpo, e
     il titolo è passato da 21 a 30 caratteri sulla riga più lunga: il corpo
     scende e la legge «una riga sola» del 15/07 cade con lei — il titolo è
     DUE righe per costruzione (L3), non per ripiego. */
  line-height:1.04;
  letter-spacing:-.005em;
  font-size:clamp(1.9rem, 5.4vw, 5.2rem);
  color:var(--ink);
  /* L'ALONE DI CARTA (owner 22/08: «spacca così, solo che il testo non
     saprei dove posizionarlo»).
     Misurato sul fotogramma 1 del girato — quello fermo sotto il titolo —
     a griglia 8x6, media/deviazione per riquadro:
       riga alta   242 / dev 1   → carta vuota
       righe 2-4   170-190 / dev 55-72 → creste: qui il fondo CAMBIA di
                   ~70 livelli dentro la stessa parola
       riga bassa  225 / dev 3   → carta vuota
     Il titolo cade per forza sulle righe centrali (è lì che sta il corpo
     della pagina), e non è la media a romperlo — è la deviazione: gli
     avvallamenti scuri delle curve di livello passano sotto le aste e
     l'occhio perde la lettera. Spostare il testo dove il fondo è liscio
     vorrebbe dire toglierlo dalla mappa, cioè togliere la composizione che
     all'owner piace.
     Quindi non si sposta il testo: si mette la CARTA sotto le lettere. Tre
     ombre crema concentriche (secca, media, larga) — non un riquadro, non
     un velo sull'immagine: solo il contorno del glifo che si stacca. La
     mappa resta visibile ovunque, anche fra una lettera e l'altra.
     Ombre CHIARE, non scure: su crema una scura si legge come sporco di
     stampa (era la ragione del `text-shadow:none` di prima, che vale
     ancora — infatti qui non c'è nessuna ombra scura). */
  text-shadow:
    0 0 2px rgba(247,242,233,.92),
    0 0 12px rgba(247,242,233,.88),
    0 0 34px rgba(247,242,233,.62);
}
.b01-dot{ color:var(--gold); }

.b01-sub{
  margin:clamp(14px, 2vh, 22px) 0 0;
  max-width:28ch;
  font-family:var(--font-body);
  font-weight:400;
  font-size:1rem;
  line-height:1.5;
  /* il sottotitolo è corpo piccolo su fondo mosso: senza alone sparisce
     prima del titolo. Inchiostro pieno (era .72: su una cresta scura una
     trasparenza è il modo più veloce per perdere una riga) + lo stesso
     alone di carta, stretto perché il corpo è piccolo. */
  color:var(--ink);
  text-shadow:
    0 0 2px rgba(247,242,233,.92),
    0 0 10px rgba(247,242,233,.8);
}

/* ---- Scorciatoie dell'hero (2026-08-14) ---------------------------
   Registro mono/oro come i kicker: segnaletica, non un secondo livello di
   titolo — il display resta uno solo. Target 44px senza allargare la
   colonna del lockup. Escono col titolo (beats.js) perché stanno dentro
   .b01-title: durante il volo nessuno deve avere bottoni sotto gli occhi. */
/* IN BASSO A SINISTRA e con più presenza (owner 18/08 sera-5): pieno
   carta, bordo oro vero, corpo su — non più fili d'aria sotto il
   sottotitolo. Assolute nel .b01-title, così escono col titolo. */
.b01-jump{
  position:absolute;
  left:var(--b01-pad-x);
  /* compensazione toolbar iOS (legge lvh #3): il title-box è alto 100lvh,
     ma a toolbar visibile il fold è 100svh — senza il delta le pill
     nascevano SOTTO la piega (screenshot owner 16:40) */
  bottom:calc((100lvh - 100svh) + clamp(24px, 5svh, 56px));
  display:flex;
  flex-wrap:wrap;
  gap:.6em;
  pointer-events:auto;      /* .b01-overlay e .pin sono pointer-events:none */
}
.b01-jump__link{
  display:flex;
  align-items:center;
  min-height:48px;
  padding:0 1.35em;
  border:1px solid rgba(165,130,74,.75);
  border-radius:999px;
  font-family:var(--font-mono);
  font-size:.8rem;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--ink);
  text-decoration:none;
  background:var(--print);
  box-shadow:0 1px 2px rgba(46,44,40,.12), 0 10px 22px -12px rgba(46,44,40,.35);
  transition:border-color .3s ease, background-color .3s ease, transform .3s ease;
}
@media (hover:hover){
  .b01-jump__link:hover{ border-color:rgba(165,130,74,.9); background:rgba(165,130,74,.12); }
}
.b01-jump__link:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }

/* Masked-line reveal — osmo masked-text-reveal mechanics (overflow mask).
   Base state is VISIBLE (transform:none) so JS-off / no-gsap still shows the
   headline. The JS PARKS the line (yPercent:110) at init, then reveals it. */
.b01-mask{
  display:block;
  overflow:hidden;
  padding-bottom:.08em;
}
.b01-line{
  display:block;
  transform:none;
  will-change:transform;
}

/* La copy di volo (.b01-flight ×3 + .b01-flight-scrim) è uscita col pin il
   18/08 sera: senza corsa di scrub non aveva più un tempo in cui vivere.
   Regole cancellate qui, markup cancellato in index.html.
   .b01-wash (dissolvenza al nero) era già uscita il 2026-08-04. */

.b01-cue{
  position:absolute;
  left:50%;
  bottom:clamp(20px, 3.4vh, 40px);
  transform:translateX(-50%);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
}
.b01-cue__line{
  width:1px;
  height:clamp(28px, 5vh, 52px);
  background:linear-gradient(180deg, transparent, rgba(165,130,74,.55));
}
.b01-cue__label{
  font-family:var(--font-mono);
  font-size:11px;
  letter-spacing:.3em;
  color:rgba(165,130,74,.85);
}

@media (max-width:820px) and (min-width:481px){
  .b01-headline{ max-width:92vw; bottom:clamp(88px, 15vh, 150px); }   /* +scorciatoie 14/08 */
  .b01-h1{ font-size:clamp(1.8rem, 4.9vw, 3.2rem); }
}

@media (max-width:480px){
  .b01-overlay{ --b01-pad-x: clamp(18px, 6vw, 26px); }
  .b01-kicker .b01-line{ font-size:10px; letter-spacing:.16em; }
  .b01-headline{ max-width:92vw; bottom:clamp(96px, 17vh, 158px); }   /* +scorciatoie 14/08 */
  /* a 390px la prima riga («Hochzeitsfilm & Hochzeitsfotos») va a capo da
     sola: tre righe di titolo a 29px stanno meglio di due a 25px, e il
     lockup ci sta lo stesso sopra le scorciatoie. */
  .b01-h1{ font-size:clamp(1.75rem, 8.6vw, 2.6rem); }
  .b01-sub{ font-size:.94rem; max-width:26ch; }
}

/* reduced-motion: never park — every line visible (JS also skips parking) */
@media (prefers-reduced-motion:reduce){
  .b01-line{ transform:none; }
}


/* === section:b03-daniel === */
/* ---- Beat 03 — Daniel intro (warm rest band) ------------------------ */
.b03{
  /* GROUND UNICO (17/08): era `var(--shadow)`, cioè sabbia piena, e fra b03
     e b04 si vedeva un gradino netto. Ora è la velatura --ground-2: la
     sezione resta appena più calda del resto senza che ci sia un bordo da
     guardare. Il --muted rinforzato resta: era stato misurato sulla sabbia
     (4,44:1 → 5,46:1) e su una velatura più chiara guadagna soltanto. */
  background:var(--ground-2);
  --muted:#5c544a;
  /* LA CODA (Daniel 21/08 18:19): la sfumatura legno→cartone deve cadere
     su carta VUOTA, non addosso alla CTA. La sezione si allunga sotto il
     contenuto esattamente della lunghezza della sfumatura (--b03-fade) e
     il flex la tiene centrata sopra. Un numero solo, letto qui e dalla
     maschera del legno: non possono sfasarsi. */
  /* L11 (pagina corta, «ogni fase lascia la pagina uguale o più corta»):
     la coda si paga in altezza, quindi si paga il MINIMO che regge la
     dissolvenza — 18svh invece di 26 — e la si compensa togliendo aria
     sopra (l'aria sopra ce l'ha già il giunto in penombra con l'hero).
     Misurato a 1430x780: sezione 973px con la coda lunga → 866px con
     questa, contro i 788px di prima del legno. +78px su una pagina di
     ~10 viewport: la coda non è una sezione in più, è il giunto. */
  --b03-fade:clamp(120px, 18svh, 210px);
  display:flex;
  align-items:center;
  padding:clamp(40px,6vh,78px) clamp(20px,6vw,96px);
  padding-bottom:calc(clamp(40px,6vh,78px) + var(--b03-fade));
  overflow:hidden;
  position:relative;
}
/* IL LEGNO DI DANIEL (vocale 17:37, parola per parola: «l'anello cade su
   di me, su un legno rusticale… poi va avanti con sto legno finché
   diventa cartone, e poi vengono i video»). Il ground di b03 è L'ULTIMO
   FRAME del girato del crollo — stesso pixel del freeze dell'hero, quindi
   il giunto non esiste. Il ritratto vero (DOM) ci sta sopra: è il «si
   vede subito chi sono».

   21/08 18:19 — LA MASCHERA DIAGONALE È USCITA. Diceva: legno in alto a
   sinistra (sotto il ritratto), cartone in basso a destra (sotto la copy).
   Daniel, parola per parola: «lì praticamente la foto con me e il mio
   intro, la mia descrizione, chi sono, così via, SEMPRE CON QUEL SFONDO
   DEL LEGNO LÌ». Il legno quindi tiene tutta la sezione, bordo a bordo,
   testo compreso — e la sfumatura verso il cartone non taglia più la
   sezione a metà: cade in fondo, sulla coda vuota (--b03-fade), che è
   esattamente il giunto con la sezione video («poi viene la sezione video
   con una sfumatura dal legno al cartone»).
   Conseguenza obbligata: sul legno si scrive in CREMA — vedi il blocco
   §b03 SUL LEGNO qui sotto, stessa legge già applicata al Tisch. */
.b03::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
  /* IL GIUNTO CON L'HERO. Il fotogramma congelato dell'hero è la stessa
     tavola ma inquadrata da più vicino e con la penombra del crollo
     addosso: attaccati, i due legni fanno una riga netta a metà schermo.
     Non si aggiusta con la scala (il canvas è cover sul pin, questo è
     cover sulla sezione: due box diversi, mai la stessa crop) — si
     aggiusta con la LUCE. La sezione entra in penombra e schiarisce in
     240px: il taglio cade dentro un'ombra, che è esattamente quello che
     l'occhio si aspetta guardando un tavolo. */
  /* LA LASTRA v2 (24/08, owner: «il cut non è netto e flush, non sembrano
     avere la stessa texture»). Due difetti della v1:
     (1) la lastra era un REDRAW AI del fotogramma — il grano era nato più
         grande dell'originale, quindi «non è la stessa texture» era vero
         alla lettera;
     (2) `100% auto` è scala in LARGHEZZA, ma il canvas dell'hero è cover
         ancorato al centro: scale = max(vw/iw, lvh/ih) sul box del pin
         (100lvh). Su laptop e telefono vince l'ALTEZZA, non la larghezza
         (1512×982: 0,909 contro 0,787 = grano ~15% più piccolo qui sotto;
         a 390 il frame mob è 608w → 0,78 contro 0,20 = 4× più piccolo).
     v2, deterministica, zero AI:
     · ring-wood-plate2.webp = PIXEL VERI dell'ultimo fotogramma: banda
       780–1079 (sotto l'anello) + il suo flip verticale sopra (tile
       1920×600, tools: ffmpeg crop+vflip+vstack → cwebp q76). La riga 0
       della lastra È la riga 1079 del frame → al giunto il grano continua
       C0; il mirror rende il tile continuo anche su se stesso
       (bookmatch, come i tavoloni veri). La vignetta del girato nelle
       ultime righe diventa l'ombra fra un tavolone e l'altro.
     · background-size replica ESATTAMENTE la matematica del cover:
       larghezza disegnata = 1920·scale. Desk (frame 1920×1080):
       max(100vw, 177.78lvh). Mobile ≤820px (frame 608×1080 center-crop
       dello stesso master, stesso centro): max(315.79vw, 177.78lvh).
     · position-y corregge il caso ultra-wide (cover limitato in
       larghezza: il crop dell'hero non arriva alla riga 1079 → la lastra
       risale di metà dell'eccedenza). Su laptop/telefono vale 0.
     La penombra artificiale è USCITA: i pixel ora continuano da sé, un
     velo sopra sarebbe di nuovo un gradino di tono. */
  background-image:url("../assets/media/ring-wood-plate2.webp");
  background-size:max(100vw, 177.78lvh) auto;
  background-repeat:repeat-y;
  background-position:50% calc((100lvh - max(56.25vw, 100lvh)) / 2);
  /* la sfumatura in px, non in %: la coda della sezione è alta --b03-fade
     a qualunque viewport, e la dissolvenza deve essere lunga QUELLA, se no
     su schermi bassi diventa un bordo e su schermi alti mangia la copy */
  -webkit-mask-image:linear-gradient(to bottom, #000 0,
    #000 calc(100% - var(--b03-fade)), transparent calc(100% - 2px));
          mask-image:linear-gradient(to bottom, #000 0,
    #000 calc(100% - var(--b03-fade)), transparent calc(100% - 2px));
}
@media (max-width:820px){
  .b03::before{
    /* stesso breakpoint di ring.js: sotto 820 il canvas disegna il frame
       MOB 608×1080 (center-crop dello stesso master, stesso centro) →
       scale = max(vw/608, lvh/1080), larghezza lastra = 1920·scale */
    background-size:max(315.79vw, 177.78lvh) auto;
    background-position:50% calc((100lvh - max(177.63vw, 100lvh)) / 2);
  }
}

/* ==== §b03 SUL LEGNO — l'inchiostro si ribalta ======================
   Stessa legge misurata sul Tisch (§b05 .is-scrub): su un piano di noce
   ogni token scuro sparisce dentro il legno. Qui il fondo è ancora più
   difficile perché è una VENATURA VIVA con nodi chiari e solchi neri:
   nessun colore di testo, da solo, tiene su tutti e due. Quindi due cose
   insieme, come per il lockup di b05: testo crema + un velo scuro sfumato
   che muore a zero prima di diventare un riquadro.
   Le eccezioni sono gli oggetti di CARTA (la didascalia sul bordo della
   stampa, la CTA a pillola d'oro): lì il fondo è chiaro e l'inchiostro
   resta scuro — sotto, esplicite. */
.b03 .b03-h{
  color:#faf4e6;
  text-shadow:0 1px 14px rgba(20,12,4,.42);
}
.b03 .b03-h em,
.b03 .b03-dot,
.b03 .b03-num,
.b03 .b03-kicker{ color:#c9a050; }
.b03 .b03-rule{ background:#c9a050; }
.b03 .b03-quote{
  color:rgba(246,238,224,.94);
  text-shadow:0 1px 8px rgba(20,12,4,.34);
}
.b03 .b03-sign{
  color:rgba(246,238,224,.92);
  text-shadow:0 1px 8px rgba(20,12,4,.34);
}
.b03 .b03-sign em{ color:#c9a050; }
.b03 .b03-sigrule path{ stroke:#c9a050; }
/* IL VELO sotto la colonna di testo. Radiale, ancorato in alto a sinistra
   dove comincia la lettura, e a zero prima del bordo: non è un pannello,
   è ombra. Stesso gesto approvato il 21/08 sul lockup del Tisch. */
.b03 .b03-text{ position:relative; }
.b03 .b03-text::before{
  content:"";
  position:absolute;
  z-index:-1;
  /* stessa geometria del velo di b05: `closest-side` + ultimo stop
     trasparente = alfa zero prima del bordo, mai un riquadro */
  inset:-30% -28% -34% -26%;
  background:radial-gradient(closest-side at 34% 48%,
    rgba(18,12,6,.72) 0%,
    rgba(18,12,6,.46) 52%,
    rgba(18,12,6,0) 100%);
  pointer-events:none;
}
/* la didascalia sta sul bordo di CARTA della stampa, non sul legno:
   resta inchiostro (il --muted della sezione la porterebbe a crema su
   bianco, cioè invisibile) */
.b03 .b03-portrait__cap{ color:#6b6156; }
.b03-inner{ z-index:1; }
.b03 .scene-label{ display:none; }

.b03-inner{
  /* --b03-pw = larghezza della stampa, dichiarata UNA volta: la leggono la
     figure (max-width) e la striscia a contatto (offset). Un numero solo,
     due elementi che non possono più sfasarsi (owner 18/08). */
  --b03-pw:clamp(280px,34vw,440px);
  position:relative;            /* contesto della striscia in assoluto */
  width:100%;
  max-width:1360px;
  margin:0 auto;
  display:grid;
  grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(32px,6vw,96px);
  align-items:center;
}

.b03-text{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  order:1;                      /* il ritratto è primo nel markup (è quello
                                   in cui l'hero si dissolve): sul desktop le
                                   colonne restano testo → foto */
}

/* .b03-print rimossa con l'handoff-morph (owner 2026-08-12): era solo il
   bersaglio della stampa in volo. */

/* Sosta lockup — numero mono '02' oro + mono kicker */
.b03-lockup{
  display:flex;
  align-items:baseline;
  gap:.9em;
  margin-bottom:clamp(14px,2.2vh,24px);
}
.b03-num{
  font-family:var(--font-display);
  font-weight:400;
  font-size:clamp(1.6rem,3.6vw,2.5rem);
  line-height:1;
  letter-spacing:0;
  color:var(--gold);
}
/* la riga oro del kicker: si disegna scaleX 0→1 (--d-snap) all'entrata */
.b03-rule{
  display:block;
  width:clamp(28px,4vw,56px);
  height:1px;
  background:var(--gold);
  transform:scaleX(1);
  transform-origin:left center;
  align-self:center;
}
.b03-kicker{
  font-family:var(--font-body); font-weight:500;
  font-size:clamp(10px,1.05vw,12px);
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--gold);
  padding-bottom:.15em;
}

/* Display headline — Barlow Condensed, gold emphasis (never serif-italic) */
.b03-h{
  margin:0 0 clamp(18px,2.6vh,30px);
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.06;
  letter-spacing:-.005em;
  font-size:clamp(1.9rem,4.2vw,3.4rem);
  color:var(--paper);
}
.b03-h em{ font-style:normal; color:var(--gold); }
.b03-dot{ color:var(--gold); }

/* Quote — Inter body, line-reveal masks built by JS */
.b03-quote{
  margin:0 0 clamp(18px,2.6vh,30px);
  max-width:46ch;
  font-family:var(--font-body);
  font-weight:400;
  font-size:clamp(1rem,1.2vw,1.1rem);   /* min bumped .98rem→1rem: 16px floor a 390px */
  line-height:1.5;
  letter-spacing:.002em;
  color:var(--muted);
}
.b03-line-mask{
  display:block;
  overflow:hidden;
  padding-bottom:.14em;
  margin-bottom:-.14em;
}
.b03-line{
  display:block;
  will-change:transform;
}

/* firma handwritten (owner 2026-07-16) — elemento umano, non display type */
.b03-sign{
  /* il margine sotto è passato al filetto oro che ora segue la firma */
  margin:0 0 .1em;
  font-family:'Caveat', 'Bradley Hand', cursive;
  font-weight:500;
  font-size:clamp(1.6rem,2.2vw,2.1rem);
  line-height:1.1;
  transform:rotate(-2deg);
  transform-origin:left center;
  color:var(--muted);
}
.b03-sign em{ font-style:normal; color:var(--gold); }

/* CTA — pill oro (allineata a .sticky-cta, 2026-08-11: era testo mono nudo) */
.b03-cta{
  --b062-ease:cubic-bezier(0.625,0.05,0,1);
  position:relative;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:48px;
  padding:.9em 1.6em;
  border-radius:999px;
  background:var(--gold2);
  color:var(--ink);
  font-family:var(--font-body); font-weight:500;
  font-size:.8rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  text-decoration:none;
  box-shadow:0 8px 22px rgba(46,44,40,.16);
  -webkit-tap-highlight-color:transparent;
}
.b03-cta__label{ line-height:1; }
@media (hover:hover) and (pointer:fine){
  .b03-cta{ transition:background .35s var(--b062-ease), transform .35s var(--b062-ease); }
  .b03-cta:is(:hover,:focus-visible){
    background:color-mix(in srgb, var(--gold2) 86%, var(--ink) 14%);
    transform:translateY(-1px);
  }
}
@media (prefers-reduced-motion:reduce){ .b03-cta{ transition:none; } }

/* Portrait — LA STAMPA APPESA AL MURO (owner 18/08 «rendi più figo su
   mobile»). Prima era un rettangolo a filo con la didascalia in overlay su
   un velo nero: pulito ma anonimo, e soprattutto ESTRANEO alla grammatica
   materiale che il resto della pagina ha già (b05 = carta su legno).
   Ora è una .tprint a tutti gli effetti — stesse frazioni di bordo (4,2%
   sui lati, 12,5% sotto), stesso --print, stesso raggio 2px, stessa doppia
   ombra (1px di contatto + 5/12px di stacco) — appoggiata storta al muro
   crema e fissata con due pezzi di nastro di carta.
   L'aspect-ratio 3/4 si sposta sul __media: la figure adesso è più alta di
   così (bordo + didascalia), e tenerlo qui schiacciava la foto.
   Parallasse overscan e scale 1.06→1 (smoothScrub, sections.js) restano
   identici: agiscono sull'img dentro il __media. */
.b03-portrait{
  position:relative;
  z-index:1;                    /* sopra la striscia a contatto */
  margin:0;
  order:2;                      /* markup: figura prima del testo */
  justify-self:end;
  width:100%;
  max-width:var(--b03-pw);
  padding:4.2% 4.2% 12.5%;
  background:var(--print);
  border-radius:2px;
  box-shadow:
    0 1px 1px rgba(46,44,40,.10),
    0 5px 12px -6px rgba(46,44,40,.30);
  transform:rotate(-1.6deg);    /* riposo mobile; il desktop lo ripassa sotto */
  transform-origin:50% 0;
}
/* i due pezzi di NASTRO DI CARTA, a cavallo degli angoli alti. Carta crema
   traslucida (si intuisce la stampa sotto), un filo interno appena accennato
   al posto del bordo e una goccia d'ombra: basta quello per staccarlo dal
   muro. Rotazioni opposte — un nastro strappato non è mai simmetrico.
   z sopra il bordo di carta, come nella realtà: il nastro sta SOPRA. */
.b03-portrait::before,
.b03-portrait::after{
  content:'';
  position:absolute;
  z-index:2;
  width:92px;
  height:30px;
  background:rgba(250,247,240,.82);
  box-shadow:
    inset 0 0 0 1px rgba(46,44,40,.05),
    0 1px 2px rgba(46,44,40,.10);
  pointer-events:none;
}
.b03-portrait::before{ top:-13px; left:-26px;  transform:rotate(-45deg); }
.b03-portrait::after { top:-11px; right:-24px; transform:rotate(40deg);  }

.b03-portrait__media{
  position:relative;
  overflow:hidden;
  aspect-ratio:3/4;
  background:var(--sand);
}
.b03-portrait__img{
  position:absolute;
  top:-10%;
  left:0;
  width:100%;
  height:120%;
  object-fit:cover;
  object-position:center 22%;
  will-change:transform;
}
/* il velo scuro in fondo alla foto è USCITO con l'overlay: serviva solo a
   rendere leggibile la didascalia sopra l'immagine. Ora la didascalia sta
   sul bordo di carta, dove va scritta una didascalia su una stampa. */
.b03-portrait__cap{
  display:block;
  margin-top:calc(4.2% + .35em);
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--muted);
}

/* ---- la STRISCIA A CONTATTO dietro la stampa (owner 18/08) ----------
   Mini .tstrip: tre provini quadrati su cartoncino --print, ruotata, in
   assoluto dentro .b03-inner e sotto la figura in z. Spunta di poco — è un
   dettaglio periferico, non un secondo soggetto.
   left è calcolato sulla larghezza REALE della stampa (--b03-pw), non su un
   numero a caso: così a 320 come a 430 lo sbordo resta quello voluto e non
   può uscire dal viewport (che comunque la sezione taglia, overflow:hidden). */
.b03-strip{
  position:absolute;
  z-index:0;
  top:9%;
  left:calc(var(--b03-pw) - 64px);
  width:88px;
  /* NON flex-column (a differenza di .tstrip): in colonna flex la misura
     principale è l'ALTEZZA e i provini prendono i loro 600px intrinseci
     ignorando l'aspect-ratio calcolato dalla larghezza — misurato, la
     striscia usciva alta 1827px. In blocco normale l'aspect-ratio 1 si
     risolve dalla larghezza e i tre quadrati sono quadrati. */
  display:block;
  padding:6px 6px 12px;
  background:var(--print);
  border-radius:2px;
  box-shadow:0 4px 10px -5px rgba(46,44,40,.34);
  transform:rotate(6deg);
  pointer-events:none;
}
.b03-strip img{
  display:block;
  width:100%;
  /* height:auto OBBLIGATORIO: gli attributi width/height="600" del markup
     (che servono a riservare il posto e non far ballare il layout) valgono
     come regola di presentazione, e senza questo l'aspect-ratio perdeva —
     misurato: provini alti 600px, striscia da 1827px. */
  height:auto;
  aspect-ratio:1;
  margin:0 0 5px;
  object-fit:cover;
  filter:grayscale(.5) contrast(1.06);
}
.b03-strip img:last-child{ margin-bottom:0; }

/* ---- il sottolineato a mano sotto la firma -------------------------
   Stato di riposo = disegnato (nessun dash qui): senza JS, in
   reduced-motion o a tab in background non manca niente. Il dash lo scrive
   sections.js solo quando c'è davvero un'animazione da fare. */
.b03-sigrule{
  display:block;
  width:min(180px, 62%);
  height:auto;
  margin:-.4em 0 clamp(22px,3vh,36px) 2px;
  overflow:visible;
}

/* Mobile — stack, portrait above, text below */
@media (max-width:820px){
  .b03{
    padding:clamp(36px,5.5vh,64px) clamp(18px,6vw,32px);
    /* la shorthand qui sopra azzera la coda della sfumatura: va riscritta,
       se no sul telefono il legno finisce di colpo sotto la CTA */
    padding-bottom:calc(clamp(36px,5.5vh,64px) + var(--b03-fade));
  }
  .b03-inner{
    grid-template-columns:1fr;
    gap:clamp(26px,5vh,40px);
  }
  /* la stampa si stringe per lasciare respiro al nastro e alla striscia:
     min(70vw,320px) invece di 78vw/360 — a 390 la carta arriva a ~273px,
     la striscia sborda di 24px e restano ~90px di muro a destra. */
  .b03-inner{ --b03-pw:min(70vw,320px); }
  /* la didascalia deve stare su UNA riga sul bordo di carta: a 390 andava a
     capo su «FOTOGRAF» e il bordo basso sembrava sbagliato (owner 18/08) */
  .b03-portrait__cap{ font-size:9px; letter-spacing:.07em; white-space:nowrap; }
  .b03-portrait{
    order:0;                    /* già primo nel markup: la foto è in cima */
    justify-self:start;
  }
  .b03-h{ font-size:clamp(1.55rem,6.8vw,2.6rem); }
  .b03-quote{ max-width:none; }
}

/* Desktop — la stampa sta nella colonna destra a filo: la striscia si
   ancora a DESTRA (non più all'offset calcolato da sinistra, che lì
   cadrebbe in mezzo alla copy) e tutto cresce di un gradino. */
@media (min-width:821px){
  .b03-portrait{ transform:rotate(-2deg); }
  .b03-portrait::before,
  .b03-portrait::after{ width:112px; height:34px; }
  .b03-portrait::before{ top:-15px; left:-32px; }
  .b03-portrait::after { top:-13px; right:-28px; }
  .b03-strip{
    left:auto;
    right:-26px;
    top:14%;
    width:120px;
    padding:8px 8px 16px;
  }
  .b03-strip img{ margin-bottom:7px; }
}

@media (prefers-reduced-motion:reduce){
  .b03-line{ transform:none !important; }
}

/* === section:b04h-referenzen === */

/* ---- shared close button ----------------------------------------- */
.b04-x{
  position:absolute; top:2.5vw; right:2.5vw; z-index:6;
  width:3em; height:3em; border-radius:50%;
  border:1px solid rgba(242,236,227,.35); background:rgba(11,10,9,.5);
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; color:var(--paper);
  transition:border-color .3s var(--ease-osmo), background .3s var(--ease-osmo);
}
@media (hover:hover) and (pointer:fine){
  .b04-x:hover{ border-color:var(--gold); background:rgba(11,10,9,.75); }
}
.b04-x span{ position:absolute; width:15px; height:1.5px; background:currentColor; border-radius:2px; }
.b04-x span:first-child{ transform:rotate(45deg); }
.b04-x span:last-child{ transform:rotate(-45deg); }

/* ---- film lightbox ----------------------------------------------- */
.b04-film-lb{
  position:fixed; inset:0; z-index:130;
  display:flex; align-items:center; justify-content:center; padding:5vw;
  opacity:0; visibility:hidden; pointer-events:none;
}
.b04-film-lb.is--open{ pointer-events:auto; }
.b04-film-lb__bg{ position:absolute; inset:0; background:rgba(11,10,9,.96); }
.b04-film-lb__player{
  position:relative; width:100%; max-width:1180px; aspect-ratio:16/9;
  background:#000; border-radius:8px; overflow:hidden;
  box-shadow:0 40px 120px rgba(0,0,0,.7), 0 0 0 1px rgba(201,160,80,.14);
}
.b04-film-lb__iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }

@media (max-width:820px){
  .b04-x{ top:16px; right:16px; width:46px; height:46px; }  /* tap ≥44px */
}

/* STORIA DI QUESTA SEZIONE (le regole sono state rimosse, non commentate):
   · 06/08  cilindro 3D `.b04cyl*` — port osmo «3d-perspective-tiles-infinite-loop».
            Ritirato: mostrava UN film alla volta in 562px, cinque su sei
            raggiungibili solo aspettando il giro.
   · 12/08  muro `.b04deck` / `.b04row*` — sei righe cinema tutte visibili.
            Onesto ma piatto: sei referenze con lo stesso peso.
   · 13/08  I SEI MANIFESTI (qui sotto). */

/* b04 — Der Film · Referenzen: I SEI MANIFESTI (2026-08-13).
   Spec BUILD-b04-MANIFESTI-2026-08-13.md · numeri RE-SIENA-b04-2026-08-13.md.
   Nessun pin: scroll normale, sei sezioni da 100svh nel flusso. */
/* IL FLIP CHIARO DI b04 — 2026-08-17, owner sul live: «deve essere same
   color chiaro delle altre». Cade il dimmer ai bordi (le due fasce
   crema→#1c1813→nero che facevano da porta della "sala cinema"): non c'è
   più una stanza buia da entrare e uscire. La sezione porta `.theme-light`
   come b03/b05/b06 e i suoi token si ripuntano da soli — `--paper`
   diventa inchiostro, `--gold` diventa gold-deep (l'oro chiaro non passa
   AA sul corpo in crema).
   L'UNICO dark superstite della pagina è l'hero b01. Il lightbox del film
   resta scuro: lì il buio è funzionale, è una sala di proiezione modale.
   Le fasce erano PADDING e non sovrapposizioni: togliendole resta solo un
   respiro normale, e la sezione si accorcia di ~270px su 390. */
[data-beat="04"]{
  position:relative;
  padding:clamp(70px,9svh,120px) 0 clamp(70px,9svh,120px);
}

.b04w-head{
  max-width:820px;
  margin:0 auto clamp(8px,1.4vh,22px);
  padding:0 clamp(24px,6vw,88px);
  /* lo scroll-snap è rimosso (13/08). Lo scroll-margin resta: serve
     all'ancora «Referenzen» (#beat-04), che senza incollerebbe l'header al
     bordo alto dello schermo, sotto la barra. */
  scroll-margin-top:clamp(96px,12svh,124px);
}
.b04h-kicker{
  display:block;
  margin-bottom:clamp(12px,1.8vh,20px);
  font-family:var(--font-mono);
  font-size:.72rem;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--gold);
}
.b04h-title{
  margin:0;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.06;
  letter-spacing:-.005em;
  font-size:clamp(2rem,min(5.2vw,6.2vh),4.2rem);
  color:var(--paper);
}
.b04h-dot{ color:var(--gold); }
.b04h-sub{
  margin:clamp(16px,2.2vh,24px) 0 0;
  max-width:44ch;
  font-family:var(--font-body);
  font-size:clamp(.95rem,1.1vw,1.05rem);
  line-height:1.6;
  color:var(--muted);
}

/* utility: testo per i soli lettori di schermo (in questo build non ce n'era
   ancora una — serve solo alla pillola indice, che ha già un contenuto
   visibile e non può prendersi un aria-label che lo sovrascriva) */
.u-sr{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
}

/* ====================================================================
   IL DECK DEI FILM — porting osmo «flick-cards-slider», 2026-08-17
   --------------------------------------------------------------------
   STORIA (le regole sono state RIMOSSE, non commentate):
     · 06/08  cilindro 3D `.b04cyl*` (osmo 3d-perspective-tiles).
     · 12/08  muro `.b04deck`/`.b04row*` — sei righe tutte visibili.
     · 13/08  I SEI MANIFESTI `.b04m*` — biglietti siena a 100svh, con
              clipPath a tacca e tabella ORT/JAHR/LÄNGE vuota.
              Bocciati dal cliente e dall'owner (17/08): «sta sezione va
              rimossa o rielaborata». Via markup, clipPath, CSS e motore.
     · 17/08  IL DECK (qui sotto), e poche ore dopo il FLIP CHIARO.

   LA CARD È UNA STAMPA, non una locandina al buio. Col passaggio a
   `.theme-light` (owner: «same color chiaro delle altre») una card scura
   a filo del bordo sarebbe diventata un buco nero sul crema. Qui vale la
   STAMPE NUDE anche qui (owner 25/08: «questa sezione ha le polaroid e
   non dovrebbe avercele» — stessa legge del Tisch, 21/08: «senza polaroid
   e senza robe bianche»). La carta bianca è USCITA: resta la foto piena,
   il raggio 2px, l'ombra di contatto+distacco che la tiene sul piano.
   La didascalia non ha più la fascia di carta sotto: sta SULLA foto, in
   basso, in crema su uno scrim scuro — la stessa legge del legno
   («sul legno si scrive in crema», b03/Tisch): dove il fondo è
   un'immagine, l'inchiostro non si usa.

   GEOMETRIA. Tutto pende da `--card-w` (ora larghezza della FOTO):
     foto = card-w, rapporto 2:3 (il manifesto di cinema, che è anche
     quello dell'originale osmo: `padding-top:150%`);
     didascalia = overlay assoluto in fondo alla foto, non aggiunge
     altezza. Il titolo resta tagliato a due righe (clamp).
   L'altezza del deck è quindi solo la foto. Le card stanno tutte
   sovrapposte sullo stesso punto e il motore le apre a ±25% / ±45% con
   rotazione e scala.

   390pt: carta 78vw = 304px. Le vicine spuntano di lato per una scheggia
   — è così che si legge come un MAZZO e non come una foto sola.
   `overflow-x:clip` sul deck: le card a ±45% scalate escono dai bordi e
   senza il taglio darebbero scroll orizzontale alla pagina.
   ==================================================================== */
.b04deck{
  /* owner 18/08 sul telefono: card «super grandi» — 66vw lascia respiro ai
     lati e la card intera (foto+didascalia) sta sotto i 2/3 del viewport a 390. */
  --card-w:min(66vw, 270px);
  position:relative;
  margin-top:clamp(18px,3vh,34px);
  overflow-x:clip;            /* non `hidden`: non deve creare un contenitore di scroll */
}

.b04deck__stage{
  position:relative;
  /* solo la foto: la didascalia è un overlay dentro di lei */
  height:calc(var(--card-w) * 1.5);
}
.b04deck__list{
  position:absolute; inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  margin:0; padding:0;
  list-style:none;
}
.b04deck__item{
  position:absolute;
  width:var(--card-w);
  /* stato di riposo SENZA JS: le card restano impilate e la prima si
     legge lo stesso (legge del repo: mai trappole opacity:0 in CSS) */
  will-change:transform;
}

/* L'OMBRA CHE REAGISCE AL TILT (pass C2, 18/08).
   Sta sul <li> e non sulla card: il <li> è l'elemento che il motore
   posiziona, e un pseudo-elemento del <li> dipinge PRIMA di `.b04c`,
   cioè dietro la carta — senza z-index negativi e senza toccare la pila
   del deck. `--tsh` (0→1) la scrive il motore dal micro-tilt: l'ombra si
   allunga verso il basso e si stacca quando il cartoncino si inclina.
   Solo transform e opacity: nessun box-shadow ricalcolato per frame,
   perché l'ombra qui è disegnata una volta e poi soltanto mossa. */
.b04deck__item::before{
  content:"";
  position:absolute;
  inset:0;
  border-radius:2px;
  box-shadow:0 20px 38px -14px rgba(46,44,40,.52);
  opacity:var(--tsh, 0);
  transform:translateY(calc(var(--tsh, 0) * 9px));
  pointer-events:none;
}

/* IL MARGINE DI COPERTURA DELLA FOTO.
   La sorgente riempie il vano quasi esattamente (1200x1789 = 0,671 su
   1/1.5 = 0,667): senza ingrandirla, la parallasse scoprirebbe il vano.
   La scala la mette il motore (js §LA PROFONDITÀ DENTRO LA CARD, OVER),
   non il CSS, perché è lo stesso numero da cui dipende quanto può
   traslare — un valore, un posto. Qui resta solo la promessa al
   compositore che questa immagine si muoverà. */
.b04deck__item .b04c__img{ will-change:transform; }

/* LA STAMPA NUDA — stessi valori delle stampe nude del Tisch
   (§STAMPE NUDE, .b05tisch__stage .tprint): niente carta, la foto e
   l'ombra che la tiene sul piano. */
.b04c{
  position:relative;
  display:block;
  padding:0;
  background:transparent;
  border-radius:2px;
  box-shadow:
    0 1px 2px rgba(46,44,40,.38),
    0 12px 28px -12px rgba(46,44,40,.5);
  -webkit-user-select:none; user-select:none;
}
.b04c__media{
  position:relative;
  overflow:hidden;
  aspect-ratio:1 / 1.5;
  border-radius:2px;
  background:var(--sand);
}
/* `.b04c__img` e `.b04c__v` condividono la regola: il giorno che arrivano
   gli export di Daniel il <video> prende il posto dell'<img> senza che il
   layout cambi di un pixel (TODO nel markup). */
.b04c__img,
.b04c__v{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  object-position:var(--op, 50% 46%);
  pointer-events:none;
  -webkit-user-select:none; user-select:none;
}

/* LA DIDASCALIA, SULLA foto ---------------------------------------------
   Overlay in fondo al vano, crema su scrim scuro (legge «sul legno si
   scrive in crema»: dove il fondo è un'immagine, niente inchiostro).
   Lo scrim è parte della stampa: raggio in basso uguale, e sta sotto
   il bordo della foto — non è un banner appoggiato. */
.b04c__foot{
  position:absolute;
  inset:auto 0 0 0;
  z-index:1;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  padding:44px 14px 12px;
  border-radius:0 0 2px 2px;
  background:linear-gradient(to top,
    rgba(24,18,12,.74), rgba(24,18,12,.42) 58%, rgba(24,18,12,0));
  /* niente pointer-events speciali: come prima, sopra c'è il dragger
     (z2) e il tap/click lo gestisce il motore */
}
.b04c__plate{
  font-family:var(--font-mono);
  font-size:.62rem;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--gold);
}
.b04c__title{
  margin:6px 0 0;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.06;
  letter-spacing:-.005em;
  font-size:clamp(1.1rem, 4.6vw, 1.4rem);
  color:#f7f2e9;
  text-shadow:0 1px 2px rgba(24,18,12,.5);
  /* due righe FISSE: l'altezza della didascalia è nel calcolo del deck */
  display:-webkit-box;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:2;
  overflow:hidden;
}
/* il bottone è una RIGA DI TESTO, non una scatola: sulla carta una pill
   piena sembrerebbe un banner. Resta un <button> vero — focus da
   tastiera, Invio/Spazio, aria-label — alto 44px per il pollice. */
.b04c__btn{
  display:flex;
  align-items:center;
  gap:8px;
  margin-top:4px;
  min-height:44px;
  padding:0;
  border:0;
  background:none;
  font-family:var(--font-mono);
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--gold);           /* sullo scrim scuro: oro chiaro, non deep */
  text-align:left;
  cursor:pointer;
  transition:color .35s linear;
}
.b04c__btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.b04c__arrow{ font-family:var(--font-body); transition:transform .4s var(--ease-expo-out, cubic-bezier(.16,1,.3,1)); }
@media (hover:hover) and (pointer:fine){
  .b04c__btn:hover{ color:#f7f2e9; }   /* sullo scrim scuro: crema, non inchiostro */
  .b04c__btn:hover .b04c__arrow{ transform:translateX(4px); }
}

/* SOLO la card attiva è cliccabile: sulle altre il primo tocco le porta
   al centro (lo fa il motore), non apre un film che non stai guardando. */
.b04deck__item .b04c__btn{
  opacity:0;
  transform:translateY(40%);
  pointer-events:none;
  transition:opacity .4s cubic-bezier(.625,.05,0,1), transform 1s cubic-bezier(.16,1,.3,1), color .35s linear;
}
.b04deck__item[data-flick-status="active"] .b04c__btn{
  opacity:1;
  transform:translateY(0);
  pointer-events:auto;
}
/* le vicine arretrano di un velo. Su fondo chiaro NON si abbassa
   l'opacità della carta (diventerebbe grigia e sporcherebbe il crema):
   si scolora solo la FOTO, la carta resta carta. */
.b04deck__item .b04c__media{ transition:opacity .2s ease; opacity:.62; }
.b04deck__item[data-flick-status="2-before"] .b04c__media,
.b04deck__item[data-flick-status="2-after"]  .b04c__media{ opacity:.82; }
.b04deck__item[data-flick-status="active"]   .b04c__media{ opacity:1; }
.b04deck__item:not([data-flick-status="active"]) .b04c__title{ color:var(--muted); }

/* IL DRAGGER — generato dal JS dentro ogni card (osmo).
   `touch-action:pan-y`: il dito che scorre in VERTICALE resta al browser,
   quello che scorre in orizzontale è nostro. È la riga che tiene insieme
   swipe della card e scroll della pagina su 390 (L10). */
[data-flick-dragger]{
  position:absolute; inset:0;
  z-index:2;
  pointer-events:auto;
  touch-action:pan-y;
}
.b04deck[data-flick-drag="grab"]     [data-flick-dragger]{ cursor:grab; }
.b04deck[data-flick-drag="grabbing"] [data-flick-dragger]{ cursor:grabbing; }

/* la barra sotto ----------------------------------------------------- */
.b04deck__bar{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:clamp(14px,4vw,26px);
  margin-top:clamp(18px,2.6vh,30px);
}
.b04deck__nav{
  display:flex; align-items:center; justify-content:center;
  width:46px; height:46px;                 /* target ≥44px, anche su touch */
  border:1px solid var(--line);
  border-radius:50%;
  background:transparent;
  color:var(--ink);
  font-size:1rem;
  cursor:pointer;
  transition:border-color .35s linear, background .35s linear, color .35s linear;
}
.b04deck__nav:focus-visible{ outline:2px solid var(--gold-deep); outline-offset:3px; }
@media (hover:hover) and (pointer:fine){
  .b04deck__nav:hover{ border-color:var(--gold-deep); color:var(--gold-deep); }
}
.b04deck__count{
  margin:0;
  min-width:5.4ch;
  text-align:center;
  font-family:var(--font-mono);
  font-size:.78rem;
  letter-spacing:.16em;
  color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.b04deck__count b{ font-weight:400; color:var(--gold-deep); }
.b04deck__slash{ margin:0 .5ch; }

.b04deck__hint{
  margin:clamp(10px,1.6vh,16px) 0 0;
  text-align:center;
  font-family:var(--font-mono);
  font-size:.62rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--muted);
  opacity:.7;
  transition:opacity .5s linear;
}
.b04deck__hint span{ color:var(--gold-deep); }
.b04deck__hint.is--off{ opacity:0; }

/* ---- DESKTOP -------------------------------------------------------
   NIENTE seconda anatomia (era l'errore del vecchio manifesto, che aveva
   due impaginati da mantenere): cambiano SOLO la larghezza della carta —
   qui misurata anche sull'altezza disponibile — e i corpi del testo. */
@media (min-width:821px){
  .b04deck{
    /* niente più fascia didascalia: la card è solo foto, e su desktop il
       limite d'altezza può salire di conseguenza (34→38svh) senza che il
       deck superi il vecchio ingombro totale (foto+foot) */
    --card-w:min(26vw, 38svh, 340px);
  }
  .b04c__title{ font-size:clamp(1.3rem, 1.6vw, 1.7rem); }
  .b04c__plate{ font-size:.66rem; }
  .b04deck__hint{ font-size:.66rem; }
}

/* reduced-motion: il deck resta NAVIGABILE, senza molla e senza
   dissolvenze. Il motore JS legge la stessa media query e mette
   `duration:0` sui suoi tween. */
@media (prefers-reduced-motion: reduce){
  .b04deck__item,
  .b04c__btn,
  .b04deck__item .b04c__media,
  .b04deck__hint{ transition-duration:.01ms !important; }
}

/* === section:b05-foto === */
/* ===== BEAT 05 — Hochzeitsfotos: stack 3D delle stampe + muro =========
   Porta di osmo «stacking-cards-3d-css» (sorgente misurato il 06/08).
   L'originale è CSS puro e tiene TUTTA l'animazione dentro
   @supports (animation-timeline: view()). Qui quel wrapper non esiste e
   non deve esistere: senza animation-timeline le @keyframes partirebbero
   come animazioni a tempo di durata zero e ogni carta si renderizzerebbe
   già nello stato finale inclinato (trappola dichiarata dagli autori).
   Su iOS view() arriva solo con Safari 26 — troppo tardi per il gesto
   centrale di una sezione wow. Quindi: stessi valori esatti, motore
   ScrollTrigger (js/sections.js), aspetto identico ovunque.

   Valori del sorgente preservati:
     riga 100svh · sosta 10svh · carta = riga − 2·sosta
     cerniera 50% 100% · perspective(60em) rotateX(25deg) scale(.85)
     brightness(.45) · andamento lineare · ultima carta ferma.
   ==================================================================== */

.b05{
  background:var(--bg);
  /* padding-top corto: la sezione non «comincia», ENTRA — il cielo del
     diorama è lo stesso crema della pagina, quindi non serve aria per
     staccarlo da b04, serve che non ci sia stacco (fase B2). */
  padding:clamp(20px, 3.4vh, 44px) 0 clamp(40px, 6vh, 88px);
}

/* ---- lockup: numero mono gold + display, come nelle altre sezioni ----
   Fase B2: NON è più un blocco nel flusso sopra al tavolo — vive DENTRO
   la scena incollata, appoggiato sulla carta, e la sua opacità/quota le
   detta il progresso della corsa (js/sections.js §b05-tisch). Qui sotto
   solo la posizione nel riquadro; lo stato di riposo è visibile, così
   senza JS e in reduced-motion il titolo c'è. */
.b05-lockup{
  position:absolute;
  z-index:4;
  left:0; right:0;
  /* owner 18/08 sera-3 (screenshot 390): più centrato e più basso — non
     appeso al bordo alto ma nel terzo alto-centrale del viewport. Esce
     comunque (lout u .17–.29) prima che le stampe alte atterrino. */
  top:clamp(112px, 26svh, 240px);
  max-width:820px;
  margin:0 auto;
  padding:0 clamp(24px, 7vw, 88px);
  pointer-events:none;
  will-change:transform, opacity;
}

/* LEGGIBILITÀ SUL LEGNO (owner 21/08: «testo non si legge qua»).
   Misurato sui fotogrammi veri del Tisch nella finestra del lockup: il
   fondo sta fra L .20 e L .36 e CAMBIA mentre scorri, quindi nessun
   colore di testo fisso regge da solo (ink 3.2:1 nel punto peggiore,
   crema 2.3:1). Serve un fondo prevedibile: un velo sfumato che muore a
   zero prima di diventare un riquadro. Due regimi come i due piani:
   cartone chiaro nel percorso DOM (testo scuro -> velo crema) e noce col
   girato (testo crema -> velo scuro). */
/* 21/08 sera — IL VELO ERA UN RIQUADRO. La misura `115% 95%` fa arrivare
   la sfumatura al bordo della sua scatola ancora ACCESA: il gradiente
   muore a zero solo al 78% del raggio, ma quel raggio è più lungo del
   box, quindi ai lati e sotto il velo veniva TAGLIATO e si vedeva un
   rettangolo scuro sul legno (screenshot owner).
   Il rimedio è geometrico, non di opacità: `closest-side` ancora il 100%
   del gradiente esattamente al bordo più vicino, e l'ultimo stop è
   trasparente — così l'alfa è zero PRIMA di qualunque bordo, su tutti e
   quattro i lati, a qualunque proporzione della scatola. Il box cresce
   perché la sfumatura ha bisogno di strada per morire. */
.b05-lockup::before{
  content:"";
  position:absolute;
  z-index:-1;
  inset:-34% -26% -40% -26%;
  background:radial-gradient(closest-side at 34% 46%,
    rgba(247,242,233,.86) 0%,
    rgba(247,242,233,.52) 52%,
    rgba(247,242,233,0) 100%);
  pointer-events:none;
}
.b05tisch.is-scrub .b05-lockup::before{
  background:radial-gradient(closest-side at 34% 46%,
    rgba(18,12,6,.74) 0%,
    rgba(18,12,6,.46) 52%,
    rgba(18,12,6,0) 100%);
}

@media (min-width:768px){
  .b05-lockup{ top:clamp(96px, 15svh, 190px); }
}
.b05-num{
  display:block;
  font-family:var(--font-body); font-weight:500;
  font-size:clamp(11px, 1vw, 13px);
  letter-spacing:.16em;
  color:var(--gold);
  margin:0 0 clamp(16px, 2.2vh, 24px) 2px;
}
.b05-head{
  margin:0 0 clamp(20px, 2.6vh, 30px);
  /* 24ch: il lockup non è più una colonna stretta accanto allo stage, sta
     sopra allo stack a tutta larghezza — a 18ch il titolo andava a cinque
     righe e non teneva il passo dell'occhiello di b04 */
  max-width:24ch;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.1;
  letter-spacing:-.005em;
  font-size:clamp(1.6rem, 3.9vw, 2.85rem);
  color:var(--paper);
}
.b05-dot{ color:var(--gold); }
.b05-body{
  margin:0;
  max-width:44ch;
  font-family:var(--font-body);
  font-weight:400;
  font-size:clamp(1rem, 1.1vw, 1.12rem);
  line-height:1.62;
  color:var(--muted);
}

/* ---- marker oro sulla copy ------------------------------------------
   Evidenziatore, non underline: un gradiente oro basso e traslucido che
   si apre da sinistra. background-size parte a 0% e lo anima il JS
   (b05-duo). Senza JS / reduced motion resta aperto, quindi la copy non
   è mai in uno stato invisibile. */
.b05-mark{
  color:var(--paper);
  background-image:linear-gradient(rgba(200,169,110,.52), rgba(200,169,110,.52));
  background-repeat:no-repeat;
  background-position:0 88%;
  background-size:100% .42em;
  box-decoration-break:clone;
  -webkit-box-decoration-break:clone;
  padding:0 .06em;
}
/* IL DUO «Zwei Perspektiven · Ein Moment» — RIMOSSO 2026-08-17.
   Owner sul live: «togli sta roba qua». Erano due cornici (film 16:9 col
   timecode lampeggiante + stampa 4:5) in counter-parallax, coda della
   sezione. Via markup, regole (comprese la @keyframes b05Rec e il blocco
   mobile «tavolo luminoso») e i due ScrollTrigger in js/sections.js.
   b05 chiude sulla scena del tavolo e passa dritta a b06. */

@media (prefers-reduced-motion:reduce){
  .b05-mark{ background-size:100% .42em !important; }
}

/* ====================================================================
   «DER TISCH» — fase B, 17/08. Sostituisce integralmente la pila
   flick-cards (.b05stack / .b05print / .b05stack__count, con la sua
   traccia da 500svh e il suo modulo JS): §L11, il tavolo NON si somma
   al vecchio b05, lo rimpiazza. Qui sotto restano solo i tre pezzi
   nuovi — banda paper-cut, riga oro del lockup, tavolo — più il duo
   di chiusura che sta già sopra.

   Geometria del tavolo: PERCENTUALI, non pixel. Ogni oggetto porta le
   sue coordinate nello style inline (--x/--y/--w per telefono,
   --xd/--yd/--wd per desktop) e lo stage ha un aspect-ratio: la scena
   si scala intera, le sovrapposizioni disegnate restano quelle a
   qualunque larghezza, e il JS non deve ricalcolare niente al resize.
   Mobile-first (§L10): il tavolo di 390 è il progetto — 6 stampe, una
   colonna sola, caduta corta; il desktop aggiunge tre stampe e allarga,
   non allunga.
   ==================================================================== */

/* ---- 1 · IL DIORAMA PAPER-CUT (§L7, asset di Daniel) ----------------
   BANDA STATICA: BOCCIATA due volte («togli ste montagne a caso»).
   Al suo posto la TRANSIZIONE: quattro fogli veri (papercut/MANIFEST.md,
   sky · far · mid · near) che si aprono in profondità mentre si scorre e
   poi passano oltre l'obiettivo, consegnando il tavolo. Sono la testa
   della stessa corsa del tavolo, non una sezione a parte: stanno DENTRO
   il pin e sopra al piano (z-index 3).

   Cosa fa il CSS e cosa fa il JS: qui c'è solo lo stato di riposo —
   composizione a offset 0, scala base 1.12 (MANIFEST: sovradimensionare
   sempre, o la corsa differenziale scopre il bordo di un foglio) con
   cerniera 50% 85%. Tutta la corsa (translate/scale/opacity) la scrive
   il JS in transform: mai `top`, mai `height`, o si perde il compositing.

   Perché il cielo sta FUORI dal riquadro dei monti: il foglio sky è un
   gradiente verticale orizzontalmente uniforme (MANIFEST, limite 4),
   quindi ritagliarlo non costa niente e può coprire tutto il pin — è lui
   che rende la scena opaca sopra il tavolo, ed è lui che, sparendo,
   diventa la carta. Su telefono i monti stanno nella fascia bassa
   (nessun ingrandimento assurdo del panorama a 390px) e il cielo tiene
   il resto dello schermo: è quel cielo che il lockup usa come foglio. */
.b05dio{
  position:absolute;
  inset:0;
  z-index:3;
  overflow:hidden;
  pointer-events:none;
}
/* l'obiettivo: porta l'ultimo affondo e la dissolvenza, tutti i fogli
   insieme e quindi senza differenziale (vedi index.html) */
.b05dio__cam{
  position:absolute;
  inset:0;
  transform-origin:50% 78%;
  will-change:transform, opacity;
}
.b05dio__sheet{
  position:absolute;
  inset:0;
  background-repeat:no-repeat;
  background-size:cover;
  /* ancorati in basso: la corsa cresce verso lo spettatore, il piede
     della valle non si stacca mai dal bordo inferiore.
     Il ritaglio orizzontale su telefono è scelto (24%, non 50%): tiene
     dentro la mezza destra delle guglie e l'imbocco della valle — al
     centro il panorama non ha né le une né l'altra. */
  background-position:24% 100%;
  transform-origin:50% 85%;
  backface-visibility:hidden;
  will-change:transform, opacity;
}
/* il cielo: opaco, tiene tutto il pin, cerniera in basso (non deve mai
   scorrere: è il fondo). Il colore di fondo è il tono alto della lastra,
   così anche fuori dal riquadro dell'immagine non c'è un salto. */
.b05dio__sheet--sky{
  background-color:#f8f1e5;
  background-image:url("../assets/media/papercut/layer-sky-1170.webp");
  transform-origin:50% 100%;
}
/* il riquadro dei monti: su telefono è la fascia bassa dello schermo,
   su desktop è tutto il pin */
.b05dio__frame{
  position:absolute;
  left:0; right:0; bottom:0;
  height:92svh;
}
.b05dio__sheet--far { background-image:url("../assets/media/papercut/layer-far-1170.webp"); }
.b05dio__sheet--mid { background-image:url("../assets/media/papercut/layer-mid-1170.webp"); }
.b05dio__sheet--near{ background-image:url("../assets/media/papercut/layer-near-1170.webp"); }
/* profondità extra senza riesportare (MANIFEST §5): la drop-shadow si
   disegna solo sul bordo alpha — cioè sulla cresta — e viaggia col foglio */
.b05dio__sheet--far { filter:drop-shadow(0 -3px 7px rgba(58,40,22,.14)); }
.b05dio__sheet--mid { filter:drop-shadow(0 -3px 8px rgba(58,40,22,.16)); }
.b05dio__sheet--near{ filter:drop-shadow(0 -4px 10px rgba(58,40,22,.18)); }

/* la lastra grande dove serve davvero: su schermi fitti il riquadro
   mobile ingrandisce il panorama ~2,9× dalla 1170 e le creste si
   impastano. Il taglio è sulla densità, non sulla larghezza. */
@media (min-resolution:1.5dppx), (min-width:768px){
  .b05dio__sheet--sky { background-image:url("../assets/media/papercut/layer-sky.webp"); }
  .b05dio__sheet--far { background-image:url("../assets/media/papercut/layer-far.webp"); }
  .b05dio__sheet--mid { background-image:url("../assets/media/papercut/layer-mid.webp"); }
  .b05dio__sheet--near{ background-image:url("../assets/media/papercut/layer-near.webp"); }
}
@media (min-width:768px){
  .b05dio__frame{ height:100%; }
  .b05dio__sheet{ background-position:50% 100%; }
}

/* ---- 1b · IL PIANO SEQUENZA (fase B3) ------------------------------
   Il dolly nei monti non lo fanno più i quattro fogli: lo fa una ripresa
   sola scrubbata sul canvas (145 frame, assets/frames/tisch/), stesso
   motore dell'hero. Il canvas occupa tutto il pin e ritaglia in cover —
   esattamente come fa il foglio `sky` del diorama, quindi l'inquadratura
   a 390 è quella già approvata in B2.

   GATING DEL PESO, non della sola visibilità: quando il canvas comanda
   (`.is-scrub`, che è lo stato di default del markup) il diorama è
   display:none, quindi il browser NON scarica le quattro lastre
   papercut. Il fallback — reduced-motion, no-JS, frame che non
   arrivano — toglie la classe: solo allora quelle lastre entrano in
   rete. Un percorso alla volta, mai i byte di entrambi.

   Il wrap parte a opacity 0 e la accende il JS al PRIMO blit riuscito:
   così, nel mezzo secondo prima che i frame siano decodificati, non si
   vede né un canvas vuoto né il tavolo scoperto in anticipo. */
/* FASE B5 · IL CANVAS NON È PIÙ UN'APERTURA, È IL PIANO.
   In B3 stava SOPRA a tutto (z-index 3) e se ne andava in dissolvenza
   sul cartone. Ora l'ultimo fotogramma del girato dell'owner è una
   scrivania di noce e resta congelato in scena per tutta la coda:
   quindi il canvas scende sotto allo stage (z-index 1) e le stampe gli
   atterrano SOPRA. Ordine completo dentro il pin:
     0  matwrap  — cartone DOM (solo percorso di fallback)
     1  scrub    — il girato / il piano di noce congelato
     2  light    — la luce dell'obiettivo, ora POSATA SUL LEGNO
     3  stage    — stampe, ombre, striscia, matita
     4  lockup   — il titolo scritto sul tavolo
   (l'orlo crema di uscita che stava sopra a tutto è uscito: vedi
   §USCITA DELLA SEZIONE — NEUTRA, più in basso) */
/* IL WRAP È IL RITAGLIO, e non sborda MAI dal pin.
   Sbagliato al primo giro (visto in qa/shots-20260818-faseB5, giunto a
   390): avevo dato il margine di corsa al wrap, con top/bottom negativi.
   Risultato — sotto all'orlo di uscita, che è ancorato al fondo del pin,
   spuntava una seconda banda di legno alta --tover + la traslazione, cioè
   esattamente il gradino che l'orlo doveva togliere. Il margine sta sul
   CANVAS, dentro un wrap che ritaglia a inset:0: così l'unica cosa che
   può uscire dal pin è niente. */
.b05scrub{
  position:absolute;
  inset:0;
  z-index:1;
  overflow:hidden;
  pointer-events:none;
  /* il tono alto della carta: se il primo frame tarda un fotogramma, sotto
     non c'è un buco ma lo stesso crema del cielo paper-cut */
  background:#f8f1e5;
  opacity:0;
  will-change:opacity;
  /* IL BORDO DI ENTRATA. Il pin comincia con uno spigolo netto: sopra il
     crema della pagina, sotto il cielo del girato — due toni vicinissimi
     (#f7f2e9 / #f8f1e5) ma non uguali, quindi la riga si vede. §L1 dice
     che la sezione non deve «cominciare», deve ENTRARE. 60px di sfumatura
     in cima e lo spigolo sparisce; sotto ci pensa l'orlo. */
  -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 60px);
          mask-image:linear-gradient(to bottom, transparent 0, #000 60px);
}
/* L'USCITA (owner 18/08 sera-2): il noce congelato consegna al crema di
   b06 con un GRADIENT spaziale sul fondo del pin — non un crossfade del
   girato. Sta dentro lo scrub-box (sopra il canvas, sotto stage e
   stampe: z-index del box = 1, lo stage = 3) e si accende solo nella
   coda della corsa: --hemop la scrive il JS (render, u .86→.98), quindi
   è bidirezionale per costruzione e a riposo non vela niente. */
.b05scrub::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:0;
  height:62%;
  background:linear-gradient(to bottom,
    rgba(247,242,233,0) 0,
    rgba(247,242,233,.5) 38%,
    var(--cream) 68%);
  opacity:var(--hemop, 0);
  pointer-events:none;
}
/* il margine di corsa: senza, la traslazione della camera sul tavolo
   (js §LA CAMERA SUL TAVOLO) scoprirebbe il bordo del fotogramma. È
   --tover a dettare sia il margine sia l'ampiezza del movimento — un
   numero e due usi, quindi il piano non può scoprirsi per definizione. */
.b05scrub > canvas{
  display:block;
  position:absolute;
  left:0; right:0;
  top:calc(var(--tover) * -1px);
  width:100%;
  height:calc(100% + var(--tover) * 2px);
  will-change:transform;
}
/* ---- STAMPE NUDE (owner 21/08: «senza polaroid e senza robe bianche»):
   sul Tisch la foto non ha cornice di nessun tipo — ne' la carta bianca
   ne' il fotogramma di pellicola. Resta la foto, il suo spessore e
   l'ombra che la tiene sul piano. La carta bianca vive ancora sul
   ritratto b03 e sulle stampe dell'hero, che non stanno qui. */
/* 25/08: atterraggio USCITO (Daniel: «dove cadono le foto non è un
   granché») — si nascondono SOLO stampe e ombre: lo stage resta in
   scena perché DENTRO ci vive il canvas dello scrub (nasconderlo
   spegneva il dolly — misurato). Il motore dell'atterraggio esce da
   solo sul guard !prints.length. */
.b05tisch .b05tisch__stage .tprint,
.b05tisch .b05tisch__stage .tshadow{ display:none; }
.b05tisch__stage .tprint{
  padding:0;
  background:transparent;
  border-radius:2px;
  box-shadow:
    0 1px 2px rgba(20,14,8,.42),
    0 12px 28px -12px rgba(20,14,8,.58);
}
.b05tisch__stage .tshadow::before{
  padding-top:calc(var(--wcur) * 1% * (.085 + .085 + .94 / var(--ar)));
}

/* nel percorso scrub il piano è il fotogramma di noce: il cartone crema
   non serve più e, se restasse, spunterebbe nell'orlo di uscita sotto al
   legno. Torna da sé quando la classe cade (fallback). */
.b05tisch.is-scrub .b05tisch__matwrap{ display:none; }
.b05tisch.is-scrub .b05dio{ display:none; }
.b05tisch:not(.is-scrub) .b05scrub{ display:none; }
/* percorso DOM: si ripristina l'ordine di B2 alla lettera — il diorama
   (z-index 3) deve coprire lo stage mentre la camera è nella valle */
.b05tisch:not(.is-scrub) .b05tisch__stage{ z-index:2; }
/* reduced-motion: il JS esce prima di armare qualunque cosa, quindi qui
   il canvas resterebbe vuoto per sempre → comanda il diorama composto.
   DIVERGENZA DICHIARATA (fase B5): il fallback NON ha il tavolo di noce,
   ha il cartone crema di B2. Il noce è un fotogramma, non un colore: un
   finto legno in CSS sotto le stampe sarebbe peggio del cartone vero,
   che è una scena coerente e già approvata. Qui si rimette in piedi tutto
   il percorso DOM in blocco. */
@media (prefers-reduced-motion:reduce){
  .b05tisch.is-scrub .b05dio{ display:block; }
  .b05tisch.is-scrub .b05scrub{ display:none; }
  .b05tisch.is-scrub .b05tisch__matwrap{ display:block; }
  .b05tisch.is-scrub .b05tisch__stage{ z-index:2; }
}

/* ---- 2 · la riga oro del lockup ------------------------------------
   Si disegna insieme al lockup, sullo stesso progresso della corsa
   (js/sections.js). Stato di riposo = disegnata: senza JS o in
   reduced-motion non manca niente. */
.b05-rule{
  display:block;
  width:min(200px, 42%);
  height:2px;
  margin:0 0 clamp(18px, 2.4vh, 28px) 2px;
  background:linear-gradient(90deg,
    var(--gold-deep),
    color-mix(in srgb, var(--gold-deep) 22%, transparent));
  transform-origin:0 50%;
}

/* ---- 3 · IL TAVOLO -------------------------------------------------- */
/* LA SCENA È INCOLLATA (owner 17/08: «come se scrollassi e in 3D le foto
   atterrano sul tavolo»). La traccia è alta 100svh + --dolly + --drop: mentre
   la si percorre la scena resta ferma sotto l'obiettivo e lo scroll non
   scorre la pagina, POSA LE STAMPE. Costo dichiarato (§L11): il run è il
   solo prezzo, 160svh su telefono / 180 su desktop — la sezione resta
   comunque ben sotto il b05 di partenza (misure in report).
   Sticky CSS e non pin di GSAP: niente pin-spacer da ricalcolare, ed è
   lo stesso meccanismo che questa pagina usa già altrove. */
.b05tisch{
  /* LA CORSA, IN DUE TEMPI (svh, senza unità: li rilegge anche il JS per
     sapere dove finisce un atto e comincia l'altro — un solo numero, due
     lettori, nessuna deriva).
       --dolly = la testa: la camera entra nella valle di carta
       --drop  = la coda: le stampe si posano sul tavolo (invariata)
     §L11: la testa NON allunga la sezione — è pagata cancellando la banda
     statica e portando il lockup dentro la scena (misure nel report). */
  /* 08/09 (owner: «quello del Tisch possiamo renderlo smooth come quello
     hero che è perfetto?»). Misura: l'hero corre 394 fotogrammi su 200 svh
     = 2 f/svh; il Tisch correva 335 su 70 = 4,8 f/svh — a parità di dito
     chiedeva al decoder 2,4× i fotogrammi, e negli sweep veloci li
     mancava (diagnosi 25/08: miss ~35 %, frame stantio = «si blocca»).
     La testa sale a 150 (≈2,2 f/svh, la densità dell'hero). Costa +80 svh
     di pagina (L11) — è il prezzo della fluidità che l'owner ha scelto. */
  --dolly:150;
  /* 128, non più 160 (owner 18/08 sera-2: «lo spazio dopo la fine del
     video è troppo grande»): dopo l'ultima stampa restava ~24% di corsa
     pinnata vuota. LAST in js/sections.js sale a .52 di pari passo. */
  /* 25/08 Daniel: «dove cadono le foto sul tavolo non è un granché» —
     L'ATTERRAGGIO È USCITO (lo stage delle stampe è display:none e il
     motore in sections.js esce sul guard !prints.length). Le foto ora
     vivono nei NASTRI sotto la scena; la coda del pin resta solo un
     respiro sul tavolo di noce prima di uscire. Era 128/148. */
  --drop:36;
  /* --tover (px, senza unità: lo rilegge anche il JS) = quanto il wrap
     del girato sborda sopra e sotto il pin, ED È ANCHE l'ampiezza della
     camera che scivola sul tavolo di noce. Un numero, due usi: il piano
     non può mai scoprire il proprio bordo perché il margine È la corsa.
     Su telefono è volutamente piccolo: un wrap più alto stringe il
     cover-fit sui lati del 9:16 e la cosa da non sacrificare è il tuffo
     nella valle (§L10). Su desktop il 16:9 ha margine da vendere. */
  --tover:34;
  position:relative;
  width:100%;
  /* base 100lvh, NON svh (owner 18/08 sera-2: «spazio bianco sotto, della
     barra»): su iOS Safari il viewport durante lo scroll è lvh — un pin
     svh lascia scoperta una banda alta (lvh−svh) sotto la scena per tutto
     il tempo del pin. La CORSA (--dolly/--drop) resta in svh: è distanza
     di scroll, non copertura. Legge iOS lvh (memoria ios-lvh-scroll-machine). */
  height:calc(100lvh + (var(--dolly) + var(--drop)) * 1svh);
  /* le stampe alte sono grandi il 50% in più e sforano di lato: si taglia
     dove taglia il viewport. `clip` e non `hidden` — hidden farebbe di
     questo box un contenitore di scroll e ammazzerebbe lo sticky. */
  overflow-x:clip;
  overflow-y:visible;
  /* owner 18/08: niente coda crema fra tavolo e Ablauf. */
  margin:0;
}
/* IL LEGNO STRUTTURALE È USCITO (owner 18/08 sera-2: «togli la roba wood
   sotto, la sezione dopo è chiara; il background come è sempre stato»).
   Il noce vive SOLO dentro il girato: il fotogramma congelato resta il
   piano su cui atterrano le stampe, ma sotto e dopo la sezione c'è il
   crema della pagina. Il giunto verso b06 non è più noce-su-noce: è il
   GRADIENT di uscita sul fondo del pin (.b05scrub::after, opacità
   guidata dal JS sulla coda della corsa) — un gradiente spaziale, non un
   crossfade del girato. */
@media (min-width:768px){
  .b05tisch{ --dolly:170; --drop:42; --tover:70; }
}
.b05tisch__pin{
  position:sticky;
  top:0;
  /* 100lvh, non svh: copre il viewport anche a toolbar collassata (vedi
     il commento sulla height della traccia qui sopra) */
  height:100lvh;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow-x:clip;
  overflow-y:visible;
}

/* la materia: il cartone. Il wrap è la finestra (maschera i due bordi
   nel crema della pagina, così il tavolo non ha una cornice), il mat è
   la lastra che scorre più lenta delle stampe. */
.b05tisch__matwrap{
  position:absolute;
  inset:0;
  z-index:0;
  overflow:hidden;
  pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,
    transparent 0, #000 72px, #000 calc(100% - 96px), transparent 100%);
          mask-image:linear-gradient(to bottom,
    transparent 0, #000 72px, #000 calc(100% - 96px), transparent 100%);
}
.b05tisch__mat{
  position:absolute;
  left:0; right:0;
  /* margine di corsa per lo scorrimento differenziale: il piano non deve
     mai scoprire il proprio bordo dentro la finestra */
  top:-20%; bottom:-20%;
  /* cartone: base fra crema e sabbia (le stampe sono #fffdf8 e devono
     restare più chiare del piano), luce da sinistra-alto, due macchie
     appena accennate perché la superficie abbia struttura riconoscibile
     — è quella che rende leggibile il differenziale in scroll. */
  background-color:#ece2ce;
  background-image:
    radial-gradient(54% 32% at 18% 12%, rgba(255,255,255,.58), rgba(255,255,255,0) 74%),
    radial-gradient(42% 26% at 84% 56%, rgba(150,116,66,.11), rgba(150,116,66,0) 74%),
    radial-gradient(32% 20% at 12% 80%, rgba(150,116,66,.09), rgba(150,116,66,0) 76%),
    url("../assets/media/paper-texture.webp");
  background-repeat:no-repeat, no-repeat, no-repeat, repeat;
  background-size:auto, auto, auto, 720px auto;
  will-change:transform;
}
/* fibra della carta: rumore fine, in multiply — è grana, non velo grigio */
.b05tisch__grain{
  position:absolute;
  inset:0;
  opacity:.24;
  mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='t'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23t)'/%3E%3C/svg%3E");
  background-size:160px 160px;
}
/* la luce della camera: NON scorre col piano (è dell'obiettivo, non del
   tavolo). Fase B5: è uscita dal matwrap e sta sopra al canvas (z-index
   2), perché il piano su cui deve posarsi è il fotogramma di noce.
   Parte spenta e la accende il JS quando la valle consegna il tavolo. */
.b05tisch__light{
  position:absolute;
  inset:0;
  z-index:2;
  pointer-events:none;
  opacity:0;
  will-change:opacity;
  background:
    radial-gradient(122% 74% at 50% 44%,
      rgba(58,46,30,0) 50%, rgba(58,46,30,.075) 78%, rgba(58,46,30,.17) 100%);
}
/* sul NOCE la stessa vignetta bruna al 17% non si vede: il legno è già
   scuro e caldo, un bruno sopra al bruno non fa pozza di luce. Serve un
   nero, e più deciso — è quello che scava il piano attorno alle stampe e
   dice «c'è una lampada sopra questo tavolo». */
.b05tisch.is-scrub .b05tisch__light{
  background:
    radial-gradient(126% 78% at 50% 44%,
      rgba(14,8,3,0) 44%, rgba(14,8,3,.16) 74%, rgba(14,8,3,.42) 100%);
}

/* USCITA DELLA SEZIONE — NEUTRA (owner 18/08, in corsa su questa fase).
   Qui c'era `.b05tisch__hem`: una banda di crema in fondo al pin, sopra
   anche le stampe, che spegneva il tavolo prima dell'unpin per non
   lasciare un gradino noce/crema sul giunto con b06.
   RIMOSSA, e non commentata a metà: b06 (Ablauf) diventerà a sua volta
   MONDO LEGNO — la scrivania prosegue nella sezione successiva. Un
   raccordo verso il crema sarebbe un raccordo verso un colore che fra
   poco non esiste più: lavoro da disfare, e nel frattempo una banda
   chiara in fondo allo schermo per tutta la coda.
   Il legno finisce col finire della sezione. Il giunto vero lo costruisce
   il pass su b06, che è l'unico che sa dove va a parare. */

/* Lo stage NON ha più un aspect-ratio proprio: dentro una scena incollata
   deve stare nello schermo, quindi l'altezza la detta il viewport e la
   larghezza è tappata a 1,6× l'altezza. Così il rapporto del piano è
   sempre ≤1,6 — le coordinate in percentuale delle stampe valgono a
   qualunque viewport (telefono in piedi, desktop, telefono coricato) e
   nessuna sovrapposizione disegnata si rompe. */
.b05tisch__stage{
  position:relative;
  /* fase B5: sopra al canvas — le stampe atterrano SUL legno, non sotto */
  z-index:3;
  width:min(100% - 26px, 1320px, calc(88svh * 1.6));
  height:88svh;
  margin:0 auto;
}
@media (min-width:768px){
  .b05tisch__stage{ width:min(100% - 96px, 1320px, calc(88svh * 1.6)); }
}

/* geometria condivisa: stampa, ombra della caduta e striscia fotobox
   leggono le stesse quattro variabili, quindi l'ombra la può clonare il
   JS copiando lo style e basta.
   La coppia telefono/desktop si sceglie UNA volta qui (--wcur…) e non si
   ripete più giù: sotto, ogni misura interna alla stampa è scritta come
   frazione di --wcur.
   PERCHÉ NON PERCENTUALI SECCHE DENTRO LA STAMPA: questi nodi sono in
   position:absolute, quindi un `padding:3.6%` NON è il 3,6% della stampa
   ma dello STAGE — su desktop (stage 1320) faceva bordi da 47px su carte
   da 343 e la foto si riduceva a un francobollo. `calc(var(--wcur) * 1% *
   K)` invece vale K·larghezza-della-stampa a qualunque viewport, perché
   la larghezza della stampa è essa stessa una percentuale dello stage. */
.tprint,
.tshadow,
.tstrip{
  --xcur:var(--x);
  --ycur:var(--y);
  --wcur:var(--w);
  --rcur:var(--r);
  position:absolute;
  left:calc(var(--xcur) * 1%);
  top:calc(var(--ycur) * 1%);
  width:calc(var(--wcur) * 1%);
  margin:0;
  transform:rotate(calc(var(--rcur) * 1deg));
}
@media (min-width:768px){
  .tprint,
  .tshadow,
  .tstrip{
    --xcur:var(--xd);
    --ycur:var(--yd);
    --wcur:var(--wd);
    --rcur:var(--rd);
  }
}
/* le tre stampe in più del desktop non esistono affatto sul telefono:
   nascoste, restano fuori anche dalla timeline (il JS filtra su
   offsetParent) */
.tprint--wide{ display:none; }
@media (min-width:768px){ .tprint--wide{ display:block; } }

/* la stampa vera: bordo carta più largo sotto, ombra corta di contatto */
.tprint{
  padding:
    calc(var(--wcur) * 1% * .042)
    calc(var(--wcur) * 1% * .042)
    calc(var(--wcur) * 1% * .125);
  background:var(--print);
  border-radius:2px;
  box-shadow:
    0 1px 1px rgba(46,44,40,.10),
    0 5px 12px -6px rgba(46,44,40,.30);
  will-change:transform;
}
.tprint__media{
  position:relative;
  overflow:hidden;
  aspect-ratio:var(--ar);
  background:var(--sand);
}
.tprint__media img{
  display:block;
  width:100%; height:100%;
  object-fit:cover;
}

/* l'ombra della CADUTA: sta sul tavolo, non sulla stampa, quindi è un
   nodo a parte al posto d'atterraggio. Mentre la stampa scende, questa
   si stringe e si scurisce — è l'unica cosa che dice «quanto è alta».
   La costruisce il JS: senza JS resta l'ombra di contatto del CSS. */
.tshadow{
  background:rgba(58,46,30,.5);
  border-radius:6px;
  filter:blur(9px);
  opacity:0;
  pointer-events:none;
  will-change:transform, opacity;
}
/* stessa altezza della stampa senza duplicarne un numero: bordo alto +
   foto (larghezza − 2 bordi, diviso il rapporto) + bordo basso */
.tshadow::before{
  content:"";
  display:block;
  padding-top:calc(var(--wcur) * 1% * (.042 + .125 + .916 / var(--ar)));
}
@media (min-width:768px){
  .tshadow{ filter:blur(14px); }
}

/* dettaglio 1/2 — la striscia della fotobox, mezza fuori dal piano */
.tstrip{
  display:flex;
  flex-direction:column;
  gap:calc(var(--wcur) * 1% * .06);
  padding:
    calc(var(--wcur) * 1% * .07)
    calc(var(--wcur) * 1% * .07)
    calc(var(--wcur) * 1% * .14);
  background:var(--print);
  box-shadow:0 4px 10px -5px rgba(46,44,40,.34);
}
.tstrip img{
  display:block;
  width:100%;
  aspect-ratio:1;
  object-fit:cover;
  filter:grayscale(.5) contrast(1.06);
}
/* owner 18/08 (recording): la striscia finiva sotto la copy a 390 — su
   telefono esce di scena, il tavolo respira. Resta sul desktop, dove il
   tavolo è largo e la copy non la tocca. */
@media (max-width:767px){ .tstrip{ display:none; } }
@media (min-width:768px){
}

/* PERCHÉ TUTTO IL BLOCCO STA DENTRO `prefers-reduced-motion: no-preference`
   e non solo dentro `.is-scrub`: la classe `is-scrub` è nel markup e ci
   RESTA anche in reduced-motion — là il JS esce prima di armare qualsiasi
   cosa, quindi non passa mai da `toDom()`, che è l'unico punto che toglie
   la classe. Risultato del primo giro (preso in castagna in
   qa/shots-20260818-faseB5, m390-reduced-*): il canvas era display:none,
   il piano era di nuovo cartone crema, ma il titolo restava color crema —
   testo invisibile su fondo dello stesso tono.
   La condizione giusta non è «il markup chiede lo scrub», è «lo scrub sta
   davvero girando», e quella coincide con: il moto è permesso. Nel
   percorso di fallback a runtime (frame che non arrivano) ci pensa già la
   classe, che lì cade sul serio. */
@media (prefers-reduced-motion: no-preference){
/* ====================================================================
   FASE B5 · IL CONTRASTO SUL NOCE
   --------------------------------------------------------------------
   Tutta la scena qui sopra è disegnata su CARTONE CREMA: inchiostro
   scuro su fondo chiaro. Col girato dell'owner il piano diventa una
   scrivania di noce (rgb 131,96,67 — misurato sull'ultimo fotogramma),
   e ogni elemento di scena scritto in bruno ci sparisce dentro.
   Le stampe no: hanno il bordo bianco e sul noce POPPANO da sole, anzi
   meglio di prima. Il resto va ribaltato: dove prima c'era inchiostro
   ora c'è crema/gesso, e le ombre — che su carta chiara erano il modo
   di dire «quanto è alta» — sul legno vanno ALLEGGERITE, o si leggono
   come sporco invece che come profondità (l'opacità la taglia il JS,
   qui c'è la materia: più sfocatura, bruno quasi nero al posto del
   bruno medio).
   Tutto sotto `.is-scrub`: se lo scrub ricade sul percorso DOM il piano
   torna cartone e questi override cadono insieme alla classe.
   ==================================================================== */

/* IL LOCKUP STA SUL LEGNO, non prima. Provato a 390 anche l'alternativa
   (titolo sulla valle, prima del freeze): là il testo si posa sul cielo
   di carta mentre la camera sta ancora scendendo e le due cose si
   disturbano — il titolo frena il tuffo, il tuffo trascina via il
   titolo. Sul noce invece il movimento è finito, il piano è fermo e la
   pagina ha un secondo di quiete: è il posto giusto per la frase, e la
   serif crema su legno scuro è il contrasto più alto di tutta la
   sezione. Si scrive quando la luce si accende e se ne va quando
   arrivano le stampe: la coreografia non cambia di una riga. */
/* owner 18/08 sera-3: «leggermente più visibile» — alpha su, e un'ombra
   corta calda che stacca la serif dalla venatura viva del noce */
.b05tisch.is-scrub .b05-head{
  color:#faf4e6;
  text-shadow:0 1px 14px rgba(20,12,4,.38);
}
.b05tisch.is-scrub .b05-body{
  color:rgba(246,238,224,.94);
  text-shadow:0 1px 8px rgba(20,12,4,.32);
}
/* --gold nel tema chiaro è rimappato su --gold-deep (#a5824a) perché
   sul crema l'oro chiaro non passa AA. Sul noce vale l'opposto: il
   gold-deep è quasi il colore del legno e sparisce. Qui torna l'oro
   pieno, che su fondo scuro è l'unica versione leggibile. */
.b05tisch.is-scrub .b05-num,
.b05tisch.is-scrub .b05-dot{ color:#c9a050; }
.b05tisch.is-scrub .b05-rule{
  background:linear-gradient(90deg, #c9a050, rgba(201,160,80,.18));
}
/* l'evidenziatore: su crema era una velatura d'oro sotto il testo scuro,
   sul noce deve invece STACCARE dal legno — stesso gesto, più corpo */
.b05tisch.is-scrub .b05-mark{
  color:#f7efe0;
  background-image:linear-gradient(rgba(201,160,80,.62), rgba(201,160,80,.62));
}

/* le ombre della caduta: più morbide e meno opache (l'alfa la scala il
   JS, §shA0/shA1), ma di un bruno quasi nero — sul legno il differenziale
   si legge solo verso il basso */
.b05tisch.is-scrub .tshadow{
  background:rgba(16,9,3,.62);
  filter:blur(15px);
}
@media (min-width:768px){
  .b05tisch.is-scrub .tshadow{ filter:blur(24px); }
}
/* l'ombra di contatto cotta nel CSS invece va nell'altra direzione: è
   quella che SIEDE la stampa sul piano, e su legno scuro va rinforzata
   o la carta bianca sembra ritagliata e appiccicata */
.b05tisch.is-scrub .tprint{
  box-shadow:
    0 1px 2px rgba(18,10,3,.36),
    0 10px 26px -12px rgba(18,10,3,.62);
}
.b05tisch.is-scrub .tstrip{
  box-shadow:0 8px 20px -10px rgba(18,10,3,.66);
}
}


/* Reduced motion: niente corsa, niente scrub — la scena si SMONTA in tre
   pezzi impilati e tutti e tre sono nello stato finale, visibili:
     1. il panorama composto (offset 0, scala 1: è esattamente la sorgente)
     2. il lockup nel flusso, riga oro disegnata
     3. il tavolo apparecchiato con le stampe posate
   Il JS esce prima di armare qualunque timeline, quindi qui non resta
   nessuno stato di partenza da cui non si uscirebbe. L'ordine visivo lo
   mette `order` sul flex: nel DOM il lockup sta prima dello stage per la
   lettura, a schermo il panorama sta in testa perché è l'apertura. */
@media (prefers-reduced-motion:reduce){
  .b05dio__sheet,
  .b05tisch__mat,
  .b05tisch__light,
  .b05-lockup,
  .tprint{ will-change:auto; }
  .b05tisch{ height:auto; }
  .b05tisch__pin{
    position:static;
    height:auto;
    display:flex;
    flex-direction:column;
    padding:clamp(18px,3vh,40px) 0;
  }
  .b05dio{
    order:-1;
    position:relative;
    inset:auto;
    width:100%;
    aspect-ratio:2400 / 1357;
    margin-bottom:clamp(22px, 4vh, 52px);
  }
  .b05dio__cam{ position:absolute; inset:0; transform:none; opacity:1; }
  .b05dio__frame{ position:absolute; inset:0; height:100%; }
  .b05dio__sheet{ transform:none; }
  /* il pin qui è una colonna nel flusso: una vignetta inset:0 e un orlo
     di uscita ancorati al fondo non hanno più niente da vignettare né da
     spegnere. Escono entrambi, e con loro l'unico stato che il JS —
     che in reduced-motion esce prima di armare qualunque cosa — non
     sarebbe mai venuto ad accendere. */
  .b05tisch__light{ display:none; }
  .b05-lockup{
    position:static;
    max-width:820px;
    margin:0 auto clamp(24px, 4vh, 56px);
    opacity:1;
    transform:none;
  }
  .b05-rule{ transform:none; }
  .b05tisch__stage{
    width:min(100% - 26px, 1320px);
    height:auto;
    aspect-ratio:364 / 743;
  }
  @media (min-width:768px){
    .b05tisch__stage{ width:min(100% - 96px, 1320px); aspect-ratio:1320 / 825; }
  }
}

/* ==== §b05 · LA STAMPA SI PRENDE IN MANO (Daniel 21/08 18:19) ========
   Verbatim: «se uno vuole guardare le foto, può cliccare su e si
   ingrandiscono […] con l'album non lo vedo, un po' complicato, forse
   troppa roba: magari lì farei quello delle montagne e poi appaiono
   queste foto, una roba più semplice».
   Quindi NIENTE album sfogliabile e niente secondo meccanismo di scroll:
   la sezione resta quella (monti → tavolo → stampe che si posano) e
   l'unica cosa che si aggiunge è il gesto più ovvio del mondo — tocchi
   una stampa, la stampa si ingrandisce. Stesso pattern della lightbox
   dei film in b04 (fondo scuro, X in alto a destra, Esc/fondo per
   chiudere), così la pagina ha UN modo solo di aprire le cose.
   Frecce e ← → perché una volta aperta la stampa il gesto successivo è
   «e la prossima?», non «chiudi e ricomincia».
   La misura massima è legata alla sorgente (480x600): oltre ~1,2x la
   stampa si sfoca e il gesto si ritorce contro. Quando Daniel manda i
   file grandi, alzare --lb-max e basta. */
.b05-lb{
  --lb-max:576px;
  position:fixed;
  inset:0;
  /* 130 come la lightbox dei film (§b04): la barra di navigazione sta a
     100, e una lightbox che passa SOTTO la navbar non è una lightbox */
  z-index:130;
  display:flex;
  align-items:center;
  justify-content:center;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity var(--d-photo) ease, visibility 0s linear var(--d-photo);
}
.b05-lb.is--open{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transition:opacity var(--d-photo) ease, visibility 0s;
}
@media (prefers-reduced-motion:reduce){
  .b05-lb{ transition:none; }
}
.b05-lb__bg{
  position:absolute;
  inset:0;
  /* non nero pieno: bruno di legno molto scuro, così l'apertura resta
     dentro il mondo della sezione invece di bucarlo */
  background:rgba(14,9,4,.94);
}
.b05-lb__fig{
  position:relative;
  margin:0;
  max-width:min(92vw, var(--lb-max));
  max-height:84svh;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.9em;
}
.b05-lb__img{
  display:block;
  width:auto; height:auto;
  max-width:min(92vw, var(--lb-max));
  max-height:78svh;
  object-fit:contain;
  border-radius:2px;
  box-shadow:0 24px 60px -20px rgba(0,0,0,.7);
}
.b05-lb__cap{
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:rgba(246,238,224,.62);
  text-align:center;
  max-width:44ch;
}
.b05-lb__close{ position:absolute; top:18px; right:18px; color:#f3ebdc; }
/* le frecce: nodi da 48px (bersaglio del pollice), invisibili finché non
   servono — sul telefono restano ai bordi ma non toccano mai la stampa,
   che è al massimo 92vw */
.b05-lb__nav{
  position:absolute;
  top:50%;
  transform:translateY(-50%);
  width:52px; height:52px;
  display:flex; align-items:center; justify-content:center;
  border:0;
  border-radius:999px;
  background:rgba(247,242,233,.10);
  color:#f3ebdc;
  font-size:20px;
  line-height:1;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.b05-lb__nav--prev{ left:clamp(8px,2vw,28px); }
.b05-lb__nav--next{ right:clamp(8px,2vw,28px); }
@media (hover:hover) and (pointer:fine){
  .b05-lb__nav{ transition:background var(--d-snap) ease; }
  .b05-lb__nav:is(:hover,:focus-visible){ background:rgba(247,242,233,.20); }
}
/* la stampa sul tavolo diventa un oggetto che si prende: il cursore lo
   dice, e su touch non cambia niente (nessun hover, nessun tap-highlight) */
/* 25/08: atterraggio USCITO (Daniel: «dove cadono le foto non è un
   granché») — si nascondono SOLO stampe e ombre: lo stage resta in
   scena perché DENTRO ci vive il canvas dello scrub (nasconderlo
   spegneva il dolly — misurato). Il motore dell'atterraggio esce da
   solo sul guard !prints.length. */
.b05tisch .b05tisch__stage .tprint,
.b05tisch .b05tisch__stage .tshadow{ display:none; }
.b05tisch__stage .tprint{ cursor:zoom-in; }

/* === section:b06-ablauf === */
/* ---- Beat 06 — Ablauf: «MONDO LEGNO» ---------------------------------
   Pass C2, 2026-08-18. Sostituisce integralmente il blocco «il fronte di
   luce» del 13/08 (provino verticale + velo scuro + griglia a due
   colonne). Selettori usciti: .b06-grid, .b06-film, .b06-frame,
   .b06-veil. Rimozione, non commento.

   MANDATO owner: «la next sezione deve avere il colore del legno e va
   rielaborata per qualcosa di più interessante».

   ── IL GROUND ────────────────────────────────────────────────────────
   Non è un marrone scelto: è il piano di b05 che continua. La texture
   viene dall'ULTIMO fotogramma del girato dell'owner (f0335), passata
   per tools/derive-walnut-tile.py — de-illuminata (resta la sola
   venatura) e resa tileabile per roll+crossfade, mai per mirror (su
   venatura orizzontale il mirror disegna una farfalla).

   Il gradiente della lampada NON è cotto nella texture: si rifà qui, con
   lo stesso orientamento del girato (più chiaro a destra, più cupo in
   alto a sinistra). Se stesse nel file si ripeterebbe a ogni tile e
   disegnerebbe una griglia di lampade sul tavolo.

   Il tono di fondo (#8f6c4e) è la MEDIA MISURATA della banda bassa del
   fotogramma, cioè esattamente ciò che il visitatore ha sotto gli occhi
   quando b05 finisce: il giunto non è raccordato, è continuo.

   ── LA GRAMMATICA ────────────────────────────────────────────────────
   Gli step sono SCHEDE DI CARTA appoggiate sulla scrivania: stessa
   anatomia delle stampe di b05 (.tprint) e delle card di b04 (.b04c) —
   superficie --print, raggio 2px, padding proporzionale alla larghezza,
   doppia ombra (una di contatto, una di distacco). Cambia solo che qui
   il piano è scuro, quindi l'ombra è più calda e più profonda.
   Rotazioni ±0,8–1,5°: appoggiate a mano, non allineate a una griglia.

   ── I COLORI SUL LEGNO (misurati a schermo, non sul token) ───────────
   Il ground FINITO — texture + lampada — vale rgb(120,89,61), L 0,115.
   È il valore letto in pagina, non quello del file: la lampada qui sotto
   scurisce, e calcolare i contrasti sul tile nudo darebbe numeri che
   nessuno vede. Contrasti WCAG contro quel legno:
     crema  #f7f2e9  L 0,892  → 5,71:1  ✔ kicker · titolo · promessa · spina
     gold   #c9a050  L 0,382  → 2,62:1  ✘ mai testo — solo il punto e i tratti
     gold-deep #a5824a L 0,245 → 1,79:1 ✘ VIETATO: è quasi il noce (§B5)
   Da qui la regola della sezione: SUL legno si scrive in crema; il
   gold-deep sopravvive solo DENTRO le schede, dove il fondo è carta.
   Quindi: tutto ciò che sta SUL LEGNO è crema; il gold pieno resta un
   accento decorativo (il punto del titolo, il tratto del contatore);
   gold-deep sopravvive solo DENTRO le schede, dove il fondo è carta.

   ── COSA NON C'È ─────────────────────────────────────────────────────
   Nessun pin nuovo (§L11), nessuno sticky, nessuno scroll-jack. La
   sezione è dimensionata dal contenuto: nessuna misura di viewport,
   quindi la legge iOS lvh non la tocca.

   STATO DI DEFAULT = STATO FINALE: spina piena, schede posate e accese,
   promessa in crema. Senza JS o in reduced-motion non manca niente.
   L'unica eccezione è il contatore (decorativo + aria-hidden).

   Porting osmo (osmo/resources/):
     draw-path-on-scroll              → spina disegnata in scrub
     follow-svg-path-on-scroll        → il capo (e il contatore) sul path
     scroll-progress-number           → contatore 00→24 h
     css-only-numbered-list-items     → 01/02/03 da counter CSS
   ---------------------------------------------------------------- */
/* MONDO LEGNO REVOCATO (owner 18/08 sera-2: «togli la roba wood, la
   sezione dopo è praticamente bianca; il background come è sempre
   stato»). Il ground torna il crema della pagina (§L1, ground unico);
   il noce resta SOLO dentro il girato di b05, e il giunto lo fa il
   gradient di uscita del pin. La grammatica delle schede di carta
   resta identica — cambiano solo i colori, che tornano ai token su
   chiaro (ink/muted/gold-deep). */
[data-beat="06"]{
  background:var(--cream);
  /* clip SOLO orizzontale: `clip` e non `hidden` — non deve creare un
     contenitore di scroll. */
  overflow-x:clip;
}

.b06{
  position:relative;
  /* niente overflow:clip qui — lo fa la sezione, e solo in orizzontale */
  padding-top:clamp(40px, 5.5vh, 72px);
  /* niente più raccordo legno→crema da ospitare (crema su crema): la
     coda si stringe — owner 18/08 sera-2, «lo spazio prima della fotobox
     è troppo grande» */
  padding-bottom:clamp(48px, 7vh, 88px);
  isolation:isolate;

  /* geometria — un solo set di variabili, mobile le riscrive.
     La corsia della spina è larga quanto serve al contatore scritto a
     gesso (rail + rail-gap ≥ 30px): un numero e due usi. */
  --shot-col:32%;                       /* la stampa dentro la scheda    */
  --shot-ar:.75;                        /* mobile: 3:4, l'aspetto nativo */
  --card-pad:clamp(11px, 1.5vw, 18px);
  --step-gap:clamp(15px, 2.2vh, 26px);
}

/* IL PIANO — texture reale + luce. Due strati, un solo elemento:
   il gradiente sopra (la lampada del girato), la venatura sotto.

   IL GIUNTO MISURATO È MORTO (owner 18/08 sera: «blocco di legno che sale»:
   l'estensione viaggiava con b06 e su iPhone la misura invecchiava).
   Il legno ora è strutturale su entrambe le sezioni — .b05tisch.is-scrub ha
   lo stesso tile — quindi il piano parte a top:0 e non risale.
   Nessuna misura da invecchiare.

   background-size: derivata, non scelta. Il crop viene da un fotogramma
   1920w; a 1440 quel fotogramma è mostrato a 0,75 ⇒ i 1200px del crop
   valgono 900px a schermo. Su mobile la ladder 9:16 porta lo stesso
   tavolo a 390 con fattore 0,64 ⇒ 780px. Alla texture si chiede la
   grana del tavolo vero, non una grana comoda. */
/* Tile noce + lampada + raccordi (::before/::after/.b06-topblend) USCITI
   col mondo legno (owner 18/08 sera-2): crema su crema non ha cuciture
   da nascondere. Il tile resta su disco (assets/media/desk-walnut-tile.webp)
   e la procedura di calibro della lampada sta in qa/shots-20260818-faseC2. */
.b06-topblend{ display:none; }

/* ---- head: copy approvata, colori nuovi (sta SUL legno) ------------- */
.b06-head{
  position:relative;
  z-index:2;
  max-width:74em;
  margin:0 auto clamp(20px, 3.4vh, 40px);
  padding-inline:clamp(20px, 5vw, 48px);
}
.b06-kicker{
  display:block;
  margin:0 0 clamp(12px, 1.8vh, 22px);
  font-family:var(--font-body); font-weight:500;
  font-size:clamp(10px, 1vw, 12px);
  letter-spacing:.16em;
  text-transform:uppercase;
  /* su crema torna il token dei kicker chiari (stesso di b04/b05) */
  color:var(--gold-deep);
}
.b06-title{
  margin:0;
  max-width:16ch;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.08;
  letter-spacing:-.005em;
  font-size:clamp(1.6rem, 3.9vw, 3.2rem);
  color:var(--ink);
}
/* il gold pieno #C9A050 sopravvive come ACCENTO, mai come testo */
.b06-title .b06-dot{ color:#C9A050; }

/* ---- lo stack (osmo stacking-sticky-cards-bounce, port 18/08) --------
   Le schede sono sticky e si impilano: geometria qui, coreografia
   (rotate/x/y in scrub + pulse elastico) in js/sections.js §b06. */
.b06-stack{
  position:relative;
  z-index:2;
  max-width:74em;
  margin-inline:auto;
  padding-inline:clamp(20px, 5vw, 48px);
}
.b06-stack__list{
  counter-reset:step;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:clamp(46px, 9lvh, 90px);
  margin:0;
  padding:0;
  list-style:none;
}
.b06-stack__item{
  counter-increment:step;
  position:sticky;
  /* sotto la meganav; lvh, non svh: il dock non deve ballare con la
     toolbar iOS */
  top:clamp(88px, 15lvh, 150px);
  width:min(100%, 700px);
}

/* LA CARTA — anatomia di prima (grammatica .tprint/.b04c); il transform
   ora lo scrive GSAP (rotate/x/y del componente), quindi niente rotate
   CSS. L ombra sta sulla carta: il vecchio shadow-sul-<li> viveva sulla
   manopola --rotp, morta col rework. */
.b06-card{
  position:relative;
  display:grid;
  grid-template-columns:var(--shot-col) minmax(0, 1fr);
  align-items:center;
  gap:var(--card-pad);
  padding:var(--card-pad);
  border-radius:2px;
  background:var(--print);
  box-shadow:
    0 1px 2px rgba(46,44,40,.14),
    0 18px 34px -18px rgba(46,44,40,.34);
  will-change:transform;
}
/* il bordo di carta: una riga sottilissima, non un contorno disegnato */
.b06-card::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:2px;
  border:1px solid rgba(46,44,40,.09);
  pointer-events:none;
}

.b06-card__shot{
  position:relative;
  margin:0;
  aspect-ratio:1 / calc(1 / var(--shot-ar));
  overflow:clip;
  background:var(--sand);
  /* la stampa dentro la scheda ha lo stesso segno di contatto delle
     stampe sul tavolo: appoggiata, non incollata */
  box-shadow:0 1px 2px rgba(46,44,40,.14);
}
.b06-card__shot img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center var(--op, 46%);
  filter:saturate(.97) contrast(1.03);
}

.b06-card__body{ min-width:0; }
.b06-step-num{
  display:block;
  margin:0 0 .45em;
  font-family:var(--font-mono); font-weight:400;
  font-size:10.5px;
  letter-spacing:.22em;
  /* DENTRO la scheda il fondo è carta: qui gold-deep è il token giusto
     (è lo stesso della targhetta di b04). Sul legno non compare mai. */
  color:var(--gold-deep);
}
.b06-step-num::before{ content:counter(step, decimal-leading-zero); }
.b06-step-h3{
  margin:0 0 .28em;
  font-family:var(--font-display);
  font-weight:400;
  letter-spacing:0;
  line-height:1.1;
  font-size:clamp(20px, 2.1vw, 32px);
  color:var(--ink);
}
.b06-step-p{
  margin:0;
  font-family:var(--font-body);
  font-size:clamp(14px, 1.1vw, 17px);
  line-height:1.5;
  color:var(--muted);
}

/* ---- la promessa: chiude lo stack ----------------------------------- */
.b06-promise{
  position:relative;
  z-index:2;
  margin:clamp(28px, 4.5vh, 48px) 0 0;
  text-align:center;
  font-family:var(--font-body); font-weight:500;
  font-size:clamp(10px, .95vw, 12px);
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink);
}

/* ---- parità mobile: stesso meccanismo, sole proporzioni diverse ----- */
@media screen and (max-width:767px){
  .b06{
    --shot-col:31%;
    --step-gap:15px;
  }
  .b06-stack__item{ top:clamp(76px, 13lvh, 120px); }
  .b06-step-h3{ font-size:20px; }
  .b06-step-p{ font-size:14.5px; line-height:1.48; }
  .b06-step-num{ font-size:10px; }
}

/* desktop: la stampa torna 3:2 come il resto delle cornici della pagina */
@media screen and (min-width:768px){
  .b06{ --shot-ar:1.5; --shot-col:min(33%, 215px); }
}

/* schermi molto stretti: il testo prima di tutto */
@media screen and (max-width:359px){
  .b06{ --shot-col:29%; }
  .b06-step-h3{ font-size:18px; }
  .b06-step-p{ font-size:14px; }
}

@media (prefers-reduced-motion:reduce){
  /* il JS non parte affatto: le schede restano impilate dal solo sticky,
     senza rotazioni né pulse — già lo stato giusto */
  .b06-card{ box-shadow:0 1px 2px rgba(46,44,40,.14); }
}

/* === section:b07-fotobox === */
/* ---- Beat 07 — Fotobox v2 (2026-08-13) -------------------------------
   La griglia di card 4:5 con sei still è uscita: restano l'intro, il
   girato e «Dein Abzug.». Il resto della sezione (stage full-bleed,
   melt, macro, sorgente pinnata) sta in fondo a questo file, blocco
   «BEAT 07 v2». Le vecchie regole .b07-hero / .b07-f* / .b07-strip* /
   .b07-swipe* / .b07-lamp / .b07-wash sono state rimosse con il merge:
   non avevano più markup. */
[data-beat="07"] .scene-label{ display:none; }

.b07{
  padding:clamp(3.5rem, 8vh, 6rem) 0 clamp(3rem, 7vh, 5rem);
  /* GROUND UNICO (17/08): era un gradiente che a metà sezione valeva
     --shadow (sabbia piena). Fondo piatto come tutte le altre. */
  background:var(--bg);
  /* SOLO orizzontale (era overflow:clip su entrambi gli assi). La pozza
     della lampada nasce a 7% dell'hero, cioè a ~110px dal bordo alto
     della sezione, e ha raggio ~350: un clip verticale la tagliava con
     una riga netta lungo tutto lo schermo. La luce che trabocca in alto
     cade nel nero della sezione precedente e si legge per quello che è. */
  overflow-x:clip;
  overflow-y:visible;
}

/* ---- intro ---------------------------------------------------------- */
/* Lockup d'apertura: copy a sinistra, fotobox a destra. */
/* 2026-08-12: il lockup a due colonne (copy | fotobox) è finito — il girato
   è uscito dal lockup ed è diventato il palcoscenico pinnato qui sotto.
   Resta la sola intro, a colonna singola, che apre la sezione. */
.b07-open{
  width:min(92vw, 1080px);
  margin:0 auto clamp(1.75rem, 4vh, 3rem);
  display:grid;
  grid-template-columns:minmax(0, 1fr);
  align-items:center;
  gap:clamp(1.75rem, 5vw, 4rem);
}
.b07-intro{ margin:0; }
.b07-num{
  display:block;
  font-family:var(--font-body); font-weight:500;
  font-size:.72rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--gold);
  margin-bottom:1.1em;
}
.b07-head{
  margin:0 0 .55em;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.08;
  letter-spacing:-.005em;
  font-size:clamp(2rem, 5.4vw, 4.2rem);
  max-width:16ch;
  color:var(--paper);
}
.b07-dot{ color:var(--gold); }
.b07-body{
  margin:0;
  max-width:52ch;
  font-size:clamp(.95rem, 1.1vw, 1.06rem);
  line-height:1.62;
  color:var(--muted);
}

/* ---- il girato pinnato: vedi il blocco «BEAT 07 v2» in fondo al file
   (.b07-source*, traccia 170svh, scrub sui frame 96→192). Le vecchie
   .b07-swipeStage* / .b07-swipe* / .b07-swipeCap* sono uscite con il
   markup il 2026-08-13. ------------------------------------------------ */
/* ---- finale «Dein Abzug» — RIMOSSO 2026-08-17 (trim L8).
   Era il SECONDO «la stampa esce dalla fessura» della sezione: lo scrub
   del girato è esattamente quel gesto, sul materiale vero. Via le
   .b07-final* e le .b07-print* (carta, slot, bagno di sviluppo)
   insieme al markup e agli override in fondo al file. */

/* ---- mobile: stessa sequenza, stesso gesto, colonna sola ------------ */
@media (max-width:820px){
  .b07{ padding:clamp(3.5rem, 9vh, 6rem) 0 clamp(3rem, 8vh, 5rem); }
  .b07-head{ max-width:none; }
  .b07-body{ max-width:none; }
  .b07-open{
    grid-template-columns:1fr;
    gap:1.5rem;
    margin-bottom:clamp(2.25rem, 6vh, 3.5rem);
  }
}

/* ---- b07 · LE FOTO DELLA CABINA — Depth Tiles (osmo) -----------------
   23/08. Il Layered Slider era una finestra ferma con delle frecce: su
   telefono non succedeva niente finché non lo toccavi. Qui le foto girano
   da sole appena la sezione entra in campo — una avanti, grande, a fuoco;
   le altre indietro, più piccole, ruotate in prospettiva.

   Niente cornici, niente carta: raggio 4px e basta (le polaroid sono
   fuori, owner 22/08). Il buio resta CONTENUTO nella foto, che è la
   regola della sezione dal 17/08.

   Le misure sono quelle di 390, il desktop è l'adattamento. */
.b07-shots{
  width:100%;
  margin:clamp(1.75rem, 5vh, 3.25rem) auto 0;
  -webkit-user-select:none; user-select:none;
}
/* il palco: le tessere di lato escono dalla colonna del testo ed è
   giusto così — quello che non devono fare è allargare la pagina.
   `overflow-x:clip` sta già su .b07 (sezione), qui basta non creare
   contesti che lo rompano. */
.b07-shots__stage{
  position:relative;
  display:flex;
  justify-content:center; align-items:center;
  padding-block:clamp(.5rem, 2vh, 1.25rem);
  /* l'orbita si trascina in orizzontale (Draggable in js/b07-shots.js);
     il dito che scorre in VERTICALE resta al browser — stessa legge
     dell'archivio b05 */
  touch-action:pan-y;
}
@media (hover:hover) and (pointer:fine){
  .b07-shots[data-drag] .b07-shots__stage{ cursor:grab; }
  .b07-shots[data-drag="grabbing"] .b07-shots__stage{ cursor:grabbing; }
}
.b07-shots__list{
  display:grid;
  place-items:center;
}
.b07-shots__tile{
  grid-area:1 / 1;              /* tutte nella stessa cella: è l'orbita */
  margin:0;
  display:flex;
  align-items:center; justify-content:center;
  width:max-content; height:max-content;
  /* solo transform: opacity e filter non li tocca più nessuno (vedi
     js/b07-shots.js) e promettere al compositore proprietà che non
     cambiano è memoria buttata su un telefono che sta già decodificando
     due video */
  will-change:transform;
  cursor:zoom-in;
}
.b07-shots__card{
  position:relative;
  display:block;
  /* 9:16 = la forma dello schermo della cabina, e il formato nativo di
     tre foto su quattro. La quarta (3:4) è ritagliata sul lato, con
     l'object-position scritta nel markup per non perdere la cabina. */
  /* 23/08, owner: «rendile un po' più piccole». A 72vw la tessera davanti
     mangiava lo schermo e delle altre restavano due schegge nere ai bordi:
     l'orbita non si leggeva. A 56vw (218px a 390) le vicine entrano intere
     — si vedono TRE foto, e il fatto che girino si capisce senza aspettare
     il passo successivo. */
  width:clamp(180px, 56vw, 240px);
  aspect-ratio:9 / 16;
  border-radius:4px;
  overflow:hidden;
  background:#0c0a08;
  box-shadow:0 26px 60px -32px rgba(28,20,10,.6);
}
.b07-shots__img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  -webkit-user-drag:none;
  pointer-events:none;
}
/* la didascalia vive DENTRO la foto e si accende solo su quella davanti:
   una riga sola in tutta la sezione, mai quattro didascalie insieme.
   Lo stato lo scrive il componente (data-depth-tiles-item-status). */
.b07-shots__cap{
  position:absolute; inset:auto 0 0 0;
  z-index:2;
  padding:2.6rem 1rem .9rem;
  font-family:var(--font-body); font-weight:500;
  font-size:.6rem; letter-spacing:.14em; text-transform:uppercase;
  text-align:center;
  color:rgba(247,242,233,.94);
  background:linear-gradient(to top,
    rgba(9,7,5,.86) 0%, rgba(9,7,5,.42) 52%, rgba(9,7,5,0) 100%);
  opacity:0;
  transition:opacity .5s ease;
  pointer-events:none;
}
[data-depth-tiles-item-status="active"] .b07-shots__cap{ opacity:1; }

.b07-shots__hint{
  margin:clamp(.9rem, 3vh, 1.5rem) 0 0;
  text-align:center;
  font-family:var(--font-body); font-weight:500;
  font-size:.58rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted);
}

/* le tre promesse (ex-didascalie dello scrub): una riga, non tre schermate */
.b07-shots__promises{
  list-style:none;
  margin:clamp(1rem, 3.4vh, 1.8rem) 0 0;
  padding:0;
  display:flex; flex-wrap:wrap;
  justify-content:center;
  gap:.45rem 1.6rem;
  font-family:var(--font-body);
  font-size:.66rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted);
}
.b07-shots__promises b{ color:var(--gold); font-weight:500; margin-right:.6em; }

@media (min-width:821px){
  .b07-shots__card{ width:clamp(220px, 19vw, 286px); }
}

/* SENZA MOTORE: le tessere sono impilate nella stessa cella e si vedrebbe
   solo l'ultima. Restano visibili la prima (davanti) e la sua didascalia:
   quello che si vede senza JS è una foto vera, non una pila muta. */
.b07-shots:not(.is--on) .b07-shots__tile{ opacity:0; }
.b07-shots:not(.is--on) .b07-shots__tile:first-child{ opacity:1; }
.b07-shots:not(.is--on) .b07-shots__tile:first-child .b07-shots__cap{ opacity:1; }

/* === section:b08-wunschtermin === */
/* Sezione rimossa dall'HTML 2026-08-11 (kalender/timbri VERGEBEN). Lo
   stile del timbro vive ora in .anfrage-stamp, section:b09-form-footer. */
/* === section:b09-form-footer === */
/* ===== BEAT 09 — Anfrage + Footer (osmo live-form-validation-advanced + footer-parallax-effect, dark-themed) ===== */
.b09{ min-height:0; background:var(--bg); color:var(--paper); overflow:hidden; position:relative; }
.b09 .scene-label{ display:none; }
.b09__inner{ position:relative; z-index:2; }

/* ---- osmo card around the form --------------------------------------- */
.b09-form-wrap{
  background:var(--print);
  border:1px solid var(--line);
  border-radius:8px;
  padding:clamp(22px,3vw,40px);
  box-shadow:0 24px 60px rgba(46,44,40,.14);
}
.b09__inner{
  max-width:1280px; margin:0 auto;
  padding:clamp(72px,12vw,160px) clamp(20px,6vw,80px) clamp(64px,9vw,120px);
  display:grid;
  grid-template-columns:minmax(300px,.9fr) 1.1fr;
  gap:clamp(36px,5vw,88px);
  align-items:start;
}
@media (max-width:960px){ .b09__inner{ grid-template-columns:1fr; } }

/* --- lockup (asymmetric) --- */
.b09__head{ max-width:760px; margin-bottom:0; position:sticky; top:120px; }
@media (max-width:960px){ .b09__head{ position:static; margin-bottom:clamp(28px,5vw,44px); } }
.b09__kicker{ font-family:var(--font-body); font-weight:500; font-size:.72rem; letter-spacing:.16em; text-transform:uppercase; color:var(--gold); margin:0 0 clamp(18px,2.5vw,28px); }
.b09__title{ font-family:var(--font-display); font-weight:400; line-height:1.06; letter-spacing:-.005em; font-size:clamp(2.1rem,6.6vw,4.6rem); color:var(--paper); margin:0; }
.b09__dot{ color:var(--gold); }
.b09__lead{ font-family:var(--font-body); font-weight:400; color:var(--muted); font-size:clamp(1rem,1.4vw,1.12rem); line-height:1.6; max-width:34ch; margin:clamp(20px,2.6vw,28px) 0 0; }

/* ---- scarsità (ex-b08 kalender, rimosso 2026-08-11) — una riga sobria,
   nessuna griglia: la frase + un timbro decorativo a fianco. ---- */
.b09-scarcity{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:.9em;
  margin:clamp(16px,2.2vw,22px) 0 0;
  max-width:40ch;
}
.b09-scarcity__text{
  margin:0;
  font-family:var(--font-body); font-weight:500;
  font-size:.8rem;
  letter-spacing:.05em;
  line-height:1.5;
  color:var(--muted);
}
/* timbro — stile portato pari pari da .b08-date__stamp prima della rimozione
   della sezione: inchiostro oro, bordo mangiato, nessuna immagine. Qui è
   statico e decorativo (non scrubbato dallo scroll), rotazione fissa -8deg. */
.anfrage-stamp{
  display:inline-block;
  flex:none;
  padding:.3em .52em .26em;
  font-family:var(--font-body); font-weight:500;
  font-size:.62rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  white-space:nowrap;
  color:var(--gold);
  border:2px solid color-mix(in srgb, var(--gold) 78%, transparent);
  border-radius:2px;
  background:color-mix(in srgb, var(--gold) 7%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--gold) 22%, transparent),
    inset 0 0 7px color-mix(in srgb, var(--gold) 16%, transparent);
  text-shadow:0 0 5px color-mix(in srgb, var(--gold) 40%, transparent);
  -webkit-mask-image:radial-gradient(128% 150% at 24% 12%, #000 52%, rgba(0,0,0,.52) 100%);
          mask-image:radial-gradient(128% 150% at 24% 12%, #000 52%, rgba(0,0,0,.52) 100%);
  transform:rotate(-8deg);
}

/* --- form shell --- */
.b09-form-wrap{ max-width:none; margin-left:0; }
.b09-form{ display:flex; flex-direction:column; gap:clamp(18px,2.4vw,24px); }
.b09-form__row{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(14px,2vw,20px); }
.b09 .form-field-group{ display:flex; flex-direction:column; gap:10px; }
.b09 .form-label{ font-family:var(--font-body); font-weight:500; font-size:.68rem; letter-spacing:.16em; text-transform:uppercase; color:var(--muted); }
.b09 .form-required{ color:var(--gold); }
.b09 .form-optional{ color:color-mix(in srgb, var(--muted) 72%, transparent); letter-spacing:.12em; }
.b09 .form-field{ position:relative; }

.b09 .form-input{
  width:100%; box-sizing:border-box;
  font-family:var(--font-body); font-size:1rem; color:var(--paper);
  background:var(--shadow);
  border:1px solid var(--line);
  border-radius:2px;
  padding:15px 44px 15px 16px; min-height:52px;
  transition:border-color .25s ease, background .25s ease, box-shadow .25s ease;
  -webkit-appearance:none; appearance:none;
}
.b09 .form-input::placeholder{ color:color-mix(in srgb, var(--muted) 62%, transparent); }
@media (hover:hover) and (pointer:fine){
  .b09 .form-input:hover{ border-color:color-mix(in srgb, var(--gold) 55%, var(--line)); }
}
/* FOCUS SU CARTA (17/08). Prima: `outline:none` + un alone da 1px al 35%
   di opacità — su un fondo `--print` quasi bianco quell'anello era sotto
   la soglia del visibile, e chi naviga da tastiera perdeva il segno.
   Ora il bordo diventa oro pieno e l'anello è da 2px opaco; il
   `:focus-visible` aggiunge l'outline vero, che è quello che i tester di
   accessibilità cercano e che il puntatore non fa comparire. */
.b09 .form-input:focus{
  outline:none;
  border-color:var(--gold-deep);
  box-shadow:0 0 0 2px rgba(165,130,74,.55);
  background-color:var(--print);
}
.b09 .form-input:focus-visible{
  outline:2px solid var(--gold-deep);
  outline-offset:2px;
}
.b09 textarea.form-input.is--textarea{ min-height:132px; resize:vertical; line-height:1.55; padding-top:14px; }
.b09 input[type=date].form-input{ color-scheme:light; }

/* select — custom caret so it doesn't read as a broken input */
.b09 select.form-input{
  cursor:pointer; padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%232e2c28' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center;
}

/* phone: prefix + number */
.b09-phone{ display:flex; gap:10px; }
.b09-phone__code{ flex:0 0 96px; text-align:center; padding-left:12px; }
.b09-phone__num{ flex:1 1 auto; }

/* validation icons (osmo contract) */
.b09 .form-field-icon{ position:absolute; top:15px; right:14px; width:22px; height:22px; display:none; pointer-events:none; }
.b09 .form-field-group.is--success .form-input{ border-color:rgba(165,130,74,.7); }
.b09 .form-field-group.is--success .form-field-icon.is--success{ display:block; color:var(--gold); }
.b09 .form-field-group.is--error .form-input{ border-color:#C0563D; }
.b09 .form-field-group.is--error .form-field-icon.is--error{ display:block; color:#C0563D; }
.b09 .is--textarea ~ .form-field-icon{ top:auto; bottom:14px; }

/* submit — button-025 not in vault; osmo form-submit-btn styled as gold pill */
.b09 .form-submit-btn{
  position:relative; margin-top:clamp(6px,1vw,12px);
  display:inline-flex; align-items:center; justify-content:center; gap:12px;
  align-self:flex-start;
  font-family:var(--font-body); font-weight:500; font-size:.78rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink); background:var(--gold2);
  border:1px solid var(--gold); border-radius:999px;
  padding:16px 34px; min-height:52px; cursor:pointer; overflow:hidden;
  transition:transform .3s cubic-bezier(.76,0,.24,1), background .3s ease, color .3s ease;
}
.b09 .form-submit-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
.b09 .form-submit-btn-arrow{ transition:transform .3s cubic-bezier(.76,0,.24,1); }
/* l'inversione oro→trasparente è un effetto puntatore: su touch il :hover
   resta appiccicato dopo il tap e il bottone rimane svuotato. */
@media (hover:hover) and (pointer:fine){
  .b09 .form-submit-btn:hover{ background:var(--ink); color:var(--cream); border-color:var(--ink); }
  .b09 .form-submit-btn:hover .form-submit-btn-arrow{ transform:translateX(4px); }
}
.b09 .form-submit{ position:absolute; inset:0; opacity:0; width:100%; height:100%; border:0; background:none; cursor:pointer; pointer-events:none; }

/* notifications */
.b09 .form-notifcation{ display:none; align-items:center; gap:14px; margin-top:8px; padding:22px 24px; border-radius:3px; background:var(--shadow); border:1px solid rgba(201,160,80,.45); }
.b09 .form-notifcation.is--error{ border-color:rgba(192,86,61,.5); }
.b09 .form-notification-icon{ width:26px; height:26px; flex:0 0 auto; color:var(--gold); }
.b09 .form-notification-p{ margin:0; font-family:var(--font-body); font-size:1rem; color:var(--paper); line-height:1.5; }
.b09 .w-form-fail .form-notification-p{ color:var(--muted); }

/* ===== footer (osmo footer-parallax-effect, dark) ===== */
.b09-footer-wrap{ position:relative; background:var(--bg); overflow:hidden; padding-top:clamp(24px,6vw,80px); }
.b09-footer{ position:relative; z-index:2; max-width:1320px; margin:0 auto; padding:clamp(48px,7vw,96px) clamp(20px,6vw,80px) clamp(24px,3vw,36px); border-top:1px solid color-mix(in srgb, var(--gold) 30%, transparent); }

/* top: brand block left, link columns right */
.b09-footer__top{
  position:relative; z-index:2;
  display:grid;
  grid-template-columns:minmax(200px,.9fr) 2fr;
  gap:clamp(32px,5vw,88px);
  align-items:start;
  padding-bottom:clamp(40px,5vw,72px);
}
.b09-footer__brand{ display:flex; flex-direction:column; gap:18px; }
.b09-footer__logo{ width:clamp(84px,8vw,116px); height:auto; display:block; opacity:.96; }
.b09-footer__claim{
  margin:0; max-width:22ch;
  font-family:var(--font-body); font-size:1rem; line-height:1.6;   /* .92rem→1rem: 16px floor mobile */
  color:var(--muted);
}
.b09-footer__dot{ color:var(--gold); }
.b09-footer__cols{ display:grid; grid-template-columns:repeat(4,auto); gap:clamp(24px,3.4vw,56px); justify-content:end; }

/* L'ULTIMA SCENA — i titoli di coda (owner 25/08) ---------------------
   eyebrow mono → wordmark monumentale che si scopre dentro la maschera →
   firma Caveat appoggiata sopra, come una stampa firmata. Stati di
   partenza scritti dallo scrub (js/sections.js §footer parallax): la
   base CSS mostra tutto — reduced-motion e no-JS non perdono niente. */
.b09-footer__word{ position:relative; z-index:2; }
.b09-footer__word-eyebrow{
  margin:0 0 clamp(10px,1.4vw,18px) 2px;
  font-family:var(--font-mono);
  font-size:clamp(.62rem, .8vw, .74rem);
  letter-spacing:.26em;
  text-transform:uppercase;
  color:var(--gold);
}
.b09-footer__wordmask{
  overflow:hidden;
  border-bottom:1px solid var(--line);
}
.b09-footer__wordmark{
  margin:0;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1;
  letter-spacing:-.01em;
  font-size:clamp(2.8rem, 10vw, 10rem);
  color:var(--paper);
  white-space:nowrap;
  padding-bottom:clamp(20px,3vw,40px);
  will-change:transform;
}
.b09-footer__sign{
  position:absolute;
  right:clamp(6px, 3vw, 48px);
  top:-.4em;
  font-family:'Caveat', 'Bradley Hand', cursive;
  font-weight:500;
  font-size:clamp(1.7rem, 3.2vw, 2.8rem);
  color:var(--gold);
  transform:rotate(-5deg);
  pointer-events:none;
}

/* legal strip */
.b09-footer__legal{
  position:relative; z-index:2;
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:12px 28px;
  padding-top:clamp(16px,2vw,24px);
  font-family:var(--font-body); font-weight:500; font-size:.72rem; letter-spacing:.08em;
  color:color-mix(in srgb, var(--muted) 78%, transparent);
}
.b09-footer__eyebrow{ font-family:var(--font-body); font-weight:500; font-size:.68rem; letter-spacing:.16em; text-transform:uppercase; color:var(--gold); margin:0 0 14px; }
.b09-footer__body{ font-family:var(--font-body); font-weight:500; font-size:1rem; letter-spacing:.02em; line-height:1.6; color:var(--muted); margin:0; }   /* .86rem→1rem: 16px floor mobile */
/* Bersaglio da 44px sul telefono senza toccare il ritmo tipografico: il
   padding allarga l'area di tocco, il margine negativo lo riassorbe, quindi
   la riga resta esattamente dov'era. Anche su max-width (non solo pointer:
   coarse, 2026-08-11): alcuni contesti mobile-viewport riportano hover:hover
   / pointer:fine, la regola non scattava mai lì. */
.b09-footer__link{ color:var(--muted); text-decoration:none; transition:color .25s ease; }
@media (hover:none), (pointer:coarse), (max-width:768px){
  .b09-footer__link{ display:inline-block; padding-block:15px; margin-block:-15px; }
}
@media (hover:hover) and (pointer:fine){
  .b09-footer__link:hover{ color:var(--gold); }
}
/* la chiusura del footer: era sabbia piena, cioè l'ultimo gradino di
   colore della pagina. Stessa velatura di b03 (GROUND UNICO, 17/08). */
.b09-footer-wrap__dark{ position:absolute; inset:0; z-index:1; background:var(--ground-2); pointer-events:none; }

/* ===== mobile ===== */
@media (max-width:768px){
  .b09-form-wrap{ margin-left:0; }
  .b09-form__row{ grid-template-columns:1fr; }
  .b09__lead{ max-width:none; }
  .b09-footer__top{ grid-template-columns:1fr; gap:32px; }
  .b09-footer__cols{ grid-template-columns:1fr 1fr; gap:28px; justify-content:start; }
  .b09-footer__wordmark{ font-size:clamp(2rem, 10.5vw, 3.4rem); white-space:normal; }
  /* col wordmark a capo la firma non ha più un angolo libero sopra:
     scende sotto la riga, allineata a destra, da elemento di chiusura */
  .b09-footer__sign{
    position:static;
    display:block;
    text-align:right;
    margin-top:10px;
    transform:rotate(-3deg);
  }
  .b09-footer__legal{ flex-direction:column; }
  .b09 .form-submit-btn{ align-self:stretch; width:100%; }
}
@media (max-width:390px){
  .b09__inner{ padding-left:18px; padding-right:18px; }
  .b09 .form-input{ font-size:16px; } /* prevent iOS zoom */
}

/* ===== reduced motion ===== */
@media (prefers-reduced-motion:reduce){
  .b09 .form-submit-btn, .b09 .form-submit-btn-arrow, .b09 .form-input, .b09-footer__link{ transition:none; }
  .b09-footer, .b09-footer-wrap__dark,
  .b09-footer__wordmark, .b09-footer__word-eyebrow, .b09-footer__sign{ transform:none !important; opacity:1 !important; }
}

/* === section:cursor-global === */
/* ===================================================================
 * cursor-global — osmo easings port + custom cursor + grain overlay
 * =================================================================== */

/* (1) osmo/easings/easings.css — ported verbatim (:root ease tokens).
 *     Now available to every CSS transition in the build. */
:root{
  /* Osmo Favorites */
  --ease-osmo: cubic-bezier(0.625, 0.05, 0, 1);
  --ease-energy: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-smooth: cubic-bezier(0.38, 0.005, 0.215, 1);
  --ease-punch: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-relaxed: cubic-bezier(0.7, 0, 0.3, 1);
  --ease-jump: cubic-bezier(0.35, 1.5, 0.6, 1);
  --ease-pop: cubic-bezier(0.17, 0.67, 0.3, 1.33);
  --ease-anticipate: cubic-bezier(0.8, -0.4, 0.5, 1);
  --ease-fade: cubic-bezier(0.25, 0.1, 0.25, 1);
  /* GSAP curves */
  --ease-power2-out: cubic-bezier(0.33, 1, 0.68, 1);
  --ease-power2-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-power3-out: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-power4-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-expo-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-expo-inout: cubic-bezier(0.87, 0, 0.13, 1);
  --ease-circ-out: cubic-bezier(0, 0.55, 0.45, 1);
  --ease-back-out: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* (1b) Ease-param swap on the EXISTING loader transition.
 *      main.css: `.loader{ transition:opacity .6s ease, visibility .6s ease }`
 *      + `@media (prefers-reduced-motion:reduce){ .loader{ transition:none } }`
 *      Retarget the default `ease` to the osmo signature curve ONLY when motion
 *      is allowed, at plain `.loader` specificity — so the existing
 *      reduced-motion `transition:none` guard keeps winning for RM users
 *      (bumping to `html .loader` would out-specify and re-enable the fade). */
@media (prefers-reduced-motion: no-preference){
  .loader{
    transition: opacity .6s var(--ease-osmo), visibility .6s var(--ease-osmo);
  }
}

/* (2) Custom cursor RIMOSSO (owner law 2026-07-15: mai custom cursor — cursore nativo) */

/* (3) Grain — data-uri fractal noise, .04, over the media, never over UI chrome */
.grain{
  position:fixed;
  inset:0;
  z-index:40;
  pointer-events:none;
  opacity:.04;
  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='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}


/* === section:nav-scroll === */
/* Qui c'erano, nell'ordine: la PILLOLA NAV MOBILE (.navpill, 12/08,
   rimossa il 13/08), la guardia reduced-motion dell'auto-hide e tutta la
   SALA BUIA .mnav-ov (l'overlay mobile della meganav).
   Tutto rimosso con la Fase A2: l'auto-hide direzionale non c'è più
   (LEGGE §L4 «wayfinding sempre visibile»: la barra dopo l'hero resta) e
   il menu del telefono è il pannello osmo scaling-hamburger, che vive in
   §section:nav insieme al resto della barra. */

/* ---- IL LOGO SULLA CARTA (2026-08-17) --------------------------------
   assets/logo.webp è la pellicola in oro PIÙ la scritta «DANIEL SOCIN ·
   FILM & FRAMES» in BIANCO: nato per il fondo nero. Su crema la parte
   bianca sparisce e resta un mezzo marchio.
   Finché non c'è una variante monocroma dell'asset, in zona chiara il logo
   si legge come una silhouette d'inchiostro — che è comunque un modo, non
   un ripiego: sulla carta i marchi si stampano in un colore solo.
   (La stessa regola per la barra sta in §section:nav.)
   DA CHIEDERE A DANIEL: il logo in versione scura/one-color. */
.theme-light .b09-footer__logo{
  filter:brightness(0);
  opacity:.86;
}

/* ==== BEAT 07 v2 — mergiato il 2026-08-13 da proto/b07-v2.css ==== */
/* ====================================================================
   hochzeit-v3 — css/main.css · blocco BEAT 07 v2 (da proto/b07-v2.css)
   BEAT 07 — Fotobox v2. Mergiato il 2026-08-13.

   Sostituisce interamente il blocco b07 di css/main.css a valle di
   .b07-open (vecchie .b07-hero / .b07-f / .b07-strip / .b07-swipe*) e il
   prototipo «Der Faden» (bocciato: nessun tracciato SVG decorativo qui).

   LA TESI
   Gli asset di assets/fotobox/ esistono già in coppia landscape 16:9 +
   portrait 0.8 e non erano mai stati usati per quello che sono: due crop
   pensati per andare a piena larghezza su desktop e su telefono. Finora
   erano francobolli dentro card. Qui l'immagine È il contenuto: tre
   momenti, tre blocchi di copy, zero griglia.

   LE MISURE CHE HANNO DECISO IL LAYOUT
   · macro-licht.webp / macro-print.webp = 1440×804 → a 1440 di viewport
     un full-bleed vale 804px, l'89% di uno schermo 1440×900. Il crop era
     stato inquadrato per questo: il soggetto sta a sinistra/centro e la
     destra è nero → è lì che va la copy.
   · macro-*-45.webp = 1400×1751 (0,7995) → a 390 di viewport valgono
     390×488 SENZA UN PIXEL DI CROP. La copy va in basso, sul corpo scuro.
   · open-45.webp = 1400×1751, angoli #1b130d contro il #0B0A09 della
     pagina → la maschera scioglie i bordi e non serve nessuna cornice.
   · gli angoli di macro-print-45 a destra sono #303a44 (il fianco blu
     della cabina): in full-bleed il bordo è fuori schermo, quindi non si
     legge come «bordo di una foto». Un altro motivo per non incorniciare.

   PALETTE E TIPI: quelli del progetto (:root di main.css).
   ==================================================================== */

.b07--v2{
  --b07v2-gutter: clamp(1.25rem, 6vw, 5rem);
  --b07v2-rhythm: clamp(2.75rem, 9vh, 6.5rem);

  /* IL FONDO È LA CARTA. La sezione porta `.theme-light`, quindi `--bg`
     vale già --cream: qui basta dichiararlo per battere il gradiente
     scuro che main.css dava a `.b07` (era 180deg #0B0A09 → #1A140E →
     #0B0A09, il fondale della vecchia direzione).
     17/08, owner: «anche la fotobox deve stare su fondo chiaro come il
     resto del sito». L'alternanza crema/nero della sezione — che prima
     succedeva tre volte — non esiste più: il buio vive solo DENTRO le
     due cornici (la macro e la sorgente). */
  background:var(--bg);
}

/* Verificato: le regole di main.css che vestivano i vecchi still
   (.b07-hero, .b07-hero__img, .b07-f__media, .b07-f__media img) NON
   selezionano niente qui — le classi non esistono più nel markup v2.
   Nessun neutralizzatore necessario, e uno generico su `img` avrebbe avuto
   specificità (0,2,1) e battuto le regole legittime qui sotto.

/* --------------------------------------------------------------------
   Lo stage: un momento. Nessuna card, nessun bordo, nessun radius.
   -------------------------------------------------------------------- */
.b07v2-stage{
  position:relative;
  margin:0;
  width:100%;
}
.b07v2-stage + .b07v2-stage{ margin-top:var(--b07v2-rhythm); }
.b07-open + .b07v2-stage{ margin-top:clamp(1.5rem, 5vh, 3rem); }

/* ====================================================================
   IL FLIP CHIARO DI b07 — 2026-08-17 (owner sul live: «anche la fotobox
   deve stare su fondo chiaro come il resto del sito»).
   --------------------------------------------------------------------
   PRIMA: la macro era FULL-BLEED e la sezione alternava crema e nero tre
   volte; il testo stava SOPRA l'immagine, in chiaro, con text-shadow e
   scrim. Il buio era l'AMBIENTE della pagina.
   ORA: il buio è CONTENUTO. La figure diventa una stampa — carta
   `--print`, raggio 2px, la stessa doppia ombra di `.tprint` (b05) e
   delle card di b04 — la foto sta dentro, la didascalia sotto SULLA
   carta, in inchiostro. Niente scrim, niente text-shadow, niente
   maschera-feather: la cucitura fra immagine e pagina non esiste più
   perché c'è un bordo dichiarato.
   È rimasta UNA sola macro (il touchscreen): l'oggetto e la macro della
   lampada sono usciti col trim L8, e con loro le regole
   `.b07v2-object*`, il pool della lampada e gli override di
   «Dein Abzug» — rimosse, non commentate.

   TODO — asset fotobox con SFONDO CHIARO da rigenerare (Blender/
   Higgsfield): oggi i render e il girato hanno il fondale nero della
   vecchia direzione, e su una pagina di carta restano una finestra di
   buio. Interim accettato dall'owner: media scuro CONTENUTO in cornice.
   Quando arrivano gli asset chiari, qui cambia solo il contenuto della
   cornice — la cornice resta.
   ==================================================================== */

/* la didascalia: non è più uno slot sovrapposto ma una fascia sulla carta */
.b07v2-slot{
  position:static;
  display:block;
  margin:0;
  padding:clamp(.9rem, 3.2vw, 1.5rem) 2px clamp(.2rem, 1vw, .5rem);
  pointer-events:auto;
}
.b07v2-cap{
  max-width:56ch;
  will-change:transform, opacity;
}
.b07v2-cap__kicker{
  display:block;
  margin:0 0 .8em;
  font-family:var(--font-mono);
  font-size:clamp(.6rem, 2.6vw, .7rem);
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--gold-deep);
}
.b07v2-cap__head{
  margin:0 0 .34em;
  font-family:var(--font-display);
  font-weight:400;
  line-height:1.08;
  letter-spacing:-.005em;
  /* più piccola di prima: non deve più reggere una piena larghezza di
     immagine, sta in una didascalia larga quanto la stampa */
  font-size:clamp(1.35rem, 4.8vw, 2.1rem);
  color:var(--ink);
  text-shadow:none;
}
.b07v2-cap__text{
  margin:0;
  max-width:44ch;
  font-size:clamp(.9rem, 3.5vw, 1.02rem);
  line-height:1.6;
  color:var(--muted);
  text-shadow:none;
}

/* ====================================================================
   LA MACRO — una stampa sul crema (era full-bleed)
   ==================================================================== */
.b07v2-macro{
  --frame-w:min(88vw, 860px);
  width:var(--frame-w);
  margin-inline:auto;
  padding:calc(var(--frame-w) * .028) calc(var(--frame-w) * .028) 0;
  background:var(--print);
  border-radius:2px;
  box-shadow:
    0 1px 1px rgba(46,44,40,.10),
    0 12px 32px -12px rgba(46,44,40,.34);
  overflow:visible;
}
/* il crop verticale smette di avere senso PRIMA del breakpoint di layout:
   il <source media> nell'HTML ha lo stesso 600. */
.b07v2-macro picture{
  display:block;
  overflow:hidden;
  aspect-ratio:1400 / 1751;
  background:var(--sand);
}
@media (min-width:600px){
  .b07v2-macro picture{ aspect-ratio:1440 / 804; }
}
.b07v2-macro__img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  will-change:transform;
  transform-origin:50% 50%;
}

/* ====================================================================
   DESKTOP — ≥821px (il breakpoint del progetto)
   ==================================================================== */
@media (min-width:821px){
  .b07v2-macro{ --frame-w:min(72vw, 900px); }
}

/* ====================================================================
   PARITÀ MOBILE — nessun effetto rimosso, solo adattato.
   Il melt, il ken-burns, la pozza e il pin dello scrub esistono identici
   su touch: cambiano crop e ampiezza, mai la presenza.
   ==================================================================== */

@media (prefers-reduced-motion:reduce){
  /* tutto visibile, niente scrub: il pin collassa e il video resta il suo
     poster (frame 192 = stato finale). */
  .b07--v2 .b07v2-macro__img{ transform:none !important; }
  .b07v2-cap{ opacity:1 !important; transform:none !important; }

}

/* (LA SORGENTE — lo scrub del girato della fotobox — è uscita il
   2026-08-22 su richiesta dell'owner: .b07-source* rimosse, non
   commentate. Al suo posto le foto vere della cabina, blocco b07-shots.) */

/* (Il calibro del giunto legno ai monitor larghi è uscito col mondo
   legno — owner 18/08 sera-2. Procedura conservata in qa/shots-20260818-faseC2.) */

/* === section:b05-all — l'ingresso all'archivio (25/08 sera: «più
   ovvio»). Ventaglio di quattro mini-stampe nude + badge +23 + pill col
   bordo oro, tutto UN bottone. L'affordance è il ventaglio: mostra che
   le foto sotto esistono. */
.b05-all{
  display:flex;
  justify-content:center;
  padding:clamp(14px,2.6vh,30px) 20px clamp(30px,4.6vh,52px);
}
.b05-all__btn{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:clamp(12px,1.8vh,18px);
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.b05-all__btn:focus-visible{ outline:2px solid var(--gold-deep); outline-offset:6px; border-radius:8px; }
.b05-all__fan{
  position:relative;
  display:flex;
  align-items:center;
  height:86px;
  transition:transform .4s cubic-bezier(.16,1,.3,1);
}
.b05-all__fan img{
  width:62px; height:78px;
  object-fit:cover;
  border-radius:2px;
  box-shadow:0 1px 2px rgba(46,44,40,.34), 0 8px 18px -8px rgba(46,44,40,.44);
  -webkit-user-drag:none;
}
.b05-all__fan img:nth-child(1){ transform:rotate(-7deg) translateY(4px); }
.b05-all__fan img:nth-child(2){ transform:rotate(-2deg) translateY(-2px); margin-left:-18px; }
.b05-all__fan img:nth-child(3){ transform:rotate(3deg) translateY(2px); margin-left:-18px; }
.b05-all__fan img:nth-child(4){ transform:rotate(8deg) translateY(-1px); margin-left:-18px; }
.b05-all__more{
  position:absolute;
  right:-14px; top:-6px;
  display:flex;
  align-items:center;
  justify-content:center;
  min-width:34px; height:34px;
  padding:0 6px;
  border-radius:999px;
  background:var(--gold-deep);
  color:#f7f2e9;
  font-family:var(--font-mono);
  font-style:normal;
  font-size:.62rem;
  letter-spacing:.06em;
  box-shadow:0 4px 10px -4px rgba(46,44,40,.5);
}
.b05-all__pill{
  display:flex;
  align-items:center;
  gap:10px;
  min-height:46px;
  padding:0 22px;
  border-radius:999px;
  border:1px solid color-mix(in srgb, var(--gold-deep) 55%, transparent);
  background:color-mix(in srgb, var(--print, #fff) 55%, transparent);
  font-family:var(--font-mono);
  font-size:.7rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--gold-deep);
  transition:color .3s linear, border-color .3s linear, background .3s linear;
}
.b05-all__arrow{ font-family:var(--font-body); transition:transform .4s cubic-bezier(.16,1,.3,1); }
@media (hover:hover) and (pointer:fine){
  .b05-all__btn:hover .b05-all__fan{ transform:translateY(-3px); }
  .b05-all__btn:hover .b05-all__pill{ color:var(--ink); border-color:var(--gold-deep); background:var(--print, #fff); }
  .b05-all__btn:hover .b05-all__arrow{ transform:translateX(4px); }
}
@media (prefers-reduced-motion:reduce){
  .b05-all__fan, .b05-all__arrow{ transition:none; }
}

/* === section:mdock — dock mobile (Daniel 25/08) ======================
   «foto, video e la photobox sempre dentro anche se scrollo giù».
   Tre pill in miniatura, fisse in basso al centro, solo telefono.
   Compare/si ritira via .is--on (js/meganav.js §mdock) con una
   dissolvenza corta — niente che «vola dentro» (L5). z 90: sotto la
   navbar (100) e sotto le lightbox (130). */
.mdock{
  position:fixed;
  left:50%;
  bottom:calc(12px + env(safe-area-inset-bottom, 0px));
  transform:translateX(-50%) translateY(8px);
  z-index:90;
  display:none;
  gap:6px;
  padding:5px;
  border-radius:999px;
  background:color-mix(in srgb, var(--paper, #f7f2e9) 82%, transparent);
  -webkit-backdrop-filter:blur(14px);
          backdrop-filter:blur(14px);
  border:1px solid color-mix(in srgb, var(--gold-deep) 34%, transparent);
  box-shadow:0 10px 30px -12px rgba(46,44,40,.35);
  opacity:0;
  pointer-events:none;
  transition:opacity .35s linear, transform .45s cubic-bezier(.16,1,.3,1);
}
.mdock.is--on{
  opacity:1;
  pointer-events:auto;
  transform:translateX(-50%) translateY(0);
}
.mdock a{
  display:flex;
  align-items:center;
  min-height:38px;
  padding:0 14px;
  border-radius:999px;
  font-family:var(--font-mono);
  font-size:.62rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  text-decoration:none;
  color:var(--ink);
  -webkit-tap-highlight-color:transparent;
}
.mdock a:active{ background:color-mix(in srgb, var(--gold-deep) 16%, transparent); }
@media (max-width:820px){
  .mdock{ display:flex; }
}
@media (prefers-reduced-motion:reduce){
  .mdock{ transition:none; }
}

/* === section:archiv — Das Archiv (25/08) =============================
   Port osmo infinite-draggable-grid-basic dentro un overlay a schermo
   pieno. Sta a z 120: sopra tutto tranne le lightbox (130) e sotto
   niente che serva. Apertura/chiusura di classe (legge background-tab).
   Il fondo è crema pieno: l'archivio è una STANZA, non un velo. */
.archiv{
  position:fixed;
  inset:0;
  z-index:120;
  background:var(--bg, #f7f2e9);
  touch-action:none;
  overflow:clip;
  cursor:grab;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity .45s ease, visibility 0s linear .45s;
}
.archiv.is--open{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transition:opacity .45s ease;
}
.archiv[data-infinite-grid-status="dragging"]{ cursor:grabbing; }
/* la griglia appare quando è costruita (stato osmo): il velo evita il
   lampo delle tile che si impaginano */
.archiv__collection{
  position:absolute;
  width:100%; height:100%;
  will-change:transform;
  transition:opacity .5s ease;
}
.archiv[data-infinite-grid-status="loading"] .archiv__collection{ opacity:0; }
.archiv__list{
  position:absolute;
  top:0; left:0;
  display:grid;
  grid-template-columns:repeat(var(--grid-columns, 4), auto);
}
.archiv__item{
  display:flex;
  align-items:center;
  justify-content:center;
  width:clamp(150px, 30vw, 260px);
  aspect-ratio:1;
  padding:clamp(10px, 2vw, 22px);
}
/* stampa nuda, come ovunque (legge 21/08): niente carta, raggio 2px,
   ombra di contatto */
.archiv__card{
  position:relative;
  width:88%;
  aspect-ratio:4 / 5;
  border-radius:2px;
  box-shadow:
    0 1px 2px rgba(46,44,40,.3),
    0 10px 24px -10px rgba(46,44,40,.4);
  -webkit-user-select:none; user-select:none;
}
.archiv__img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  border-radius:inherit;
  pointer-events:none;
  -webkit-user-select:none; user-select:none;
}
.archiv__head{
  position:absolute;
  top:0; left:0; right:0;
  z-index:2;
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:clamp(16px,3vw,28px) clamp(18px,4vw,44px);
  /* la X (.b04-x) è assoluta in alto a destra: il titolo non deve
     passarle sotto — 46px di bottone + aria */
  padding-right:clamp(72px, 8vw, 110px);
  pointer-events:none;
  background:linear-gradient(to bottom, color-mix(in srgb, var(--bg, #f7f2e9) 92%, transparent), transparent);
}
.archiv__title{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(1.3rem, 2.4vw, 2rem);
  color:var(--ink);
}
.archiv__n{
  font-family:var(--font-mono);
  font-size:.55em;
  letter-spacing:.2em;
  color:var(--gold-deep);
}
.archiv__close{ pointer-events:auto; }
.archiv__hint{
  position:absolute;
  bottom:calc(14px + env(safe-area-inset-bottom, 0px));
  left:50%;
  transform:translateX(-50%);
  z-index:2;
  margin:0;
  font-family:var(--font-mono);
  font-size:.6rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
  pointer-events:none;
  white-space:nowrap;
}
@media (prefers-reduced-motion:reduce){
  .archiv{ transition:none; }
  .archiv__collection{ transition:none; }
}

/* === section:b07casc — la cabina sul palco (cascading-slider, 25/08) ==
   L'attivo è il palco (78vw a 390), i vicini restano come lame: il
   clip-path con --clip è la firma del componente. Stampe nude (legge
   21/08), didascalia in crema su scrim SULLA slide attiva (legge «sul
   legno si scrive in crema»). */
.b07casc{
  width:100%;
  margin:clamp(1.75rem, 5vh, 3.25rem) auto 0;
  -webkit-user-select:none; user-select:none;
}
.b07casc__list{
  --gap:clamp(6px, 1vw, 14px);
  position:relative;
  width:100%;
  /* palco per media 9:16: alto quanto serve all'attivo, cappato perché
     la sezione resti corta (L11) */
  height:clamp(430px, 138vw, 560px);
  overflow:hidden;
  touch-action:pan-y;    /* lo swipe orizzontale è del Draggable */
}
@media (min-width:768px){
  .b07casc__list{ height:clamp(480px, 62svh, 660px); }
}
.b07casc__item{
  --clip:0;
  position:absolute;
  inset:0 auto auto 0;
  height:100%;
  will-change:transform, clip-path;
  clip-path:inset(0px calc(var(--clip) * 1px) round 2px);
  cursor:pointer;
}
.b07casc__item[data-status="active"]{ cursor:default; }
.b07casc__bg{
  position:absolute;
  inset:0;
  border-radius:2px;
  overflow:hidden;
  box-shadow:
    0 1px 2px rgba(46,44,40,.3),
    0 12px 28px -12px rgba(46,44,40,.42);
}
.b07casc__media{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  pointer-events:none;
  -webkit-user-select:none; user-select:none;
}
/* la didascalia solo sull'attiva, crema su scrim — una riga in scena */
.b07casc__cap{
  position:absolute;
  inset:auto 0 0 0;
  z-index:2;
  margin:0;
  padding:44px 16px 14px;
  font-family:var(--font-mono);
  font-size:.64rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:#f7f2e9;
  text-shadow:0 1px 2px rgba(24,18,12,.5);
  background:linear-gradient(to top, rgba(24,18,12,.6), rgba(24,18,12,0));
  opacity:0;
  transition:opacity .35s linear .25s;
  pointer-events:none;
}
.b07casc__item[data-status="active"] .b07casc__cap{ opacity:1; }

/* barra: frecce + contatore, registro mono/oro come b04 */
.b07casc__bar{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:clamp(14px, 4vw, 26px);
  margin-top:clamp(14px, 2.4vh, 24px);
}
.b07casc__btn{
  display:flex;
  align-items:center;
  justify-content:center;
  width:46px; height:46px;
  border-radius:50%;
  border:1px solid color-mix(in srgb, var(--gold-deep) 45%, transparent);
  background:none;
  color:var(--gold-deep);
  font-family:var(--font-body);
  font-size:1.05rem;
  cursor:pointer;
  transition:border-color .3s linear, color .3s linear;
}
.b07casc__btn:focus-visible{ outline:2px solid var(--gold-deep); outline-offset:2px; }
@media (hover:hover) and (pointer:fine){
  .b07casc__btn:hover{ border-color:var(--gold-deep); color:var(--ink); }
}
.b07casc__count{
  font-family:var(--font-mono);
  font-size:.72rem;
  letter-spacing:.18em;
  color:var(--muted);
}
.b07casc__count b{ font-weight:400; color:var(--gold-deep); }
.b07casc__hint{
  margin:clamp(10px, 1.6vh, 16px) 0 0;
  text-align:center;
  font-family:var(--font-mono);
  font-size:.6rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}
/* stato di riposo senza JS: le slide impilate, la prima leggibile
   (legge del repo: mai trappole) — is--on non nasconde niente, il
   layout iniziale lo scrive il motore */

/* === section:b04strip — I DUE NASTRI (25/08 sera) ====================
   Due marquee di stampe nude in direzioni opposte (ordine owner: la
   pellicola 35mm è uscita). Il contrappunto è il movimento, non la
   cornice: fila sopra a sinistra, fila sotto a destra, gap di crema.
   Stampe nude come ovunque (legge 21/08), meta in crema su scrim. */
.b04strip{
  width:100%;
  margin-top:clamp(22px, 4vh, 44px);
  -webkit-user-select:none; user-select:none;
}
.b04strip__row{
  position:relative;
  width:100%;
  overflow:hidden;
  padding:clamp(5px, 0.8vh, 9px) 0;
  touch-action:pan-y;     /* l'orizzontale è del Draggable */
  cursor:grab;
}
.b04strip__row:active{ cursor:grabbing; }
.b04strip__collection{
  display:flex;
  width:max-content;
  will-change:transform;
}
.b04strip__list{
  display:flex;
  width:max-content;
}
.b04strip__frame{
  display:block;
  flex:none;
  margin:0 clamp(5px, 0.7vw, 10px);
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.b04strip__frame:focus-visible{ outline:2px solid var(--gold-deep); outline-offset:3px; }
.b04strip__cell{
  position:relative;
  display:block;
  /* due file: la card scende perché l'ingombro totale resti da sezione,
     non da doppia sezione (L11) */
  width:clamp(140px, 36vw, 210px);
  aspect-ratio:2 / 3;
  border-radius:2px;
  overflow:hidden;
  box-shadow:
    0 1px 2px rgba(46,44,40,.32),
    0 10px 24px -10px rgba(46,44,40,.4);
}
.b04strip__img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  pointer-events:none;
  -webkit-user-select:none; user-select:none;
}
/* targa + nomi + invito, crema su scrim: la legge di sempre */
.b04strip__meta{
  position:absolute;
  inset:auto 0 0 0;
  display:flex;
  flex-direction:column;
  gap:2px;
  padding:30px 10px 8px;
  text-align:left;
  background:linear-gradient(to top, rgba(20,14,8,.76), rgba(20,14,8,0));
}
.b04strip__meta b{
  font-family:var(--font-mono);
  font-weight:400;
  font-size:.54rem;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--gold);
}
.b04strip__meta span{
  font-family:var(--font-display);
  font-size:clamp(.92rem, 3vw, 1.15rem);
  line-height:1.05;
  color:#f7f2e9;
  text-shadow:0 1px 2px rgba(24,18,12,.5);
}
.b04strip__meta em{
  font-family:var(--font-mono);
  font-style:normal;
  font-size:.54rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:color-mix(in srgb, #f7f2e9 72%, transparent);
}
.b04strip__hint{
  margin:clamp(12px, 2vh, 20px) 0 0;
  text-align:center;
  font-family:var(--font-mono);
  font-size:.6rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--muted);
}

/* === section:b05nastri — aggancio alla scena (25/08 v3) =============
   La chiusa testuale è USCITA (collideva col lockup tornando indietro —
   screenshot iPhone 15:00; ora è il LOCKUP a restare in scena, vedi
   sections.js §IL LOCKUP). I nastri risalgono dentro la coda del
   fotogramma congelato: via il vuoto crema fra la scena e le foto. */
.b05nastri{
  position:relative;
  z-index:2;
  margin-top:clamp(-380px, -36svh, -120px);
}

/* === section:b01-cue-chevron (25/08, Daniel: «non capiva che doveva
   scrollare» — la freccia che lo dice) ================================
   Chevron oro che rimbalza piano sotto la label; su telefono il cue
   sale SOPRA la fila delle pill (misurato: ci finiva in mezzo, la
   label attraversava FILME) e perde la linea — compatto. */
.b01-cue__chev{
  width:11px; height:11px;
  border-right:2px solid var(--gold-deep);
  border-bottom:2px solid var(--gold-deep);
  transform:rotate(45deg);
  animation:b01cue-bob 1.9s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes b01cue-bob{
  0%,100%{ transform:translateY(0) rotate(45deg); opacity:.95; }
  50%{ transform:translateY(7px) rotate(45deg); opacity:.4; }
}
@media (prefers-reduced-motion:reduce){ .b01-cue__chev{ animation:none; } }
@media (max-width:820px){
  .b01-cue{
    bottom:calc((100lvh - 100svh) + clamp(78px, 12svh, 120px));
    gap:7px;
  }
  .b01-cue__line{ display:none; }
}

/* === section:b01-anelli — HERO «DIE RINGE» (Daniel 08/09/2026) ===========
   Il suo video degli anelli scrubbato con lo scroll: traccia, pin, motore
   e uscita del titolo sono quelli di §b01-ring / js/ring.js — qui solo la
   PELLE: il girato è chiaro in alto (cielo, anelli) e scuro in basso
   (valle, poi la camicia bianca di Daniel al freeze, quando il titolo è
   già uscito). Titolo crema in fascia bassa su un velo scuro che muore a
   zero; il velo crema della mappa (.b01-holder::after) qui non serve. */
[data-anelli] .b01-holder::after{ display:none; }
[data-anelli] .b01-holder::before{
  content:"";
  position:absolute;
  inset:auto 0 0 0;
  z-index:2;                 /* sopra il canvas (z1), sotto l'overlay (z3) */
  height:62%;
  background:linear-gradient(0deg, rgba(24,17,9,.66), rgba(24,17,9,.36) 44%, rgba(24,17,9,0));
  opacity:var(--titleveil, 1);   /* esce col titolo (js/ring.js) */
  pointer-events:none;
}
[data-anelli] .b01-h1,
[data-anelli] .b01-sub .b01-line{ color:#faf4e6; text-shadow:0 1px 14px rgba(20,12,4,.45); }
[data-anelli] .b01-cue__label{ color:rgba(250,244,230,.78); }
[data-anelli] .b01-cue__line{ background:linear-gradient(180deg, transparent, rgba(250,244,230,.7)); }
[data-anelli] .b01-cue__chev{ border-color:var(--gold); }
[data-anelli] .b01-paper img{ transform:none; }   /* still di riserva: nessun assestamento */
/* IL FOGLIO CHE LO COPRE (owner 08/09 «fallo meglio»): --sheet (0→1 sulla
   coda, js/ring.js) — Daniel scivola su di un 10 % (parallasse: il foglio è
   SOPRA di lui, non davanti) e va in penombra fino a .35. La striscia
   scoperta in basso è sempre sotto il foglio (10 % < 100 %). */
[data-anelli] .b01ring__scrub,
[data-anelli] .b01-paper{
  transform:translate3d(0, calc(var(--sheet, 0) * -10%), 0);
  will-change:transform;
}
[data-anelli] .b01-holder::after{
  content:"";
  display:block;
  position:absolute;
  inset:0;
  height:auto;
  z-index:2;
  background:#181109;
  opacity:calc(var(--sheet, 0) * .35);
  pointer-events:none;
}
@media (min-width:821px){
  [data-anelli][data-title-pos="bottom"] .b01-headline{
    /* Daniel sta al centro del 16:9: il titolo resta a sinistra, tre righe
       (la &nbsp; del markup manda «& Hochzeitsfotos» a capo da sola) */
    max-width:34vw;
  }
  [data-anelli] .b01-h1{ font-size:clamp(1.9rem, 4.3vw, 4.4rem); }
  /* il cue va a destra: al centro-basso, al freeze, c'è la mano con gli anelli */
  [data-anelli] .b01-cue{
    left:auto;
    right:var(--b01-pad-x);
    transform:none;
    align-items:flex-end;
  }
}
@media (max-width:820px){
  [data-anelli] .b01-holder::before{ height:70%; }
  [data-anelli] .b01-h1{ font-size:clamp(1.9rem, 9vw, 2.8rem); }
}

/* === section:b03-cream — «Hi, ich bin Daniel» su carta (owner 08/09) =====
   Dopo il freeze su Daniel con gli anelli, b03 torna la sezione di carta
   crema della LEGGE §B03: niente lastra di legno (§b03::before, era il
   giunto con l'hero «Der Ring»), niente velo scuro, inchiostro scuro.
   La coda di dissolvenza (--b03-fade) non ha più niente da dissolvere:
   zero, e la pagina si accorcia (L11). Il Tisch che segue è la
   transizione — il dolly nei monti, com'era. */
.b03.is-cream{
  --b03-fade:0px;
  background:var(--ground-2);
  /* IL FOGLIO (owner 08/09): b03 sale SOPRA il freeze dell'hero. Tirato su
     di un viewport (la coda --rdrop dell'hero è lunga altrettanto), sopra
     in z, alto almeno un viewport così copre tutto il pin da solo, con
     l'ombra di un foglio appoggiato su una foto. Il testo sta centrato
     sul foglio. */
  position:relative;
  z-index:2;
  margin-top:-100lvh;
  /* 08/09 sera (owner: «remove all of this whitespace»): niente
     min-height da un viewport — il foglio è alto quanto il testo, e a
     coprire il resto dell'hero fermo ci pensa il Tisch che viene dopo
     (positioned, dipinto sopra il pin dell'hero per ordine di DOM). */
  min-height:0;
  /* testo in ALTO sul foglio: arriva subito dopo il bordo */
  align-items:flex-start;
  padding-top:clamp(56px,12svh,128px);
  padding-bottom:clamp(40px,6vh,78px);
  box-shadow:0 -28px 70px rgba(30,20,8,.22);
  /* carta, non un div: angoli alti arrotondati + il taglio chiaro del bordo */
  border-radius:22px 22px 0 0;
}
.b03.is-cream::after{
  content:"";
  position:absolute;
  top:0; left:0; right:0;
  height:2px;
  border-radius:22px 22px 0 0;
  background:rgba(255,255,255,.6);
  pointer-events:none;
}
@media (max-width:820px){
  .b03.is-cream{ border-radius:18px 18px 0 0; }
  .b03.is-cream::after{ border-radius:18px 18px 0 0; }
}
.b03.is-cream::before{ display:none; }
.b03.is-cream .b03-h{ color:var(--ink); text-shadow:none; }
.b03.is-cream .b03-h em,
.b03.is-cream .b03-dot,
.b03.is-cream .b03-num,
.b03.is-cream .b03-kicker{ color:var(--gold-deep); }
.b03.is-cream .b03-rule{ background:var(--gold-deep); }
.b03.is-cream .b03-quote{ color:var(--ink); text-shadow:none; }
.b03.is-cream .b03-sign{ color:var(--ink); text-shadow:none; }
.b03.is-cream .b03-sign em{ color:var(--gold-deep); }
.b03.is-cream .b03-sigrule path{ stroke:var(--gold-deep); }
.b03.is-cream .b03-text::before{ display:none; }
.b03.is-cream .b03-portrait__cap{ color:#6b6156; }
/* colonna sola (ritratto uscito 08/09): il testo si prende la misura di
   lettura, non tutta la griglia */
.b03.is-cream .b03-inner{
  display:block;
  max-width:min(100%, 760px);
  margin:0 auto 0 0;
}
.b03.is-cream .b03-quote{ max-width:none; }
@media (max-width:820px){
  .b03.is-cream{ padding-top:clamp(48px,10svh,96px); padding-bottom:clamp(36px,5.5vh,64px); }
}

/* === section:no-numbers (owner 08/09: «remove all of this stuff») ========
   Via tutti i numeri/kicker di sezione: «02 — Hinter der Kamera», «03»
   del Tisch, «04 — Der Film · Referenzen», «05 — Und so läuft's ab»,
   «06 — Für eure Gäste», «( 07 ) — Anfrage». Nascosti, non rimossi dal
   markup: js/sections.js li tocca ancora (filetto b03, rise b06/b07). I
   numeri dei passi dell'Ablauf (.b06-step-num) sono un'altra cosa e
   restano. */
.b03-lockup,
.b05-num,
.b04h-kicker,
.b06-kicker,
.b07-num,
.b09__kicker{ display:none !important; }

/* === section:osmo-text (08/09) — tre animazioni di testo osmo =============
   Meccaniche in js/osmo-text.js. Qui solo la geometria dei pezzi.
   1 · marker: il titolo nasce invisibile (le barre lo coprono al build);
       il JS lo accende, il failsafe/reduced-motion lo accende comunque. */
[data-osmo-marker]{ visibility:hidden; }
@media (prefers-reduced-motion:reduce){ [data-osmo-marker]{ visibility:visible; } }
.omk-line{
  display:inline-block;
  position:relative;
  overflow:hidden;
  vertical-align:top;
  padding:.04em .06em .08em 0;   /* le discendenti non si tagliano */
  margin:-.04em 0 -.08em;
}
.omk-text{ display:inline-block; will-change:transform; }   /* sale mentre la barra si ritira */
.omk-bar{
  position:absolute;
  inset:0;
  z-index:1;
  display:block;
  transform-origin:right center;
  pointer-events:none;
}
/* 2 · highlight on scroll: parole intere (niente a capo dentro la parola) */
.omh-w{ display:inline-block; white-space:nowrap; }
.omh-c{ display:inline-block; }
/* 3 · rotating words: la riga è la maschera, la parola scorre dentro */
.omr-line{
  display:inline-block;
  overflow-x:visible;
  overflow-y:clip;
  padding-bottom:.1em;
  margin-bottom:-.1em;
  white-space:nowrap;
  vertical-align:top;
}
[data-rotating-words], .b09__rot{ display:inline-block; position:relative; color:var(--gold); }
/* la sottolineatura oro si ridisegna a ogni parola (da sinistra) */
[data-rotating-words]::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:.02em;
  height:.06em;
  background:var(--gold);
  transform-origin:left center;
  transform:scaleX(var(--omr-u, 1));
  opacity:.9;
  pointer-events:none;
}
.omr-inner{ display:inline-block; position:relative; height:1em; vertical-align:top; line-height:inherit; }
.omr-word{ display:block; white-space:nowrap; position:absolute; top:0; left:0; }
