/* ═══════════════════════════════════════════════════════════════════════════
   mascot.css — Mascotte flamme « compagnon » (fixed bottom-right)
   ---------------------------------------------------------------------------
   Utilisée par :
     • cards.html  (jeu de cartes en cours)
     • game.html   (jeu de dés en cours + jeu progressif en cours)

   API JS : voir mascot.js (DS_MASCOT.attach / .react / .show / .hide).

   ⚠️ NE PAS confondre avec la mascotte « slider » dans level-slider.css,
   qui vit dans une barre et bouge avec la poignée. Celle-ci est un
   compagnon de jeu fixe, plus grosse, plus réactive.

   Classe principale : `.ds-mascot` (avec alias `.cards-mascot` pour
   l'existant cards.html, qui pose les deux classes via JS).
   ═══════════════════════════════════════════════════════════════════════════ */

.ds-mascot,
.cards-mascot {
  position: fixed;
  right: clamp(16px, 3vw, 28px);
  bottom: clamp(16px, 3vh, 32px);
  /* Bien visible, mais discrète au repos */
  width:  clamp(72px, 10vw, 96px);
  height: clamp(72px, 10vw, 96px);
  pointer-events: auto;
  /* z-index ≥ 9000 (modale action) → reste visible pendant la révélation */
  z-index: 9500;
  opacity: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transform-origin: 50% 100%;
  /* `translateZ(0)` force la couche GPU → anti-aliasing crisp,
     évite le flou lors des transforms (WKWebView). */
  transform: scale(var(--cm-scale, 1)) translateZ(0);
  filter:
    hue-rotate(var(--cm-hue, 0deg))
    saturate(var(--cm-sat, 1))
    drop-shadow(0 3px 8px var(--cm-glow, rgba(255, 140, 30, 0.65)));
  transition:
    opacity 0.45s ease,
    transform 0.55s cubic-bezier(0.34, 1.55, 0.5, 1),
    filter 0.5s ease;
  will-change: transform, filter, opacity;
  backface-visibility: hidden;
}
.ds-mascot svg,
.cards-mascot svg {
  width: 100%; height: 100%;
  display: block;
  shape-rendering: geometricPrecision;
  animation: cmBob 3s ease-in-out infinite;
}
.ds-mascot.is-visible,
.cards-mascot.is-visible { opacity: 0.92; }
.ds-mascot:hover,
.cards-mascot:hover { opacity: 1; }

/* ───── Animations idle ────────────────────────────────────── */
@keyframes cmBob {
  0%, 100% { transform: translateY(0)    rotate(-2deg); }
  50%      { transform: translateY(-3px) rotate(2deg);  }
}

/* ───── Animations DOUBLE-TAP (5 variantes amusantes, en place) ─────
   Flam reste dans le coin (ne sort PAS de l'écran). À chaque double-tap,
   une des 5 variantes est jouée aléatoirement. On coupe les transitions
   parent ET les animations héritées d'états (`is-hot`, `is-happy`).

   Variantes :
     • is-bigjump   — saut puissant avec flip 360°
     • is-tornado   — toupie rapide en place (rotation 1080°)
     • is-wiggle    — secouée latérale frénétique
     • is-squish    — gros squash & stretch en boule de jelly
     • is-orbit     — petite orbite (cercle de ~50 px) qui reste sur place */
.ds-mascot.is-bigjump,
.cards-mascot.is-bigjump,
.ds-mascot.is-tornado,
.cards-mascot.is-tornado,
.ds-mascot.is-wiggle,
.cards-mascot.is-wiggle,
.ds-mascot.is-squish,
.cards-mascot.is-squish,
.ds-mascot.is-orbit,
.cards-mascot.is-orbit,
.ds-mascot.is-flying,
.cards-mascot.is-flying {
  z-index: 99999 !important;
  transition: none !important;
  opacity: 1 !important;
  filter: drop-shadow(0 6px 18px rgba(255, 140, 30, 0.7)) !important;
}

