/* Motion timing tokens — matches src/motion/transitions.ts */
:root {
  --motion-fast:   100ms ease-out;
  --motion-base:   200ms cubic-bezier(0.4, 0, 0.2, 1);
  --motion-slow:   300ms cubic-bezier(0.4, 0, 0.2, 1);
  --motion-bounce: 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
  --motion-spring: 350ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* Accessibility: respect user's motion preferences. All animation durations
   collapse to near-zero so layout still shifts (pure opacity:0 feels broken)
   but motion is imperceptible. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast:   0ms;
    --motion-base:   0ms;
    --motion-slow:   0ms;
    --motion-bounce: 0ms;
    --motion-spring: 0ms;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* View Transitions API — cross-fade on server-side navigation.
   Degrades gracefully on browsers without View Transitions support. */
@view-transition {
  navigation: auto;
}
::view-transition-old(root) { animation: motionFadeOut 100ms ease-out forwards; }
::view-transition-new(root) { animation: motionFadeIn  200ms ease-out forwards; }
@keyframes motionFadeOut { to { opacity: 0; } }
@keyframes motionFadeIn  { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* HTMX partial update transitions */
.htmx-swapping { opacity: 0; transition: opacity var(--motion-fast); }
.htmx-settling  { opacity: 1; transition: opacity var(--motion-base); }

/* ─────────────────────────────────────────────────────────────────────────
   Animation vocabulary — P1-A-4 (named element-level state changes)

   Six animations matched to design tokens. Use these classes consistently
   across views; do NOT author per-view custom keyframes — propose adding
   to the vocabulary instead.

   - cos-anim-enter      list/card item appears
   - cos-anim-exit       list/card item dismissed/resolved
   - cos-anim-advance    state moves forward (Now → Next)
   - cos-anim-celebrate  completion (Done, decision recorded)
   - cos-anim-surface    tooltip/popover/modal opening
   - cos-anim-pulse      fresh-arrival emphasis (SSE-driven)

   Tokens consumed: --dur-fast, --dur-base, --dur-slower,
                    --ease-out-fast, --ease-spring-card, --ease-spring-nav,
                    --status-active-tint, --accent-primary, --shadow-sm
   ───────────────────────────────────────────────────────────────────────── */

/* enter — new item appears */
@keyframes cos-anim-enter {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.cos-anim-enter {
  animation: cos-anim-enter var(--dur-base) var(--ease-spring-card) both;
}

/* exit — item dismissed/resolved */
@keyframes cos-anim-exit {
  from { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(0.96); }
}
.cos-anim-exit {
  animation: cos-anim-exit var(--dur-fast) var(--ease-out-fast) both;
}

/* advance — state moves forward (Now → Next, etc.) */
@keyframes cos-anim-advance {
  0%   { transform: translateX(0); }
  40%  { transform: translateX(4px); }
  100% { transform: translateX(0); }
}
.cos-anim-advance {
  animation: cos-anim-advance var(--dur-base) var(--ease-spring-nav) both;
}

/* celebrate — completion (decision recorded, blocker resolved) */
@keyframes cos-anim-celebrate {
  0%   { transform: scale(1); box-shadow: var(--shadow-sm); }
  40%  { transform: scale(1.04); box-shadow: 0 0 0 4px var(--status-active-tint); }
  100% { transform: scale(1); box-shadow: var(--shadow-sm); }
}
.cos-anim-celebrate {
  animation: cos-anim-celebrate var(--dur-slower) var(--ease-spring-card) both;
}

/* surface — modal/popover/tooltip opening */
@keyframes cos-anim-surface {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
.cos-anim-surface {
  animation: cos-anim-surface var(--dur-fast) var(--ease-out-fast) both;
}

/* pulse — fresh-arrival emphasis (2 cycles) */
@keyframes cos-anim-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-primary); }
  50%      { box-shadow: 0 0 0 6px transparent; }
}
.cos-anim-pulse {
  animation: cos-anim-pulse var(--dur-slower) ease-out 2;
}

/* prefers-reduced-motion: collapse vocabulary to fade-only or instant
   (the global rule above zeroes durations, but explicit collapse below
   ensures keyframe-driven motion is fully suppressed and end-state holds) */
@media (prefers-reduced-motion: reduce) {
  .cos-anim-enter,
  .cos-anim-exit,
  .cos-anim-advance,
  .cos-anim-celebrate,
  .cos-anim-surface,
  .cos-anim-pulse {
    animation: none;
  }
  .cos-anim-enter,
  .cos-anim-surface { opacity: 1; transform: none; }
  .cos-anim-exit { opacity: 0; }
}

/* ─────────────────────────────────────────────────────────────────────────
   NumberTween primitive — P1-A-4.6
   Server renders final value; client tween applies via cos-num-tween.js.
   Class establishes the contract; no animation property here (RAF-driven).
   ───────────────────────────────────────────────────────────────────────── */
.cos-num-tween {
  display: inline-block;
  font-variant-numeric: tabular-nums;
}

/* ─────────────────────────────────────────────────────────────────────────
   Hover + drag affordances — WI-P2-3 §1.5

   - cos-drag-active   pressed/lifted state for draggable elements (foothold)
   - cos-hover-shift   1px lift + shadow elevation on hover (signature delight)
   ───────────────────────────────────────────────────────────────────────── */

.cos-drag-active {
  transform: translateY(-1px) scale(1.005);
  box-shadow: var(--shadow-md);
  cursor: grabbing;
}

.cos-hover-shift {
  transition:
    transform var(--dur-fast) var(--ease-out-fast),
    box-shadow var(--dur-fast) var(--ease-out-fast),
    border-color var(--dur-fast) var(--ease-out-fast);
}
.cos-hover-shift:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
@media (prefers-reduced-motion: reduce) {
  .cos-hover-shift {
    transition: none;
  }
  .cos-hover-shift:hover {
    transform: none;
  }
}
