/* ==========================================================================
   Kefero — la sequenza di apertura

   A schermo intero, sopra tutto. L'HUD è diegetico: non è un'interfaccia
   sovrapposta alla scena, è ciò che la scena dice di sé — i numeri sono
   quelli veri del calcolo.
   ========================================================================== */

.opening {
    position: fixed;
    inset: 0;
    z-index: var(--layer-modal);
    background: var(--bg-deep);
    display: grid;
    place-items: center;
    opacity: 1;
    transition: opacity var(--motion-duration-slow) var(--motion-easing-standard);
}

.opening[data-state='closing'] { opacity: 0; pointer-events: none; }

/* Lampo dell'esplosione radiale (genesi → sistema solare): scatta con
   l'inizio della voce, riempie la scena e si dissolve. Guidato da data-burst. */
.opening::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    opacity: 0;
    /* ── L'ACCENSIONE È BIANCA, NON DORATA ────────────────────────────────
       Prima il lampo era un alone ambrato che si allargava: bello, ma
       "caldo" — leggeva come un bagliore, non come una detonazione. Una
       stella che si accende butta fuori luce BIANCA, e il bianco satura
       l'occhio prima di qualunque colore.
       Il nucleo ora è bianco pieno fino al 18%, l'oro resta solo sul bordo
       (è lì che serve, per non farlo sembrare un flash da fotocamera), e la
       coda si estende fino all'80% invece del 62%: il lampo copre quasi
       tutto il quadro invece di restare una macchia al centro. */
    background: radial-gradient(circle at 50% 46%,
        rgba(255, 255, 255, 1) 0%,
        rgba(255, 252, 240, 1) 18%,
        rgba(255, 226, 160, 0.55) 42%,
        rgba(255, 190, 100, 0) 80%);
    mix-blend-mode: screen;
}

.opening[data-burst='go']::after {
    animation: opening-burst-flash 900ms cubic-bezier(0.12, 0.9, 0.2, 1);
}

/* ── VIOLENTO VUOL DIRE RIPIDO, NON LUNGO ─────────────────────────────────
   La violenza di un lampo sta nella RAPIDITÀ con cui arriva, non nella sua
   durata: un'esplosione lenta è un'alba. Prima il picco arrivava al 16% di
   mille millisecondi — 160 ms — e si fermava a 0,95 di opacità.
   Ora il bianco pieno è addosso in 54 ms (6% di 900), satura a 1 e ci resta
   un istante, poi lascia. Ed è più grande: parte da 0,12 (un punto) e arriva
   a 2,6 invece di 1,7, così sembra investire la camera invece di gonfiarsi
   davanti. La curva d'uscita fa il resto — crolla e poi si posa. */
@keyframes opening-burst-flash {
    0%   { opacity: 0;    transform: scale(0.12); }
    6%   { opacity: 1;    transform: scale(0.6); }
    14%  { opacity: 1; }
    46%  { opacity: 0.28; }
    100% { opacity: 0;    transform: scale(2.6); }
}

.opening-stage {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
}

.opening-stage canvas {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Un filo più luminoso (+7%): agisce sul canvas, non sullo stage, così NON
       entra in conflitto con le animazioni brightness di suck_off/reignite/
       detonate (che stanno sullo .opening-stage). Uniforme su mobile e desktop,
       costo zero. Tarabile: alzare/abbassare questo valore. */
    filter: brightness(1.07);
}

/* --------------------------------------------------------------------------
   L'HUD

   Il dato tecnico in monospazio, la glossa in display. La differenza di
   carattere dice quale dei due è misura e quale è commento — senza doverlo
   spiegare.
   -------------------------------------------------------------------------- */

.opening-hud {
    position: absolute;
    left: 50%;
    top: 7vh;
    transform: translateX(-50%);
    z-index: 1;
    width: 100%;
    max-width: 900px;
    text-align: center;
    padding: 0 var(--space-6);
    pointer-events: none;
}

/* --------------------------------------------------------------------------
   L'iscrizione in alto

   La data (e l'altro dato-chiave di ogni scena) sta in alto, grande, in un
   carattere sacro e distanziato: un'iscrizione, non un'etichetta. Durante il
   riavvolgimento scorre all'indietro, e la scrittura solenne rende il viaggio
   nel tempo.
   -------------------------------------------------------------------------- */

/* Il font LED a 7 segmenti per la data: le cifre di un vecchio orologio, con
   i segmenti spenti che restano visibili come ombra. */
@font-face {
    font-family: 'DSEG7 Classic';
    src: url('../fonts/DSEG7Classic-Bold.woff2') format('woff2');
    font-weight: 700;
    font-display: swap;
}

.opening-readout {
    font-family: var(--type-family-display), serif;
    font-size: clamp(1.4rem, 3.6vw, 2.4rem);
    font-weight: var(--type-weight-light, 300);
    letter-spacing: 0.06em;
    line-height: 1.3;
    color: var(--hud-text);
    white-space: pre-line;
    margin: 0;
    min-height: 1.4em;
    opacity: 0;
    transition: opacity 700ms var(--motion-easing-standard);
    text-shadow: 0 0 26px var(--bg-deep), 0 0 10px var(--bg-deep);
}

/* La data: font LED, cifre da display luminoso con alone ceruleo. */
.opening-readout[data-clock='true'] {
    font-family: 'DSEG7 Classic', 'Share Tech Mono', ui-monospace, monospace;
    font-size: clamp(1.3rem, 3.4vw, 2.3rem);
    font-weight: 700;
    letter-spacing: 0.14em;
    color: #7fe9ff;
    text-shadow:
        0 0 6px #7fe9ff,
        0 0 16px rgba(90, 200, 255, 0.8),
        0 0 30px rgba(120, 130, 255, 0.5);
}

/* I punti di separazione, più larghi, distanziano giorno / mese / anno. */
.opening-readout[data-clock='true'] .sep {
    margin: 0 0.30em;
    color: #e6faff;
    text-shadow: 0 0 8px #aef0ff, 0 0 18px rgba(120, 170, 255, 0.7);
}

/* Il cursore dell'incipit: un blocco LED che lampeggia (boot) e avanza in
   coda mentre la data viene digitata (typeReadout). Stesso alone ceruleo
   della data. Riusa il keyframe 'opening-hud-caret'. */
