/* ===================== animations.css =====================
 * TOUTES les animations de l'appli sont ici, et TOUTES sont sous « html.anim-on ».
 * Cette classe est posée par js/animations.js seulement si le réglage « Animations »
 * est activé ET si le téléphone n'a pas demandé de réduire les animations.
 * Sans la classe : l'appli est exactement comme avant.
 * Pour tout retirer : supprimer ce fichier, js/animations.js et leurs deux lignes dans index.html.
 * Règle : on n'anime que transform et opacity (fluide même sur un vieux téléphone).
 * ========================================================= */

:root {
  --a-fast: 150ms;
  --a-med: 240ms;
  --a-slow: 300ms;
  --a-shift: 18px;                                   /* amplitude des glissements (petit écran) */
  --a-ease: cubic-bezier(.22, .8, .3, 1);
  --a-bounce: cubic-bezier(.34, 1.56, .64, 1);
}
/* Ordinateur à la souris : mouvements un peu plus amples */
@media (hover: hover) and (pointer: fine) and (min-width: 900px) {
  :root { --a-med: 280ms; --a-slow: 320ms; --a-shift: 32px; }
}

/* Pas de barre de défilement horizontale parasite pendant un mouvement : on coupe ce qui dépasse
 * sur le conteneur des écrans (en permanence), et NON sur <html> : changer l'overflow de <html>
 * en cours de route modifiait la taille de l'écran sur certains téléphones (l'accueil « grandissait »). */
html.anim-on #view-root { overflow-x: clip; }

/* ---------- 1. Transitions entre écrans ---------- */
/* a) API View Transitions (Chrome, Edge, Safari récents) : l'en-tête reste en place, le contenu glisse */
html.anim-on.vt-fwd::view-transition-old(root),
html.anim-on.vt-back::view-transition-old(root),
html.anim-on.vt-home::view-transition-old(root),
html.anim-on.vt-fwd::view-transition-new(root),
html.anim-on.vt-back::view-transition-new(root),
html.anim-on.vt-home::view-transition-new(root) { mix-blend-mode: normal; animation-timing-function: var(--a-ease); animation-fill-mode: both; }
html.anim-on.vt-fwd::view-transition-old(root)  { animation: a-vt-out-l var(--a-med) var(--a-ease) both; }
html.anim-on.vt-fwd::view-transition-new(root)  { animation: a-vt-in-r  var(--a-med) var(--a-ease) both; }
html.anim-on.vt-back::view-transition-old(root) { animation: a-vt-out-r var(--a-med) var(--a-ease) both; }
html.anim-on.vt-back::view-transition-new(root) { animation: a-vt-in-l  var(--a-med) var(--a-ease) both; }
html.anim-on.vt-home::view-transition-old(root) { animation: a-vt-fade-out var(--a-fast) ease both; }
html.anim-on.vt-home::view-transition-new(root) { animation: a-vt-fade-in var(--a-med) ease both; }
@keyframes a-vt-out-l { to   { opacity: 0; transform: translate3d(calc(var(--a-shift) * -1), 0, 0); } }
@keyframes a-vt-out-r { to   { opacity: 0; transform: translate3d(var(--a-shift), 0, 0); } }
@keyframes a-vt-in-r  { from { opacity: 0; transform: translate3d(var(--a-shift), 0, 0); } }
@keyframes a-vt-in-l  { from { opacity: 0; transform: translate3d(calc(var(--a-shift) * -1), 0, 0); } }
@keyframes a-vt-fade-out { to { opacity: 0; } }
@keyframes a-vt-fade-in  { from { opacity: 0; } }

/* b) Repli CSS (navigateurs sans View Transitions, ou retour par le geste du téléphone) */
html.anim-on .screen.anim-in-fwd  { animation: a-in-fwd  var(--a-med) var(--a-ease) backwards; }
html.anim-on .screen.anim-in-back { animation: a-in-back var(--a-med) var(--a-ease) backwards; }
html.anim-on .screen.anim-in-fade { animation: a-in-fade var(--a-med) var(--a-ease) backwards; }
@keyframes a-in-fwd  { from { opacity: 0; transform: translate3d(var(--a-shift), 0, 0); } }
@keyframes a-in-back { from { opacity: 0; transform: translate3d(calc(var(--a-shift) * -1), 0, 0); } }
@keyframes a-in-fade { from { opacity: 0; } }

