/* ============================================================
   La mascotte — styles et animations.

   Tout est en CSS : aucune image, aucun canvas, aucune boucle JS. Le
   navigateur anime sur le compositeur (transform/opacity uniquement),
   donc ça ne coûte rien à la batterie même en boucle infinie.

   Réglages honorés :
   · prefers-reduced-motion → toutes les boucles s'arrêtent, la mascotte
     reste dessinée et lisible (elle n'est jamais porteuse d'info seule)
   · safe-area iOS → elle se pose au-dessus de la barre d'onglets, jamais
     sous le geste de retour à l'accueil
   ============================================================ */

.mascotte {
  --masc-clair: #35506e;
  --masc-fonce: #22364c;
  --masc-trait: #9fb6cf;
  --masc-accent: var(--en, #5590ff);

  position: fixed;
  /* 72 px = hauteur de la barre d'onglets ; +10 pour ne pas la toucher */
  bottom: calc(72px + 10px + env(safe-area-inset-bottom));
  right: 10px;
  z-index: 15;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none; /* la page reste cliquable derrière */
}

.mascotte.costume-prof { --masc-accent: var(--ar, #2ec48e); }
.mascotte.costume-ceo {
  --masc-clair: #3d4d63;
  --masc-fonce: #26313f;
  --masc-accent: #f0993f;
}

.masc-perso {
  pointer-events: auto; /* … sauf le personnage lui-même */
  appearance: none;
  border: 0;
  padding: 0;
  margin: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
}

.masc-svg {
  width: 78px;
  height: 85px;
  overflow: visible;
  display: block;
}

/* Variante « ancrée » : la mascotte se pose juste au-dessus de son
   conteneur (qui doit être en position: relative). Utilisée par l'app
   CEO, dont le bas d'écran porte une barre de saisie à hauteur variable
   — un décalage fixe en pixels y recouvrirait le bouton d'envoi. */
.mascotte.ancree {
  position: absolute;
  bottom: 100%;
  right: 10px;
  margin-bottom: 4px;
}

/* Sur un écran large on peut se permettre un personnage plus présent. */
@media (min-width: 760px) {
  .masc-svg { width: 96px; height: 104px; }
  .mascotte { right: 20px; bottom: calc(20px + env(safe-area-inset-bottom)); }
  .mascotte.ancree { right: 20px; bottom: 100%; }
}

/* ---------- Traits communs ---------- */

/* Les transform-origin sont en unités du viewBox (120×130), pas en % :
   sur un <ellipse> ou un <path> SVG, un origin en pourcentage se calcule
   sur la boîte englobante de la FORME, qui diffère d'un état à l'autre.
   En coordonnées absolues, le pivot reste où on l'a mis. */
.masc-ombre {
  fill: rgba(0, 0, 0, 0.42);
  transform-origin: 60px 122px;
  transition: transform 220ms ease-out, opacity 220ms ease-out;
}
.masc-bouche { transform-origin: 60px 67px; }
.masc-sourcil-g { transform-origin: 49px 41px; }
.masc-sourcil-d { transform-origin: 71px 41px; }
.masc-joue { transform-origin: 60px 61px; }

.masc-bras,
.masc-yeux-fermes path,
.masc-sourcil,
.masc-bouche,
.masc-lunettes path,
.masc-livre path,
.masc-tablette path,
.masc-casque-nervure {
  fill: none;
  stroke: var(--masc-trait);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.masc-oeil { fill: #0d141d; }
.masc-reflet { fill: #ffffff; opacity: 0.9; }
.masc-crane,
.masc-buste { stroke: rgba(255, 255, 255, 0.1); stroke-width: 1.5; }

.masc-lunettes circle {
  fill: rgba(180, 220, 255, 0.09);
  stroke: var(--masc-accent);
  stroke-width: 2.4;
}
.masc-lunettes path { stroke: var(--masc-accent); }

.masc-toupet { fill: var(--masc-trait); opacity: 0.75; }

.masc-casque { fill: var(--masc-accent); }
.masc-casque-bord { fill: var(--masc-accent); }
.masc-casque-nervure { stroke: rgba(0, 0, 0, 0.28); }

.masc-livre rect,
.masc-tablette rect {
  fill: var(--masc-accent);
  opacity: 0.92;
}
.masc-livre path,
.masc-tablette path { stroke: rgba(0, 0, 0, 0.4); stroke-width: 1.8; }

.masc-joue {
  fill: var(--masc-accent);
  opacity: 0;
  transition: opacity 200ms ease-out;
}

.masc-yeux-fermes { opacity: 0; }
.masc-pense { opacity: 0; }
.masc-pense circle { fill: var(--masc-accent); }

.masc-corps,
.masc-tete,
.masc-bouche,
.masc-sourcil {
  transition: transform 260ms cubic-bezier(0.34, 1.4, 0.64, 1);
}
.masc-corps { transform-origin: 60px 120px; }
.masc-tete { transform-origin: 60px 78px; }

/* ---------- État : repos ---------- */
/* Deux boucles indépendantes : la respiration (lente, continue) et le
   clignement (rare, sec). Les mélanger dans une seule animation donne un
   personnage qui cligne au rythme de sa respiration — mécanique. */

.etat-repos .masc-corps { animation: masc-respire 3.6s ease-in-out infinite; }
.etat-repos .masc-tete { animation: masc-regarde 9s ease-in-out infinite; }
.etat-repos .masc-yeux-ouverts { animation: masc-cligne 6.2s infinite; }

@keyframes masc-respire {
  0%, 100% { transform: translateY(0) scaleY(1); }
  50% { transform: translateY(-1.6px) scaleY(1.018); }
}

@keyframes masc-regarde {
  0%, 44%, 100% { transform: rotate(0deg); }
  55% { transform: rotate(-4.5deg); }
  72% { transform: rotate(3.5deg); }
}

@keyframes masc-cligne {
  0%, 94%, 100% { opacity: 1; }
  96%, 98% { opacity: 0; }
}

/* Les paupières fermées suivent le même rythme, en négatif. */
.etat-repos .masc-yeux-fermes { animation: masc-cligne-inverse 6.2s infinite; }
@keyframes masc-cligne-inverse {
  0%, 94%, 100% { opacity: 0; }
  96%, 98% { opacity: 1; }
}

/* ---------- État : réfléchit ---------- */

.etat-reflechit .masc-tete { transform: rotate(-9deg) translateY(-2px); }
.etat-reflechit .masc-corps { animation: masc-respire 2.4s ease-in-out infinite; }
.etat-reflechit .masc-sourcil-g { transform: translateY(-2.5px) rotate(-6deg); }
.etat-reflechit .masc-sourcil-d { transform: translateY(1px); }
/* Bouche pincée. On l'obtient par transform et NON par la propriété CSS
   `d` : `d` n'est animable que depuis Safari 17.4, et l'app tourne sur
   des iPhone plus anciens — la mascotte y garderait une bouche souriante
   en pleine réflexion. */
.etat-reflechit .masc-bouche { transform: scaleX(0.72) scaleY(0.35) translateY(-2px); }
.etat-reflechit .masc-pense { opacity: 1; }
.etat-reflechit .masc-pense circle { animation: masc-pense-pulse 1.5s ease-in-out infinite; }
.etat-reflechit .masc-pense circle:nth-child(2) { animation-delay: 0.22s; }
.etat-reflechit .masc-pense circle:nth-child(3) { animation-delay: 0.44s; }

@keyframes masc-pense-pulse {
  0%, 100% { opacity: 0.25; transform: translateY(0); }
  50% { opacity: 1; transform: translateY(-2.5px); }
}

/* ---------- État : parle ---------- */

.etat-parle .masc-corps { animation: masc-respire 3s ease-in-out infinite; }
.etat-parle .masc-bouche { animation: masc-parle 420ms ease-in-out infinite alternate; }

@keyframes masc-parle {
  from { transform: scaleY(0.55) translateY(1px); }
  to { transform: scaleY(1.5) translateY(-1px); }
}

/* ---------- État : content ---------- */

.etat-content .masc-corps { animation: masc-saute 620ms cubic-bezier(0.28, 1.6, 0.5, 1) 2; }
.etat-content .masc-yeux-ouverts { opacity: 0; }
.etat-content .masc-yeux-fermes { opacity: 1; }
.etat-content .masc-joue { opacity: 0.55; }
.etat-content .masc-bouche { transform: scaleX(1.18) scaleY(1.5); }
.etat-content .masc-sourcil-g { transform: translateY(-3px) rotate(-8deg); }
.etat-content .masc-sourcil-d { transform: translateY(-3px) rotate(8deg); }
/* On rétrécit l'ombre par transform, pas via l'attribut `rx` : `rx` en
   CSS n'est pas animable partout et ne l'est pas du tout sur iOS < 16. */
.etat-content .masc-ombre { transform: scaleX(0.78); opacity: 0.5; }

@keyframes masc-saute {
  0% { transform: translateY(0) scaleY(1); }
  28% { transform: translateY(-11px) scaleY(1.06); }
  60% { transform: translateY(0) scaleY(0.94); }
  100% { transform: translateY(0) scaleY(1); }
}

/* ---------- État : rate ---------- */
/* Affaissement + regard de côté. Aucune moue, aucun sourcil froncé :
   l'erreur n'est pas un reproche, c'est la matière du cours suivant. */

.etat-rate .masc-corps { transform: translateY(3px) scaleY(0.965); }
.etat-rate .masc-tete { transform: rotate(7deg) translateY(2px); }
.etat-rate .masc-bouche { transform: scaleY(-0.85) translateY(-7px); }
.etat-rate .masc-sourcil-g { transform: translateY(1.5px) rotate(7deg); }
.etat-rate .masc-sourcil-d { transform: translateY(1.5px) rotate(-7deg); }

/* ---------- État : dort ---------- */

.etat-dort .masc-yeux-ouverts { opacity: 0; }
.etat-dort .masc-yeux-fermes { opacity: 1; }
.etat-dort .masc-tete { transform: rotate(11deg) translateY(3px); }
.etat-dort .masc-corps { animation: masc-respire 5.2s ease-in-out infinite; }

/* ---------- La bulle ---------- */

.masc-bulle {
  /* La bulle flotte au-dessus du contenu, y compris au-dessus du bouton
     principal d'une carte. Elle NE DOIT PAS intercepter le tap : elle
     disparaît d'elle-même, alors qu'un bouton bloqué est un bug. */
  pointer-events: none;
  max-width: min(58vw, 300px);
  margin-bottom: 22px;
  padding: 10px 13px;
  background: var(--carte-2, #1c2836);
  border: 1px solid var(--bord-clair, #33445a);
  border-radius: 14px 14px 4px 14px;
  box-shadow: var(--ombre, 0 8px 28px rgba(0, 0, 0, 0.45));
  font-size: 14px;
  line-height: 1.45;
  color: var(--texte, #e9eff6);
  opacity: 0;
  transform: translateY(6px) scale(0.96);
  transform-origin: bottom right;
  transition: opacity 200ms ease-out, transform 220ms cubic-bezier(0.34, 1.4, 0.64, 1);
}

.masc-bulle.visible { opacity: 1; transform: translateY(0) scale(1); }

/* ---------- Moins d'animations ---------- */

@media (prefers-reduced-motion: reduce) {
  .mascotte * { animation: none !important; }
  .masc-bulle { transition: opacity 120ms linear; transform: none; }
  .masc-bulle.visible { transform: none; }
}

/* Aucune règle sur `body` ici, volontairement : ce fichier est partagé
   par deux apps aux mises en page opposées. L'app prof défile dans le
   corps et doit gagner de la marge basse pour que la mascotte flottante
   ne recouvre pas son dernier bouton — c'est fait dans son style.css.
   L'app CEO est une colonne flex à hauteur fixe (`overflow: hidden`) :
   une marge basse y casserait la mise en page, et sa mascotte est ancrée
   au composeur, donc dans le flux. */