/* ⚠️ BOUNDS — la mascotte est ancrée bottom-right (right:20px, bottom:20px,
   ~96 px wide). Pour rester DANS l'écran à 100% sur mobile (390×844) :
     • translateX : MAX -55vw (jamais positif — déjà au bord droit)
     • translateY : MAX -65vh (jamais positif — déjà au bord bas)
   Toutes les variantes ci-dessous respectent ces limites. */

/* MULTI-BONDS — 3 sauts qui traversent l'écran de plus en plus haut */
.ds-mascot.is-bigjump,
.cards-mascot.is-bigjump { animation: cmBigJump 1.8s cubic-bezier(.34,1.55,.5,1) both !important; }
@keyframes cmBigJump {
  0%   { transform: translate(0, 0)         scale(1)         rotate(0deg); }
  10%  { transform: translate(-12vw, -25vh) scale(1.05)      rotate(180deg); }
  20%  { transform: translate(-22vw, 0)     scale(1.25, 0.7) rotate(360deg); }
  35%  { transform: translate(-35vw, -40vh) scale(1.05)      rotate(720deg); }
  45%  { transform: translate(-45vw, 0)     scale(1.25, 0.7) rotate(1080deg); }
  60%  { transform: translate(-35vw, -55vh) scale(1.05)      rotate(1440deg); }
  70%  { transform: translate(-25vw, 0)     scale(1.2, 0.75) rotate(1800deg); }
  85%  { transform: translate(-10vw, -10vh) scale(1)         rotate(2160deg); }
  100% { transform: translate(0, 0)         scale(1)         rotate(2160deg); }
}

/* TORNADO — toupie qui voyage en cercle CÔTÉ GAUCHE (jamais à droite, jamais en bas) */
.ds-mascot.is-tornado,
.cards-mascot.is-tornado { animation: cmTornado 1.7s cubic-bezier(.4,.0,.4,1) both !important; }
@keyframes cmTornado {
  0%   { transform: translate(0, 0)         rotate(0deg)    scaleX(1)    scaleY(1); }
  15%  { transform: translate(-15vw, -15vh) rotate(540deg)  scaleX(0.6)  scaleY(1.35); }
  30%  { transform: translate(-40vw, -25vh) rotate(1080deg) scaleX(0.5)  scaleY(1.45); }
  45%  { transform: translate(-50vw, -45vh) rotate(1620deg) scaleX(0.55) scaleY(1.4); }
  60%  { transform: translate(-30vw, -55vh) rotate(2160deg) scaleX(0.6)  scaleY(1.35); }
  75%  { transform: translate(-10vw, -40vh) rotate(2700deg) scaleX(0.65) scaleY(1.3); }
  90%  { transform: translate(-5vw, -15vh)  rotate(3060deg) scaleX(0.8)  scaleY(1.15); }
  100% { transform: translate(0, 0)         rotate(3240deg) scaleX(1)    scaleY(1); }
}

/* BOOMERANG — file vers l'angle haut-gauche puis revient (entièrement à l'écran) */
.ds-mascot.is-wiggle,
.cards-mascot.is-wiggle { animation: cmBoomerang 1.6s cubic-bezier(.2,.7,.3,1) both !important; }
@keyframes cmBoomerang {
  0%   { transform: translate(0, 0)         rotate(0deg)     scaleX(1); }
  18%  { transform: translate(-25vw, -25vh) rotate(-360deg)  scaleX(0.85); }
  35%  { transform: translate(-50vw, -45vh) rotate(-720deg)  scaleX(0.7); }
  50%  { transform: translate(-55vw, -60vh) rotate(-1080deg) scaleX(0.75); }   /* extrême */
  65%  { transform: translate(-40vw, -55vh) rotate(-1440deg) scaleX(0.85); }
  80%  { transform: translate(-20vw, -30vh) rotate(-1800deg) scaleX(0.95); }
  100% { transform: translate(0, 0)         rotate(-1800deg) scaleX(1); }
}

