/* Lean motion — opacity/transform only (compositor path for 60fps).
   Visual timing/easing unchanged; translateZ(0) promotes layers without
   changing the look. */

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeOut {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes popIn {
  from {
    opacity: 0;
    transform: translate3d(0, -3px, 0) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes popOut {
  from {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    opacity: 0;
    transform: translate3d(0, -2px, 0) scale(0.985);
  }
}

@keyframes modalIn {
  from {
    opacity: 0;
    transform: translate3d(0, 6px, 0) scale(0.99);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes modalOut {
  from {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    opacity: 0;
    transform: translate3d(0, 4px, 0) scale(0.99);
  }
}

@keyframes dashReveal {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* First paint — hold tiles until cascade starts */
html.dash-boot .topbar,
html.dash-boot .home-workflow,
html.dash-boot .streams-card,
html.dash-boot .playlist-checker {
  opacity: 0;
}

body.is-dash-revealing .dash-reveal-item {
  animation: dashReveal var(--reveal-dur, 0.48s) var(--ease-out) both;
  animation-delay: calc(var(--reveal-i, 0) * var(--reveal-stagger, 64ms));
  backface-visibility: hidden;
}

/* Toolbar pops — no layout containment while tweening */
.icon-pop:not(.hidden):not(.is-closing),
.lookup-pop:not(.hidden):not(.is-closing) {
  animation: popIn 0.18s var(--ease-out) both;
  backface-visibility: hidden;
}

.icon-pop.is-closing,
.lookup-pop.is-closing {
  animation: popOut 0.12s var(--ease-move) both;
  pointer-events: none;
  backface-visibility: hidden;
}

/* ── Shared modal enter/exit (all chrome windows) ──
   Keep timing identical to the per-file copies; this block adds GPU hints
   and covers every modal so none fall back to a paint-heavy path. */

.playlist-modal:not(.hidden) .playlist-modal-backdrop,
.mail-modal:not(.hidden) .mail-modal-backdrop,
.reposters-modal:not(.hidden) .reposters-modal-backdrop,
.tracker-modal:not(.hidden) .tracker-modal-backdrop,
.track-modal:not(.hidden):not(.is-closing) .track-modal-backdrop,
.artist-modal:not(.hidden):not(.is-closing) .artist-modal-backdrop,
.distro-modal:not(.hidden):not(.is-closing) .distro-modal-backdrop,
.dmca-modal:not(.hidden):not(.is-closing) .dmca-modal-backdrop,
.notifications-modal:not(.hidden):not(.is-closing) .notifications-modal-backdrop,
.item-modal:not(.is-closing) .item-modal-backdrop,
.settings-modal:not(.hidden) .settings-modal-backdrop {
  animation: fadeIn 0.16s var(--ease-soft) both;
  backface-visibility: hidden;
  transform: translateZ(0);
}

.playlist-modal:not(.hidden) .playlist-modal-panel,
.mail-modal:not(.hidden) .mail-modal-panel,
.reposters-modal:not(.hidden) .reposters-modal-panel,
.tracker-modal:not(.hidden) .tracker-modal-panel,
.track-modal:not(.hidden):not(.is-closing) .track-modal-panel,
.artist-modal:not(.hidden):not(.is-closing) .artist-modal-panel,
.distro-modal:not(.hidden):not(.is-closing) .distro-modal-panel,
.dmca-modal:not(.hidden):not(.is-closing) .dmca-modal-panel,
.notifications-modal:not(.hidden):not(.is-closing) .notifications-modal-panel,
.item-modal:not(.is-closing) .item-modal-panel {
  animation: modalIn 0.2s var(--ease-out) both;
  backface-visibility: hidden;
}

.playlist-modal.is-closing .playlist-modal-backdrop,
.mail-modal.is-closing .mail-modal-backdrop,
.reposters-modal.is-closing .reposters-modal-backdrop,
.tracker-modal.is-closing .tracker-modal-backdrop,
.track-modal.is-closing .track-modal-backdrop,
.artist-modal.is-closing .artist-modal-backdrop,
.distro-modal.is-closing .distro-modal-backdrop,
.dmca-modal.is-closing .dmca-modal-backdrop,
.notifications-modal.is-closing .notifications-modal-backdrop,
.item-modal.is-closing .item-modal-backdrop {
  animation: fadeOut 0.12s var(--ease-move) both;
  backface-visibility: hidden;
  transform: translateZ(0);
}

.playlist-modal.is-closing .playlist-modal-panel,
.mail-modal.is-closing .mail-modal-panel,
.reposters-modal.is-closing .reposters-modal-panel,
.tracker-modal.is-closing .tracker-modal-panel,
.track-modal.is-closing .track-modal-panel,
.artist-modal.is-closing .artist-modal-panel,
.distro-modal.is-closing .distro-modal-panel,
.dmca-modal.is-closing .dmca-modal-panel,
.notifications-modal.is-closing .notifications-modal-panel,
.item-modal.is-closing .item-modal-panel {
  animation: modalOut 0.14s var(--ease-move) both;
  backface-visibility: hidden;
}

.playlist-modal.is-closing,
.mail-modal.is-closing,
.reposters-modal.is-closing,
.tracker-modal.is-closing,
.track-modal.is-closing,
.artist-modal.is-closing,
.distro-modal.is-closing,
.dmca-modal.is-closing,
.settings-modal.is-closing,
.notifications-modal.is-closing,
.item-modal.is-closing {
  pointer-events: none;
}

/* Promote blurred scrims to their own layer (opacity fades stay smooth) */
[class*="-modal-backdrop"] {
  transform: translateZ(0);
  backface-visibility: hidden;
  isolation: isolate;
}

/* Light interactive transitions — color only stays cheap */
.icon-btn,
.chart-range-btn,
.playlist-filter button,
.notif-mark-all {
  transition:
    color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out);
}

#refresh.is-spinning svg {
  animation: spin 0.7s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  html.dash-boot .topbar,
  html.dash-boot .home-workflow,
  html.dash-boot .streams-card,
  html.dash-boot .playlist-checker {
    opacity: 1;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  #refresh.is-spinning svg {
    animation: none !important;
  }
}
