/* ============================================================
   Hero a sequenza — Caposile Festival

   Nessun colore e nessuna scala tipografica propria: vengono tutti dal tema
   (--ink, --paper, --c, --f-display, .lbl, .btn-cap). Qui c'è solo la meccanica
   della scena.

   L'aggancio è `position: sticky` e non il `pin` di ScrollTrigger: il pin
   riscrive il DOM attorno alla sezione e dentro l'iframe di LiveCanvas litiga
   con l'editor. Sticky non tocca niente.
   ============================================================ */

.ns-hero {
	/* riscritta dal JS dall'attributo data-lunghezza */
	--ns-hero-lunghezza: 300vh;

	/* Durata e curva dell'entrata dei testi.
	   Lunga di proposito: il testo deve **andarsene**, non sparire. La curva parte
	   quasi ferma e decelera a lungo senza mai rimbalzare — è quella che rende
	   morbide le animazioni di scroll fatte bene, e l'assenza di rimbalzo è metà
	   dell'effetto: un rimbalzo, per piccolo che sia, si legge come un giocattolo. */
	--ns-hero-testo-durata: 1100ms;
	--ns-hero-testo-ease: cubic-bezier(.28, .11, .32, 1);
	--ns-hero-testo-scarto: 44px;

	/* Lo scaglionamento fra un elemento e il successivo dentro lo stesso blocco. */
	--ns-hero-passo: 90ms;

	/* L'altezza della testata, misurata dal JS. Serve a due cose opposte: tirare su
	   la sezione perché il girato passi *sotto* l'intestazione — «a schermo intero in
	   larghezza e lunghezza» — e insieme scostare i testi in giù perché non ci finiscano
	   sotto. Senza la misura sarebbe un numero fisso che sbaglia appena la testata
	   cambia altezza. */
	--ns-hero-testata: 0px;

	position: relative;

	/* Sopra la sezione che segue: senza, quella verrebbe disegnata dopo — è più avanti
	   nel documento — e coprirebbe la scena invece di lasciarsi scoprire. */
	z-index: 3;

	/**
	 * **Finché non è pronta, è alta una schermata e basta.**
	 *
	 * Prima era subito alta tre schermate, con il margine negativo che tira su la
	 * sezione successiva. Ma lo scroll si aggancia solo a caricamento finito: sul
	 * telefono, con otto megabyte e mezzo da scaricare, restavano secondi in cui si
	 * scorreva dentro un'immagine ferma e sbiadita mentre l'hero vero spuntava da
	 * sotto. Non era un difetto di rifinitura: era la pagina rotta per tutto il tempo
	 * che conta, cioè il primo.
	 *
	 * Così invece, finché non è pronta, è un hero a schermo intero normale. Se la rete
	 * non ce la fa, resta quello — ed è una pagina che funziona.
	 */
	height: 100svh;
	margin: calc(-1 * var(--ns-hero-testata)) 0 0;

	/* Il margine negativo in alto porta il girato sotto l'intestazione. */

	/* **Niente fondo qui.** Il nero sta sulla scena, non sulla sezione: la sezione è
	   sopra quella successiva (z-index 3), e un fondo suo si vedrebbe al posto
	   dell'hero proprio nel momento in cui la scena si dissolve per scoprirlo. */
	background: transparent;
}

/**
 * Da qui in poi la sezione è lunga e scorrevole: lo scroll è agganciato.
 *
 * Il margine negativo in basso fa salire la sezione successiva di una schermata, cioè
 * **dietro** la scena mentre questa è ancora appiccicata. Senza, alla fine restava una
 * schermata intera di bianco vuoto da attraversare prima che l'hero comparisse: la scena
 * non aveva più niente da mostrare ma doveva comunque scorrere via.
 *
 * L'altezza della testata rientra nel conto, o la sezione successiva si allinea al bordo
 * dello schermo e la sua prima riga finisce sotto l'intestazione appiccicata.
 *
 * **Tutto in `svh`, niente `vh`.** Su iOS sono due misure diverse — `vh` è il viewport
 * con la barra dell'indirizzo nascosta, `svh` quello con la barra visibile — e
 * mescolarle sulla stessa pagina vuol dire che l'altezza della sezione e quella della
 * scena non concordano mai, e il disallineamento cambia a ogni comparsa della barra.
 */
