/* ==========================================================================
   Animations — état initial masqué des éléments animés au chargement / scroll
   ==========================================================================

   Ce fichier ne fait qu'UNE chose : masquer l'état de départ des éléments
   que GSAP anime ensuite (opacity 0). Le décalage vertical (translateY)
   est géré uniquement par GSAP (fromTo), ce qui permet à
   `clearProps: 'transform'` de rendre un style parfaitement propre en fin
   d'animation sans que le CSS ne réapplique un décalage résiduel.

   Tout est conditionné à la classe `.anim-ready`, posée sur <html> par un
   petit script inline dans le <head> (voir functions.php) AVANT le premier
   rendu, et uniquement si :
     - JavaScript est actif ;
     - l'utilisateur n'a PAS demandé « réduire les animations »
       (prefers-reduced-motion: reduce).

   Conséquences :
     - Sans JS / JS en échec / mouvement réduit : la classe est absente,
       donc AUCUNE de ces règles ne s'applique, tout le contenu est visible
       immédiatement dans son état final (comme si ce fichier n'existait pas).
     - Avec animations : l'état masqué est appliqué dès le <head>, donc pas
       de « flash » de contenu visible puis caché.
     - Filet de sécurité : si GSAP ne se charge pas, animations.js retire
       lui-même `.anim-ready`, ce qui ré-affiche tout via ces mêmes règles.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Reveal au scroll — sections d'un bloc + cartes en cascade (Phase 1)
   -------------------------------------------------------------------------- */
.anim-ready .esg-banner,
.anim-ready .brochure-cta,
.anim-ready .division-overview,
.anim-ready .division-case-study,
.anim-ready .division-cta,
.anim-ready .about-journey,
.anim-ready .about-footprint,
.anim-ready .about-cta,
.anim-ready .news-featured,
.anim-ready .news-filters,
.anim-ready .news-grid__empty,
.anim-ready .news-newsletter,
.anim-ready .contact-main,
.anim-ready .contact-faq,
.anim-ready .careers-empty,
.anim-ready .careers-offer,
.anim-ready .careers-apply,
.anim-ready .atlas-map-section,
.anim-ready .atlas-no-route,
.anim-ready .divisions-bento__grid > .division-card,
.anim-ready .news__track > .news-card,
.anim-ready .about-mvv__grid > .about-mvv__card,
.anim-ready .about-leadership__grid > .leader-card,
.anim-ready .news-grid > .news-card,
.anim-ready .careers-grid > .careers-grid__item,
.anim-ready .division-services .service-card {
	opacity: 0;
}

/* --------------------------------------------------------------------------
   Entrée animée du Hero au chargement (Phase 3)

   Le Hero lui-même reste visible immédiatement (pas de ScrollTrigger) :
   seuls ses éléments internes (badge, titre, sous-titre, CTA) partent
   masqués et sont révélés par une timeline GSAP jouée au chargement.
   Le slider (images, pagination, flèches) n'est pas concerné.
   -------------------------------------------------------------------------- */
.anim-ready .hero__actions,
.anim-ready .about-hero__title,
.anim-ready .news-hero__overline,
.anim-ready .news-hero__title,
.anim-ready .contact-hero__title,
.anim-ready .contact-hero__subtitle,
.anim-ready .careers-hero__back,
.anim-ready .careers-hero__title,
.anim-ready .careers-hero__subtitle,
.anim-ready .atlas-hero__title,
.anim-ready .atlas-hero__subtitle,
.anim-ready .division-hero__overline,
.anim-ready .division-hero__title,
.anim-ready .division-hero__subtitle,
.anim-ready .article-hero__badge,
.anim-ready .article-hero__title,
.anim-ready .article-hero__meta,
.anim-ready .training-cta__eyebrow,
.anim-ready .training-cta__title,
.anim-ready .training-cta__subtitle,
.anim-ready .training-cta__content .btn {
	opacity: 0;
}

/* --------------------------------------------------------------------------
   Hero (accueil) — titre et sous-titre en « machine à écrire » (frappe unique)

   Le H1 et le sous-titre ne sont PLUS masqués ni animés en fondu (ils ne
   figurent donc plus dans la liste ci-dessus ; seuls les CTA le restent) :
   sous `.anim-ready` leur vrai texte (.hero__tw-text) reste dans le flux — il
   réserve la hauteur exacte du texte complet, donc rien ne bouge pendant la
   frappe — et dans l'arbre d'accessibilité, mais il est rendu invisible
   (opacity, pas display/visibility). Le calque .hero__tw-typed (aria-hidden,
   rempli par animations.js) se superpose exactement à lui :
     - ::before = lettres déjà écrites (data-shown) ;
     - ::after  = lettres restantes (data-rest), invisibles mais présentes
       pour que les retours à la ligne soient identiques à ceux du texte
       complet (sans cela un mot en cours de frappe sauterait à la ligne).
   Une fois la ligne écrite, le JS pose `.is-static` : le vrai texte reprend la
   place du calque (identique au pixel près) et le calque disparaît.
   Mouvement réduit / sans JS / GSAP absent : `.anim-ready` est absent, aucune
   de ces règles ne s'applique → les textes complets s'affichent d'emblée.
   -------------------------------------------------------------------------- */
.anim-ready [data-typewriter] {
	position: relative;
}

.anim-ready [data-typewriter] > .hero__tw-text {
	opacity: 0;
}

.anim-ready [data-typewriter] > .hero__tw-typed {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	pointer-events: none;
	user-select: none;
}

.anim-ready [data-typewriter] > .hero__tw-typed::before {
	content: attr(data-shown);
}

/* Aucune décoration (bordure, marge, padding, inline-block, enfant en absolu)
   à la frontière entre les deux parties : la moindre décoration coupe le
   crénage / ouvre un point de césure à cet endroit, et le calque peut alors
   se retourner à la ligne autrement que le vrai texte (mot qui saute). C'est
   aussi pourquoi il n'y a pas de curseur. */
.anim-ready [data-typewriter] > .hero__tw-typed::after {
	content: attr(data-rest);
	visibility: hidden;
}

.anim-ready [data-typewriter].is-static > .hero__tw-text {
	opacity: 1;
}

.anim-ready [data-typewriter].is-static > .hero__tw-typed {
	display: none;
}
