/* ==========================================================================
   G WORLD — motion
   --------------------------------------------------------------------------
   All animation is decorative and every keyframe below is disabled inside
   `prefers-reduced-motion: reduce`, which is also asserted in the CSS review
   checklist (docs/05-security.md and docs/07-development-workflow.md).
   ========================================================================== */

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(0.6rem) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes skeleton-shimmer {
  from {
    background-position: 100% 50%;
  }
  to {
    background-position: 0 50%;
  }
}

@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(0.5rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Page content fades in once `boot()` has finished wiring the page. */
.reveal {
  animation: fade-up 260ms ease-out both;
}

.spinner {
  display: inline-block;
  inline-size: 1.1rem;
  block-size: 1.1rem;
  border: 2px solid color-mix(in srgb, currentColor 35%, transparent);
  border-block-start-color: currentColor;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
  vertical-align: -0.15em;
}

/* A "busy" element keeps its layout but shows it is working. */
[aria-busy='true'] {
  cursor: progress;
}

/* One blanket rule instead of per-component opt-outs: with reduced motion the
   UI still communicates state (toasts appear, skeletons keep their shape,
   spinners keep their label) but nothing slides, fades or loops. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
