/* motion.css — Motion + Materials token layer (Apple / Emil Kowalski philosophy).
 *
 * Orthogonal to Theme (color) and Structure (size/density): this layer owns
 * TIME (easing, duration, spring) and MATERIAL (translucency / glass / depth).
 * Consumers reference ONLY the token names below — never inline a raw curve or ms.
 * Mirrors the themes/ + structure/ idiom: fixed variable names, values are the
 * default sampling, reduced-motion / reduced-transparency baked in (a11y floor).
 *
 * WHY strong curves: the browser built-in `ease-out` is too weak to read as
 * intentional. These are the curves Apple/Emil actually ship.
 * WHY a ceiling: UI motion stays <300ms; a 180ms dropdown feels faster than 400ms.
 */

:root {
  /* ── Easing (in decision order) ───────────────────────────────────────── */
  --ease-out:      cubic-bezier(0.23, 1, 0.32, 1);      /* enter / exit — the default */
  --ease-in-out:   cubic-bezier(0.77, 0, 0.175, 1);     /* move / morph on-screen */
  --ease-drawer:   cubic-bezier(0.32, 0.72, 0, 1);      /* iOS-style drawer / sheet */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);        /* hover / color change */
  /* NEVER ease-in on UI: it delays the exact moment the user is watching.       */

  /* ── Duration scale (UI ceiling = --dur-slow; nothing slower without reason) */
  --dur-instant: 100ms;   /* button press feedback (100–160) */
  --dur-fast:    160ms;   /* tooltip / small popover / hover */
  --dur-base:    220ms;   /* dropdown / select / tab */
  --dur-slow:    320ms;   /* modal / drawer — the ceiling */

  /* ── Motion posture (Charter #16 — persona-driven; consumers gate on it) ── */
  --motion: full;         /* full | reduced | none  (Terminal≈none, Soft-SaaS=full) */

  /* ── Spring config for JS (Motion/Framer). Apple maps: damping↔bounce, response↔duration.
   *    Default = critically damped (no overshoot). Add bounce ONLY after a momentum
   *    gesture (flick/throw/drag-release), never on a menu that merely faded in.     */
  --spring-bounce:          0;      /* damping 1.0 — graceful, non-distracting default */
  --spring-duration:        0.4s;   /* Apple "response" ≈ 0.3–0.4 */
  --spring-bounce-momentum: 0.2;    /* damping ~0.8 — reserve for drag-to-dismiss / flick */

  /* ── Materials — Apple translucency ("glass"): a floating layer, not an opaque strip */
  --material-blur:     20px;
  --material-saturate: 180%;
  --glass-bg:     color-mix(in srgb, var(--surface) 72%, transparent);
  --glass-border: color-mix(in srgb, var(--text) 8%, transparent);
  /* scroll-edge fade — use INSTEAD of a 1px divider under sticky chrome */
  --scroll-edge-mask: linear-gradient(to bottom, #000 0, #000 calc(100% - 24px), transparent 100%);
}

/* Reduced motion ≠ no feedback: keep opacity/color, drop transform-based movement,
 * and collapse durations toward a gentle cross-fade. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion: reduced;
    --dur-instant: 1ms; --dur-fast: 120ms; --dur-base: 140ms; --dur-slow: 160ms;
    --spring-bounce: 0; --spring-bounce-momentum: 0;
  }
}

/* Reduced transparency: frost the glass to solid, drop the blur. */
@media (prefers-reduced-transparency: reduce) {
  :root { --material-blur: 0px; --glass-bg: var(--surface); }
}

/* ── Optional utility set (safe defaults; consumers may use or roll their own) ── */

/* Translucent chrome (Apple nav/toolbar): content scrolls UNDER it. */
.u-glass {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--material-blur)) saturate(var(--material-saturate));
  backdrop-filter: blur(var(--material-blur)) saturate(var(--material-saturate));
  border-bottom: 1px solid var(--glass-border);
}
/* Scroll-edge fade where content meets floating chrome (not a hard divider). */
.u-scroll-edge { -webkit-mask-image: var(--scroll-edge-mask); mask-image: var(--scroll-edge-mask); }

/* Button press feedback — instant, on the press; never animate from a zero scale. */
.u-press { transition: transform var(--dur-instant) var(--ease-out); }
.u-press:active { transform: scale(0.97); }

/* Popover / dropdown entrance — from the trigger, not from center. Modals stay centered. */
.u-pop {
  transform-origin: var(--transform-origin, top center);
  animation: u-pop-in var(--dur-base) var(--ease-out);
}
@keyframes u-pop-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .u-pop { animation: u-fade-in var(--dur-fast) var(--ease-standard); }
  @keyframes u-fade-in { from { opacity: 0; } to { opacity: 1; } }
}

/* Optical typography (Apple): tracking is size-specific — tighten large text, body near 0;
 * leading tracks size inversely. NEVER one letter-spacing for all sizes. */
.u-display { letter-spacing: -0.02em; line-height: 1.05; font-optical-sizing: auto; }
.u-title   { letter-spacing: -0.01em; line-height: 1.15; }
.u-body    { letter-spacing: 0;       line-height: 1.5;  }
.u-caption { letter-spacing: 0.01em;  line-height: 1.4;  }

/* Hover-gating helper: touch fires false hovers on tap — gate transform hovers. */
@media (hover: hover) and (pointer: fine) {
  .u-hover-lift { transition: transform var(--dur-fast) var(--ease-out); }
  .u-hover-lift:hover { transform: translateY(-2px); }
}
