// motion.jsx — unified motion language shared by both ScreenSync MG pieces.
// One easing family + three duration tiers. Loaded after animations.jsx.
//
//   FAST  ~0.25–0.35s  clicks, key presses, flashes
//   MED   ~0.55–0.70s  flights, crossfades, card entrances
//   SLOW  ~0.90–1.30s  window entrances, camera moves, big reveals

const MO = { fast: 0.3, med: 0.6, slow: 1.0 };

// Gentle back-out: barely-perceptible overshoot for panels/windows.
// c1 = 0.9 ≈ 3% overshoot on the eased value — alive, never bouncy.
function softBackOut(c1 = 0.9) {
  const c3 = c1 + 1;
  return (t) => { const u = t - 1; return 1 + c3 * u * u * u + c1 * u * u; };
}

const MEase = {
  out: Easing.easeOutCubic,      // standard decelerate-into-place
  outLong: Easing.easeOutQuart,  // longer, calmer reveals & landings
  inOut: Easing.easeInOutCubic,  // moves, flights, camera pans
  in: Easing.easeInCubic,        // exits
  panel: softBackOut(0.9),       // UI panels/windows: settle with slight overshoot
  spring: softBackOut(2.0),      // click release: quick springy return past rest
};

// Quick press-down then springy release. Returns press amount 0..1;
// briefly dips slightly negative on release (overshoots past rest) then settles.
function clickPulse(t, c, down = 0.09, up = 0.3) {
  if (t < c - down || t > c + up) return 0;
  if (t <= c) return Easing.easeOutQuad((t - (c - down)) / down);
  return 1 - MEase.spring((t - c) / up);
}

// Subtle scale breathing for focal holds. `on` ramps the amplitude in (0..1)
// so the breath fades in continuously instead of popping.
function breathScale(t, on = 1, amp = 0.005, period = 3.4) {
  return 1 + amp * Math.sin((t / period) * Math.PI * 2) * clamp(on, 0, 1);
}

Object.assign(window, { MO, MEase, softBackOut, clickPulse, breathScale });
