/* ============================================================================
   Motion foundation — subtle, GPU-friendly entrance & interaction polish.
   Loaded after components.css/responsive.css so it can layer on top.

   Design rules:
   - Progressive enhancement: the "hidden" initial state for reveals applies ONLY
     under html.has-motion, which an inline head script adds *unless* the user
     prefers reduced motion (and only when JS runs). No JS / reduced motion =>
     everything is visible immediately, never hidden.
   - Durations 150–350ms, easing favours a gentle ease-out.
   ========================================================================== */

/* ---- Scroll-reveal -------------------------------------------------------- */
/* Initial (pre-reveal) state — gated on .has-motion so content is never hidden
   without JS or under reduced-motion. JS adds .is-revealed when the element
   scrolls into view. */
html.has-motion [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  will-change: opacity, transform;
}
html.has-motion [data-reveal="fade"]  { transform: none; }
html.has-motion [data-reveal="left"]  { transform: translateX(-18px); }
html.has-motion [data-reveal="right"] { transform: translateX(18px); }
html.has-motion [data-reveal="scale"] { transform: scale(0.96); }

html.has-motion [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity 340ms cubic-bezier(0.22, 1, 0.36, 1),
              transform 340ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: auto;
}

/* Safety net: if the motion script never runs (error/blocked), reveal everything
   so content can't get stuck invisible. The inline head script flips this on. */
html.motion-failed [data-reveal] { opacity: 1 !important; transform: none !important; }

/* ---- Image fade-in ------------------------------------------------------- */
img[data-fade] { opacity: 0; transition: opacity 400ms ease; }
img[data-fade].is-loaded,
html:not(.has-motion) img[data-fade] { opacity: 1; }

/* ---- Focus visibility (keyboard only) ------------------------------------ */
/* A consistent ring for non-field interactives. Form fields keep their own
   focus styling to avoid a double ring. */
:where(a, button, .btn, [role="button"], summary, [tabindex]):focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ---- Button polish (layers on existing .btn) ----------------------------- */
.btn {
  transition: background var(--transition), border-color var(--transition),
              color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}
@media (hover: hover) {
  .btn--primary:hover { transform: translateY(-1px); box-shadow: 0 8px 18px rgba(47, 83, 155, 0.18); }
}
.btn:active { transform: translateY(0.5px) scale(0.99); }

/* ---- Reduced-motion: stand down ------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  img[data-fade] { opacity: 1 !important; }
}
