/**
 * Animations du thème E4Y.
 * Emplacement : assets/css/animations.css — chargé après layout.css.
 *
 * Trois règles que ce fichier respecte partout :
 *
 * 1. Rien n'est masqué sans JavaScript. Les états de départ sont préfixés par
 *    .anim-actif, classe posée sur <html> par main.js une fois l'observateur
 *    en place. Si le script échoue, tout le contenu reste visible.
 * 2. On n'anime au survol que ce qui est cliquable. Faire léviter une carte
 *    non interactive promet une action qui n'existe pas.
 * 3. prefers-reduced-motion coupe réellement tout, y compris les keyframes —
 *    passer --duration à 0 ne suffit pas.
 */

/* ============================================================
   Révélation au défilement
   ============================================================ */

/* Le sélecteur cible la valeur vide, pas l'attribut : data-anim écrit seul vaut
   data-anim="". Chaque variante nommée — groupe, media, anneau, parcours — a
   donc son propre comportement sans avoir à neutraliser celui-ci. */
.anim-actif [data-anim=''] {
	opacity: 0;
	transform: translateY(20px);
	transition:
		opacity var(--duration-lente) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
}

.anim-actif [data-anim=''].est-visible {
	opacity: 1;
	transform: none;
}

/* Variante groupe : le conteneur est observé, ses enfants entrent en cascade.
   Un seul observateur pour toute une grille de cartes. */
.anim-actif [data-anim='groupe'] > * {
	opacity: 0;
	transform: translateY(20px);
	transition:
		opacity var(--duration-lente) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
}

.anim-actif [data-anim='groupe'].est-visible > * {
	opacity: 1;
	transform: none;
}

/* Le rang de chaque enfant, en nombre. Il sert au décalage ci-dessous, mais
   surtout il descend par héritage jusqu'à l'intérieur des cartes : ce qu'elles
   animent en propre se règle ainsi sur l'entrée de leur propre carte, sans
   qu'aucun sélecteur n'ait à recompter les rangs. */
[data-anim='groupe'] > *:nth-child(1) { --i: 0; }
[data-anim='groupe'] > *:nth-child(2) { --i: 1; }
[data-anim='groupe'] > *:nth-child(3) { --i: 2; }
[data-anim='groupe'] > *:nth-child(4) { --i: 3; }
[data-anim='groupe'] > *:nth-child(5) { --i: 4; }
[data-anim='groupe'] > *:nth-child(6) { --i: 5; }

.anim-actif [data-anim='groupe'].est-visible > * {
	transition-delay: calc(var(--i, 0) * var(--anim-decalage));
}


/* Variante média : une photo pleine largeur ne peut pas monter, elle se
   décollerait de son bord. Elle se dézoome lentement à la place, sur un temps
   plus long que le fondu pour que le mouvement reste imperceptible.
   overflow évite que le recadrage initial ne déborde en largeur. */
.anim-actif [data-anim='media'] {
	opacity: 0;
	overflow: hidden;
	transition: opacity var(--duration-lente) var(--ease-sortie);
}

.anim-actif [data-anim='media'] > img {
	transform: scale(1.06);
	transition: transform 1400ms var(--ease-sortie);
}

.anim-actif [data-anim='media'].est-visible {
	opacity: 1;
}

.anim-actif [data-anim='media'].est-visible > img {
	transform: none;
}


/* ============================================================
   Cartes chiffre clé — pictogramme, filet, puis décompte

   Trois temps à l'intérieur de chaque carte, calés sur son rang --i pour que
   la cascade horizontale reste lisible. L'ordre suit la lecture, de haut en
   bas : le pictogramme paraît, le filet se trace, et le nombre part alors en
   décompte. Le décompte est le seul des trois que le CSS ne sait pas faire ;
   main.js s'en charge, en lisant son attente ci-dessous.
   ============================================================ */

/* Déclarée pour que getComputedStyle rende une durée résolue plutôt que le
   calc() tel qu'écrit — c'est ce qui permet de garder la valeur ici, en CSS,
   et de n'en écrire aucune dans le script. Un navigateur qui ignore @property
   rend une chaîne illisible, le script retombe alors sur une attente nulle :
   le décompte part avec la carte au lieu de suivre le filet. */
@property --compteur-attente {
	syntax: '<time>';
	inherits: false;
	initial-value: 0s;
}

.anim-actif [data-anim='groupe'] .card-chiffre__img {
	opacity: 0;
	transform: scale(0.82);
	transition:
		opacity var(--duration-lente) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
	transition-delay: calc(var(--i, 0) * var(--anim-decalage) + 120ms);
}

.anim-actif [data-anim='groupe'].est-visible .card-chiffre__img {
	opacity: 1;
	transform: none;
}

