/* ============================================================
 *  NuMat — style.css v9 (v1.0.13)
 *  + Watermark SVG (chiffres filigranés) sur le body
 *  + Modale de victoire refondue (fond joyeux)
 *  + Boutons toolbar transparents (sans fond doré)
 *  + Animation pair-fade-out
 *  + v1.0.174 — badge .numat-iq-penalty : pastille orange
 *    « -X QI » clignotante affichée ~2,8 s au-dessus d'une aide
 *    utilisée (bombe 💣 / minuterie ⏱ / boutons power-ups) quand
 *    elle retire des points de QI — voir app.js showIQPenalty().
 *  + v1.0.175 — TROIS AJOUTS (retour d'essai v1.0.174) :
 *    1. variante VERTE .numat-iq-free : même pastille, libellée
 *       « GRATUIT » — les 4 boutons du bas l'affichent pendant
 *       leur capital gratuit (chaque utilisation d'aide a désormais
 *       un retour visible) ;
 *    2. tremblement .numat-rot-shake : les cartes qui VONT être
 *       déplacées par la rotation du plateau tremblent sur place
 *       (liseré doré pulsé, boucle 0,28 s) avant de se replacer —
 *       2 s sur le layout Rectangle, 0,6 s sur l'Anneau ;
 *    3. étincelle .bomb-spark : la nouvelle icône de bombe SVG
 *       (app.js BOMB_ICON_SVG) a une étincelle qui pétille en
 *       continu (opacité + halo) — la bombe paraît « vivante ».
 * ============================================================ */

/* v1.0.115 — FIX 04 : clignotage rouge sur les tuiles qui vont exploser (bombe) */
@keyframes bombTargetPulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(255, 0, 0, 0.9), 0 0 18px rgba(255, 0, 0, 0.7) !important; transform: scale(1); }
  50%      { box-shadow: 0 0 0 6px rgba(255, 82, 82, 1),   0 0 28px rgba(255, 0, 0, 1)   !important; transform: scale(1.05); }
}
.tile.bomb-target {
  animation: bombTargetPulse 0.4s ease-in-out infinite !important;
  z-index: 999 !important;
}

/* ============================================================
 *  v1.0.174 — PÉNALITÉ QI VISIBLE (demande utilisateur) :
 *  « quand la bombe ou n'importe quelle autre aide est utilisée,
 *    montrer juste à côté, en jaune ou en orange : "- 5 QI", qui
 *    n'apparaît que quelques secondes en clignotant puis
 *    disparaît, et mettre le compteur QI à jour en même temps. »
 *  Badge .numat-iq-penalty : pastille dégradé jaune→orange, texte
 *  blanc lisible, clignote (numatIQPenaltyBlink ~2,2 s) puis
 *  s'envole en fondu (numatIQPenaltyFly ~0,55 s). Position fixed
 *  calculée en JS juste AU-DESSUS de l'aide utilisée (tuile 💣/⏱
 *  ou bouton) ; z-index 64000 : au-dessus du plateau ET des
 *  modales (60000), sous les confettis (65000) et le splash.
 * ============================================================ */
@keyframes numatIQPenaltyBlink {
  0%, 100% { opacity: 1;   transform: translate(-50%, 0)    scale(1);    filter: brightness(1.2); }
  50%      { opacity: 0.35; transform: translate(-50%, 2px) scale(1.15); filter: brightness(0.85); }
}
@keyframes numatIQPenaltyFly {
  0%   { opacity: 1; transform: translate(-50%, 0)     scale(1); }
  100% { opacity: 0; transform: translate(-50%, -20px) scale(0.82); }
}
.numat-iq-penalty {
  position: fixed !important;
  /* left/top posés en JS via setProperty(..., 'important') : le CSS ne
   * doit PAS les déclarer !important, sinon il écraserait l'inline. */
  padding: 4px 12px !important;
  border-radius: 14px !important;
  background: linear-gradient(180deg, #ffc400 0%, #ff9100 55%, #ff6d00 100%) !important;
  color: #ffffff !important;
  font-size: 0.95rem !important;
  font-weight: 900 !important;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  letter-spacing: 0.5px !important;
  white-space: nowrap !important;
  border: 2px solid rgba(255, 255, 255, 0.85) !important;
  box-shadow: 0 0 0 2px rgba(255, 109, 0, 0.5), 0 5px 16px rgba(0, 0, 0, 0.6) !important;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45) !important;
  pointer-events: none !important;
  z-index: 64000 !important;
  transform: translate(-50%, 0) !important;
  animation: numatIQPenaltyBlink 0.42s ease-in-out infinite !important;
  -webkit-user-select: none !important;
  user-select: none !important;
}
.numat-iq-penalty.fading {
  animation: numatIQPenaltyFly 0.55s ease-in forwards !important;
}

/* ============================================================
 *  v1.0.175 — 1. BADGE VERT « GRATUIT » (constat utilisateur : « je
 *  vois bien les -5 QI quand la bombe joue mais pas quand
 *  j'utilise les autres aides — les 4 boutons du bas »).
 *  Pendant le capital gratuit (3 indices, 2 annulations, 2 mélanges,
 *  3 nouveaux), l'aide ne retire RIEN : la pastille VERTE « GRATUIT »
 *  explique pourquoi — même position, même clignotement, même durée
 *  que la pastille orange « -X QI » qui prend le relais ensuite.
 *  Dégradé vert plein (pas fluo) + bordure blanc cassé : lisible sur
 *  tous les fonds, sans crier plus fort que la pénalité orange.
 * ============================================================ */
.numat-iq-penalty.numat-iq-free {
  background: linear-gradient(180deg, #7ee787 0%, #2ea043 55%, #1a7f37 100%) !important;
  border-color: rgba(255, 255, 255, 0.9) !important;
  box-shadow: 0 0 0 2px rgba(26, 127, 55, 0.5), 0 5px 16px rgba(0, 0, 0, 0.6) !important;
  color: #ffffff !important;
}

/* ============================================================
 *  v1.0.175 — 2. TREMBLEMENT PRÉ-ROTATION (demande utilisateur :
 *  « une animation qui fait trembler les cartes 2 ou 3 secondes
 *  avant de les replacer »). La rotation du plateau (rectangle :
 *  retournement auto-apparié / bombe / minuterie ; anneau : chaque
 *  match) est maintenant PRÉCÉDÉE d'un tremblement des cartes qui
 *  vont bouger : petits déplacements ±2 px + légère rotation ±1°,
 *  boucle de 0,28 s, et un LISÉRÉ DORÉ qui pulse pour dire
 *  « attention, ça va bouger ». Le reste de la tuile (ombre, relief)
 *  est conservé : la classe n'écrase que transform/box-shadow.
 *  La classe est posée par app.js (rotateBoardAnimated) et
 *  RÉAPPLIQUÉE à chaque render() pendant la fenêtre — d'où
 *  l'itération infinie (le tremblement continue jusqu'au replacement).
 * ============================================================ */
@keyframes numatRotShake {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  20%      { transform: translate(-2px, 1px) rotate(-1deg); }
  40%      { transform: translate(2px, -1px) rotate(1deg); }
  60%      { transform: translate(-2px, -1px) rotate(-0.7deg); }
  80%      { transform: translate(2px, 1px) rotate(0.7deg); }
}
.tile.numat-rot-shake {
  animation: numatRotShake 0.28s linear infinite !important;
  box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.75), 0 0 18px rgba(255, 193, 7, 0.55), 0 4px 0 rgba(0, 0, 0, 0.6) !important;
}

/* ============================================================
 *  v1.0.175 — 3. ÉTINCELLE DE LA NOUVELLE ICÔNE DE BOMBE.
 *  BOMB_ICON_SVG (app.js) remplace l'emoji 💣 par un dessin maison
 *  (sphère noire brillante + culot + mèche + étincelle 8 branches).
 *  Le groupe .bomb-spark PÉTILLE en continu : opacité 0,55→1 + halo
 *  doré, boucle 0,55 s en alternate — sobre en CPU (une seule
 *  propriété animée + filter), visible sans être agressif. L'icône
 *  est un SVG inline : elle hérite de la taille de sa tuile (82 %)
 *  et se centre toute seule (le conteneur .tile est flex centré).
 *  NB : .numat-bomb-icon garde pointer-events:none pour ne pas
 *  dévorer le clic (c'est la tuile parente qui écoute).
 * ============================================================ */
