/*
 * GOYN — entrate al passaggio in vista (meccanismo condiviso)
 *
 * Fonte: il `whileInView` di Motion, usato in tutte le sezioni della home del
 * progetto React (`Rise` e `SplitLines` in src/components/Text.jsx).
 *
 * ═════════════════════════════════════════════════════════════════════════
 * IL CONTRATTO
 * ═════════════════════════════════════════════════════════════════════════
 *
 *   data-goyn-scene       sul contenitore da osservare. reveal.js gli aggiunge
 *                         `is-armed` (gli stati iniziali entrano in vigore) e
 *                         poi `is-in` quando arriva in vista.
 *   data-goyn-rise        su ciò che entra da sotto con dissolvenza.
 *   data-goyn-rise-line   sullo `<span>` dentro `.goyn-line`: entra da sotto la
 *                         maschera, senza dissolvenza.
 *   data-goyn-rise-wipe   si scopre dal basso con un `clip-path`, senza muoversi.
 *                         Per le fotografie: una foto che sale trascina con sé il
 *                         proprio ritaglio e il soggetto sembra scivolare.
 *
 *   --goyn-delay          ritardo del singolo elemento (0 se assente). È qui
 *                         che ogni widget esprime la propria cascata: un
 *                         `calc()` con l'indice della voce, scritto dal
 *                         template.
 *   --goyn-rise-shift     di quanto sale (24px se assente).
 *   --goyn-rise-dur       durata (0.85s se assente).
 *
 * ═════════════════════════════════════════════════════════════════════════
 * PERCHÉ `is-armed` E NON GLI STATI INIZIALI SEMPRE ATTIVI
 * ═════════════════════════════════════════════════════════════════════════
 *
 * `opacity: 0` scritto senza condizioni è contenuto invisibile ogni volta che
 * lo script non gira: file non servito, errore a monte, browser senza
 * IntersectionObserver. Gli stati iniziali valgono quindi solo dentro
 * `.is-armed`, che aggiunge reveal.js — e solo dopo aver verificato di poter
 * anche togliere quello stato.
 *
 * La classe è sulla SCENA e non su `<html>`: due sezioni nella stessa pagina
 * sono indipendenti, e una scena che lo script non ha ancora raggiunto non
 * deve sparire perché un'altra è pronta.
 *
 * ⚠️ `both` come fill, non `forwards`: durante il ritardo l'elemento deve
 *    restare nello stato di partenza. Con `forwards` da solo si vedrebbe un
 *    lampo a piena opacità prima che il ritardo scada.
 *
 * ⚠️⚠️ CONSEGUENZA DA RICORDARE: un elemento con `data-goyn-rise` NON può
 *      ricevere altre trasformazioni. Il `fill` lascia scritta per sempre la
 *      `transform` del fotogramma finale (`none`), e un'animazione batte
 *      qualunque dichiarazione normale nella cascata: la trasformazione
 *      dichiarata nel foglio viene calcolata e ignorata.
 *
 *      Se all'elemento serve anche un'altra trasformazione — un parallasse,
 *      un'inclinazione che segue il puntatore, un ingrandimento — mettila su un
 *      FIGLIO. È il motivo per cui la fotografia del manifesto ha due livelli
 *      (tendina fuori, parallasse dentro) e quelle della newsletter pure
 *      (entrata sul riquadro, inclinazione dentro). Misurato in pagina in
 *      entrambi i casi.
 *
 * ═════════════════════════════════════════════════════════════════════════
 * ENTRATE PROPRIE DI UNA SEZIONE
 * ═════════════════════════════════════════════════════════════════════════
 *
 * Qui stanno le tre entrate che ricorrono. Una sezione che ne ha una davvero
 * sua NON aggiunge un'animazione a questo file: si agancia allo stesso
 * interruttore, nel proprio foglio.
 *
 *   [data-goyn-scene].is-armed .mia-classe        { stato di partenza }
 *   [data-goyn-scene].is-armed.is-in .mia-classe  { animation: … }
 *
 * Così l'effetto resta dove è usato e la garanzia importante — nessuno stato
 * iniziale senza JavaScript — vale comunque, perché `is-armed` la mette solo
 * reveal.js. Ricordarsi di annullare lo stato di partenza sotto
 * `prefers-reduced-motion`, come fa la sezione 5 qui sotto per i due casi
 * generali.
 */

/* ============================================================
   1. I fotogrammi
   ============================================================ */

