/* ─────────────────────────────────────────────────────────────
   Le mouvement : les règles du porteur (1er novembre 2026 ; maquette
   Anim-Regles, docs/06-design-retenu.md). Ce fichier est la seule source
   des durées et des courbes : app/mouvement.js les lit ici.

   Plus c'est rare, plus ça brille. Quatre niveaux, et un moment ne monte
   jamais d'un niveau pour « faire plus » : petit geste, réussite,
   récompense, événement (un palier, une fois).

   La page porte toujours l'état final ; une animation ne fait que le
   rejoindre. « Réduire les animations » et un tap donnent donc le même
   résultat. On n'anime que transform, opacity, clip-path et
   stroke-dashoffset, sauf un chiffre qui se compte (--mv-n).
   ───────────────────────────────────────────────────────────── */
@property --mv-n{syntax:"<integer>";inherits:false;initial-value:0}
:root{
  /* les quatre niveaux */
  --mv-geste:200ms; --mv-reussite:600ms; --mv-recompense:1500ms; --mv-evenement:3000ms;
  /* l'arrivée sur l'accueil : un peu moins qu'une récompense, on est venu travailler */
  --mv-accueil:1200ms;
  /* l'aura (rayons du palier et du trophée) : un tour complet, en boucle ; lente, elle ne distrait pas */
  --mv-aura:16000ms;
  /* les petits gestes (maquette Anim-Micro) */
  --mv-bouton:100ms; --mv-carte:150ms; --mv-onglet:250ms; --mv-barre:300ms; --mv-feuille:300ms;
  --mv-secousse:360ms; --mv-compteur:400ms; --mv-vol:450ms; --mv-eclat:500ms; --mv-charge:1600ms;
  /* entrée, sortie */
  --mv-entree:cubic-bezier(.2,.8,.2,1); --mv-sortie:cubic-bezier(.4,0,1,1);
  /* les ombres du mouvement : la carte levée au survol, le panneau du bas, la phrase qui passe */
  --mv-ombre-carte:0 10px 24px rgba(21,23,43,.12);
  --mv-ombre-feuille:0 -12px 40px rgba(21,23,43,.16);
  --mv-ombre-badge:0 8px 20px rgba(21,23,43,.2);
  /* le halo d'un bouton jaune */
  --mv-halo:rgba(255,225,77,.55);
  /* les éclats : le blanc reste blanc, aux deux thèmes */
  --mv-blanc:#FFFFFF;
  /* les six formes des paliers (service/eclairs.py) : les mêmes couleurs aux deux thèmes */
  --mv-f-jaune:#FFE14D; --mv-f-bleu:#2B44B0; --mv-f-encre:#15172B;
  /* les rayons du palier */
  --mv-rayon:rgba(255,225,77,.2); --mv-halo-disque:rgba(255,225,77,.3);
  /* le « ! » sur l'orange, la coche sur le vert ; une case vide sur le bleu */
  --mv-sur-casse:#FFFFFF; --mv-sur-tient:#FFFFFF; --mv-case-vide:rgba(255,255,255,.28);
}
:root[data-theme="sombre"]{--mv-sur-casse:#14151D;--mv-sur-tient:#14151D}

/* ── l'onglet : d'une page à l'autre, la page change d'un coup et seule la pastille de l'onglet actif glisse jusqu'au
   nouveau (View Transitions entre deux pages du site : Chrome, Edge, Safari récents ; ailleurs, elle change de place sans
   animation). L'accord @view-transition n'est pas ici : il doit être dans la page (pages.ONGLET_TOT). ── */
@media (prefers-reduced-motion:no-preference){
  ::view-transition-old(root),::view-transition-new(root){animation:none}
  ::view-transition-group(onglet-actif),::view-transition-old(onglet-actif),::view-transition-new(onglet-actif){
    animation-duration:var(--mv-onglet);animation-timing-function:var(--mv-entree)}
  .onglets-e a[aria-current="page"] .pic,.menu-m a[aria-current="page"]{view-transition-name:onglet-actif}
  /* F029 : le bandeau bleu de l'espace de l'élève porte un nom, pour que le navigateur le garde affiché pendant le changement
     de page au lieu de le faire passer par un blanc. Il ne glisse, ne s'étire et ne se fond pas (sa hauteur change d'une page
     à l'autre) : l'ancien disparaît d'un coup, le nouveau est en place d'un coup. */
  .espace .bandeau{view-transition-name:bandeau}
  ::view-transition-group(bandeau),::view-transition-new(bandeau){animation:none}
  ::view-transition-old(bandeau){display:none}
}

/* ── le bouton : translateY(4px), le rebord s'écrase sous le doigt ── */
:is(.bouton,.gros-bouton,.suivant,.envoi,.puce,.rendre-a,.envoyer,.confirme-a button,.continuer-pal){
  transition:transform var(--mv-bouton) var(--mv-entree),box-shadow var(--mv-bouton) var(--mv-entree)}
:is(.rendre-a,.envoyer:not([disabled]),.confirme-a button:not(.creux),.continuer-pal):active{transform:translateY(var(--rebord));box-shadow:none}

/* ── la carte au survol : se lève de 3 px, sur un ordinateur seulement, rien sur un téléphone ── */
:is(.carte-cliquable,.ch,.mini,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button,.porte){
  transition:transform var(--mv-carte) var(--mv-entree),box-shadow var(--mv-carte) var(--mv-entree),border-color var(--mv-carte) var(--mv-entree)}
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  :is(.carte-cliquable,.ch,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button,.porte):not(.relais-ouvert):hover{
    transform:translateY(-3px);box-shadow:var(--mv-ombre-carte)}
}
/* une série en cours n'est une carte que sur un ordinateur : plus bas, c'est une ligne dans une liste */
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference) and (min-width:1024px){
  .mini:hover{transform:translateY(-3px);box-shadow:var(--mv-ombre-carte)}
}