/* MEGA SQUISH — squish + propulsion verticale (jamais hors écran en Y) */
.ds-mascot.is-squish,
.cards-mascot.is-squish { animation: cmSquish 1.4s cubic-bezier(.34,1.7,.42,1) both !important; }
@keyframes cmSquish {
  0%   { transform: translateY(0)     scaleX(1)    scaleY(1); }
  8%   { transform: translateY(0)     scaleX(1.7)  scaleY(0.4); }
  20%  { transform: translateY(-55vh) scaleX(0.55) scaleY(1.65); }
  35%  { transform: translateY(-65vh) scaleX(0.95) scaleY(1.05); }
  50%  { transform: translateY(-35vh) scaleX(1.1)  scaleY(0.9); }
  65%  { transform: translateY(0)     scaleX(1.45) scaleY(0.55); }
  78%  { transform: translateY(-15vh) scaleX(0.78) scaleY(1.28); }
  88%  { transform: translateY(0)     scaleX(1.15) scaleY(0.88); }
  100% { transform: translateY(0)     scaleX(1)    scaleY(1); }
}

/* MEGA ORBIT — grande orbite côté gauche-haut (jamais positif sur X) */
.ds-mascot.is-orbit,
.cards-mascot.is-orbit { animation: cmOrbit 2s cubic-bezier(.4,.0,.6,1) both !important; }
@keyframes cmOrbit {
  0%   { transform: translate(0, 0)         rotate(0deg); }
  12%  { transform: translate(-20vw, -15vh) rotate(45deg); }
  25%  { transform: translate(-45vw, -30vh) rotate(90deg); }
  37%  { transform: translate(-55vw, -50vh) rotate(135deg); }
  50%  { transform: translate(-40vw, -65vh) rotate(180deg); }
  62%  { transform: translate(-15vw, -60vh) rotate(225deg); }
  75%  { transform: translate(0, -40vh)     rotate(270deg); }
  87%  { transform: translate(-5vw, -15vh)  rotate(315deg); }
  100% { transform: translate(0, 0)         rotate(360deg); }
}

/* Le svg interne reste calme pendant ces animations (sauf tornado où on
   peut le faire tourner aussi pour effet renforcé) */
