/* ============================================================
   Nadjmi — le mouvement.
   Chargé APRÈS nadjmi.css : ce fichier n'ajoute que du geste,
   jamais de couleur ni de mise en page. Le retirer du header
   ramène le site à son état antérieur, sans rien casser.

   Trois principes, tenus partout :
   · court — 120 à 380 ms. Au-delà, un enfant de cinq ans a
     déjà appuyé une deuxième fois ;
   · une seule animation appuyée, l'arrivée d'un badge. Le reste
     reste discret, sinon l'effet s'use ;
   · rien ne retarde une action : le mouvement accompagne le
     clic, il ne le fait jamais attendre.

   Le texte des manuels ne bouge pas. Seule l'interface réagit.
   ============================================================ */

:root {
  /* Courbes Material 3 */
  --m-emphase:  cubic-bezier(.2, 0, 0, 1);
  --m-decelere: cubic-bezier(.05, .7, .1, 1);   /* ce qui entre */
  --m-accelere: cubic-bezier(.3, 0, .8, .15);   /* ce qui sort  */
  /* Hors spécification : réservé aux récompenses. Material vise
     l'outil professionnel ; ici le public a 4 à 18 ans. */
  --m-rebond:   cubic-bezier(.2, 1.3, .4, 1);

  --t-court: 120ms;
  --t-moyen: 220ms;
  --t-long:  380ms;

  --encre-ripple: rgba(28, 35, 64, .18);
}
html[data-mode="sombre"] { --encre-ripple: rgba(255, 255, 255, .22); }

/* ------------------------------------------------------------
   1. L'onde au point de contact
   Sur mobile il n'y a pas de survol : sans ce retour, rien ne
   confirme qu'un appui a été pris en compte, et l'enfant appuie
   une seconde fois.
   ------------------------------------------------------------ */
/* .ord-carte est volontairement absente : sa pastille de rang déborde en
   haut à gauche, et « overflow: hidden » la couperait. Ces cartes ont déjà
   leur propre retour visuel quand on les pose. */
.btn, .quiz-opt, .jeu-tuile, .admin-tuile, .hero-carte,
.tri-panier, .pr-carte, .dl-mot, .dl-opt,
.badge-carte, .filtre-cat, .dm-onglet, .conte-genre {
  position: relative;
  overflow: hidden;
}
.onde {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
  background: var(--encre-ripple); transform: scale(0); opacity: .9;
  animation: onde-pousse 520ms var(--m-decelere) forwards;
}
/* Le contenu du bouton reste au-dessus de l'onde */
.btn > *, .quiz-opt > *, .jeu-tuile > *, .tri-panier > * { position: relative; z-index: 1; }
@keyframes onde-pousse { to { transform: scale(2.6); opacity: 0; } }

/* ------------------------------------------------------------
   2. Boutons — relief à l'approche, enfoncement à l'appui
   ------------------------------------------------------------ */
.btn {
  transition: transform var(--t-court) var(--m-emphase),
              box-shadow var(--t-moyen) var(--m-emphase),
              filter var(--t-court) var(--m-emphase);
}
.btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--ombre); filter: brightness(1.04); }
.btn:active:not(:disabled) { transform: translateY(0) scale(.97); transition-duration: 80ms; }
.btn:disabled { transform: none; }

/* ------------------------------------------------------------
   3. Cartes et tuiles — élévation, et l'icône qui prend vie
   ------------------------------------------------------------ */
.jeu-tuile, .admin-tuile, .hero-carte, .badge-carte, .bloc-activite {
  transition: transform var(--t-moyen) var(--m-emphase),
              box-shadow var(--t-moyen) var(--m-emphase),
              border-color var(--t-moyen) var(--m-emphase),
              opacity var(--t-long) var(--m-decelere);
}
a.jeu-tuile:hover, a.admin-tuile:hover, a.hero-carte:hover, a.bloc-activite:hover {
  transform: translateY(-5px);
}
.jeu-ico, .tuile-ico, .act-ico, .hero-ico, .badge-ico {
  display: inline-block;
  transition: transform var(--t-long) var(--m-rebond);
}
a.jeu-tuile:hover .jeu-ico,
a.admin-tuile:hover .tuile-ico,
a.bloc-activite:hover .act-ico,
a.hero-carte:hover .hero-ico { transform: scale(1.14) rotate(-5deg); }

