/*
  DA du jeu — registre de la référence donnée : Block Blast.

  Fond profond bleu-violet, cases vides franchement lisibles, blocs
  saturés et brillants avec un vrai volume, score blanc énorme.
  On reprend le REGISTRE VISUEL d'un puzzle de blocs pour enfant, jamais
  le nom, le logo ni les assets : l'identité reste celle de ce studio.

  Le volume des blocs est la clé : face du dessus éclairée, flancs,
  arête basse dans l'ombre, reflet franc. Un carré coloré à plat, c'est
  ce qui fait « maquette » au lieu de « jeu ».
*/

@font-face {
  font-family: "Archivo";
  src: url("./fonts/archivo-latin-600-normal.woff2") format("woff2");
  font-weight: 600;
  font-display: block;
}
@font-face {
  font-family: "Archivo";
  src: url("./fonts/archivo-latin-800-normal.woff2") format("woff2");
  font-weight: 800;
  font-display: block;
}
@font-face {
  font-family: "Archivo";
  src: url("./fonts/archivo-latin-900-normal.woff2") format("woff2");
  font-weight: 900;
  font-display: block;
}

/* La typo d'affiche du jeu. Une grotesque de texte ne fera jamais un logo
   de jeu, quelle que soit la graisse : il faut des pleins ronds et des
   contreformes fermées. Six familles libres (OFL) sont dans fonts/, il
   suffit de changer le nom dans --typo-titre pour en essayer une autre.
   Licences OFL déposées dans le même dossier. */