.opening-caret {
    display: inline-block;
    width: 0.62em;
    height: 1.02em;
    margin-left: 0.10em;
    vertical-align: -0.14em;
    background: #7fe9ff;
    box-shadow: 0 0 6px #7fe9ff, 0 0 16px rgba(90, 200, 255, 0.8), 0 0 30px rgba(120, 130, 255, 0.5);
    animation: opening-hud-caret 0.7s steps(1) infinite;
}

@media (prefers-reduced-motion: reduce) {
    .opening-caret { animation: none; }
}

.opening-gloss {
    font-family: var(--type-family-display);
    /* Stessa riduzione del sottotitolo della voce: è l'altra riga narrativa
       della scena e le due devono avere lo stesso peso. */
    font-size: var(--type-base);
    font-weight: var(--type-weight-light);
    line-height: var(--type-leading-tight);
    color: var(--text);
    margin: var(--space-4) 0 0;
    min-height: 1.6em;
    opacity: 0;
    transition: opacity 700ms var(--motion-easing-standard);
    text-shadow: 0 0 22px var(--bg-deep), 0 0 10px var(--bg-deep);
}

/* --------------------------------------------------------------------------
   Comandi
   -------------------------------------------------------------------------- */

.opening-progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: var(--border);
}

.opening-progress::after {
    content: '';
    display: block;
    height: 100%;
    width: var(--progress, 0%);
    background: var(--accent);
    transition: width var(--motion-duration-quick) linear;
}

.opening-skip {
    position: absolute;
    right: var(--space-6);
    bottom: var(--space-8);
    z-index: 2;
    background: transparent;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-full);
    color: var(--text-dim);
    font-family: var(--type-family-utility);
    font-size: var(--type-xs);
    letter-spacing: var(--type-tracking-wide);
    text-transform: uppercase;
    padding: var(--space-2) var(--space-5);
    cursor: pointer;
    pointer-events: auto;
}

.opening-skip:hover { color: var(--text); border-color: var(--text-dim); }

/* --------------------------------------------------------------------------
   Gli HUD ancorati

   Non pannelli sovrapposti, ma etichette appese al punto che descrivono: un
   corpo, un gate. La regia le proietta dal 3D e le posiziona qui a ogni
   fotogramma. Il testo arriva tradotto dal sistema lingue.
   -------------------------------------------------------------------------- */

.opening-anchors {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    overflow: hidden;
}

.opening-anchor {
    position: absolute;
    opacity: 0;
    transition: opacity var(--motion-duration-quick) linear;
    pointer-events: none;
}

/* Il punto sull'elemento (esagramma/gate/corpo). */
.opening-anchor__dot {
    position: absolute;
    left: 0;
    top: 0;
    width: 6px;
    height: 6px;
    margin: -3px 0 0 -3px;
    border-radius: var(--radius-full);
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent), 0 0 16px var(--accent);
}

.opening-anchor__dot::before {
    content: '';
    position: absolute;
    inset: -6px;
    border: 1px solid var(--accent);
    border-radius: var(--radius-full);
    opacity: 0.5;
}

/* La linea di richiamo: sottile e discreta, collega il punto al box (che ora
   sta più lontano dal gate). Geometria diagonale impostata dalla regia. */
.opening-anchor__line {
    position: absolute;
    top: 0;
    height: 1px;
    width: 66px;
    background: linear-gradient(90deg, rgba(210, 220, 245, 0.85), rgba(210, 220, 245, 0));
    opacity: 0.45;
}
.opening-anchor[data-side='right'] .opening-anchor__line { left: 3px; }
.opening-anchor[data-side='left']  .opening-anchor__line { right: 3px; left: auto; }

/* Niente più pannello bordato: solo una sfumatura scura dietro il testo,
   che lo mantiene leggibile su qualunque fondo senza disegnare un riquadro
   visibile. Il testo resta il soggetto, non la cornice che lo contiene. */
.opening-anchor__box {
    position: absolute;
    top: 0;
    /* --dy: schivata verticale calcolata dalla regia per non accavallare i
       box vicini (impostata in positionAnchors). 0 quando non serve. */
    transform: translateY(calc(-50% + var(--dy, 0px)));
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 18px;
    background: radial-gradient(ellipse 140% 180% at 50% 50%,
        rgba(6, 9, 18, 0.82) 0%, rgba(6, 9, 18, 0.55) 45%, rgba(6, 9, 18, 0) 92%);
    white-space: nowrap;
}
.opening-anchor[data-side='right'] .opening-anchor__box { left: 112px; text-align: left; align-items: flex-start; }
.opening-anchor[data-side='left']  .opening-anchor__box { right: 112px; left: auto; text-align: right; align-items: flex-end; }

/* Verticale (telefono/tablet in ritratto): il box sta SOPRA il punto invece
   che di lato, dove in verticale non c'e' spazio. --dx e' la stessa idea di
   --dy ma in orizzontale: la schivata anti-collisione calcolata in
   positionAnchors quando piu' etichette sono vicine. */
.opening-anchor[data-side='top'] .opening-anchor__box {
    left: 0;
    top: auto;
    bottom: 88px;
    transform: translateX(calc(-50% + var(--dx, 0px)));
    text-align: center;
    align-items: center;
}

.opening-anchor__title {
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: var(--type-sm);
    letter-spacing: 0.12em;
    color: var(--text);
    line-height: 1.25;
    text-transform: uppercase;
}

.opening-anchor__sub {
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: var(--type-xs);
    letter-spacing: var(--type-tracking-wide);
    color: var(--hud-text);
    opacity: 0.82;
}

/* Cursore "computing" durante la scrittura. */
.opening-anchor.typing .opening-anchor__box::after {
    content: '▮';
    color: var(--accent);
    font-family: var(--type-family-utility, monospace);
    font-size: var(--type-xs);
    animation: opening-hud-caret 0.7s steps(1) infinite;
    align-self: flex-start;
}
.opening-anchor[data-side='left'].typing .opening-anchor__box::after { align-self: flex-end; }
.opening-anchor[data-side='top'].typing .opening-anchor__box::after { align-self: center; }

@keyframes opening-hud-caret { 50% { opacity: 0; } }

/* --------------------------------------------------------------------------
   La tinta segue il circuito dominante

   Non colori liberi ma scelte fra tinte già curate: nessuna combinazione
   può risultare sgradevole, e due carte diverse hanno aperture diverse.
   -------------------------------------------------------------------------- */