.ns-hero.is-lunga {
	height: var(--ns-hero-lunghezza);
	margin-bottom: calc(-100svh + var(--ns-hero-testata));
}

/* La scena resta ferma mentre la sezione scorre sotto.
   `svh` e non `vh`: su iOS la barra degli indirizzi cambia `vh` a metà scroll e
   la scena salta di una quarantina di pixel proprio mentre la stai guardando. */
.ns-hero__scena {
	position: sticky;
	top: 0;
	height: 100svh;
	overflow: hidden;
	display: grid;
	place-items: center;

	/* I testi scendono di quanto è alta la testata, così restano centrati nello
	   spazio che si vede davvero invece che nello spazio totale. */
	padding-top: var(--ns-hero-testata);

	/* L'opacità la scrive il JS nell'ultimo tratto: è la dissolvenza che scopre la
	   sezione dietro. `background` esplicito perché mentre svanisce non deve lasciar
	   vedere il nero della sezione. */
	background: #0B0B0C;
}

.ns-hero__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	transform-origin: 50% 50%;
	will-change: transform;
}

/* La velatura in alto.
   L'intestazione del sito diventa bianca sopra la scena, e un fotogramma chiaro —
   il cielo di una ripresa da drone lo è quasi sempre — la farebbe sparire. Questa
   sfumatura le dà sempre qualcosa dietro. Sta sotto il velo, così quando arriva il
   bianco se ne va da sola senza doverla spegnere. */
.ns-hero__scena::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: calc(32svh + var(--ns-hero-testata));
	z-index: 1;
	background: linear-gradient(rgba(11, 11, 12, .78), rgba(11, 11, 12, 0));
	pointer-events: none;
}

/* La stessa cosa in basso: la barra, il comando «salta» e il conteggio sono testo
   chiaro, e senza questa riposano su qualunque cosa capiti nel fotogramma. */
.ns-hero__scena::after {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	height: 26svh;
	z-index: 1;
	background: linear-gradient(rgba(11, 11, 12, 0), rgba(11, 11, 12, .68));
	pointer-events: none;
}

/* Il velo che porta al chiaro. È del colore di fondo del sito, così quando
   arriva a uno la sezione seguente entra senza che si veda la giunzione.

   `z-index: 2` e non 1: uno pseudo-elemento `::after` si disegna **dopo** i figli
   dell'elemento, quindi la velatura in basso finiva sopra il velo e restava
   visibile come una fascia grigia sul bianco. L'ordine nel DOM non basta a
   deciderlo. */
