/* QCM — feuille de style de la mascotte.
   Chargée APRÈS app.css : ses règles de placement et de cohabitation
   viennent donc en dernier, comme dans l'ancien index.html. */

/* ══════════════════════════════════════════════════════════════════════
   MASCOTTE — dessin et gestes (repris de l'ancien bac à sable, supprimé)
   Adapté au monde de l'app : ses variables locales (#7ACEFF, #4A7E9C,
   #FFFCF0, #261412…) sont exactement les jetons de `interface.html`, donc
   aucune palette n'est réintroduite — tout est branché sur les jetons.
   Ce qui bouge, en trois étages. Le balancement lent (balance, 7,4 s, autour
   des pieds) porte le saut (sujet), qui porte le tassement (corps) : trois
   rythmes, trois éléments, une seule propriété chacun — c'est la seule façon
   de les superposer sans qu'ils s'écrasent. Les gestes du corps (saut, petit
   saut, penche) agissent sur `sujet` et jamais sur le bouton, pour que
   l'ombre — restée dehors — encaisse le poids : elle se rétracte et pâlit au
   décollage, s'étale et se reteinte à l'atterrissage.
   Les yeux ne clignent plus en boucle : le script les ferme à intervalles
   irréguliers (2,2 à 6,5 s, un double une fois sur trois) et leur fait un
   sourire de temps en temps avec les arcs de l'original, qui étaient le point
   bas du balancement. Le clic la fait sauter, le score jette les étincelles,
   une erreur la fait pencher, le verdict reçoit un signe muet — et rien,
   jamais, ne s'écrit : elle n'a pas de bulle (voir la note du script).
   `prefers-reduced-motion` coupe tout, minuteries comprises : le repos est
   un état où l'on reste, pas un démarrage qu'on saute.
   ── pour redimensionner : --mascotte-taille sur .mascotte-zone ──
   ══════════════════════════════════════════════════════════════════════ */
.mascotte-zone{
  --mascotte-taille:190px;
  /* LE PERCHOIR. Deux écarts, jamais une mise en page : le script pose
     --perchoir-x et --perchoir-y, la translation les applique — left et bottom
     restent ceux des feuilles de style. Vers la gauche elle ne se décale que
     là où il y a de la place, pour ne jamais passer devant la feuille ; vers
     la droite, l'écart n'existe que le temps d'une traversée, où elle marche
     par-dessus la copie pour se poser de l'autre bord (js/mascotte.js). */
  --perchoir-x:0px;--perchoir-y:0px;
  position:relative;
  width:var(--mascotte-taille);
  height:calc(var(--mascotte-taille) * 196 / 192);
  transform:translate(calc(-1 * var(--perchoir-x)),calc(-1 * var(--perchoir-y)));
  transition:transform 1.35s cubic-bezier(.37,.06,.3,1);
  pointer-events:none;              /* seule la mascotte est cliquable */
}
.mascotte{
  appearance:none;display:block;width:100%;height:100%;
  margin:0;padding:0;border:0;background:none;color:inherit;
  cursor:pointer;border-radius:999px;pointer-events:auto;
  position:relative;
}
.mascotte:focus-visible{outline:3px solid var(--blue-deep);outline-offset:8px}

/* EN TRAVERSÉE, elle passe devant la copie : elle n'y prend plus les clics.
   Un bouton posé par-dessus les questions n'en est pas un (le script pose la
   classe au départ, la retire au retour). */
.mascotte-zone.en-traversee .mascotte{pointer-events:none}

/* EN MARCHE, pareil : pendant qu'elle traverse la copie, elle n'avale pas
   un clic destiné à une réponse. */
.mascotte-zone.en-marche .mascotte{pointer-events:none}

.mascotte__svg{
  display:block;width:100%;height:100%;overflow:visible;
  transform-origin:50% 92%;
  transition:transform .32s cubic-bezier(.34,1.56,.64,1);
}
@media (hover:hover){
  .mascotte:hover .mascotte__svg{transform:scale(1.04)}
  .mascotte:hover .m-joue{opacity:.85}
}

/* couleurs : les jetons de l'app, un pour un */
.m-corps{fill:var(--blue)}
.m-ombre-bas{fill:var(--blue-deep);opacity:.22}
.m-surbrillance{fill:none;stroke:var(--blue-edge-1);stroke-width:10;
                stroke-linecap:round;opacity:.85}
