/* La Quête du Cavalier — effets (game feel) : ondes, particules, pièce projetée, secousse,
   confettis, entrée d'un niveau et vague de victoire. Tout est décoratif : base.css ramène
   les animations à presque rien quand l'utilisateur préfère les réduire, et effects.js ne
   crée alors aucun élément. Les effets posés sur une case utilisent le même repère que le
   cavalier : --px et --py (colonne, rangée), en tailles de case (--cell). */

/* ---------- Calque des effets ---------- */

.board__fx {
  position: absolute;
  inset: 0;
  z-index: 5;
  overflow: visible;
  pointer-events: none;
}

.fx-ripple,
.fx-burst,
.fx-fling {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--cell);
  height: var(--cell);
  transform: translate(calc(var(--px, 0) * var(--cell)), calc(var(--py, 0) * var(--cell)));
}

/* ---------- Onde à l'atterrissage ---------- */

.fx-ripple::before {
  content: "";
  position: absolute;
  inset: 10%;
  border: calc(var(--cell) * 0.06) solid var(--ripple, var(--gold));
  border-radius: 50%;
  opacity: 0;
  animation: fx-ripple 0.62s var(--ease) var(--delay, 0ms) both;
}

.fx--banner { --ripple: var(--banner); }

@keyframes fx-ripple {
  0% { opacity: 0.9; transform: scale(0.35); }
  100% { opacity: 0; transform: scale(1.6); }
}

/* ---------- Gerbe de particules (bannière, jalon, prise) ---------- */

.fx-particle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--cell) * 0.14);
  height: calc(var(--cell) * 0.08);
  border-radius: 2px;
  background: var(--c);
  opacity: 0;
  animation: fx-particle 0.85s cubic-bezier(0.2, 0.7, 0.3, 1) var(--delay, 0ms) both;
}

.fx-particle--round {
  width: calc(var(--cell) * 0.1);
  height: calc(var(--cell) * 0.1);
  border-radius: 50%;
}

@keyframes fx-particle {
  0% { opacity: 1; transform: translate(-50%, -50%) scale(0.5) rotate(0deg); }
  70% { opacity: 1; }
  100% {
    opacity: 0;
    transform: translate(calc(-50% + var(--dx) * var(--cell)), calc(-50% + var(--dy) * var(--cell))) scale(1) rotate(var(--rot));
  }
}

/* ---------- Pièce prise : chassée de sa case en tournoyant ---------- */

.fx-fling {
  display: grid;
  place-items: center;
}

/* Elle reste à sa place le temps que le cavalier arrive, puis s'envole et retombe. */
.fx-fling__art {
  width: 80%;
  height: 80%;
  animation: fx-fling 0.95s cubic-bezier(0.3, 0.1, 0.6, 1) var(--delay, 0ms) both;
}

@keyframes fx-fling {
  0%, 22% { opacity: 1; transform: none; }
  45% { opacity: 1; transform: translate(calc(var(--dir) * 22%), -55%) rotate(calc(var(--dir) * 70deg)) scale(1.12); }
  100% { opacity: 0; transform: translate(calc(var(--dir) * 85%), 110%) rotate(calc(var(--dir) * 240deg)) scale(0.6); }
}

/* ---------- Secousse du plateau (prise) ---------- */

.board.is-shaking { animation: fx-shake 0.34s var(--ease); }

@keyframes fx-shake {
  0%, 100% { transform: none; }
  20% { transform: translate(-3px, 1px) rotate(-0.4deg); }
  40% { transform: translate(3px, -1px) rotate(0.4deg); }
  60% { transform: translate(-2px, 0); }
  80% { transform: translate(1px, 0); }
}

/* ---------- Confettis de victoire ---------- */

.fx-confetti {
  position: absolute;
  inset: 0;
  overflow: visible;
}

.fx-confetto {
  position: absolute;
  top: -6%;
  left: var(--x);
  width: calc(var(--cell) * 0.12);
  height: calc(var(--cell) * 0.2);
  border-radius: 2px;
  background: var(--c);
  opacity: 0;
  animation: fx-confetto var(--fall, 1.6s) cubic-bezier(0.25, 0.6, 0.4, 1) var(--delay, 0ms) both;
}

.fx-confetto--round {
  height: calc(var(--cell) * 0.12);
  border-radius: 50%;
}

@keyframes fx-confetto {
  0% { opacity: 0; transform: translate(0, -20%) rotate(0deg); }
  10% { opacity: 1; }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--drift) * var(--cell)), calc(var(--rows) * var(--cell))) rotate(var(--rot)); }
}

/* ---------- Entrée d'un niveau : tuiles en cascade, cavalier qui se pose ---------- */

.board.is-entering .tile,
.board.is-entering .cell > * {
  animation: fx-tile-in 0.46s var(--ease-bounce) var(--enter, 0ms) both;
}

.board.is-entering .board__knight-art { animation: fx-knight-drop 0.55s var(--ease-bounce) 0.3s both; }

@keyframes fx-tile-in {
  from { opacity: 0; transform: scale(0.5) rotate(-6deg); }
  to { opacity: 1; transform: none; }
}

@keyframes fx-knight-drop {
  from { opacity: 0; transform: translateY(-70%) scale(1.3); }
  to { opacity: 1; transform: none; }
}

/* ---------- Victoire : le parcours se rallume case par case ---------- */

.tile.is-celebrating { animation: fx-wave 0.55s var(--ease-bounce) var(--wave, 0ms) both; }

@keyframes fx-wave {
  0% { transform: none; filter: none; }
  40% { transform: scale(1.15); filter: brightness(1.35) saturate(1.3); }
  100% { transform: none; filter: none; }
}
