/* ============================================================
   easing-playground — motion tokens
   ------------------------------------------------------------
   Drop-in custom properties for a complete motion system:
   16 named easing curves, a 5-step duration scale, and
   ready-made recipes. MIT — copy freely.

   Usage:
     @import url("tokens.css");           (or paste the :root block)
     .toast { transition: transform var(--motion-enter); }

   Explore every curve interactively:
     https://alebrito124356.github.io/easing-playground/
   ============================================================ */

:root {

  /* ----------------------------------------------------------
     EASINGS — basics
     ---------------------------------------------------------- */

  /* Constant velocity. Only for progress bars, marquees and
     color/opacity fades. Movement with linear reads robotic. */
  --ease-linear: linear;

  /* ----------------------------------------------------------
     EASINGS — ease-out (decelerate): ENTRANCES
     Fast start, soft landing. The user gets the information
     immediately and the settle feels polished.
     ---------------------------------------------------------- */

  /* Gentlest deceleration — subtle hovers, tiny shifts. */
  --ease-out-quad: cubic-bezier(0.5, 1, 0.89, 1);

  /* The workhorse. Dropdowns, toasts, entrances. Default when in doubt. */
  --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1);

  /* More dramatic settle — modals, sheets, larger surfaces. */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);

  /* Near-instant start, long settle — hero reveals, big panels.
     Keeps long durations feeling snappy. */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

  /* Max velocity at start like expo but settles earlier —
     short, punchy micro-interactions. */
  --ease-circ-out: cubic-bezier(0, 0.55, 0.45, 1);

  /* ----------------------------------------------------------
     EASINGS — ease-in-out (accelerate + decelerate): MOVES
     For elements that are already on screen and travel to a
     new position. Symmetric launch and land.
     ---------------------------------------------------------- */

  /* Reordering, tab indicators, A-to-B moves. */
  --ease-in-out-cubic: cubic-bezier(0.65, 0, 0.35, 1);

  /* Carousels, large positional swaps. */
  --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);

  /* Almost a hard cut with cushioned ends — full-screen transitions. */
  --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1);

  /* ----------------------------------------------------------
     EASINGS — ease-in (accelerate): EXITS ONLY
     Ease-in feels laggy on anything the user is waiting for.
     The one sanctioned use: an element leaving the screen —
     it accelerates away like it was thrown. Keep it short.
     ---------------------------------------------------------- */

  --ease-in-cubic: cubic-bezier(0.32, 0, 0.67, 0);

  /* ----------------------------------------------------------
     EASINGS — overshoot & anticipation: PERSONALITY
     Use for emphasis, one per view. Everywhere = circus.
     ---------------------------------------------------------- */

  /* Overshoots ~10% and returns — playful popovers, FABs, badges. */
  --ease-back-out: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Winds up, then overshoots on arrival — attention-grabbing swaps. */
  --ease-back-in-out: cubic-bezier(0.68, -0.6, 0.32, 1.6);

  /* Pulls back ~6% before launching — telegraphs a jump. */
  --ease-anticipate: cubic-bezier(0.55, -0.35, 0.25, 1);

  /* ----------------------------------------------------------
     EASINGS — springs via linear()
     Real damped-spring physics sampled into CSS. cubic-bezier
     can only overshoot once; these oscillate like UIKit/Framer
     springs. Sampled (33 evenly spaced stops) from
       x(t) = 1 - e^(-z*w*t) * (cos(wd*t) + (z*w/wd) * sin(wd*t))
     where z = damping ratio, w = angular frequency,
     wd = w * sqrt(1 - z^2).

     Support: Chrome 113+, Edge 113+, Firefox 112+, Safari 17.2+.
     Older engines ignore the declaration — pair each spring with
     a bezier fallback on the line before it, like:
       transition-timing-function: var(--ease-back-out);
       transition-timing-function: var(--ease-spring-snappy);
     ---------------------------------------------------------- */

  /* z=0.75, w=8 — barely 3% overshoot. Calm, physical: sheets, cards. */
  --ease-spring-soft: linear(0, 0.028, 0.097, 0.191, 0.298, 0.408, 0.514, 0.612, 0.7, 0.776, 0.839, 0.891, 0.933, 0.965, 0.989, 1.006, 1.017, 1.024, 1.027, 1.028, 1.028, 1.026, 1.023, 1.02, 1.017, 1.014, 1.011, 1.009, 1.006, 1.005, 1.003, 1.002, 1);

  /* z=0.62, w=10.5 — fast attack, ~8% overshoot, quick settle.
     Buttons, toggles, chips: the classic native-app feel. */
  --ease-spring-snappy: linear(0, 0.047, 0.162, 0.311, 0.472, 0.624, 0.759, 0.87, 0.955, 1.016, 1.055, 1.076, 1.083, 1.081, 1.072, 1.06, 1.047, 1.034, 1.022, 1.013, 1.005, 1, 0.996, 0.994, 0.993, 0.993, 0.994, 0.995, 0.996, 0.997, 0.998, 0.999, 1);

  /* z=0.32, w=22 — full double bounce, ~34% overshoot.
     Celebratory moments only: success states, reactions. */
  --ease-spring-bouncy: linear(0, 0.197, 0.62, 1.031, 1.285, 1.344, 1.255, 1.104, 0.969, 0.893, 0.884, 0.92, 0.973, 1.017, 1.039, 1.039, 1.024, 1.006, 0.992, 0.986, 0.987, 0.993, 0.999, 1.003, 1.005, 1.004, 1.002, 1, 0.999, 0.998, 0.999, 0.999, 1);

  /* ----------------------------------------------------------
     DURATION SCALE
     Duration follows distance and size: the further or bigger
     the thing that moves, the longer it needs. Small elements
     on long durations feel broken; big surfaces on short
     durations feel violent.
     ---------------------------------------------------------- */

  --duration-instant: 50ms;    /* state flips: checkbox ticks, active states   */
  --duration-fast: 150ms;      /* hovers, focus rings, small fades             */
  --duration-base: 250ms;      /* most UI: dropdowns, toasts, local movement   */
  --duration-moderate: 400ms;  /* panels, drawers, modals, list reordering     */
  --duration-slow: 700ms;      /* full-screen transitions, hero reveals        */

  /* ----------------------------------------------------------
     RECIPES — duration + curve pairs for the four motion jobs.
     Each expands to "<duration> <easing>", so they slot straight
     into the transition shorthand:

       .dropdown { transition: transform var(--motion-enter),
                               opacity   var(--motion-enter); }
       .toast-leaving { transition: transform var(--motion-exit); }
     ---------------------------------------------------------- */

  /* ENTER — something appears. Decelerate: arrive fast, land soft. */
  --motion-enter: var(--duration-base) var(--ease-out-cubic);

  /* EXIT — something leaves. Faster than enter (get out of the way)
     and the only sanctioned home of ease-in. */
  --motion-exit: var(--duration-fast) var(--ease-in-cubic);

  /* MOVE — something on screen changes place. In-out: launch + land. */
  --motion-move: var(--duration-moderate) var(--ease-in-out-cubic);

  /* EMPHASIS — draw the eye. Overshoot, used at most once per view. */
  --motion-emphasis: var(--duration-moderate) var(--ease-spring-snappy);
}

/* ============================================================
   REDUCED MOTION
   Zeroing the duration tokens collapses every transition built
   on them to an instant state change — one media query covers
   the whole app. Keep decorative keyframe animations behind
   their own reduced-motion guards as well.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 0ms;
    --duration-fast: 0ms;
    --duration-base: 0ms;
    --duration-moderate: 0ms;
    --duration-slow: 0ms;
  }
}