.ds-mascot.is-tornado svg,
.cards-mascot.is-tornado svg { animation: cmSpinFast 0.18s linear infinite !important; }
@keyframes cmSpinFast {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* ─── Vol en cercles à travers l'écran (6e variante) ─────────────────
   Effet « grand vol » qui traverse l'écran et revient. Plus spectaculaire
   mais sort partiellement de la zone — gardé en variante optionnelle. */
.ds-mascot.is-flying,
.cards-mascot.is-flying { animation: cmFly 2.6s cubic-bezier(.45,.05,.55,.95) both !important; }
.ds-mascot.is-flying svg,
.cards-mascot.is-flying svg { animation: cmSpin 0.4s linear infinite !important; }
@keyframes cmFly {
  /* Trajectoire 100% dans le viewport. Mascotte ancrée bottom-right,
     ne dépasse JAMAIS -55vw (gauche) ni -65vh (haut), pas de positif. */
  0%   { transform: translate(0, 0)         rotate(0deg); }
  12%  { transform: translate(-20vw, -18vh) rotate(180deg); }
  25%  { transform: translate(-45vw, -35vh) rotate(360deg); }
  38%  { transform: translate(-55vw, -55vh) rotate(540deg); }
  50%  { transform: translate(-35vw, -65vh) rotate(720deg); }
  62%  { transform: translate(-10vw, -55vh) rotate(900deg); }
  75%  { transform: translate(-5vw,  -30vh) rotate(1080deg); }
  88%  { transform: translate(-30vw, -10vh) rotate(1260deg); }
  100% { transform: translate(0, 0)         rotate(1440deg); }
}
@keyframes cmSpin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* Désactive les animations d'état (is-hot pulse, etc.) pour les variantes
   exclusives — la dernière déclaration gagne. */
.ds-mascot.is-bigjump.is-hot, .cards-mascot.is-bigjump.is-hot { animation: cmBigJump 1.1s cubic-bezier(.34,1.55,.5,1) both !important; }
.ds-mascot.is-tornado.is-hot, .cards-mascot.is-tornado.is-hot { animation: cmTornado 1s linear both !important; }
.ds-mascot.is-wiggle.is-hot,  .cards-mascot.is-wiggle.is-hot  { animation: cmWiggle 0.85s ease-in-out both !important; }
.ds-mascot.is-squish.is-hot,  .cards-mascot.is-squish.is-hot  { animation: cmSquish 0.95s cubic-bezier(.34,1.7,.42,1) both !important; }
.ds-mascot.is-orbit.is-hot,   .cards-mascot.is-orbit.is-hot   { animation: cmOrbit 1.2s cubic-bezier(.4,.0,.6,1) both !important; }
.ds-mascot.is-flying.is-hot,  .cards-mascot.is-flying.is-hot  { animation: cmFly 2.6s cubic-bezier(.45,.05,.55,.95) both !important; }

/* Clignement (les paires d'yeux) */
.ds-mascot svg > g > g,
.cards-mascot svg > g > g {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmBlink 4.5s ease-in-out infinite;
}
.ds-mascot svg > g > g:nth-of-type(2),
.cards-mascot svg > g > g:nth-of-type(2) {
  animation-delay: 0.12s;
}
@keyframes cmBlink {
  0%, 92%, 100% { transform: scaleY(1); }
  94%           { transform: scaleY(0.1); }
  96%           { transform: scaleY(1); }
}

/* Pupilles qui scrutent */
.ds-mascot svg > g > g > circle,
.cards-mascot svg > g > g > circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmLook 5.8s ease-in-out infinite;
}
@keyframes cmLook {
  0%, 30%, 100% { transform: translateX(0); }
  40%, 55%      { transform: translateX(1.1px); }
  65%, 80%      { transform: translateX(-1.1px); }
}

/* ───── Lunettes d'été : les yeux sont cachés → animation alternative au
   clignement. Périodiquement, la mascotte SOULÈVE ses lunettes sur le front
   (révélant les yeux qui clignent dessous), puis les redescend. */
.ds-mascot   .ds-mascot-acc--glasses,
.cards-mascot .ds-mascot-acc--glasses,
.lvs-mascot  .ds-mascot-acc--glasses {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmGlassesLift 6.5s ease-in-out infinite;
}
@keyframes cmGlassesLift {
  0%, 68%   { transform: translateY(0); }      /* lunettes sur les yeux */
  76%, 90%  { transform: translateY(-18px); }  /* relevées sur le front */
  100%      { transform: translateY(0); }      /* redescendues */
}
@media (prefers-reduced-motion: reduce) {
  .ds-mascot-acc--glasses { animation: none; }
}

/* ───── Cœur de Saint-Valentin qui bat sur la poitrine ───── */
.ds-mascot-acc--vheart {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmHeartBeat 1.3s ease-in-out infinite;
}
@keyframes cmHeartBeat {
  0%, 100% { transform: scale(1); }
  12%      { transform: scale(1.28); }   /* premier battement */
  24%      { transform: scale(1); }
  36%      { transform: scale(1.18); }   /* second battement */
  50%      { transform: scale(1); }
}

/* ───── Pleine lune : léger flottement + halo qui respire ───── */
.ds-mascot-acc--moon {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmMoonFloat 5s ease-in-out infinite;
}
@keyframes cmMoonFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2.5px); }
}
.ds-moon-glow {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmMoonGlow 5s ease-in-out infinite;
}
@keyframes cmMoonGlow {
  0%, 100% { opacity: 0.22; transform: scale(1); }
  50%      { opacity: 0.36; transform: scale(1.15); }
}
/* ───── Grosse pleine lune DERRIÈRE la mascotte : reste FIXE ─────
   Le <svg> entier « bobe » (cmBob : translateY 0→-3px). On applique à la
   lune le mouvement inverse (0→+3px, même timing) → net ≈ 0, lune immobile
   pendant que le corps se balance. */
