:root {
  --gentleduck-motion-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --gentleduck-motion-spring: linear(
    0,
    0.0018,
    0.0069 1.16%,
    0.0262 2.32%,
    0.0642,
    0.1143 5.23%,
    0.2244 7.84%,
    0.5881 15.68%,
    0.6933,
    0.7839,
    0.8591,
    0.9191 26.13%,
    0.9693,
    1.0044 31.93%,
    1.0234,
    1.0358 36.58%,
    1.0434 39.19%,
    1.046 42.39%,
    1.0446 44.71%,
    1.0404 47.61%,
    1.0118 61.84%,
    1.0028 69.39%,
    0.9981 80.42%,
    0.9991 99.87%
  );
  --gentleduck-motion-dur: 150ms;
}

/*
 * Reduced motion: collapse durations to ~0 while still firing animation/transition
 * lifecycle events so consumers (e.g. AnimatePresence, transitionend listeners) work.
 *  - 1ms duration keeps the start/end events firing.
 *  - -1ms animation-delay starts the animation already-completed (skip to the end frame)
 *    instead of holding the initial frame; intentional, not a bug.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-delay: -1ms;
    animation-duration: 1ms;
    animation-iteration-count: 1;
    scroll-behavior: auto;
    transition-delay: 0ms;
    transition-duration: 1ms;
  }
}
