/* ════════════════════════════════════════════════════════════
   AL MILLENNIUM — motion.css
   Site-wide cinematic motion layer. Loaded on EVERY public page
   (after components.css), so the flow that made the home page feel
   state-of-the-art now lifts the whole site to the same bar.

   Pairs with motion.js. Everything here is:
     · token-only (no raw hex, no new fonts — DESIGN_SYSTEM safe)
     · progressive (feature-detected; old engines see the static page)
     · reduced-motion-safe (all motion collapses to an instant reveal)
   Composed and slow — never bounces or springs (DESIGN_SYSTEM §7).
   ════════════════════════════════════════════════════════════ */

:root {
  --mo-ease:      cubic-bezier(0.16, 1, 0.3, 1);   /* long, cinematic decelerate */
  --mo-ease-soft: cubic-bezier(0.2, 0, 0.2, 1);    /* standard decelerate         */
  --mo-rise:      1.15s;                            /* headline line-rise duration */
}

/* ─────────────────────────────────────────────────────
   1 · BLUR-IN REVEAL UPGRADE
   The site already reveals .reveal / .reveal-group on scroll
   (animate.js toggles .vis). This adds a gentle "focus-in" — a
   small blur that resolves as the element settles — and a longer,
   more cinematic ease, lifting every existing reveal at once.
───────────────────────────────────────────────────── */
.reveal,
.reveal-group > .reveal-item {
  transition:
    opacity   0.85s var(--mo-ease),
    transform 0.95s var(--mo-ease),
    filter    0.85s ease;
}
.reveal:not(.vis),
.reveal-group:not(.vis) > .reveal-item { filter: blur(7px); }
.reveal.vis,
.reveal-group.vis > .reveal-item { filter: blur(0); }

/* ─────────────────────────────────────────────────────
   2 · GENERIC REVEAL ENGINE — [data-reveal]
   Opt-in entrance variants for any element. motion.js adds .in
   when the element scrolls into view. --rd = per-element delay.
───────────────────────────────────────────────────── */
[data-reveal] {
  opacity: 0;
  transition:
    opacity   0.9s ease            var(--rd, 0ms),
    transform var(--mo-rise) var(--mo-ease) var(--rd, 0ms),
    filter    0.9s ease            var(--rd, 0ms);
  will-change: opacity, transform;
}
[data-reveal="up"],
[data-reveal=""]        { transform: translateY(24px); }
[data-reveal="fade"]    { transform: none; }
[data-reveal="blur"]    { transform: translateY(16px); filter: blur(12px); }
[data-reveal="scale"]   { transform: scale(0.94); }
[data-reveal="left"]    { transform: translateX(-30px); }
[data-reveal="right"]   { transform: translateX(30px); }
[data-reveal].in        { opacity: 1; transform: none; filter: none; }

/* ─────────────────────────────────────────────────────
   3 · MASK / LINE REVEAL — the signature move
   motion.js wraps a heading's text in .mr-line-wrap > .mr-line.
   The line rises out from behind a clipped edge. data-reveal="mask"
   rises the whole block as one; "lines" splits on <br>. The wrap's
   tiny padding/negative-margin keeps glyph descenders from clipping
   at rest (mirrors v2.css .kw).
───────────────────────────────────────────────────── */
[data-reveal="mask"],
[data-reveal="lines"] {
  opacity: 1;            /* the container stays put; the inner line animates */
  transform: none;
  will-change: auto;
}
.mr-line-wrap {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.mr-line {
  display: block;
  transform: translateY(118%);
  opacity: 0;
  transition:
    transform var(--mo-rise) var(--mo-ease) var(--rd, 0ms),
    opacity   0.6s ease                var(--rd, 0ms);
  will-change: transform;
}
[data-reveal].in .mr-line { transform: none; opacity: 1; }

/* ─────────────────────────────────────────────────────
   4 · DECODE EYEBROW — a brief sci-fi "signal resolving" pass
   motion.js scrambles the eyebrow text then resolves it left→right
   once, when it enters view. Pure-text elements only. A faint gold
   caret rides the resolving edge.
───────────────────────────────────────────────────── */
.mo-decode { white-space: nowrap; }
.mo-decode .mo-cap {
  color: var(--gold-light);
  opacity: 0.55;
}
.mo-decode.mo-done .mo-cap { display: none; }

/* ─────────────────────────────────────────────────────
   5 · MAGNETIC CTAs
   motion.js gently pulls the primary CTAs toward the cursor.
   Here we add the matching gold halo on hover so the button
   feels lit as it reaches for you. Works with the slide-fill.
───────────────────────────────────────────────────── */
.btn-prime, .cta-prime, .featured-cta { will-change: transform; }
.btn-prime:hover,
.cta-prime:hover,
.featured-cta:hover {
  box-shadow: 0 0 34px -8px color-mix(in oklab, var(--gold-light) 55%, transparent);
}

/* ─────────────────────────────────────────────────────
   6 · SCROLL-DRIVEN PARALLAX — [data-depth]
   Native, off-main-thread depth on a framed (overflow-hidden)
   image. Progressive: only modern engines run it; everyone else
   sees the static, correctly-scaled image. Use ONLY on layers
   that don't have their own hover/JS transform.
───────────────────────────────────────────────────── */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-depth] {
      animation: mo-depth linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
    [data-depth="1"] { --mo-shift: 4%; }
    [data-depth="2"] { --mo-shift: 7%; }
    [data-depth="3"] { --mo-shift: 11%; }
    @keyframes mo-depth {
      from { transform: translateY(calc(var(--mo-shift, 6%) * -1)) scale(1.16); }
      to   { transform: translateY(var(--mo-shift, 6%)) scale(1.16); }
    }
  }
}