.ds-mascot-acc--moonbig {
  transform-box: fill-box;
  transform-origin: center;
  animation: cmMoonAntiBob 3s ease-in-out infinite;
}
@keyframes cmMoonAntiBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(3px); }
}
@media (prefers-reduced-motion: reduce) {
  .ds-mascot-acc--vheart, .ds-mascot-acc--moon, .ds-moon-glow,
  .ds-mascot-acc--moonbig { animation: none; }
}

/* ───── États émotionnels (déclenchés par DS_MASCOT.react) ─── */

/* Hot — carte 🔥 (5-6 cœurs) ou résultat ardent */
.ds-mascot.is-hot,
.cards-mascot.is-hot {
  --cm-scale: 1.45;
  --cm-hue:  -28deg;
  --cm-sat:  1.45;
  --cm-glow: rgba(255, 30, 30, 0.95);
  opacity: 1 !important;
}

/* Happy — résultat doux/moyen ou carte normale jouée
   La flamme s'éclate : saut + rotations marquées + ❤️ qui pop. */
.ds-mascot.is-happy,
.cards-mascot.is-happy {
  animation: cmHappy 1.1s cubic-bezier(0.34, 1.55, 0.5, 1);
}
@keyframes cmHappy {
  0%   { transform: scale(var(--cm-scale, 1))             rotate(0deg)   translateY(0); }
  18%  { transform: scale(calc(var(--cm-scale, 1) * 1.42)) rotate(-15deg) translateY(-12px); }
  38%  { transform: scale(calc(var(--cm-scale, 1) * 1.18)) rotate(12deg)  translateY(-4px); }
  58%  { transform: scale(calc(var(--cm-scale, 1) * 1.32)) rotate(-8deg)  translateY(-8px); }
  78%  { transform: scale(calc(var(--cm-scale, 1) * 1.08)) rotate(4deg)   translateY(-2px); }
  100% { transform: scale(var(--cm-scale, 1))             rotate(0deg)   translateY(0); }
}
.ds-mascot.is-happy svg > g > g,
.cards-mascot.is-happy svg > g > g {
  animation: cmBlink 0.4s ease-in-out;
}
.ds-mascot.is-happy::after,
.cards-mascot.is-happy::after {
  content: '❤️';
  position: absolute;
  top: -30%; left: 50%;
  transform: translate(-50%, 0) scale(0);
  font-size: 0.65em;
  pointer-events: none;
  animation: cmHappyHeart 1.1s ease-out;
}
@keyframes cmHappyHeart {
  0%   { opacity: 0; transform: translate(-50%, 12px) scale(0)   rotate(-20deg); }
  30%  { opacity: 1; transform: translate(-50%, -6px) scale(1.4) rotate(15deg); }
  60%  { opacity: 1; transform: translate(-50%, -22px) scale(1.15) rotate(-8deg); }
  100% { opacity: 0; transform: translate(-50%, -42px) scale(0.7) rotate(10deg); }
}

/* Curious — joueur tape une carte / réfléchit */
.ds-mascot.is-curious svg,
.cards-mascot.is-curious svg {
  animation: cmCurious 0.6s ease-in-out;
}
@keyframes cmCurious {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-2px) rotate(-15deg); }
}

/* Sad — action impossible / passer son tour */
.ds-mascot.is-sad,
.cards-mascot.is-sad {
  opacity: 0.38 !important;
  transform: scale(calc(var(--cm-scale, 1) * 0.85)) translateY(4px);
  filter:
    hue-rotate(180deg) saturate(0.4)
    drop-shadow(0 4px 10px rgba(80, 100, 200, 0.4));
}