.m-pied{fill:var(--blue-deep)}
.m-reflet-pied{fill:var(--blue)}
.m-joue{fill:var(--blue-deep);opacity:.55;transition:opacity .25s ease}
.m-bouche{fill:var(--ink);stroke:var(--ink);stroke-width:2.8;stroke-linejoin:round}
.m-langue{fill:var(--blue)}
.m-oeil-fond{fill:var(--paper)}
.m-separateur{fill:var(--ink)}
.m-pupille{fill:var(--blue-ink)}
.m-contour-oeil{fill:none;stroke:var(--ink);stroke-width:3.2}
.m-paupiere{fill:none;stroke:var(--ink);stroke-width:3.6;stroke-linecap:round}
.m-trait{fill:none;stroke:var(--ink);stroke-width:3.6;
         stroke-linejoin:round;stroke-linecap:round}
.m-ombre-fonce{fill:var(--blue-edge-2)}
.m-ombre-claire{fill:var(--blue-edge-1)}
.m-etincelle-claire{fill:var(--blue-edge-1)}
.m-etincelle-moyenne{fill:var(--blue-hi)}
.m-etincelle-fonce{fill:var(--blue-deep)}

/* ── LE REPOS, EN TROIS ÉTAGES ──────────────────────────────────────
   Chaque couche tient une propriété pour elle : un transform sur un élément
   n'en supporte qu'une à la fois, donc trois mouvements = trois groupes
   imbriqués (balance > sujet > corps). Le balancement est volontairement
   bancal dans son cycle (34 % d'un côté, 62 % revenu à peine, puis le long
   retour) : un aller-retour symétrique s'entend comme une machine. */
.mascotte__balance{
  transform-box:fill-box;transform-origin:50% 100%;
  animation:balance 7.4s ease-in-out infinite;
}
@keyframes balance{
  0%  {transform:rotate(-.65deg)}
  34% {transform:rotate(.6deg)}
  62% {transform:rotate(.15deg)}
  100%{transform:rotate(-.65deg)}
}
.mascotte__sujet{transform-box:fill-box;transform-origin:50% 88%}
/* le tassement : plus lent que le balancement d'origine (1,08 s), pour qu'il
   respire au lieu de battre — et surtout pour ne plus tomber sur le même
   temps que le clignement, qui n'est plus une horloge mais un tirage. */
.mascotte__corps{
  transform-box:fill-box;transform-origin:50% 90%;
  animation:flotte 2.4s ease-in-out infinite;
}
@keyframes flotte{
  0%   {transform:translateY(0)      scaleY(1)}
  18%  {transform:translateY(-3.4px) scaleY(1.035)}
  38%  {transform:translateY(-0.4px) scaleY(1.004)}
  58%  {transform:translateY(2.1px)  scaleY(0.960)}
  78%  {transform:translateY(0.3px)  scaleY(0.996)}
  100% {transform:translateY(0)      scaleY(1)}
}
/* le clignement : on ne dessine pas de paupière, on écrase les yeux — c'est
   la fermeture du dessin lui-même. Déclenché par le script, jamais par une
   boucle CSS : c'est de là que vient l'irrégularité. */
.mascotte__yeux{
  transform-box:fill-box;transform-origin:50% 50%;
  transition:opacity .11s ease;
}
.mascotte.cligne .mascotte__yeux{animation:cligne .16s ease-in-out}
.mascotte.cligne-deux .mascotte__yeux{animation:cligne-deux .42s ease-in-out}
@keyframes cligne{
  0%,100%{transform:scaleY(1)}
  40%,70%{transform:scaleY(.08)}
}
@keyframes cligne-deux{
  0%     {transform:scaleY(1)}
  16%,30%{transform:scaleY(.08)}
  44%    {transform:scaleY(1)}
  60%,74%{transform:scaleY(.08)}
  100%   {transform:scaleY(1)}
}
/* le sourire des yeux : les arcs de l'original, qui remplacent les yeux
   ouverts. Ils étaient le point bas du balancement ; ils deviennent un geste
   à part entière, et la seule chose que la mascotte fait quand tout va bien. */
.mascotte__paupieres{opacity:0;transition:opacity .11s ease}
.mascotte.sourit .mascotte__yeux{opacity:0}
.mascotte.sourit .mascotte__paupieres{opacity:1}
.mascotte.sourit .m-joue{opacity:.9}

