/* ==========================================================================
   ANIMATIONS — sobre : 2 durées, 1 easing (voir tokens). Voir DESIGN.md #9.
   ========================================================================== */

@keyframes sheet-up {
  /* `translate` (pas `transform`) : n'établit PAS de bloc conteneur pour les
     enfants `position: fixed` (le fond flouté .np-bg reste calé au viewport). */
  from { translate: 0 24px; opacity: .6; }
  to   { translate: 0 0; opacity: 1; }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes mini-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes skel-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.toast.out { opacity: 0; transform: translateY(6px); transition: opacity .2s, transform .2s; }

/* --marquee-shift (posé par views-player.js, en px négatifs) = le vrai
   débordement du titre pour CE titre précis. Un calc(-100% + 120px) fixe
   supposait toujours la même largeur de boîte -> coupait des mots sur les
   titres longs, ou glissait trop loin (par-dessus la pochette) sur les
   courts. */
@keyframes marquee {
  0%, 12%   { transform: translateX(0); }
  45%, 60%  { transform: translateX(var(--marquee-shift, 0px)); }
  92%, 100% { transform: translateX(0); }
}

/* petit cœur qui "bat" au toggle favori */
@keyframes fav-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.3); }
  100% { transform: scale(1); }
}
.fav-pop { animation: fav-pop .28s var(--ease); }

/* spinner inline */
.spinner {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--surface-3); border-top-color: var(--ink);
  animation: spin .8s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* égaliseur mini (3 barres) — décor discret */
.eq { display: inline-flex; align-items: flex-end; gap: 2px; height: 12px; }
/* `display:inline-flex` bat l'attribut [hidden] : sans cette règle, l'égaliseur
   restait peint dans le mini-player hors lecture. */
.eq[hidden] { display: none; }
.eq i { width: 2.5px; border-radius: 1px; background: var(--red); animation: eq-bounce 1s ease-in-out infinite; }
.eq i:nth-child(1) { height: 55%; animation-delay: 0s; }
.eq i:nth-child(2) { height: 100%; animation-delay: .18s; }
.eq i:nth-child(3) { height: 40%; animation-delay: .36s; }
@keyframes eq-bounce {
  0%, 100% { transform: scaleY(.35); }
  50%      { transform: scaleY(1); }
}
.eq.paused i { animation-play-state: paused; transform: scaleY(.3); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .mini-title.scroll { animation: none; }
}