/* ------------------------------------------------------------
   4. Entrée en cascade
   Les tuiles se posent l'une après l'autre : l'œil suit l'ordre
   de lecture au lieu de recevoir toute la grille d'un coup.
   ------------------------------------------------------------ */
.jeux-grille > *, .admin-grille > *, .badges-grille > *, .hero-cartes > *,
.biblio-grille > *, .lecons-grille > *, .famille-grille > * {
  animation: nadjmi-monte var(--t-long) var(--m-decelere) both;
}
.jeux-grille > :nth-child(1), .admin-grille > :nth-child(1),
.badges-grille > :nth-child(1), .hero-cartes > :nth-child(1),
.biblio-grille > :nth-child(1), .lecons-grille > :nth-child(1) { animation-delay: 0ms; }
.jeux-grille > :nth-child(2), .admin-grille > :nth-child(2),
.badges-grille > :nth-child(2), .hero-cartes > :nth-child(2),
.biblio-grille > :nth-child(2), .lecons-grille > :nth-child(2) { animation-delay: 55ms; }
.jeux-grille > :nth-child(3), .admin-grille > :nth-child(3),
.badges-grille > :nth-child(3), .hero-cartes > :nth-child(3),
.biblio-grille > :nth-child(3), .lecons-grille > :nth-child(3) { animation-delay: 110ms; }
.jeux-grille > :nth-child(4), .admin-grille > :nth-child(4),
.badges-grille > :nth-child(4), .biblio-grille > :nth-child(4),
.lecons-grille > :nth-child(4) { animation-delay: 165ms; }
.jeux-grille > :nth-child(5), .admin-grille > :nth-child(5),
.badges-grille > :nth-child(5), .biblio-grille > :nth-child(5),
.lecons-grille > :nth-child(5) { animation-delay: 220ms; }
.jeux-grille > :nth-child(n+6), .admin-grille > :nth-child(n+6),
.badges-grille > :nth-child(n+6), .biblio-grille > :nth-child(n+6),
.lecons-grille > :nth-child(n+6) { animation-delay: 275ms; }
@keyframes nadjmi-monte { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

/* Là où le site gère déjà l'apparition au scroll (.anim-en-vue), on ne
   superpose pas une seconde mécanique : la nôtre jouerait à vide sous la
   ligne de flottaison et écraserait ses transitions. La cascade ne sert donc
   que les grilles rendues d'un bloc — badges, cartes d'accueil. */
.jeux-grille > .anim-en-vue, .admin-grille > .anim-en-vue,
.badges-grille > .anim-en-vue, .hero-cartes > .anim-en-vue,
.biblio-grille > .anim-en-vue, .lecons-grille > .anim-en-vue,
.famille-grille > .anim-en-vue { animation: none; }

/* ------------------------------------------------------------
   5. Quiz et activités — signaler, jamais punir
   La secousse d'erreur est volontairement faible : 5 pixels.
   ------------------------------------------------------------ */
.quiz-opt, .tri-panier, .pr-carte, .ord-carte {
  transition: transform var(--t-court) var(--m-emphase),
              border-color var(--t-moyen) var(--m-emphase),
              background var(--t-moyen) var(--m-emphase);
}
.quiz-opt:hover:not(:disabled) { transform: translateX(4px); }
.quiz-juste, .tri-juste { animation: nadjmi-pulse 460ms var(--m-rebond); }
.quiz-faux,  .tri-faux  { animation: nadjmi-secousse 340ms var(--m-emphase); }
@keyframes nadjmi-pulse { 0% { transform: scale(1); } 45% { transform: scale(1.035); } 100% { transform: scale(1); } }
@keyframes nadjmi-secousse { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }

/* Le retour et l'explication arrivent ensemble, du bas */
.msg-debrief, .explication, .quiz-fin, .jeu-fin {
  animation: nadjmi-bulle var(--t-long) var(--m-rebond) both;
}
@keyframes nadjmi-bulle { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: none; } }

/* Remise en ordre : la carte posée se cale à sa place */
.ord-carte:hover { transform: translateY(-3px); }
.ord-piste .ord-carte { animation: nadjmi-pose var(--t-moyen) var(--m-rebond) both; }
@keyframes nadjmi-pose { from { transform: scale(.88); opacity: .4; } to { transform: none; opacity: 1; } }

/* Associations : la paire trouvée s'efface doucement */
.pr-trouve { transition: opacity var(--t-long) var(--m-emphase), border-color var(--t-moyen) var(--m-emphase); }