/* arrivée, saut, étincelles */
.mascotte.arrive .mascotte__svg{animation:arrive .6s cubic-bezier(.34,1.56,.64,1)}
@keyframes arrive{from{opacity:0;transform:translateY(18px) scale(.9)}}

/* LES MARCHES — le saut (clic, fête), le petit saut (vie propre) et la
   penche (erreur de l'app, et le « non » d'une mauvaise réponse). Toutes
   portent sur .mascotte__sujet : l'ombre n'est pas dedans, donc elle ne
   décolle pas avec le corps. Le déplacement de perchoir, lui, se fait en
   marchant (voir .mascotte.marche-place) : la zone porte la mascotte pendant
   qu'elle marche, en douceur, sur la même durée. */
.mascotte.saut .mascotte__sujet,
.mascotte.fete .mascotte__sujet{animation:saut .62s cubic-bezier(.3,.8,.4,1)}
@keyframes saut{
  0%  {transform:translateY(0)     scaleY(1)}
  22% {transform:translateY(-16px) scaleY(1.02)}
  42% {transform:translateY(0)     scaleY(.95)}
  58% {transform:translateY(-7px)  scaleY(1)}
  78% {transform:translateY(0)     scaleY(.985)}
  100%{transform:translateY(0)     scaleY(1)}
}
/* l'ombre : elle recule au sol quand le corps monte, s'étale quand il tombe.
   C'est elle qui donne le poids — un personnage dont l'ombre s'envole a l'air
   d'une image qu'on soulève. */
.mascotte__ombre{transform-box:fill-box;transform-origin:50% 50%}
.mascotte.saut .mascotte__ombre,
.mascotte.fete .mascotte__ombre{animation:ombre-saut .62s cubic-bezier(.3,.8,.4,1)}
@keyframes ombre-saut{
  0%  {transform:scale(1,1);       opacity:1}
  22% {transform:scale(.88,.6);    opacity:.45}
  42% {transform:scale(1.07,1.14); opacity:1}
  58% {transform:scale(.94,.8);    opacity:.72}
  78% {transform:scale(1.02,1.05); opacity:1}
  100%{transform:scale(1,1);       opacity:1}
}
.mascotte.ptit-saut .mascotte__sujet{animation:ptit-saut .44s cubic-bezier(.3,.8,.4,1)}
@keyframes ptit-saut{
  0%  {transform:translateY(0)      scaleY(1)}
  30% {transform:translateY(-7px)   scaleY(1.03)}
  56% {transform:translateY(0)      scaleY(.975)}
  76% {transform:translateY(-2.5px) scaleY(1.01)}
  100%{transform:translateY(0)      scaleY(1)}
}
.mascotte.ptit-saut .mascotte__ombre{animation:ombre-ptit-saut .44s cubic-bezier(.3,.8,.4,1)}
@keyframes ombre-ptit-saut{
  0%  {transform:scale(1,1);       opacity:1}
  30% {transform:scale(.93,.78);   opacity:.7}
  56% {transform:scale(1.04,1.07); opacity:1}
  100%{transform:scale(1,1);       opacity:1}
}
/* la penche : le « hmm » — elle se penche depuis les pieds, sans jamais dire
   un mot (à cet instant, c'est le corrigé qui parle). Jouée sur une erreur de
   l'app, et en second temps après le sursaut d'une mauvaise réponse. */
.mascotte.penche .mascotte__sujet{animation:penche .78s ease-in-out}
@keyframes penche{
  0%  {transform:rotate(0)}
  26% {transform:rotate(-3.4deg)}
  58% {transform:rotate(-2.1deg)}
  100%{transform:rotate(0)}
}
.etincelle{opacity:0;transform-box:fill-box;transform-origin:center}
.mascotte.fete .etincelle{animation:etincelle .9s ease-out}
.mascotte.fete .etincelle:nth-of-type(1){animation-delay:0s}
.mascotte.fete .etincelle:nth-of-type(2){animation-delay:.06s}
.mascotte.fete .etincelle:nth-of-type(3){animation-delay:.12s}
.mascotte.fete .etincelle:nth-of-type(4){animation-delay:.18s}
.mascotte.fete .etincelle:nth-of-type(5){animation-delay:.24s}
.mascotte.fete .etincelle:nth-of-type(6){animation-delay:.3s}
@keyframes etincelle{
  0%  {opacity:0;transform:translateY(8px) scale(.2)}
  25% {opacity:1;transform:translateY(0)   scale(1)}
  100%{opacity:0;transform:translateY(-30px) scale(.6)}
}