.opening[data-circuit='individual']  { --accent: var(--circuit-individual); }
.opening[data-circuit='tribal']      { --accent: var(--circuit-tribal); }
.opening[data-circuit='collective']  { --accent: var(--circuit-collective); }
.opening[data-circuit='integration'] { --accent: var(--circuit-integration); }

/* --------------------------------------------------------------------------
   Il bodygraph nella scena del tipo

   È il grafico VERO (SVG classic, lo stesso della lettura), montato come
   overlay e assemblato a fasi: prima i gate, poi i canali (con i flussi
   luminosi sui definiti, come in Impronta STUDIO), poi i centri.
   -------------------------------------------------------------------------- */

.opening-bg {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: grid;
    place-items: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1s var(--motion-easing-standard);
}

.opening-bg[data-on='true'] { opacity: 1; }

/* ── L'ALONE NON STA PIÙ SULL'ELEMENTO CHE SI MUOVE ─────────────────────────
   Qui c'era `filter: drop-shadow(0 0 34px …)` sul .bodygraph — lo stesso
   elemento su cui gira l'avanzamento lento in scala. Animare una trasformazione
   su un elemento filtrato costringe il browser a ri-rasterizzare a ogni
   fotogramma un livello sfocato grande quanto il disegno, e a comporlo sopra un
   canvas WebGL già vivo: è la prima causa dell'inchiodamento su Android, e si
   pagava per tutti i ventidue secondi dell'avanzamento.

   L'alone ora è un gradiente radiale su uno pseudo-elemento che NON si muove e
   NON è filtrato: costa una sola rasterizzazione, e visivamente è lo stesso
   bagliore dietro la figura. */
.opening-bg::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 46%;
    width: min(62vh, 480px);
    height: min(62vh, 480px);
    transform: translate(-50%, -50%);
    pointer-events: none;
    background: radial-gradient(circle,
        rgba(120, 160, 255, 0.30) 0%,
        rgba(120, 160, 255, 0.14) 42%,
        rgba(120, 160, 255, 0) 70%);
}

.opening-bg .bodygraph {
    width: min(46vh, 360px);
    max-width: 82vw;
    transform-origin: 50% 46%;
    position: relative;
}

/* L'AVANZAMENTO: il bodygraph, a figura completa, viene verso di noi.
   La durata la detta il JS (--bg-zoom-ms): è il tempo che resta davvero fino
   alla fine della scena, così l'avanzamento non si interrompe a metà né
   finisce prima.

   ── LA MISURA GIUSTA STA IN MEZZO ─────────────────────────────────────────
   È passata per tre valori. Prima 1 → 1,14: a occhio quasi fermo, e la scena
   più lunga del film restava immobile. Poi 1 → 1,5, che risolveva
   l'immobilità ma esagerava dall'altra parte: la figura sconfinava dal quadro
   e nell'ultimo terzo si guardavano i piedi del disegno mentre la voce
   parlava della strategia — un avvicinamento che si mangia il soggetto non è
   più un avvicinamento, è un dettaglio non voluto.

   Ora 1 → 1,26. Il movimento resta chiaramente percepibile (a ventidue
   secondi di scena si legge benissimo), ma il bodygraph resta INTERO nel
   quadro fino alla fine: è la figura che si avvicina, non la camera che ci
   entra dentro. Chi guarda deve poter seguire i centri che si accendono per
   tutto il tempo, e per farlo devono essere tutti ancora visibili. */
.opening-bg[data-zoom='true'] .bodygraph {
    animation: opening-bg-zoom var(--bg-zoom-ms, 14s) cubic-bezier(0.32, 0, 0.5, 1) forwards;
    /* Promuove il disegno a un livello proprio: senza, ogni passo della scala
       costringe a ri-disegnare da capo la vettoriale — centinaia di forme —
       ed è uno dei punti in cui la scena si inchioda sui telefoni. Con la
       promozione il livello si rasterizza e poi si scala, che è lavoro della
       scheda grafica. Costa un filo di nitidezza a fine corsa, e vale
       ampiamente la fluidità. */
    will-change: transform;
}
@keyframes opening-bg-zoom {
    from { transform: scale(1); }
    to   { transform: scale(1.26); }
}
@media (prefers-reduced-motion: reduce) {
    .opening-bg[data-zoom='true'] .bodygraph { animation: none; }
}

.opening-bg .bodygraph svg { width: 100%; height: auto; display: block; }

/* ── QUI NON C'È PIÙ NULLA CHE RIGUARDI IL DISEGNO ────────────────────────
   Vivevano qui una trentina di regole sul bodygraph della scena: la comparsa
   di porte e centri, la scintilla, il colore dei centri accesi, il negativo
   dei loro nomi, la dissolvenza del resto.

   Ora il disegno della scena è SIGILLATO (vedi opening-bodygraph.js): non
   porta più le classi del bodygraph della lettura, i suoi colori sono
   attributi scritti sugli elementi, e le poche regole di comparsa viaggiano
   dentro l'SVG stesso. Queste regole non avevano più un bersaglio.

   Non è una pulizia formale. Erano proprio loro il punto debole: un colore
   che dipende dalla cascata dipende dall'ordine dei fogli, dalla specificità,
   e da quale versione la cache ha servito — ed è così che un centro DEFINITO
   poteva disegnarsi come un centro aperto. Un attributo no.

   Restano qui sotto solo le cose che riguardano il CONTENITORE: l'alone,
   l'avanzamento, il lampo, la dissolvenza d'uscita. */

/* L'esplosione del bodygraph deve poter USCIRE dal riquadro: senza questo,
   l'SVG ritaglia i pezzi al suo bordo (la "maschera quadrata"). */
.opening-bg,
.opening-bg .bodygraph,
.opening-bg svg { overflow: visible; }

/* Flash alla RICOMPOSIZIONE del bodygraph nel finale ("...and all of it is
   you"): un bagliore caldo che accompagna le parti che rientrano al centro. */
.opening-bg[data-flash='go']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background: radial-gradient(circle at 50% 46%,
        rgba(255, 244, 214, 0.75) 0%, rgba(255, 210, 130, 0.3) 32%, rgba(255, 180, 90, 0) 62%);
    mix-blend-mode: screen;
    animation: opening-burst-flash 900ms ease-out;
}