.ns-hero__velo {
	position: absolute;
	inset: 0;
	z-index: 2;
	background: var(--paper, #F2F2F2);
	opacity: 0;
	pointer-events: none;
}

/* --- i testi ------------------------------------------------------------ */

.ns-hero__blocchi {
	position: relative;
	z-index: 3;
	transform-origin: 50% 40%;
	width: 100%;
	max-width: 76rem;
	padding: 0 clamp(1.15rem, 4vw, 3rem);
	display: grid;
}

/* Tutti i blocchi occupano la stessa cella: entrano ed escono nello stesso
   posto, non uno sotto l'altro. È la ragione per cui la griglia ha una cella
   sola e ogni blocco la occupa tutta. */
.ns-hero__blocco {
	grid-area: 1 / 1;
	color: #fff;
	pointer-events: none;
}

.ns-hero__blocco.is-on { pointer-events: auto; }

/* **Si muovono i figli, non il blocco.**
   Far entrare tutto insieme è la differenza fra un'animazione e un cambio di stato:
   l'occhio legge un blocco unico che appare. Scaglionando di novanta millisecondi
   l'occhiello, il titolo e il pulsante, legge invece una cosa che arriva — ed è
   esattamente lo stesso costo. */
.ns-hero__blocco .lbl,
.ns-hero__blocco .btn {
	opacity: 0;
	transform: translateY(var(--ns-hero-testo-scarto));
	transition:
		opacity   var(--ns-hero-testo-durata) var(--ns-hero-testo-ease),
		transform var(--ns-hero-testo-durata) var(--ns-hero-testo-ease);
	will-change: transform, opacity;
}

.ns-hero__blocco.is-on .lbl,
.ns-hero__blocco.is-on .btn {
	opacity: 1;
	transform: none;
}

.ns-hero__blocco.is-on .lbl { transition-delay: 0ms; }
.ns-hero__blocco.is-on .btn { transition-delay: calc(var(--ns-hero-passo) * 3); }

/* --- l'entrata del titolo, riga per riga -------------------------------- */

/*
   Ogni riga è una fessura che taglia, e dentro il testo sale da sotto la propria
   base. Non è una dissolvenza: è una cosa che **arriva**, e la differenza fra le
   due è tutta qui.

   Le fasce le costruisce il JavaScript spezzando il titolo sui `<br>`: nel
   contenuto salvato resta il titolo com'è, e il cliente continua a scriverlo
   normalmente nell'editor.

   `padding-bottom` con `margin-bottom` negativo perché il taglio non mangi le
   discendenti e gli accenti: senza, la coda della «g» sparisce.
*/

.ns-hero__riga {
	display: block;
	overflow: hidden;
	padding-bottom: .12em;
	margin-bottom: -.12em;
}

.ns-hero__riga > span {
	display: block;
	transform: translateY(115%);
	transition: transform 1250ms var(--ns-hero-testo-ease);
	will-change: transform;
}

.ns-hero__blocco.is-on .ns-hero__riga > span { transform: none; }

/* Il titolo non traspare e non si muove come blocco: il movimento è delle righe.
   Sovrapporre le due cose darebbe un doppio movimento, che si legge come un errore. */
.ns-hero__blocco .ns-hero__titolo {
	opacity: 1;
	transform: none;
}

/* In uscita non serve dichiarare niente: tolto `.is-on` restano le regole di base,
   che il ritardo non ce l'hanno. Se ne vanno insieme, ed è giusto così — uno
   scaglionamento all'indietro si legge come una sincronia sbagliata.
   (Il ritardo per riga lo scrive il JS come stile inline, e resta anche in uscita:
   è voluto, le righe rientrano nello stesso ordine in cui erano arrivate.) */

.ns-hero__blocco .lbl {
	color: rgba(255, 255, 255, .62);
	margin-bottom: 1rem;
}

/* Il titolo scala sul contenitore e non sulla finestra: dentro una colonna
   `vw` non sa quanto spazio ha davvero. La riga `vw` resta come ripiego per
   chi non conosce `cqi`, ed è dichiarata per prima di proposito. */
.ns-hero__titolo {
	font-family: var(--f-display);
	font-weight: var(--f-display-weight, 900);
	letter-spacing: var(--f-display-tracking, -.01em);
	text-transform: uppercase;
	line-height: .9;
	margin: 0;

	/* **Niente sillabazione qui.** Le classi display del tema ce l'hanno perché nelle
	   card stanno in colonne strette, dove una parola lunga non ci sta comunque. Un
	   titolo d'apertura ha invece tutta la larghezza: deve andare a capo sugli spazi.
	   Sull'hub evento il titolo arriva da `[lc_the_title]`, quindi senza interruzioni
	   scritte a mano, e usciva «CAPOSILE VE-RONA 2026». */
	hyphens: manual;
	-webkit-hyphens: manual;

	/* Ultima rete, per una parola sola più larga dello schermo. */
	overflow-wrap: break-word;

	/* Le righe si dividono in parti simili invece di lasciarne una con una parola. */
	text-wrap: balance;
	font-size: clamp(2.6rem, 9vw, 7rem);
	font-size: clamp(2.6rem, 10cqi, 7rem);

	/* Non un'ombra per staccare: un alone scuro largo e tenue che scava il fondo
	   dietro le lettere. Il girato ha un neon arancione molto luminoso proprio
	   dove passa il titolo, e senza questo il bianco su bianco-caldo si perde. */
	text-shadow: 0 2px 60px rgba(11, 11, 12, .55), 0 1px 12px rgba(11, 11, 12, .35);
}

.ns-hero__blocco .lbl { text-shadow: 0 1px 16px rgba(11, 11, 12, .6); }

/* --- il caricamento -------------------------------------------------------- */

/*
   **Il caricamento non si mette in scena.**

   Prima era uno schermo nero con una barra al centro, e diciassette megabyte dopo
   sembrava una pagina rotta. Adesso la prima cosa che si vede è il **poster** —
   un file solo, poche decine di chilobyte, disegnato sul canvas entro un istante —
   quindi la scena c'è già: quello che manca è solo la possibilità di scorrerla.

   Resta un filo di avanzamento sul bordo inferiore e un contatore piccolissimo
   nell'angolo. Bastano a dire «sta arrivando» senza diventare l'esperienza.
*/

.ns-hero__carico {
	position: absolute;
	z-index: 6;
	inset: auto 0 0 0;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: .9rem;
	padding: 0 clamp(1.15rem, 4vw, 3rem) 1.1rem;
	opacity: 0;
	transition: opacity 700ms var(--ns-hero-testo-ease);
	pointer-events: none;
}

.ns-hero.is-carica .ns-hero__carico { opacity: 1; }

/* Il contatore: piccolo, mono, tabulare — le cifre non devono ballare mentre salgono. */
.ns-hero__carico-conta {
	font-family: var(--f-mono);
	font-size: .625rem;
	letter-spacing: .14em;
	color: rgba(255, 255, 255, .5);
	font-variant-numeric: tabular-nums;
}

.ns-hero__carico-conta::after { content: "%"; opacity: .5; }

/* Il filo, sul bordo estremo: si vede se lo cerchi, non se guardi la scena. */
.ns-hero__carico-riga {
	position: absolute;
	inset: auto 0 0 0;
	height: 2px;
	background: rgba(255, 255, 255, .14);
	overflow: hidden;
}

.ns-hero__carico-riga > span {
	display: block;
	height: 100%;
	background: rgba(255, 255, 255, .85);
	transform: scaleX(0);
	transform-origin: 0 50%;
	/* gli otto download in parallelo arrivano a scatti: senza questa la barra
	   sobbalza invece di avanzare */
	transition: transform 260ms linear;
}

/* Finché si carica, la scena è appena più morbida e più scura: si capisce che non
   è ancora viva senza doverlo scrivere. Va a fuoco quando è pronta. */
.ns-hero.is-carica .ns-hero__canvas {
	filter: brightness(.72) saturate(.85);
	transform: scale(1.03);
}

.ns-hero__canvas {
	transition:
		filter    1200ms var(--ns-hero-testo-ease),
		transform 1200ms var(--ns-hero-testo-ease);
}

/* --- l'indicatore di scroll ------------------------------------------------ */

/*
   Un anello di testo che gira attorno a una freccia. Sostituisce la scritta «vai al
   festival», che era un ripiego: diceva cosa fare invece di invitare a farlo.

   L'anello ruota sempre, lentamente. La freccia respira. Nessuno dei due movimenti
   è vistoso da solo — insieme dicono «continua» senza una parola in più di
   «SCROLL», che ruotando si legge da qualsiasi punto si guardi.
*/

.ns-hero__scroll {
	position: absolute;
	z-index: 6;
	left: 50%;
	bottom: clamp(1.6rem, 4svh, 3rem);
	width: 104px;
	height: 104px;
	margin-left: -52px;
	display: grid;
	place-items: center;
	color: #fff;
	text-decoration: none;
	opacity: 0;
	transform: translateY(14px);
	transition:
		opacity   900ms var(--ns-hero-testo-ease),
		transform 900ms var(--ns-hero-testo-ease);
}

/* Entra solo quando la scena è pronta, e con un respiro di ritardo: prima si vede
   il fotogramma, poi arriva l'invito. */
.ns-hero.is-pronto .ns-hero__scroll {
	opacity: 1;
	transform: none;
	transition-delay: 500ms;
}

.ns-hero__scroll-anello {
	grid-area: 1 / 1;
	width: 100%;
	height: 100%;
	fill: currentColor;
	animation: ns-hero-gira 16s linear infinite;
}

/* La spaziatura non è a occhio: la circonferenza dell'anello è 2πr ≈ 264px e le tre
   ripetizioni di «SCROLL · » sono 27 caratteri, cioè 9,8px l'uno. Con quattro
   ripetizioni il testo era più lungo del giro e si accavallava su sé stesso. */
.ns-hero__scroll-anello text {
	font-family: var(--f-mono);
	font-size: 9.5px;
	letter-spacing: .41em;
	text-transform: uppercase;
	opacity: .92;
	paint-order: stroke;
	stroke: rgba(11, 11, 12, .45);
	stroke-width: 2.4px;
	stroke-linejoin: round;
}

.ns-hero__scroll-freccia {
	grid-area: 1 / 1;
	width: 24px;
	height: 24px;
	filter: drop-shadow(0 1px 6px rgba(11, 11, 12, .55));
	animation: ns-hero-respira 2.6s var(--ns-hero-testo-ease) infinite;
}

.ns-hero__scroll:hover .ns-hero__scroll-anello,
.ns-hero__scroll:focus-visible .ns-hero__scroll-anello { animation-duration: 7s; }

.ns-hero__scroll:hover .ns-hero__scroll-freccia,
.ns-hero__scroll:focus-visible .ns-hero__scroll-freccia { animation-duration: 1.3s; }

@keyframes ns-hero-gira {
	to { transform: rotate(360deg); }
}

/* Non un rimbalzo: scende, si ferma un istante, risale. La pausa in basso è ciò
   che lo distingue da un'icona che saltella. */
@keyframes ns-hero-respira {
	0%, 100% { transform: translateY(-3px); opacity: .85; }
	45%      { transform: translateY(4px);  opacity: 1; }
	60%      { transform: translateY(4px);  opacity: 1; }
}

/* --- avanzamento dello scroll ------------------------------------------- */

.ns-hero__barra {
	position: absolute;
	z-index: 4;
	inset: auto 0 0 0;
	height: 2px;
	background: var(--c, #1B31D8);
	transform: scaleX(0);
	transform-origin: 0 50%;
}

/* --- l'atterraggio ------------------------------------------------------ */

/* Un ancoraggio alto zero in fondo alla sezione: è dove porta «vai al festival»
   e dove la scena smette di essere appiccicata. */
.ns-hero__fine {
	position: absolute;
	inset: auto 0 0 0;
	height: 1px;
}

/* --- gli stati di rinuncia ---------------------------------------------- */

/*
   `is-statico` — movimento ridotto, Save Data, rete lenta, GSAP assente.
   La sezione smette di essere alta tre schermate e diventa un hero normale:
   una schermata, il poster, i testi già al loro posto. Non è una versione
   degradata, è una versione diversa che funziona.
*/
.ns-hero.is-statico {
	height: 100svh;
	margin: 0;
	z-index: auto;
}

.ns-hero.is-statico .ns-hero__scena { position: relative; }
.ns-hero.is-statico .ns-hero__canvas { display: none; }
.ns-hero.is-statico .ns-hero__velo { display: none; }
.ns-hero.is-statico .ns-hero__carico,
.ns-hero.is-statico .ns-hero__barra,
.ns-hero.is-statico .ns-hero__scroll { display: none; }

/* Con il canvas spento serve un fondo: il poster, o il nero se non c'è nemmeno
   quello. Il poster lo mette il JS come variabile. */
.ns-hero.is-statico .ns-hero__scena {
	background: var(--ns-hero-poster, #0B0B0C) center / cover no-repeat;
}

/* Nello stato statico i blocchi sono tutti visibili: si impilano invece di
   sovrapporsi, o si leggerebbero uno sopra l'altro. */
.ns-hero.is-statico .ns-hero__blocchi { display: block; }
.ns-hero.is-statico .ns-hero__blocco + .ns-hero__blocco { margin-top: 2.5rem; }

@media (prefers-reduced-motion: reduce) {
	.ns-hero__blocco .lbl,
	.ns-hero__blocco .btn { transition: none; }

	/* Le righe restano al loro posto: la fessura c'è ma non taglia niente. */
	.ns-hero__riga > span { transform: none; transition: none; }

	.ns-hero__carico-riga > span { transition: none; }
	.ns-hero__canvas { transition: none; }

	/* L'anello smette di girare e la freccia di respirare: restano fermi e leggibili.
	   Toglierli del tutto vorrebbe dire togliere l'unica indicazione che si scorre. */
	.ns-hero__scroll-anello,
	.ns-hero__scroll-freccia { animation: none; }
}

/* --- l'intestazione del sito sopra la scena ------------------------------ */

/* L'unico punto in cui questo componente tocca un elemento fuori da sé, ed è
   inevitabile: la testata del tema è scura su fondo chiaro e sopra la scena
   sparirebbe. La classe la mette e la toglie il JS. */
header.sticky-blur.is-su-hero {
	background: transparent !important;
	border-color: transparent !important;
	box-shadow: none !important;
	backdrop-filter: none !important;
}

header.sticky-blur.is-su-hero-scuro { color: #fff; }

header.sticky-blur.is-su-hero-scuro a,
header.sticky-blur.is-su-hero-scuro .lbl { color: #fff; }

/* Il gruppo a pillola della navigazione ha un fondo chiaro suo, e il testo qui
   diventa bianco: bianco su chiaro non si legge. Va scurito insieme al testo —
   invertire il colore senza invertire il fondo è mezzo lavoro. */
/* Il gruppo a pillola ha un fondo chiaro suo. Sopra il girato va scurito insieme
   al testo — invertire il colore senza invertire il fondo è mezzo lavoro. Quando il
   velo è già bianco torna quello di sempre, perché lì sotto il fondo è chiaro. */
header.sticky-blur.is-su-hero .nav-pills {
	background: transparent !important;
}

header.sticky-blur.is-su-hero-scuro .nav-pills {
	background: rgba(255, 255, 255, .12) !important;
	backdrop-filter: blur(6px);
}

header.sticky-blur.is-su-hero-scuro .nav-pills .nav-link.active,
header.sticky-blur.is-su-hero-scuro .nav-pills .show > .nav-link {
	background: rgba(255, 255, 255, .22);
	color: #fff;
}

/* Lo stesso per il selettore di lingua, che è un menù con fondo bianco. */
header.sticky-blur.is-su-hero-scuro .wpml-ls select,
header.sticky-blur.is-su-hero-scuro .wpml-ls a,
header.sticky-blur.is-su-hero-scuro .wpml-ls-item a {
	background: rgba(255, 255, 255, .12);
	color: #fff;
	border-color: rgba(255, 255, 255, .28);
}

header.sticky-blur.is-su-hero-scuro .btn-cap {
	background: #fff;
	color: #0B0B0C;
	border-color: #fff;
}

/* Il pulsante che apre il menù sul telefono: bordo e icona ereditano il colore,
   ma il bordo scuro sparirebbe sul girato. */
header.sticky-blur.is-su-hero-scuro .btn.border {
	border-color: rgba(255, 255, 255, .4) !important;
	color: #fff;
}

/* Mentre il pulsante porta avanti da solo, l'anello gira in fretta: dice che il
   movimento lo sta facendo lui e non tu, che è l'unica cosa che distingue uno
   scorrimento automatico da uno impazzito. */
.ns-hero.is-scorre .ns-hero__scroll-anello { animation-duration: 3.5s; }
.ns-hero.is-scorre .ns-hero__scroll-freccia { animation-duration: 900ms; }
