/*
 * Timeline a onda — [timeline_onda]
 *
 * Nessuno sfondo e nessuna larghezza fissa sul contenitore radice: lo sfondo
 * lo mette Elementor, la larghezza e' quella del contenitore.
 *
 * Tutte le misure sono variabili. Quelle geometriche dell'onda vengono lette
 * anche dal JavaScript, che costruisce il tracciato: cambiarle qui basta,
 * non c'e' niente di cablato nel JS.
 */

.kb-onda {

	/* Font: acumin-variable e' gia' caricato globalmente dal sito. */
	--kb-onda-font: "acumin-variable", sans-serif;

	/* --- Geometria dell'onda (misure dal vettore Figma) --------------- */
	--kb-onda-lunghezza-donda: 147.15px;
	--kb-onda-ampiezza: 39.6px;   /* picco rispetto alla linea di mezzeria */
	--kb-onda-spessore: 22px;
	--kb-onda-colore: #2e2e2e;

	/* Distanza fra due tappe, in lunghezze d'onda. Deve restare un numero
	   INTERO: e' cosi' che tutte le tappe cadono sullo stesso punto dell'onda.
	   Con un valore non intero finirebbero a quote diverse. */
	--kb-onda-passo-tappe: 2;

	/* Dove stanno le tappe sull'onda, in frazioni di lunghezza d'onda a
	   partire da un attraversamento a salire:
	     0     mezzeria che sale
	     0.25  CRESTA, il punto piu' alto
	     0.5   mezzeria che scende
	     0.75  avvallamento, il punto piu' basso
	   Qualunque altro valore e' lecito e mette le tappe a mezza gobba. */
	--kb-onda-fase-tappe: 0.25;

	/* --- Rapporto fra scroll e avanzamento -------------------------------
	 * Quanto scroll verticale serve per passare da una tappa alla
	 * successiva, in altezze di finestra. E' la manopola della velocita':
	 * piu' alto = l'onda avanza piu' lentamente sotto la stessa rotellina.
	 *
	 * Non e' una durata. Con ScrollTrigger il progresso e' una funzione
	 * della posizione di scroll, quindi la velocita' del pallino la decide
	 * chi scorre: qui si fissa solo il rapporto di trasmissione.
	 */
	--kb-onda-scroll-passo: 1;

	/* Corsa minima, in pixel, quando la finestra e' bassa.
	 *
	 * La corsa agganciata e' scroll-passo x altezza della finestra, ed e' un
	 * BUDGET DI GESTO, non una grandezza geometrica: le dita non si
	 * accorciano quando si gira il telefono. Su un telefono in orizzontale
	 * l'altezza e' circa 390px, e senza pavimento una tappa disterebbe
	 * dall'altra meno di un colpo di pollice.
	 *
	 * Sul desktop e' inerte: la finestra e' sempre piu' alta di cosi'. */
	--kb-onda-scroll-minimo: 560px;

	/* --- Sosta sulle tappe ------------------------------------------------
	 * Quanto il movimento rallenta in prossimita' di ogni tappa.
	 *
	 * 0 = movimento uniforme: il pallino attraversa la tappa alla stessa
	 * velocita' con cui percorre il resto, e non "arriva" da nessuna parte.
	 * 1 = massimo indugio: si accosta alla tappa con velocita' che tende a
	 * zero, sosta, e riparte.
	 *
	 * Non e' una pausa nel TEMPO: se ci si ferma con lo scroll non si muove
	 * niente comunque. E' una pausa nello SPAZIO DI SCROLL - vicino alla
	 * tappa serve molto scroll per spostare poco - e per questo non richiede
	 * di sequestrare la pagina a nessuno.
	 *
	 * Si paga in velocita' di punta: il movimento tolto vicino alle tappe
	 * ricompare in mezzo. A 0.5 il picco e' il 44% piu' alto che a 0.
	 */
	--kb-onda-sosta: 0.5;

	/* --- Quanto basta per impegnarsi alla tappa successiva -----------------
	 * Frazione del tragitto fra due tappe oltre la quale lo snap va AVANTI
	 * invece di riportare indietro.
	 *
	 * 0.5 sarebbe "vai alla piu' vicina", ed e' il motivo per cui muovendosi
	 * poco si tornava sempre al punto di partenza. 0.3 vuol dire che coprire
	 * un terzo della distanza basta a impegnarsi: il gesto viene assecondato
	 * invece che annullato.
	 *
	 * Non scendere troppo: sotto ~0.15 diventa impossibile restare sulla
	 * tappa dove si e', perche' qualunque assestamento impegna alla prossima.
	 */
	--kb-onda-soglia-avanzamento: 0.3;

	/* Coda garantita oltre i due bordi, in lunghezze d'onda: assicura che
	   l'onda esca sempre dallo schermo a qualunque risoluzione. */
	--kb-onda-coda: 1.5;

	/* --- Pallini ------------------------------------------------------ */
	--kb-onda-pallino-raggio: 9px;
	--kb-onda-pallino-colore: #ffffff;
	--kb-onda-pallino-attivo-colore: #f86036;

	/* --- Testo della tappa -------------------------------------------- */
	--kb-onda-testo-colore: #ffffff;
	--kb-onda-nome-dim: 20px;
	--kb-onda-nome-peso: 500;
	--kb-onda-nome-spaziatura: 0.04em;
	--kb-onda-data-dim: 40px;
	--kb-onda-data-peso: 500;
	--kb-onda-testo-interlinea: 1.15;
	--kb-onda-testo-stacco: 6px;      /* fra nome e data */
	/* Il blocco di testo termina al centro della fascia, sulla stessa
	   verticale del pallino arancione, e da li' si scosta con l'offset. */
	--kb-onda-testo-offset-x: 0px;    /* scosta il testo da sinistra del centro */
	--kb-onda-testo-altezza-min: 84px; /* riserva lo spazio di nome + data */
	--kb-onda-righe-testo: 2;          /* oltre, il testo viene troncato con "..." */

	/* --- Fascia -------------------------------------------------------- */
	--kb-onda-spazio-sopra: 56px;   /* stacco fra il testo e l'onda */

	/* Zero su qualunque schermo, desktop compreso. Lo spazio attorno alla
	   sezione lo governa il container di Elementor, che ha i suoi valori per
	   ogni breakpoint: due padding sovrapposti sono due posti dove cambiare
	   la stessa cosa, e il secondo lo si scopre sempre per sbaglio. Resta una
	   variabile, quindi chi la vuole se la rimette da Elementor. */
	--kb-onda-padding-y: 0px;

	font-family: var(--kb-onda-font);
	display: block;
	position: relative;
	width: 100%;
	min-width: 0;
	/* Nessuno sfondo qui. */
}

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

