/* ============================================================
   Corvue Design System — Interactions
   Scroll reveals, hero entrance, micro-transitions, status pulses.

   Requires tokens from colors_and_type.css.
   Pairs with reveals.js for the IntersectionObserver.
   ============================================================ */

/* ── Scroll reveal system ──────────────────────────────────
   HOW IT WORKS
   1. Add an inline <script> in <head> before the stylesheet:
        <script>document.documentElement.classList.add('js');</script>
      The `html.js` gate prevents a FOUC: if JS never runs, the hide
      rules never apply and content stays visible.
   2. Tag elements you want to animate in with `class="reveal"`.
   3. Include reveals.js at the end of body. It adds `.is-visible`
      as each target enters the viewport.
   4. Wrap groups in a parent with `class="reveal-group"` to cascade.
   5. Honours `prefers-reduced-motion: reduce` automatically.
   ────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
  html.js .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity   720ms var(--ease-out),
      transform 720ms var(--ease-out);
  }
  html.js .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  /* Stagger for grouped reveals (up to 8 children). */
  .reveal-group > .reveal:nth-child(1) { transition-delay:   0ms; }
  .reveal-group > .reveal:nth-child(2) { transition-delay:  90ms; }
  .reveal-group > .reveal:nth-child(3) { transition-delay: 180ms; }
  .reveal-group > .reveal:nth-child(4) { transition-delay: 270ms; }
  .reveal-group > .reveal:nth-child(5) { transition-delay: 360ms; }
  .reveal-group > .reveal:nth-child(6) { transition-delay: 450ms; }
  .reveal-group > .reveal:nth-child(7) { transition-delay: 540ms; }
  .reveal-group > .reveal:nth-child(8) { transition-delay: 630ms; }

  /* Tighter stagger variant for dense rows. */
  .reveal-group.is-tight > .reveal:nth-child(2) { transition-delay:  60ms; }
  .reveal-group.is-tight > .reveal:nth-child(3) { transition-delay: 120ms; }
  .reveal-group.is-tight > .reveal:nth-child(4) { transition-delay: 180ms; }
  .reveal-group.is-tight > .reveal:nth-child(5) { transition-delay: 240ms; }
  .reveal-group.is-tight > .reveal:nth-child(6) { transition-delay: 300ms; }

  /* Variants — mirror the reveal state machine but swap the transform. */
  html.js .reveal.reveal-up    { transform: translateY(14px); }
  html.js .reveal.reveal-down  { transform: translateY(-14px); }
  html.js .reveal.reveal-left  { transform: translateX(-14px); }
  html.js .reveal.reveal-right { transform: translateX(14px); }
  html.js .reveal.reveal-fade  { transform: none; }
  html.js .reveal.reveal-up.is-visible,
  html.js .reveal.reveal-down.is-visible,
  html.js .reveal.reveal-left.is-visible,
  html.js .reveal.reveal-right.is-visible,
  html.js .reveal.reveal-fade.is-visible { transform: none; }
}

/* ── Hero / page-load entrance ─────────────────────────────
   Add `class="entrance-stack"` to a container whose direct
   children should cascade in on load. Up to 5 children supported. */
@media (prefers-reduced-motion: no-preference) {
  .entrance-stack > *            { animation: entrance-in 720ms var(--ease-out) both; }
  .entrance-stack > *:nth-child(1) { animation-delay: 120ms; }
  .entrance-stack > *:nth-child(2) { animation-delay: 240ms; }
  .entrance-stack > *:nth-child(3) { animation-delay: 360ms; }
  .entrance-stack > *:nth-child(4) { animation-delay: 480ms; }
  .entrance-stack > *:nth-child(5) { animation-delay: 600ms; }
}
@keyframes entrance-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ── Micro-interactions ────────────────────────────────────
   Drop-in classes you can sprinkle on existing elements. */

/* Animated underline on hover. Works on any inline/inline-flex element
   that has `class="link-underline"`. */
.link-underline {
  position: relative;
  padding: 2px 0;
}
.link-underline::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 360ms var(--ease-out);
}
.link-underline:hover::after,
.link-underline:focus-visible::after { transform: scaleX(1); }

/* Arrow-slide on hover — pair `.arrow-host` (the hover target) with a
   nested `.arrow-glyph` (svg or text →) inside it. */
.arrow-glyph {
  display: inline-block;
  transition: transform var(--dur-2) var(--ease-out);
}
.arrow-host:hover .arrow-glyph,
.arrow-host:focus-visible .arrow-glyph { transform: translateX(2px); }

/* Gentle rotate — for a brand mark next to a wordmark. */
.rotate-on-hover {
  transition: transform 520ms var(--ease-out);
}
.rotate-on-hover:hover,
.rotate-on-hover:focus-visible { transform: rotate(45deg); }

/* ── Status-dot breathing pulses ───────────────────────────
   Apply one of these to a small round indicator. Matches the
   semantic palette from colors_and_type.css. */
@media (prefers-reduced-motion: no-preference) {
  .dot-pulse-live    { animation: dot-pulse-live    2.8s ease-in-out infinite; }
  .dot-pulse-running { animation: dot-pulse-running 2.2s ease-in-out infinite; }
  .dot-pulse-ember   { animation: dot-pulse-ember   3.6s ease-in-out infinite; }
  .dot-pulse-ink     { animation: dot-pulse-ink     3.8s ease-in-out infinite; }
}
@keyframes dot-pulse-live {
  0%, 100% { box-shadow: 0 0 0 3px rgba(63, 125, 91, 0.18); }
  50%      { box-shadow: 0 0 0 6px rgba(63, 125, 91, 0.02); }
}
@keyframes dot-pulse-running {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 78, 0, 0.00); }
  50%      { box-shadow: 0 0 0 5px rgba(245, 78, 0, 0.16); }
}
@keyframes dot-pulse-ember {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 78, 0, 0.00); }
  50%      { box-shadow: 0 0 0 4px rgba(245, 78, 0, 0.10); }
}
@keyframes dot-pulse-ink {
  0%, 100% { box-shadow: 0 0 0 0 rgba(30, 28, 20, 0.00); }
  50%      { box-shadow: 0 0 0 4px rgba(30, 28, 20, 0.08); }
}

/* ── Reduced motion — belt-and-braces ──────────────────────
   Our element rules are already gated, but this flattens any
   developer overrides too. */
@media (prefers-reduced-motion: reduce) {
  .dot-pulse-live,
  .dot-pulse-running,
  .dot-pulse-ember,
  .dot-pulse-ink,
  .entrance-stack > *,
  .rotate-on-hover { animation: none !important; transform: none !important; }
}