/* Dissolvenza radiale d'uscita: gate e centri si rimpiccioliscono e svaniscono
   (i canali/ghost li porta a 0 il JS); il ritardo per-elemento (impostato dal
   JS in base alla distanza dal centro) crea l'onda radiale. */
.opening-bg[data-dissolve='true'] {
    opacity: 0;
    transition: opacity 1.1s ease;
}


/* --------------------------------------------------------------------------
   La scomposizione della data

   Quando compare l'anello del mandala, le cifre della data di nascita si
   staccano una a una e derivano verso il centro, dissolvendosi: la data
   diventa la ruota.
   -------------------------------------------------------------------------- */

.opening-shatter {
    position: absolute;
    left: 50%;
    top: 7vh;
    transform: translateX(-50%);
    z-index: 2;
    display: flex;
    gap: 0.02em;
    pointer-events: none;
    font-family: 'DSEG7 Classic', 'Share Tech Mono', ui-monospace, monospace;
    font-weight: 700;
    font-size: clamp(1.9rem, 5.4vw, 3.6rem);
    color: #f2f6ff;
    text-shadow: 0 0 10px rgba(150, 200, 255, 0.55), 0 0 26px rgba(120, 170, 255, 0.35);
}

.opening-shatter span {
    display: inline-block;
    opacity: 1;
    will-change: transform, opacity, filter;
}

/* L'animazione parte solo dopo aver misurato dove volare (classe .go). */
.opening-shatter.go span {
    animation: opening-shatter-fly 2.6s cubic-bezier(0.32, 0, 0.15, 1) forwards;
    animation-delay: var(--d, 0s);
}

/* Volo ad arco: la cifra si solleva e "pompa" a metà strada (--mx/--my), poi
   rientra rimpicciolendo nel gate. La scia luminosa la rende cinematica. */
@keyframes opening-shatter-fly {
    0%   { opacity: 1; transform: translate(0, 0) rotate(0) scale(1); filter: blur(0); }
    18%  { opacity: 1; }
    45%  { opacity: 1;
           transform: translate(var(--mx, 0), var(--my, -60px)) rotate(calc(var(--rot, 0deg) * 0.4)) scale(var(--sc, 1.25));
           filter: blur(0.4px) drop-shadow(0 0 10px rgba(150, 200, 255, 0.7)); }
    100% { opacity: 0;
           transform: translate(var(--dx, 0), var(--dy, 300px)) rotate(var(--rot, 0)) scale(0.16);
           filter: blur(1.4px) drop-shadow(0 0 16px rgba(150, 200, 255, 0.9)); }
}

/* --------------------------------------------------------------------------
   Scomposizione della data nei 7 SEGMENTI (3D verso i gate accesi)

   Ogni cifra si spezza nei suoi segmenti, che volano in 3D (tumbling +
   profondità grazie alla prospettiva) verso i gate, con un bagliore dorato,
   e svaniscono. La posizione/dispersione è calcolata dalla regia.
   -------------------------------------------------------------------------- */
