/* ============================================================================
   LUX INVICTA — shared design tokens
   ----------------------------------------------------------------------------
   THIS FILE IS THE CONTRACT. Every variant inherits it and MUST NOT redefine
   these values locally. Anything a variant leaves unpinned, six agents will each
   answer differently (memory feedback_parallel_agent_site_builds: one CTA band
   came back in 7 reds and 4 navies). Vary the visual CONCEPT, never the tokens.

   Palette is verbatim from LuxOps/src/lib/branding.ts — do not eyeball new hexes.
   ========================================================================== */

:root {
  /* --- LUX brand spectrum (the lion's own colours) --------------------- */
  --lux-gold: #f0c000;
  --lux-orange: #f06010; /* PRIMARY flame accent */
  --lux-red: #e01030;
  --lux-magenta: #e00060;
  --lux-magenta-lift: #e5228a; /* spectrum variant, use on dark */
  --lux-purple: #5a2a9a;
  --lux-purple-lift: #8b4de0;
  --lux-blue: #1e7bd6;
  --lux-blue-lift: #2e8bff;
  --lux-teal: #2dd4bf; /* the "live system" signal — LuxOps' colour */
  --lux-cyan: #22d3ee;

  /* THE metal. Brandon 2026-07-31: silver, not gold. Heraldically that's *argent*,
     which is also the right tincture for a crest — the two agree. Gold stays in the
     palette because it is literally in the lion's mane, but it is never the metal. */
  --lux-silver: #cbd5e1;
  --lux-silver-dim: #94a3b8;

  /* The signature warm→cool gradient. Hero marks and headline accents only. */
  --lux-gradient: linear-gradient(
    135deg,
    #f0c000 0%,
    #f06010 22%,
    #e01030 44%,
    #c00070 62%,
    #5a2a9a 82%,
    #1e7bd6 100%
  );

  /* --- Surfaces: near-black base, generous darkness ---------------------- */
  --bg: #08090b;
  --bg-elev: #0e1014;
  --bg-elev-2: #16191f;
  --hairline: rgb(255 255 255 / 0.09);
  --hairline-strong: rgb(255 255 255 / 0.16);

  /* --- Text ramp (all pass AA on --bg; see the a11y note below) ---------- */
  --ink: #f7f8fa; /* headlines            ~19.4:1 */
  --ink-body: #c8ccd4; /* body                 ~11.6:1 */
  --ink-muted: #8b93a1; /* captions, labels      ~5.9:1 */
  --ink-faint: #6b7280; /* decorative ONLY       ~3.8:1 — never body text */

  /* --- Semantic roles ---------------------------------------------------- */
  --accent: var(--lux-orange); /* the one single-colour accent */
  --accent-ink: #12060a; /* text ON flame orange — 8.1:1, never white */
  --live: var(--lux-teal); /* system-is-running signal */
  --live-ink: #04231f; /* text ON teal — 9.6:1, never white */
  --metal: var(--lux-silver); /* foil / crest / hairline-rule treatment */
  --focus: var(--lux-silver); /* focus rings must not be the accent */

  /* --- Typeface: MONUMENT (Brandon 2026-07-31) ---------------------------
     Archivo variable carries display AND body; JetBrains Mono carries the
     instrument-style micro labels. Load exactly this, once, in <head>:

     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@62..125,100..900&family=JetBrains+Mono:wght@300..700&display=swap">

     Display is Archivo at wdth 125 (expanded) — the expansion IS the voice.
     Never fake it with letter-spacing on the normal width. */
  --font-display: 'Archivo', system-ui, sans-serif;
  --font-body: 'Archivo', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  --disp-weight: 800;
  --disp-width: 'wdth' 125;

  /* --- Type scale (fluid, 320px → 1440px) -------------------------------- */
  --step--1: clamp(0.83rem, 0.79rem + 0.18vw, 0.94rem);
  --step-0: clamp(1rem, 0.95rem + 0.22vw, 1.13rem);
  --step-1: clamp(1.2rem, 1.11rem + 0.44vw, 1.5rem);
  --step-2: clamp(1.44rem, 1.28rem + 0.8vw, 2rem);
  --step-3: clamp(1.73rem, 1.45rem + 1.4vw, 2.66rem);
  --step-4: clamp(2.07rem, 1.6rem + 2.35vw, 3.55rem);
  --step-5: clamp(2.49rem, 1.72rem + 3.85vw, 4.74rem);
  --step-6: clamp(2.99rem, 1.76rem + 6.14vw, 6.31rem);
  --step-7: clamp(3.58rem, 1.66rem + 9.6vw, 8.41rem); /* hero only */

  /* Tracking. Wide-tracked caps are the inherited LUX signature. */
  --track-hero: -0.02em;
  --track-caps: 0.14em;
  --track-caps-wide: 0.42em; /* the LUX RENTALS subline treatment */
  --track-label: 0.18em;

  /* --- Space (8px base) --------------------------------------------------- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-12: 3rem;
  --s-16: 4rem;
  --s-24: 6rem;
  --s-32: 8rem;
  --section-y: clamp(4rem, 10vw, 9rem); /* one idea per screen: breathe */
  --measure: 62ch; /* never set body wider */
  --shell: 1200px;
  --gutter: clamp(1.25rem, 5vw, 4rem);

  /* --- Radii / elevation --------------------------------------------------- */
  --r-sm: 6px;
  --r-md: 12px;
  --r-lg: 20px;
  --r-pill: 999px;
  --glow-accent: 0 0 60px -12px rgb(240 96 16 / 0.55);
  --glow-live: 0 0 48px -14px rgb(45 212 191 / 0.5);

  /* --- Motion ------------------------------------------------------------- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 180ms;
  --dur: 380ms;
  --dur-slow: 720ms;
}

/* ============================================================================
   Motion vocabulary — inherited in FEEL from LuxOps globals.css, reimplemented
   lean for a static page. Every animation below is disabled under
   prefers-reduced-motion at the bottom of this file.
   ========================================================================== */

/* Slow-drifting spectrum aurora. The page's ambient depth. */
@keyframes lux-aurora {
  0% {
    transform: translate3d(-2%, 0, 0);
    opacity: 0.4;
  }
  100% {
    transform: translate3d(2%, -1%, 0);
    opacity: 0.65;
  }
}

.lux-ambient {
  position: relative;
  isolation: isolate;
  background: radial-gradient(50rem 24rem at 50% -12rem, rgb(240 96 16 / 0.08), transparent 70%),
    var(--bg);
}

.lux-ambient::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.5;
  background: radial-gradient(30rem 16rem at 12% -4rem, rgb(240 96 16 / 0.07), transparent 60%),
    radial-gradient(30rem 16rem at 88% -4rem, rgb(139 77 224 / 0.08), transparent 60%);
  animation: lux-aurora 18s var(--ease-in-out) infinite alternate;
}