/* ── l'appui (F014) : ce qui répond au doigt avant que la page suivante arrive.
   Une carte qu'on touche se resserre (scale .98) en --mv-bouton et revient en --mv-carte au relâcher ; elle reste levée par
   le survol seulement à la souris. Une ligne de liste et un onglet du bas ne changent pas d'échelle : un voile bleu pâle
   apparaît, en opacité seulement (un pseudo-élément posé sur la surface). Le voile gris du navigateur s'en va, sur ces
   surfaces seulement. Le bouton jaune garde son enfoncement de 4 px. Avec « réduire les animations » : le voile seul. ── */
:is(.carte-cliquable,.ch,a.mini,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button,.onglets-e a,.compte .item,.defi-l summary){
  -webkit-tap-highlight-color:transparent}
@media (prefers-reduced-motion:no-preference){
  :is(.carte-cliquable,.ch,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button):not(.relais-ouvert):active{
    transform:scale(.98);transition-duration:var(--mv-bouton)}
}
@media (prefers-reduced-motion:no-preference) and (min-width:1024px){
  a.mini:active{transform:scale(.98);transition-duration:var(--mv-bouton)}
}
/* « réduire les animations » : le voile seul, tout de suite, sans changement d'échelle (le filet garde sa transition d'aujourd'hui) */
@media (prefers-reduced-motion:reduce){
  :is(.carte-cliquable,.ch,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button){
    transition:border-color var(--mv-carte) var(--mv-entree)}
  :is(.carte-cliquable,.ch,.act,.crs,a.crs-c,a.chiffre,.opt,.chapitre,a.serie,.a-faire-c,.grille-relecture a,.passees button,.choix-auto button):not(.relais-ouvert):active{
    box-shadow:inset 0 0 0 999px var(--bleu-f)}
}
@media (min-width:1024px) and (prefers-reduced-motion:reduce){a.mini{transition:border-color var(--mv-carte) var(--mv-entree)}a.mini:active{box-shadow:inset 0 0 0 999px var(--bleu-f)}}
/* le voile : un pseudo-élément sous le contenu, dont seule l'opacité s'anime */
:is(.onglets-e a,.compte .item,.defi-l summary){position:relative;isolation:isolate}
:is(.onglets-e a,.compte .item,.defi-l summary)::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:12px;background:var(--bleu-f);opacity:0;
  pointer-events:none;transition:opacity var(--mv-carte) var(--mv-entree)}
.onglets-e a::before{inset:0 8px}
.defi-l summary::before{border-radius:0}
:is(.onglets-e a,.compte .item,.defi-l summary):active::before{opacity:1;transition-duration:var(--mv-bouton)}
@media (max-width:1023px){
  a.mini{position:relative;isolation:isolate}
  a.mini::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:12px;background:var(--bleu-f);opacity:0;pointer-events:none;
    transition:opacity var(--mv-carte) var(--mv-entree)}
  a.mini:active::before{opacity:1;transition-duration:var(--mv-bouton)}
}
@media (prefers-reduced-motion:reduce){:is(.onglets-e a,.compte .item,.defi-l summary,a.mini)::before{transition:none}}

/* ── le menu du compte (F021) : il grandit depuis le rond (origine : le centre du rond, qui sur un ordinateur est aussi le bout
   arrondi de la pastille du prénom), et il se ferme sans animation : une fermeture ne retarde jamais le geste suivant.
   Le <details> ouvert porte déjà le menu entier : sans script ni animation, c'est l'état d'aujourd'hui. ── */