/* Drawing — pioche / lancer en cours : aspire + souffle, ✨ qui jaillit */
.ds-mascot.is-drawing,
.cards-mascot.is-drawing {
  animation: cmDraw 0.9s cubic-bezier(0.34, 1.55, 0.5, 1);
}
@keyframes cmDraw {
  0%   { transform: scale(var(--cm-scale, 1)) translateY(0); }
  18%  { transform: scale(var(--cm-scale, 1)) scaleY(1.25) scaleX(0.88) translateY(-3px); }
  45%  { transform: scale(var(--cm-scale, 1)) scaleY(0.85) scaleX(1.15) translateY(2px); }
  70%  { transform: scale(var(--cm-scale, 1)) scaleY(1.08) scaleX(0.96) translateY(-1px); }
  100% { transform: scale(var(--cm-scale, 1)) translateY(0); }
}
.ds-mascot.is-drawing::after,
.cards-mascot.is-drawing::after {
  content: '✨';
  position: absolute;
  top: -25%; left: 50%;
  transform: translate(-50%, 0) scale(0);
  font-size: 0.7em;
  pointer-events: none;
  animation: cmDrawSpark 0.9s ease-out;
}
@keyframes cmDrawSpark {
  0%   { opacity: 0; transform: translate(-50%, 10px)  scale(0)   rotate(0); }
  35%  { opacity: 1; transform: translate(-50%, -8px)  scale(1.3) rotate(180deg); }
  100% { opacity: 0; transform: translate(-50%, -28px) scale(0.6) rotate(360deg); }
}

/* Celebrating — victoire (exclusif, ne peut être interrompu) */
.ds-mascot.is-celebrating,
.cards-mascot.is-celebrating {
  --cm-scale: 2.2;
  --cm-glow:  rgba(255, 200, 60, 1);
  opacity: 1 !important;
  z-index: 9999;
  animation: cmCheer 1.4s cubic-bezier(0.34, 1.55, 0.5, 1);
}
@keyframes cmCheer {
  0%   { transform: scale(0.6) rotate(0); }
  30%  { transform: scale(2.6) rotate(-12deg) translateY(-30px); }
  55%  { transform: scale(2.0) rotate(10deg)  translateY(-20px); }
  80%  { transform: scale(2.3) rotate(-6deg)  translateY(-26px); }
  100% { transform: scale(var(--cm-scale, 2.2)) rotate(0) translateY(0); }
}
.ds-mascot.is-celebrating::before,
.ds-mascot.is-celebrating::after,
.cards-mascot.is-celebrating::before,
.cards-mascot.is-celebrating::after {
  content: '✨';
  position: absolute;
  font-size: 0.55em;
  pointer-events: none;
  animation: cmSparkle 1.4s ease-out 0.2s 2;
}
.ds-mascot.is-celebrating::before,
.cards-mascot.is-celebrating::before { top: -10%; left: -20%;  animation-delay: 0s;   }
.ds-mascot.is-celebrating::after,
.cards-mascot.is-celebrating::after  { top:  5%;  right: -25%; animation-delay: 0.4s; }
@keyframes cmSparkle {
  0%   { opacity: 0; transform: scale(0)   rotate(0); }
  30%  { opacity: 1; transform: scale(1.2) rotate(180deg); }
  100% { opacity: 0; transform: scale(1)   rotate(360deg) translateY(-12px); }
}

/* Welcoming — entrée fracassante en accueil : la flamme jaillit du
   coin avec rotation, dépasse en taille, settle. Étincelles tout autour.
   Plus court que celebrating (~1.4 s) pour ne pas retarder l'utilisateur. */