/* "The system is running." Teal only — this dot means live data. */
@keyframes lux-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.4;
    transform: scale(0.8);
  }
}

.lux-live-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--live);
  box-shadow: var(--glow-live);
  animation: lux-pulse 1.8s var(--ease-in-out) infinite;
}

/* Scroll-in reveal. Pair with IntersectionObserver adding [data-revealed]. */
@keyframes lux-reveal-up {
  from {
    opacity: 0;
    transform: translate3d(0, 14px, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.lux-reveal {
  opacity: 0;
}
.lux-reveal[data-revealed] {
  animation: lux-reveal-up var(--dur-slow) var(--ease-out) both;
}

/* Scanning shimmer for live rails/bars. */
@keyframes lux-sweep {
  from {
    background-position: -150% 0;
  }
  to {
    background-position: 250% 0;
  }
}

.lux-sweep {
  background-image: linear-gradient(100deg, transparent 30%, rgb(255 255 255 / 0.06) 50%, transparent 70%);
  background-size: 200% 100%;
  animation: lux-sweep 3.5s linear infinite;
}

/* ============================================================================
   Primitives shared by every variant
   ========================================================================== */

/* ⚠️ Horizontal-scroll safety net. The brief forbids sideways scroll absolutely,
   and every variant here paints decorative light — rays, seams, glows, drifting
   gradients — much of it in ::before/::after. Measured on variant D: a 28px
   horizontal scroll that appears only mid-animation and has NO enumerable
   offender, because pseudo-elements don't show up in querySelectorAll. Chasing
   each one individually is whack-a-mole; this stops the whole class.

   `clip`, NOT `hidden`: hidden would make <html> a scroll container and break
   position: sticky inside the page. clip contains the paint without that. */
html {
  overflow-x: clip;
}

/* Gradient-filled text. Always give it a solid fallback colour first: if the
   clip fails the text must still be readable, never invisible. */
.lux-gradient-text {
  color: var(--lux-orange);
  background: var(--lux-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .lux-gradient-text {
    -webkit-text-fill-color: currentColor;
    background: none;
  }
}

/* Instrument-style micro label — the LuxOps panel-title voice. */
.lux-label {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--ink-muted);
}

/* Keyboard focus must be visible on every interactive element, on any surface. */
:where(a, button, input, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

/* ============================================================================
   prefers-reduced-motion — one authoritative block. Variants must not animate
   anything they don't also silence here.
   ========================================================================== */

@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;
  }
  .lux-reveal,
  .lux-reveal[data-revealed] {
    opacity: 1;
    animation: none;
    transform: none;
  }
}