@keyframes mv-menu-nait{from{opacity:0;transform:scale(.96)}}
@media (prefers-reduced-motion:no-preference){
  .compte[open] .menu{transform-origin:calc(100% - 22px) -8px;animation:mv-menu-nait var(--mv-carte) var(--mv-entree)}
}

/* ── le chargement : l'éclair se dessine, puis se remplit de jaune. Le seul mouvement en boucle ──
   Sans animation, il est là, entier et plein : c'est son état de repos. */
.charge-eclair{display:block;flex:none;width:26px;height:40px;overflow:visible}
.charge-eclair path{fill:var(--jaune);stroke:var(--bleu);stroke-width:1.3;stroke-linejoin:round;stroke-dasharray:90;
  animation:mv-dessine var(--mv-charge) infinite,mv-remplit var(--mv-charge) infinite}
@keyframes mv-dessine{0%{stroke-dashoffset:90}55%,100%{stroke-dashoffset:0}}
@keyframes mv-remplit{0%,50%{fill-opacity:0}65%,85%{fill-opacity:1}100%{fill-opacity:0}}
.en-charge{display:flex;align-items:center;gap:12px}

/* ── ce que les briques de app/mouvement.js posent le temps d'une animation ── */
/* le flash : un fond qui ne fait que s'effacer */
.mv-flash{position:relative;isolation:isolate}
.mv-flash::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--tient-f);opacity:0;pointer-events:none}
/* le reflet qui passe sur une barre qui avance */
.segs i,.mv-reflet{position:relative;overflow:hidden}
.mv-reflet::after{content:"";position:absolute;top:0;bottom:0;left:0;width:40%;opacity:0;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.75),transparent)}
/* le chiffre qui se compte : le vrai chiffre garde sa place, le compte s'écrit par-dessus */
.mv-compte{position:relative;display:inline-block;counter-reset:mv var(--mv-n);-webkit-text-fill-color:transparent;
  font-variant-numeric:tabular-nums}
.mv-compte::after{content:counter(mv);position:absolute;inset:0;text-align:inherit;-webkit-text-fill-color:currentColor}
/* le chiffre qui roule vers le haut : l'ancien, puis le nouveau */
.mv-roule{display:inline-block;height:1.15em;line-height:1.15em;overflow:hidden;vertical-align:bottom}
.mv-roule > span{display:flex;flex-direction:column}
.mv-roule > span > span{display:block;height:1.15em}
/* les six formes : le compteur et les paliers */
.forme-p{display:block;flex:none;overflow:visible}
.fp-j{fill:var(--mv-f-jaune)}.fp-b{fill:var(--mv-f-bleu)}.fp-n{fill:var(--mv-f-encre)}.fp-bl{fill:var(--mv-blanc)}
.fp-t{stroke:var(--mv-f-encre);stroke-linejoin:round}
.fp-r{fill:none;stroke:var(--mv-f-encre);stroke-linecap:round}
/* un nombre du Suivi, le temps de se compter : le même dessin que le texte qu'il remplace */
.nb-mv{font-style:normal}
/* ce qui se remplit depuis la gauche, ce qui monte depuis le bas (l'accueil, le Suivi) */
.segs i.f{transform-origin:0 50%}
.barre-s.en-cours{transform-origin:50% 100%}
/* le halo d'un bouton qui devient utile */
.mv-pulse{position:relative}
.mv-pulse::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--mv-halo);z-index:-1;opacity:0;pointer-events:none}
/* la phrase qui passe, au-dessus d'une ligne : aux deux thèmes, le bloc plein */
.mv-badge{position:fixed;z-index:60;display:flex;align-items:center;gap:8px;padding:9px 16px 9px 12px;border-radius:999px;
  background:var(--bloc);color:var(--bloc-texte);font-size:15px;font-weight:800;white-space:nowrap;box-shadow:var(--mv-ombre-badge);
  transform:translateX(-50%);pointer-events:none}
.mv-badge svg{flex:none;width:14px;height:21px;fill:var(--jaune)}
/* ce qui vole et ce qui jaillit : au-dessus de tout, et ça laisse passer le doigt */
.mv-vol,.mv-eclat{position:fixed;left:0;top:0;margin:0;z-index:60;pointer-events:none}
.mv-eclat{width:12px;height:18px;overflow:visible;fill:var(--jaune);opacity:0}
.mv-eclat.blanc{fill:var(--mv-blanc)}
.mv-eclat.bleu{fill:var(--bleu)}

