/* --------------------------------------------------------------------------
   Animations de révélation.

   Le JavaScript se contente d'ajouter la classe « is-inview » quand l'élément
   entre dans l'écran ; toute la mise en mouvement est décrite ici.
   -------------------------------------------------------------------------- */

:root {
	--mhc-anim-duration: 720ms;
	--mhc-anim-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

[data-mhc-anim] {
	will-change: opacity, transform;
	transition:
		opacity var(--mhc-anim-duration) var(--mhc-anim-ease),
		transform var(--mhc-anim-duration) var(--mhc-anim-ease);
}

/* Révélation par balayage : le contenu se découvre du bas vers le haut
   derrière un bord net, sans que l'élément lui-même bouge. Convient aux
   images, qu'un déplacement rendrait flottantes.

   La découpe porte sur l'enfant, jamais sur l'élément observé : un élément
   entièrement rogné par clip-path est tenu pour hors écran par
   IntersectionObserver, et ne déclencherait donc jamais sa propre
   apparition. */
[data-mhc-anim="reveal-up"] { overflow: hidden; }

[data-mhc-anim="reveal-up"] > img,
[data-mhc-anim="reveal-up"] > picture,
[data-mhc-anim="reveal-up"] > .mhc-reveal {
	clip-path: inset(0 0 100% 0);
	transform: scale(1.06);
	transition:
		clip-path 1000ms var(--mhc-anim-ease),
		transform 1400ms var(--mhc-anim-ease);
}

[data-mhc-anim="reveal-up"].is-inview > img,
[data-mhc-anim="reveal-up"].is-inview > picture,
[data-mhc-anim="reveal-up"].is-inview > .mhc-reveal {
	clip-path: inset(0 0 0 0);
	transform: scale(1);
}

/* État de départ, par type d'animation. */
[data-mhc-anim="fade"]        { opacity: 0; }
[data-mhc-anim="fade-up"]     { opacity: 0; transform: translateY(32px); }
[data-mhc-anim="fade-down"]   { opacity: 0; transform: translateY(-32px); }
[data-mhc-anim="slide-left"]  { opacity: 0; transform: translateX(48px); }
[data-mhc-anim="slide-right"] { opacity: 0; transform: translateX(-48px); }
[data-mhc-anim="zoom"]        { opacity: 0; transform: scale(0.94); }

/* Révélation par masque : le contenu remonte derrière un bord net.

   Le déplacement porte sur l'enfant « .mhc-reveal », pas sur l'élément
   observé. Un élément entièrement rogné par clip-path est considéré comme
   hors écran par IntersectionObserver : il ne déclencherait jamais sa propre
   apparition. Le parent se contente donc de masquer ce qui dépasse. */
[data-mhc-anim="mask-up"] {
	overflow: hidden;
	/* Marge basse pour ne pas rogner les jambages des lettres. */
	padding-bottom: 0.12em;
}
[data-mhc-anim="mask-up"] .mhc-reveal {
	display: block;
	transform: translateY(105%);
	transition: transform var(--mhc-anim-duration) var(--mhc-anim-ease);
}
[data-mhc-anim="mask-up"].is-inview .mhc-reveal {
	transform: translateY(0);
}

/* État d'arrivée, commun à tous les types. */
[data-mhc-anim].is-inview {
	opacity: 1;
	transform: none;
	will-change: auto;
}

/* --------------------------------------------------------------------------
   Décalage en cascade

   Le script décale déjà les éléments selon leur ordre d'arrivée à l'écran,
   ce qui vaut pour n'importe quelle disposition, grille comprise. Cette
   classe reste disponible pour une cascade purement décorative sur des
   éléments qui ne sont pas observés : ne la posez pas sur un conteneur dont
   les enfants portent « data-mhc-anim », les deux délais s'additionneraient.
   -------------------------------------------------------------------------- */
.mhc-stagger > *:nth-child(1) { transition-delay: 0ms; }
.mhc-stagger > *:nth-child(2) { transition-delay: 90ms; }
.mhc-stagger > *:nth-child(3) { transition-delay: 180ms; }
.mhc-stagger > *:nth-child(4) { transition-delay: 270ms; }
.mhc-stagger > *:nth-child(5) { transition-delay: 360ms; }
.mhc-stagger > *:nth-child(6) { transition-delay: 450ms; }

/* --------------------------------------------------------------------------
   Mouvement réduit
   Réglage système « limiter les animations » : on affiche l'état final
   immédiatement, sans transition ni déplacement.
   -------------------------------------------------------------------------- */
/* Filet de sécurité pour les sauts d'ancre que le script ne traite pas,
   raccourci clavier, lien collé dans la barre d'adresse : la section s'arrête
   sous l'en-tête plutôt que dessous. */
html { scroll-padding-top: 7rem; }

@media (prefers-reduced-motion: reduce) {
	[data-mhc-anim],
	[data-mhc-anim].is-inview,
	[data-mhc-anim] .mhc-reveal {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.mhc-stagger > * { transition-delay: 0ms !important; }

	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
	}
}