/* ─────────────────────────────────────────────────────
   7 · ANIMATED HAIRLINE — [data-rule]
   A gold divider that draws itself in from the centre when seen.
───────────────────────────────────────────────────── */
[data-rule] {
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 1s var(--mo-ease) var(--rd, 0ms);
}
[data-rule].in { transform: scaleX(1); }

/* ─────────────────────────────────────────────────────
   8 · CONSISTENT FOCUS RING (accessibility + polish)
   A single gold focus-visible treatment across interactive
   elements. Components that style their own focus (e.g. the
   lens cards in v2.css, loaded after this) still win.
───────────────────────────────────────────────────── */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 1px solid var(--gold-light);
  outline-offset: 3px;
}

/* ─────────────────────────────────────────────────────
   9 · INTERACTIVE 3D TILT — [data-tilt]
   Cards lean in 3D toward the cursor (motion.js drives the
   transform via rAF; CSS only smooths the lift + return).
   Desktop fine-pointer only; collapses for reduced motion.
───────────────────────────────────────────────────── */
[data-tilt] {
  transform-style: preserve-3d;
  transition: box-shadow 0.45s var(--mo-ease);
}
[data-tilt].tilting {
  box-shadow: 0 30px 60px -32px rgba(0,0,0,0.8);
  z-index: 1;
}
/* a soft gold light that tracks the cursor across the tilted card —
   kept deliberately subtle (a faint sheen, not a heavy gloss) */
[data-tilt] > .tilt-sheen {
  content: ''; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  opacity: 0; transition: opacity 0.4s ease;
  background: radial-gradient(150px circle at var(--gx, 50%) var(--gy, 50%),
    color-mix(in oklab, var(--gold-light) 9%, transparent), transparent 62%);
  mix-blend-mode: screen;
}
[data-tilt].tilting > .tilt-sheen { opacity: 0.5; }

/* ─────────────────────────────────────────────────────
   10 · CLIP REVEAL — [data-reveal="clip"]
   A cinematic curtain: the image wipes up into view.
───────────────────────────────────────────────────── */
[data-reveal="clip"] {
  opacity: 1;
  transform: none;
  clip-path: inset(100% 0 0 0);
  transition: clip-path 1.15s var(--mo-ease) var(--rd, 0ms);
  will-change: clip-path;
}
[data-reveal="clip"].in { clip-path: inset(0 0 0 0); }

/* ─────────────────────────────────────────────────────
   11 · RICHER PAGE TRANSITION — gilded curtain
   enhancements.js fades a full-screen .page-curtain on every
   page load (and hides it after ~0.6s). These are pseudo-only
   additions (no competing rule, no !important, no JS change):
   a faint gold bloom + a single gold scan-line so the brief
   veil reads as cinematic instead of a flat dark flash.
───────────────────────────────────────────────────── */
.page-curtain.curtain-cinematic::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at 50% 46%,
    color-mix(in oklab, var(--gold-light) 13%, transparent), transparent 56%);
}
.page-curtain.curtain-cinematic::after {
  content: ''; position: absolute; left: 0; right: 0; height: 1px; top: 0; pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--gold-light) 70%, transparent), transparent);
  animation: mo-curtain-scan 0.85s var(--mo-ease) forwards;
}
@keyframes mo-curtain-scan {
  0%   { top: 0;    opacity: 0; }
  18%  { opacity: 0.9; }
  100% { top: 100%; opacity: 0; }
}

/* ─────────────────────────────────────────────────────
   12 · COUNT-UP — [data-countup] (+ the site's count chips)
   motion.js tallies a number from 0 to its value when it
   scrolls into view. Tabular figures keep the width steady.
───────────────────────────────────────────────────── */
[data-countup], .fb-btn .count, .count-total {
  font-variant-numeric: tabular-nums;
}

/* ─────────────────────────────────────────────────────
   13 · MOTION SAFETY
   Anything that moves collapses to a clean, instant, legible
   state for reduced-motion users.
───────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal].in,
  [data-rule] {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
  .mr-line { transform: none !important; opacity: 1 !important; transition: none !important; }
  .reveal:not(.vis),
  .reveal-group:not(.vis) > .reveal-item { filter: none; }
  [data-depth] { animation: none !important; }
  .mo-decode .mo-cap { display: none !important; }
  [data-tilt] { transform: none !important; }
  [data-tilt] > .tilt-sheen { display: none !important; }
  [data-reveal="clip"] { clip-path: none !important; transition: none !important; }
  .page-curtain.curtain-cinematic::after { animation: none !important; opacity: 0 !important; }
}