.ds-mascot.is-welcoming,
.cards-mascot.is-welcoming {
  --cm-glow: rgba(255, 200, 60, 0.95);
  opacity: 1 !important;
  z-index: 9999;
  animation: cmWelcome 1.4s cubic-bezier(0.34, 1.65, 0.5, 1);
}
@keyframes cmWelcome {
  0%   { opacity: 0; transform: scale(0)    rotate(-220deg) translate(80px, 80px); }
  25%  { opacity: 1; transform: scale(2.6)  rotate(-30deg)  translate(-15px, -25px); }
  45%  {              transform: scale(1.3)  rotate(20deg)   translate(8px, -8px); }
  62%  {              transform: scale(1.85) rotate(-12deg)  translate(-5px, -15px); }
  80%  {              transform: scale(1.5)  rotate(6deg)    translate(2px, -6px); }
  100% { opacity: 0.92; transform: scale(1)  rotate(0deg)    translate(0, 0); }
}
/* Pluie d'étincelles autour de la flamme à l'arrivée — 4 points cardinaux */
.ds-mascot.is-welcoming::before,
.cards-mascot.is-welcoming::before {
  content: '✨';
  position: absolute;
  top: -30%; left: -30%;
  font-size: 0.7em;
  pointer-events: none;
  opacity: 0;
  animation: cmWelcomeSparkA 1.2s ease-out 0.25s;
}
.ds-mascot.is-welcoming::after,
.cards-mascot.is-welcoming::after {
  content: '✨';
  position: absolute;
  top: -25%; right: -35%;
  font-size: 0.6em;
  pointer-events: none;
  opacity: 0;
  animation: cmWelcomeSparkB 1.2s ease-out 0.4s;
}
@keyframes cmWelcomeSparkA {
  0%   { opacity: 0; transform: translate(20px, 20px) scale(0)   rotate(0); }
  30%  { opacity: 1; transform: translate(-5px, -8px) scale(1.6) rotate(180deg); }
  100% { opacity: 0; transform: translate(-22px, -38px) scale(0.7) rotate(360deg); }
}
@keyframes cmWelcomeSparkB {
  0%   { opacity: 0; transform: translate(-20px, 18px) scale(0)   rotate(0); }
  30%  { opacity: 1; transform: translate(6px, -10px)  scale(1.4) rotate(-180deg); }
  100% { opacity: 0; transform: translate(28px, -36px) scale(0.6) rotate(-360deg); }
}

/* Bulle de dialogue « Bienvenue ✨ » — fade-in puis float-up puis fade-out.
   Injectée dynamiquement par mascot.js dans la mascotte. */
.ds-mascot-bubble {
  position: fixed;
  /* Positionnée AU-DESSUS de la mascotte (bottom-right) — anchored via JS
     pour s'aligner sur le nœud .ds-mascot. */
  right: clamp(86px, 13vw, 132px);
  bottom: clamp(48px, 7vh, 86px);
  z-index: 9998;
  padding: 10px 18px;
  border-radius: 999px 999px 4px 999px;       /* coin bas-droit qui pointe vers la flamme */
  background: linear-gradient(135deg, #fff8e0, #ffd75c);
  color: #1a0010;
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
  font-weight: 700;
  font-size: clamp(0.95rem, 2.2vw, 1.2rem);
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.45),
    0 0 32px rgba(255, 200, 60, 0.55);
  pointer-events: none;
  opacity: 0;
  transform: translateY(8px) scale(0.92);
  animation: cmBubbleIn 1.8s ease-out forwards;
}
@keyframes cmBubbleIn {
  0%   { opacity: 0; transform: translateY(16px) scale(0.7); }
  18%  { opacity: 1; transform: translateY(-4px) scale(1.05); }
  35%  { opacity: 1; transform: translateY(0)    scale(1); }
  78%  { opacity: 1; transform: translateY(-6px) scale(1.02); }
  100% { opacity: 0; transform: translateY(-22px) scale(0.92); }
}

/* Help bubble — bulle interactive « Besoin d'aide ? » avec boutons Oui/Non.
   Plus large que .ds-mascot-bubble, cliquable, reste affichée jusqu'à réponse. */
