/* Motion. Five effects, no more:
     1. lattice fill/pulse during launch   — the signature moment
     2. page-load stagger                  — once, not scroll-repeated
     3. card hover lift
     4. theme toggle sun/moon morph        — see theme_toggle.css
     5. quick/advanced segment slide

   Every animation here must settle to a correct STATIC end state when reduced
   motion is on. The block at the bottom sets durations to a near-zero value
   rather than `animation: none`, because `none` on a fill-mode animation snaps
   the element back to its pre-animation state — a lattice frozen empty, or
   content stuck invisible at opacity 0. */

/* ---- 2. page-load stagger ---------------------------------------------- */
/* Applied by adding .rise to an element and --rise-index: N for the delay.
 *
 * The element's RESTING state is visible; the animation only overrides the
 * start. Written the obvious way — `from { opacity: 0 }` with fill-mode
 * backwards — the element sits at opacity 0 until the animation runs, so any
 * condition that stops it from running leaves the page permanently blank:
 * a background/hidden tab freezes the document timeline, and some privacy
 * modes suppress animations outright. Content must never depend on an
 * animation completing in order to be visible. */
@keyframes rc-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

.rise {
  /* Resting state is visible. fill-mode is `none` on purpose: `backwards` or
     `both` would apply the keyframe's opacity:0 during the delay, which is the
     same trap in slower motion. If the animation never runs, the element simply
     appears — the worst case is no animation, never invisible content. */
  opacity: 1;
  animation: rc-rise var(--dur-slow) var(--ease-out) none;
  animation-delay: calc(var(--rise-index, 0) * 40ms);
}

/* ---- 1. lattice --------------------------------------------------------- */
@keyframes rc-cell-claim {
  from { opacity: 0; transform: scale(0.6); }
  to   { opacity: 1; transform: none; }
}

/* The "we are still waiting" breath. Deliberately slow — a fast pulse next to
   an 18-minute wait reads as anxiety. */
@keyframes rc-cell-breathe {
  0%, 100% { opacity: 0.85; }
  50%      { opacity: 0.45; }
}

@keyframes rc-scan {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* ---- shared ------------------------------------------------------------- */
@keyframes rc-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes rc-pop-in {
  from { opacity: 0; transform: translateY(6px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

@keyframes rc-spin {
  to { transform: rotate(360deg); }
}

/* ---- focus -------------------------------------------------------------- */
/* One focus treatment for the whole product. :focus-visible so a mouse click
   does not leave a ring behind, but keyboard focus is always unmistakable.

   NOT written with :where(). antd emits `a:where(.css-hash):focus { outline: 0 }`,
   which has real specificity (0,2,0) — a zero-specificity :where() rule loses to
   it and keyboard users get no ring on any link inside a ConfigProvider.
   The :root prefix plus :focus-visible clears antd's rules without !important. */
:root a:focus-visible,
:root button:focus-visible,
:root input:focus-visible,
:root select:focus-visible,
:root textarea:focus-visible,
:root summary:focus-visible,
:root [tabindex]:focus-visible,
:root .ant-btn:focus-visible,
:root .ant-input:focus-visible,
:root .ant-select-selector:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