/* ------------------------------------------------------------
   6. Le badge gagné — le seul moment appuyé du site
   Deux temps : la carte monte, puis l'icône se redresse.
   ------------------------------------------------------------ */
.badge-gagne { animation: nadjmi-badge 620ms var(--m-rebond) both; }
.badge-gagne .badge-gagne-ico { animation: nadjmi-badge-ico 700ms var(--m-emphase) 120ms both; }
@keyframes nadjmi-badge { from { opacity: 0; transform: translate(-50%, 90%) scale(.85); } to { opacity: 1; transform: translate(-50%, 0) scale(1); } }
@keyframes nadjmi-badge-ico { from { transform: rotate(-25deg) scale(.5); } to { transform: none; } }
.badge-gagne.sortie { animation: nadjmi-badge-sort var(--t-long) var(--m-accelere) forwards; }
@keyframes nadjmi-badge-sort { to { opacity: 0; transform: translate(-50%, 60%) scale(.9); } }

/* La collection : un badge gagné respire au survol */
.badge-carte:not(.badge-verrouille):hover { transform: translateY(-4px); }
.badge-carte:not(.badge-verrouille):hover .badge-ico { transform: scale(1.16) rotate(-6deg); }

/* ------------------------------------------------------------
   7. Mémorisateur — le mot lu se soulève
   Sur onze mots en écriture arabe, le relief aide l'œil bien
   plus qu'un simple changement de couleur.
   ------------------------------------------------------------ */
.dl-mot {
  transition: transform var(--t-moyen) var(--m-rebond),
              background var(--t-court) var(--m-emphase),
              box-shadow var(--t-moyen) var(--m-emphase),
              opacity var(--t-moyen) var(--m-emphase);
}
.dl-mot.dl-actif { transform: translateY(-5px) scale(1.07); box-shadow: 0 8px 22px rgba(232, 163, 63, .35); }
.dl-frise-seg { transition: background var(--t-court) var(--m-emphase), transform var(--t-court) var(--m-emphase); }
.dl-mot.dl-cache { transition: opacity var(--t-long) var(--m-emphase), filter var(--t-long) var(--m-emphase); }

/* ------------------------------------------------------------
   8. Modal — il monte du bas, il repart par le bas
   L'aller-retour emprunte le même chemin : l'enfant sait d'où
   il vient et où il retourne.
   ------------------------------------------------------------ */
.dm-voile { animation: nadjmi-fondu var(--t-moyen) var(--m-emphase) both; }
.dm-boite { animation: nadjmi-boite var(--t-long) var(--m-emphase) both; }
@keyframes nadjmi-fondu { from { opacity: 0; } to { opacity: 1; } }
@keyframes nadjmi-boite { from { opacity: 0; transform: translateY(28px) scale(.94); } to { opacity: 1; transform: none; } }
.zoom-vue { animation: nadjmi-fondu var(--t-moyen) var(--m-emphase) both; }
.abc-fiche:not([hidden]) { animation: nadjmi-boite var(--t-long) var(--m-emphase) both; }

/* ------------------------------------------------------------
   9. Détails
   ------------------------------------------------------------ */
/* Une barre de progression se remplit, elle ne saute pas */
.jauge > i, .progres-barre > i, .barre-progres > span { transition: width 700ms var(--m-emphase); }

/* Le haut-parleur bat quand il parle */
.btn-vocal { transition: transform var(--t-court) var(--m-emphase); }
.btn-vocal:hover { transform: scale(1.12); }
.btn-vocal.joue { animation: nadjmi-parle 1s var(--m-emphase) infinite; }
@keyframes nadjmi-parle { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.14); } }

/* Le conte : chaque scène remplace la précédente en douceur */
.conte-scene-img, .conte-texte { animation: nadjmi-scene var(--t-long) var(--m-decelere) both; }
@keyframes nadjmi-scene { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }

/* Onglets et filtres */
.dm-onglet, .filtre-cat { transition: background var(--t-moyen) var(--m-emphase), border-color var(--t-moyen) var(--m-emphase), color var(--t-moyen) var(--m-emphase); }

/* ------------------------------------------------------------
   Un enfant sensible au mouvement, ou un appareil réglé ainsi,
   ne voit rien de tout cela. Cette règle doit rester la dernière.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .onde { display: none; }
}
