/* ============================================================
   ANIMATIONS — le mouvement raconte quelque chose (jamais gratuit)
   ============================================================ */

/* --- Logo : tracé à l'apparition + battement continu --- */
.logo-heart__outline {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
.logo-heart.is-animated .logo-heart__outline {
  animation: logo-draw 1.1s var(--ease-soft) 0.15s forwards;
}
.logo-heart__seam {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  opacity: 0;
}
.logo-heart.is-animated .logo-heart__seam {
  animation: logo-draw 0.7s var(--ease-soft) 0.5s forwards, seam-glow 2.6s ease-in-out 1.3s infinite;
}
.logo-heart__half--left { transform-origin: 50px 45px; }
.logo-heart__half--right { transform-origin: 50px 45px; }
.logo-heart.is-animated .logo-heart__half--left {
  animation: half-slide-in-left 0.7s var(--ease-soft) both;
}
.logo-heart.is-animated .logo-heart__half--right {
  animation: half-slide-in-right 0.7s var(--ease-soft) both;
}
.logo-heart__beat {
  transform-origin: 50px 45px;
  animation: heartbeat 3.4s var(--ease-heart) infinite;
}

@keyframes logo-draw {
  to { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes seam-glow {
  0%, 100% { filter: drop-shadow(0 0 0 transparent); }
  50% { filter: drop-shadow(0 0 5px var(--color-fusion)); }
}
@keyframes half-slide-in-left {
  from { transform: translateX(-14px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
@keyframes half-slide-in-right {
  from { transform: translateX(14px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  8% { transform: scale(1.055); }
  16% { transform: scale(0.99); }
  24% { transform: scale(1.03); }
  32% { transform: scale(1); }
}

/* --- Présence de l'autre joueur : un "souffle" plutôt qu'une pastille --- */
.presence-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-other);
  display: inline-block;
  animation: breathe 2.4s ease-in-out infinite;
}
@keyframes breathe {
  0%, 100% { transform: scale(0.85); opacity: 0.6; box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-other) 50%, transparent); }
  50% { transform: scale(1.15); opacity: 1; box-shadow: 0 0 0 6px transparent; }
}

/* --- Transitions de vue : "respiration" plutôt que slide plat --- */
.view-enter {
  animation: view-in var(--dur-med) var(--ease-soft) both;
}
@keyframes view-in {
  from { opacity: 0; transform: translateY(10px) scale(0.99); filter: blur(4px); }
  to { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}

/* --- Fusion : quand les deux réponses convergent --- */
@keyframes converge-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-fusion) 55%, transparent); }
  70% { box-shadow: 0 0 0 18px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.is-converged {
  animation: converge-pulse 1.1s var(--ease-soft);
  border-color: var(--color-fusion) !important;
}

/* --- Carte qui s'envole vers l'autre joueur (validation de réponse) --- */
@keyframes fly-to-other {
  0% { transform: translate(0, 0) scale(1); opacity: 1; }
  70% { opacity: 0.9; }
  100% { transform: translate(var(--fly-x, 40px), var(--fly-y, -60px)) scale(0.35); opacity: 0; }
}
.is-flying {
  animation: fly-to-other 0.6s var(--ease-heart) forwards;
}

/* --- Hover discret sur les cartes interactives --- */
.card-hoverable {
  transition: transform var(--dur-fast) var(--ease-soft), box-shadow var(--dur-fast) var(--ease-soft), border-color var(--dur-fast) var(--ease-soft);
}
.card-hoverable:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}

/* --- Toast --- */
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.toast {
  animation: toast-in var(--dur-med) var(--ease-soft) both;
}

/* --- Entrée en cascade des cartes (bibliothèque de jeux, reprises...) --- */
.stagger-in {
  animation: stagger-in var(--dur-med) var(--ease-soft) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes stagger-in {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* --- Avatar : apparition "pop" après upload --- */
.avatar-pop {
  animation: avatar-pop 0.5s var(--ease-pop) both;
}
@keyframes avatar-pop {
  from { transform: scale(0.6); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}

/* --- Doodles : dérive lente en fond, jamais statiques --- */
.doodle {
  animation: doodle-drift 7s ease-in-out infinite;
}
@keyframes doodle-drift {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  50% { transform: translate(6px, -10px) rotate(8deg); }
}

/* --- Confettis-cœurs quand deux réponses se rencontrent --- */
.heart-particle {
  position: absolute;
  top: 50%;
  left: 50%;
  font-size: 1.1rem;
  pointer-events: none;
  animation: heart-burst 1.1s var(--ease-heart) forwards;
}
@keyframes heart-burst {
  0% { transform: translate(-50%, -50%) scale(0.4); opacity: 1; }
  100% {
    transform: translate(calc(-50% + var(--hx, 0px)), calc(-50% + var(--hy, -70px))) scale(1.1) rotate(var(--hr, 12deg));
    opacity: 0;
  }
}

/* --- Mot doux : l'enveloppe s'ouvre --- */
.note-unfold {
  animation: note-unfold var(--dur-med) var(--ease-pop) both;
}
@keyframes note-unfold {
  from { transform: scaleY(0.85); opacity: 0; }
  to { transform: scaleY(1); opacity: 1; }
}

/* --- Compteur numérique (série de jours, indice de connexion) --- */
.count-up { font-variant-numeric: tabular-nums; }

/* --- Village : une case posée "pop" à l'écran, chez les deux joueurs --- */
.tile-pop { animation: tile-pop 0.4s var(--ease-pop) both; }
@keyframes tile-pop {
  from { transform: scale(0.7); }
  to { transform: scale(1); }
}

/* --- Village : les habitants respirent doucement, jamais figés ---
   (les keyframes sont réutilisées par .village-person__body dans
   components.css — définition centralisée ici) */
@keyframes villager-idle {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-1.5px); }
}

/* --- Popups --- */
.modal-backdrop {
  animation: backdrop-in var(--dur-fast) var(--ease-soft) both;
}
.modal-backdrop .modal-card {
  animation: modal-in var(--dur-med) var(--ease-pop) both;
}
.modal-backdrop.is-closing {
  animation: backdrop-in var(--dur-fast) var(--ease-soft) reverse both;
}
.modal-backdrop.is-closing .modal-card {
  animation: modal-in 160ms var(--ease-soft) reverse both;
}
@keyframes backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(16px) scale(0.94); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* --- Pulsation douce pour attirer l'œil sur un élément neuf --- */
@keyframes soft-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}
.pulse-once {
  animation: soft-pulse 0.6s var(--ease-pop) 2;
}

/* --- Lueur qui parcourt la jauge quand elle progresse --- */
@keyframes gauge-shimmer {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-fusion) 55%, transparent); }
  100% { box-shadow: 0 0 14px 2px transparent; }
}
.gauge-bump {
  animation: gauge-shimmer 0.8s var(--ease-soft);
}


@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}