.ds-help-bubble {
  position: fixed;
  right: clamp(86px, 13vw, 132px);
  /* Au-dessus de la zone des CTA sticky (~100-120px avec safe-area) : la
     bulle recouvrait entièrement « On l'a fait » en paysage sur le Défi du
     jour. Elle reste accrochée visuellement à la mascotte (coin bas-droit). */
  bottom: clamp(104px, 15vh, 150px);
  z-index: 9999;
  padding: 14px 18px 12px;
  border-radius: 18px 18px 4px 18px;
  background: linear-gradient(160deg, rgba(40, 0, 60, 0.96), rgba(20, 0, 30, 0.96));
  border: 1.5px solid color-mix(in srgb, var(--pink-soft, #ff70c7) 60%, transparent);
  color: #fff8fc;
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.6),
    0 0 28px color-mix(in srgb, var(--glow, rgba(255,48,140,0.6)) 60%, transparent);
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
  font-weight: 600;
  font-size: clamp(0.95rem, 2vw, 1.1rem);
  opacity: 0;
  transform: translateY(8px) scale(0.92);
  animation: cmHelpBubbleIn 0.32s cubic-bezier(0.34, 1.55, 0.5, 1) forwards;
}
@keyframes cmHelpBubbleIn {
  0%   { opacity: 0; transform: translateY(12px) scale(0.85); }
  100% { opacity: 1; transform: translateY(0)    scale(1); }
}
.ds-help-bubble.is-closing {
  animation: cmHelpBubbleOut 0.25s ease-out forwards;
}
@keyframes cmHelpBubbleOut {
  0%   { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(8px) scale(0.92); }
}
.ds-help-bubble-text { display: block; margin-bottom: 10px; text-align: center; }
/* Case à cocher optionnelle (ex. « me le rappeler chaque jour »), intégrée
   directement dans la bulle plutôt que d'ouvrir un réglage séparé. */
.ds-help-bubble-check {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 12px; padding: 2px 2px;
  font-family: 'Inter', system-ui, sans-serif; font-style: normal; font-weight: 600;
  font-size: 0.82rem; color: rgba(255, 235, 245, 0.85);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ds-help-bubble-check input[type="checkbox"] {
  width: 18px; height: 18px; flex-shrink: 0; margin: 0;
  accent-color: var(--pink-hot, #ff2e95); cursor: pointer;
}
.ds-help-bubble-actions { display: flex; gap: 8px; justify-content: center; }
.ds-help-bubble-btn {
  font-family: inherit;
  font-style: normal;
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  padding: 6px 16px;
  border-radius: 999px;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: transform 0.18s cubic-bezier(0.34, 1.55, 0.5, 1);
}
.ds-help-bubble-btn--yes {
  background: linear-gradient(135deg, var(--pink-hot, #ff2e95), var(--pink, #ff3d8e));
  color: #fff;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--glow, rgba(255,48,140,0.5)) 65%, transparent);
}
.ds-help-bubble-btn--no {
  background: rgba(255, 255, 255, 0.06);
  color: rgba(220, 195, 225, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.14);
}
.ds-help-bubble-btn:active { transform: scale(0.94); }

/* Jumping — tap easter egg */
.ds-mascot.is-jumping,
.cards-mascot.is-jumping {
  animation: cmJump 0.7s cubic-bezier(0.34, 1.55, 0.5, 1);
}
@keyframes cmJump {
  0%   { transform: scale(var(--cm-scale, 1))            translateY(0); }
  40%  { transform: scale(calc(var(--cm-scale, 1) * 1.2)) translateY(-18px); }
  70%  { transform: scale(calc(var(--cm-scale, 1) * 0.95)) translateY(2px); }
  100% { transform: scale(var(--cm-scale, 1))            translateY(0); }
}

/* Réduction des animations si l'utilisateur a activé le réglage iOS */
@media (prefers-reduced-motion: reduce) {
  .ds-mascot svg,
  .cards-mascot svg { animation: none !important; }
  .ds-mascot.is-happy,
  .ds-mascot.is-drawing,
  .ds-mascot.is-curious svg,
  .ds-mascot.is-jumping,
  .cards-mascot.is-happy,
  .cards-mascot.is-drawing,
  .cards-mascot.is-curious svg,
  .cards-mascot.is-jumping { animation: none !important; }
}
