/* Motion design : jetons de mouvement, entrée des pages, micro-interactions, notifications, dialogues, menu mobile, accueil.
   Piloté par data-motion sur <html> (auto | reduced | off, posé par js/core/motion.js) et par prefers-reduced-motion.
   Uniquement transform et opacity ; états de départ « cachés » réservés aux classes posées par motion.js (mo-in, mo-reveal,
   mo-hero, mo-count) ; animations remplies vers l'arrière seulement : à la fin, l'élément retrouve exactement son style normal. */

/* ---------- Jetons ---------- */
:root {
  --mo-dur-fast: 140ms;      /* appui, survol */
  --mo-dur: 220ms;           /* fondus, petites transitions */
  --mo-dur-enter: 360ms;     /* entrée d'un élément de page */
  --mo-dur-slow: 450ms;      /* barres, anneaux */
  --mo-stagger: 18ms;        /* décalage de la cascade (12 éléments au plus : 198 ms) */
  --mo-rise: 14px;           /* distance de montée à l'entrée */
  --mo-ease-out: cubic-bezier(.16, 1, .3, 1);       /* sortie « expo » : démarre vite, se pose en douceur */
  --mo-ease-in: cubic-bezier(.4, 0, 1, 1);
  --mo-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --mo-spring: cubic-bezier(.34, 1.4, .64, 1);      /* léger rebond (petits éléments uniquement) */
}

/* ---------- Images clés ---------- */
@keyframes mo-rise { from { opacity: 0; transform: translate3d(0, var(--mo-rise), 0); } 50% { opacity: 1; } }
@keyframes mo-fade { from { opacity: 0; } }
@keyframes mo-lift { from { transform: translate3d(0, 10px, 0); } }
@keyframes mo-pop { from { opacity: 0; transform: scale(.6); } }
@keyframes mo-scale-in { from { opacity: 0; transform: scale(.86); } }
@keyframes mo-fill-x { from { transform: scaleX(0); } }
@keyframes mo-fill-y { from { transform: scaleY(0); } }
@keyframes mo-spin-in { from { opacity: 0; transform: rotate(-90deg) scale(.6); } }
@keyframes mo-sheet-item { from { opacity: 0; transform: translate3d(0, 10px, 0); } }
@keyframes mo-dialog-in { from { opacity: 0; transform: translate3d(0, 12px, 0) scale(.96); } }
@keyframes mo-veil { from { opacity: .9; } to { opacity: 0; } }
@keyframes mo-ripple { from { opacity: .5; transform: scale(1); } to { opacity: 0; transform: scale(2.8); } }
@keyframes mo-ping { 0% { opacity: .6; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(1.9); } }
@keyframes mo-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@keyframes mo-toast-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* ---------- Entrée des pages (cascade) ---------- */
.mo-in {
  animation: mo-rise var(--mo-dur-enter) var(--mo-ease-out) backwards;
  animation-delay: calc(var(--i, 0) * var(--mo-stagger));
}
/* Apparition au défilement : même mouvement, petite cascade entre les éléments atteints ensemble */
.mo-reveal {
  animation: mo-rise 400ms var(--mo-ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 40ms);
}

/* Barres, histogrammes et anneaux se remplissent avec leur carte (tout est fini avant ~600 ms) */
.mo-in .bar__fill, .mo-reveal .bar__fill {
  transform-origin: left center;
  animation: mo-fill-x 420ms var(--mo-ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 9ms + 60ms);
}
.mo-in .cols__bar, .mo-reveal .cols__bar {
  transform-origin: center bottom;
  animation: mo-fill-y 400ms var(--mo-ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 9ms + 60ms);
}
.mo-in .ring, .mo-reveal .ring {
  animation: mo-scale-in 420ms var(--mo-ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 9ms + 40ms);
}
/* Pastilles d'icônes : petit rebond */
.mo-in :is(.stat__icon, .step-card__icon, .module-card__icon, .roadmap__num), .mo-reveal :is(.stat__icon, .step-card__icon, .module-card__icon, .roadmap__num) {
  animation: mo-pop 340ms var(--mo-spring) backwards;
  animation-delay: calc(var(--i, 0) * var(--mo-stagger) + 60ms);
}

/* Compteurs : le nombre qui défile est un pseudo-élément, le texte réel (lu par les lecteurs d'écran) ne change pas */
.mo-count { position: relative; -webkit-text-fill-color: transparent; }
.mo-count::after {
  content: attr(data-mo-n); position: absolute; inset: 0;
  -webkit-text-fill-color: currentColor; white-space: nowrap; pointer-events: none;
}