@keyframes goyn-rise {
	from {
		opacity: 0;
		transform: translateY(var(--goyn-rise-shift, 24px));
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* La riga di titolo entra da sotto la maschera di `.goyn-line` con la
   rotazione di 2 gradi dell'originale. Nessuna dissolvenza: la maschera fa già
   tutto, e un fade renderebbe visibile il bordo del ritaglio. */
@keyframes goyn-rise-line {
	from {
		transform: translateY(110%) rotate(2deg);
	}

	to {
		transform: none;
	}
}

/*
 * La tendina che scopre dal basso. Nessuna opacità e nessuno spostamento: un
 * ritaglio a altezza zero è già invisibile, e muovere una fotografia mentre la
 * si scopre fa scivolare il soggetto dentro l'inquadratura.
 *
 * ⚠️ `clip-path` va animato in @keyframes e NON interpolato in JavaScript: nel
 *    progetto React interpolare stringhe di `clipPath` con `useTransform` dava
 *    valori non monotoni. Il browser interpola due `inset()` della stessa forma
 *    senza problemi.
 */
@keyframes goyn-rise-wipe {
	from {
		clip-path: inset(0 0 100% 0);
	}

	to {
		clip-path: inset(0 0 0 0);
	}
}

/* ============================================================
   2. Stati iniziali — solo a scena armata
   ============================================================ */

[data-goyn-scene].is-armed [data-goyn-rise] {
	opacity: 0;
}

[data-goyn-scene].is-armed .goyn-line > span[data-goyn-rise-line] {
	transform: translateY(110%) rotate(2deg);
}

[data-goyn-scene].is-armed [data-goyn-rise-wipe] {
	clip-path: inset(0 0 100% 0);
}

/* ============================================================
   3. L'entrata
   ============================================================ */

[data-goyn-scene].is-armed.is-in [data-goyn-rise] {
	animation: goyn-rise var(--goyn-rise-dur, 0.85s)
		var(--goyn-ease, cubic-bezier(0.22, 1, 0.36, 1))
		var(--goyn-delay, 0ms) both;
}

[data-goyn-scene].is-armed.is-in .goyn-line > span[data-goyn-rise-line] {
	animation: goyn-rise-line var(--goyn-rise-dur, 1s)
		var(--goyn-ease, cubic-bezier(0.22, 1, 0.36, 1))
		var(--goyn-delay, 0ms) both;
}

[data-goyn-scene].is-armed.is-in [data-goyn-rise-wipe] {
	animation: goyn-rise-wipe var(--goyn-rise-dur, 1s)
		var(--goyn-ease, cubic-bezier(0.22, 1, 0.36, 1))
		var(--goyn-delay, 0ms) both;
}

/* ============================================================
   4. Editor di Elementor
   ------------------------------------------------------------
   reveal.js non parte nell'editor, quindi `is-armed` non c'è e queste regole
   di norma non servono. Coprono il caso in cui la classe resti su un elemento
   da una resa precedente: Elementor riusa il DOM dell'anteprima, e un
   contenuto invisibile nel pannello è un guasto, non un effetto.
   ============================================================ */

.elementor-editor-active [data-goyn-scene] [data-goyn-rise],
.elementor-editor-preview [data-goyn-scene] [data-goyn-rise] {
	opacity: 1;
	animation-name: none;
}

.elementor-editor-active [data-goyn-scene] .goyn-line > span[data-goyn-rise-line],
.elementor-editor-preview [data-goyn-scene] .goyn-line > span[data-goyn-rise-line] {
	transform: none;
	animation-name: none;
}

.elementor-editor-active [data-goyn-scene] [data-goyn-rise-wipe],
.elementor-editor-preview [data-goyn-scene] [data-goyn-rise-wipe] {
	clip-path: none;
	animation-name: none;
}

/* ============================================================
   5. prefers-reduced-motion
   ------------------------------------------------------------
   Il child theme azzera le durate dentro `.goyn-widget` (base.css, sezione 6),
   e con una durata a zero uno stato iniziale resterebbe fissato per sempre:
   un titolo fuori dalla maschera, dei blocchi invisibili. Qui si annullano
   gli stati, non le animazioni.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
	[data-goyn-scene].is-armed [data-goyn-rise] {
		opacity: 1;
	}

	[data-goyn-scene].is-armed .goyn-line > span[data-goyn-rise-line] {
		transform: none;
	}

	[data-goyn-scene].is-armed [data-goyn-rise-wipe] {
		clip-path: none;
	}
}