/* Le filet se tire du centre vers ses deux bords. Son translateX(-50%) n'est
   pas décoratif, il le centre : il doit être reconduit dans les deux états,
   sinon le filet glisse d'une demi-largeur en s'ouvrant. */
.anim-actif [data-anim='groupe'] .card-chiffre__texte::before {
	transform: translateX(-50%) scaleX(0);
	transition: transform var(--duration-lente) var(--ease-sortie);
	transition-delay: calc(var(--i, 0) * var(--anim-decalage) + 300ms);
}

.anim-actif [data-anim='groupe'].est-visible .card-chiffre__texte::before {
	transform: translateX(-50%) scaleX(1);
}

/* ── Disques chiffrés des pages pays ──────────────────────────

   L'anneau se compose déjà tout seul : il porte son propre data-anim, et ses
   arcs s'allument un à un. Restent le pictogramme et le nombre.

   Le pictogramme paraît une fois l'anneau tracé — 250 ms de pose et
   14 × 70 ms de tracé, soit 700 ms après l'entrée du disque — et le décompte
   suit. Attendre ainsi évite que trois mouvements ne se disputent le regard
   au même instant. */
.anim-actif [data-anim='groupe'] .card-chiffre-rond__picto {
	opacity: 0;
	transform: scale(0.82);
	transition:
		opacity var(--duration-lente) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
	transition-delay: calc(var(--anim-attente) + 700ms + var(--i, 0) * var(--anim-decalage));
}

.anim-actif [data-anim='groupe'].est-visible .card-chiffre-rond__picto {
	opacity: 1;
	transform: none;
}

.card-chiffre-rond__valeur {
	--compteur-attente: calc(var(--anim-attente) + 940ms + var(--i, 0) * var(--anim-decalage));
}

/* Le nombre part quand le filet est tiré. */
.card-chiffre__valeur {
	--compteur-attente: calc(var(--i, 0) * var(--anim-decalage) + 420ms);
}


/* ============================================================
   Anneau segmenté — les arcs s'allument un à un

   --i est posé sur chaque <circle> par le composant anneau. L'ordre suit le
   tracé, l'anneau se compose donc dans le sens horaire.
   ============================================================ */

/* Même temps mort que les animations d'ouverture : l'anneau du Programme est
   au-dessus de la ligne de flottaison, son tracé se jouerait pendant le
   chargement. Plus bas dans la page, ce délai se lit comme un temps de pose
   avant que l'anneau se compose. */
.anim-actif .anneau[data-anim] .anneau__arc {
	opacity: 0;
	transition: opacity 500ms var(--ease-sortie);
	transition-delay: calc(var(--anim-attente) + var(--i, 0) * 70ms);
}

.anim-actif .anneau[data-anim].est-visible .anneau__arc {
	opacity: 1;
}

/* Le contenu central attend que l'anneau soit tracé. */
.anim-actif .anneau[data-anim] .anneau__contenu {
	opacity: 0;
	transition: opacity var(--duration-lente) var(--ease-sortie);
	/* Après les 14 arcs : 250 ms de pose + 14 × 70 ms de tracé. */
	transition-delay: calc(var(--anim-attente) + 700ms);
}

.anim-actif .anneau[data-anim].est-visible .anneau__contenu {
	opacity: 1;
}


/* ============================================================
   Pastilles du parcours — entrée en cascade

   --i est posé sur chaque pastille par le PHP et hérité par son médaillon.
   ============================================================ */

.anim-actif [data-anim='parcours'] .pgm-parcours__pastille {
	opacity: 0;
	transform: scale(0.88);
	transition:
		opacity var(--duration-lente) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
	transition-delay: calc(var(--anim-attente) + var(--i, 0) * var(--anim-decalage));
}

.anim-actif [data-anim='parcours'].est-visible .pgm-parcours__pastille {
	opacity: 1;
	transform: none;
}

/* Le médaillon suit sa pastille d'un temps. Son translateX(-50%) de centrage
   doit être reconduit dans les deux états : l'omettre le décalerait d'une
   demi-largeur au repos. */
.anim-actif [data-anim='parcours'] .pgm-parcours__medaillon {
	opacity: 0;
	transform: translateX(-50%) scale(0.7);
	transition:
		opacity var(--duration) var(--ease-sortie),
		transform var(--duration-lente) var(--ease-sortie);
	transition-delay: calc(var(--anim-attente) + var(--i, 0) * var(--anim-decalage) + 220ms);
}

.anim-actif [data-anim='parcours'].est-visible .pgm-parcours__medaillon {
	opacity: 1;
	transform: translateX(-50%);
}