/* ------------------------------------------------------------------ */
/* Scena: visibile solo quando il JavaScript la attiva                  */
/* ------------------------------------------------------------------ */

/*
 * La scena e' una colonna: prima il testo, poi lo stacco, poi l'onda. Non
 * taglia niente, cosi' il testo non puo' finire sotto l'onda ne' essere
 * ritagliato. A tagliare e' solo la pista, piu' sotto.
 */
.kb-onda__scena {
	display: none;
	position: relative;
	width: 100%;
	flex-direction: column;
	gap: var(--kb-onda-spazio-sopra);
	padding: var(--kb-onda-padding-y) 0;
}

.kb-onda--attiva > .kb-onda__scena {
	display: flex;
}

/*
 * Pista: l'unico blocco che taglia. L'onda e' piu' larga della fascia e deve
 * uscire dai due lati, quindi viene ritagliata qui, al bordo del contenitore.
 */
.kb-onda__pista {
	width: 100%;
	overflow: hidden;
}

/* Il JavaScript aggiunge .kb-onda--attiva solo se puo' animare davvero. */
/* Con l'animazione attiva l'elenco si toglie dagli occhi, NON dalla pagina.
 *
 * Con display:none succedeva questo: la scena e' aria-hidden, quindi
 * invisibile all'albero di accessibilita', e l'elenco spariva da quello
 * stesso albero. Per chi usa un lettore di schermo la sezione diventava un
 * vuoto assoluto - niente fra il titolo e la sezione dopo - pur essendo
 * l'unico posto dove le tappe sono scritte. Contenuto informativo
 * presentato in sola forma decorativa.
 *
 * clip-path invece di left:-9999px: dentro un elemento agganciato in
 * position:fixed uno spostamento fuori schermo genera scorrimento
 * orizzontale, il ritaglio no.
 */