.numat-bomb-icon {
  pointer-events: none !important;
  -webkit-user-select: none !important;
  user-select: none !important;
}
@keyframes numatBombSpark {
  from { opacity: 0.55; filter: drop-shadow(0 0 1px rgba(255, 143, 0, 0.0)); }
  to   { opacity: 1;    filter: drop-shadow(0 0 3px rgba(255, 171, 0, 0.9)); }
}
.numat-bomb-icon .bomb-spark {
  animation: numatBombSpark 0.55s ease-in-out infinite alternate !important;
  transform-origin: 48px 9px;
  transform-box: view-box;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body.numat-app,
body.vita-app {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  /* v1.0.45 — Background par défaut neutre sombre. Le JS (startLevel) surcharge
   * avec l'image utilisateur (assets/backgrounds/bg-N.jpg) OU le gradient du
   * thème si NUM_BACKGROUND_IMAGES=0. Plus de gradient vert + watermark ici
   * (causait un flash vert avant chargement de l'image + surcharge inutile). */
  background-color: #0a0a0a !important;
  background-image: none !important;
  background-repeat: no-repeat !important;
  background-attachment: fixed !important;
  background-size: cover !important;
  color: #fff !important;
  min-height: 100vh;
  min-height: 100dvh;
  /* v1.0.18 — padding:0 sur body (le #numat-root a son propre padding) */
  padding: 0 !important;
  margin: 0 !important;
  overflow: hidden !important;   /* empêche le scroll de la page ; seule .game-area scroll */
  -webkit-tap-highlight-color: transparent;
}

#numat-root,
#vita-root {
  max-width: 480px;
  margin: 0 auto;
  display: flex !important;
  flex-direction: column !important;
  gap: 6px !important;
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0 8px calc(78px + env(safe-area-inset-bottom, 0)) !important;
  box-sizing: border-box !important;
}

.logo-svg { height: 28px; width: auto; }

/* ============================================================
 *  v1.0.15 — Top bar : logo + niveau + QI + restants SUR UNE LIGNE
 * ============================================================ */
.top-bar {
  width: 100% !important;
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 8px !important;
  padding: 6px 10px !important;
  background: rgb(1 24 115 / 63%) !important;
  border-radius: 10px !important;
  font-size: 0.85rem !important;
  color: #fff !important;
  font-weight: 700 !important;
  box-sizing: border-box !important;
}
.top-logo {
  height: 26px !important;
  max-width: 90px !important;
  object-fit: contain !important;
  flex: 0 0 auto !important;
}
.top-stat {
  flex: 0 0 auto !important;
  white-space: nowrap !important;
}
.top-stat b {
  font-size: 1rem !important;
}

/* Zone de jeu scrollable (tray + board) */
.game-area {
  flex: 1 1 auto !important;
  display: flex !important;
  flex-direction: column !important;
  gap: 6px !important;
  overflow-y: auto !important;
  min-height: 0 !important; /* important pour flexbox scroll */
  -webkit-overflow-scrolling: touch;
  padding-bottom: 8px;
}
.game-area #board {
  width: 100%;
  margin-top: 4px;
  overflow: visible;
}

/* ============================================================
 *  v1.0.15 — Boutons en bas (fixes), plus gros
 * ============================================================ */
.controls-bottom {
  position: fixed !important;
  bottom: 0 !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
  width: 100% !important;
  max-width: 480px !important;
  display: flex !important;
  justify-content: space-around !important;
  gap: 6px !important;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 8px)) !important;
  background: linear-gradient(180deg, rgba(0,0,0,0.0) 0%, rgba(0,0,0,0.6) 30%, rgba(0,0,0,0.8) 100%) !important;
  backdrop-filter: blur(10px) !important;
  -webkit-backdrop-filter: blur(10px) !important;
  z-index: 9000 !important;
  box-sizing: border-box !important;
}
.controls-bottom .icon-btn {
  width: 60px !important;
  height: 60px !important;
  flex: 0 0 auto !important;
}
.controls-bottom .icon-btn svg,
.controls-bottom .icon-btn img {
  width: 42px !important;
  height: 42px !important;
}
.status {
  background: rgba(0, 0, 0, 0.25) !important;
  border-radius: 8px !important;
  padding: 6px 10px !important;
}

/* ============================================================
 *  Tray (zone du haut pour cartes sélectionnées)
 *  v1.0.163 — RÉDUIT (demande utilisateur : « plus large que nécessaire ») :
 *  la largeur s'ajuste au CONTENU (1 à 4 tuiles) au lieu d'un bloc fixe
 *  de 240 px — le calque inline de app.js (width:auto, align-self:center,
 *  min-width réduit à 78 px) pilote le rendu réel ; ces règles restent
 *  le filet de sécurité si un thème WP forçait le style.
 * ============================================================ */
.tray {
  width: auto !important;
  min-width: 78px !important;
  max-width: 246px !important;
  height: 72px !important;
  min-height: 72px !important;
  align-self: center !important;
  /* v1.0.51 — Bleu marine semi-transparent (alpha c2/91) assorti au top-bar */
  background: linear-gradient(111deg, #33377fc2 0%, #121fc391 100%) !important;
  border: 3px solid #ffeb3b !important;
  border-radius: 12px !important;
  display: flex !important;
  justify-content: center !important;
  align-items: center !important;
  gap: 8px !important;
  margin: 4px 0 8px 0 !important;
  padding: 0 8px !important;
  z-index: 9999 !important;
  position: relative !important;
  overflow: visible !important;
  box-shadow: 0 0 24px rgba(255, 235, 59, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.06) !important;
}

/* v1.0.60 — Animation permanente du tray : dégradé qui pulse doucement
   v1.0.61 — Opacité augmentée pour être VISIBLE au-dessus du fond bleu
   v1.0.62 — Étoiles supprimées (mouvement saccadé), seul le glow reste */
.tray::before {
  content: '' !important;
  position: absolute !important;
  inset: 0 !important;
  border-radius: 10px !important;
  background: linear-gradient(111deg, rgba(255,235,59,0.18) 0%, rgba(79,195,247,0.14) 50%, rgba(105,240,174,0.12) 100%) !important;
  animation: numat-tray-glow 3s ease-in-out infinite alternate !important;
  pointer-events: none !important;
  z-index: 1 !important;
}

@keyframes numat-tray-glow {
  0%   { opacity: 0.5; transform: scale(1); }
  50%  { opacity: 0.9; transform: scale(1.02); }
  100% { opacity: 0.6; transform: scale(1); }
}

@keyframes numat-tray-stars {
  0%   { transform: translateX(0); opacity: 0.2; }
  50%  { opacity: 0.5; }
  100% { transform: translateX(20px); opacity: 0.2; }
}

/* Animation : tray qui tremble (défaite) */
.tray.tray-shake {
  animation: tray-shake 0.5s cubic-bezier(.36,.07,.19,.97) !important;
}
@keyframes tray-shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}

/* ============================================================
 *  Board
 * ============================================================ */
#board {
  position: relative !important;
  width: 100% !important;
  height: 340px !important;
  margin-top: 4px !important;
  overflow: visible !important;
}

/* ============================================================
 *  Tuiles
 * ============================================================ */
