/* =====================================================================
   Schulze & Co. V2.1 — motion layer (opt-in, self-contained).
   Load AFTER every other stylesheet (site.css, v2.css, content-v2.css, v21.css, nav).
   Pair with /motion/motion-v21.js (defer). See MOTION-INTEGRATION.md.

   Principles
   - One easing family: --ease-out (the house curve, also in site.css) for colour, opacity and
     lines (never overshoots); --ease-spring (about 2% overshoot) for movement only.
   - Movement uses transform / translate / scale / rotate and opacity only. Hover colour, border
     and glow changes are paint-only. Nothing here changes size or position in the layout.
   - Without JavaScript nothing is hidden: the "pending" state is written only by the script.
   - prefers-reduced-motion: reduce removes every transition and animation in this layer and
     shows all content immediately (bottom of this file).
   - Pointer effects only exist under (hover: hover) and (pointer: fine).
   - No z-index above 0 and nothing applied to html, body or main: the fixed bottom nav and
     its backdrop-filter are never affected.
   ===================================================================== */

:root {
  /* ---- easing family (shared with the bottom nav: see MOTION-INTEGRATION.md) */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --ease-in: cubic-bezier(.55, 0, .8, .25);
  /* damped spring, ~2% overshoot; generated by SchulzeMotion.core.springCurve() */
  --ease-spring: linear(0, 0.052, 0.172, 0.321, 0.471, 0.608, 0.724, 0.817, 0.888, 0.94, 0.975, 0.998, 1.011, 1.018, 1.02, 1.019, 1.017, 1.014, 1.011, 1.008, 1.006, 1.004, 1.002, 1.001, 1);

  /* ---- duration scale */
  --dur-1: 120ms;  /* press, selection, small state flips */
  --dur-2: 200ms;  /* hover colour */
  --dur-3: 320ms;  /* hover movement, glow, menu collapse */
  --dur-4: 480ms;  /* reveals, menu / mega-panel expand */
  --dur-5: 720ms;  /* hero entrance, section accent lines */

  /* ---- distances and amounts */
  --stagger: 70ms;
  --reveal-distance: 22px;
  --reveal-scale: .965;
  --enter-distance: 28px;
  --lift: -4px;
  --press: .97;

  /* ---- colour used by motion: aliases of the V2.1 palette (v21.css --glow-*, --c-accent-*), with fallbacks */
  --mo-accent: var(--c-accent, var(--accent, #355C8A));
  --mo-glow-accent: var(--glow-slate, rgba(53, 92, 138, .5));
  --mo-glow-lilac: var(--glow-lilac, rgba(183, 166, 242, .85));
  --mo-glow-mint: var(--glow-mint, rgba(159, 220, 192, .85));
  --mo-glow-peach: var(--glow-peach, rgba(246, 195, 158, .85));
  --mo-glow-sky: var(--c-accent-sky, #A9C4E8);
  --mo-sheen-light: rgba(255, 255, 255, .55);
}
@supports not (transition-timing-function: linear(0, 1)) {
  :root { --ease-spring: cubic-bezier(.3, 1.2, .55, 1); }
}
/* Small screens: shorter distances and durations, no lift. */
@media (max-width: 720px) {
  :root { --dur-4: 360ms; --dur-5: 520ms; --stagger: 40ms; --reveal-distance: 10px; --reveal-scale: .985; --enter-distance: 12px; --lift: 0px; }
}

/* ---- tint per element (default: the accent). Set on the element or any ancestor; industry tint classes map
   automatically. Read everywhere as var(--mo-tint, var(--mo-glow-accent)) so an ancestor's tint inherits. */
:where([data-motion-tint="peach"], [data-motion-tint="rose"], .v2-ind-rose, .cv2-acc-rose, .industry-rose) { --mo-tint: var(--mo-glow-peach); }
:where([data-motion-tint="mint"], [data-motion-tint="sage"], .v2-ind-sage, .cv2-acc-sage, .industry-sage) { --mo-tint: var(--mo-glow-mint); }
:where([data-motion-tint="sky"], .v2-ind-slate, .cv2-acc-slate, .industry-slate) { --mo-tint: var(--mo-glow-sky); }
:where([data-motion-tint="lilac"], .v2-ind-violet, .cv2-acc-violet, .industry-violet) { --mo-tint: var(--mo-glow-lilac); }
:where([data-motion-tint="accent"]) { --mo-tint: var(--mo-glow-accent); }

/* =====================================================================
   1. Reveals (script-driven, IntersectionObserver). Only elements the script marked
      data-motion-state="pending" are hidden, so no-JS visitors see everything.
   ===================================================================== */
[data-motion-state="pending"] { opacity: 0; translate: 0 var(--reveal-distance); }
[data-motion-state="pending"]:is([data-motion-reveal="fade"], [data-motion-stagger="fade"] > *) { translate: none; }
[data-motion-state="pending"]:is([data-motion-reveal="scale"], [data-motion-stagger="scale"] > *) { translate: 0 calc(var(--reveal-distance) / 2); scale: var(--reveal-scale); }
[data-motion-state="in"] {
  transition:
    opacity var(--dur-4) var(--ease-out) var(--mo-delay, 0ms),
    translate var(--dur-5) var(--ease-out) var(--mo-delay, 0ms),
    scale var(--dur-5) var(--ease-out) var(--mo-delay, 0ms);
  will-change: opacity, translate;
}
/* The kicker dot inside a revealed heading pops in on the spring. */
[data-motion-state="in"] .v2-kicker::before { animation: mo-pop var(--dur-4) var(--ease-spring) calc(var(--mo-delay, 0ms) + 120ms) both; }

/* Section accent: a coloured rule that draws itself across the top edge (static without JS). */
:where([data-motion-rule]) { position: relative; }
[data-motion-rule]::before {
  content: ''; position: absolute; left: 0; right: 0; top: -2px; height: 2px; z-index: 0; pointer-events: none;
  background: linear-gradient(90deg, var(--mo-accent) 0%, var(--mo-glow-lilac) 38%, var(--mo-glow-peach) 62%, transparent 100%);
  transform-origin: 0 50%;
}
[data-motion-rule="light"]::before { background: linear-gradient(90deg, #FFFFFF 0%, var(--mo-glow-sky) 40%, var(--mo-glow-lilac) 70%, transparent 100%); }
[data-motion-rule][data-motion-state="pending"] { opacity: 1; translate: none; }
[data-motion-rule][data-motion-state="pending"]::before { transform: scaleX(0); }
[data-motion-rule][data-motion-state="in"] { transition: none; will-change: auto; }
[data-motion-rule][data-motion-state="in"]::before { transition: transform var(--dur-5) var(--ease-out) var(--mo-delay, 0ms); will-change: transform; }

/* =====================================================================
   2. Entrance (CSS only, for the first screen). Plays once on load with or without JS
      and always ends fully visible. Index with style="--mo-i: n" (0–4).
   ===================================================================== */
[data-motion-enter] { animation: mo-enter var(--dur-5) var(--ease-out) calc(min(var(--mo-i, 0), 4) * var(--stagger) + 60ms) both; }
[data-motion-enter="fade"] { animation-name: mo-fade; }

@keyframes mo-enter { from { opacity: 0; translate: 0 var(--enter-distance); } to { opacity: 1; translate: none; } }
@keyframes mo-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes mo-pop { from { scale: 0; } to { scale: 1; } }

/* =====================================================================
   3. Buttons: colour-shifting hover (from the page's own tokens), coloured glow behind,
      arrow nudge, press squish. [data-motion-magnetic] adds a small lean toward the mouse.
   ===================================================================== */
:where(.btn-v2, [data-motion-magnetic]) { position: relative; isolation: isolate; }
.btn-v2, [data-motion-magnetic] {
  transition:
    background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-3) var(--ease-out), border-color var(--dur-2) var(--ease-out),
    translate var(--dur-3) var(--ease-spring), scale var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.btn-v2::after, [data-motion-magnetic]::after {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  box-shadow: 0 14px 30px -12px var(--mo-btn-glow, var(--mo-glow-accent)), 0 0 0 0 transparent;
  opacity: 0; transition: opacity var(--dur-3) var(--ease-out);
}
.btn-v2:hover::after, .btn-v2:focus-visible::after,
[data-motion-magnetic]:hover::after, [data-motion-magnetic]:focus-visible::after { opacity: 1; }
.btn-v2:active, [data-motion-magnetic]:active { scale: var(--press); }
.btn-v2 .i-arrow { transition: transform var(--dur-3) var(--ease-spring); }
/* Hover fill colours stay with the page's own rules (v21.css): this layer only times them and adds the glow.
   Ghost on light fills with ink, so its glow is a soft ink shadow. */
.btn-v2.btn-v2-ghost:hover { --mo-btn-glow: rgba(11, 11, 12, .28); }
/* On dark bands the glow is a light accent. */
:where(.v2-cta, .v21-statement, .v2-dark, [data-motion-dark]) .btn-v2 { --mo-btn-glow: rgba(141, 180, 232, .55); }
@media (hover: hover) and (pointer: fine) {
  [data-motion-magnetic] { translate: var(--mo-mx, 0px) var(--mo-my, 0px); }
}

/* =====================================================================
   4. Cards and glass panes
      [data-motion-card]  hover lift + tinted glow + border tint (CSS only)
      [data-motion-tilt]  the same, plus a small tilt toward the mouse (script)
      [data-motion-glow]  a soft light that follows the mouse inside a glass pane (script)
   ===================================================================== */
:where([data-motion-card], [data-motion-tilt], [data-motion-glow]) { position: relative; isolation: isolate; }
[data-motion-card][data-motion-card], [data-motion-tilt][data-motion-tilt] {
  transition:
    translate var(--dur-3) var(--ease-spring), transform var(--dur-3) var(--ease-spring), scale var(--dur-1) var(--ease-out),
    background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-3) var(--ease-out);
}
[data-motion-card]::after, [data-motion-tilt]::after {
  content: ''; position: absolute; inset: -1px; z-index: -1; border-radius: inherit; pointer-events: none;
  box-shadow: 0 26px 54px -22px var(--mo-tint, var(--mo-glow-accent)), 0 0 0 1px color-mix(in srgb, var(--mo-tint, var(--mo-glow-accent)) 70%, transparent);
  opacity: 0; transition: opacity var(--dur-3) var(--ease-out);
}
[data-motion-card]:is(:hover, :focus-visible)::after, [data-motion-tilt]:is(:hover, :focus-visible)::after { opacity: 1; }
[data-motion-card][data-motion-card]:is(:hover, :focus-visible), [data-motion-tilt][data-motion-tilt]:is(:hover, :focus-visible) {
  border-color: color-mix(in srgb, var(--mo-tint, var(--mo-glow-accent)) 80%, #FFFFFF);
}
[data-motion-card][data-motion-card]:active, [data-motion-tilt][data-motion-tilt]:active { scale: .99; }
@media (hover: hover) and (pointer: fine) {
  [data-motion-card][data-motion-card]:hover, [data-motion-tilt][data-motion-tilt]:hover { translate: 0 var(--lift); }
  /* Tilt replaces any hover transform on the same card (lift comes from translate above). */
  [data-motion-tilt][data-motion-tilt]:hover { transform: perspective(1000px) rotateX(var(--mo-rx, 0deg)) rotateY(var(--mo-ry, 0deg)); }
  [data-motion-tilt][data-motion-active] { will-change: transform, translate; }
}
/* Touch / no fine pointer: hooked cards keep their colour feedback but never move on (sticky) hover. */
@media not ((hover: hover) and (pointer: fine)) {
  [data-motion-card][data-motion-card]:hover, [data-motion-tilt][data-motion-tilt]:hover { transform: none; translate: none; }
}

/* Pointer-follow light inside glass panes. Moves by transform only; clipped to the pane. */
:where([data-motion-glow]) { overflow: clip; }
[data-motion-glow]::before {
  content: ''; position: absolute; left: 0; top: 0; z-index: -1; pointer-events: none;
  width: var(--mo-sheen-size, 360px); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--mo-tint, var(--mo-glow-accent)) 55%, transparent), color-mix(in srgb, var(--mo-sheen-light) 40%, transparent) 55%, transparent);
  transform: translate(calc(var(--mo-gx, 50%) - 50%), calc(var(--mo-gy, 50%) - 50%));
  opacity: 0; transition: opacity var(--dur-3) var(--ease-out);
}
:where(.v2-cta, .v21-statement, .v2-dark, [data-motion-dark]) [data-motion-glow]::before,
[data-motion-glow][data-motion-dark]::before {
  background: radial-gradient(closest-side, rgba(141, 180, 232, .32), rgba(181, 160, 239, .14) 55%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  [data-motion-glow][data-motion-active]::before { opacity: 1; will-change: transform; }
}

/* =====================================================================
   5. Small links: underline/arrow nudge on the spring (no layout change).
   ===================================================================== */
:is(.v2-link, .v21-textlink, .link-arrow) .i-arrow { transition: transform var(--dur-3) var(--ease-spring); }

/* =====================================================================
   6. Reduced motion: everything in this layer is off and all content is visible at once.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  [data-motion-state], [data-motion-state] *, [data-motion-enter], [data-motion-rule]::before,
  .btn-v2, .btn-v2::after, .btn-v2 .i-arrow, [data-motion-magnetic], [data-motion-magnetic]::after,
  [data-motion-card], [data-motion-card]::after, [data-motion-tilt], [data-motion-tilt]::after,
  [data-motion-glow], [data-motion-glow]::before, :is(.v2-link, .v21-textlink, .link-arrow) .i-arrow {
    transition: none !important; animation: none !important;
  }
  [data-motion-state], [data-motion-enter] { opacity: 1 !important; translate: none !important; scale: none !important; will-change: auto !important; }
  [data-motion-rule]::before { transform: none !important; }
  [data-motion-magnetic], [data-motion-card], [data-motion-tilt], .btn-v2 { translate: none !important; scale: none !important; }
  [data-motion-tilt] { transform: none !important; }
  [data-motion-glow]::before { opacity: 0 !important; }
}
/* Forced colours: no decorative glows. */
@media (forced-colors: active) {
  .btn-v2::after, [data-motion-magnetic]::after, [data-motion-card]::after, [data-motion-tilt]::after, [data-motion-glow]::before, [data-motion-rule]::before { display: none; }
}
