/* MOTION — spring-derived, not easing-derived.

   Apple's interface motion is spring-based. SwiftUI's default animation is a spring,
   and springs are the default for most interactions across the system: launching an
   app, pushing a detail view, presenting a sheet. A spring is specified by a
   DURATION (how long it takes to settle) and a BOUNCE (0 = no overshoot, 1 = maximum),
   not by a cubic-bezier control polygon.

   The three system presets, and the only three this system uses:

     smooth   bounce 0.00   critically damped — reaches its target without ever crossing it
     snappy   bounce 0.15   slightly underdamped — a small overshoot, the liveliest default
     bouncy   bounce 0.30   clearly underdamped — visible overshoot and a brief oscillation

   Each --ease-* value below was generated by integrating the spring equation
   (omega0 = 2*pi/duration, zeta = 1 - bounce) at duration 0.5s and sampling it into a
   CSS linear() easing. A cubic-bezier cannot express the oscillation in 'bouncy', which
   is why linear() is used. Pair each easing with its matching --duration-* token: the
   duration IS part of the spring definition, so mixing an easing with an unrelated
   duration changes the physics and breaks the feel.

   NOTE ON PROVENANCE — re-verified against motion.md, and it holds. Apple's Motion page
   publishes principles only: no easings, no durations, no spring constants, and no
   platform considerations at all for iOS, iPadOS, macOS or tvOS. The three bounce values
   and the 0.5s duration are the documented defaults of SwiftUI's spring presets, which is
   the closest thing Apple publishes to a motion specification. The generated linear()
   curves are this system's faithful conversion of them to CSS, not values Apple ships.

   The four numbers motion.md DOES publish, none of which are CSS tokens:
     • Games should hold a consistent 30–60 fps for motion to read as smooth.
     • In visionOS, avoid sustained oscillation near 0.2 Hz — people are acutely
       sensitive to that frequency. If something must oscillate, keep amplitude low and
       make the content translucent.
     • visionOS motion at the edge of the field of view causes discomfort, not just
       distraction; if an object must move in the periphery, match its brightness to the
       rest of the visible content.
     • watchOS layout and appearance animations carry built-in easing at both ends that
       cannot be turned off or customised — do not try to re-implement it.

   Two principles that constrain how these tokens get used: make motion OPTIONAL (never
   the only channel for important information — pair it with haptics or audio), and let
   people CANCEL it (never block interaction until an animation finishes). Apple also says
   to avoid adding motion to frequent UI interactions at all — the system already animates
   standard elements subtly, so a custom flourish on a common control is a tax.

   REDUCE MOTION. Apple does not say "remove animation" — accessibility.md names five specific
   techniques: tighten animation springs to REDUCE BOUNCE, track animations with the gesture that
   drives them, avoid animating depth on the z-axis, REPLACE x/y/z transitions WITH FADES, and
   avoid animating into or out of a blur. So the block at the bottom of this file keeps short
   fades alive and strips the physics: every spring becomes critically damped and non-bouncing,
   movement durations shrink rather than vanish, and the press scale is removed. */

