/* Lean motion — opacity/transform only */

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

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

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Reusable entrance utilities (opacity/transform only) */
.u-fade-in {
  animation: fadeIn var(--dur-med) var(--ease-soft) both;
}

.u-slide-up {
  animation: slideUp var(--dur-med) var(--ease-out) both;
}

.u-pop-in {
  animation: popIn var(--dur-fast) var(--ease-out) both;
}

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

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

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

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

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

/* First paint — hold tiles until cascade starts */
html.dash-boot .topbar,
html.dash-boot .api-quota-card:not(.hidden),
html.dash-boot .notes-strip,
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));
}

/* Toolbar pops */
.icon-pop:not(.hidden):not(.is-closing),
.lookup-pop:not(.hidden):not(.is-closing) {
  animation: popIn 0.18s var(--ease-out) both;
  contain: layout style;
}

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

/* Modals */
.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,
.settings-modal:not(.hidden) .settings-modal-backdrop {
  animation: fadeIn 0.16s var(--ease-soft) both;
}

.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,
.settings-modal:not(.hidden) .settings-modal-panel {
  animation: modalIn 0.2s var(--ease-out) both;
  contain: layout style;
}

.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,
.settings-modal.is-closing .settings-modal-backdrop {
  animation: fadeOut 0.12s var(--ease-move) both;
}

.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,
.settings-modal.is-closing .settings-modal-panel {
  animation: modalOut 0.14s var(--ease-move) both;
}

.playlist-modal.is-closing,
.mail-modal.is-closing,
.reposters-modal.is-closing,
.tracker-modal.is-closing,
.settings-modal.is-closing {
  pointer-events: none;
}

/* Light interactive transitions */
.icon-btn,
.chart-range-btn,
.playlist-filter button,
.note-action,
.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 .api-quota-card:not(.hidden),
  html.dash-boot .notes-strip,
  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;
  }
}