@font-face {
  font-family: "Titan One";
  src: url("./fonts/titan-one-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: "Luckiest Guy";
  src: url("./fonts/luckiest-guy.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: "Chewy";
  src: url("./fonts/chewy.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: "Bungee";
  src: url("./fonts/bungee.woff2") format("woff2");
  font-weight: 400;
  font-display: block;
}
@font-face {
  font-family: "Fredoka";
  src: url("./fonts/fredoka-600.woff2") format("woff2");
  font-weight: 600;
  font-display: block;
}

/* Baloo 2 : les grands chiffres. Ronde, lisible de loin, faite pour être
   grosse. Licence OFL, dans fonts/. */
@font-face {
  font-family: "Baloo 2";
  src: url("./fonts/baloo2-latin-800.woff2") format("woff2");
  font-weight: 800;
  font-display: block;
}

:root {
  /* Toutes ces valeurs sont RELEVÉES AU PIXEL sur la référence donnée
     (capture 886x1920, image de la vidéo de présentation), pas estimées :
     fond, plateau, case vide, et les sept teintes prises au centre de la
     face d'un bloc. */
  --fond-haut: #4757AF;
  --fond-bas: #566FC1;
  --plateau-fond: #1D2447;
  --plateau-case: #242A55;
  --plateau-bord: #12162E;
  --plateau-trait: #2E3765;
  --blanc: #FFFFFF;
  --texte-doux: #C3CCF2;

  --rouge: #E8443C;
  --orange: #F0602F;
  --jaune: #F7BD2C;
  --vert: #28B93B;
  --cyan: #2EC0EE;
  --bleu: #4565F0;
  --violet: #9057E2;

  /* Le bloc de la référence est un cube extrudé, presque carré : le rayon
     vaut 7 % de la case, pas un galet arrondi. */
  /* Un seul endroit pour changer la typo du titre : ici. */
  --typo-titre: "Luckiest Guy", "Titan One", sans-serif;

  --r-bloc: 7%;
  --r-panneau: 10px;
  /* Relevé : le plateau occupe 89,8 % de la largeur, une case 11,23 %. */
  --plateau: min(89.8vw, 430px, 46vh);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

body {
  /* Fond de la référence : un bleu-violet PLAT qui s'éclaircit vers le bas,
     avec un halo doux derrière le plateau. Pas de dégradé spectaculaire :
     c'est le calme du fond qui fait ressortir les blocs. */
  background:
    radial-gradient(120% 55% at 50% 34%, rgba(255, 255, 255, 0.10), transparent 70%),
    linear-gradient(180deg, var(--fond-haut) 0%, var(--fond-bas) 100%);
  /* Le vert du bas de l'herbe, mesuré au pixel sur le calque : la zone
     système du bas de l'iPhone se fond dans la prairie au lieu de la
     couper d'une bande de couleur étrangère. Pas d'accroche fixe du fond :
     iOS la repeint en saccades dès que le décor bouge, et la page ne
     défile pas de toute façon. */
  background-color: rgb(32, 64, 34);
  color: var(--blanc);
  font-family: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-weight: 600;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  /* La marge d'écran (encoche, barre du bas) est gérée PAR CHAQUE PAGE,
     jamais ici : appliquée aussi sur le corps, elle se cumulait et
     poussait la barre du bas hors de l'écran sur téléphone. */
  padding: 0;
  touch-action: none;
  overflow: hidden;
}

button {
  font-family: inherit;
  border: none;
  cursor: pointer;
  background: none;
  color: inherit;
}

/* ---------- En-tête ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* L'écran de jeu gère sa marge d'encoche LUI-MÊME, comme les autres
     pages : sans elle, le logo passait sous la caméra frontale et le
     bouton retour devenait intouchable sur iPhone. */
  padding: calc(14px + env(safe-area-inset-top)) 18px 0;
  flex-shrink: 0;
}

.topbar-logo {
  height: 54px;
  width: auto;
  filter: drop-shadow(0 3px 6px rgba(10, 8, 32, 0.5));
  -webkit-user-drag: none;
}

.icon-btn {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.16);
  border-bottom: 4px solid rgba(0, 0, 0, 0.22);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.1s ease, border-width 0.1s ease;
}

.icon-btn:active {
  transform: translateY(3px);
  border-bottom-width: 1px;
}

.icon-btn svg {
  width: 24px;
  height: 24px;
  color: var(--blanc);
}

.icon-badge {
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 23px;
  height: 23px;
  padding: 0 6px;
  border-radius: 12px;
  background: var(--vert);
  color: #05341C;
  font-size: 12px;
  font-weight: 900;
  line-height: 23px;
  text-align: center;
  border: 3px solid #3A2A8C;
}

/* ---------- Score ---------- */

/* Le score de la référence est ÉNORME, blanc, centré, sans cadre : c'est le
   seul chiffre de l'écran et il occupe 13 % de la largeur en hauteur de
   glyphe. Le record vit en haut à gauche derrière une couronne. */
.scoreboard {
  position: relative;
  flex: 0 0 auto;
  min-height: 86px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  padding: 2px 0 8px;
}

.score-value {
  position: relative;
  z-index: 2;
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: clamp(46px, 13.5vw, 72px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  text-shadow:
    0 3px 0 rgba(24, 30, 76, 0.35),
    0 6px 14px rgba(14, 18, 56, 0.4);
}

.score-value.bump { animation: bump 0.28s ease; }

/* La série vivante : une pastille dorée sous le score, typographique,
   qui pulse au rythme de la série. L'ancien coeur dessiné en CSS est
   retiré : un visuel fabriqué à la main n'a pas sa place ici. */
.serie-pastille {
  align-self: center;
  margin-top: 4px;
  padding: 3px 13px 4px;
  border-radius: 999px;
  background: linear-gradient(180deg, #FFD95C, #F7A928);
  border-bottom: 3px solid #C07C10;
  color: #5A3A00;
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: 14px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  animation: serie-pulse 1.1s ease-in-out infinite;
}

.serie-pastille.hidden { display: none; }

@keyframes serie-pulse {
  0%, 100% { transform: scale(1); }
  18% { transform: scale(1.12); }
  36% { transform: scale(1.02); }
}

/* Record : couronne dorée, chiffre doré, en haut à gauche. */
/* La couronne du record : sur pastille sombre, jamais à nu sur les nuages
   clairs du décor, sinon elle disparaît sur téléphone. */
.score-sub {
  display: inline-flex;
  align-self: center;
  align-items: center;
  gap: 7px;
  margin-top: 6px;
  padding: 4px 14px 5px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.6);
  font-size: 16px;
  font-weight: 900;
  color: #FFC426;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 0 rgba(24, 30, 76, 0.3);
}

.score-sub svg { width: 22px; height: 17px; color: #FFC426; }

@keyframes bump {
  0% { transform: scale(1); }
  40% { transform: scale(1.14); }
  100% { transform: scale(1); }
}

/* ---- PASTILLE DE LA CRÉATURE ----
   Elle reste en haut à droite pendant toute la partie. L'anneau se remplit
   au fil des pièces gagnées, la créature se révèle par le bas à l'intérieur.
   C'est le rappel permanent de POURQUOI on joue. */
.pastille-creature {
  position: relative;
  width: 60px;
  height: 60px;
  flex-shrink: 0;
  border-radius: 50%;
  padding: 0;
  transition: transform 0.14s cubic-bezier(0.2, 1.5, 0.4, 1);
}

.pastille-creature:active { transform: scale(0.93); }

.pastille-anneau {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(#FFD02E var(--part, 0deg), rgba(255, 255, 255, 0.16) var(--part, 0deg));
  transition: background 0.5s ease;
}

.pastille-anneau::after {
  content: "";
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: #221A4E;
}

.pastille-anneau.pleine { animation: anneau-plein 1.2s ease-in-out infinite; }

@keyframes anneau-plein {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 208, 46, 0.6); }
  50% { box-shadow: 0 0 0 7px rgba(255, 208, 46, 0); }
}

.pastille-visuel {
  position: absolute;
  inset: 7px;
  display: block;
  border-radius: 50%;
  overflow: hidden;
}

.pastille-visuel .cec-pile { position: relative; width: 100%; height: 100%; }

.pastille-visuel img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.pastille-visuel .cec-ombre { filter: brightness(0) invert(1); opacity: 0.2; }

.pastille-visuel .cec-vraie {
  transition: clip-path 0.55s cubic-bezier(0.3, 1.2, 0.4, 1);
  animation: souffle 3.7s ease-in-out infinite;
}

.pastille-part {
  position: absolute;
  left: 50%;
  bottom: -7px;
  transform: translateX(-50%);
  padding: 1px 7px 2px;
  border-radius: 999px;
  background: #221A4E;
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  font-size: 10.5px;
  font-weight: 900;
  color: #FFD02E;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- BANDEAU DE COMBO ----
   Sur la référence, chaque rangée effacée pose une bannière en travers du
   plateau : « Combo » en blanc italique, le numéro en couleur, et le gain
   à gauche. La couleur tourne avec le rang du combo. */
.bandeau-combo {
  position: absolute;
  z-index: 8;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  pointer-events: none;
  animation: combo-entre 0.9s cubic-bezier(0.2, 1.4, 0.4, 1) forwards;
}

.bandeau-combo::before {
  content: "";
  position: absolute;
  left: -4%;
  right: -4%;
  height: 74%;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--teinte-combo, #4565F0) 18%, var(--teinte-combo, #4565F0) 82%, transparent);
  opacity: 0.5;
  filter: blur(3px);
}

.combo-gain {
  position: relative;
  font-size: 15px;
  font-weight: 900;
  color: #FFFFFF;
  text-shadow: 0 2px 3px rgba(0, 0, 0, 0.6);
  font-variant-numeric: tabular-nums;
}

.combo-mot {
  position: relative;
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: clamp(21px, 6vw, 30px);
  font-weight: 800;
  font-style: italic;
  letter-spacing: -0.02em;
  color: #FFFFFF;
  -webkit-text-stroke: 3px rgba(18, 24, 66, 0.75);
  paint-order: stroke fill;
  text-shadow: 0 3px 4px rgba(0, 0, 0, 0.5);
}

.combo-nb {
  position: relative;
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: clamp(25px, 7.4vw, 36px);
  font-weight: 800;
  font-style: italic;
  color: #FFD02E;
  -webkit-text-stroke: 3px rgba(18, 24, 66, 0.75);
  paint-order: stroke fill;
  text-shadow: 0 3px 4px rgba(0, 0, 0, 0.5);
  font-variant-numeric: tabular-nums;
}

@keyframes combo-entre {
  0% { opacity: 0; transform: scale(0.55); }
  22% { opacity: 1; transform: scale(1.12); }
  34% { transform: scale(1); }
  76% { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(1) translateY(-22px); }
}

/* Le mot d'encouragement : Bien ! puis Super ! puis Excellent ! puis
   Incroyable ! Il monte et s'efface, comme sur le modèle. */
.mot-bravo {
  position: absolute;
  z-index: 9;
  pointer-events: none;
  font-size: clamp(18px, 5.4vw, 26px);
  font-weight: 900;
  font-style: italic;
  white-space: nowrap;
  -webkit-text-stroke: 3px rgba(18, 24, 66, 0.7);
  paint-order: stroke fill;
  text-shadow: 0 3px 5px rgba(0, 0, 0, 0.45);
  animation: bravo-monte 1s ease-out forwards;
}

@keyframes bravo-monte {
  0% { opacity: 0; transform: translate(-50%, 8px) scale(0.7); }
  20% { opacity: 1; transform: translate(-50%, 0) scale(1.08); }
  32% { transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -46px) scale(1); }
}

/* ---------- Défi du jour ---------- */

/* Fond sombre franc : le bandeau passe devant les nuages clairs du décor,
   à 22 % d'opacité il devenait illisible sur téléphone. Le sélecteur double
   bat le verre clair générique, qui repeignait le bandeau en blanc. */
.defi.verre,
.defi {
  flex-shrink: 0;
  width: var(--plateau);
  margin: 0 auto 8px;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(12, 8, 32, 0.62);
  border-radius: 12px;
}

.defi-etiquette {
  font-size: 12px;
  font-weight: 900;
  color: var(--jaune);
  flex-shrink: 0;
}

.defi-texte {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 800;
  color: var(--blanc);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.defi-compte {
  font-size: 15px;
  font-weight: 900;
  color: var(--blanc);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.defi.defi-reussi {
  background: rgba(47, 208, 123, 0.24);
  box-shadow: inset 0 0 0 2px rgba(47, 208, 123, 0.6);
}

.defi.defi-reussi .defi-compte { color: var(--vert); }

/* ---------- Progression vers la prochaine créature ----------
   Huit encoches, une par pièce : un enfant compte ce qui lui reste,
   une barre continue ne se compte pas. */

.monster-progress {
  flex-shrink: 0;
  width: var(--plateau);
  margin: 0 auto 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.monster-progress-label {
  font-size: 13px;
  font-weight: 800;
  color: var(--texte-doux);
  flex-shrink: 0;
}

.progress-track {
  flex: 1;
  display: flex;
  gap: 5px;
}

.progress-notch {
  flex: 1;
  height: 11px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.25);
  transition: background 0.25s ease;
}

.progress-notch.on {
  background: linear-gradient(180deg, #FFE486, var(--jaune));
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.75), 0 2px 0 rgba(150, 100, 0, 0.5);
}

.monster-progress.bump .progress-notch.on { animation: encoche 0.32s ease; }

@keyframes encoche {
  0% { transform: scaleY(1); }
  45% { transform: scaleY(1.7); }
  100% { transform: scaleY(1); }
}

/* La page de jeu vit dans le monde en calques, comme toutes les autres.
   Le plateau opaque et sombre porte seul la lisibilité. Les poussières
   d'or restent, posées par le jeu. */
.page-jeu { position: relative; overflow: hidden; }

.jeu-poussiere { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

.grain {
  position: absolute;
  border-radius: 1px;
  background: rgba(255, 226, 150, 0.85);
  box-shadow: 0 0 6px rgba(255, 214, 120, 0.7);
  animation: grain-monte var(--t) linear infinite;
  animation-delay: var(--d);
}

@keyframes grain-monte {
  0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: 0; }
  12% { opacity: 0.9; }
  80% { opacity: 0.55; }
  100% { transform: translateY(-72vh) translateX(var(--dx)) rotate(220deg); opacity: 0; }
}

/* Tout le jeu passe au-dessus du décor. */
.page-jeu .topbar,
.page-jeu .scoreboard,
.page-jeu .defi,
.page-jeu .stage { position: relative; z-index: 2; }

/* ---------- Plateau ---------- */

.stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* La ligne du © occupe le tout bas de l'écran : le plateau et ses
     boutons s'arrêtent au-dessus d'elle au lieu de la chevaucher. */
  padding: 0 12px calc(30px + env(safe-area-inset-bottom, 0px));
  gap: 20px;
  min-height: 0;
}

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  gap: 0;
  width: var(--plateau);
  aspect-ratio: 1 / 1;
  padding: 0;
  background: var(--plateau-fond);
  border: 2px solid var(--plateau-bord);
  border-radius: 3px;
  box-shadow: 0 10px 26px rgba(10, 14, 40, 0.42);
}

/* Le plateau de la référence n'a pas d'écart entre les cases : il a un
   trait de séparation fin et sombre. Les blocs sont donc jointifs, ce qui
   fait lire une ligne pleine comme une barre continue. */
.cell {
  position: relative;
  box-shadow: inset -1px -1px 0 rgba(255, 255, 255, 0.045);
}

.cell-block {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--r-bloc);
  opacity: 0;
}

/* ---- LA MATIÈRE DU BLOC ----
   Mesurée au pixel sur la référence, en fractions de la case :
     face du dessus, très claire ....... 15 % de la hauteur
     arête basse, très sombre .......... 14 % de la hauteur
     flanc gauche, légèrement clair .... 10 % de la largeur
     flanc droit, légèrement sombre .... 10 % de la largeur
     face principale ................... dégradé vertical, haut 8 % plus clair
   L'ordre des couches compte : dessus et arête basse passent PAR-DESSUS les
   flancs, exactement comme sur le modèle. Aucun reflet en pastille : la
   référence n'en a pas, c'est ça qui faisait bonbon. */
.cell.filled .cell-block,
.cell.preview-ok .cell-block,
.voxel {
  background-color: var(--c, var(--violet));
  background-image:
    linear-gradient(to bottom, color-mix(in srgb, var(--c, #9057E2) 38%, #FFFFFF) 0 15%, rgba(0, 0, 0, 0) 15%),
    linear-gradient(to top,    color-mix(in srgb, var(--c, #9057E2) 62%, #08040F) 0 14%, rgba(0, 0, 0, 0) 14%),
    linear-gradient(to right,  color-mix(in srgb, var(--c, #9057E2) 89%, #FFFFFF) 0 10%, rgba(0, 0, 0, 0) 10%),
    linear-gradient(to left,   color-mix(in srgb, var(--c, #9057E2) 86%, #08040F) 0 10%, rgba(0, 0, 0, 0) 10%),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.07), rgba(0, 0, 0, 0.09));
}

.cell.filled .cell-block {
  opacity: 1;
  animation: pose 0.16s cubic-bezier(0.2, 1.6, 0.5, 1);
}

@keyframes pose {
  0% { transform: translateY(-7px) scale(0.84); opacity: 0.35; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

/* L'aperçu de pose : la pièce apparaît EN FANTÔME DE SA COULEUR dans les
   cases visées — un vrai bloc à moitié transparent, pas une case à peine
   éclaircie. L'enfant voit exactement où elle va tomber. */
.cell.preview-ok { background: rgba(255, 255, 255, 0.1); }

.cell.preview-ok .cell-block {
  opacity: 0.55;
}

.cell.preview-bad { background: rgba(255, 90, 110, 0.22); }

/* La ligne qui va sauter s'annonce par-dessus les blocs déjà posés,
   sinon le repère est masqué là où il sert le plus. */
.cell.preview-line::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: rgba(255, 255, 255, 0.4);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.95);
  animation: annonce-ligne 0.7s ease-in-out infinite;
}

@keyframes annonce-ligne {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

/* La case qui saute s'éclaire à blanc puis se rétracte : sur la référence
   elle éclate, elle ne disparaît pas. Les éclats sont ajoutés par le jeu. */
.cell.clearing .cell-block {
  animation: casse 0.34s cubic-bezier(0.3, 0, 0.6, 1) forwards;
}

@keyframes casse {
  0% { transform: scale(1); }
  26% { transform: scale(1.16); filter: brightness(2.4) saturate(0.5); }
  100% { transform: scale(0.15) rotate(12deg); opacity: 0; filter: brightness(2.4); }
}

/* ---- ÉCLATS ----
   Une ligne qui saute se pulvérise en petits cubes qui partent en l'air.
   C'est le retour le plus fort du modèle : sans lui, effacer ne récompense
   pas. Les éclats sont posés au-dessus du plateau et se suppriment seuls. */
.eclat {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  border-radius: 1px;
  will-change: transform, opacity;
  animation: eclat-vole var(--d, 620ms) cubic-bezier(0.15, 0.6, 0.4, 1) forwards;
}

@keyframes eclat-vole {
  0% { transform: translate(0, 0) scale(1) rotate(0deg); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(0.2) rotate(var(--rot)); opacity: 0; }
}

/* ---- FAISCEAU ----
   La rangée effacée est balayée par un trait de lumière sur toute sa
   longueur, comme sur le modèle. */
.faisceau {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.85), transparent);
  animation: faisceau-passe 0.42s ease-out forwards;
}

.faisceau.vertical {
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.85), transparent);
}

@keyframes faisceau-passe {
  0% { opacity: 0; transform: scale(0.6); }
  35% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.06); }
}

/* ---------- Pièces en attente ---------- */

/* Sur la référence le tiroir n'est pas un panneau : les trois pièces
   flottent sur le fond, largement espacées, avec beaucoup de vide entre le
   plateau et elles. C'est ce vide qui rend le jeu lisible. */
.tray,
.tray.verre {
  display: flex;
  justify-content: space-around;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 460px;
  min-height: 108px;
  flex-shrink: 0;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.tray-slot {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 96px;
}

.tray-piece {
  display: grid;
  touch-action: none;
  cursor: grab;
  filter: drop-shadow(0 5px 6px rgba(8, 12, 40, 0.4));
  transition: opacity 0.12s ease, transform 0.16s ease;
}

.tray-piece.dragging { opacity: 0.14; }
.tray-piece.used { visibility: hidden; }

/* Pièce neuve : un éclat court à l'arrivée, comme sur le modèle. */
.tray-piece.neuve { animation: piece-arrive 0.34s cubic-bezier(0.2, 1.5, 0.4, 1); }

@keyframes piece-arrive {
  0% { transform: scale(0.5); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

.voxel {
  position: relative;
  border-radius: var(--r-bloc);
}

/* ---- PIÈCE QUI NE RENTRE PLUS ----
   Le modèle la vide : il n'en reste que le contour lumineux. L'enfant voit
   immédiatement laquelle est morte, sans avoir à essayer. */
.tray-piece.impossible { filter: none; }

.tray-piece.impossible .voxel {
  background: rgba(255, 255, 255, 0.04);
  background-image: none;
  box-shadow:
    inset 0 0 0 2px color-mix(in srgb, var(--c, #2EC0EE) 80%, #FFFFFF),
    0 0 10px color-mix(in srgb, var(--c, #2EC0EE) 60%, transparent);
  animation: pulse-morte 1.6s ease-in-out infinite;
}

@keyframes pulse-morte {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

.drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 50;
  display: grid;
  filter: drop-shadow(0 12px 10px rgba(0, 0, 0, 0.35));
}

/* ---------- Boosters ----------
   Gagnés en jouant. Grisés quand le stock est vide : l'enfant voit ce qu'il
   pourrait avoir, ce qui donne envie de continuer. */

.boosters {
  display: flex;
  justify-content: center;
  gap: 14px;
  width: var(--plateau);
  flex-shrink: 0;
  margin-top: -4px;
}

.booster {
  position: relative;
  width: 52px;
  height: 44px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.16);
  border-bottom: 4px solid rgba(0, 0, 0, 0.26);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.1s ease, background 0.15s ease, border-width 0.1s ease;
}

.booster svg {
  width: 24px;
  height: 24px;
  color: var(--blanc);
}

.booster:active { transform: translateY(3px); border-bottom-width: 1px; }

.booster.vide {
  opacity: 0.4;
  pointer-events: none;
}

.booster.arme {
  background: var(--jaune);
  border-bottom-color: #B98200;
}

.booster.arme svg { color: #4A3200; }

.booster-nb {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px;
  background: var(--vert);
  color: #05341C;
  font-size: 11px;
  font-weight: 900;
  line-height: 20px;
  text-align: center;
  border: 2px solid #3A2A8C;
}

.booster.vide .booster-nb { background: rgba(255, 255, 255, 0.3); color: #2A1D6B; }

.booster-aide {
  height: 0;
  overflow: hidden;
  font-size: 13px;
  font-weight: 800;
  color: var(--jaune);
  text-align: center;
  transition: height 0.15s ease;
}

.booster-aide.visible { height: 20px; }

/* Quand un booster est armé, le plateau devient une cible : on coupe le
   glisser-déposer et on montre que le doigt doit désigner une case. */
.board.mode-booster { cursor: crosshair; }
.board.mode-booster .cell { transition: background 0.12s ease; }
.board.mode-booster .cell.filled:hover .cell-block { filter: brightness(1.35); }

.secondary-btn {
  width: 100%;
  margin-top: 9px;
  padding: 12px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.14);
  color: var(--blanc);
  font-size: 15px;
  font-weight: 800;
  transition: transform 0.1s ease;
}

.secondary-btn:active { transform: scale(0.97); }
.primary-btn.hidden, .secondary-btn.hidden { display: none; }

/* ---------- Fenêtres ---------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 12, 55, 0.78);
  z-index: 150;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.modal-overlay.hidden { display: none; }

.modal-card {
  width: 100%;
  max-width: 306px;
  background: var(--panneau);
  border-radius: 26px;
  padding: 26px 22px 22px;
  text-align: center;
  box-shadow: 0 7px 0 var(--panneau-ombre);
}

.modal-card h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 800;
  color: var(--texte-doux);
}

.modal-score {
  font-size: 56px;
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -0.04em;
  margin: 4px 0 16px;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 4px 0 rgba(0, 0, 0, 0.22);
}

.modal-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 20px;
  padding-top: 15px;
  border-top: 2px solid rgba(255, 255, 255, 0.13);
}

.modal-row {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  font-weight: 600;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

.modal-row span:last-child { color: var(--blanc); font-weight: 900; }

.primary-btn {
  width: 100%;
  padding: 15px;
  border-radius: 15px;
  background: linear-gradient(180deg, #5BE89B, var(--vert));
  color: #04351D;
  font-size: 17px;
  font-weight: 900;
  border-bottom: 5px solid #178F51;
  transition: transform 0.1s ease, border-width 0.1s ease;
}

.primary-btn:active { transform: translateY(4px); border-bottom-width: 1px; }

.birth-overlay { z-index: 160; }

.birth-stage {
  height: 158px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin: 14px 0 10px;
}

.birth-figure {
  height: 152px;
  animation: eclosion 0.5s cubic-bezier(0.2, 1.5, 0.4, 1);
}

.birth-figure .creature-svg,
.birth-figure .creature-img { height: 100%; width: auto; }

@keyframes eclosion {
  0% { transform: scale(0.25) translateY(26px); opacity: 0; }
  62% { transform: scale(1.1) translateY(0); opacity: 1; }
  100% { transform: scale(1); }
}

.birth-name {
  font-size: 26px;
  font-weight: 900;
  letter-spacing: -0.03em;
  margin-bottom: 18px;
}

/* ---------- Habitat ----------
   Des étagères, pas une grille de cartes identiques. */

.tracking-overlay {
  position: fixed;
  inset: 0;
  background: linear-gradient(178deg, var(--fond-haut) 0%, var(--fond-bas) 100%);
  z-index: 100;
  display: flex;
  flex-direction: column;
  padding: calc(18px + env(safe-area-inset-top)) 18px calc(18px + env(safe-area-inset-bottom));
}

.tracking-overlay.hidden { display: none; }

.habitat-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
  flex-shrink: 0;
}

.habitat-header h2 {
  font-size: 30px;
  font-weight: 900;
  letter-spacing: -0.035em;
  margin: 0;
}

.habitat-hint {
  margin: 0 0 18px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--texte-doux);
  flex-shrink: 0;
}

.habitat-grid {
  flex: 1;
  overflow-y: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  display: flex;
  flex-direction: column;
}

/* L'habitat est un vrai lieu : une prairie où les créatures vivent. Le voile
   sombre au-dessus de l'image n'est pas décoratif, il sert à ce que les noms
   blancs et les créatures très saturées restent lisibles sur le vert. */
.habitat-overlay {
  background:
    linear-gradient(
      rgba(20, 14, 42, 0.62) 0%,
      rgba(20, 14, 42, 0.2) 16%,
      rgba(20, 14, 42, 0.12) 62%,
      rgba(20, 14, 42, 0.55) 100%
    ),
    url("./decor/prairie.jpg") center / cover no-repeat,
    linear-gradient(178deg, var(--fond-haut) 0%, var(--fond-bas) 100%);
}

.shelf-bloc { margin-bottom: 20px; }

.shelf {
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  gap: 8px;
  padding: 0 6px 6px;
  min-height: 104px;
}

/* Sur une prairie, une étagère en cubes n'a rien à faire : les créatures
   sont posées au sol, avec une ombre de contact qui les y accroche. */
.tablette { display: none; }

.creature-visuel::after {
  content: "";
  position: absolute;
  bottom: -5px;
  left: 50%;
  width: 76%;
  height: 9px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(20, 30, 12, 0.5) 0%, rgba(20, 30, 12, 0) 72%);
  pointer-events: none;
}

.creature-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 6px 8px 2px;
  border-radius: 14px;
  transition: background 0.14s ease, transform 0.14s ease;
}

.creature-slot:active { transform: translateY(-3px); }

.creature-slot.selected {
  background: rgba(255, 255, 255, 0.22);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5);
}

.habitat-header h2,
.habitat-hint {
  text-shadow: 0 2px 6px rgba(12, 8, 24, 0.75);
}

/* ---------- État visible de la créature ----------
   Sale, elle se couvre de taches et se ternit. Affamée, elle pâlit.
   Chaque couche est découpée sur sa propre silhouette par un masque,
   donc l'effet colle à n'importe quelle illustration. */

.creature-visuel {
  position: relative;
  display: flex;
  align-items: flex-end;
  animation: souffle 3.4s ease-in-out infinite;
}

.creature-img {
  height: 100%;
  width: auto;
  display: block;
  transition: filter 0.5s ease;
}

.creature-absente {
  width: 60px;
  height: 100%;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.12);
}

.creature-visuel.affame .creature-img { filter: saturate(0.35) brightness(0.78); }
.creature-visuel.affame { animation-duration: 5.2s; }

.salete,
.mousse,
.reflet {
  position: absolute;
  inset: 0;
  pointer-events: none;
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

.salete {
  opacity: var(--crasse, 0);
  transition: opacity 0.6s ease;
  background:
    radial-gradient(circle at 26% 64%, rgba(72, 48, 20, 0.92) 0 10%, transparent 11%),
    radial-gradient(circle at 63% 41%, rgba(72, 48, 20, 0.86) 0 8%, transparent 9%),
    radial-gradient(circle at 44% 78%, rgba(60, 40, 16, 0.9) 0 12%, transparent 13%),
    radial-gradient(circle at 74% 66%, rgba(72, 48, 20, 0.8) 0 7%, transparent 8%),
    radial-gradient(circle at 36% 30%, rgba(72, 48, 20, 0.7) 0 6%, transparent 7%),
    radial-gradient(circle at 55% 55%, rgba(58, 38, 14, 0.5) 0 30%, transparent 60%);
}

.mousse {
  opacity: 0;
  background: radial-gradient(circle at 50% 60%, rgba(255, 255, 255, 0.95) 0 45%, rgba(255, 255, 255, 0.55) 60%, transparent 75%);
  transition: opacity 0.3s ease;
}

.creature-visuel.savonnee .mousse { opacity: 0.9; }

.reflet {
  opacity: 0;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.95) 48%, transparent 58%);
  background-size: 260% 100%;
  background-position: 130% 0;
}

.creature-visuel.brille .reflet { animation: balayage 0.7s ease-out; }

@keyframes balayage {
  0% { opacity: 0.95; background-position: 130% 0; }
  100% { opacity: 0; background-position: -40% 0; }
}

/* Les temps du repas et du bain. Chaque état a sa posture : elle remarque,
   elle se penche, elle prend une bouchée, elle mâche, elle est rassasiée. */

.creature-visuel.remarque { animation: remarque 0.28s ease-out; }
@keyframes remarque {
  0% { transform: translateY(0) rotate(0deg); }
  55% { transform: translateY(-7px) rotate(-3deg); }
  100% { transform: translateY(0) rotate(0deg); }
}

.creature-visuel.penche {
  animation: none;
  transform: translateY(4px) rotate(4deg);
  transition: transform 0.25s ease;
}

.creature-visuel.bouchee { animation: bouchee 0.2s ease-in-out; }
@keyframes bouchee {
  0% { transform: translateY(4px) rotate(4deg); }
  50% { transform: translateY(13px) rotate(7deg) scaleY(0.94); }
  100% { transform: translateY(4px) rotate(4deg); }
}

.creature-visuel.mache { animation: mache 0.17s ease-in-out 2; }
@keyframes mache {
  0%, 100% { transform: translateY(4px) rotate(4deg) scale(1, 1); }
  50% { transform: translateY(4px) rotate(4deg) scale(1.05, 0.93); }
}

.creature-visuel.rassasie { animation: rassasie 0.5s cubic-bezier(0.2, 1.5, 0.4, 1); }
@keyframes rassasie {
  0% { transform: scale(1, 1); }
  35% { transform: scale(1.12, 0.9) translateY(4px); }
  70% { transform: scale(0.96, 1.08) translateY(-9px); }
  100% { transform: scale(1, 1) translateY(0); }
}

.creature-visuel.sursaute { animation: sursaute 0.18s ease-in-out 2; }
@keyframes sursaute {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px) scale(1.04, 0.95); }
}

.creature-visuel.frotte-gauche { animation: frotte-g 0.23s ease-in-out; }
.creature-visuel.frotte-droite { animation: frotte-d 0.23s ease-in-out; }
@keyframes frotte-g {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(-6deg) translateX(-4px); }
}
@keyframes frotte-d {
  0%, 100% { transform: rotate(0deg); }
  50% { transform: rotate(6deg) translateX(4px); }
}

.creature-visuel.rince { animation: rince 0.35s ease-out; }
@keyframes rince {
  0% { transform: scaleY(1); }
  40% { transform: scaleY(0.95) translateY(3px); }
  100% { transform: scaleY(1); }
}

.creature-visuel.ebroue { animation: ebroue 0.09s ease-in-out 4; }
@keyframes ebroue {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-5px) rotate(-4deg); }
  75% { transform: translateX(5px) rotate(4deg); }
}

/* Le niveau de la gamelle baisse à chaque bouchée. */
.gamelle::before {
  transform: scaleY(var(--niveau, 1));
  transform-origin: bottom;
  transition: transform 0.3s ease;
}

.gamelle.part { animation: gamelle-part 0.32s ease-in forwards; }
@keyframes gamelle-part {
  0% { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(30px); opacity: 0; }
}

.poussiere {
  position: absolute;
  bottom: 4px;
  left: 50%;
  width: 62px;
  height: 12px;
  margin-left: -31px;
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255, 255, 255, 0.5) 0%, transparent 70%);
  animation: poussiere 0.6s ease-out forwards;
}
@keyframes poussiere {
  0% { transform: scale(0.3); opacity: 0.9; }
  100% { transform: scale(1.6); opacity: 0; }
}

.goutte {
  position: absolute;
  top: -6px;
  width: 4px;
  height: 12px;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(180deg, rgba(180, 225, 255, 0.5), #9BD8FF);
  animation: goutte-tombe 0.55s ease-in forwards;
}
.goutte-basse { top: 40%; }
@keyframes goutte-tombe {
  0% { transform: translateY(0); opacity: 0; }
  15% { opacity: 1; }
  100% { transform: translateY(110px); opacity: 0; }
}

.gouttelette {
  position: absolute;
  top: 42%;
  left: 50%;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #BFE6FF;
  animation: gouttelette 0.55s ease-out forwards;
}
@keyframes gouttelette {
  0% { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--dx, 20px), var(--dy, -20px)) scale(0.4); opacity: 0; }
}

.etincelle {
  position: absolute;
  top: 24%;
  width: 10px;
  height: 10px;
  background:
    linear-gradient(90deg, transparent 44%, #FFF3B0 45% 55%, transparent 56%),
    linear-gradient(0deg, transparent 44%, #FFF3B0 45% 55%, transparent 56%);
  animation: etincelle 0.85s ease-out forwards;
}
@keyframes etincelle {
  0% { transform: scale(0) rotate(0deg); opacity: 0; }
  35% { transform: scale(1.3) rotate(45deg); opacity: 1; }
  100% { transform: scale(0.2) rotate(120deg) translateY(-26px); opacity: 0; }
}

/* Les mouches n'apparaissent que quand c'est vraiment sale : c'est le
   signal que l'enfant lit sans qu'on lui explique. */
.mouche {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: #23142e;
  opacity: 0;
  pointer-events: none;
}

.creature-visuel.degoutant .mouche { opacity: 0.9; animation: vole 2.6s ease-in-out infinite; }
.mouche-0 { top: 8%; left: 12%; animation-delay: 0s; }
.mouche-1 { top: 24%; right: 8%; animation-delay: 0.7s; }
.mouche-2 { top: 46%; left: 4%; animation-delay: 1.4s; }

@keyframes vole {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(9px, -7px); }
  50% { transform: translate(-6px, 5px); }
  75% { transform: translate(7px, 6px); }
}

/* ================================================================
   ANIMATION RIGIDE DES CRÉATURES
   ================================================================
   Les Naspionks sont des robots en blocs : des corps DURS. Le découpage
   en tranches les coupait en deux et l'écrasement de dessin animé les
   aplatissait — deux effets qui font faux sur un corps rigide. Un jouet
   dur sautille, bascule, atterrit avec du poids, mais ne se déforme
   JAMAIS : aucune mise à l'échelle dans ces gestes, seulement des
   translations et des bascules.

   L'enveloppe .bete ne porte QUE le retournement gauche-droite (statique,
   jamais interpolé : pas d'aplatissement au demi-tour). Les gestes vivent
   sur .corps. */

.bete {
  position: relative;
  flex-shrink: 0;
  transform: scaleX(var(--sens, 1));
  filter: drop-shadow(0 10px 12px rgba(16, 26, 10, 0.5));
}

.corps {
  width: 100%;
  height: 100%;
  transform-origin: 50% 100%;
  will-change: transform;
  animation: repos-rigide 3.6s ease-in-out infinite;
}

.corps img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  -webkit-user-drag: none;
}

/* Repos : la bascule d'un jouet posé, à peine visible, jamais d'echelle. */
@keyframes repos-rigide {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  32% { transform: translateY(-2.5px) rotate(-1.2deg); }
  66% { transform: translateY(-0.5px) rotate(1deg); }
}

/* Saut : petite anticipation, envol avec bascule, atterrissage qui tasse
   d'un pixel, rebond. Le poids sans la deformation. */
.bete.saut .corps { animation: saut-rigide 0.8s cubic-bezier(0.3, 0, 0.4, 1); }

@keyframes saut-rigide {
  0% { transform: translateY(0) rotate(0deg); }
  14% { transform: translateY(2px) rotate(-2deg); }
  38% { transform: translateY(-26px) rotate(4deg); }
  55% { transform: translateY(-30px) rotate(1.5deg); }
  74% { transform: translateY(0) rotate(-3deg); }
  82% { transform: translateY(2px) rotate(0deg); }
  91% { transform: translateY(-3px) rotate(0.5deg); }
  100% { transform: translateY(0) rotate(0deg); }
}

/* Elle se tourne vers quelque chose : bascule franche, temps d'arret,
   retour. */
.bete.tourne .corps { animation: tourne-rigide 1.9s ease-in-out; }

@keyframes tourne-rigide {
  0%, 100% { transform: rotate(0deg) translateX(0); }
  16% { transform: rotate(var(--vers, -10deg)) translateX(var(--dec, -4px)); }
  74% { transform: rotate(var(--vers, -10deg)) translateX(var(--dec, -4px)); }
}

/* Sursaut : un bond sec de tout le corps, comme un jouet qu'on surprend. */
.bete.sursaut .corps { animation: sursaut-rigide 0.6s cubic-bezier(0.25, 0, 0.35, 1); }

@keyframes sursaut-rigide {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  18% { transform: translateY(-8px) rotate(-2.5deg); }
  42% { transform: translateY(1px) rotate(2deg); }
  66% { transform: translateY(-2px) rotate(-1deg); }
}

/* Marche : des petits bonds cadences avec la bascule d'un pas a l'autre.
   C'est comme ca qu'avance un jouet rigide. */
.bete.marche .corps { animation: pas-rigide 0.5s ease-in-out infinite; }

@keyframes pas-rigide {
  0%, 100% { transform: translateY(0) rotate(-2.5deg); }
  25% { transform: translateY(-4px) rotate(0deg); }
  50% { transform: translateY(0) rotate(2.5deg); }
  75% { transform: translateY(-4px) rotate(0deg); }
}

/* ---- LE POIDS DES CRÉATURES ----
   Une bête qui monte et descend en bloc flotte comme un ballon. Une bête
   vivante garde les PIEDS AU SOL et se déforme : elle se tasse en
   expirant, elle s'étire en inspirant, sa largeur compense sa hauteur.
   C'est la déformation qui donne la masse, pas le déplacement. */
.creature-visuel,
.garde-bete,
.silhouette-encours .reelle,
.pastille-visuel .cec-vraie { transform-origin: 50% 100%; }

@keyframes souffle {
  0%, 100% { transform: scale(1, 1); }
  30% { transform: scale(0.982, 1.032); }
  62% { transform: scale(1.014, 0.988); }
}

/* Le saut : accroupi, détente, envol, impact, rebond. Sans l'accroupi et
   sans l'impact, un saut n'a pas de poids. */
@keyframes saute {
  0% { transform: translateY(0) scale(1, 1); }
  16% { transform: translateY(0) scale(1.14, 0.84); }
  36% { transform: translateY(-30px) scale(0.9, 1.14); }
  52% { transform: translateY(-34px) scale(0.94, 1.08); }
  70% { transform: translateY(0) scale(1.16, 0.82); }
  84% { transform: translateY(0) scale(0.96, 1.05); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* Le dandinement : le poids passe d'un pied sur l'autre. */
@keyframes dandine {
  0%, 100% { transform: rotate(0deg) scale(1, 1); }
  25% { transform: rotate(-4.5deg) scale(1.02, 0.985); }
  50% { transform: rotate(0deg) scale(1, 1); }
  75% { transform: rotate(4.5deg) scale(1.02, 0.985); }
}

/* Le regard : elle se tourne vers sa voisine, marque un temps, revient. */
@keyframes regarde {
  0%, 100% { transform: rotate(0deg) translateX(0); }
  22% { transform: rotate(var(--vers, -7deg)) translateX(var(--decale, -5px)); }
  70% { transform: rotate(var(--vers, -7deg)) translateX(var(--decale, -5px)); }
}

/* Le sursaut de surprise, quand une voisine saute à côté. */
@keyframes surprise {
  0%, 100% { transform: scale(1, 1) translateY(0); }
  18% { transform: scale(0.9, 1.13) translateY(-8px); }
  40% { transform: scale(1.08, 0.93) translateY(0); }
  62% { transform: scale(0.98, 1.02) translateY(0); }
}

.creature-visuel.saute { animation: saute 0.78s cubic-bezier(0.3, 0, 0.4, 1); }
.creature-visuel.dandine { animation: dandine 1.5s ease-in-out; }
.creature-visuel.regarde { animation: regarde 1.7s ease-in-out; }
.creature-visuel.surprise { animation: surprise 0.55s cubic-bezier(0.3, 0, 0.4, 1); }

/* Le nom doit rester lisible sur l'herbe, le ciel ou la roche : un contour
   sombre marche partout, un fond de pastille ferait tache sur le décor. */
.monster-name {
  font-size: 12px;
  font-weight: 900;
  color: #FFFFFF;
  text-shadow:
    0 1px 0 rgba(12, 8, 24, 0.9),
    0 0 4px rgba(12, 8, 24, 0.8),
    0 0 9px rgba(12, 8, 24, 0.55);
}

.creature-slot.selected .monster-name { color: var(--blanc); }

.monster-card-empty {
  text-align: center;
  color: var(--texte-doux);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.6;
  padding: 60px 20px;
}

/* Tiroir de soin : une seule zone en bas, pour la créature choisie. */
.care-drawer {
  flex-shrink: 0;
  margin-top: 12px;
  padding: 15px;
  background: var(--panneau);
  border-radius: var(--r-panneau);
  box-shadow: 0 5px 0 var(--panneau-ombre);
  display: flex;
  align-items: center;
  gap: 14px;
}

.care-drawer.hidden { display: none; }

/* La scène de soin : la créature en grand, posée sur un sol, avec la
   place au-dessus pour la gamelle, la mousse et les miettes. */
.care-scene {
  position: relative;
  width: 132px;
  height: 132px;
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  border-radius: 16px;
  overflow: hidden;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.09) 0%, rgba(255, 255, 255, 0.03) 62%, rgba(0, 0, 0, 0.22) 63%, rgba(0, 0, 0, 0.3) 100%);
}

.care-scene .creature-visuel { margin-bottom: 8px; }

.gamelle {
  position: absolute;
  bottom: 6px;
  left: 50%;
  width: 46px;
  height: 20px;
  margin-left: -23px;
  border-radius: 0 0 22px 22px;
  background: linear-gradient(180deg, #E8E2D4 0%, #B9AF9B 100%);
  box-shadow: inset 0 3px 0 rgba(255, 255, 255, 0.7), 0 2px 0 rgba(0, 0, 0, 0.3);
  animation: gamelle-arrive 0.3s cubic-bezier(0.2, 1.4, 0.5, 1);
}

.gamelle::before {
  content: "";
  position: absolute;
  top: -7px;
  left: 7px;
  right: 7px;
  height: 12px;
  border-radius: 10px;
  background: radial-gradient(circle at 30% 40%, #FF9426 0 34%, transparent 35%),
              radial-gradient(circle at 66% 46%, #FFD23F 0 30%, transparent 31%),
              radial-gradient(circle at 48% 62%, #2FD07B 0 28%, transparent 29%),
              #7A4A2A;
}

@keyframes gamelle-arrive {
  0% { transform: translateY(26px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

.miette {
  position: absolute;
  bottom: 34px;
  width: 5px;
  height: 5px;
  border-radius: 2px;
  background: #FFD23F;
  animation: miette-saute 0.9s ease-out forwards;
}

@keyframes miette-saute {
  0% { transform: translate(0, 0) rotate(0deg); opacity: 1; }
  100% { transform: translate(calc((var(--d, 1) * 16px)), 34px) rotate(180deg); opacity: 0; }
}

.bulle {
  position: absolute;
  bottom: 12px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 32%, rgba(255, 255, 255, 0.95) 0 22%, rgba(255, 255, 255, 0.35) 60%, rgba(255, 255, 255, 0.12) 100%);
  box-shadow: inset 0 0 4px rgba(255, 255, 255, 0.8);
  animation: bulle-monte 1.4s ease-out forwards;
}

@keyframes bulle-monte {
  0% { transform: translateY(0) scale(0.4); opacity: 0; }
  20% { opacity: 1; }
  100% { transform: translateY(-104px) scale(1.1); opacity: 0; }
}

.care-info { flex: 1; min-width: 0; }

.care-etat {
  font-size: 13px;
  font-weight: 600;
  color: var(--texte-doux);
  margin: -6px 0 9px;
}

.care-name {
  font-size: 17px;
  font-weight: 900;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}

.gauge-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.gauge-label {
  font-size: 12px;
  font-weight: 800;
  color: var(--texte-doux);
  width: 48px;
  flex-shrink: 0;
}

.gauge {
  flex: 1;
  height: 9px;
  background: rgba(0, 0, 0, 0.28);
  border-radius: 5px;
  overflow: hidden;
}

.gauge-fill {
  height: 100%;
  border-radius: 5px;
  background: linear-gradient(180deg, #FFE486, var(--jaune));
  transition: width 0.3s ease;
}

.gauge-fill.bas { background: linear-gradient(180deg, #FF8494, var(--rouge)); }

.care-actions {
  display: flex;
  flex-direction: column;
  gap: 7px;
  flex-shrink: 0;
}

.care-btn {
  font-size: 13px;
  font-weight: 900;
  padding: 10px 15px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.17);
  color: var(--blanc);
  border-bottom: 3px solid rgba(0, 0, 0, 0.28);
  transition: transform 0.1s ease, border-width 0.1s ease;
}

.care-btn:active { transform: translateY(2px); border-bottom-width: 1px; }

.close-btn {
  font-size: 26px;
  font-weight: 600;
  color: var(--texte-doux);
  width: 38px;
  height: 38px;
}

/* ---------- Suivi ---------- */

.tracking-overlay pre {
  flex: 1;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.25);
  padding: 15px;
  border-radius: var(--r-panneau);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.6;
  white-space: pre-wrap;
  margin: 8px 0 0;
  user-select: text;
  scrollbar-width: thin;
}

.tracking-actions {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-top: 12px;
  flex-shrink: 0;
}

.tracking-btn {
  display: block;
  padding: 14px;
  background: rgba(255, 255, 255, 0.17);
  color: var(--blanc);
  font-size: 14px;
  font-weight: 900;
  border-radius: 14px;
  border-bottom: 4px solid rgba(0, 0, 0, 0.28);
  text-align: center;
  cursor: pointer;
}

.tracking-btn:active { transform: translateY(3px); border-bottom-width: 1px; }

/* ---------- Retours ---------- */

.toast {
  position: fixed;
  bottom: calc(22px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%) translateY(16px);
  background: rgba(20, 12, 55, 0.92);
  color: var(--blanc);
  padding: 11px 20px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 900;
  opacity: 0;
  transition: opacity 0.22s ease, transform 0.22s ease;
  pointer-events: none;
  z-index: 90;
  white-space: nowrap;
}

.toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.burst {
  position: fixed;
  top: 38%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 40px;
  font-weight: 900;
  letter-spacing: -0.04em;
  color: var(--jaune);
  -webkit-text-stroke: 6px #2A1D6B;
  paint-order: stroke fill;
  opacity: 0;
  pointer-events: none;
  z-index: 95;
  white-space: nowrap;
}

.burst.visible { animation: annonce 1.1s cubic-bezier(0.2, 1.1, 0.4, 1) forwards; }

@keyframes annonce {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.7) rotate(-6deg); }
  16% { opacity: 1; transform: translate(-50%, -50%) scale(1.14) rotate(3deg); }
  30% { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  74% { opacity: 1; transform: translate(-50%, -58%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -72%) scale(0.98); }
}

/* Écran court (paysage, petit téléphone, fenêtre de bureau basse) : sans
   cette borne le plateau déborde et vient recouvrir la ligne du défi et la
   progression de la créature. */
@media (max-height: 740px) {
  :root { --plateau: min(96vw, 380px, 40vh); }

  .scoreboard { min-height: 58px; padding: 2px 0 6px; }
  .score-value { font-size: 36px; }
  .score-sub { margin-top: 5px; padding: 4px 13px 5px; font-size: 15px; }
  .defi { margin-bottom: 6px; padding: 9px 12px; }
  .monster-progress { margin-bottom: 8px; }
  .progress-notch { height: 9px; }
  .stage { gap: 12px; padding-bottom: calc(26px + env(safe-area-inset-bottom, 0px)); }
  .tray { min-height: 96px; padding: 6px; }
  .tray-slot { min-height: 82px; }
  .booster { width: 44px; height: 38px; }
  .booster svg { width: 21px; height: 21px; }
  .boosters { gap: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  /* On calme le mouvement, on ne supprime jamais le retour. Couper les
     animations rendait le jeu figé : plus de respiration des créatures,
     plus de mousse, plus de miettes, et l'enfant ne voyait plus ce qu'il
     venait de réussir. Ici tout joue, plus court et sans grand déplacement. */
  .creature-visuel { animation-duration: 6s; }
  .cell.filled .cell-block { animation-duration: 0.1s; }
  .cell.clearing .cell-block { animation-duration: 0.22s; }
  .cell.preview-line::before { animation-duration: 1.4s; }
  .birth-figure { animation-duration: 0.3s; }
  .burst.visible { animation-duration: 0.8s; }
  .score-value.bump,
  .monster-progress.bump .progress-notch.on { animation-duration: 0.2s; }
  .miette, .bulle, .goutte, .gouttelette, .etincelle, .poussiere { animation-duration: 0.55s; }
  .creature-visuel.degoutant .mouche { animation-duration: 4s; }
  .toast { transition-duration: 0.15s; }
}


/* ================================================================
   MATIÈRE : verre liquide
   ================================================================
   Les aplats plats faisaient daté. Ici les panneaux sont en verre :
   translucides, floutés, avec une arête de lumière en haut et un reflet
   qui glisse. Derrière eux, trois lueurs dérivent lentement, sans quoi
   le flou n'aurait rien à réfracter et la matière ne se verrait pas. */

.lumieres {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.lueur {
  position: absolute;
  border-radius: 50%;
  filter: blur(58px);
  opacity: 0.6;
}

.lueur.l1 {
  width: 62vw; height: 62vw;
  background: radial-gradient(circle, #7C5BFF 0%, rgba(124, 91, 255, 0) 70%);
  top: -12vw; left: -14vw;
  animation: derive1 26s ease-in-out infinite;
}
.lueur.l2 {
  width: 54vw; height: 54vw;
  background: radial-gradient(circle, #FF5FA2 0%, rgba(255, 95, 162, 0) 70%);
  top: 34vh; right: -18vw;
  animation: derive2 31s ease-in-out infinite;
}
.lueur.l3 {
  width: 70vw; height: 70vw;
  background: radial-gradient(circle, #2CD9E8 0%, rgba(44, 217, 232, 0) 70%);
  bottom: -22vh; left: 8vw;
  animation: derive3 37s ease-in-out infinite;
}

@keyframes derive1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(9vw, 7vh) scale(1.14); }
}
@keyframes derive2 {
  0%, 100% { transform: translate(0, 0) scale(1.06); }
  50% { transform: translate(-11vw, -6vh) scale(0.94); }
}
@keyframes derive3 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(6vw, -8vh) scale(1.1); }
}

/* Les PAGES passent au-dessus des lumières de fond. Rien d'autre.
   Cette règle visait tout `body > *` : plus forte que `.modal-overlay`,
   `.pluie` ou `.toast`, elle écrasait leur `position: fixed` et les faisait
   tomber dans le flux, SOUS le bas de l'écran. La fenêtre de fin était
   posée à y=968 dans une fenêtre de 968 px de haut : présente dans le DOM,
   jamais visible. Elle ne vise plus que les pages. */
body > .page { position: relative; z-index: 1; }

/* Le verre lui-même. Une seule règle, réutilisée partout. */
.verre {
  position: relative;
  background: rgba(255, 255, 255, 0.11);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -1px 0 rgba(0, 0, 0, 0.16),
    0 10px 26px rgba(12, 6, 38, 0.3);
  overflow: hidden;
}

/* Le reflet qui glisse : c'est lui qui fait lire « verre » plutôt que
   « rectangle transparent ». */
.verre::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 34%, rgba(255, 255, 255, 0.22) 46%, transparent 58%);
  background-size: 260% 100%;
  background-position: 140% 0;
  pointer-events: none;
  animation: reflet-verre 9s ease-in-out infinite;
}

@keyframes reflet-verre {
  0%, 62% { background-position: 140% 0; }
  86%, 100% { background-position: -50% 0; }
}

/* Le plateau n'est PAS du verre. Sur la référence c'est un caisson opaque
   et sombre : c'est ce contraste qui fait briller les blocs. Le verre reste
   pour les panneaux d'information, où il a un sens. */

.defi { background: rgba(255, 255, 255, 0.1); }

.modal-card,
.care-drawer,
.booster { border-bottom: 1px solid rgba(255, 255, 255, 0.2); }

.modal-card { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 26px 60px rgba(8, 4, 26, 0.6); }

/* ================================================================
   CRÉATURE EN FABRICATION
   ================================================================
   Elle est là, visible, et se remplit par le bas à chaque pièce gagnée.
   L'enfant voit ce qu'il construit au lieu de lire une jauge. */

.cec {
  flex-shrink: 0;
  width: var(--plateau);
  margin: 0 auto 10px;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-radius: 16px;
  transition: transform 0.18s cubic-bezier(0.2, 1.5, 0.4, 1);
}

.cec.encastre { animation: encastre 0.42s cubic-bezier(0.2, 1.6, 0.4, 1); }

@keyframes encastre {
  0% { transform: scale(1); }
  35% { transform: scale(1.045); }
  100% { transform: scale(1); }
}

.cec-visuel { width: 68px; height: 76px; flex-shrink: 0; }

.cec-pile { position: relative; width: 100%; height: 100%; }

.cec-pile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* La part non gagnée reste en ombre : on devine la bestiole sans la voir. */
.cec-ombre { filter: brightness(0) invert(1); opacity: 0.16; }

.cec-vraie {
  clip-path: inset(100% 0 0 0);
  transition: clip-path 0.55s cubic-bezier(0.3, 1.2, 0.4, 1);
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35));
}

.cec-infos { flex: 1; min-width: 0; }

.cec-nom {
  font-size: 15px;
  font-weight: 900;
  color: var(--blanc);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cec-compte {
  font-size: 12px;
  font-weight: 700;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

.cec-pourcent {
  font-size: 24px;
  font-weight: 900;
  color: var(--jaune);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  text-shadow: 0 2px 8px rgba(255, 200, 40, 0.4);
}

/* La pièce gagnée qui vole du plateau vers la créature. */
.piece-volante {
  position: fixed;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: linear-gradient(180deg, #FFE486, var(--jaune));
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.7), 0 0 16px rgba(255, 210, 63, 0.8);
  z-index: 300;
  pointer-events: none;
  animation: vol-piece 0.62s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

@keyframes vol-piece {
  0% { transform: translate(0, 0) scale(0.4); opacity: 0; }
  18% { transform: translate(0, -26px) scale(1.25); opacity: 1; }
  100% { transform: translate(var(--vx), var(--vy)) scale(0.5); opacity: 0.9; }
}

/* ================================================================
   VIE DE L'HABITAT
   ================================================================
   Les créatures qui attendent bougent, se retournent et se saluent.
   Un habitat figé donne un musée. */

.creature-visuel.act-saut { animation: act-saut 0.9s cubic-bezier(0.3, 1.4, 0.4, 1); }
@keyframes act-saut {
  0%, 100% { transform: translateY(0) scaleY(1); }
  22% { transform: translateY(0) scaleY(0.86); }
  55% { transform: translateY(-22px) scaleY(1.08); }
  80% { transform: translateY(0) scaleY(0.94); }
}

.creature-visuel.act-tourne { animation: act-tourne 1.2s ease-in-out; }
@keyframes act-tourne {
  0%, 100% { transform: scaleX(1); }
  20%, 80% { transform: scaleX(-1); }
}

.creature-visuel.act-regarde { animation: act-regarde 1.3s ease-in-out; }
@keyframes act-regarde {
  0%, 100% { transform: rotate(0deg); }
  30% { transform: rotate(-9deg); }
  65% { transform: rotate(9deg); }
}

.creature-visuel.act-balance { animation: act-balance 1.4s ease-in-out; }
@keyframes act-balance {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-9px) rotate(-5deg); }
  75% { transform: translateX(9px) rotate(5deg); }
}

.creature-visuel.salut-droite { animation: salut-d 1.1s ease-in-out; }
.creature-visuel.salut-gauche { animation: salut-g 1.1s ease-in-out; }
@keyframes salut-d {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  40% { transform: translateX(10px) rotate(10deg) translateY(-6px); }
}
@keyframes salut-g {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  40% { transform: translateX(-10px) rotate(-10deg) translateY(-6px); }
}

/* ================================================================
   RÉGLAGES son, musique, vibration
   ================================================================ */

.topbar-actions { display: flex; align-items: center; gap: 8px; }

.reglage {
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.12s ease, opacity 0.15s ease;
}

.reglage svg { width: 18px; height: 18px; color: var(--blanc); }
.reglage .barre { opacity: 0; }
.reglage:active { transform: scale(0.92); }

.reglage.coupe { opacity: 0.45; }
.reglage.coupe .barre { opacity: 1; }
.reglage.coupe .onde { opacity: 0; }

/* ================================================================
   PAGES
   ================================================================
   Accueil, jeu, nurserie, arène, réglages. Une seule visible à la
   fois, chacune occupe tout l'écran. */

.page {
  display: none;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  animation: page-entre 0.28s cubic-bezier(0.2, 1, 0.4, 1);
}

.page.active { display: flex; }

@keyframes page-entre {
  0% { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); }
}

.page-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(14px + env(safe-area-inset-top)) 18px 10px;
  flex-shrink: 0;
}

.page-tete h2 {
  font-size: 24px;
  font-weight: 900;
  letter-spacing: -0.03em;
  margin: 0;
  text-shadow: 0 2px 8px rgba(12, 8, 24, 0.5);
}

.page-tete-vide { width: 42px; }

.btn-retour {
  width: 42px;
  height: 42px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.14);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform 0.12s ease;
}

.btn-retour svg { width: 22px; height: 22px; color: var(--blanc); }
.btn-retour:active { transform: scale(0.92); }

/* ---------------------------- ACCUEIL --------------------------- */

/* ---- ACCUEIL ----
   L'accueil, c'est le monde du jeu, pas un fond de couleur. La prairie est
   le décor de l'arène : l'enfant arrive DANS le monde de ses créatures, et
   elles sont là, vivantes, avant même qu'il touche un bloc. Les deux voiles
   sombres, en haut et en bas, servent uniquement à rendre le texte lisible. */
.page-accueil {
  position: relative;
  overflow: hidden;
  justify-content: space-between;
  padding: calc(18px + env(safe-area-inset-top)) 20px calc(18px + env(safe-area-inset-bottom));
}

.accueil-haut { position: relative; z-index: 2; text-align: center; flex-shrink: 0; }

/* ================================================================
   LOBBY
   ================================================================
   Ce que montrent les références : on n'arrive pas sur un menu, on
   arrive dans un CAMP. En haut, qui je suis et ce que je possède. Au
   milieu, un guide qui me donne ma mission. En bas, le grand bouton
   encadré de deux boutons ronds, et la barre des trois lieux. */

.lobby-barre {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  margin-bottom: 4px;
}

.joueur {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 5px 12px 5px 5px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  text-align: left;
}

.joueur-face {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.12);
  border: 2px solid #FFD02E;
}

.joueur-face img { width: 100%; height: 100%; object-fit: contain; }

.joueur-infos { flex: 1; min-width: 0; }

.joueur-nom {
  display: block;
  font-size: 12px;
  font-weight: 900;
  color: #FFFFFF;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.joueur-jauge {
  display: block;
  height: 6px;
  margin-top: 3px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.4);
  overflow: hidden;
}