:root {
  /* Spring settle times, measured from the simulation above. Use these with the
     matching easing; they are not interchangeable with arbitrary durations. */
  --duration-smooth: 611ms; /* @kind other */
  --duration-snappy: 570ms; /* @kind other */
  --duration-bouncy: 565ms; /* @kind other */

  /* Non-spring durations, for things that genuinely are not springs:
     opacity fades, colour changes, and indeterminate progress. */
  --duration-instant: 100ms; /* @kind other */
  --duration-fast: 200ms; /* @kind other */
  --duration-base: 300ms; /* @kind other */
  --duration-slow: 500ms; /* @kind other */

  /* The three system springs, as CSS easings */
  --ease-smooth: linear(0, 0.042 4.2%, 0.135 8.3%, 0.25 12.5%, 0.366 16.7%, 0.475 20.8%, 0.572 25%, 0.655 29.2%, 0.725 33.3%, 0.782 37.5%, 0.829 41.7%, 0.866 45.8%, 0.896 50%, 0.92 54.2%, 0.938 58.3%, 0.952 62.5%, 0.963 66.7%, 0.972 70.8%, 0.979 75%, 0.984 79.2%, 0.988 83.3%, 0.991 87.5%, 0.993 91.7%, 0.995 95.8%, 1); /* @kind other */
  --ease-snappy: linear(0, 0.038 4.2%, 0.127 8.3%, 0.241 12.5%, 0.363 16.7%, 0.48 20.8%, 0.587 25%, 0.679 29.2%, 0.758 33.3%, 0.821 37.5%, 0.872 41.7%, 0.912 45.8%, 0.942 50%, 0.964 54.2%, 0.979 58.3%, 0.99 62.5%, 0.998 66.7%, 1.002 70.8%, 1.005 75%, 1.006 79.2%, 1.006 83.3%, 1.006 87.5%, 1.005 91.7%, 1.005 95.8%, 1); /* @kind other */
  --ease-bouncy: linear(0, 0.038 4.2%, 0.131 8.3%, 0.255 12.5%, 0.389 16.7%, 0.522 20.8%, 0.643 25%, 0.749 29.2%, 0.837 33.3%, 0.906 37.5%, 0.959 41.7%, 0.997 45.8%, 1.022 50%, 1.037 54.2%, 1.044 58.3%, 1.046 62.5%, 1.044 66.7%, 1.039 70.8%, 1.034 75%, 1.027 79.2%, 1.021 83.3%, 1.016 87.5%, 1.011 91.7%, 1.007 95.8%, 1); /* @kind other */

  /* Plain easings — fades and colour only, never position or scale */
  --ease-out: cubic-bezier(0.2, 0, 0, 1); /* @kind other */
  --ease-in: cubic-bezier(0.4, 0, 1, 1); /* @kind other */
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* @kind other */

  /* Composed transitions. The split that matters: a control's COLOUR and OPACITY changes are
     fades, not springs, and want to be quick (a 570ms hover feels broken). A control part that
     physically MOVES — a switch knob, a segmented thumb — is a spring, and gets 'snappy' because
     controls must feel immediate. Navigation and sheets get 'smooth': overshoot on a large moving
     surface reads as sloppiness rather than life. */
  --transition-control: var(--duration-fast) var(--ease-out); /* colour, background, opacity @kind other */
  --transition-move: var(--duration-snappy) var(--ease-snappy); /* a control part that moves @kind other */
  --transition-nav: var(--duration-smooth) var(--ease-smooth); /* @kind other */
  --transition-sheet: var(--duration-smooth) var(--ease-smooth); /* @kind other */
  --transition-fade: var(--duration-fast) var(--ease-out); /* @kind other */

  /* Press feedback — a small scale-down, never a colour flash on iOS */
  --press-scale: 0.96; /* @kind other */
  --press-opacity: 0.4; /* @kind other */
  --hover-opacity-macos: 0.08; /* @kind other */

  /* Widget data-update animations may run up to TWO SECONDS (widgets.md > Updating
     widget content) — far longer than any in-app transition, because the point is to
     catch someone's eye on a glanceable surface they were not already watching. Do not
     borrow this for in-app motion. */
  --duration-widget-update-max: 2000ms; /* @kind other */

  /* Live Activities carry the same two-second ceiling, stated on live-activities.md
     under "Adding transitions and animating content updates". VERIFIED.

     The rule that matters more than the number: on an Always-On display with reduced
     luminance the system performs NO animations at all. So an update that only reads
     as an update because it animated will be missed entirely on a face-up iPhone or a
     dropped wrist. Make the resting state carry the information. */
  --duration-live-activity-max: 2000ms; /* @kind other */

  /* ---- LIQUID GLASS MOTION VARIES BY INPUT (motion.md, revised Sept 9 2025) ----
     VERIFIED September 2026. Glass movement "responds to direct touch interaction with
     greater emphasis to reinforce the feeling of a tactile experience, but produces a
     more subdued effect when a person interacts using a trackpad."

     So glass motion is not one curve — it is two, chosen by input modality. System
     components do this for themselves. Custom glass should scale its response the same
     way; on the web, (hover: none) and (pointer: coarse) approximate touch. */
  --glass-motion-emphasis-touch: 1; /* @kind other */
  --glass-motion-emphasis-pointer: 0.6; /* @kind other */

  /* ---- visionOS comfort limits (motion.md > visionOS) — VERIFIED ----
     The one number on the page: AVOID SUSTAINED OSCILLATION NEAR 0.2 Hz (a five-second
     period). People are unusually sensitive to that frequency and it causes discomfort,
     not just distraction. If content must oscillate, keep amplitude low and make it
     translucent.

     Also: never rotate a virtual world, even subtly and even under the person's own
     control — use an instantaneous directional change behind a quick fade instead.
     Prefer fading an object out, moving it, and fading it back in over animating it
     across the field of view. Keep motion out of the periphery; if unavoidable, match
     the object's brightness to the rest of the scene. */
  --visionos-oscillation-avoid-hz: 0.2; /* @kind other */

  /* Games: a consistent 30-60 fps is the stated target for smooth motion. */
  --game-framerate-min: 30; /* @kind other */
  --game-framerate-target: 60; /* @kind other */

  /* watchOS: layout- and appearance-based animations carry built-in easing at the start
     and end that CANNOT be turned off or customized. Do not design watch motion that
     depends on a linear curve — you will not get one. */

  /* Legacy aliases. Kept so existing rules keep working; prefer the named springs. */
  --ease-standard: var(--ease-smooth); /* @kind other */
  --ease-spring: var(--ease-smooth); /* @kind other */
  --ease-spring-snappy: var(--ease-snappy); /* @kind other */
  --duration-sheet: var(--duration-smooth); /* @kind other */
}

@media (prefers-reduced-motion: reduce) {
  :root {
    /* Springs lose their bounce and settle almost immediately — "tighten the spring",
       not "delete the animation". */
    --ease-smooth: var(--ease-out); /* @kind other */
    --ease-snappy: var(--ease-out); /* @kind other */
    --ease-bouncy: var(--ease-out); /* @kind other */
    --duration-smooth: 120ms; /* @kind other */
    --duration-snappy: 100ms; /* @kind other */
    --duration-bouncy: 100ms; /* @kind other */
    /* Fades survive intact: Apple's remedy for a movement transition IS a fade — and
       motion.md independently gives the same recipe for relocating an object, fade out,
       move, fade back in. */
    --duration-instant: 100ms; /* @kind other */
    --duration-fast: 200ms; /* @kind other */
    --duration-base: 200ms; /* @kind other */
    --duration-slow: 200ms; /* @kind other */
    /* Movement itself goes. Scale and position are the parts that cause discomfort. */
    --press-scale: 1; /* @kind other */
    --transition-move: var(--duration-snappy) var(--ease-out); /* @kind other */
    --transition-nav: var(--duration-fast) var(--ease-out); /* @kind other */
    --transition-sheet: var(--duration-fast) var(--ease-out); /* @kind other */
  }
}
