/* ═══════════════════════════════════════════════════════
   animations.css — Système d'animations Tangoléo

   POUR AJUSTER UNE ANIMATION : modifier les variables
   CSS ci-dessous, pas les keyframes.
   Chaque animation a son propre bloc bien délimité.
   ═══════════════════════════════════════════════════════ */

/* Coins arrondis des 4 cases d'angle — alignés sur l'arrondi de la grille,
   pour que l'anneau d'erreur / la lueur / l'indice ne soient pas rognés. */
#grid tr:first-child td:first-child .ci { border-top-left-radius: 9px; }
#grid tr:first-child td:last-child  .ci { border-top-right-radius: 9px; }
#grid tr:last-child  td:first-child .ci { border-bottom-left-radius: 9px; }
#grid tr:last-child  td:last-child  .ci { border-bottom-right-radius: 9px; }

/* ── Variables globales ────────────────────────────── */
:root {
  /* Placement d'un symbole */
  --anim-place-duration:  140ms;
  --anim-place-scale:     1.14;
  --anim-place-easing:    cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Effacement d'un symbole */
  --anim-erase-duration:  100ms;
  --anim-erase-scale:     0.82;

  /* Placement d'un indice (lueur lune) */
  --anim-hint-duration:   520ms;
  --anim-hint-color:      rgba(143, 168, 212, 0.70);

  /* Erreur (shake) */
  --anim-error-duration:  320ms;
  --anim-error-distance:  5px;

  /* Erreur — pulse continu de la surbrillance rouge */
  --anim-err-pulse-duration: 1400ms;
  --anim-err-pulse-min:      0.55; /* opacité au creux du pulse */

  /* Apparition des cellules (chargement grille) */
  --anim-cell-in-duration: 150ms;
  --anim-cell-in-easing:   cubic-bezier(0.34, 1.56, 0.64, 1);
  --anim-grid-stagger:     9ms;

  /* Cascade de victoire */
  --anim-win-duration:     500ms;
  --anim-win-color:        rgba(245, 200, 66, 0.30);
  --anim-win-stagger:      28ms;

  /* Lueur de ligne/colonne complétée */
  --anim-line-glow-duration: 600ms;
  --anim-line-glow-color:    rgba(245, 200, 66, 0.28);
  /* Anneau rouge d'erreur (doit correspondre au box-shadow .ci.err des pages) */
  --anim-err-ring:           rgba(220, 80, 60, 0.85);
  --anim-err-ring-outer:     rgba(220, 80, 60, 0.30);
  /* (le stagger de propagation est dans animations.js : ANIM_LINE_GLOW_STAGGER) */
}

/* ── Respect de prefers-reduced-motion ────────────── */
@media (prefers-reduced-motion: reduce) {
  :root {
    --anim-place-duration:   0ms;
    --anim-erase-duration:   0ms;
    --anim-error-duration:   0ms;
    --anim-cell-in-duration: 0ms;
    --anim-win-duration:     0ms;
    --anim-grid-stagger:     0ms;
    --anim-win-stagger:      0ms;
    --anim-line-glow-duration: 0ms;
    --anim-err-pulse-duration: 0ms;
    --anim-hint-duration:      0ms;
  }
}

/* ── Placement d'un symbole (seul le symbole grandit) ─ */
@keyframes anim-place-sym {
  0%   { transform: scale(1); }
  45%  { transform: scale(var(--anim-place-scale)); }
  100% { transform: scale(1); }
}
.anim-place-sym::before {
  animation: anim-place-sym var(--anim-place-duration) var(--anim-place-easing) both;
}

/* ── Placement d'un indice (lueur lune) ───────────── */
@keyframes anim-hint {
  0%   { box-shadow: inset 0 0 0 0 transparent; }
  35%  { box-shadow: inset 0 0 0 3px var(--anim-hint-color), 0 0 12px var(--anim-hint-color); }
  100% { box-shadow: inset 0 0 0 0 transparent; }
}
.anim-hint {
  animation: anim-hint var(--anim-hint-duration) ease both;
}