/* ============================================================
   Ouverture de page — header et hero

   Volontairement hors de .anim-actif, contrairement aux révélations au
   défilement. Une animation en keyframes se termine toujours d'elle-même :
   l'élément finit visible même sans JavaScript, le garde-fou est donc inutile.
   L'y soumettre retarderait le mouvement jusqu'au chargement du script en pied
   de page, ce qui produit un saut au lieu d'une entrée.

   backwards applique l'état initial pendant le délai, sans quoi les éléments
   décalés s'affichent puis disparaissent avant de démarrer.
   ============================================================ */

@keyframes e4y-monte {
	from {
		opacity: 0;
		transform: translateY(24px);
	}
}

@keyframes e4y-descend {
	from {
		opacity: 0;
		transform: translateY(-100%);
	}
}

/* Le bandeau descend, puis les liens montent à leur tour. La transformation
   ne gêne pas le positionnement collant : elle est terminée bien avant le
   premier défilement, et l'animation ne laisse aucun transform résiduel. */
.site-header {
	animation: e4y-descend 800ms var(--ease-sortie) backwards;
}

.site-nav__list > li {
	animation: e4y-monte 600ms var(--ease-sortie) backwards;
	animation-delay: var(--anim-attente);
}

.site-nav__list > li:nth-child(2) { animation-delay: calc(var(--anim-attente) + 60ms); }
.site-nav__list > li:nth-child(3) { animation-delay: calc(var(--anim-attente) + 120ms); }
.site-nav__list > li:nth-child(4) { animation-delay: calc(var(--anim-attente) + 180ms); }
.site-nav__list > li:nth-child(5) { animation-delay: calc(var(--anim-attente) + 240ms); }
.site-nav__list > li:nth-child(6) { animation-delay: calc(var(--anim-attente) + 300ms); }

/* Le hero démarre après le header, pour que les deux mouvements se lisent
   l'un après l'autre plutôt que de se superposer. */
.page-hero__inner > * {
	animation: e4y-monte 800ms var(--ease-sortie) backwards;
	animation-delay: var(--anim-attente);
}

.page-hero__inner > *:nth-child(2) {
	animation-delay: calc(var(--anim-attente) + var(--anim-decalage));
}

.page-hero__inner > *:nth-child(3) {
	animation-delay: calc(var(--anim-attente) + var(--anim-decalage) * 2);
}

.page-hero__inner > *:nth-child(4) {
	animation-delay: calc(var(--anim-attente) + var(--anim-decalage) * 3);
}


/* ============================================================
   Micro-interactions — uniquement sur les éléments actionnables
   ============================================================ */

/* La flèche avance à l'approche du curseur. */
.btn__icon--arrow {
	transition: transform var(--duration) var(--ease);
}

.btn:hover .btn__icon--arrow,
.btn:focus-visible .btn__icon--arrow {
	transform: translateX(4px);
}

/* Flèche diagonale : même geste, dans son axe. */
.btn__icon--diag {
	transition: transform var(--duration) var(--ease);
}

.btn:hover .btn__icon--diag,
.btn:focus-visible .btn__icon--diag {
	transform: translate(3px, -3px);
}

/* Question d'accordéon : léger retrait, sans changement de couleur qui
   entrerait en concurrence avec l'état ouvert. */
.accordeon__question {
	transition: opacity var(--duration) var(--ease);
}

.accordeon__question:hover {
	opacity: 0.78;
}


/* ============================================================
   Préférence système : arrêt complet

   !important assumé — ces règles doivent l'emporter sur tout état de départ
   déclaré plus haut, y compris les délais en cascade.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {

	.site-header,
	.page-hero__inner > *,
	.anim-actif [data-anim],
	.anim-actif [data-anim] > *,
	.anim-actif [data-anim='groupe'] > *,
	.anim-actif [data-anim='media'] > img,
	.anim-actif [data-anim='parcours'] .pgm-parcours__pastille,
	.anim-actif [data-anim='groupe'] .card-chiffre__img,
	.anim-actif [data-anim='groupe'] .card-chiffre-rond__picto,
	.anim-actif .anneau[data-anim] .anneau__arc,
	.anim-actif .anneau[data-anim] .anneau__contenu {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
		animation: none !important;
	}

	/* Même exception que le médaillon : ce transform centre le filet.
	   Le décompte, lui, ne part pas du tout — main.js lit la préférence. */
	.anim-actif [data-anim='groupe'] .card-chiffre__texte::before {
		transform: translateX(-50%) !important;
		transition: none !important;
		animation: none !important;
	}

	/* Exception : ce transform n'est pas décoratif, il centre le médaillon.
	   Le remettre à none le décalerait d'une demi-largeur. */
	.anim-actif [data-anim='parcours'] .pgm-parcours__medaillon {
		opacity: 1 !important;
		transform: translateX(-50%) !important;
		transition: none !important;
		animation: none !important;
	}

}