.tile {
  position: absolute !important;
  border-radius: 8px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  font-weight: 900 !important;
  font-size: 1.8rem !important;
  color: #fff !important;
  box-shadow: 0 3px 0 rgba(0,0,0,0.55), inset 0 0 0 2px rgba(255,255,255,0.22), 0 0 0 1px rgba(0,0,0,0.25) !important;
  border: 2px solid rgba(255,255,255,0.35) !important;
  opacity: 1 !important;
  transition: transform 0.18s ease-out, box-shadow 0.18s ease-out, opacity 0.18s ease-out;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.tile:active {
  transform: scale(0.94);
}

/* Couleurs (fallback CSS — l'inline dans app.js reste prioritaire) */
.tile.c1 { background: #e53935 !important; color: #ffffff !important; }
.tile.c2 { background: #fb8c00 !important; color: #ffffff !important; }
.tile.c3 { background: #fdd835 !important; color: #1a1a1a !important; }
.tile.c4 { background: #43a047 !important; color: #ffffff !important; }
.tile.c5 { background: #00acc1 !important; color: #ffffff !important; }
.tile.c6 { background: #1e88e5 !important; color: #ffffff !important; }
.tile.c7 { background: #5e35b1 !important; color: #ffffff !important; }
.tile.c8 { background: #d81b60 !important; color: #ffffff !important; }
.tile.c9 { background: #6d4c41 !important; color: #ffffff !important; }

.tile.blocked {
  opacity: 0.45 !important;
  box-shadow: 0 2px 0 rgba(0,0,0,0.35), inset 0 0 0 1px rgba(255,255,255,0.12) !important;
}

/* Tuiles dans le tray */
.tray-tile {
  position: relative !important;
  width: 48px !important;
  height: 60px !important;
  font-size: 1.7rem !important;
  flex: 0 0 auto !important;
  /* animation inline (JS) via setAnim */
}

/* Indice : halo doré pulsé */
.tile.hint {
  outline: 3px solid #ffeb3b !important;
  outline-offset: 2px !important;
  animation: numat-pulse 0.55s ease-in-out infinite alternate !important;
}
@keyframes tray-enter {
  0%   { transform: scale(0.3) translateY(-12px); opacity: 0; }
  60%  { transform: scale(1.08) translateY(0);    opacity: 1; }
  100% { transform: scale(1)    translateY(0);    opacity: 1; }
}

/* ============================================================
 *  Animations de tuiles — keyframes (les propriétés d'anim sont inline JS avec !important)
 * ============================================================ */

/* v1.0.12 — entrée en glissant de droite à gauche avec overshoot */
@keyframes tile-slide-in {
  0%   { transform: translateX(140px) scale(0.5) rotate(8deg); opacity: 0; }
  60%  { transform: translateX(-8px) scale(1.06) rotate(-2deg); opacity: 1; }
  100% { transform: translateX(0)    scale(1)    rotate(0);    opacity: 1; }
}
/* Ancienne anim (conservée en fallback) */
@keyframes tile-fall-in {
  0%   { transform: translateY(-110px) scale(0.4) rotate(-8deg); opacity: 0; }
  60%  { transform: translateY(8px)    scale(1.05) rotate(2deg); opacity: 1; }
  100% { transform: translateY(0)      scale(1)    rotate(0);     opacity: 1; }
}

@keyframes tile-leave {
  0%   { transform: scale(1) translateY(0); opacity: 1; }
  100% { transform: scale(0.3) translateY(-26px); opacity: 0; }
}

@keyframes tile-match {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0 rgba(255, 235, 59, 0); }
  35%  { transform: scale(1.18); box-shadow: 0 0 28px 6px rgba(255, 235, 59, 0.85), 0 0 0 4px rgba(255, 255, 255, 0.6); }
  100% { transform: scale(0);   box-shadow: 0 0 0 0 rgba(255, 235, 59, 0); opacity: 0; }
}

@keyframes tile-shake {
  0%, 100% { transform: translateX(0) rotate(0); }
  20%      { transform: translateX(-6px) rotate(-4deg); }
  40%      { transform: translateX(6px)  rotate(4deg); }
  60%      { transform: translateX(-4px) rotate(-2deg); }
  80%      { transform: translateX(4px)  rotate(2deg); }
}

@keyframes numat-pulse {
  from { transform: scale(1);    filter: brightness(1); }
  to   { transform: scale(1.1); filter: brightness(1.3); }
}

@keyframes tray-enter {
  0%   { transform: scale(0.3) translateY(-12px); opacity: 0; }
  60%  { transform: scale(1.08) translateY(0);    opacity: 1; }
  100% { transform: scale(1)    translateY(0);    opacity: 1; }
}

@keyframes tray-shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}

/* v1.0.13 — paire qui s'efface ensemble dans le tray
   On utilise filter:drop-shadow() (et non box-shadow) car paintTile pose
   box-shadow inline !important, ce qui écraserait celui du keyframe. */
@keyframes pair-fade-out {
  0%   { transform: scale(1);    opacity: 1; filter: brightness(1) drop-shadow(0 0 0 rgba(255, 235, 59, 0)); }
  30%  { transform: scale(1.22); opacity: 1; filter: brightness(1.6) drop-shadow(0 0 16px rgba(255, 235, 59, 0.95)); }
  100% { transform: scale(0);    opacity: 0; filter: brightness(1) drop-shadow(0 0 0 rgba(255, 235, 59, 0)); }
}

/* ============================================================
 *  Particules (match) — propriétés d'anim inline JS avec !important
 * ============================================================ */
.particle {
  position: absolute !important;
  width: 9px !important;
  height: 9px !important;
  border-radius: 50% !important;
  pointer-events: none !important;
  z-index: 200 !important;
  display: block !important;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 6px currentColor !important;
}
@keyframes particle-fly {
  0%   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, 0))) scale(0.2); opacity: 0; }
}

/* ============================================================
 *  FEUX D'ARTIFICE (v1.0.12)
 * ============================================================ */
.firework-glow {
  position: absolute !important;
  width: 14px !important;
  height: 14px !important;
  border-radius: 50% !important;
  pointer-events: none !important;
  display: block !important;
  z-index: 60002 !important;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 12px 3px currentColor !important;
}
@keyframes firework-glow-expand {
  0%   { transform: translate(-50%, -50%) scale(1);  opacity: 1; box-shadow: 0 0 12px 3px currentColor; }
  100% { transform: translate(-50%, -50%) scale(10); opacity: 0; box-shadow: 0 0 0 0 currentColor; }
}

.firework-particle {
  position: absolute !important;
  width: 7px !important;
  height: 7px !important;
  border-radius: 50% !important;
  pointer-events: none !important;
  display: block !important;
  z-index: 60002 !important;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 8px currentColor !important;
}
@keyframes firework-fly {
  0%   { transform: translate(-50%, -50%) scale(1);   opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, 0))) scale(0.3); opacity: 0; }
}

/* ============================================================
 *  Confettis (victoire) — propriétés d'anim inline JS avec !important
 * ============================================================ */
.confetti {
  position: absolute !important;
  top: -20px !important;
  border-radius: 1px !important;
  pointer-events: none !important;
  display: block !important;
  animation-name: confetti-fall !important;
  animation-timing-function: linear !important;
  animation-fill-mode: forwards !important;
  /* animation-duration + animation-delay sont réglés inline (JS) AVEC !important */
}
@keyframes confetti-fall {
  0%   { transform: translateY(0)    rotate(0deg);   opacity: 1; }
  100% { transform: translateY(110vh) rotate(720deg); opacity: 0; }
}

/* ============================================================
 *  Flash rouge (défaite) — anim inline JS via setAnim
 * ============================================================ */
@keyframes flash-fade {
  0%   { opacity: 0; }
  30%  { opacity: 0.7; }
  100% { opacity: 0; }
}

/* ============================================================
 *  Modale (remplace alert)
 * ============================================================ */
#modal.show {
  display: flex !important;
  animation: modal-backdrop-in 0.25s ease-out !important;
}