/* ── Effacement d'un symbole ──────────────────────── */
@keyframes anim-erase {
  0%   { transform: scale(1);                   opacity: 1; }
  40%  { transform: scale(var(--anim-erase-scale)); opacity: 0.6; }
  100% { transform: scale(1);                   opacity: 1; }
}
.anim-erase {
  animation: anim-erase var(--anim-erase-duration) ease both;
}

/* ── Erreur — shake horizontal ────────────────────── */
@keyframes anim-error {
  0%, 100% { transform: translateX(0); }
  18%      { transform: translateX(calc(-1 * var(--anim-error-distance))); }
  36%      { transform: translateX(var(--anim-error-distance)); }
  54%      { transform: translateX(calc(-0.6 * var(--anim-error-distance))); }
  72%      { transform: translateX(calc(0.4 * var(--anim-error-distance))); }
  88%      { transform: translateX(calc(-0.2 * var(--anim-error-distance))); }
}
.anim-error {
  animation: anim-error var(--anim-error-duration) cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

/* ── Apparition au chargement (stagger via --ci) ──── */
@keyframes anim-cell-in {
  0%   { transform: scale(0.72); opacity: 0; }
  100% { transform: scale(1);    opacity: 1; }
}
.anim-cell-in {
  animation: anim-cell-in var(--anim-cell-in-duration) var(--anim-cell-in-easing) both;
  animation-delay: calc(var(--ci, 0) * var(--anim-grid-stagger));
}

/* ── Flash de victoire ────────────────────────────── */
@keyframes anim-win-flash {
  0%   { background: var(--surface); }
  35%  { background: var(--anim-win-color); }
  100% { background: var(--surface); }
}
.anim-win-flash {
  animation: anim-win-flash var(--anim-win-duration) ease both;
}

/* ── Pulse synchronisé sur les cases en erreur ──────
   Une seule horloge globale (--err-pulse animée sur body)
   pilote l'opacité de TOUTES les cases en erreur → pulse
   parfaitement synchronisé, indépendant du rebuild DOM.
   Comme le pulse passe par l'opacité (et non 'animation'),
   il n'entre plus en conflit avec le shake (transform).   */
@property --err-pulse {
  syntax: '<number>';
  inherits: true;
  initial-value: 1;
}
@keyframes anim-err-pulse {
  0%, 100% { --err-pulse: 1; }
  50%      { --err-pulse: var(--anim-err-pulse-min); }
}
body {
  animation: anim-err-pulse var(--anim-err-pulse-duration) ease-in-out infinite;
}
.ci.err {
  opacity: var(--err-pulse, 1);
}

/* ── Lueur de bordure (ligne/colonne complétée) ───── */
@keyframes anim-line-glow {
  0%   { box-shadow: inset 0 0 0 0 transparent; }
  40%  { box-shadow: inset 0 0 0 2px var(--anim-line-glow-color), 0 0 10px var(--anim-line-glow-color); }
  100% { box-shadow: inset 0 0 0 0 transparent; }
}
.anim-line-glow {
  animation: anim-line-glow var(--anim-line-glow-duration) ease both;
}
/* Si la case est aussi en erreur : garder l'anneau rouge AU PREMIER PLAN
   (1re couche) et faire briller le glow doré DERRIÈRE (dernière couche). */
@keyframes anim-line-glow-err {
  0%   { box-shadow: inset 0 0 0 3px var(--anim-err-ring), 0 0 14px var(--anim-err-ring-outer); }
  40%  { box-shadow: inset 0 0 0 3px var(--anim-err-ring), 0 0 14px var(--anim-err-ring-outer), 0 0 10px var(--anim-line-glow-color); }
  100% { box-shadow: inset 0 0 0 3px var(--anim-err-ring), 0 0 14px var(--anim-err-ring-outer); }
}
.ci.err.anim-line-glow {
  animation: anim-line-glow-err var(--anim-line-glow-duration) ease both;
}