.joueur-jauge-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, #6FE3A0, #28B93B);
  transition: width 0.6s cubic-bezier(0.3, 1.2, 0.4, 1);
}

.joueur-niveau {
  flex-shrink: 0;
  min-width: 24px;
  padding: 2px 7px 3px;
  border-radius: 999px;
  background: #FFD02E;
  color: #4A3200;
  font-size: 12px;
  font-weight: 900;
  text-align: center;
}

.bourse {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 7px 12px 7px 9px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  font-size: 13px;
  font-weight: 900;
  color: #FFD02E;
  font-variant-numeric: tabular-nums;
}

.bourse svg { width: 17px; height: 17px; }

.rond-icone {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(16, 11, 40, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  transition: transform 0.12s ease;
}

.rond-icone svg { width: 21px; height: 21px; color: #FFFFFF; }
.rond-icone:active { transform: scale(0.9) rotate(35deg); }

.lobby-titre { position: relative; z-index: 2; flex-shrink: 0; text-align: center; }

/* ---- LE GUIDE ----
   Une créature parle à l'enfant et lui dit quoi faire. C'est le fil de
   l'histoire : sans lui, un menu reste un menu. */
.guide {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  flex-shrink: 0;
  margin: 2px 0 0;
  animation: guide-arrive 0.6s cubic-bezier(0.2, 1.4, 0.4, 1) 0.35s both;
}

@keyframes guide-arrive {
  0% { opacity: 0; transform: translateX(-26px); }
  100% { opacity: 1; transform: translateX(0); }
}

.guide-bete { width: 72px; height: 72px; flex-shrink: 0; }

.guide-bulle {
  position: relative;
  flex: 1;
  min-width: 0;
  padding: 11px 14px 12px;
  border-radius: 16px 16px 4px 16px;
  background: rgba(255, 252, 244, 0.95);
  color: #2A1E12;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  box-shadow: 0 8px 20px rgba(10, 8, 30, 0.4);
}

/* La pointe de la bulle, tournée vers la créature. */
.guide-bulle::after {
  content: "";
  position: absolute;
  right: -8px;
  bottom: 8px;
  border-width: 7px 0 4px 10px;
  border-style: solid;
  border-color: transparent transparent transparent rgba(255, 252, 244, 0.95);
}

.guide-bulle b { color: #C25E05; font-weight: 900; }

/* ---- LES TROIS BOUTONS DU BAS ----
   Une grille symétrique : le bouton Jouer au centre exact, les deux
   satellites centrés dans leur colonne et alignés sur le CENTRE DU ROND,
   pas sur le bas du bouton. Plus rien à régler à l'oeil. */
.lobby-cotes {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  justify-items: center;
  flex-shrink: 0;
}

.rond-gros {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: 68px;
  height: 68px;
  /* Compense l'étiquette « Jouer » sous le rond central : les satellites
     s'alignent sur le centre du disque. */
  margin-bottom: 30px;
  flex-shrink: 0;
  border-radius: 50%;
  background: linear-gradient(180deg, #7C63E8 0%, #5B41CE 100%);
  border-bottom: 4px solid #3E2A9C;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 8px 18px rgba(10, 8, 34, 0.45);
  transition: transform 0.1s ease;
}

.rond-gros.defi { background: linear-gradient(180deg, #FF7BC4 0%, #E24C9C 100%); border-bottom-color: #A82C6E; }
.rond-gros:active { transform: translateY(4px); border-bottom-width: 1px; }
.rond-gros svg { width: 26px; height: 26px; color: #FFFFFF; }

.rond-mot {
  font-size: 9.5px;
  font-weight: 900;
  color: #FFFFFF;
  letter-spacing: 0.01em;
}

.rond-pastille {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px;
  background: #E8443C;
  border: 2.5px solid #2A1F58;
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 900;
  line-height: 15px;
  text-align: center;
}

.rond-pastille.vide { display: none; }

/* ---- BARRE DU BAS ---- */
.lobby-nav {
  position: relative;
  z-index: 3;
  /* Même règle que le plateau : la barre du bas laisse la ligne du © vivre
     sous elle, sans jamais la recouvrir. */
  margin-bottom: 14px;
  display: grid;
  /* QUATRE onglets, quatre colonnes : à trois, Réglages passait à la
     ligne et la barre se faisait couper en bas de l'écran du téléphone. */
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  flex-shrink: 0;
  margin-top: 12px;
  padding: 7px;
  border-radius: 20px;
  background: rgba(14, 9, 36, 0.7);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
}

.nav-onglet {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 4px 7px;
  border-radius: 14px;
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
  font-weight: 800;
  transition: background 0.16s ease, color 0.16s ease;
}

.nav-onglet svg { width: 22px; height: 22px; }

.nav-onglet.actif {
  background: linear-gradient(180deg, #FFB947, #EF7C0C);
  color: #FFFFFF;
  box-shadow: inset 0 1.5px 0 rgba(255, 255, 255, 0.4);
}

.nav-badge {
  position: absolute;
  top: 2px;
  right: 12px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: #28B93B;
  border: 2px solid #221A4E;
  color: #FFFFFF;
  font-size: 10px;
  font-weight: 900;
  line-height: 14px;
}

.nav-badge.vide { display: none; }

/* ================================================================
   PAGE DE GARDE
   ================================================================
   L'écran qui PRÉSENTE le jeu, avant le menu. Le monde en grand et en
   mouvement, le nom, la promesse en une ligne, les créatures qui entrent,
   et un seul geste possible. */

.page-garde {
  position: relative;
  overflow: hidden;
  justify-content: space-between;
  padding: calc(30px + env(safe-area-inset-top)) 18px calc(30px + env(safe-area-inset-bottom));
}

/* ================================================================
   LE MONDE EN CALQUES
   ================================================================
   Le décor n'est plus une photo posée : c'est cinq images générées
   séparément — ciel, nuages, montagnes, collines, herbe — qui glissent
   chacune à sa vitesse. Les lointains avancent lentement, les proches
   plus vite. C'est ce décalage qui fabrique la profondeur et le
   mouvement, pas un zoom sur une image plate.

   Chaque calque mobile contient DEUX exemplaires côte à côte : quand le
   premier sort à gauche, le second est déjà en place, et la boucle ne se
   voit jamais. */

.monde {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.monde-ciel {
  position: absolute;
  inset: 0;
  background: url("./decor/01-ciel.jpg") center top / cover no-repeat;
}

/* Quatre copies par couche, une sur deux en miroir : chaque joint met
   face à face une image et son reflet, donc les bords se prolongent
   toujours exactement. C'est ce qui rend la boucle invisible — deux
   copies simples montraient une couture verticale à chaque raccord. */
.monde-couche {
  position: absolute;
  left: 0;
  width: 400%;
  display: flex;
  will-change: transform;
  animation: defile var(--vitesse) linear infinite;
}

.monde-couche i {
  display: block;
  width: 25%;
  height: 100%;
  background-image: var(--img);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

.monde-couche i:nth-child(even) { transform: scaleX(-1); }

/* On avance d'une paire entière (image + reflet) : le motif revient
   exactement sur lui-même, la boucle ne se voit jamais. */
@keyframes defile {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

/* Les vitesses viennent de la distance : les montagnes mettent cinq
   minutes à traverser, les nuages une minute. */
.monde-couche.nuages {
  --img: url("./decor/02-nuages.png");
  --vitesse: 144s;
  top: 9%;
  height: 15%;
  opacity: 0.94;
}

.monde-couche.nuages-2 {
  --img: url("./decor/02-nuages.png");
  --vitesse: 236s;
  top: 20%;
  height: 11%;
  opacity: 0.6;
  transform: scaleX(-1);
}

/* Chaque calque doit ENFONCER son bord bas derrière le calque de devant.
   Sans ce recouvrement, la coupure droite du bas de l'image se voit et
   toute la profondeur s'effondre. */
.monde-couche.montagnes {
  --img: url("./decor/03-montagnes.png");
  --vitesse: 680s;
  /* Les montagnes descendent DERRIERE les collines : leur bord bas coupe
     net, il doit toujours etre recouvert, sinon une bande de ciel creme
     passe entre les deux couches. */
  bottom: 16%;
  height: 46%;
}

.monde-couche.collines {
  --img: url("./decor/04-collines.png");
  --vitesse: 380s;
  bottom: 6%;
  height: 34%;
}

.monde-couche.herbe {
  --img: url("./decor/05-herbe.png");
  --vitesse: 192s;
  bottom: 0;
  height: 22%;
  z-index: 2;
}

/* ---- LA FAUNE ----
   Des oiseaux qui traversent le ciel et des papillons qui butinent au ras
   des fleurs. Le battement d'ailes est une VRAIE animation image par
   image : chaque bande contient les positions d'ailes générées, et le
   balayage passe de l'une à l'autre en pas francs, sans glissement. */

.vol {
  position: absolute;
  z-index: 1;
  animation: traverse var(--t) linear infinite;
  animation-delay: var(--d, 0s);
}

@keyframes traverse {
  0% { left: -90px; }
  100% { left: calc(100% + 90px); }
}

.vol-bob {
  animation: vol-bob var(--bob, 2.8s) ease-in-out infinite;
}

@keyframes vol-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(var(--amp, -14px)); }
}

.oiseau {
  width: var(--c, 44px);
  height: var(--c, 44px);
  background-image: url("./faune/oiseau.png");
  background-size: 300% 100%;
  background-repeat: no-repeat;
  transform: scaleX(var(--sens, 1));
  animation: bat-oiseau 0.44s step-end infinite;
}

/* Cycle bas, milieu, haut, milieu : un vrai battement, pas un va-et-vient. */
@keyframes bat-oiseau {
  0%, 100% { background-position: 0 0; }
  25% { background-position: 50% 0; }
  50% { background-position: 100% 0; }
  75% { background-position: 50% 0; }
}

.papillon-vol {
  position: absolute;
  z-index: 2;
  animation: papillon-derive var(--t, 11s) ease-in-out infinite alternate;
  animation-delay: var(--d, 0s);
}

@keyframes papillon-derive {
  0% { transform: translateX(0) rotate(-6deg); }
  30% { transform: translateX(var(--dx1, 40px)) translateY(-16px) rotate(5deg); }
  60% { transform: translateX(var(--dx2, -22px)) translateY(-30px) rotate(-4deg); }
  100% { transform: translateX(var(--dx3, 52px)) translateY(-8px) rotate(6deg); }
}

.papillon {
  width: var(--c, 30px);
  height: var(--c, 30px);
  background-image: url("./faune/papillon.png");
  background-size: 400% 100%;
  background-repeat: no-repeat;
  animation: bat-papillon 0.5s step-end infinite;
  animation-delay: var(--d2, 0s);
}

@keyframes bat-papillon {
  0%, 100% { background-position: 0 0; }
  25% { background-position: 33.34% 0; }
  50% { background-position: 66.67% 0; }
  75% { background-position: 100% 0; }
}

/* Le monde reste ÉCLATANT : plus aucun voile sombre posé dessus. La
   lisibilité vient des pastilles et fonds propres de chaque texte, jamais
   d'un assombrissement global qui éteint toutes les couleurs. Il ne reste
   qu'un souffle en haut et en bas, à peine visible. */
.monde-voile {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: linear-gradient(
    rgba(20, 15, 48, 0.16) 0%,
    rgba(20, 15, 48, 0) 14%,
    rgba(20, 15, 48, 0) 86%,
    rgba(16, 10, 40, 0.2) 100%);
}

/* Ancien fond d'un seul tenant, conservé le temps que toutes les pages
   passent aux calques. */
.garde-ciel { display: none; }

/* La lumière chaude qui passe sur la vallée. */
.garde-halo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(42% 24% at 50% 12%, rgba(255, 224, 150, 0.34), transparent 72%),
    radial-gradient(60% 34% at 22% 62%, rgba(255, 170, 90, 0.14), transparent 74%);
  animation: garde-lumiere 9s ease-in-out infinite;
}

@keyframes garde-lumiere {
  0%, 100% { opacity: 0.55; transform: translateX(0); }
  50% { opacity: 1; transform: translateX(4%); }
}

/* Le logo tient le MILIEU de l'écran : c'est la signature du jeu, pas une
   étiquette posée en haut. */
.garde-milieu {
  position: relative;
  z-index: 3;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  /* Le logo se centre dans TOUT l'espace laissé libre au-dessus du
     troupeau : c'est ce bloc qui absorbe la hauteur restante. */
  padding-bottom: 8px;
}

/* Les rayons qui tournent derrière le logo, comme sur une affiche. */
.garde-rayons {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 150vw;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  pointer-events: none;
  background: repeating-conic-gradient(
    from 0deg,
    rgba(255, 238, 190, 0.16) 0deg 7deg,
    rgba(255, 238, 190, 0) 7deg 18deg);
  -webkit-mask-image: radial-gradient(closest-side, #000 12%, rgba(0, 0, 0, 0.55) 34%, transparent 62%);
  mask-image: radial-gradient(closest-side, #000 12%, rgba(0, 0, 0, 0.55) 34%, transparent 62%);
  animation: rayons-tournent 44s linear infinite;
}

@keyframes rayons-tournent {
  0% { transform: translate(-50%, -50%) rotate(0deg); }
  100% { transform: translate(-50%, -50%) rotate(360deg); }
}

.garde-titre {
  position: relative;
  z-index: 3;
  text-align: center;
  flex-shrink: 0;
}

/* La couronne tracée en SVG a été retirée : le logo dessiné porte déjà
   ses propres cornes, et une forme faite à la main n'a rien à faire à
   côté d'un visuel généré. */

.garde-baseline {
  max-width: 300px;
  margin: 14px auto 0;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.45;
  color: #FFFFFF;
  text-shadow: 0 2px 6px rgba(12, 8, 32, 0.85);
  animation: garde-monte 0.6s ease-out 1.5s both;
}

@keyframes garde-monte {
  0% { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* Le troupeau : les créatures entrent en marchant depuis les deux bords,
   puis respirent sur place. C'est ce mouvement qui fait « monde vivant »
   au lieu de « photo de fond ». */
/* Le troupeau est un BLOC DE LA COLONNE, pas un calque flottant. Tant
   qu'il était positionné en absolu, il fallait deviner la hauteur du
   bouton en dessous, et il finissait toujours par mordre dessus. En flux,
   le chevauchement devient structurellement impossible. */
.garde-troupeau {
  position: relative;
  z-index: 2;
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
  margin-bottom: 18px;
}

/* L'arrivée vit sur le conteneur, les gestes sur l'image : sans cette
   séparation, chaque saut relancerait l'entrée et la bête clignerait. */
.garde-bete {
  position: relative;
  filter: drop-shadow(0 12px 14px rgba(16, 26, 10, 0.5));
  animation: bete-entre 0.9s cubic-bezier(0.2, 1.2, 0.4, 1) both;
}




.garde-bete::after {
  content: "";
  position: absolute;
  left: 18%;
  right: 18%;
  bottom: 2px;
  height: 10px;
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(20, 30, 10, 0.55), transparent 72%);
}

@keyframes bete-entre {
  0% { opacity: 0; transform: translateX(var(--depuis)) scale(0.7); }
  100% { opacity: 1; transform: translateX(0) scale(1); }
}

.garde-bas {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  animation: garde-monte 0.6s ease-out 1.9s both;
}

.btn-garde .rond { animation: jouer-appelle 2s ease-in-out infinite; }

/* ---- LOGO ----
   Le modèle empile des lettres extrudées, une couleur par lettre, avec une
   épaisseur qui descend vers la droite. On reprend le PROCÉDÉ typographique
   avec le nom et les couleurs de ce jeu, jamais leur dessin.
   Chaque lettre est un <span> posé par le jeu, avec sa teinte. */
/* ---- LE LOGO ----
   C'est une IMAGE, dessinée et générée, pas un mot tapé dans une police.
   Aucun réglage typographique ne fabrique un logo de jeu : il faut un
   dessin. Le code ne fait plus que le poser et le faire respirer. */
.logo-jeu {
  display: block;
  width: min(78vw, 340px);
  height: auto;
  margin: 0 auto;
  filter: drop-shadow(0 8px 16px rgba(10, 8, 32, 0.55));
  animation: logo-respire 4.2s ease-in-out infinite;
}

/* Les anciennes couches typographiques (contour, extrusion, vernis,
   reflet) sont supprimées : elles servaient à faire passer du texte pour
   un logo. Le logo est maintenant un dessin. */

/* Sur la page de garde, le logo est l'élément principal : plus grand, et
   les lettres tombent une par une au lancement. */
.logo-garde {
  width: min(90vw, 430px);
}

/* Sur la page de garde, le logo tombe une fois au lancement, puis
   respire. */
.logo-garde {
  animation:
    logo-tombe 0.7s cubic-bezier(0.2, 1.5, 0.35, 1) 0.15s both,
    logo-respire 4.2s ease-in-out infinite 0.9s;
}

@keyframes logo-tombe {
  0% { opacity: 0; transform: translateY(-140px) scale(1.35) rotate(-6deg); }
  62% { opacity: 1; transform: translateY(10px) scale(0.97) rotate(1.5deg); }
  100% { opacity: 1; transform: translateY(0) scale(1) rotate(0deg); }
}

.logo-sous {
  margin-top: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--texte-doux);
}

/* La vitrine : les créatures posées dans la prairie, qui bougent chacune à
   son rythme, et celle qui est encore en fabrication à côté d'elles. */
.accueil-vitrine {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  min-height: 0;
  /* Les bêtes se tiennent AU-DESSUS de la rangée de boutons, jamais
     dedans : le compteur sous leurs pieds et le bouton rond mordaient
     l'un sur l'autre alors que la place ne manquait pas. */
  padding-bottom: 34px;
  margin-bottom: 6px;
}

.accueil-vitrine .creature-visuel {
  filter: drop-shadow(0 10px 12px rgba(20, 30, 12, 0.45));
}

/* L'ombre au sol : sans elle les créatures flottent au lieu de se tenir. */
.accueil-vitrine .creature-visuel::after {
  content: "";
  position: absolute;
  left: 16%;
  right: 16%;
  bottom: -4px;
  height: 9px;
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(24, 34, 14, 0.5), transparent 72%);
  animation: ombre-suit 3.6s ease-in-out infinite;
}

@keyframes ombre-suit {
  0%, 100% { transform: scaleX(1); opacity: 0.55; }
  50% { transform: scaleX(0.86); opacity: 0.38; }
}

/* La créature en fabrication se tient avec les autres, en ombre, et se
   remplit par le bas au fil des pièces gagnées. */
.silhouette-encours {
  position: relative;
  align-self: flex-end;
}

.silhouette-encours .pile { position: relative; }

.silhouette-encours img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.silhouette-encours .fantome {
  filter: brightness(0) invert(1);
  opacity: 0.22;
}

.silhouette-encours .reelle {
  position: absolute;
  inset: 0;
  transition: clip-path 0.7s cubic-bezier(0.3, 1.2, 0.4, 1);
  animation: souffle 3.9s ease-in-out infinite;
}

.silhouette-encours .part {
  position: absolute;
  left: 50%;
  bottom: -22px;
  transform: translateX(-50%);
  padding: 2px 9px 3px;
  border-radius: 999px;
  background: rgba(16, 12, 40, 0.66);
  font-size: 11px;
  font-weight: 900;
  color: #FFD02E;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Collection vide : le modèle fait flotter une pièce au milieu de l'écran
   d'accueil. On reprend le geste, avec une vraie pièce du jeu — même
   matière, mêmes teintes — et la phrase qui dit quoi faire. */
.vitrine-vide {
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  max-width: 250px;
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--texte-doux);
  line-height: 1.5;
}

.piece-flottante {
  display: grid;
  grid-template-columns: repeat(2, 34px);
  grid-template-rows: repeat(2, 34px);
  gap: 3px;
  filter: drop-shadow(0 10px 12px rgba(10, 14, 44, 0.45));
  animation: flotte 3.2s ease-in-out infinite;
}

@keyframes flotte {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-13px) rotate(2deg); }
}

.accueil-bas { position: relative; z-index: 2; flex-shrink: 0; }

/* ---- BOUTON JOUER ----
   Le modèle met un gros bouton rond orange avec un triangle blanc, posé
   seul, au tiers bas de l'écran. Rien d'autre ne se dispute l'attention. */
.btn-jouer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  margin: 0 auto;
  background: none;
  padding: 0;
  transition: transform 0.1s ease;
}

.btn-jouer .rond {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(96px, 28vw, 132px);
  height: clamp(96px, 28vw, 132px);
  border-radius: 50%;
  /* Un seul disque. L'ancienne ombre portée pleine de 9 px dessinait un
     deuxième bouton sous le premier : on garde une arête fine et une vraie
     ombre floue, pas un doublon. */
  background:
    radial-gradient(62% 46% at 34% 20%, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 64%),
    linear-gradient(180deg, #FFB947 0%, #F79024 52%, #E9760A 100%);
  border-bottom: 4px solid #C25E05;
  box-shadow:
    inset 0 -3px 0 rgba(150, 66, 0, 0.32),
    inset 0 2px 0 rgba(255, 255, 255, 0.4),
    0 12px 24px rgba(12, 16, 48, 0.5);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
  animation: jouer-appelle 2.6s ease-in-out infinite;
}

.btn-jouer .rond svg {
  width: 42%;
  height: 42%;
  margin-left: 8%;
  color: #FFFFFF;
  filter: drop-shadow(0 2px 3px rgba(140, 60, 0, 0.5));
}

.btn-jouer:active .rond {
  transform: translateY(4px);
  border-bottom-width: 1px;
  box-shadow: inset 0 -2px 0 rgba(150, 66, 0, 0.32), 0 4px 10px rgba(12, 16, 48, 0.42);
  animation: none;
}

@keyframes jouer-appelle {
  0%, 82%, 100% { transform: scale(1); }
  90% { transform: scale(1.06); }
}

.btn-jouer .mot {
  font-size: 19px;
  font-weight: 900;
  letter-spacing: 0.01em;
  color: #FFFFFF;
  text-shadow: 0 2px 0 rgba(24, 30, 76, 0.35);
}

/* Version large, pour les pages internes. */
.btn-jouer.secondaire {
  flex-direction: row;
  margin: 0 20px calc(20px + env(safe-area-inset-bottom));
  padding: 15px 18px;
  width: auto;
  border-radius: 18px;
  font-size: 17px;
  font-weight: 900;
  color: #FFFFFF;
  background: linear-gradient(180deg, #FFAE3D, #EF7C0C);
  box-shadow: 0 6px 0 #C25E05, 0 12px 20px rgba(12, 16, 48, 0.35);
  animation: none;
}

.btn-jouer.secondaire:active { transform: translateY(5px); box-shadow: 0 1px 0 #C25E05; }

.accueil-record {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin: 12px 0 14px;
  font-size: 15px;
  font-weight: 900;
  color: #FFC426;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 2px 0 rgba(24, 30, 76, 0.3);
}

.accueil-record svg {
  width: 20px;
  height: 16px;
  flex: 0 0 auto;
  color: #FFC426;
}

.accueil-tuiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.tuile {
  min-width: 0;
  padding: 12px 6px;
  border-radius: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  transition: transform 0.12s ease;
}

.tuile-nom, .tuile-info {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tuile:active { transform: translateY(3px); }
.tuile svg { width: 26px; height: 26px; color: var(--blanc); }

.tuile-nom {
  font-size: 13px;
  font-weight: 900;
  color: var(--blanc);
}

.tuile-info {
  font-size: 11px;
  font-weight: 700;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

/* --------------------------- NURSERIE --------------------------- */

/* ---- NURSERIE ----
   Un endroit, pas un écran de statistiques : le creux de la vallée à la
   tombée du jour, les lucioles, le berceau de blocs, et la créature qui se
   remplit au milieu. L'enfant doit avoir envie d'y revenir voir où elle en
   est. */
.page-nurserie { position: relative; overflow: hidden; }

/* Les couches de décor sont posées en absolu : sans rang explicite, elles
   recouvrent le bandeau du haut et le bouton retour disparaît. */
.page-nurserie .page-tete,
.page-nurserie .nurserie-infos,
.page-nurserie .btn-jouer { position: relative; z-index: 3; }

/* L'ancien decor flou et le voile de nuit ont ete retires : ils
   eteignaient toute la page. La nurserie est en plein jour, dans le
   monde en calques, comme le reste du jeu. */

.nur-lucioles { position: absolute; inset: 0; pointer-events: none; }

.luciole {
  position: absolute;
  z-index: 2;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: #FFFDF2;
  box-shadow: 0 0 7px 2px rgba(255, 244, 200, 0.8);
  animation: luciole-vole var(--t) ease-in-out infinite;
  animation-delay: var(--d);
}

@keyframes luciole-vole {
  0%, 100% { transform: translate(0, 0); opacity: 0; }
  16% { opacity: 0.9; }
  50% { transform: translate(var(--dx), var(--dy)); opacity: 1; }
  84% { opacity: 0.7; }
}

.nur-histoire {
  position: relative;
  z-index: 2;
  width: fit-content;
  max-width: min(330px, calc(100% - 40px));
  margin: 0 auto 6px;
  padding: 8px 15px 9px;
  border-radius: 16px;
  background: rgba(16, 11, 40, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  text-align: center;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.5;
  color: #FFFFFF;
}

.nurserie-scene {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 0;
  padding: 4px 18px 8px;
}

/* ---- LES HUIT PIÈCES ----
   Elles ne sont plus un chiffre : ce sont huit vrais blocs du jeu, posés
   en arc au-dessus de la machine. Celles qui sont gagnées brillent, les
   autres ne sont qu'un contour. L'enfant compte ce qui lui manque d'un
   coup d'oeil, sans savoir lire. */
.nur-arc {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 7px;
  flex-shrink: 0;
  height: 46px;
}

.nur-piece {
  position: relative;
  width: 26px;
  height: 26px;
  border-radius: 4px;
  transform: translateY(var(--y, 0));
}

.nur-piece.vide {
  border: 2px dashed rgba(255, 255, 255, 0.32);
  background: rgba(255, 255, 255, 0.05);
}

.nur-piece.pleine {
  animation: piece-arrivee 0.5s cubic-bezier(0.2, 1.6, 0.4, 1) both, piece-brille 2.6s ease-in-out infinite;
  animation-delay: var(--d, 0s), calc(var(--d, 0s) + 0.5s);
}

@keyframes piece-arrivee {
  0% { opacity: 0; transform: translateY(calc(var(--y, 0px) - 34px)) scale(0.4) rotate(-40deg); }
  100% { opacity: 1; transform: translateY(var(--y, 0)) scale(1) rotate(0deg); }
}

@keyframes piece-brille {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50% { box-shadow: 0 0 12px 2px rgba(255, 240, 180, 0.55); }
}

/* ---- LA MACHINE ---- */
.nur-machine {
  position: relative;
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 300px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 24px;
}

/* Le faisceau qui monte du socle et traverse la créature. */
/* Le cône de lumière en dégradé CSS a été RETIRÉ : un trapèze dégradé
   fabriqué à la main ne ressemble jamais à de la lumière, il ressemble à
   un trapèze dégradé. La lumière de cette scène viendra d'un visuel
   généré, pas d'une forme tracée en CSS. */
.nur-faisceau { display: none; }

@keyframes faisceau-souffle {
  0%, 100% { opacity: 0.55; transform: translateX(-50%) scaleX(0.92); }
  50% { opacity: 1; transform: translateX(-50%) scaleX(1.05); }
}

/* Halo réduit à une lueur au sol, sous les pieds. Le grand rond lumineux
   derrière la bête faisait tache, comme le cône. */
.nur-halo {
  position: absolute;
  left: 50%;
  bottom: 34px;
  width: 62%;
  height: 26px;
  transform: translateX(-50%);
  pointer-events: none;
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(255, 214, 130, 0.3), transparent 72%);
  animation: nur-pulse 3.4s ease-in-out infinite;
}

@keyframes nur-pulse {
  0%, 100% { opacity: 0.5; transform: translateX(-50%) scale(0.92); }
  50% { opacity: 1; transform: translateX(-50%) scale(1.08); }
}

.nurserie-oeuf {
  position: relative;
  z-index: 3;
  width: 78%;
  max-width: 230px;
  aspect-ratio: 3 / 4;
}

/* ---- LE SOCLE ----
   Fait des blocs du jeu, empilés. La créature est en blocs, elle naît
   donc d'une machine en blocs : le monde est cohérent. */
.nur-socle {
  position: absolute;
  left: 50%;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  transform: translateX(-50%);
  z-index: 2;
}

.nur-rangee { display: flex; gap: 3px; }

.nur-cube {
  width: 26px;
  height: 15px;
  border-radius: 3px;
}

/* Les étincelles qui montent du socle et entrent dans la créature. */
.nur-etincelles { position: absolute; inset: 0; pointer-events: none; z-index: 4; }

.nur-grain {
  position: absolute;
  bottom: 8%;
  width: 5px;
  height: 5px;
  border-radius: 1px;
  animation: grain-aspire var(--t) ease-in infinite;
  animation-delay: var(--d);
}

@keyframes grain-aspire {
  0% { transform: translate(0, 0) scale(1); opacity: 0; }
  14% { opacity: 1; }
  86% { opacity: 0.8; }
  100% { transform: translate(var(--dx), var(--dy)) scale(0.2); opacity: 0; }
}

.nur-pile { position: relative; width: 100%; height: 100%; }

.nur-pile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* La partie pas encore fabriquée n'est plus une ombre grise : c'est un
   contour lumineux, comme un plan qui attend d'être rempli. */
/* En plein jour, le plan en attente est une silhouette SOMBRE : une
   silhouette blanche disparaissait sur le ciel clair. */
.nur-ombre {
  filter: brightness(0);
  opacity: 0.22;
  animation: plan-attend 2.4s ease-in-out infinite;
}

@keyframes plan-attend {
  0%, 100% { opacity: 0.14; }
  50% { opacity: 0.28; }
}

.nur-vraie {
  clip-path: inset(100% 0 0 0);
  transition: clip-path 0.6s cubic-bezier(0.3, 1.2, 0.4, 1);
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.45));
  animation: souffle 3.6s ease-in-out infinite;
}

.nurserie-infos {
  margin: 0 20px 16px;
  padding: 16px 18px;
  border-radius: 20px;
  text-align: center;
  flex-shrink: 0;
}

.nurserie-etat { font-size: 16px; font-weight: 900; }

.nurserie-pourcent {
  font-size: 42px;
  font-weight: 900;
  letter-spacing: -0.04em;
  color: var(--jaune);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 3px 12px rgba(255, 200, 40, 0.35);
}

.nurserie-jauge {
  height: 10px;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.26);
  overflow: hidden;
  margin: 6px 0 8px;
}

.nurserie-jauge-fill {
  height: 100%;
  width: 0;
  border-radius: 5px;
  background: linear-gradient(180deg, #FFE486, var(--jaune));
  transition: width 0.5s cubic-bezier(0.3, 1.2, 0.4, 1);
}

.nurserie-compte {
  font-size: 13px;
  font-weight: 800;
  color: var(--texte-doux);
}

.nurserie-aide {
  margin: 10px 0 0;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--texte-doux);
}

/* ----------------------------- ARÈNE ---------------------------- */

/* ---- ARÈNE ----
   Le décor est cadré sur le SOL, là où les créatures se tiennent : cadré
   sur le ciel, elles flottaient et le texte blanc devenait illisible sur
   les nuages. Un voile sombre franc tient le haut et le bas de l'écran :
   un texte posé sur une image se lit par son fond, pas par son ombre. */
.page-arene {
  position: relative;
  overflow: hidden;
  padding-bottom: calc(16px + env(safe-area-inset-bottom));
}

/* Dans l'arène, l'herbe du premier plan monte plus haut : les créatures
   se tiennent DANS le pré, pas devant une image du pré. */
.page-arene .monde-couche.herbe { height: 30%; }
.page-arene .monde-couche.collines { bottom: 14%; height: 38%; }
.page-arene .monde-couche.montagnes { bottom: 24%; height: 44%; }

.page-arene .page-tete { position: relative; z-index: 2; }
.page-arene .habitat-grid {
  position: relative;
  z-index: 2;
  flex: 1;
  align-content: center;
  padding: 0 18px;
}

/* ---- LA VALLÉE ----
   Un espace libre, pas une grille. Chaque bête a sa place, sa taille et
   sa profondeur, et se déplace dedans. */
.vallee {
  position: relative;
  z-index: 2;
  flex: 1;
  min-height: 300px;
  display: block;
  padding: 0;
  overflow: hidden;
}

.habitant {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  transform: translateX(-50%);
  cursor: pointer;
}

.habitant-nom {
  margin-top: 2px;
  padding: 1px 8px 2px;
  border-radius: 999px;
  background: rgba(14, 9, 34, 0.6);
  font-size: 10.5px;
  font-weight: 900;
  color: #FFFFFF;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.habitant.choisie .habitant-nom,
.habitant:hover .habitant-nom { opacity: 1; }

.habitant.choisie .bete { filter: drop-shadow(0 0 12px rgba(255, 208, 46, 0.9)) drop-shadow(0 10px 12px rgba(16, 26, 10, 0.5)); }

/* Ce qu'elle réclame, écrit au-dessus de sa tête. */
.habitant-etat {
  order: -1;
  margin-bottom: 2px;
  padding: 0 8px 1px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 900;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.25s ease;
}

.habitant-etat.faim {
  opacity: 1;
  background: #E8443C;
  color: #FFFFFF;
  animation: reclame 1.6s ease-in-out infinite;
}

.habitant-etat.sale {
  opacity: 1;
  background: #8B6B3A;
  color: #FFF3D8;
  animation: reclame 2.1s ease-in-out infinite;
}

@keyframes reclame {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

/* Une bête affamée traîne, une bête sale est terne : l'état se voit sur
   elle avant qu'on lise quoi que ce soit. */
.habitant.affamee .corps { filter: saturate(0.55) brightness(0.82); }
.habitant.crade .corps { filter: sepia(0.42) saturate(0.8) brightness(0.86); }
.page-arene .care-drawer { position: relative; z-index: 3; margin: 12px 18px 0; }

/* La consigne : centrée, calibrée sur la largeur du texte, sur son propre
   fond. Elle doit se lire d'un coup d'oeil, pas se déchiffrer. */
.page-arene .habitat-hint {
  position: relative;
  z-index: 2;
  width: fit-content;
  max-width: min(320px, calc(100% - 36px));
  margin: 0 auto 14px;
  padding: 8px 15px 9px;
  border-radius: 999px;
  background: rgba(14, 9, 34, 0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  text-align: center;
  font-size: 13px;
  font-weight: 800;
  line-height: 1.4;
  color: #FFFFFF;
  text-shadow: none;
}

/* Arène vide : une vraie carte au milieu, avec ce qu'il faut faire et le
   bouton pour y aller. Une phrase posée sur des nuages ne se lit pas. */
.monster-card-empty {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin: 8px auto;
  padding: 22px 20px 20px;
  max-width: 300px;
  border-radius: 22px;
  background: rgba(18, 12, 44, 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 0 18px 40px rgba(8, 5, 24, 0.5);
  text-align: center;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.5;
  color: #EFE8FF;
}

.vide-fantome { width: 112px; height: 112px; }

.vide-fantome img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.26;
  animation: souffle 3.8s ease-in-out infinite;
}

.vide-titre {
  font-size: 17px;
  font-weight: 900;
  color: #FFFFFF;
}

.vide-texte { color: #D8CEF6; }

.monster-card-empty .btn-jouer.secondaire {
  margin: 4px 0 0;
  width: 100%;
  justify-content: center;
}

/* --------------------------- RÉGLAGES --------------------------- */

.reglages-liste {
  flex: 1;
  overflow-y: auto;
  padding: 4px 18px calc(24px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.reglage-ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* La liste est une colonne flex : sans ce flex-shrink, les lignes hautes
     (curseurs, statistiques, règles du jeu) sont écrasées et leur contenu
     disparaît. */
  flex-shrink: 0;
  padding: 14px 16px;
  border-radius: 16px;
}

.reglages-liste > * { flex-shrink: 0; }

.reglage-nom { display: block; font-size: 15px; font-weight: 800; }

.reglage-aide {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--texte-doux);
}

.reglage-ligne.colonne {
  flex-direction: column;
  align-items: stretch;
  gap: 9px;
}

.reglage-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.reglage-val {
  font-size: 13px;
  font-weight: 900;
  color: #FFD02E;
  font-variant-numeric: tabular-nums;
}

/* La glissière de volume : grosse, attrapable par un doigt d'enfant. */
.glissiere {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 10px;
  border-radius: 5px;
  background: linear-gradient(90deg, #FFD02E var(--rempli, 70%), rgba(0, 0, 0, 0.3) var(--rempli, 70%));
  outline: none;
}

.glissiere::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(180deg, #FFFFFF, #E4E0F5);
  border: 3px solid #FFD02E;
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.4);
  cursor: pointer;
}

.glissiere::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #FFFFFF;
  border: 3px solid #FFD02E;
  cursor: pointer;
}

/* Les chiffres de la partie, en quatre cases. */
.reglage-ligne.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  padding: 14px 10px;
}

.stat-case {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
}

.stat-nb {
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: 22px;
  font-weight: 800;
  line-height: 1.1;
  color: #FFD02E;
  font-variant-numeric: tabular-nums;
}

.stat-nom {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--texte-doux);
  text-align: center;
}

.reglage-ligne.regles { gap: 7px; }

.reglage-ligne.regles p {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.45;
  color: #EDE7FF;
}

.reglage-ligne.regles b { color: #FFD02E; font-weight: 900; }

.interrupteur {
  width: 54px;
  height: 30px;
  border-radius: 15px;
  background: rgba(0, 0, 0, 0.3);
  position: relative;
  flex-shrink: 0;
  transition: background 0.2s ease;
}

.interrupteur .pastille {
  position: absolute;
  top: 3px;
  left: 27px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--blanc);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.35);
  transition: left 0.2s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.interrupteur:not(.coupe) { background: var(--vert); }
.interrupteur.coupe .pastille { left: 3px; }

/* Préférences de confort : elles agissent vraiment sur l'écran. */
body.sans-animations .garde-ciel,
body.sans-animations .garde-halo,
body.sans-animations .garde-rayons,
body.sans-animations .jeu-decor,
body.sans-animations .nur-decor,
body.sans-animations .grain,
body.sans-animations .luciole,
body.sans-animations .logo-jeu,
body.sans-animations .logo-garde,
body.sans-animations .btn-jouer .rond { animation: none !important; }

body.sans-aide .cell.preview-line::before { display: none; }

.reglages-titre {
  margin-top: 12px;
  font-size: 12px;
  font-weight: 900;
  color: var(--jaune);
}

.tracking-btn.danger { color: #FFC9CE; }

.reglages-pied {
  margin-top: 18px;
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--texte-doux);
}

/* ------------------- Baptême de la créature --------------------- */

.birth-question {
  font-size: 15px;
  font-weight: 800;
  color: var(--texte-doux);
  margin-bottom: 8px;
}

.birth-input {
  width: 100%;
  padding: 13px 14px;
  margin-bottom: 14px;
  border-radius: 14px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  background: rgba(0, 0, 0, 0.26);
  color: var(--blanc);
  font-family: inherit;
  font-size: 18px;
  font-weight: 900;
  text-align: center;
  outline: none;
}

.birth-input:focus { border-color: var(--jaune); }
.birth-input::placeholder { color: rgba(255, 255, 255, 0.35); font-weight: 700; }

/* Le raccourci vers la nurserie est un bouton : il doit rester lisible. */
.cec { text-align: left; font-family: inherit; cursor: pointer; }

/* ================================================================
   AVENTURE
   ================================================================
   Le sentier de l'histoire. Une pierre par pièce gagnée, une créature au
   bout de chaque chapitre. Les pierres sont les blocs du jeu : le chemin
   est fait de la même matière que ce qu'on y gagne. */

.page-aventure { position: relative; overflow: hidden; }
.page-aventure .page-tete { position: relative; z-index: 3; }

.aventure-conte {
  position: relative;
  z-index: 3;
  margin: 0 18px 8px;
  padding: 12px 16px;
  border-radius: 16px;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.5;
  color: #FFFFFF;
  flex-shrink: 0;
}

.aventure-conte b { color: #FFD02E; }

.aventure-piste {
  position: relative;
  z-index: 2;
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.piste-interieur { position: relative; width: 100%; }

/* Une pierre du sentier : un bloc du jeu, posé de biais. */
.etape {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  transform: translate(-50%, -50%) rotate(var(--a, 0deg));
  border-radius: 10px;
  transition: transform 0.15s ease;
}

.etape.faite {
  opacity: 0.96;
}

.etape.faite::after {
  content: "";
  width: 15px;
  height: 9px;
  border-left: 3.5px solid #FFFFFF;
  border-bottom: 3.5px solid #FFFFFF;
  transform: rotate(-45deg) translate(1px, -2px);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.4));
}

.etape.a-venir {
  background: rgba(255, 255, 255, 0.16) !important;
  background-image: none !important;
  border: 2.5px dashed rgba(255, 255, 255, 0.55);
  box-shadow: none;
}

.etape.actuelle {
  z-index: 2;
  animation: etape-appelle 1.6s ease-in-out infinite;
}

.etape.actuelle::before {
  content: "";
  position: absolute;
  inset: -9px;
  border-radius: 14px;
  border: 3px solid #FFD02E;
  animation: etape-onde 1.6s ease-out infinite;
}

@keyframes etape-appelle {
  0%, 100% { transform: translate(-50%, -50%) rotate(var(--a, 0deg)) scale(1); }
  50% { transform: translate(-50%, -50%) rotate(var(--a, 0deg)) scale(1.12); }
}

@keyframes etape-onde {
  0% { opacity: 1; transform: scale(0.9); }
  100% { opacity: 0; transform: scale(1.35); }
}

/* La borne de fin de chapitre : la créature qui y naît. */
.etape.borne {
  width: 74px;
  height: 74px;
  border-radius: 50%;
  background: linear-gradient(180deg, #FFE9AC, #FFC94A) !important;
  border: 3.5px solid #FFFFFF;
  box-shadow: 0 6px 16px rgba(120, 70, 0, 0.4);
}

.etape.borne img {
  width: 82%;
  height: 82%;
  object-fit: contain;
}

.etape.borne.a-venir {
  background: rgba(255, 255, 255, 0.14) !important;
  border: 3px dashed rgba(255, 255, 255, 0.6);
}

.etape.borne.a-venir img { filter: brightness(0); opacity: 0.3; }

.etape-nom {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 1px 8px 2px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.66);
  font-size: 10px;
  font-weight: 900;
  color: #FFFFFF;
  white-space: nowrap;
}

/* Les petits pas entre deux pierres. */
.pas {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.55);
  transform: translate(-50%, -50%) rotate(20deg);
}

/* ---- MISSION ---- */
.mission-carte { text-align: center; }

.mission-guide {
  width: 84px;
  height: 84px;
  margin: -58px auto 2px;
  filter: drop-shadow(0 8px 12px rgba(10, 8, 30, 0.5));
}

.mission-texte {
  margin: 6px 0 12px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.5;
  color: #EFE8FF;
}

.mission-texte b { color: #FFD02E; }

.mission-boosters {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 14px;
}

.mission-boosters .jeton {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.13);
  font-size: 12.5px;
  font-weight: 900;
  color: #FFFFFF;
}

.mission-boosters .jeton svg { width: 15px; height: 15px; }

/* ---- LA CRÉATURE PARLE, LE BOUTON RÉPOND ----
   Le bas de la nurserie n'est plus un panneau d'information : la créature
   demande ce qui lui manque dans une bulle, et le bouton est la réponse à
   sa demande. Petit, centré, il rebondit de temps en temps pour appeler
   la main, et sa flèche pointe vers l'action. */

.nur-parole {
  position: relative;
  z-index: 3;
  display: flex;
  justify-content: center;
  flex-shrink: 0;
  margin: -6px 26px 8px;
}

.nur-bulle {
  position: relative;
  max-width: 300px;
  padding: 11px 16px 12px;
  border-radius: 16px;
  background: rgba(255, 252, 244, 0.96);
  color: #2A1E12;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  box-shadow: 0 8px 20px rgba(10, 8, 30, 0.35);
  animation: bulle-pop 0.45s cubic-bezier(0.2, 1.5, 0.4, 1);
}

.nur-bulle b { color: #C25E05; font-weight: 900; }

/* La pointe monte VERS la créature : c'est elle qui parle. */
.nur-bulle::before {
  content: "";
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  border-width: 0 8px 10px;
  border-style: solid;
  border-color: transparent transparent rgba(255, 252, 244, 0.96);
}

@keyframes bulle-pop {
  0% { opacity: 0; transform: scale(0.7) translateY(8px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

/* Le panneau de progression : sombre, compact, lisible sur l'herbe. */
.page-nurserie .nurserie-infos {
  width: fit-content;
  min-width: 210px;
  margin: 0 auto 10px;
  padding: 10px 22px 12px;
  border-radius: 18px;
  background: rgba(16, 11, 40, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1.5px solid rgba(255, 255, 255, 0.16);
  text-align: center;
  flex-shrink: 0;
}

/* Le bouton d'appel : petit, centré, et il saute sur place toutes les
   quelques secondes comme la créature saute — même langage. */
.btn-appel {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 auto calc(18px + env(safe-area-inset-bottom));
  padding: 12px 24px 13px;
  border-radius: 999px;
  background: linear-gradient(180deg, #FFB947, #EF7C0C);
  border-bottom: 4px solid #C25E05;
  color: #FFFFFF;
  font-size: 16.5px;
  font-weight: 900;
  box-shadow: 0 8px 18px rgba(12, 16, 48, 0.35);
  flex-shrink: 0;
  animation: appel-sautille 3.4s ease-in-out infinite;
  transition: transform 0.1s ease;
}

.btn-appel svg { width: 19px; height: 19px; }
.btn-appel:active { transform: translateY(3px); border-bottom-width: 1px; animation: none; }

@keyframes appel-sautille {
  0%, 78%, 100% { transform: translateY(0) scale(1); }
  84% { transform: translateY(-7px) scale(1.05, 0.96); }
  90% { transform: translateY(0) scale(1.03, 0.98); }
  95% { transform: translateY(-3px) scale(1); }
}

/* ================================================================
   NIVEAUX ET CHRONO
   ================================================================ */

.page-modes { position: relative; overflow: hidden; }
.page-modes .page-tete { position: relative; z-index: 3; }

.modes-liste {
  position: relative;
  z-index: 3;
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 20px calc(20px + env(safe-area-inset-bottom));
}

.modes-liste > * { flex-shrink: 0; }

.modes-titre {
  margin-top: 6px;
  font-size: 13px;
  font-weight: 900;
  color: #FFFFFF;
  text-shadow: 0 2px 6px rgba(12, 8, 32, 0.7);
}

.carte-niveau,
.chrono-choix {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 13px 16px;
  border-radius: 18px;
  background: rgba(16, 11, 40, 0.66);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 2.5px solid rgba(255, 255, 255, 0.16);
  text-align: left;
  transition: transform 0.12s ease, border-color 0.15s ease, background 0.15s ease;
}

.carte-niveau:active,
.chrono-choix:active { transform: scale(0.97); }

.carte-niveau.choisi,
.chrono-choix.choisi {
  border-color: #FFD02E;
  background: rgba(46, 30, 90, 0.8);
  box-shadow: 0 0 0 3px rgba(255, 208, 46, 0.25), 0 8px 20px rgba(10, 8, 32, 0.4);
}

.niveau-nom { font-size: 16px; font-weight: 900; color: #FFFFFF; }

.carte-niveau.choisi .niveau-nom::after,
.chrono-choix.choisi .niveau-nom::after {
  content: " ✓";
  color: #FFD02E;
}

.niveau-detail {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  color: #CFC6EE;
}

.chrono-choix-ligne {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.modes-go { margin-top: 10px; font-size: 18px; }

/* La ligne du chrono, sous le défi : lisible d'un regard, rouge quand il
   reste peu. */
.chrono-ligne {
  display: flex;
  align-items: center;
  gap: 8px;
  width: var(--plateau);
  margin: 0 auto 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.6);
  flex-shrink: 0;
  position: relative;
  z-index: 2;
}

.chrono-ligne.hidden { display: none; }
.chrono-ligne svg { width: 17px; height: 17px; color: #FFD02E; flex-shrink: 0; }

.chrono-ligne span {
  font-family: "Baloo 2", "Archivo", sans-serif;
  font-size: 16px;
  font-weight: 800;
  color: #FFFFFF;
  min-width: 46px;
  font-variant-numeric: tabular-nums;
}

.chrono-jauge {
  flex: 1;
  height: 8px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.35);
  overflow: hidden;
}

.chrono-fill {
  height: 100%;
  width: 100%;
  border-radius: 4px;
  background: linear-gradient(90deg, #6FE3A0, #28B93B);
  transition: width 1s linear;
}

.chrono-ligne.urgent svg,
.chrono-ligne.urgent span { color: #FF6B76; animation: chrono-bat 1s step-end infinite; }
.chrono-ligne.urgent .chrono-fill { background: linear-gradient(90deg, #FF8A93, #E8443C); }

@keyframes chrono-bat {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

/* ================================================================
   FIN DE PARTIE ANIMÉE + PLUIE DE BLOCS
   ================================================================ */

/* La fenêtre de fin ARRIVE au lieu d'apparaître : voile qui se fond,
   carte qui rebondit, titre qui se pose. */
.modal-overlay:not(.hidden) { animation: voile-fond 0.3s ease-out; }

.modal-overlay:not(.hidden) .modal-card {
  animation: carte-rebond 0.55s cubic-bezier(0.2, 1.5, 0.4, 1);
}

@keyframes voile-fond {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes carte-rebond {
  0% { opacity: 0; transform: translateY(60px) scale(0.7); }
  60% { opacity: 1; transform: translateY(-8px) scale(1.04); }
  80% { transform: translateY(2px) scale(0.99); }
  100% { transform: translateY(0) scale(1); }
}

#roundend-titre { animation: titre-pose 0.5s cubic-bezier(0.2, 1.6, 0.4, 1) 0.2s both; }

@keyframes titre-pose {
  0% { opacity: 0; transform: scale(1.6) rotate(-4deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

/* La pluie de blocs : les cubes du jeu qui tombent en tournant, pour les
   victoires, les naissances et les fins de partie. Posée par le jeu,
   supprimée toute seule. */
.pluie {
  position: fixed;
  inset: 0;
  z-index: 220;
  pointer-events: none;
  overflow: hidden;
}

.pluie .voxel {
  position: absolute;
  top: -30px;
  animation: bloc-tombe var(--t) cubic-bezier(0.3, 0, 0.8, 1) var(--d) forwards;
}

@keyframes bloc-tombe {
  0% { transform: translateY(0) rotate(0deg); opacity: 1; }
  85% { opacity: 1; }
  100% { transform: translateY(112vh) rotate(var(--rot)); opacity: 0.7; }
}


/* ---- APAISEMENT iPHONE ----
   Le verre dépoli (backdrop-filter) posé sur un décor qui défile oblige
   iOS à recalculer le flou à chaque image : tous les panneaux semblent
   trembler et miroiter. Sur iOS uniquement, le verre devient une teinte
   pleine, immobile par nature. Le décor, lui, continue de vivre. */
@supports (-webkit-touch-callout: none) {
  .verre,
  .lobby-nav,
  .guide,
  .rond-gros,
  .rond-icone {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  .verre { background: rgba(24, 17, 60, 0.58); }

  /* Les animations d'ENTRÉE (bouton qui monte, troupeau qui arrive) se
     jouent UNE fois partout ailleurs, mais iOS les rejoue en boucle :
     le bouton Commencer clignotait sans fin. Ici elles sont posées
     directement à leur état final. Les gestes des créatures, le décor
     et les papillons continuent de vivre normalement. */
  .garde-bas,
  .garde-baseline,
  .garde-bete,
  .page {
    animation: none !important;
    opacity: 1 !important;
  }
  .garde-bete { transform: none !important; }
}

/* Le copyright, présent sur CHAQUE écran comme dans les jeux classiques :
   minuscule, centré tout en bas, au-dessus du décor et sous les fenêtres. */
.copyright-global {
  position: fixed;
  left: 0;
  right: 0;
  /* Le point le plus BAS où il reste visible : collé au bord de la zone
     peinte, juste au-dessus de la bande système. Y ajouter la hauteur de
     la bande le remontait de 36px ; l'y descendre le faisait disparaître.
     Ce 1px est la limite mesurée, il ne bouge plus. */
  bottom: 1px;
  z-index: 60;
  text-align: center;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.05em;
  color: rgba(255, 255, 255, 0.62);
  text-shadow: 0 1px 3px rgba(10, 6, 30, 0.9);
  pointer-events: none;
}

/* Badge de version : discret, sur la page de garde. Il existe pour qu'une
   simple capture d'ecran dise QUELLE version tourne, sans deviner. */
.version-badge {
  position: absolute;
  z-index: 4;
  right: 10px;
  bottom: calc(8px + env(safe-area-inset-bottom));
  padding: 2px 9px 3px;
  border-radius: 999px;
  background: rgba(16, 11, 40, 0.55);
  font-size: 10.5px;
  font-weight: 800;
  color: rgba(255, 255, 255, 0.85);
  font-variant-numeric: tabular-nums;
}

/* ---- VICTOIRE ----
   Record battu : la carte devient dorée, le titre pulse, une couronne de
   lumière tourne derrière. C'est la seule victoire possible dans un jeu de
   blocs, elle doit se voir. */
.roundend-sous {
  margin: 2px 0 10px;
  font-size: 13.5px;
  font-weight: 700;
  color: #CFC6EE;
}

.modal-overlay.gagne .modal-card {
  border: 2.5px solid #FFD02E;
  box-shadow: 0 0 0 4px rgba(255, 208, 46, 0.2), 0 26px 60px rgba(8, 4, 26, 0.6);
}

.modal-overlay.gagne #roundend-titre {
  color: #FFD02E;
  text-shadow: 0 3px 0 rgba(120, 70, 0, 0.4), 0 0 22px rgba(255, 208, 46, 0.6);
  animation: titre-pose 0.5s cubic-bezier(0.2, 1.6, 0.4, 1) 0.2s both,
             titre-vibre 1.4s ease-in-out 0.8s infinite;
}

.modal-overlay.gagne .roundend-sous { color: #FFE9AC; }

@keyframes titre-vibre {
  0%, 100% { transform: scale(1) rotate(0deg); }
  25% { transform: scale(1.06) rotate(-1.5deg); }
  75% { transform: scale(1.06) rotate(1.5deg); }
}

/* La couronne de lumière derrière la carte gagnante. */
.modal-overlay.gagne .modal-card::before {
  content: "";
  position: absolute;
  inset: -60px;
  z-index: -1;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg,
    rgba(255, 216, 120, 0.3) 0deg 8deg,
    rgba(255, 216, 120, 0) 8deg 20deg);
  animation: couronne-tourne 12s linear infinite;
}

@keyframes couronne-tourne {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.modal-card { position: relative; }