/* ── LES HUMEURS — reprises de l'ancien bac à sable (supprimé) ──────
   Ce que l'app ne savait pas encore faire : s'ennuier après 25 secondes
   de calme, s'endormir après une minute et se réveiller à la moindre
   action, marcher sur place (trois allures), faire un grand saut volé
   suivi d'un petit rebond, sourire de joie, se surprendre. Le dessin
   porte les pièces qu'il faut (bouches, paupières lourdes, pieds
   séparés, signes de sommeil). Tout est coupé par prefers-reduced-motion,
   minuteries comprises. Les mèches ayant été retirées du dessin, leurs
   animations (meche-hop, meche-alterne) ne sont pas reprises. */
.mascotte__ombre{transform-box:fill-box;transform-origin:50% 50%;
  transition:transform .45s ease-out}
.etincelle{opacity:0;transform-box:fill-box;transform-origin:center}

/* RÉACTIONS : le corps exprime le poids, le visage porte l'émotion.
   Pas de voyage ni de grands sursauts pendant la lecture d'un corrigé. */
.mascotte__sujet{transition:transform .7s ease-in-out}
.mascotte__yeux{transition:opacity .18s ease,transform .65s ease}
.mascotte__bouche{transform-box:fill-box;transform-origin:center;
  transition:transform .35s ease,opacity .18s ease}
.mascotte__bouche-oh,.mascotte__bouche-calme,.mascotte__repos,
.mascotte__paupieres-lourdes{opacity:0;transition:opacity .25s ease}
.mascotte__bouche-oh{fill:var(--ink);stroke:var(--ink);stroke-width:2.4}
.mascotte__bouche-calme{fill:none;stroke:var(--ink);stroke-width:2.8;stroke-linecap:round}
/* les paupières fermées gardent l'épaisseur du trait des autres : un trait
   écrasé par un scaleY s'amincit aussi, d'où une ligne trop fine. La paupière
   lourde est donc un second tracé, plat, et non l'arque du sommeil écrasée. */
.mascotte.ennuie .mascotte__sujet{transform:translateY(2px) rotate(2deg)}
.mascotte.ennuie .mascotte__yeux{opacity:0}
.mascotte.ennuie .mascotte__paupieres-lourdes{opacity:1}
.mascotte.ennuie .mascotte__bouche,
.mascotte.dort .mascotte__bouche,
.mascotte.surprise .mascotte__bouche{opacity:0}
.mascotte.ennuie .mascotte__bouche-calme,
.mascotte.dort .mascotte__bouche-calme{opacity:1}
.mascotte.dort .mascotte__sujet{transform:translateY(4px) rotate(3.5deg) scaleY(.975)}
.mascotte.dort .mascotte__yeux{opacity:0}
.mascotte.dort .mascotte__repos{opacity:1}
.mascotte.ennuie .mascotte__corps,
.mascotte.dort .mascotte__corps{animation:respire 5.8s ease-in-out infinite}
@keyframes respire{
  0%,100%{transform:translateY(0) scaleY(1)}
  45%{transform:translateY(-1.3px) scaleY(1.014)}
  70%{transform:translateY(.5px) scaleY(.994)}
}
.mascotte.joie .mascotte__yeux{opacity:0}
.mascotte.joie .mascotte__paupieres{opacity:1}
.mascotte.joie .mascotte__bouche{transform:translateY(-1px) scale(1.2,1.08)}
.mascotte.joie .m-joue{opacity:.95}
.mascotte.joie .mascotte__sujet{animation:joie .78s ease-in-out}
.mascotte.joie .mascotte__ombre{animation:ombre-joie .78s ease-in-out}
@keyframes joie{
  0%{transform:translateY(0) scale(1,1)}
  15%{transform:translateY(2px) scale(1.035,.95)}
  40%{transform:translateY(-12px) scale(.975,1.04)}
  64%{transform:translateY(1px) scale(1.025,.97)}
  82%{transform:translateY(-2px) scale(.995,1.01)}
  100%{transform:translateY(0) scale(1,1)}
}
@keyframes ombre-joie{
  0%,100%{transform:scale(1,1);opacity:1}
  15%,64%{transform:scale(1.05,1.08);opacity:1}
  40%{transform:scale(.88,.72);opacity:.6}
  82%{transform:scale(.97,.95);opacity:.9}
}
.mascotte.surprise .mascotte__sujet{animation:surprise-douce .95s ease-out}
.mascotte.surprise .mascotte__yeux{transform:scale(1.12,1.08)}
.mascotte.surprise .mascotte__bouche-oh{opacity:1}
.mascotte.surprise .m-pupille,.mascotte.surprise .m-separateur{transform:translate(0,3px)}
@keyframes surprise-douce{
  0%{transform:translateY(0) rotate(0deg) scaleY(1)}
  16%{transform:translateY(-3px) rotate(-1.5deg) scaleY(1.025)}
  35%{transform:translateY(0) rotate(-2.5deg) scaleY(.99)}
  65%{transform:translateY(0) rotate(-2deg) scaleY(1)}
  100%{transform:translateY(0) rotate(0deg) scaleY(1)}
}
/* ── LA MARCHE SUR PLACE — les pieds vont en avant et en arrière ───────
   Les pieds reculent et reviennent (un rien de biais, et une petite variation
   d'échelle qui suggère la profondeur — vers l'avant elle grossit, vers
   l'arrière elle rétrécit), sur une amplitude courte. C'est le corps qui porte
   l'allure : il se balance et rebondit à chaque pas, et l'ombre se tasse quand
   il retombe. Un cycle de 0,85 s, deux pas. */