.kb-onda--attiva > .kb-onda__elenco {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* L'SVG lo crea il JavaScript, con larghezza e altezza calcolate. */
.kb-onda__svg {
	display: block;
	position: relative;
	/* Il JavaScript lo sposta a sinistra di una coda INTERA, con un margine
   in linea, cosi' lo zero dell'SVG cade sul bordo della fascia. */
	max-width: none;
}

.kb-onda__tracciato {
	fill: none;
	stroke: var(--kb-onda-colore);
	stroke-width: var(--kb-onda-spessore);
	stroke-linecap: round;
	stroke-linejoin: round;
}

.kb-onda__pallino {
	fill: var(--kb-onda-pallino-colore);
}

.kb-onda__pallino--attivo {
	fill: var(--kb-onda-pallino-attivo-colore);
}

/*
 * Il gruppo mobile e' l'unica cosa che trasla: dentro ci sono il tracciato e
 * i pallini bianchi. Il pallino arancione resta fuori, fermo al centro della
 * fascia, e il JavaScript ne aggiorna la quota a ogni fotogramma perche'
 * segua l'onda che gli scorre sotto.
 */
.kb-onda__mobile {
	will-change: transform;
}

/* Niente transizioni sull'elemento agganciato.
 *
 * ScrollTrigger gli scrive position, top, left e width in linea quando lo
 * aggancia. Elementor dichiara transizioni sui propri contenitori, e se una
 * di quelle ereditasse su questo elemento il browser interpolerebbe valori
 * che GSAP considera gia' applicati: la sezione sobbalzerebbe agganciandosi,
 * soprattutto ri-agganciandosi da sotto. Non e' teorico, e' la trappola piu'
 * segnalata in assoluto sui page builder.
 */
.kb-onda {
	transition: none;
}

/* Il testo sfuma fra una tappa e l'altra.
 *
 * L'opacita' arriva dal JavaScript come variabile, calcolata dalla distanza
 * dalla tappa piu' vicina: non e' una transizione innescata da un evento.
 * E' la ragione per cui il percorso inverso non ha bisogno di codice suo -
 * non c'e' nessuna animazione da rigiocare al contrario, c'e' un valore che
 * si ricalcola uguale in salita e in discesa.
 *
 * Il valore di riserva e' 1: senza JavaScript la scena non compare comunque,
 * ma se comparisse il testo si vedrebbe invece di restare invisibile.
 *
 * Una posizione vuota manda 0 e non ha niente da mostrare; l'altezza minima
 * del blocco resta, cosi' l'onda non salta passando da vuota a piena.
 */
.kb-onda__testo {
	opacity: var(--kb-onda-testo-opacita, 1);
}

/* ------------------------------------------------------------------ */
/* Testo della tappa                                                    */
/* ------------------------------------------------------------------ */

/*
 * Blocco di testo, in flusso sopra l'onda. Largo meta' fascia, quindi il suo
 * bordo destro cade esattamente sul centro orizzontale, dove sta il pallino
 * arancione; il testo e' allineato a destra e ci finisce contro.
 * L'altezza minima evita che l'onda salti quando si passa da un nome su una
 * riga a uno su due.
 */
.kb-onda__testo {
	position: relative;
	width: 50%;
	min-height: var(--kb-onda-testo-altezza-min);
	padding-right: var(--kb-onda-testo-offset-x);
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: flex-end;
	gap: var(--kb-onda-testo-stacco);
	text-align: right;
	color: var(--kb-onda-testo-colore);
	pointer-events: none;
}

/*
 * Nome e data sono limitati a --kb-onda-righe-testo righe. Senza, un nome
 * chilometrico allungherebbe il blocco di testo e spingerebbe giu' l'onda,
 * perche' la scena e' una colonna: testo sopra, onda sotto.
 */
.kb-onda__nome,
.kb-onda__data,
.kb-onda__voce-nome,
.kb-onda__voce-data {
	display: -webkit-box;
	-webkit-line-clamp: var(--kb-onda-righe-testo);
	line-clamp: var(--kb-onda-righe-testo);
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
	overflow-wrap: anywhere;
}

.kb-onda__nome {
	font-size: var(--kb-onda-nome-dim);
	font-weight: var(--kb-onda-nome-peso);
	letter-spacing: var(--kb-onda-nome-spaziatura);
	line-height: var(--kb-onda-testo-interlinea);
	text-transform: uppercase;
}

.kb-onda__data {
	font-size: var(--kb-onda-data-dim);
	font-weight: var(--kb-onda-data-peso);
	line-height: var(--kb-onda-testo-interlinea);
}

/* ------------------------------------------------------------------ */
/* Elenco: contenuto vero. Sempre per gli screen reader, e al posto     */
/* della scena con reduced-motion o senza JavaScript. NON per il mobile */
/* ------------------------------------------------------------------ */

.kb-onda__elenco {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 24px;
	color: var(--kb-onda-testo-colore);
}

.kb-onda__voce {
	display: flex;
	flex-direction: column;
	gap: var(--kb-onda-testo-stacco);
}

.kb-onda__voce-nome {
	font-size: var(--kb-onda-nome-dim);
	font-weight: var(--kb-onda-nome-peso);
	letter-spacing: var(--kb-onda-nome-spaziatura);
	line-height: var(--kb-onda-testo-interlinea);
	text-transform: uppercase;
}

.kb-onda__voce-data {
	font-size: var(--kb-onda-data-dim);
	font-weight: var(--kb-onda-data-peso);
	line-height: var(--kb-onda-testo-interlinea);
}

/* ------------------------------------------------------------------ */
/* Mobile e tablet: la stessa scena, in uno spazio piu' piccolo         */
/* ------------------------------------------------------------------ */

/*
 * La geometria dell'onda NON si tocca: lambda, ampiezza, spessore e raggio
 * restano i valori del vettore Figma su qualunque schermo.
 *
 * Il motivo e' aritmetico. Lambda e' una misura assoluta, non una frazione
 * della larghezza, quindi le creste visibili sono larghezza / lambda:
 *
 *     1920px -> 13      844px -> 5.7      390px -> 2.65
 *
 * Le due creste e mezzo su un telefono ci sono gia'. Scalare lambda verso il
 * basso ne farebbe vedere DI PIU', non di meno: a 110px diventano 3.5. Se un
 * giorno servisse alleggerire l'onda su schermi molto bassi, la strada e' una
 * scala UNIFORME su lambda, ampiezza, spessore e raggio insieme - la
 * proporzione del vettore va conservata, non ritoccata pezzo per pezzo.
 *
 * Quello che scarseggia sul telefono e' l'ALTEZZA, e infatti qui si scala
 * solo il testo e lo stacco fra testo e onda. Il padding verticale e' zero
 * ovunque, desktop compreso, quindi il bilancio della scena e' testo +
 * stacco + banda dell'onda, con la banda ferma a 101.2px:
 *
 *     desktop e tablet   84 + 56 + 101.2 = 241px
 *     telefono in piedi  68 + 32 + 101.2 = 201px  su 844
 *     telefono girato    60 + 20 + 101.2 = 181px  su 390
 */

/*
 * Mobile e tablet: il blocco del testo si centra.
 *
 * Sul desktop il blocco e' largo meta' fascia e allineato a destra, cosi' il
 * suo bordo destro cade sulla verticale del pallino arancione e il testo ci
 * finisce contro. Sotto i 1025px quella composizione non regge: su 390px meta'
 * fascia sono 195px, e "APERTURA BIBLIOTECA CENTRALE" a 15px ci va su due
 * righe, la data su una, e il blocco arriva esattamente al tetto dei 68px.
 *
 * LA LARGHEZZA: 90%, non 100%.
 *
 * A larghezza piena il testo puo' toccare i due bordi dello schermo, e qui
 * non c'e' nessun padding orizzontale ne' nella scena ne' nel container di
 * Elementor. Il 90% lascia un margine che scala da solo: 19px per lato su un
 * telefono, 51px su un tablet. Su 351px lo stesso nome sta su una riga sola,
 * quindi il blocco scende da 68px a una cinquantina e resta sotto il minimo,
 * cioe' l'onda non si sposta mai.
 *
 * IL CENTRO E' QUELLO DEL PALLINO, e non ci vuole niente perche' lo sia: il
 * pallino arancione sta sulla verticale di meta' pista, la pista e' larga
 * quanto la scena, e un blocco centrato nella scena ha il suo stesso centro.
 *
 * padding-right torna a ZERO apposta: --kb-onda-testo-offset-x serve a
 * scostare il testo dal centro quando e' allineato a destra, e qui
 * scenterebbe il blocco rispetto al pallino. Vale 0px oggi, ma e' una
 * variabile e qualcuno puo' cambiarla da Elementor.
 *
 * 1024.98px e non 1023.98: e' il breakpoint di Elementor su questo sito, dove
 * il desktop comincia a 1025 (elementor_viewport_lg). Un tablet in
 * orizzontale e' largo 1180 e resta quindi al trattamento desktop, per
 * entrambi.
 */
@media (max-width: 1024.98px) {

	.kb-onda__testo {
		width: 90%;
		align-self: center;
		align-items: center;
		text-align: center;
		padding-right: 0;
	}
}

/* Telefoni, e tablet in verticale sotto i 768px.
 *
 * Qui il blocco di testo NON e' largo meta' fascia: il blocco dei 1024.98
 * qui sopra l'ha gia' portato al 90%, quindi su 390px sono 351px, non 195.
 * Il commento diceva 195 ed era rimasto indietro di una modifica.
 *
 * I corpi si rimpiccioliscono lo stesso, e per lo stesso motivo di prima:
 * anche su 351px un nome lungo a 20px va su due righe, e con la data a 40px
 * il blocco supera gli 84px del desktop e spinge giu' l'onda, perche' la
 * scena e' una colonna. A 15px lo stesso nome sta su una riga. */
@media (max-width: 767.98px) {

	.kb-onda {
		--kb-onda-nome-dim: 15px;
		--kb-onda-data-dim: 24px;
		--kb-onda-testo-altezza-min: 68px;
		--kb-onda-spazio-sopra: 32px;
	}
}

/*
 * Finestra bassa: il telefono in orizzontale, dove l'altezza e' circa 390px.
 * Sta DOPO il blocco dei 768px apposta: un telefono girato e' largo 844px,
 * quindi quel blocco non lo prende, e questo deve dichiarare tutto.
 */
@media (max-height: 499.98px) {

	.kb-onda {
		--kb-onda-nome-dim: 14px;
		--kb-onda-data-dim: 22px;
		--kb-onda-testo-altezza-min: 60px;
		--kb-onda-spazio-sopra: 20px;
	}
}

/* ------------------------------------------------------------------ */
/* L'unico ripiego rimasto: prefers-reduced-motion                      */
/* ------------------------------------------------------------------ */

/*
 * Fino a ieri qui c'era anche "sotto i 768px, in verticale, su schermi
 * bassi": la timeline si spegneva e restava l'elenco. Adesso la timeline
 * funziona su qualunque schermo, e l'elenco resta per due sole ragioni -
 * chi ha chiesto meno movimento, e chi legge con uno screen reader (per
 * quello l'elenco e' sempre nel DOM, anche a timeline accesa).
 *
 * Il JavaScript non attiva nemmeno la scena quando questa query e' vera,
 * quindi le regole qui dentro sono una seconda rete: se la classe --attiva
 * restasse appesa per un qualunque motivo, l'elenco torna comunque quello
 * che si vede.
 */
@media (prefers-reduced-motion: reduce) {

	.kb-onda {
		--kb-onda-data-dim: 28px;
	}

	.kb-onda--attiva > .kb-onda__scena {
		display: none;
	}

	.kb-onda--attiva > .kb-onda__elenco {
		display: flex;
		position: static;
		width: auto;
		height: auto;
		margin: 0;
		overflow: visible;
		clip-path: none;
		white-space: normal;
	}
}