.opening-segshatter {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    perspective: 900px;
    transform-style: preserve-3d;
}
.opening-segshatter .seg {
    position: absolute;
    border-radius: 2px;
    background: linear-gradient(180deg, #fff2c8, var(--accent, #e6b800));
    box-shadow: 0 0 8px var(--accent, #e6b800), 0 0 16px rgba(255, 210, 120, 0.5);
    transform-style: preserve-3d;
    will-change: transform, opacity, filter;
    opacity: 1;
}
.opening-segshatter.go .seg {
    /* Più LENTA (senza accorciare la scena) e con un'UNICA curva morbida:
       ease-in che parte piano (la cifra si scompone appena) e poi accelera
       verso i gate. Niente doppia easing → niente scatto a metà. */
    animation: opening-seg-fly 4.2s cubic-bezier(0.5, 0, 0.75, 0.32) forwards;
    animation-delay: var(--d, 0s);
}
@keyframes opening-seg-fly {
    0%   { opacity: 1;
           transform: translate3d(0, 0, 0) rotateX(0) rotateY(0) rotateZ(0) scale(1);
           filter: drop-shadow(0 0 6px var(--accent, #e6b800)); }
    10%  { opacity: 1;
           filter: drop-shadow(0 0 12px #ffe6a0); }
    100% { opacity: 0;
           transform: translate3d(var(--dx, 0), var(--dy, 0), var(--dz, -300px))
                      rotateX(var(--rx, 0)) rotateY(var(--ry, 0)) rotateZ(var(--rz, 0)) scale(0.15);
           filter: drop-shadow(0 0 18px var(--accent, #e6b800)); }
}
@media (prefers-reduced-motion: reduce) {
    .opening-segshatter.go .seg { animation-duration: 0.7s; }
}

/* --------------------------------------------------------------------------
   Scomposizione LEGGERA per mobile/reduced: un pezzo per carattere, animato
   SOLO con transform+opacity (compositor/GPU, zero paint). Nessun box-shadow
   né filter animato → niente blocca/riprende del video sui telefoni. Il
   bagliore è un text-shadow STATICO, dipinto una volta sola alla nascita.
   -------------------------------------------------------------------------- */
.opening-charshatter {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    font-family: 'DSEG7 Classic', 'Share Tech Mono', ui-monospace, monospace;
    font-weight: 700;
    color: #7fe9ff;
}
.opening-charshatter .chip {
    position: absolute;
    opacity: 1;
    text-shadow: 0 0 8px rgba(120, 200, 255, 0.7), 0 0 18px rgba(120, 150, 255, 0.4);
    will-change: transform, opacity;
    transform: translateZ(0);
}
.opening-charshatter.go .chip {
    animation: opening-charshatter-fly 1.8s cubic-bezier(0.4, 0, 0.2, 1) forwards;
    animation-delay: var(--d, 0s);
}
@keyframes opening-charshatter-fly {
    0%   { opacity: 1; transform: translate(0, 0) rotate(0) scale(1); }
    100% { opacity: 0; transform: translate(var(--dx, 0), var(--dy, 0)) rotate(var(--rz, 0)) scale(0.18); }
}
@media (prefers-reduced-motion: reduce) {
    .opening-charshatter.go .chip { animation-duration: 0.8s; }
}

/* --------------------------------------------------------------------------
   Il finale: esplosione di luce

   Sul finale il mandala accende tutte le porte (nel motore) e qui un bagliore
   caldo si espande e poi si posa: la carta si rivela in un lampo di luce.
   -------------------------------------------------------------------------- */

.opening[data-scene='finale']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background:
        radial-gradient(circle at 50% 52%,
            rgba(255, 240, 205, 0.55) 0%,
            rgba(255, 214, 150, 0.22) 26%,
            rgba(120, 180, 255, 0.08) 48%,
            transparent 66%);
    opacity: 0;
    animation: opening-finale-bloom 4.5s var(--motion-easing-standard) forwards;
}

@keyframes opening-finale-bloom {
    0%   { opacity: 0; transform: scale(0.7); }
    18%  { opacity: 1; }
    45%  { opacity: 0.85; transform: scale(1.05); }
    100% { opacity: 0.2; transform: scale(1); }
}

/* --------------------------------------------------------------------------
   Risucchio e riaccensione

   Dopo il tipo, tutto collassa velocemente verso il centro (risucchio) e si
   spegne; poi il cosmo si riaccende e il mandala esplode di luce.
   -------------------------------------------------------------------------- */

.opening[data-scene='suck_off'] .opening-stage {
    animation: opening-suck 1.1s cubic-bezier(0.7, 0, 0.9, 0.2) forwards;
}

@keyframes opening-suck {
    0%   { transform: scale(1); opacity: 1; filter: brightness(1); }
    70%  { opacity: 1; }
    100% { transform: scale(0.03) rotate(10deg); opacity: 0; filter: brightness(2.4); }
}

.opening[data-scene='reignite'] .opening-stage {
    animation: opening-reignite 1.6s var(--motion-easing-exit) forwards;
}

@keyframes opening-reignite {
    0%   { transform: scale(0.06); opacity: 0; filter: brightness(2.6); }
    40%  { opacity: 1; }
    100% { transform: scale(1); opacity: 1; filter: brightness(1); }
}

.opening[data-scene='reignite']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: radial-gradient(circle at 50% 50%, rgba(255, 245, 220, 0.6), rgba(150, 190, 255, 0.15) 32%, transparent 62%);
    opacity: 0;
    animation: opening-finale-bloom 2.4s var(--motion-easing-standard) forwards;
}

/* Il mandala pieno che esplode prima del bodygraph: un lampo caldo e rapido. */
.opening[data-scene='mandala_burst']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: radial-gradient(circle at 50% 50%, rgba(255, 240, 210, 0.75), rgba(180, 200, 255, 0.2) 34%, transparent 60%);
    opacity: 0;
    animation: opening-finale-bloom 1.6s var(--motion-easing-standard) forwards;
}

/* --------------------------------------------------------------------------
   Chi ha chiesto meno movimento

   Non è una cortesia: per una parte delle persone le animazioni ampie
   provocano nausea, e questa è una scena costruita sul movimento. Chi lo ha
   dichiarato riceve i testi senza la scena.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .opening-stage { display: none; }

    .opening[data-state='playing'] .opening-gloss::after { display: none; }
}

@media (max-width: 640px) {
    .opening-gloss { font-size: var(--type-sm); }
    .opening-readout { font-size: var(--type-xs); }
}

/* --------------------------------------------------------------------------
   L'arrivo dal bianco

   Il video della macchina finisce in bianco pieno. La scena parte da quel
   bianco e ci sprofonda: il lampo diventa il passaggio invece di essere un
   taglio fra due pezzi.
   -------------------------------------------------------------------------- */

.opening[data-light]::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    background: #ffffff;
    pointer-events: none;
    opacity: 1;
    transition: opacity 2.4s var(--motion-easing-standard);
}

.opening[data-light='fading']::before { opacity: 0; }

/* I testi arrivano dopo la luce: leggere sul bianco pieno è impossibile. */
.opening[data-light='true'] .opening-hud { opacity: 0; }

.opening[data-light='fading'] .opening-hud {
    opacity: 1;
    transition: opacity 1.6s var(--motion-easing-standard) 1.2s;
}

/* --------------------------------------------------------------------------
   Il pulsante "Rivedi l'apertura" nella testata del report
   -------------------------------------------------------------------------- */

.reading-replay {
    margin: var(--space-5) 0 0;
}

.reading-replay-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.5em 1.1em;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-full);
    background: transparent;
    color: var(--text-dim);
    font-family: var(--type-family-utility);
    font-size: var(--type-sm);
    letter-spacing: var(--type-tracking-wide);
    cursor: pointer;
    transition: color var(--motion-duration-quick) linear,
                border-color var(--motion-duration-quick) linear;
}

.reading-replay-btn:hover {
    color: var(--text);
    border-color: var(--text-dim);
}

.reading-replay-icon {
    font-size: 0.7em;
    line-height: 1;
}

/* --------------------------------------------------------------------------
   Finale: esplosione accecante e poi buio pieno
   -------------------------------------------------------------------------- */

/* L'esplosione: un lampo bianco-caldo che riempie lo schermo. */
.opening[data-scene='detonate']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background: radial-gradient(circle at 50% 50%, #ffffff, rgba(255, 244, 224, 0.85) 34%, rgba(255, 230, 200, 0.2) 60%, transparent 76%);
    opacity: 0;
    animation: opening-detonate 0.9s ease-out forwards;
}

@keyframes opening-detonate {
    0%   { opacity: 0; transform: scale(0.6); }
    16%  { opacity: 1; transform: scale(1.05); }
    100% { opacity: 0.9; transform: scale(1.25); }
}

/* La scena 3D "scoppia" leggermente insieme al lampo. */
.opening[data-scene='detonate'] .opening-stage {
    animation: opening-stage-burst 0.9s ease-out forwards;
}

@keyframes opening-stage-burst {
    0%   { transform: scale(1); filter: brightness(1); }
    100% { transform: scale(1.3); filter: brightness(2.4); }
}

/* Poi il buio pieno: fine. */
.opening[data-scene='blackout']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 4;
    pointer-events: none;
    background: #000;
    opacity: 0;
    animation: opening-blackout 1.4s ease-in forwards;
}

@keyframes opening-blackout {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}

/* ── IL RITORNO ALLA LUCE, IN DISSOLVENZA ─────────────────────────────────
   'reignite' riposiziona la camera di scatto (vedi sequence.js, enter()):
   un salto che il codice presuppone invisibile perché in quell'istante ogni
   livello è a zero e lo schermo è nero. Questo velo non sostituisce quella
   logica, la ASSICURA: che la coincidenza regga o no su un dato dispositivo,
   lo spettatore vede comunque una dissolvenza vera, mai un taglio secco. */
.opening[data-scene='reignite']::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 4;
    pointer-events: none;
    background: #000;
    opacity: 1;
    animation: opening-reignite-in 800ms ease-out forwards;
}

@keyframes opening-reignite-in {
    0%   { opacity: 1; }
    100% { opacity: 0; }
}

/* ── IL BLOCCO `.opening-end*` NON C'È PIÙ ────────────────────────────────
   Vestiva una seconda schermata di ringraziamenti costruita da
   `showEndScreen()` in machine.js — un metodo che non chiamava nessuno. I
   titoli di coda veri sono `.opening-thanks*`, qui sotto, e li costruisce la
   REGIA del film.

   Centodieci righe che non hanno mai colorato un pixel. Il guaio non era il
   peso del foglio: era che chi cercava dove cambiare l'aspetto della
   schermata finale trovava PRIMA queste — vengono per nome e per posizione —
   e le modificava senza capire perché a schermo non cambiasse niente.

   Se un giorno servisse davvero una seconda schermata, si riscrive: costa
   meno che tenere in giro qualcosa che mente su cosa fa. */

/* ── L'ANIMAZIONE, INVECE, RESTA ─────────────────────────────────────────
   `opening-end-rise` stava dentro quel blocco ma NON gli apparteneva: la
   usano i titoli di coda veri (`.opening-thanks*`, qui sotto) per far salire
   in dissolvenza titolo, marchio, testo e pulsanti, uno dopo l'altro.

   Portandola via con il resto sarebbe rimasta una regola che riferisce
   un'animazione inesistente: nessun errore, nessun avviso — semplicemente
   tutti gli elementi fermi a `opacity: 0`, cioè una schermata finale VUOTA.
   Il nome trae in inganno e per questo è annotato qui. */
@keyframes opening-end-rise {
    to { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------------------
   Ringraziamenti SUL CIELO STELLATO (dentro #opening, sopra la canvas)

   Rimpiazzano la vecchia schermata nera .opening-end: stesso contenuto (grazie,
   logo, powered, testo, link Kefero, pulsanti) ma su fondo TRASPARENTE, con
   solo una lieve vignetta per la leggibilità sopra le stelle. La musica (traccia
   unica) prosegue sotto. Entrano in fade-in.
   -------------------------------------------------------------------------- */

.opening-thanks {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: grid;
    place-items: center;
    padding: 8vw 7vw;
    text-align: center;
    color: #eaf0ff;
    opacity: 0;
    transition: opacity 1200ms ease;
    background: radial-gradient(ellipse at 50% 42%,
        rgba(4, 7, 16, 0.55) 0%, rgba(4, 7, 16, 0.28) 45%, rgba(4, 7, 16, 0) 75%);
}
.opening-thanks[data-on='true']  { opacity: 1; }
.opening-thanks[data-on='false'] { opacity: 0; }

.opening-thanks__inner {
    max-width: 640px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(1rem, 3.5vw, 1.9rem);
}

.opening-thanks__title {
    margin: 0;
    font-family: var(--type-family-display, 'Fraunces', serif);
    font-size: clamp(1.7rem, 6vw, 2.9rem);
    line-height: 1.15;
    color: #f6f1e6;
    opacity: 0;
    transform: translateY(10px);
    animation: opening-end-rise 1100ms ease 250ms forwards;
}

.opening-thanks__brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    opacity: 0;
    animation: opening-end-rise 1100ms ease 650ms forwards;
}
.opening-thanks__logo {
    width: clamp(64px, 16vw, 92px);
    height: auto;
    filter: drop-shadow(0 0 18px rgba(210, 180, 120, 0.35));
}
.opening-thanks__powered {
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: var(--type-sm, 0.85rem);
    letter-spacing: 0.14em;
    color: #d8c9a8;
}

.opening-thanks__intro {
    margin: 0;
    font-size: clamp(0.98rem, 3.4vw, 1.12rem);
    line-height: 1.55;
    color: #cdd6ea;
    max-width: 52ch;
    opacity: 0;
    animation: opening-end-rise 1100ms ease 1050ms forwards;
}

.opening-thanks__share {
    appearance: none;
    background: transparent;
    border: 1px solid rgba(216, 201, 168, 0.5);
    color: #e7ddc4;
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: 0.9rem;
    letter-spacing: 0.08em;
    padding: 0.55em 1.1em;
    border-radius: var(--radius-full, 999px);
    cursor: pointer;
    opacity: 0;
    animation: opening-end-rise 1100ms ease 1400ms forwards;
    transition: background 200ms ease, color 200ms ease, border-color 200ms ease;
}
.opening-thanks__share:hover { background: rgba(216, 201, 168, 0.12); }
.opening-thanks__share[data-copied='true'] { color: #bfe6c4; border-color: rgba(150, 220, 160, 0.6); }

.opening-thanks__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    justify-content: center;
    opacity: 0;
    animation: opening-end-rise 1100ms ease 1700ms forwards;
}
.opening-thanks__btn {
    appearance: none;
    border: 1px solid rgba(216, 201, 168, 0.5);
    background: linear-gradient(180deg, rgba(216, 201, 168, 0.95), rgba(198, 178, 132, 0.95));
    color: #1a1710;
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    padding: 0.72em 1.4em;
    border-radius: var(--radius-full, 999px);
    cursor: pointer;
    transition: transform 120ms ease, box-shadow 200ms ease, background 200ms ease;
}
.opening-thanks__btn:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(210, 180, 120, 0.3); }
.opening-thanks__btn.ghost { background: transparent; color: #e7ecf7; border-color: rgba(180, 195, 225, 0.4); }
.opening-thanks__btn.ghost:hover { border-color: rgba(220, 230, 250, 0.75); box-shadow: none; }

/* I DUE INVITI PRINCIPALI, AFFIANCATI: Condividi Kefero e Regala un coin.
   Card ampie con icona e alone, pensate per invitare al clic; sotto restano
   i due pulsanti secondari (Riguarda / Prosegui). */
.opening-thanks__primary {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(0.7rem, 2vw, 1.1rem);
    justify-content: center;
    width: 100%;
    opacity: 0;
    animation: opening-end-rise 1100ms ease 1400ms forwards;
}
.opening-thanks__card {
    appearance: none;
    flex: 1 1 190px;
    max-width: 262px;
    min-height: 116px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 1.15rem 1rem;
    border-radius: 16px;
    cursor: pointer;
    color: #eef2fb;
    background: color-mix(in srgb, #0a1226 62%, transparent);
    border: 1px solid rgba(150, 170, 210, 0.35);
    -webkit-backdrop-filter: blur(4px);
            backdrop-filter: blur(4px);
    transition: transform 150ms ease, box-shadow 220ms ease, border-color 220ms ease, background 220ms ease;
}
.opening-thanks__card:hover { transform: translateY(-3px); }
.opening-thanks__card:active { transform: translateY(-1px); }
.opening-thanks__card:focus-visible { outline: 2px solid rgba(220, 230, 250, 0.8); outline-offset: 3px; }
.opening-thanks__card-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
}
.opening-thanks__card-label {
    font-family: var(--type-family-utility, 'Share Tech Mono', monospace);
    font-size: 0.95rem;
    letter-spacing: 0.05em;
    line-height: 1.2;
}
/* Condividi: accento freddo, il ciano/viola della macchina. */
.opening-thanks__card--share { border-color: rgba(90, 210, 225, 0.5); }
.opening-thanks__card--share .opening-thanks__card-ico {
    color: #8ff3ec;
    background: radial-gradient(circle, rgba(55, 230, 214, 0.22), rgba(55, 230, 214, 0) 70%);
}
.opening-thanks__card--share:hover {
    border-color: rgba(120, 235, 245, 0.8);
    box-shadow: 0 10px 30px rgba(55, 230, 214, 0.28);
    background: color-mix(in srgb, #0c2030 60%, transparent);
}
.opening-thanks__card--share[data-copied='true'] {
    border-color: rgba(150, 220, 160, 0.85);
    box-shadow: 0 8px 24px rgba(120, 210, 140, 0.3);
}
/* Regala: accento caldo, l'oro della moneta. */
.opening-thanks__card--gift { border-color: rgba(216, 201, 168, 0.55); }
.opening-thanks__card--gift .opening-thanks__card-ico {
    background: radial-gradient(circle, rgba(216, 201, 168, 0.22), rgba(216, 201, 168, 0) 70%);
}
.opening-thanks__card--gift:hover {
    border-color: rgba(230, 210, 150, 0.85);
    box-shadow: 0 10px 30px rgba(210, 180, 120, 0.32);
    background: color-mix(in srgb, #241d10 55%, transparent);
}
.opening-thanks__card .opening-thanks__coin { width: 28px; height: 28px; }

@media (prefers-reduced-motion: reduce) {
    .opening-thanks__title,
    .opening-thanks__brand,
    .opening-thanks__intro,
    .opening-thanks__share,
    .opening-thanks__primary,
    .opening-thanks__actions { animation: none; opacity: 1; transform: none; }
}

/* Mobile in ORIZZONTALE: l'altezza utile è pochissima e la colonna dei
   ringraziamenti, centrata verticalmente e senza scorrimento, veniva tagliata
   sopra e sotto ("si perde tutto"). Qui la compattiamo (misure in vh così
   seguono l'altezza reale), la centriamo solo se ci sta e la rendiamo
   scorribile quando non ci sta. Additivo: portrait e desktop non cambiano. */
@media (max-height: 560px) and (orientation: landscape) {
    .opening-thanks {
        padding: 3vh 6vw;
        place-items: start center;          /* niente centratura verticale che taglia */
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .opening-thanks__inner {
        gap: clamp(0.5rem, 1.8vh, 1rem);
        max-width: 720px;
        margin: auto;                        /* centrato se ci sta, scorre se no */
        padding-block: 2vh;
    }
    .opening-thanks__title { font-size: clamp(1.25rem, 4.6vh, 2rem); }
    .opening-thanks__logo  { width: clamp(44px, 8vh, 64px); }
    .opening-thanks__powered { font-size: 0.72rem; }
    .opening-thanks__intro { font-size: clamp(0.82rem, 2.5vh, 1rem); line-height: 1.4; max-width: 62ch; }
    .opening-thanks__brand   { gap: 0.25rem; }
    .opening-thanks__actions { gap: 0.55rem; }
    .opening-thanks__share { padding: 0.4em 0.9em; font-size: 0.8rem; }
    .opening-thanks__btn   { padding: 0.5em 1.05em; font-size: 0.84rem; }
    .opening-thanks__primary { gap: 0.55rem; }
    .opening-thanks__card { min-height: 0; padding: 0.7rem 0.8rem; flex-basis: 150px; gap: 0.4rem; }
    .opening-thanks__card-ico { width: 34px; height: 34px; }
    .opening-thanks__card-label { font-size: 0.82rem; }
    .opening-thanks__card .opening-thanks__coin { width: 22px; height: 22px; }
}

/* --------------------------------------------------------------------------
   I NUMERI DEL PROFILO in scena

   A bodygraph composto, i numeri del profilo (es. 1/3) compaiono grandi e
   luminosi sopra il grafico, con una scala/bagliore d'ingresso, tengono un
   istante e SVANISCONO subito. Overlay non interattivo, dentro la scena del
   tipo (non ne allunga la durata).
   -------------------------------------------------------------------------- */
.opening-profile {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.28em;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.7s var(--motion-easing-standard);
}
.opening-profile--in  { opacity: 1; }
.opening-profile--out { opacity: 0; transition: opacity 1.2s var(--motion-easing-standard); }

/* Alone scuro dietro i numeri. Più leggero di prima, e per un motivo preciso:
   il profilo non arriva più a composizione finita, arriva MENTRE la figura si
   costruisce. Un alone pieno la coprirebbe proprio nel momento in cui c'è
   qualcosa da guardare — i numeri devono staccarsi dal fondo, non cancellarlo. */
.opening-profile::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: min(70vw, 620px);
    height: min(40vh, 320px);
    transform: translate(-50%, -50%);
    background: radial-gradient(ellipse at center,
                rgba(4, 4, 12, 0.55) 0%, rgba(4, 4, 12, 0.3) 38%, rgba(4, 4, 12, 0) 72%);
    filter: blur(8px);
    z-index: 0;
    opacity: 0;
    transition: opacity 1s var(--motion-easing-standard);
}
.opening-profile--in::before { opacity: 1; }
.opening-profile--out::before { opacity: 0; transition: opacity 1.2s var(--motion-easing-standard); }

/* Uscita in linea con .opening-word: sale, sfuma a fuoco, non più a scatto
   verso i due lati (era brusca, stonava con l'uscita più elegante della
   parola che segue). */
.opening-profile--out .opening-profile__n {
    transform: translateY(-6vh) scale(1.05);
    filter: blur(4px);
    transition: transform 1.2s cubic-bezier(0.3, 0, 0.2, 1),
                filter 1.2s var(--motion-easing-standard),
                opacity 1.2s var(--motion-easing-standard);
}
.opening-profile--out .opening-profile__sep { opacity: 0; transition: opacity 0.5s var(--motion-easing-standard); }

.opening-profile__n {
    position: relative;
    z-index: 1;
    font-family: 'Fraunces', Georgia, serif;
    font-size: clamp(4rem, 20vmin, 13rem);
    font-weight: 300;
    line-height: 1;
    color: #f4f8ff;
    text-shadow: 0 0 28px rgba(122, 215, 255, 0.75), 0 0 64px rgba(122, 215, 255, 0.4);
    transform: translateY(10px) scale(1.06);
    filter: blur(5px);
    opacity: 0;
    transition: transform 1.4s cubic-bezier(0.16, 1, 0.3, 1),
                filter 1s var(--motion-easing-standard),
                opacity 1.1s var(--motion-easing-standard);
}
.opening-profile--in .opening-profile__n { transform: translateY(0) scale(1); filter: blur(0); opacity: 1; }

.opening-profile__sep {
    position: relative;
    z-index: 1;
    align-self: center;
    font-family: 'Fraunces', Georgia, serif;
    font-size: clamp(2.6rem, 12vmin, 8rem);
    font-weight: 300;
    color: rgba(244, 248, 255, 0.55);
}

@media (prefers-reduced-motion: reduce) {
    .opening-profile__n { transform: none; filter: none; transition: opacity 0.4s linear; }
}

/* STRATEGIA, AUTORITÀ, NOT-SELF: parola grande in scena dopo il profilo, una
   alla volta, mentre lo speaker parla. Dietro il testo un ALONE SCURO morbido,
   così la parola non si confonde con le linee del bodygraph. Entrata e uscita
   cinematiche: entra salendo e mettendo a fuoco, esce salendo e dissolvendo. */
.opening-word {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 6vw;
    text-align: center;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1s var(--motion-easing-standard);
}
/* alone scuro dietro (radiale, sfumato): stacca la parola dal bodygraph */
.opening-word::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: min(92vw, 980px);
    height: min(46vh, 380px);
    transform: translate(-50%, -50%);
    background: radial-gradient(ellipse at center,
                rgba(4, 4, 12, 0.9) 0%, rgba(4, 4, 12, 0.62) 38%, rgba(4, 4, 12, 0) 72%);
    filter: blur(8px);
    z-index: 0;
    opacity: 0;
    transition: opacity 1s var(--motion-easing-standard);
}
.opening-word__t {
    position: relative;
    z-index: 1;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 300;
    font-size: clamp(2.1rem, 8.5vmin, 5.6rem);
    line-height: 1.05;
    letter-spacing: 0.14em;
    color: #f4f8ff;
    /* ombra scura per lo stacco + un filo di luce fredda per leggibilità */
    text-shadow: 0 2px 20px rgba(0, 0, 0, 0.92), 0 0 22px rgba(122, 215, 255, 0.32);
    transform: translateY(14px) scale(0.98);
    filter: blur(6px);
    opacity: 0;
    transition: transform 1.3s cubic-bezier(0.16, 1, 0.3, 1),
                letter-spacing 1.3s cubic-bezier(0.16, 1, 0.3, 1),
                filter 0.9s var(--motion-easing-standard),
                opacity 1s var(--motion-easing-standard);
}
.opening-word--in { opacity: 1; }
.opening-word--in::before { opacity: 1; }
.opening-word--in .opening-word__t {
    transform: translateY(0) scale(1);
    letter-spacing: 0.26em;
    filter: blur(0);
    opacity: 1;
}
.opening-word--out { opacity: 0; transition: opacity 1.2s var(--motion-easing-standard); }
.opening-word--out::before { opacity: 0; transition: opacity 1.2s var(--motion-easing-standard); }
.opening-word--out .opening-word__t {
    transform: translateY(-7vh) scale(1.06);
    filter: blur(4px);
    transition: transform 1.2s cubic-bezier(0.3, 0, 0.2, 1),
                filter 1.2s var(--motion-easing-standard),
                opacity 1.2s var(--motion-easing-standard);
}

@media (prefers-reduced-motion: reduce) {
    .opening-word__t { transform: none; filter: none; transition: opacity 0.4s linear; letter-spacing: 0.2em; }
}

/* --------------------------------------------------------------------------
   Nomi dei canali (scena "flows")

   Non più box HUD con punto e linea: solo il NOME del canale, centrato LUNGO
   il canale (sul suo punto medio). Per i canali sovrapposti i nomi si scansano
   in verticale (positionAnchors), così non si intralciano mai.
   -------------------------------------------------------------------------- */
.opening-anchor--bare .opening-anchor__box {
    position: absolute;
    left: 0;
    top: 0;
    transform: translate(-50%, -50%);
    padding: 1px 6px;
    border: none;
    /* Meno invadente: il nome del canale deve accompagnare, non coprire la
       scena. Fondo appena accennato e testo più piccolo/trasparente. */
    background: rgba(6, 10, 20, 0.24);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
    border-radius: 6px;
    align-items: center;
    text-align: center;
    white-space: nowrap;
}
.opening-anchor--bare .opening-anchor__title {
    font-size: 0.62rem;
    font-weight: 400;
    letter-spacing: 0.02em;
    color: #e7edfb;
    opacity: 0.6;
    text-shadow: 0 0 5px rgba(0, 0, 0, 0.8), 0 0 11px rgba(122, 215, 255, 0.32);
}

/* Il pulsante "Regala un coin" nella schermata finale: allinea la moneta al testo. */
.opening-thanks__btn[data-act='gift'] {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
}
.opening-thanks__coin {
    width: 1.15em;
    height: 1.15em;
    display: block;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