/* ── le nouveau palier : plein écran, bleu à points (maquette Anim-Palier). Le dessin, les mots, puis ce qu'on touche ── */
html.sans-defile{overflow:hidden}
.palier-e{position:fixed;inset:0;z-index:55;display:flex;flex-direction:column;align-items:center;overflow:hidden auto;
  padding:16px 20px calc(22px + env(safe-area-inset-bottom));background:var(--trame),var(--aplat);color:var(--sur-aplat);text-align:center}
.fermer-pal{position:absolute;top:16px;right:20px;z-index:2;display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;
  border-radius:999px;background:var(--blanc-voile);color:var(--sur-aplat);cursor:pointer}
.fermer-pal svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2.6;stroke-linecap:round}
.scene-pal{position:relative;isolation:isolate;flex:none;display:flex;align-items:center;justify-content:center;width:100%;height:min(38vh,320px);margin-top:44px;perspective:700px}
.rayons-pal{position:absolute;left:50%;top:50%;z-index:-1;width:560px;height:560px;margin:-280px 0 0 -280px;border-radius:999px;pointer-events:none;
  background:repeating-conic-gradient(var(--mv-rayon) 0deg 9deg,transparent 9deg 30deg);
  -webkit-mask:radial-gradient(circle,black 18%,transparent 62%);mask:radial-gradient(circle,black 18%,transparent 62%)}
.disque-pal{position:relative;display:flex;align-items:center;justify-content:center;width:min(28vh,200px);height:min(28vh,200px);border-radius:999px;background:var(--mv-blanc);
  box-shadow:0 0 0 10px var(--mv-halo-disque)}
.disque-pal::after{content:"";position:absolute;inset:-10px;z-index:-1;border-radius:999px;background:var(--mv-halo-disque);opacity:0;pointer-events:none}
.ancien-pal,.nouveau-pal{position:absolute;display:block;width:80%}
.ancien-pal{opacity:0}
.puce-pal{flex:none;margin-top:18px;padding:7px 13px;border-radius:999px;background:var(--jaune);color:var(--sur-jaune);font-size:14px;font-weight:800}
.nom-palier{flex:none;margin:14px 0 0;font-family:var(--police-titre);font-stretch:112%;font-size:clamp(36px,12vw,48px);font-weight:800;line-height:1;letter-spacing:-.03em}
.phrase-pal{flex:none;max-width:36ch;margin:12px 12px 0;font-size:17px;line-height:1.45;color:var(--texte-sur-bleu)}
.phrase-pal .nombre-pal{font-weight:800;color:var(--sur-aplat)}
.actions-pal{flex:none;display:flex;flex-direction:column;gap:6px;width:100%;max-width:420px;margin-top:auto;padding-top:20px}
.continuer-pal{min-height:54px;margin-bottom:4px;border:0;border-radius:var(--r-bouton);background:var(--jaune);color:var(--sur-jaune);box-shadow:0 var(--rebord) 0 var(--jaune-rebord);
  font:inherit;font-size:17px;font-weight:800;cursor:pointer}
/* « Voir tous les paliers », et ce qu'il devient : le rail des six paliers */
.voir-pal{align-self:center;min-height:48px;padding:0 12px;border:0;background:none;color:inherit;font:inherit;font-size:15px;font-weight:700;cursor:pointer}
.rail-pal{margin-top:8px;outline:none}
/* trois par rangée : « Étincelle » à 14 px demande 68 px, et six colonnes n'en laissent que 43 à 55 */
.rail-pal ol{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px 4px;margin:0;padding:0;list-style:none}
.rail-pal li{display:flex;flex-direction:column;align-items:center;min-width:0}
.case-pal{display:flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:999px;background:var(--mv-blanc);color:var(--mv-f-encre);font-size:18px;font-weight:800}
.case-pal .forme-p{width:36px;height:36px}
.rail-pal .ici .case-pal{box-shadow:0 0 0 3px var(--jaune)}
.rail-pal .prochain .case-pal{opacity:.72}
.rail-pal .inconnu .case-pal{background:none;box-shadow:inset 0 0 0 2px currentColor;color:inherit;opacity:.55}
.nom-case{margin-top:5px;font-size:14px;font-weight:700;line-height:1.15;overflow-wrap:anywhere}
.rail-pal p{margin:10px 0 0;font-size:14px;line-height:1.4}
@media (pointer:coarse){.continuer-pal:focus-visible{outline:none}}
/* sur le plus petit téléphone, les cases se resserrent ; les noms, eux, gardent leurs 14 px */
@media (max-width:350px){.case-pal{width:38px;height:38px}.case-pal .forme-p{width:30px;height:30px}}