.mascotte__pied{transform-box:fill-box;transform-origin:50% 50%;
  /* au repos l'animation rend la main : le pied revient à sa place en douceur
     au lieu de sauter d'un coup (utile quand un bond se termine avec un pied
     encore en l'air). */
  transition:transform .2s ease-out}
.mascotte.marche-place .mascotte__pied{animation:pas-place .85s ease-in-out infinite}
.mascotte.marche-place .mascotte__pied--droit{animation-delay:-.425s}
@keyframes pas-place{
  0%,10%   {transform:translate(0,0)       scale(1)   rotate(0deg)}
  24%      {transform:translate(-1px,-5px) scale(.9)  rotate(-3deg);
            animation-timing-function:cubic-bezier(.14,.9,.28,1)}    /* il se ramène d'un coup */
  42%      {transform:translate(0,-.5px)   scale(.97) rotate(-1deg)}
  54%,100% {transform:translate(0,0)       scale(1)   rotate(0deg)}
}
.mascotte.marche-place .mascotte__sujet{animation:dandinette .85s ease-in-out infinite}
/* Chaque segment porte sa propre courbe : l'appui s'enfonce, la détente part
   sèchement (départ rapide, arrivée freinée), et la chute accélère au lieu de
   se poser — c'est ce qui remplace l'amortissement mou d'un ease-in-out. */
@keyframes dandinette{
  0%   {transform:translateY(0)     rotate(-3deg)   scale(1);
        animation-timing-function:cubic-bezier(.45,.05,.7,.5)}
  9%   {transform:translateY(3.4px) rotate(-1.6deg) scale(1.05,.935);
        animation-timing-function:cubic-bezier(.12,.9,.26,1)}
  24%  {transform:translateY(-10px) rotate(1.4deg)  scale(.96,1.072);
        animation-timing-function:cubic-bezier(.6,0,.9,.5)}
  36%  {transform:translateY(-1px)  rotate(1.7deg)  scale(1);
        animation-timing-function:cubic-bezier(.2,.85,.4,1)}
  44%  {transform:translateY(2.4px) rotate(2.1deg)  scale(1.038,.952)}
  50%  {transform:translateY(0)     rotate(3deg)    scale(1);
        animation-timing-function:cubic-bezier(.45,.05,.7,.5)}
  59%  {transform:translateY(3.4px) rotate(1.6deg)  scale(1.05,.935);
        animation-timing-function:cubic-bezier(.12,.9,.26,1)}
  74%  {transform:translateY(-10px) rotate(-1.4deg) scale(.96,1.072);
        animation-timing-function:cubic-bezier(.6,0,.9,.5)}
  86%  {transform:translateY(-1px)  rotate(-1.7deg) scale(1);
        animation-timing-function:cubic-bezier(.2,.85,.4,1)}
  94%  {transform:translateY(2.4px) rotate(-2.1deg) scale(1.038,.952)}
  100% {transform:translateY(0)     rotate(-3deg)   scale(1)}
}
.mascotte.marche-place .mascotte__ombre{animation:ombre-place .85s ease-in-out infinite}
@keyframes ombre-place{
  0%,50%,100%{transform:scale(1,1);      opacity:1}
  9%,59%     {transform:scale(1.12,1.2); opacity:1;
              animation-timing-function:cubic-bezier(.12,.9,.26,1)}   /* elle se dérobe d'un coup */
  24%,74%    {transform:scale(.78,.58);  opacity:.45;
              animation-timing-function:cubic-bezier(.6,0,.9,.5)}     /* et revient en accélérant */
}