/* ---------- 2. Ouverture d'une fiche : zoom doux ---------- */
html.anim-on .fiche-card { animation: a-zoom-in var(--a-med) var(--a-ease) backwards; }
@keyframes a-zoom-in { from { opacity: 0; transform: scale(.955); } }
/* Le détail « Approfondir » se déplie avec un léger fondu */
html.anim-on .fiche-details.is-open { animation: a-fade-up var(--a-med) var(--a-ease) backwards; }

/* ---------- 3. Quiz : révélation de la réponse en retournement 3D ---------- */
html.anim-on .quiz-card { perspective: 900px; }
html.anim-on .quiz-card > div:not([class]) {
  transform-origin: 50% 0;
  backface-visibility: hidden;
  animation: a-flip var(--a-slow) var(--a-ease) backwards;
}
@keyframes a-flip { from { opacity: 0; transform: rotateX(-82deg); } 60% { opacity: 1; } }
html.anim-on .quiz-card .result-banner { animation: a-pop var(--a-slow) var(--a-bounce) both; animation-delay: 80ms; }

/* ---------- 4. Apparition en cascade des listes ---------- */
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn) {
  animation: a-fade-up var(--a-med) var(--a-ease) backwards;
  animation-delay: calc(var(--i, 0) * 35ms);
}
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(2)  { --i: 1; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(3)  { --i: 2; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(4)  { --i: 3; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(5)  { --i: 4; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(6)  { --i: 5; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(7)  { --i: 6; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(8)  { --i: 7; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(9)  { --i: 8; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(10) { --i: 9; }
html.anim-on :is(.mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .lib-row, .opt-btn):nth-child(n+11) { --i: 10; }
@keyframes a-fade-up { from { opacity: 0; transform: translate3d(0, 10px, 0); } }

/* ---------- 5. Retour tactile des boutons (rétrécissement, petit rebond au relâchement) ---------- */
/* :where() = priorité nulle : les styles existants de l'appli gardent toujours le dessus. */
:where(html.anim-on) :where(button, .btn):where(:not(:disabled)) { transition: transform var(--a-fast) var(--a-bounce); }
:where(html.anim-on) :where(button, .btn):where(:not(:disabled)):active { transform: scale(.965); }
/* Boutons qui ont déjà leur propre transition : on y ajoute le mouvement */
html.anim-on :is(.opt-btn, .pair-item, .home-link):not(:disabled) {
  transition: transform var(--a-fast) var(--a-bounce), border-color .15s ease, background .15s ease, opacity .15s ease;
}
html.anim-on :is(.opt-btn, .pair-item, .home-link):not(:disabled):active { transform: scale(.97); }
/* Grandes cartes : retour doux, sans rebond (un rebond les faisait grossir un instant après le tap) */
html.anim-on :is(.search-pill, .daily-card, .home-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item):not(:disabled) {
  transition: transform 130ms ease-out, border-color .15s ease, background .15s ease, opacity .15s ease;
}
html.anim-on :is(.search-pill, .daily-card, .home-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item):not(:disabled):active { transform: scale(.985); }
/* Ordinateur : léger soulèvement au survol */
@media (hover: hover) and (pointer: fine) {
  html.anim-on :is(.daily-card, .home-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .search-pill):not(:disabled):hover { transform: translateY(-2px); }
  html.anim-on :is(.daily-card, .home-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item, .search-pill):not(:disabled):active { transform: scale(.985); }
  html.anim-on .opt-btn:not(:disabled):hover { transform: translateX(3px); }
  html.anim-on .opt-btn:not(:disabled):active { transform: scale(.98); }
}

/* ---------- 6. Quiz : la bonne réponse s'illumine, la mauvaise tremble ---------- */
html.anim-on :is(.opt-btn, .pair-item, .frise-item) { position: relative; }
html.anim-on .opt-btn.is-correct,
html.anim-on .pair-item.is-good { animation: a-pop var(--a-slow) var(--a-bounce) both; animation-delay: 0s; }
html.anim-on .opt-btn.is-correct::before,
html.anim-on .pair-item.is-good::before,
html.anim-on .frise-item.is-correct-pos::before {
  content: ''; position: absolute; inset: -3px; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 0 2px var(--success), 0 0 22px 3px var(--success);
  opacity: 0; animation: a-glow 650ms ease-out;
}
html.anim-on .opt-btn.is-wrong,
html.anim-on .pair-item.is-bad,
html.anim-on .frise-item.is-wrong-pos { animation: a-shake 360ms ease both; animation-delay: 0s; }
@keyframes a-pop  { 0% { transform: scale(.96); } 55% { transform: scale(1.03); } 100% { transform: scale(1); } }
@keyframes a-glow { 0% { opacity: 0; } 25% { opacity: .85; } 100% { opacity: 0; } }
@keyframes a-shake {
  0%, 100% { transform: translate3d(0, 0, 0); }
  18% { transform: translate3d(-6px, 0, 0); } 36% { transform: translate3d(5px, 0, 0); }
  54% { transform: translate3d(-4px, 0, 0); } 72% { transform: translate3d(3px, 0, 0); }
}

/* ---------- 7. Chargements : pulsation douce (squelettes) ---------- */
@keyframes a-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }
html.anim-on.anim-loading :is(.home-card, .daily-card, .home-hero__subtitle, .search-pill) { animation: a-pulse 1.3s ease-in-out infinite; animation-delay: 0s; }
html.anim-on .btn-approfondir:disabled { animation: a-pulse 1s ease-in-out infinite; }
html.anim-on .skel { animation: a-pulse 1.3s ease-in-out infinite; }

/* ---------- 9. Étoile des favoris : « pop » et étincelles ---------- */
html.anim-on .fav-btn.is-popping svg { animation: a-star-pop 440ms var(--a-bounce); }
@keyframes a-star-pop { 0% { transform: scale(.5) rotate(-25deg); } 60% { transform: scale(1.35) rotate(8deg); } 100% { transform: scale(1) rotate(0); } }
html.anim-on .fav-spark {
  position: absolute; left: 50%; top: 50%; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px;
  border-radius: 50%; background: #ffcf4a; pointer-events: none; opacity: 0;
  animation: a-spark 560ms ease-out forwards;
}
@keyframes a-spark { 0% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); } 100% { opacity: 0; transform: translate3d(var(--dx), var(--dy), 0) scale(.2); } }

/* ---------- 10. Confettis (fin de la bouchée du jour, fin d'une série de quiz) ---------- */
html.anim-on .a-confetti { position: fixed; inset: 0; z-index: 90; pointer-events: none; overflow: hidden; }
html.anim-on .a-confetti i {
  position: absolute; top: -14px; width: 8px; height: 12px; border-radius: 2px; opacity: 0;
  animation: a-confetti-fall var(--d, 1800ms) cubic-bezier(.2, .6, .4, 1) var(--dl, 0ms) forwards;
}
@keyframes a-confetti-fall {
  0% { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg); }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translate3d(var(--x), 85vh, 0) rotate(var(--r)); }
}

/* ---------- 11. Barres de progression qui se remplissent en douceur ---------- */
html.anim-on .daily-progress__seg.is-done,
html.anim-on .daily-progress__seg.is-miss { transform-origin: left center; animation: a-seg-fill 420ms var(--a-ease) backwards; animation-delay: calc(var(--j, 0) * 45ms); }
html.anim-on .daily-progress__seg.is-current { animation: a-pulse 1.6s ease-in-out infinite; }
@keyframes a-seg-fill { from { transform: scaleX(0); } }
html.anim-on .daily-progress__seg:nth-child(2) { --j: 1; }
html.anim-on .daily-progress__seg:nth-child(3) { --j: 2; }
html.anim-on .daily-progress__seg:nth-child(4) { --j: 3; }
html.anim-on .daily-progress__seg:nth-child(5) { --j: 4; }
html.anim-on .daily-progress__seg:nth-child(6) { --j: 5; }
html.anim-on .daily-progress__seg:nth-child(7) { --j: 6; }
html.anim-on .daily-progress__seg:nth-child(8) { --j: 7; }
html.anim-on .daily-progress__seg:nth-child(9) { --j: 8; }
html.anim-on .daily-progress__seg:nth-child(10) { --j: 9; }

/* ---------- 12. Flamme de la série : palpite doucement ---------- */
html.anim-on .daily-card__streak:not([hidden]) { animation: a-flame 2.4s ease-in-out infinite; }
@keyframes a-flame { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.07); } }

/* ---------- 13. Écran de démarrage : le logo apparaît en douceur ---------- */
html.anim-on #a-splash {
  position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center;
  background: var(--bg, #0a0e1a); animation: a-fade-in 180ms ease backwards;
}
html.anim-on #a-splash img { width: 96px; height: 96px; border-radius: 24px; animation: a-splash-logo 1.3s ease-in-out infinite; }
html.anim-on #a-splash.is-leaving { opacity: 0; pointer-events: none; transition: opacity 340ms ease; }
html.anim-on #a-splash.is-leaving img { animation: none; transform: scale(1.12); transition: transform 340ms var(--a-ease); }
@keyframes a-fade-in { from { opacity: 0; } }
@keyframes a-splash-logo { 0%, 100% { transform: scale(.94); opacity: .85; } 50% { transform: scale(1.04); opacity: 1; } }

/* ---------- 14. Ordinateur : lueur douce qui suit la souris sur les cartes ---------- */
@media (hover: hover) and (pointer: fine) {
  html.anim-on :is(.home-card, .daily-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item) { position: relative; overflow: hidden; }
  html.anim-on :is(.home-card, .daily-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item)::after {
    content: ''; position: absolute; left: 0; top: 0; width: 260px; height: 260px; margin: -130px 0 0 -130px;
    border-radius: 50%; background: radial-gradient(circle, rgba(255, 255, 255, .12), transparent 65%);
    transform: translate3d(var(--mx, -999px), var(--my, -999px), 0);
    opacity: 0; transition: opacity .25s ease; pointer-events: none;
  }
  html.anim-on :is(.home-card, .daily-card, .mode-card, .domain-tile, .subtheme-row, .fiche-list-item):hover::after { opacity: 1; }
}

/* ---------- 15. Notification (toast) : elle glisse en entrant et en sortant ---------- */
html.anim-on .toast:not([hidden]) { animation: a-toast 2200ms ease both; }
@keyframes a-toast {
  0%   { opacity: 0; transform: translate3d(-50%, 14px, 0); }
  9%   { opacity: 1; transform: translate3d(-50%, 0, 0); }
  88%  { opacity: 1; transform: translate3d(-50%, 0, 0); }
  100% { opacity: 0; transform: translate3d(-50%, -6px, 0); }
}

/* ---------- 16. Écran final des séries : anneau, médaille, flammes du sans-faute ---------- */
html.anim-on .serie-end__scorecard { animation: a-zoom-in 520ms var(--a-bounce) 200ms backwards; }
html.anim-on .serie-end__medal { animation: a-pop 520ms var(--a-bounce) 700ms backwards; }
html.anim-on .serie-end__bar i { animation: a-bar-grow 800ms var(--a-ease) 700ms backwards; }
@keyframes a-bar-grow { from { transform: scaleX(0); } }
html.anim-on .serie-end__msg { animation: a-fade-up var(--a-med) var(--a-ease) 900ms backwards; }
html.anim-on .serie-bar__fill { transition: transform .45s var(--a-ease); }

/* ---------- Réglage « réduire les animations » du téléphone : tout s'arrête ---------- */
@media (prefers-reduced-motion: reduce) {
  html.anim-on *, html.anim-on *::before, html.anim-on *::after { animation: none !important; transition: none !important; }
  html.anim-on::view-transition-group(*), html.anim-on::view-transition-old(*), html.anim-on::view-transition-new(*) { animation: none !important; }
}

/* ---------- 16. Accueil : « Bouchée du jour » et « Quiz du jour » mises en avant tant qu'elles ne sont pas faites ---------- */
html.anim-on .daily-card:not(.is-done) { --pulse: 255, 176, 46; animation: a-daily-ring 2.6s ease-out infinite; }
html.anim-on .daily-card--quiz:not(.is-done) { --pulse: 255, 122, 156; animation-delay: 1.3s; }
@keyframes a-daily-ring {
  0%   { outline: 3px solid rgba(var(--pulse), .65); outline-offset: 0; }
  70%, 100% { outline: 3px solid rgba(var(--pulse), 0); outline-offset: 11px; }
}
html.anim-on .daily-card:not(.is-done) .daily-card__icon { animation: a-daily-bob 2.2s ease-in-out infinite; }
@keyframes a-daily-bob { 0%, 100% { transform: translateY(0) rotate(0); } 40% { transform: translateY(-4px) rotate(-6deg); } 70% { transform: translateY(0) rotate(4deg); } }
/* Petite étiquette « À faire » dans le coin de la carte */
.daily-card:not(.is-done)::before {
  content: 'À FAIRE'; position: absolute; top: 8px; right: 12px; z-index: 1;
  font-size: 10px; font-weight: 900; letter-spacing: .8px; line-height: 1;
  padding: 4px 7px; border-radius: 6px; background: #ffd24d; color: #171c2b; border: 2px solid #171c2b; transform: rotate(3deg);
}
html.anim-on .daily-card:not(.is-done)::before { animation: a-daily-tag 2.6s ease-in-out infinite; }
@keyframes a-daily-tag { 0%, 100% { transform: rotate(3deg) scale(1); } 50% { transform: rotate(3deg) scale(1.1); } }
