/* Motion library for ChristmasHQ — brief §25.
   All non-essential motion is gated behind prefers-reduced-motion (§17/§25).
   "Functional" state changes still occur — only the visual transitions and
   entrance animations are suppressed. */

/* ---- View entrance ---------------------------------------------------- */

@keyframes hq-fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Only fade in on a real route navigation. The router sets data-fresh="true"
   on <main id="app"> for ~500ms after every navigation and clears it after.
   Without this guard, every in-module re-render (RECORD_CHANGED, list
   refresh) would replay the fade and read as a flash. */
[data-fresh="true"] .view {
  animation: hq-fade-up var(--dur-base) var(--ease) both;
}

/* ---- Card / row stagger on first render ------------------------------- */
/* The router sets data-fresh="true" on <main id="app"> immediately before a
   route renders, and clears it ~500ms later. CSS uses that to stagger the
   entrance of stat cards and list rows on initial paint without re-staggering
   on every event-bus-driven re-render (per §25 "on first list render only").
*/

@keyframes hq-card-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

[data-fresh="true"] .stat-grid > *,
[data-fresh="true"] .list-section,
[data-fresh="true"] .recipient-grid > *,
[data-fresh="true"] .list .list-row,
[data-fresh="true"] .swipe-wrap {
  animation: hq-card-enter var(--dur-base) var(--ease) both;
}

/* Stagger up to 10 elements. After that, all subsequent items animate at the
   same delay — keeps long lists feeling lively without dragging the user
   through a 30-second cascade. */
[data-fresh="true"] .stat-grid > *:nth-child(1),
[data-fresh="true"] .list .list-row:nth-child(1),
[data-fresh="true"] .recipient-grid > *:nth-child(1),
[data-fresh="true"] .swipe-wrap:nth-child(1) { animation-delay:  0ms; }
[data-fresh="true"] .stat-grid > *:nth-child(2),
[data-fresh="true"] .list .list-row:nth-child(2),
[data-fresh="true"] .recipient-grid > *:nth-child(2),
[data-fresh="true"] .swipe-wrap:nth-child(2) { animation-delay: 30ms; }
[data-fresh="true"] .stat-grid > *:nth-child(3),
[data-fresh="true"] .list .list-row:nth-child(3),
[data-fresh="true"] .recipient-grid > *:nth-child(3),
[data-fresh="true"] .swipe-wrap:nth-child(3) { animation-delay: 60ms; }
[data-fresh="true"] .stat-grid > *:nth-child(4),
[data-fresh="true"] .list .list-row:nth-child(4),
[data-fresh="true"] .recipient-grid > *:nth-child(4),
[data-fresh="true"] .swipe-wrap:nth-child(4) { animation-delay: 90ms; }
[data-fresh="true"] .stat-grid > *:nth-child(5),
[data-fresh="true"] .list .list-row:nth-child(5),
[data-fresh="true"] .recipient-grid > *:nth-child(5),
[data-fresh="true"] .swipe-wrap:nth-child(5) { animation-delay: 120ms; }
[data-fresh="true"] .stat-grid > *:nth-child(6),
[data-fresh="true"] .list .list-row:nth-child(6),
[data-fresh="true"] .recipient-grid > *:nth-child(6),
[data-fresh="true"] .swipe-wrap:nth-child(6) { animation-delay: 150ms; }
[data-fresh="true"] .stat-grid > *:nth-child(7),
[data-fresh="true"] .list .list-row:nth-child(7),
[data-fresh="true"] .recipient-grid > *:nth-child(7),
[data-fresh="true"] .swipe-wrap:nth-child(7) { animation-delay: 180ms; }
[data-fresh="true"] .stat-grid > *:nth-child(8),
[data-fresh="true"] .list .list-row:nth-child(8),
[data-fresh="true"] .recipient-grid > *:nth-child(8),
[data-fresh="true"] .swipe-wrap:nth-child(8) { animation-delay: 210ms; }
[data-fresh="true"] .stat-grid > *:nth-child(9),
[data-fresh="true"] .list .list-row:nth-child(9),
[data-fresh="true"] .recipient-grid > *:nth-child(9),
[data-fresh="true"] .swipe-wrap:nth-child(9) { animation-delay: 240ms; }
[data-fresh="true"] .stat-grid > *:nth-child(n+10),
[data-fresh="true"] .list .list-row:nth-child(n+10),
[data-fresh="true"] .recipient-grid > *:nth-child(n+10),
[data-fresh="true"] .swipe-wrap:nth-child(n+10) { animation-delay: 270ms; }

/* ---- Checkbox bounce (delegated via JS — keyframe defined here) ------- */

@keyframes hq-check-bounce {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* ---- Update banner ---------------------------------------------------- */

#update-banner {
  transform: translateY(-100%);
  opacity: 0;
  transition: transform var(--dur-base) var(--ease), opacity var(--dur-base) var(--ease);
}
#update-banner[style*="display: block"],
#update-banner[data-shown="true"] {
  transform: translateY(0);
  opacity: 1;
}

/* ---- prefers-reduced-motion: kill non-essential motion ---------------- */

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