/* ── LES SAUTS — un grand saut qui vole, un petit qui rebondit ─────────────
   Sur place, sans dérive latérale : elle monte, elle reste en l'air, elle
   redescend. Le profil vertical est une parabole exacte de part et d'autre du
   sommet (les deux courbes ci-dessous sont l'une la montée, l'autre la chute,
   sans rien d'autre) : la vitesse décroît régulièrement jusqu'à s'annuler en
   haut, puis remonte régulièrement. Aucun à-coup, aucune reprise — c'est ce qui
   donne le vol.
   Le grand saut reste 700 ms en l'air (61 % du bond) et l'ombre s'y rétracte de
   moitié. La réception s'écrase, puis se relâche lentement : pas de rebond sec.
   Le petit saut, lui, monte à moitié et retombe aussitôt : deux bonds, un grand
   et un petit, et c'est tout. */
.mascotte.saut-petit .mascotte__sujet{animation:bond-petit .7s cubic-bezier(.4,0,.6,1)}
.mascotte.saut-grand .mascotte__sujet{animation:bond-grand 1.15s cubic-bezier(.4,0,.6,1)}
@keyframes bond-petit{
  0%   {transform:translateY(0)      scale(1);
        animation-timing-function:cubic-bezier(.45,.05,.7,.5)}      /* elle s'enfonce, bref */
  9%   {transform:translateY(2.6px)  scale(1.045,.955);
        animation-timing-function:cubic-bezier(.333,.667,.667,1)}   /* la montée */
  32%  {transform:translateY(-46px)  scale(1);
        animation-timing-function:cubic-bezier(.333,0,.667,.333)}      /* le sommet, puis la chute */
  56%  {transform:translateY(0)      scale(1.015,.99);
        animation-timing-function:cubic-bezier(.2,.8,.4,1)}
  63%  {transform:translateY(3.4px)  scale(1.05,.95)}               /* la réception */
  100% {transform:translateY(0)      scale(1)}
}
@keyframes bond-grand{
  0%   {transform:translateY(0)      scale(1);
        animation-timing-function:cubic-bezier(.45,.05,.7,.5)}
  7%   {transform:translateY(4px)    scale(1.06,.945);
        animation-timing-function:cubic-bezier(.333,.667,.667,1)}   /* la montée */
  38%  {transform:translateY(-92px)  scale(1);
        animation-timing-function:cubic-bezier(.333,0,.667,.333)}      /* le sommet, puis la chute */
  68%  {transform:translateY(0)      scale(1.02,.985);
        animation-timing-function:cubic-bezier(.2,.8,.4,1)}
  75%  {transform:translateY(5px)    scale(1.07,.94)}               /* la réception */
  93%,100%{transform:translateY(0)   scale(1)}
}
.mascotte.saut-petit .mascotte__pied{animation:pas-hop .7s ease-in-out}
.mascotte.saut-grand .mascotte__pied{animation:pas-hop 1.15s ease-in-out}
@keyframes pas-hop{
  0%      {transform:translate(0,0)      scale(1)     rotate(0deg)}
  8%      {transform:translate(0,1.4px)  scale(1.05,.93)}
  30%     {transform:translate(0,-6.5px) scale(.94)   rotate(-2.4deg)}
  45%     {transform:translate(0,-5px)   scale(.95)   rotate(-1.4deg)}
  62%     {transform:translate(0,2px)    scale(1.02,.98)}
  72%     {transform:translate(0,4.6px)  scale(1.04,.95)}
  86%,100%{transform:translate(0,0)      scale(1)     rotate(0deg)}
}
.mascotte.saut-petit .mascotte__ombre{animation:ombre-hop .7s ease-in-out}
.mascotte.saut-grand .mascotte__ombre{animation:ombre-hop 1.15s ease-in-out}
@keyframes ombre-hop{
  0%      {transform:scale(1,1);       opacity:1}
  8%      {transform:scale(1.14,1.24); opacity:1}      /* l'appui l'étale */
  35%     {transform:scale(.45,.22);   opacity:.26}    /* elle est haute : l'ombre se rétracte */
  50%     {transform:scale(.53,.3);    opacity:.33}
  62%     {transform:scale(1.18,1.3);  opacity:1}      /* la réception la retasse */
  74%     {transform:scale(.93,.84);   opacity:.85}    /* elle se relâche sans rebond */
  88%,100%{transform:scale(1,1);       opacity:1}
}