/* v1.0.13 — modale de VICTOIRE : fond joyeux (pas noir opaque) */
#modal.modal-win-mode {
  background: radial-gradient(circle at 50% 40%, rgba(255, 213, 79, 0.95) 0%, rgba(255, 138, 101, 0.92) 55%, rgba(171, 71, 188, 0.92) 100%) !important;
}
@keyframes modal-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.modal-card {
  /* v1.0.81 — Fond bleu marine (était vert #1e3a2a). */
  background: linear-gradient(180deg, #0a1858 0%, #050d2e 100%);
  border: 2px solid #ffeb3b;
  border-radius: 18px;
  padding: 28px 24px 22px;
  max-width: 320px;
  width: 100%;
  text-align: center;
  box-shadow: 0 12px 50px rgba(0, 0, 0, 0.55), 0 0 30px rgba(255, 235, 59, 0.25);
  animation: modal-card-in 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
}
@keyframes modal-card-in {
  from { transform: scale(0.6) translateY(20px); opacity: 0; }
  to   { transform: scale(1)   translateY(0);   opacity: 1; }
}

/* v1.0.11 — modale de perte moins « tristounette » : fond doux.
   v1.0.81 — Fond bleu marine (était vert #1e3a2a). Cohérent avec les autres modales. */
.modal-card-lose {
  border-color: #ffeb3b !important;
  background: linear-gradient(180deg, #0a1858 0%, #050d2e 100%) !important;
  box-shadow: 0 12px 50px rgba(0, 0, 0, 0.55), 0 0 30px rgba(255, 235, 59, 0.25) !important;
}

.modal-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  font-weight: 900;
  margin-bottom: 12px;
}
.modal-icon-win  { background: linear-gradient(135deg, #ffd54f, #ffb300); color: #4a2a00; box-shadow: 0 0 22px rgba(255, 211, 79, 0.7); }
.modal-icon-lose { background: linear-gradient(135deg, #ef5350, #c62828); color: #fff; }
.modal-icon-info { background: linear-gradient(135deg, #4fc3f7, #0288d1); color: #fff; }

.modal-title {
  margin: 4px 0 8px 0;
  font-size: 1.25rem;
  color: #ffeb3b;
  font-weight: 800;
}
.modal-card-lose .modal-title { color: #ffeb3b !important; }

/* Mini-tuiles : les 4 cartes bloquées affichées dans la modale */
.modal-cards-row {
  display: flex !important;
  justify-content: center !important;
  gap: 8px !important;
  margin: 4px 0 18px 0 !important;
}
.mini-tile {
  width: 44px !important;
  height: 56px !important;
  border-radius: 8px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  font-size: 1.5rem !important;
  font-weight: 900 !important;
  animation: mini-tile-pop 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) both !important;
}
@keyframes mini-tile-pop {
  0%   { transform: scale(0.3) translateY(-12px); opacity: 0; }
  60%  { transform: scale(1.08) translateY(0);    opacity: 1; }
  100% { transform: scale(1)    translateY(0);    opacity: 1; }
}

/* Boutons Réanimer / Redémarrer (avec icône SVG + label) */
.modal-actions .btn-revive,
.modal-actions .btn-restart,
.modal-actions .btn-revive-disabled {
  flex: 1 !important;
  padding: 12px 8px !important;
  border: none !important;
  border-radius: 12px !important;
  font-weight: 700 !important;
  font-size: 0.9rem !important;
  cursor: pointer !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 6px !important;
  color: #fff !important;
  transition: transform 0.1s ease-out, box-shadow 0.1s ease-out !important;
}
.modal-actions .btn-revive svg,
.modal-actions .btn-restart svg { display: inline-block; }
.modal-actions .btn-revive:active,
.modal-actions .btn-restart:active {
  transform: translateY(2px) !important;
}
.btn-revive {
  background: linear-gradient(180deg, #66bb6a 0%, #43a047 100%) !important;
  box-shadow: 0 4px 0 #2e7d32 !important;
}
.btn-revive:active { box-shadow: 0 2px 0 #2e7d32 !important; }
.btn-restart {
  background: linear-gradient(180deg, #ffa726 0%, #fb8c00 100%) !important;
  box-shadow: 0 4px 0 #e65100 !important;
}
.btn-restart:active { box-shadow: 0 2px 0 #e65100 !important; }
.btn-revive-disabled {
  background: rgba(255, 255, 255, 0.08) !important;
  color: rgba(255, 255, 255, 0.4) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  cursor: not-allowed !important;
}

.modal-body {
  margin: 0 0 18px 0;
  color: #e8f5e9;
  font-size: 0.95rem;
  line-height: 1.4;
}

.modal-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.modal-actions button {
  flex: 1;
  padding: 11px 8px;
  border: none;
  border-radius: 10px;
  font-weight: 700;
  font-size: 0.9rem;
  cursor: pointer;
  transition: transform 0.12s ease-out;
}
.modal-actions button:active { transform: scale(0.95); }
.btn-primary {
  background: linear-gradient(180deg, #66bb6a, #43a047);
  color: #fff;
  box-shadow: 0 4px 0 #2e7d32;
}
.btn-secondary {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.3) !important;
}

/* ============================================================
 *  Boutons de contrôle — pastilles dorées avec icônes SVG (v1.0.11)
 * ============================================================ */
.controls {
  display: flex !important;
  gap: 8px !important;
  width: 100% !important;
  margin-top: 8px !important;
  justify-content: space-around !important;
}

/* Pastille dorée (inspiration Vita Mahjong) */
/* v1.0.13 — boutons toolbar TRANSPARENTS (pas de fond doré, juste un outline subtil).
   L'utilisateur peut déposer ses propres PNG dans assets/icons/ via <img> dans le HTML. */
/* v1.0.14 — boutons toolbar SANS bordure NI padding, juste l'image.
   L'utilisateur peut déposer ses PNG dans assets/icons/. */
.icon-btn {
  width: 44px !important;
  height: 44px !important;
  flex: 0 0 auto !important;
  padding: 0 !important;
  border: none !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #ffeb3b !important;
  box-shadow: none !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  cursor: pointer !important;
  transition: transform 0.1s ease-out, filter 0.15s ease-out !important;
  -webkit-tap-highlight-color: transparent;
}
.icon-btn:active {
  transform: scale(0.88) !important;
  filter: brightness(1.3) !important;
}
.icon-btn svg,
.icon-btn img {
  display: block !important;
  width: 34px !important;
  height: 34px !important;
  max-width: none !important;
}
.icon-btn img.svg-fallback {
  filter: brightness(0) saturate(100%) invert(89%) sepia(59%) saturate(743%) hue-rotate(360deg) brightness(105%) contrast(101%) !important;
}

/* Compat : l'ancien .numat-btn reste pour les boutons texte résiduels */
.numat-btn {
  flex: 1 !important;
  padding: 11px 6px !important;
  background: linear-gradient(180deg, #43a047 0%, #2e7d32 100%) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 9px !important;
  font-weight: 700 !important;
  font-size: 0.85rem !important;
  cursor: pointer !important;
  box-shadow: 0 3px 0 #1b5e20 !important;
  transition: transform 0.1s ease-out, box-shadow 0.1s ease-out !important;
}
.numat-btn:active {
  transform: translateY(2px) !important;
  box-shadow: 0 1px 0 #1b5e20 !important;
}

/* ============================================================
 *  v1.0.13 — Modale de VICTOIRE refondue
 *  - Carte crème sur fond joyeux (dégradé jaune→orange→violet)
 *  - Médaille dorée pulsée en icône
 *  - Titres + stats centrés, taille variable
 *  - Boutons de couleurs différentes :
 *      • .btn-replay     — bleu dégradé (Rejouer)
 *      • .btn-next-level  — vert dégradé (Niveau suivant) + chevron
 * ============================================================ */
.modal-card-win {
  background: linear-gradient(180deg, #fff8e1 0%, #fffde7 100%) !important;
  border: 3px solid #ffd54f !important;
  color: #4a2a00 !important;
  box-shadow: 0 16px 60px rgba(0, 0, 0, 0.4), 0 0 40px rgba(255, 213, 79, 0.5) !important;
  padding: 32px 24px 24px !important;
}

.win-medal {
  width: 64px !important;
  height: 64px !important;
  margin: 0 auto 12px !important;
  border-radius: 50% !important;
  background: linear-gradient(135deg, #ffd54f 0%, #ffa726 60%, #ff7043 100%) !important;
  color: #fff !important;
  font-size: 36px !important;
  font-weight: 900 !important;
  line-height: 64px !important;
  text-align: center !important;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.4), 0 0 32px 6px rgba(255, 213, 79, 0.7) !important;
  animation: win-medal-pulse 1.4s ease-in-out infinite !important;
}
@keyframes win-medal-pulse {
  0%, 100% { transform: scale(1)    rotate(0deg); }
  50%      { transform: scale(1.12) rotate(8deg); }
}

.win-title {
  margin: 4px 0 2px 0 !important;
  font-size: 1.8rem !important;
  font-weight: 900 !important;
  text-align: center !important;
  color: #5d4037 !important;
  text-shadow: 0 2px 0 rgba(255, 255, 255, 0.6) !important;
}

.win-subtitle {
  margin: 0 0 4px 0 !important;
  text-align: center !important;
  color: #6d4c41 !important;
  font-size: 1rem !important;
  font-weight: 600 !important;
}

.win-stats {
  margin: 0 0 18px 0 !important;
  text-align: center !important;
  color: #8d6e63 !important;
  font-size: 0.85rem !important;
  font-weight: 500 !important;
}

/* Boutons Rejouer (bleu) + Niveau suivant (vert) */
.modal-card-win .btn-replay,
.modal-card-win .btn-next-level {
  flex: 1 !important;
  padding: 12px 10px !important;
  border: none !important;
  border-radius: 12px !important;
  font-weight: 800 !important;
  font-size: 0.9rem !important;
  cursor: pointer !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 6px !important;
  color: #fff !important;
  transition: transform 0.1s ease-out, box-shadow 0.1s ease-out !important;
}
.modal-card-win .btn-replay {
  background: linear-gradient(180deg, #42a5f5 0%, #1976d2 100%) !important;
  box-shadow: 0 4px 0 #0d47a1 !important;
}
.modal-card-win .btn-next-level {
  background: linear-gradient(180deg, #66bb6a 0%, #43a047 100%) !important;
  box-shadow: 0 4px 0 #1b5e20 !important;
}
.modal-card-win .btn-replay:active,
.modal-card-win .btn-next-level:active {
  transform: translateY(2px) !important;
  box-shadow: 0 2px 0 currentColor !important;
}
.modal-card-win .btn-next-level svg {
  display: inline-block !important;
}

/* ============================================================
 *  v1.0.14 — Cartes à double face (face cachée)
 * ============================================================ */
.tile.face-down {
  background: linear-gradient(135deg, #1a237e 0%, #311b92 50%, #1a237e 100%) !important;
  color: #ffeb3b !important;
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.55), inset 0 0 0 2px rgba(255, 235, 59, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.25) !important;
  border: 2px solid rgba(255, 235, 59, 0.45) !important;
  position: relative;
}
.tile.face-down::after {
  /* v1.0.81 — content "?" supprimé : la carte face-cachée a DÉJÀ un dessin
   *  de colibri sur card-back.png (fourni par l'utilisateur). Le "?" jaune
   *  était en superposition inutile et masquait le colibri. Plus de content. */
  content: "";
  position: absolute;
  inset: 0;
  display: block;
  pointer-events: none;
  background: transparent !important;
}
.tile.face-down.blocked {
  opacity: 0.45 !important;
}
/* Petite animation de "retournement" */
.tile.flipping {
  animation: tile-flip 0.32s ease-in-out !important;
}
@keyframes tile-flip {
  0%   { transform: scaleX(1)   rotate(0deg); }
  50%  { transform: scaleX(0.05) rotate(2deg); }
  100% { transform: scaleX(1)   rotate(0deg); }
}

/* ============================================================
 *  v1.0.14 — Badge QI dans la barre de statut
 * ============================================================ */
.status .iq-badge {
  display: inline-flex !important;
  align-items: center !important;
  gap: 4px !important;
  padding: 2px 8px !important;
  background: linear-gradient(135deg, #ffd54f, #ff9800) !important;
  color: #4a2a00 !important;
  border-radius: 10px !important;
  font-weight: 800 !important;
  font-size: 0.85rem !important;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3), 0 0 12px rgba(255, 213, 79, 0.5) !important;
}
.status .iq-badge b {
  color: #4a2a00 !important;
  font-size: 1rem !important;
}

/* ============================================================
 *  v1.0.14 — Modale RÉGLAGES (sons, liens policy / CGU-CGV)
 * ============================================================ */
.modal-card-settings {
  /* v1.0.81 — Fond bleu marine (était vert #1e3a2a). */
  background: linear-gradient(180deg, #0a1858 0%, #050d2e 100%) !important;
  border: 2px solid #4fc3f7 !important;
  color: #fff !important;
  box-shadow: 0 12px 50px rgba(0, 0, 0, 0.55), 0 0 30px rgba(79, 195, 247, 0.3) !important;
  padding: 28px 22px 20px !important;
  text-align: center;
}
.settings-title {
  margin: 0 0 18px 0 !important;
  color: #4fc3f7 !important;
  font-size: 1.3rem !important;
  font-weight: 800 !important;
  text-align: center !important;
}
.settings-row {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  padding: 12px 4px !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
}
.settings-row:last-of-type {
  border-bottom: none !important;
}
.settings-row .label {
  color: #fff !important;
  font-size: 0.95rem !important;
  font-weight: 600 !important;
  /* v1.0.114 — FIX 11 : text-align:left pour contrer le text-align:center du parent */
  text-align: left !important;
}
.settings-link {
  color: #4fc3f7 !important;
  text-decoration: none !important;
  font-size: 0.95rem !important;
  font-weight: 600 !important;
  cursor: pointer !important;
}
.settings-link:hover {
  text-decoration: underline !important;
}

/* Toggle switch */
.toggle {
  position: relative !important;
  display: inline-block !important;
  width: 46px !important;
  height: 26px !important;
}
.toggle input {
  opacity: 0 !important;
  width: 0 !important;
  height: 0 !important;
}
.toggle .slider {
  position: absolute !important;
  cursor: pointer !important;
  inset: 0 !important;
  background: #555 !important;
  border-radius: 26px !important;
  transition: 0.25s !important;
}
.toggle .slider::before {
  content: "" !important;
  position: absolute !important;
  height: 20px !important;
  width: 20px !important;
  left: 3px !important;
  top: 3px !important;
  background: #fff !important;
  border-radius: 50% !important;
  transition: 0.25s !important;
}
.toggle input:checked + .slider {
  background: linear-gradient(180deg, #66bb6a, #43a047) !important;
}
.toggle input:checked + .slider::before {
  transform: translateX(20px) !important;
}

.btn-close-settings {
  flex: 1 !important;
  padding: 11px !important;
  background: linear-gradient(180deg, #42a5f5, #1976d2) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 10px !important;
  font-weight: 700 !important;
  font-size: 0.95rem !important;
  cursor: pointer !important;
  box-shadow: 0 3px 0 #0d47a1 !important;
  margin-top: 14px !important;
}
.btn-close-settings:active {
  transform: translateY(2px) !important;
  box-shadow: 0 1px 0 #0d47a1 !important;
}

/* ============================================================
 *  v1.0.20 — Modale d'INFO intégrée (Aide, Privacy, CGU)
 *  Affiche du contenu HTML riche SANS navigation externe
 *  → contourne splashs/takeovers serveur
 * ============================================================ */
.modal-card-info {
  /* v1.0.81 — Fond bleu marine (était vert #0d3b1e). Cohérent avec la
   *  dominante du jeu : top bar rgb(1 24 115), tray #33377f, accents jaunes. */
  background: linear-gradient(180deg, #0a1858 0%, #050d2e 100%) !important;
  border: 2px solid #ffeb3b !important;
  border-radius: 16px !important;
  max-width: 460px !important;
  width: 92% !important;
  max-height: 85vh !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
  box-shadow: 0 16px 60px rgba(0, 0, 0, 0.7), 0 0 30px rgba(255, 235, 59, 0.2) !important;
  box-sizing: border-box !important;
}
.modal-info-header {
  flex: 0 0 auto !important;
  padding: 14px 16px !important;
  border-bottom: 1px solid rgba(255, 235, 59, 0.3) !important;
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  background: rgba(0, 0, 0, 0.25) !important;
}
.modal-info-title {
  color: #ffeb3b !important;
  font-size: 1.15rem !important;
  font-weight: 800 !important;
  margin: 0 !important;
}
.modal-info-close {
  background: transparent !important;
  border: none !important;
  color: #ffeb3b !important;
  font-size: 1.6rem !important;
  cursor: pointer !important;
  padding: 0 8px !important;
  line-height: 1 !important;
  box-shadow: none !important;
}
.modal-info-close:active { transform: scale(0.9) !important; }
.modal-info-body {
  padding: 16px 20px 24px !important;
  overflow-y: auto !important;
  flex: 1 1 auto !important;
  color: #f5fff5 !important;
  font-size: 0.9rem !important;
  line-height: 1.6 !important;
  -webkit-overflow-scrolling: touch !important;
}
.modal-info-body h2 {
  color: #ffeb3b !important;
  font-size: 1.1rem !important;
  font-weight: 700 !important;
  margin: 20px 0 8px !important;
  padding-bottom: 4px !important;
  border-bottom: 1px solid rgba(255, 235, 59, 0.3) !important;
}
.modal-info-body h2:first-child { margin-top: 0 !important; }
.modal-info-body h3 {
  color: #ffd54f !important;
  font-size: 0.95rem !important;
  font-weight: 600 !important;
  margin: 14px 0 6px !important;
}
.modal-info-body p { margin: 0 0 10px !important; }
.modal-info-body ul, .modal-info-body ol { margin: 0 0 10px 22px !important; }
.modal-info-body li { margin-bottom: 5px !important; }
.modal-info-body strong { color: #ffeb3b !important; font-weight: 600 !important; }
.modal-info-body em { color: #b8d4be !important; font-style: italic !important; }
.modal-info-body a { color: #4fc3f7 !important; text-decoration: underline !important; }
.modal-info-body .highlight {
  background: rgba(255, 235, 59, 0.08) !important;
  border-left: 3px solid #ffeb3b !important;
  padding: 10px 14px !important;
  border-radius: 0 8px 8px 0 !important;
  margin: 12px 0 !important;
}
.modal-info-body .highlight-warn {
  background: rgba(255, 152, 0, 0.1) !important;
  border-left: 3px solid #ff9800 !important;
  padding: 10px 14px !important;
  border-radius: 0 8px 8px 0 !important;
  margin: 12px 0 !important;
}
.modal-info-body .card {
  background: rgba(0, 0, 0, 0.2) !important;
  border: 1px solid rgba(255, 235, 59, 0.25) !important;
  border-radius: 10px !important;
  padding: 14px !important;
  margin: 12px 0 !important;
}
.modal-info-body table {
  width: 100% !important;
  border-collapse: collapse !important;
  margin: 10px 0 16px !important;
  font-size: 0.85rem !important;
}
.modal-info-body th, .modal-info-body td {
  text-align: left !important;
  padding: 6px 8px !important;
  border: 1px solid rgba(255, 235, 59, 0.2) !important;
  color: #f5fff5 !important;
}
.modal-info-body th {
  background: rgba(255, 235, 59, 0.1) !important;
  color: #ffeb3b !important;
  font-weight: 600 !important;
}
.modal-info-body code {
  background: rgba(0, 0, 0, 0.3) !important;
  color: #ffd54f !important;
  padding: 2px 6px !important;
  border-radius: 4px !important;
  font-family: "SF Mono", "Monaco", "Consolas", monospace !important;
  font-size: 0.85rem !important;
}

/* ============================================================
 *  v1.0.23 — Paillettes (match animation) + flash + dos cartes
 * ============================================================ */

/* v1.0.37 — Confettis fins et visibles */
.sparkle {
  position: absolute !important;
  pointer-events: none !important;
  display: block !important;
  z-index: 300 !important;
  transform: translate(-50%, -50%);
  animation: confetti-burst 1.2s ease-out forwards !important;
}
.sparkle.confetti-piece {
  border-radius: 1px !important;
}
@keyframes confetti-burst {
  0% {
    transform: translate(-50%, -50%) scale(0.3) rotate(0deg);
    opacity: 1;
  }
  20% {
    transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, 0))) scale(1.3) rotate(var(--rot, 180deg));
    opacity: 1;
  }
  100% {
    transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, 0) + 100px)) scale(0.6) rotate(calc(var(--rot, 0deg) + 540deg));
    opacity: 0;
  }
}

/* Flash blanc bref entre les 2 cartes qui fusionnent */
.match-flash {
  position: absolute !important;
  width: 80px !important;
  height: 80px !important;
  border-radius: 50% !important;
  pointer-events: none !important;
  display: block !important;
  z-index: 250 !important;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255,255,255,0.9) 0%, rgba(255,235,59,0.5) 40%, rgba(255,255,255,0) 70%) !important;
  animation: match-flash-anim 0.5s ease-out forwards !important;
}
@keyframes match-flash-anim {
  0% {
    transform: translate(-50%, -50%) scale(0.3);
    opacity: 1;
  }
  50% {
    transform: translate(-50%, -50%) scale(1.5);
    opacity: 0.8;
  }
  100% {
    transform: translate(-50%, -50%) scale(2.5);
    opacity: 0;
  }
}

/* v1.0.23 — Dos des cartes cachées : filigrane avec chiffres */
.tile.face-down {
  background: linear-gradient(135deg, #1a237e 0%, #311b92 50%, #1a237e 100%) !important;
  color: #ffeb3b !important;
  /* Filigrane : petit pattern de chiffres 1-9 en fond */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill='%23ffeb3b' font-family='Arial Black, sans-serif' font-weight='900' text-anchor='middle' opacity='0.12'%3E%3Ctext x='15' y='20' font-size='14'%3E1%3C/text%3E%3Ctext x='45' y='20' font-size='14'%3E2%3C/text%3E%3Ctext x='30' y='40' font-size='14'%3E3%3C/text%3E%3Ctext x='15' y='55' font-size='14'%3E4%3C/text%3E%3Ctext x='45' y='55' font-size='14'%3E5%3C/text%3E%3C/g%3E%3C/svg%3E"), linear-gradient(135deg, #1a237e 0%, #311b92 50%, #1a237e 100%) !important;
  background-repeat: repeat, no-repeat !important;
  background-size: auto, 100% 100% !important;
  box-shadow: 0 3px 0 rgba(0,0,0,0.55), inset 0 0 0 2px rgba(255, 235, 59, 0.35), 0 0 0 1px rgba(0,0,0,0.25) !important;
  border: 2px solid rgba(255, 235, 59, 0.45) !important;
  position: relative;
}
.tile.face-down::after {
  /* v1.0.81 — content "?" supprimé : la carte face-cachée a DÉJÀ un dessin
   *  de colibri sur card-back.png (fourni par l'utilisateur). Le "?" jaune
   *  était en superposition inutile et masquait le colibri. Plus de content. */
  content: "";
  position: absolute;
  inset: 0;
  display: block;
  pointer-events: none;
  background: transparent !important;
}
.tile.face-down.blocked {
  opacity: 0.45 !important;
}

/* ============================================================
 *  v1.0.39 — SPLASH À 2 PORTES COU LISSANTES
 *  (les styles inline JS gèrent 95 % du rendu ; ces règles
 *   sont des filets de sécurité au cas où le thème WP les
 *   écraserait).
 * ============================================================ */
#numat-splash {
  position: fixed !important;
  inset: 0 !important;
  z-index: 70000 !important;
  overflow: hidden !important;
  background: transparent !important;
}
#numat-door-left,
#numat-door-right {
  position: absolute !important;
  top: 0 !important;
  width: 50% !important;
  height: 100% !important;
  transform: translateX(0) !important;
  transition: transform 0.85s cubic-bezier(0.7, 0, 0.3, 1) !important;
  will-change: transform !important;
}
#numat-door-left {
  left: 0 !important;
  box-shadow: inset -8px 0 16px rgba(0,0,0,0.6), inset -2px 0 0 0 #ffeb3b !important;
}
#numat-door-right {
  right: 0 !important;
  box-shadow: inset 8px 0 16px rgba(0,0,0,0.6), inset 2px 0 0 0 #ffeb3b !important;
}
#numat-splash-center {
  position: absolute !important;
  inset: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 14px !important;
  padding: 20px !important;
  box-sizing: border-box !important;
  z-index: 70001 !important;
  transition: opacity 0.35s ease-out !important;
}
.game-area { scrollbar-width: none !important; } .game-area::-webkit-scrollbar { display: none !important; }

/* ============================================================
 * v1.0.160 — KEYFRAMES MANQUANTES (référencées par app.js mais
 * jamais définies : les animations étaient silencieusement
 * inertes depuis leur introduction).
 *  - numat-win-slide-in : entrée de la popup « Nouveau trophée »
 *  - numat-win-fade-in  : entrée de la carte de victoire (stages 2/3)
 *  - numat-sparkle-fade : étincelles du modal victoire (elles
 *    s'accumulaient sans jamais s'estomper)
 * ============================================================ */
@keyframes numat-win-slide-in {
  0%   { opacity: 0; transform: translateY(60px) scale(0.92); }
  60%  { opacity: 1; transform: translateY(-8px) scale(1.02); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes numat-win-fade-in {
  from { opacity: 0; transform: scale(0.96) translateY(14px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes numat-sparkle-fade {
  0%   { opacity: 1; transform: scale(0.4); }
  60%  { opacity: 1; transform: scale(1.3); }
  100% { opacity: 0; transform: scale(0.2); }
}

/* ============================================================
 * v1.0.162 — MODES : Miroir / Partie Dorée / Sans Indices / Paix
 * (SPEC §5.2/§5.3/§6 — numat-modes.js)
 * ============================================================ */

/* MIROIR — le plateau s'inverse latéralement à mi-parcours.
 * Le retournement s'anime dans les DEUX sens (aller au retournement,
 * retour à la normale au niveau suivant). Chaque tuile est
 * contre-retournée pour que les CHIFFRES restent lisibles : la tuile
 * vue à gauche après l'inversion EST l'ancienne tuile de droite, et
 * le clic (hit-testing du navigateur) suit le rendu transformé. */
#board { transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); }
/* !important OBLIGATOIRE : le deal pose sur chaque tuile une animation
 * « tile-slide-in » en fill-mode both (inline, important) dont la valeur
 * finale (translateX(0) scale(1)) persiste et écraserait le contre-retour.
 * Dans la cascade CSS, une déclaration !important d'auteur bat TOUTE
 * valeur d'animation (remplissage compris) : les chiffres restent lisibles. */
#board.numat-mirror { transform: scaleX(-1) !important; }
#board.numat-mirror .tile { transform: scaleX(-1) !important; }

/* PARTIE DORÉE — liseré doré pulsant autour du plateau pendant
 * toute la partie (gain de QI doublé à la victoire). */
#board.numat-golden { animation: numat-golden-glow 2.4s ease-in-out infinite; }
@keyframes numat-golden-glow {
  0%, 100% { box-shadow: inset 0 0 30px rgba(255, 215, 0, 0.10); }
  50%      { box-shadow: 0 0 24px 4px rgba(255, 215, 0, 0.35), inset 0 0 50px rgba(255, 215, 0, 0.25); }
}

/* SANS INDICES — l'ampoule est débranchée pour le niveau :
 * grisée, hors du clic, plus de halo. */
#btnHint.numat-nohint {
  opacity: 0.35 !important;
  filter: grayscale(1) !important;
  pointer-events: none !important;
}

/* ============================================================
 * v1.0.163 — HEADER 4 BOUTONS + FENÊTRES GLISSANTES + FEU D'ARTIFICE
 * (demandes utilisateur : header refondu « SCORE / TROPHÉES / DÉFI /
 * PARTAGE » en icônes, fenêtres qui glissent du haut vers le bas,
 * feu d'artifice du match qui descend jusqu'en bas de l'écran)
 * ============================================================ */

/* ---------- 1. HEADER : rangée de 4 boutons + ligne de score ----------
 * (v1.0.164 — demande utilisateur : « il faudrait que cette top-bar soit
 * tout en haut de l'écran, supprimer les icônes et ne laisser que le
 * texte pour qu'elle soit vraiment collée en haut, ce qui ferait gagner
 * de la place pour le jeu et le plateau ») :
 *   - boutons TEXTE SEUL, UNE SEULE LIGNE (~26 px au lieu de ~48 px) ;
 *   - barre COLLÉE AU PIXEL 0 : padding-top 0 sur #numat-root, arrondis
 *     supprimés, marge haute = env(safe-area-inset-top) pour les encoches ;
 *   - gain ≈ 22 px de hauteur pour le plateau. */
.top-bar.numat-topbar {
  display: flex !important;
  flex-direction: column !important;
  /* étire les deux lignes sur toute la largeur (l'ancienne règle .top-bar
     pose align-items:center, qui en colonne RÉTRÉCIRAIT et centrerait
     les lignes au lieu de les étirer) */
  align-items: stretch !important;
  gap: 3px !important;
  width: 100% !important;
  /* v1.0.164 — collée en haut : 1 px + encoche éventuelle en haut,
     zéro arrondi (bord haute de l'écran), resserrée en bas */
  padding: calc(1px + env(safe-area-inset-top, 0px)) 4px 4px !important;
  background: rgb(1 24 115 / 63%) !important;
  border-radius: 0 !important;
  color: #fff !important;
  font-weight: 700 !important;
  font-size: 0.85rem !important;
  box-sizing: border-box !important;
  flex: 0 0 auto !important;
}
.numat-topbtns {
  display: flex !important;
  justify-content: space-between !important;
  gap: 5px !important;
}
.numat-topbtn {
  flex: 1 1 0 !important;
  min-width: 0 !important;
  min-height: 26px !important;
  border: none !important;
  border-radius: 8px !important;
  /* v1.0.164 — TEXTE SEUL : padding vertical réduit (une ligne, pas deux) */
  /* v1.0.172 — PADDING HORIZONTAL (demande utilisateur : « les 4 boutons
     du haut ne semblent pas avoir de padding, les textes touchent les
     bordures des boutons ») : 2 px → 10 px. Le texte respire enfin ;
     sur écran étroit (≤ 399 px, boutons dimensionnés au contenu) on
     garde 7 px pour que la rangée tienne sans déborder. */
  padding: 4px 10px !important;
  background: rgba(255, 255, 255, 0.08) !important;
  color: #fff !important;
  display: flex !important;
  /* v1.0.164 — rangée (était column icône+texte) : une seule ligne */
  flex-direction: row !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 4px !important;
  cursor: pointer !important;
  position: relative !important;
  -webkit-tap-highlight-color: transparent !important;
  transition: transform 0.1s ease-out, filter 0.15s ease-out !important;
  box-shadow: inset 0 0 0 1px rgba(255, 235, 59, 0.28) !important;
}
.numat-topbtn:active {
  transform: scale(0.93) !important;
  filter: brightness(1.35) !important;
}
/* v1.0.164 — icônes SUPPRIMÉES du DOM ; règle défensive au cas où un
   app.js plus ancien (ou un cache) recréerait des .numat-topbtn-ico */
.numat-topbtn-ico {
  display: none !important;
}
.numat-topbtn-lbl {
  /* v1.0.164 — texte seul → un peu plus grand que l'ancien 0.55rem
     sous icône, mais la LIGNE reste bien plus basse qu'avant */
  font-size: 0.78rem !important;
  font-weight: 800 !important;
  letter-spacing: 0.04em !important;
  text-transform: uppercase !important;
  color: #ffeb3b !important;
  white-space: nowrap !important;
  line-height: 1.2 !important;
}
/* v1.0.171 — RETOUR AUX 4 BOUTONS (demande utilisateur : « supprimer
   l'onglet classement en haut à droite » — le classement vit dans la
   fenêtre Score et dans la popup de fin de partie). Les règles
   spécifiques du 5e bouton « CLASSEMENT » (libellé réduit, police
   réduite ≤ 330 px) sont retirées ; les media queries ci-dessous
   restent en filet de sécurité pour les 4 libellés sur très petits
   écrans. */
/* v1.0.170 — écrans étroits (≤ 399 px) : largeur de contenu par
   libellé (flex 0 1 auto + space-between, règle d'origine de
   .numat-topbtns) — la ligne reste unique, rien ne déborde. */
@media (max-width: 399px) {
  /* v1.0.172 — écran étroit : boutons au contenu + padding réduit (7 px)
     pour que SCORE / TROPHÉES / DÉFI / PARTAGE tiennent sur une ligne. */
  .numat-topbtn { flex: 0 1 auto !important; padding: 4px 7px !important; }
}
/* v1.0.171 — très petits écrans (≤ 330 px, ex. 320) : police réduite
   en filet de sécurité pour les 4 boutons. */
@media (max-width: 330px) {
  .numat-topbtn-lbl { font-size: 0.68rem !important; letter-spacing: 0.02em !important; }
}
/* Badge du nombre de trophées (même id « trophyCount » qu'avant) —
   v1.0.165 — DANS le bouton, en BAS À GAUCHE (demande utilisateur :
   « il faudrait le placer dans le bouton mais en bas à gauche pour
   qu'il soit visible et ne gêne pas »). Avant : haut-droit avec
   top:-4px → depuis que la barre est collée au pixel 0 (v1.0.164),
   le badge dépassait AU-DESSUS de l'écran : chiffre tronqué par le
   bord. Maintenant : entièrement DANS le bouton, coin bas-gauche,
   légèrement réduit (14 px) + liseré blanc pour bien détacher du
   fond du bouton. */
.numat-topbtn-badge {
  position: absolute !important;
  bottom: 1px !important;
  left: 3px !important;
  top: auto !important;
  right: auto !important;
  min-width: 14px !important;
  height: 14px !important;
  padding: 0 3px !important;
  border-radius: 999px !important;
  background: linear-gradient(180deg, #ff5252, #d32f2f) !important;
  color: #fff !important;
  font-size: 0.55rem !important;
  font-weight: 900 !important;
  line-height: 1 !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  border: 1px solid rgba(255, 255, 255, 0.9) !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) !important;
  box-sizing: border-box !important;
}
/* Ligne de score (les ids level/iq/levelTimer/comboStat/remaining
   sont inchangés : tout le JS de mise à jour continue de marcher) */
.numat-scoreline {
  display: flex !important;
  flex-wrap: wrap !important;
  align-items: center !important;
  justify-content: space-between !important;
  gap: 4px 6px !important;
  font-size: 0.72rem !important;
  min-width: 0 !important;
}

/* ---------- 2. FENÊTRES GLISSANTES (du HAUT vers le bas) ----------
 * Voile : couvre le plateau sous la fenêtre — le toucher referme.
 * Fenêtre : glisse depuis au-dessus de l'écran (translate -106 %),
 * s'arrête à la position ouverte (translate 0). La carte qu'elle
 * contient (.modal-card-info / .numat-modes-card) garde ses propres
 * styles éprouvés : header titre + « × », corps scrollable. */
#numatSheetVeil {
  position: fixed !important;
  inset: 0 !important;
  background: rgba(0, 0, 0, 0.5) !important;
  z-index: 60030 !important;
  opacity: 0 !important;
  transition: opacity 0.35s ease !important;
  display: block !important;
}
#numatSheetVeil.numat-on { opacity: 1 !important; }
#numatSheet {
  position: fixed !important;
  top: 0 !important;
  left: 50% !important;
  width: min(100%, 480px) !important;
  max-height: 88vh !important;
  transform: translate(-50%, -106%) !important;
  transition: transform 0.42s cubic-bezier(0.32, 0.72, 0.28, 1) !important;
  z-index: 60031 !important;
  pointer-events: none !important;
  display: block !important;
}
#numatSheet.numat-on { transform: translate(-50%, 0) !important; }
#numatSheet > * {
  margin: 8px auto !important;
  pointer-events: auto !important;
}

/* ---------- 3. FEU D'ARTIFICE DU MATCH (v1.0.163) ----------
 * Gerbe qui monte depuis la paire, bouquet à l'apogée, puis RETOMBÉE
 * EN CASCADE jusqu'au BAS de l'écran. 100 % CSS : la trajectoire est
 * portée par --dx (écart), --up (montée, négatif), --fall (chute
 * calculée en JS = apogée → bas de l'écran). Durée ~2,05-2,55 s,
 * réglée inline par app.js. z-index 10050 : au-dessus du tray (9999)
 * et des boutons du bas (9000) → visible pendant TOUTE la chute. */
.match-fw {
  position: absolute !important;
  border-radius: 50% !important;
  pointer-events: none !important;
  display: block !important;
  z-index: 10050 !important;
  transform: translate(-50%, -50%);
  animation-name: match-fw-fly !important;
  animation-timing-function: linear !important;
  animation-fill-mode: forwards !important;
  animation-iteration-count: 1 !important;
}
@keyframes match-fw-fly {
  0% {
    transform: translate(-50%, -50%) scale(0.35);
    opacity: 1;
    animation-timing-function: cubic-bezier(0.16, 0.84, 0.44, 1);   /* montée vive */
  }
  26% {
    transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--up, -150px))) scale(1.15);
    opacity: 1;
    animation-timing-function: cubic-bezier(0.55, 0.04, 0.76, 0.62); /* gravité */
  }
  88% {
    transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--up, -150px) + var(--fall, 600px))) scale(0.95);
    opacity: 1;
  }
  100% {
    transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--up, -150px) + var(--fall, 600px))) scale(0.8);
    opacity: 0;
  }
}

/* ============================================================
 *  v1.0.176 — MODE FOCUS : barres escamotables pendant le jeu
 *  (demande utilisateur : « quand le joueur commence à cliquer sur
 *  les cartes du plateau, faire remonter les boutons du haut vers
 *  le haut et les boutons du bas vers le bas pour les faire
 *  disparaître, tant qu'il clique les cartes ; s'il n'a plus
 *  d'activité pendant 3 ou 4 secondes, ils réapparaissent »)
 *
 *  app.js pose .numat-hideui sur #numat-root dès qu'une CARTE est
 *  touchée (plateau ou tray — écouteur délégué global) et le retire
 *  après 3,5 s sans contact, ou immédiatement si une modale s'ouvre
 *  (showModal/endGame), au démarrage d'un niveau (startLevel) ou au
 *  retour dans l'app après arrière-plan.
 *
 *  Délibérément SANS reflow : transform pur sur les deux barres,
 *  l'espace qu'elles occupent est préservé → les cartes du plateau
 *  ne bougent pas d'un pixel pendant l'escamotage.
 * ============================================================ */
.top-bar.numat-topbar,
.controls-bottom {
  transition: transform 0.45s cubic-bezier(0.33, 1, 0.68, 1),
              opacity 0.45s cubic-bezier(0.33, 1, 0.68, 1) !important;
  will-change: transform, opacity;
}
/* La barre du haut REMONTE hors écran (élément dans le flux : son
   espace reste réservé, le plateau ne saute pas). */
#numat-root.numat-hideui .top-bar.numat-topbar {
  transform: translate3d(0, calc(-100% - 16px), 0) !important;
  opacity: 0 !important;
  pointer-events: none !important;
}
/* Les boutons du bas DESCENDENT hors écran. La translation Y vit
   dans CONTROLS_STYLE (app.js) via la variable --numat-slide-y :
   le transform inline !important y battant toute feuille de style,
   c'est le seul pont qui conserve le centrage translateX(-50%) ET
   permet d'animer la fuite (140 % ≈ hauteur barre + marge). */
#numat-root.numat-hideui .controls-bottom {
  --numat-slide-y: 140%;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* ============================================================
 *  v1.0.176 — TEXTE COMBO arc-en-ciel élastique
 *  (« Bien ! ×2 », « Super ! ×3 » … « Incroyable ! » — inspiré du
 *  jeu de référence : Good / Great / Unbelievable). Posé par app.js
 *  spawnComboBurst() dans #confetti-host, centré sur la paire.
 * ============================================================ */
.numat-combo-pop {
  position: absolute !important;
  transform: translate(-50%, -50%);
  font-size: 1.55rem !important;
  font-weight: 900 !important;
  letter-spacing: 0.02em !important;
  white-space: nowrap !important;
  background: linear-gradient(90deg, #ff1744, #ff9100, #ffea00, #00e676, #00e5ff, #2979ff, #7c4dff) !important;
  -webkit-background-clip: text !important;
  background-clip: text !important;
  -webkit-text-fill-color: transparent !important;
  color: transparent !important;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.7));
  pointer-events: none !important;
  z-index: 66000 !important;
  animation: numat-combo-pop 0.95s cubic-bezier(0.34, 1.56, 0.64, 1) both !important;
}
@keyframes numat-combo-pop {
  0%   { transform: translate(-50%, -50%) scale(0.2) rotate(-8deg); opacity: 0; }
  40%  { transform: translate(-50%, -50%) scale(1.18) rotate(2deg); opacity: 1; }
  65%  { transform: translate(-50%, -52%) scale(0.96) rotate(0deg); opacity: 1; }
  100% { transform: translate(-50%, -140%) scale(1.02); opacity: 0; }
}

/* ============================================================
 *  v1.0.176 — Compteur QI : halo doré pulsant
 *  (le compteur « IQ » du jeu de référence pulse doucement — même
 *  signature visuelle, en discret pour ne pas distraire du plateau).
 * ============================================================ */
.iq-badge {
  animation: numat-iq-pulse 2.8s ease-in-out infinite !important;
}
@keyframes numat-iq-pulse {
  0%, 100% { filter: drop-shadow(0 0 3px rgba(255, 213, 79, 0.45)); }
  50%      { filter: drop-shadow(0 0 10px rgba(255, 213, 79, 0.95)) brightness(1.05); }
}