/* ---------- Accueil : bandeau et schéma réseau ---------- */
.mo-hero { animation: mo-lift 420ms var(--mo-ease-out) backwards; }
.mo-hero :is(.hero__kicker, .hero__title, .hero__lead, .hero__actions) { animation: mo-rise var(--mo-dur-enter) var(--mo-ease-out) backwards; }
.mo-hero .hero__kicker { animation-delay: 30ms; }
.mo-hero .hero__title { animation-delay: 80ms; }
.mo-hero .hero__lead { animation-delay: 130ms; }
.mo-hero .hero__actions { animation-delay: 180ms; }
.mo-hero .hero-topo__links { animation: mo-fade 380ms var(--mo-ease-out) 80ms backwards; }
.mo-hero .hero-topo__nodes > *, .mo-hero .hero-topo__glyphs > * { transform-box: fill-box; transform-origin: center; animation: mo-pop 320ms var(--mo-spring) backwards; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(1) { animation-delay: 80ms; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(2) { animation-delay: 115ms; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(3) { animation-delay: 150ms; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(4) { animation-delay: 185ms; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(5) { animation-delay: 220ms; }
.mo-hero :is(.hero-topo__nodes, .hero-topo__glyphs) > :nth-child(6) { animation-delay: 255ms; }
.mo-hero .hero-topo__labels { animation: mo-fade 300ms var(--mo-ease-out) 240ms backwards; }

/* Ondes autour des routeurs (décor, en boucle lente) et parallaxe à la souris (motion.js) */
:root:not([data-motion="reduced"], [data-motion="off"]) .hero-topo__pulses circle {
  transform-box: fill-box; transform-origin: center;
  animation: mo-ping 2.8s var(--mo-ease-out) infinite;
}
:root:not([data-motion="reduced"], [data-motion="off"]) .hero-topo__pulses circle:nth-child(2) { animation-delay: 1.4s; }
.hero-topo { transition: transform .5s var(--mo-ease-out); }
.hero-topo.is-tracking { will-change: transform; }

/* ---------- Micro-interactions ---------- */
.btn {
  transition: background .15s var(--ease), border-color .15s var(--ease),
    box-shadow var(--mo-dur) var(--mo-ease-out), transform var(--mo-dur-fast) var(--mo-ease-out);
}
.btn .icon { transition: transform var(--mo-dur) var(--mo-ease-out); }
.nav__link .icon, .module-card__icon, .icon-btn .icon { transition: transform var(--mo-dur) var(--mo-ease-out); }
/* Seuls le mouvement et l'ombre s'animent : les couleurs suivent le thème sans retard */
:is(.module-card, a.card, .result-list a, .pager__link, a.chip, .lesson-list a, .choice) {
  transition: transform var(--mo-dur) var(--mo-ease-out), box-shadow var(--mo-dur) var(--mo-ease-out);
}
.nav__link { transition: background .15s var(--ease), color .15s var(--ease), transform var(--mo-dur) var(--mo-ease-out); }

@media (hover: hover) and (pointer: fine) {
  :root:not([data-motion="reduced"], [data-motion="off"]) .btn:hover { transform: translateY(-1px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .btn--primary:hover { box-shadow: 0 8px 18px -10px color-mix(in srgb, var(--primary) 85%, transparent); }
  /* Flèche de fin de bouton (« Continuer → ») : elle avance d'un cran */
  :root:not([data-motion="reduced"], [data-motion="off"]) .btn:hover .icon:last-child:not(:first-child) { transform: translateX(3px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) :is(.module-card, a.card):hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .module-card:hover .module-card__icon { transform: scale(1.08) rotate(-4deg); }
  :root:not([data-motion="reduced"], [data-motion="off"]) :is(.result-list a, a.chip):hover { transform: translateY(-1px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .lesson-list a:hover { transform: translateX(2px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .pager__link--next:hover { transform: translateX(2px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .pager__link:not(.pager__link--next):hover { transform: translateX(-2px); }
  :root:not([data-motion="reduced"], [data-motion="off"]) .nav__link:hover .icon { transform: translateX(2px); }
}
/* Appui : léger enfoncement (tactile compris) */
:root:not([data-motion="off"]) .btn:active { transform: translateY(0) scale(.97); transition-duration: 60ms; }
:root:not([data-motion="off"]) :is(.choice, .lesson-list a, .result-list a):active { transform: scale(.985); transition-duration: 60ms; }
:root:not([data-motion="off"]) :is(.module-card, a.card):active { transform: translateY(-1px) scale(.99); transition-duration: 80ms; }
:root:not([data-motion="off"]) .icon-btn:active .icon { transform: scale(.88); transition-duration: 60ms; }

/* Lien du menu qui devient actif, bouton de thème, croix du menu mobile : l'icône se pose */
.nav__link.is-active .icon { animation: mo-pop 360ms var(--mo-spring); }
#theme-toggle .icon, #nav-toggle[aria-expanded="true"] .icon { animation: mo-spin-in 380ms var(--mo-ease-out); }

/* ---------- Chargement ---------- */
/* Un chargement très court ne clignote pas : l'indicateur n'apparaît qu'au bout de 120 ms */
.loading { animation: mo-fade 240ms var(--mo-ease-out) 120ms backwards; }
.loading__dot { position: relative; }
.loading__dot::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; background: inherit;
  animation: mo-ripple 1.3s var(--mo-ease-out) infinite;
}
/* Squelette de chargement réutilisable : <div class="skeleton" style="height:1rem"></div> */
.skeleton { position: relative; overflow: hidden; border-radius: var(--radius-sm); background: var(--surface-2); }
.skeleton::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--surface) 70%, transparent), transparent);
  animation: mo-shimmer 1.4s var(--mo-ease-in-out) infinite;
}

/* ---------- Notifications ---------- */
/* Entrée avec un léger rebond, sortie plus rapide (ui.js retire l'élément 300 ms après) */
.toast {
  position: relative; overflow: hidden;
  transform: translate3d(0, 14px, 0) scale(.96);
  transition: opacity 180ms var(--mo-ease-in), transform 200ms var(--mo-ease-in);
}
.toast.is-in { transform: none; transition: opacity 220ms var(--mo-ease-out), transform 380ms var(--mo-spring); }
/* Filet qui se vide pendant l'affichage (3,2 s, comme ui.js) */
.toast::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: currentColor; opacity: .28; transform-origin: left center; transform: scaleX(0);
}
.toast.is-in::after { animation: mo-toast-timer 3200ms linear; }

/* ---------- Boîtes de dialogue ---------- */
/* Sur téléphone, css/mobile.css les fait monter du bas comme une feuille : seul le fond s'y estompe d'ici */
@media (min-width: 640px) {
  .dialog[open] { animation: mo-dialog-in 260ms var(--mo-ease-out); }
  :root[data-motion="reduced"] .dialog[open] { animation: mo-fade 160ms var(--mo-ease-out); }
}
.dialog[open]::backdrop { animation: mo-fade 220ms var(--mo-ease-out); }

/* ---------- Bascule de thème : voile de l'ancien fond (motion.js) ---------- */
.mo-veil { position: fixed; inset: 0; z-index: 85; pointer-events: none; animation: mo-veil 380ms var(--mo-ease-in-out) forwards; }

/* ---------- Menu mobile (feuille « Plus » de css/mobile.css) ---------- */
/* La feuille garde ses propres durées ; ses groupes de liens montent en cascade à l'ouverture */
@media (max-width: 639px) {
  .nav-open .nav__group, .nav-open .nav__footer { animation: mo-sheet-item 280ms var(--mo-ease-out) backwards; }
  .nav-open .nav__group:nth-child(1) { animation-delay: 60ms; }
  .nav-open .nav__group:nth-child(2) { animation-delay: 90ms; }
  .nav-open .nav__group:nth-child(3) { animation-delay: 120ms; }
  .nav-open .nav__group:nth-child(4) { animation-delay: 150ms; }
  .nav-open .nav__group:nth-child(n + 5), .nav-open .nav__footer { animation-delay: 180ms; }
}

/* ---------- Animations réduites (réglage) : fondus courts, sans déplacement ni boucle ---------- */
:root[data-motion="reduced"] :is(.mo-in, .mo-reveal, .mo-hero) { animation: mo-fade 180ms var(--mo-ease-out) backwards; }
:root[data-motion="reduced"] :is(.mo-in, .mo-reveal, .mo-hero) :is(.bar__fill, .cols__bar, .ring, .stat__icon, .step-card__icon, .module-card__icon, .roadmap__num,
  .hero__kicker, .hero__title, .hero__lead, .hero__actions, .hero-topo__links, .hero-topo__nodes > *, .hero-topo__glyphs > *, .hero-topo__labels),
:root[data-motion="reduced"] :is(.nav__link.is-active .icon, #theme-toggle .icon, #nav-toggle .icon, .nav-open .nav__group, .nav-open .nav__footer, .loading__dot::after, .skeleton::after) { animation: none; }
:root[data-motion="reduced"] .toast { transform: none; }
:root[data-motion="reduced"] .fc__inner { transition: none; }
:root[data-motion="reduced"] .hero-topo { transition: none; }
:root[data-motion="reduced"] .mo-veil { animation-duration: 200ms; }
:root[data-motion="reduced"] .hero-topo__packet { display: none; }
:root[data-motion="reduced"] * { scroll-behavior: auto !important; }

/* ---------- Animations désactivées (réglage) : aucune animation ni transition ---------- */
:root[data-motion="off"] *, :root[data-motion="off"] *::before, :root[data-motion="off"] *::after, :root[data-motion="off"] ::backdrop {
  animation: none !important; transition: none !important; scroll-behavior: auto !important;
}
:root[data-motion="off"] .hero-topo__packet, :root[data-motion="off"] .mo-veil { display: none; }

/* ---------- Préférence du système « réduire les animations » (mode automatique) ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero-topo__pulses circle { animation: none !important; }
  .toast { transform: none; }
}