/* ── LA MARCHE SUR PLACE (2) — elle saute d'un pied sur l'autre ───────────
   Une démarche d'enfant. Elle pousse sur un pied, s'enlève, reste en l'air un
   bon moment — c'est la durée du vol qui donne le flottement, plus que la
   hauteur — puis se repose délicatement sur le pied opposé, ce qui balance le
   corps d'un côté puis de l'autre. Montée et chute sont deux paraboles
   exactes, comme pour les sauts : la vitesse s'annule au sommet et repart sans
   jamais casser. La compression reste sous 3 %, il n'y a aucun rebond à la
   réception — juste un tassement léger avant de repartir. */
.mascotte.marche-place-2 .mascotte__sujet{animation:bond-alterne 1.7s cubic-bezier(.4,0,.6,1) infinite}
@keyframes bond-alterne{
  0%   {transform:translate(0,0)          rotate(0deg)    scale(1);
        animation-timing-function:cubic-bezier(.5,.05,.7,.45)}      /* l'appui, bref */
  6%   {transform:translate(2.6px,2.4px)  rotate(3.5deg)  scale(1.03,.972);
        animation-timing-function:cubic-bezier(.333,.667,.667,1)}   /* la montée */
  25%  {transform:translate(0,-76px)      rotate(-1deg)   scale(1);
        animation-timing-function:cubic-bezier(.333,0,.667,.333)}      /* le sommet, puis la chute */
  44%  {transform:translate(-2.6px,0)     rotate(-2.5deg) scale(1.01,.992);
        animation-timing-function:cubic-bezier(.2,.8,.4,1)}         /* le pied opposé touche */
  47%  {transform:translate(-2px,1.8px)   rotate(-2deg)   scale(1.028,.975)}   /* il encaisse, à peine */
  50%  {transform:translate(0,0)          rotate(0deg)    scale(1);
        animation-timing-function:cubic-bezier(.5,.05,.7,.45)}
  56%  {transform:translate(-2.6px,2.4px) rotate(-3.5deg) scale(1.03,.972);
        animation-timing-function:cubic-bezier(.333,.667,.667,1)}
  75%  {transform:translate(0,-76px)      rotate(1deg)    scale(1);
        animation-timing-function:cubic-bezier(.333,0,.667,.333)}
  94%  {transform:translate(2.6px,0)      rotate(2.5deg)  scale(1.01,.992);
        animation-timing-function:cubic-bezier(.2,.8,.4,1)}
  97%  {transform:translate(2px,1.8px)    rotate(2deg)    scale(1.028,.975)}
  100% {transform:translate(0,0)          rotate(0deg)    scale(1)}
}
/* un pied pousse, se ramasse en l'air, puis cède la place à l'autre : chacune
   des deux animations est la même, décalée d'un bond — c'est ce décalage qui
   fait l'alternance, et il n'y a rien d'autre à écrire dans le dessin. */
.mascotte.marche-place-2 .mascotte__pied{animation:pied-alterne 1.7s ease-in-out infinite}
.mascotte.marche-place-2 .mascotte__pied--droit{animation-delay:-.85s}
@keyframes pied-alterne{
  0%      {transform:translate(0,0)       scale(1)      rotate(0deg)}    /* il pousse */
  6%      {transform:translate(0,1.4px)   scale(1.045,.94)}
  16%     {transform:translate(0,-5px)    scale(.95)    rotate(-3deg)}   /* il quitte le sol */
  25%     {transform:translate(0,-7px)    scale(.93)    rotate(-4deg)}   /* ramassé au sommet */
  38%     {transform:translate(0,-6.5px)  scale(.935)   rotate(-3deg)}
  60%     {transform:translate(0,-6px)    scale(.94)    rotate(-2deg)}
  80%     {transform:translate(0,-3.5px)  scale(.96)    rotate(-1deg)}
  90%     {transform:translate(0,-.5px)   scale(.99)    rotate(0deg)}    /* il redescend */
  94%     {transform:translate(0,1.2px)   scale(1.03,.96)}               /* il se pose */
  100%    {transform:translate(0,0)       scale(1)      rotate(0deg)}
}
.mascotte.marche-place-2 .mascotte__ombre{animation:ombre-alterne 1.7s ease-in-out infinite}
@keyframes ombre-alterne{
  0%,50%,100%{transform:scale(1,1);       opacity:1}
  6%,56%     {transform:scale(1.1,1.18);  opacity:1}      /* l'appui l'étale */
  25%,75%    {transform:scale(.6,.38);    opacity:.45}    /* elle est haut : l'ombre se rétracte */
  33%,83%    {transform:scale(.64,.42);   opacity:.5}
  44%,94%    {transform:scale(1.12,1.2);  opacity:1}      /* la réception la retasse */
}

