/* ============================================================
   animations.css — reveals au scroll + micro-interactions.
   Compositor-only (transform/opacity). Etats finaux garantis sous reduced-motion.
   ============================================================ */

/* reveal : masque au repos, revele a l'entree (.in via IntersectionObserver + safety sweep) */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out);
  will-change: opacity, transform;
}
/* une fois revele, on libere la couche compositeur (will-change persistant = fuite memoire) */
.reveal.in { opacity: 1; transform: none; will-change: auto; }
.reveal[data-delay="1"] { transition-delay: 0.06s; }
.reveal[data-delay="2"] { transition-delay: 0.12s; }
.reveal[data-delay="3"] { transition-delay: 0.18s; }
.reveal[data-delay="4"] { transition-delay: 0.24s; }
.reveal[data-delay="5"] { transition-delay: 0.30s; }

/* stagger pour grilles (cartes) */
.stagger > * { opacity: 0; transform: translateY(18px); transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out); }
.stagger.in > * { opacity: 1; transform: none; }
.stagger.in > *:nth-child(1) { transition-delay: 0.02s; }
.stagger.in > *:nth-child(2) { transition-delay: 0.08s; }
.stagger.in > *:nth-child(3) { transition-delay: 0.14s; }
.stagger.in > *:nth-child(4) { transition-delay: 0.20s; }
.stagger.in > *:nth-child(5) { transition-delay: 0.26s; }
.stagger.in > *:nth-child(6) { transition-delay: 0.32s; }

/* counters : pas d'animation CSS, gere en JS (rAF) — la valeur finale est dans le DOM */

/* lien souligne anime */
.link-underline { position: relative; }
.link-underline::after {
  content: ""; position: absolute; inset-inline: 0; inset-block-end: -2px; block-size: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: inline-start;
  transition: transform var(--t) var(--ease-out);
}
.link-underline:hover::after { transform: scaleX(1); }

/* sous reduced-motion : tout l'etat final est applique immediatement (le safety net global coupe les durees) */
@media (prefers-reduced-motion: reduce) {
  .reveal, .stagger > * { opacity: 1 !important; transform: none !important; }
}

/* pause manuelle des fonds animes continus (bouton .motion-toggle, WCAG 2.2.2,
   distinct de prefers-reduced-motion) : coupe toute animation continue, garde les contenus visibles */
html[data-motion="reduce"] .aurora::before,
html[data-motion="reduce"] .aurora::after,
html[data-motion="reduce"] .aurora i,
html[data-motion="reduce"] .today-card::before,
html[data-motion="reduce"] .dot-live::after {
  animation: none !important;
}
html[data-motion="reduce"] .reveal,
html[data-motion="reduce"] .stagger > * { opacity: 1 !important; transform: none !important; }

/* ---- Transitions de navigation entre documents (MPA same-origin) ----
   Cross-fade GPU, 0 JS : toutes les pages partagent ce fichier -> opt-in mutuel des deux documents.
   navigation:auto ne couvre que les nav same-origin declenchees par le contenu (pas la barre d'URL),
   et degrade en swap instantane sur les navigateurs sans support cross-document (Firefox/Safari 2026).
   Ref. developer.chrome.com/docs/web-platform/view-transitions/cross-document. */
@view-transition { navigation: auto; }
/* prefers-reduced-motion (OS) : swap instantane, aucune animation plein ecran (inconfort vestibulaire).
   Signal fiable au pagereveal cross-document — contrairement a data-motion (pose par JS apres parse) ;
   un cross-fade one-shot de navigation reste hors du champ de WCAG 2.2.2 (mouvement *continu*). */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