/* Hors champ ou onglet caché : les poses restent, les boucles se taisent. */
.mascotte.en-pause *{animation-play-state:paused!important}

@media (prefers-reduced-motion:reduce){
  .mascotte *,.mascotte::after{animation:none!important;transition:none!important}
  .mascotte__balance,.mascotte__sujet,.mascotte__corps,.mascotte__ombre,
  .mascotte__pied{transform:none!important}
  .mascotte__paupieres{opacity:0!important}
  .mascotte.sourit .mascotte__yeux{opacity:1!important}
  .mascotte:hover .mascotte__svg{transform:none}
  .mascotte-zone{transition:none}          /* elle change de perchoir sans voyager */
  /* Joie, surprise, ennui et sommeil restent lisibles comme expressions
     fixes : seules les courses disparaissent. */
  .etincelle{opacity:0!important}
}

/* ══════ 19 · LA MASCOTTE SUR LE BUREAU — repris tel quel de variants/19-mascotte-bureau ══════ */

/* ── LA MASCOTTE DANS LA MARGE GAUCHE ───────────────────────────────
   La feuille est à --shell (760px ≥1200), donc son bord gauche est à
   50% - 380px. La mascotte se pose dans cette marge, à hauteur de copie :
   la marge de gauche porte une présence, comme celle de droite porte le
   score.
   Elle est remontée à 25vh — elle était au ras du bas de l'écran, sous la
   ligne d'horizon, hors de la composition — et écartée de 36 px du bord de
   la feuille, pour ne pas sembler collée. Plafond à 320 px : sur un très
   grand écran 25vh la ferait monter plus haut que le titre. Le haut de son
   territoire tient compte de cette base tout seul : le script mesure le bas
   calculé. */
.mascotte-zone{
  --mascotte-taille:176px;
  position:fixed;
  left:calc(50% - 380px - 178px - 36px);
  bottom:clamp(120px,25vh,320px);
  z-index:25;
}

/* Sous 1240px la marge n'existe plus : elle se range à gauche, plus petite —
   mais elle garde la même hauteur, sinon elle s'assiérait sur le micro-pied. */
@media (max-width:1239px){
  .mascotte-zone{--mascotte-taille:120px;left:16px;bottom:clamp(72px,10vh,132px)}
}
/* Sous 860px il n'y a plus de place du tout à côté : elle rentre dans le flux,
   en fin de feuille. */
@media (max-width:860px){
  .mascotte-zone{
    position:relative;align-self:center;left:auto;bottom:auto;
    --mascotte-taille:120px;margin:0 0 var(--sp-2);
  }
}

/* ══════════════════════════════════════════════════════════════════════
   AJUSTEMENT DE COHABITATION — le seul que les itérations seules n'avaient
   pas à faire, parce qu'elles ne rencontraient pas la bande.
   ══════════════════════════════════════════════════════════════════════ */

/* LE FILET DE PROGRESSION. Il vit juste sous la bande, et sa piste
   d'encre (9 % d'un brun sombre) disparaît sur le haut de page refroidi :
   on ne lisait plus qu'un tiret bleu flottant sans piste pour le mesurer.
   Un cran de piste suffit à retrouver un avancement lisible. */
.rule{background:rgba(38,20,18,.14)}

/* le seuil de 19 (860 px) devient le seuil de la marge : sous 1240 px il n'y a
   plus de marge latérale, donc elle rentre dans le flux de la feuille au lieu
   de flotter sur le contenu */
@media (min-width:861px) and (max-width:1239px){
  .mascotte-zone{
    position:relative;align-self:center;left:auto;bottom:auto;
    --mascotte-taille:120px;margin:0 0 var(--sp-2);
  }
}
