/* ==========================================================================
   ZYXORA — FOUNDATION
   --------------------------------------------------------------------------
   Fonts, tokens, reset, typography law, and the primitives (container,
   buttons, forms). Everything that makes the 3D experience look the way it
   does lives in experience.css; this file is what the site would still be
   without any of it.

   PRIMARY DISPLAY FONT : Astron        (Brand / Headings / Statements)
   BODY & UI FONT       : Trade Gothic  (Paragraphs / UI / Nav / Buttons)

   ONLY these two families are permitted. No third typeface is loaded
   anywhere — the fallback stacks resolve to metric-adjusted system faces,
   never to a downloaded webfont.

   BRAND COLORS
   - Heading / highlight : #fff1d0
   - Secondary text      : #9a8f97
   - Brand accent        : #780606
   - Background          : #0e0f19
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. ASTRON (display)
   --------------------------------------------------------------------------
   Drop the licensed files into public/fonts/Astron/ with exactly these names.
   Every weight is mapped to its OWN file, so no weight is ever synthesised.
   Faces whose files are absent are skipped by the UA and the metric-matched
   fallback in section 3 takes over cleanly.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Astron';
  src: url('../public/fonts/Astron/Astron-Regular.woff2') format('woff2'),
       url('../public/fonts/Astron/Astron-Regular.woff') format('woff');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Astron';
  src: url('../public/fonts/Astron/Astron-Medium.woff2') format('woff2'),
       url('../public/fonts/Astron/Astron-Medium.woff') format('woff');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Astron';
  src: url('../public/fonts/Astron/Astron-Bold.woff2') format('woff2'),
       url('../public/fonts/Astron/Astron-Bold.woff') format('woff');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Astron';
  src: url('../public/fonts/Astron/Astron-Black.woff2') format('woff2'),
       url('../public/fonts/Astron/Astron-Black.woff') format('woff');
  font-weight: 900; font-style: normal; font-display: swap;
}

/* --------------------------------------------------------------------------
   2. TRADE GOTHIC (body / UI)
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-Light.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-Light.woff') format('woff');
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-Regular.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-Regular.woff') format('woff');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-Oblique.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-Oblique.woff') format('woff');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-Medium.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-Medium.woff') format('woff');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-Bold.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-Bold.woff') format('woff');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic';
  src: url('../public/fonts/TradeGothic/TradeGothic-BoldOblique.woff2') format('woff2'),
       url('../public/fonts/TradeGothic/TradeGothic-BoldOblique.woff') format('woff');
  font-weight: 700; font-style: italic; font-display: swap;
}

/* --------------------------------------------------------------------------
   3. Metric-matched fallbacks (no layout shift on swap)
   --------------------------------------------------------------------------
   NOT additional typefaces — already-installed system faces re-declared with
   adjusted metrics so their line box approximates the real brand font. When
   Astron / Trade Gothic finish loading the swap stays visually quiet.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Astron Fallback';
  src: local('Arial Black'), local('Impact'), local('Haettenschweiler'), local('Arial Bold');
  size-adjust: 94%; ascent-override: 92%; descent-override: 22%; line-gap-override: 0%;
  font-display: swap;
}
@font-face {
  font-family: 'Trade Gothic Fallback';
  src: local('Helvetica Neue'), local('Helvetica'), local('Segoe UI'), local('Arial');
  size-adjust: 97%; ascent-override: 96%; descent-override: 24%; line-gap-override: 0%;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   4. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Families — exactly two brand faces */
  --font-astron: 'Astron', 'Astron Fallback', 'Arial Black', 'Helvetica Neue', sans-serif;
  --font-trade-gothic: 'Trade Gothic', 'Trade Gothic Fallback', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  /* Brand */
  --color-bg: #0e0f19;
  --color-bg-raised: #131525;
  --color-heading: #fff1d0;
  --color-secondary-text: #9a8f97;
  --color-brand-accent: #780606;
  --color-accent-light: #a31111;

  --color-border: rgba(154, 143, 151, 0.18);
  --color-border-bright: rgba(255, 241, 208, 0.28);
  --color-accent-glow: rgba(120, 6, 6, 0.45);

  /* Glass */
  --glass-bg: rgba(14, 15, 25, 0.42);
  --glass-bg-strong: rgba(14, 15, 25, 0.72);
  --glass-border: rgba(255, 241, 208, 0.14);
  --glass-border-active: rgba(255, 241, 208, 0.42);
  --glass-blur: 18px;

  /* ---- Fluid type scale -------------------------------------------------
     Each step interpolates between a 360px and a 1600px viewport using the
     calc(rem + vw) form, so type never snaps at a breakpoint, never becomes
     unreadable on mobile and never runs away on a 4K display. */
  --text-hero-size:      clamp(3.1rem,   1.75rem + 6vw,     8rem);
  --text-lead:           clamp(1.02rem,  0.96rem + 0.28vw,  1.24rem);
  --text-section-title:  clamp(2.15rem,  1.32rem + 3.69vw,  5rem);
  --text-statement:      clamp(1.5rem,   1.14rem + 1.6vw,   2.7rem);
  --text-card-title:     clamp(1.35rem,  1.05rem + 1.33vw,  2.4rem);
  --text-subhead:        clamp(1.05rem,  0.98rem + 0.32vw,  1.3rem);
  --text-body:           clamp(1rem,     0.96rem + 0.18vw,  1.12rem);
  --text-small:          clamp(0.82rem,  0.79rem + 0.13vw,  0.92rem);
  --text-micro:          clamp(0.7rem,   0.68rem + 0.09vw,  0.78rem);

  /* ---- Optical tracking --------------------------------------------------
     Tracking is a function of size, not of taste. Large uppercase display
     closes up — at 8rem the default spacing reads as gappy and dated — while
     small uppercase UI labels need the opposite to stay legible at all. */
  --tracking-hero: -0.018em;
  --tracking-display: -0.006em;
  --tracking-statement: 0.005em;
  --tracking-heading: 0.015em;
  --tracking-nav: 0.11em;
  --tracking-button: 0.13em;
  --tracking-label: 0.2em;

  /* ---- Leading ---- */
  --leading-hero: 0.86;
  --leading-display: 1.02;
  --leading-heading: 1.12;
  --leading-body: 1.75;
  --leading-ui: 1.45;

  /* ---- Vertical rhythm ---- */
  --flow-tight: 0.6rem;
  --flow: 1.15rem;
  --flow-loose: 1.75rem;

  --measure: 58ch;

  /* Layout */
  --container-max: 1320px;
  --container-gutter: clamp(1.15rem, 4vw, 2.5rem);
  --section-padding-y: clamp(5rem, 11vw, 10rem);
  --header-height: 84px;

  --radius-lg: 18px;
  --radius-md: 10px;
  --radius-sm: 6px;

  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --transition-fast: 0.25s var(--ease-out-expo);
  --transition-normal: 0.45s var(--ease-out-expo);
  --transition-slow: 0.8s var(--ease-out-expo);

  /* Stacking order for the whole experience, declared in one place */
  --z-world: 0;
  --z-vignette: 1;
  --z-content: 2;
  --z-header: 60;
  --z-cursor: 900;
  --z-modal: 1000;
  --z-loader: 1200;
  --z-transition: 1300;
}

@media (min-width: 1800px) {
  :root { --container-max: 1520px; }
}

/* --------------------------------------------------------------------------
   5. Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  background-color: var(--color-bg);
  color: var(--color-secondary-text);
  font-family: var(--font-trade-gothic);
  font-size: 100%;
  line-height: var(--leading-body);
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* Kerning and common ligatures on, everywhere. Both brand faces are
     designed with kern pairs; leaving them off is what makes otherwise good
     type look subtly amateur, especially in large uppercase settings. */
  font-kerning: normal;
  font-variant-ligatures: common-ligatures contextual;
  font-feature-settings: 'kern' 1, 'liga' 1, 'clig' 1;
  font-optical-sizing: auto;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;

  /* `clip` rather than `hidden`: `hidden` turns the root into a scroll
     container, which silently breaks `position: sticky` on the pinned scenes.
     `clip` prevents the same overflow without that side effect. */
  overflow-x: hidden;
}

@supports (overflow-x: clip) {
  html { overflow-x: clip; }
}

/* Lenis owns the scrolling; native smooth behaviour would fight it. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  background-color: var(--color-bg);
  color: var(--color-secondary-text);
  font-family: var(--font-trade-gothic);
  font-weight: 400;
  min-height: 100vh;
  position: relative;
}

@supports (overflow-x: clip) {
  body { overflow-x: clip; }
}

img, picture, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
ul, ol { list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }

::selection { background-color: var(--color-brand-accent); color: var(--color-heading); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: -100px; left: 1rem; z-index: 2000;
  background: var(--color-brand-accent); color: var(--color-heading);
  padding: 0.75rem 1.25rem; border-radius: var(--radius-sm);
  font-size: var(--text-small); letter-spacing: var(--tracking-nav);
  text-transform: uppercase; font-weight: 700;
  transition: top var(--transition-fast);
}
.skip-link:focus { top: 1rem; }

/* --------------------------------------------------------------------------
   6. Typography law
   --------------------------------------------------------------------------
   ASTRON       -> brand, display, headings, statements, product names
   TRADE GOTHIC -> paragraphs, UI, nav, buttons, forms, testimonials, metadata
   -------------------------------------------------------------------------- */
h1, h2, h3,
.font-astron,
.hero-heading,
.section-title,
.statement-heading,
.cta-title,
.modal-title,
.service-panel__title,
.product-panel__title,
.glass-panel__title,
.glass-panel__num,
.service-panel__num,
.service-index__current,
.service-index__total,
.hero-stat__value,
.brand-logo__word,
.footer-col__title,
.author-avatar,
.loader__percent {
  font-family: var(--font-astron);
  color: var(--color-heading);
  font-weight: 700;
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  hyphens: none;
  -webkit-hyphens: none;
  overflow-wrap: break-word;
}

/* Uppercase is a DISPLAY treatment, not a blanket heading rule — proper nouns
   such as testimonial author names keep their real capitalisation. */
.hero-heading,
.section-title,
.statement-heading,
.cta-title,
.modal-title,
.service-panel__title,
.product-panel__title,
.glass-panel__title,
.brand-logo__word,
.footer-col__title {
  text-transform: uppercase;
}

/* The larger the display type, the tighter the tracking */
.hero-heading {
  letter-spacing: var(--tracking-hero);
  line-height: var(--leading-hero);
}

.section-title,
.cta-title {
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-display);
  text-wrap: balance;
}

/* Statements run to several lines at a middling size, where tight tracking
   starts to hurt rather than help. They get their own value. */
.statement-heading {
  letter-spacing: var(--tracking-statement);
  line-height: 1.12;
  text-wrap: balance;
}

/* Numbers that sit in a column, or that change while you watch them, have to
   be tabular or the layout twitches. */
.hero-stat__value,
.service-index__current,
.service-index__total,
.glass-panel__num,
.service-panel__num,
.product-panel__index,
.loader__percent {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'kern' 1, 'tnum' 1;
}

/* TRADE GOTHIC everywhere else */
body,
p, li, a, span, small, blockquote, figcaption,
button, input, textarea, select, label, legend,
h4, h5, h6,
.font-trade-gothic,
.nav-link, .btn, .section-label, .hero-tag, .hero-stat__label,
.hero-action__label, .hero-action__index,
.about-text, .glass-panel__body, .service-panel__body, .product-panel__body,
.product-panel__index, .review-quote, .author-name, .author-role,
.cta-desc, .modal-subtitle, .form-label, .form-input, .form-textarea,
.footer-links a, .footer-bottom, .footer-blurb, .loader__label,
.scroll-cue__label {
  font-family: var(--font-trade-gothic);
}

/* Astron must never set a long paragraph. Enforced, not merely documented. */
p,
.about-text, .glass-panel__body, .service-panel__body, .product-panel__body,
.review-quote, .cta-desc {
  font-family: var(--font-trade-gothic) !important;
}

p {
  color: var(--color-secondary-text);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: 0.004em;
  max-width: var(--measure);
  /* Avoid a single word stranded on the last line */
  text-wrap: pretty;
}

/* Consistent flow between stacked text, rather than a margin invented per
   component. Anything that needs different spacing overrides it locally. */
p + p { margin-top: var(--flow); }

.section-header + * { margin-top: 0; }

h4, h5, h6 {
  color: var(--color-heading);
  font-weight: 700;
  line-height: var(--leading-ui);
  letter-spacing: 0.015em;
}

/* Display headings own the space beneath them, not above it — margins
   collapse far less confusingly that way. */
.section-title { margin-bottom: 0; }
.statement-heading { margin-bottom: var(--flow-loose); }

strong, b { color: var(--color-heading); font-weight: 700; }

:where(a, button, input, textarea, select):focus-visible {
  outline: 2px solid var(--color-heading);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------------
   7. Split typography machinery
   --------------------------------------------------------------------------
   main.js splits headings into lines / words / chars at runtime. The hidden
   initial state is scoped to .js-anim (added to <html> before first paint) so
   there is no flash of un-animated text, and the page stays fully readable
   when JavaScript never runs.
   -------------------------------------------------------------------------- */
.js-anim [data-split],
.js-anim [data-reveal] { visibility: hidden; }

/* Each line is a clipping window; the inner word/char is what travels. That
   is what produces a true mask reveal rather than a plain fade. */
.split-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.09em;
  margin-bottom: -0.09em;
}
.split-word { display: inline-block; white-space: nowrap; will-change: transform, opacity; }
.split-char { display: inline-block; will-change: transform, opacity; }

/* Once a heading has finished, drop the compositor hints */
.split-done .split-word,
.split-done .split-char { will-change: auto; }

.no-js [data-split],
.no-js [data-reveal] { visibility: visible !important; }

/* --------------------------------------------------------------------------
   8. Primitives
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-gutter);
  position: relative;
}

.section {
  position: relative;
  padding-block: var(--section-padding-y);
  z-index: var(--z-content);
}

.section-header { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }

/* Eyebrow labels.

   #780606 on #0e0f19 measures 1.66:1 — nowhere near readable, and it is a
   colour combination no amount of good typography can rescue. Red stays in
   the label as a drawn marker, which is decoration and therefore exempt, and
   the words themselves are set in mauve at 6.1:1. */
.section-label {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-secondary-text);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  line-height: 1.4;
  margin-bottom: 0.9rem;
}

.section-label::before {
  content: '';
  flex: none;
  width: 22px;
  height: 2px;
  background: var(--color-accent-light);
}

.section-title { font-size: var(--text-section-title); }

/* ---- Buttons ---- */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--color-heading);
  --btn-border: var(--color-border);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-family: var(--font-trade-gothic);
  font-size: var(--text-small);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-button);
  line-height: 1.15;
  padding: 0.95rem 1.9rem;
  border-radius: 100px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--transition-fast), border-color var(--transition-fast),
              background-color var(--transition-fast), box-shadow var(--transition-fast);
  will-change: transform;
}

/* The fill wipes up from the bottom rather than cross-fading — same idea as
   the display type reveals, so the motion language stays consistent. */
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--color-accent-light);
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 0.42s var(--ease-out-expo);
  z-index: -1;
}
.btn:hover::before { transform: scaleY(1); }

.btn-primary {
  --btn-bg: var(--color-brand-accent);
  --btn-border: var(--color-brand-accent);
  box-shadow: 0 6px 26px var(--color-accent-glow);
}
.btn-primary:hover { border-color: var(--color-accent-light); box-shadow: 0 8px 34px rgba(163, 17, 17, 0.55); }

.btn-outline { --btn-bg: transparent; --btn-border: var(--color-border-bright); }
.btn-outline::before { background: rgba(255, 241, 208, 0.1); }
.btn-outline:hover { border-color: var(--color-heading); }

.btn-lg { padding: 1.15rem 2.6rem; font-size: var(--text-body); }
.btn-block { width: 100%; }

.btn.is-sent { --btn-bg: #0f7a52; --btn-border: #0f7a52; }
.btn.is-sent::before { display: none; }
.btn[disabled] { opacity: 0.75; cursor: default; }

/* ---- Forms ---- */
.form-group { margin-bottom: 1.2rem; }

.form-label {
  display: block;
  font-size: var(--text-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-nav);
  color: var(--color-heading);
  margin-bottom: 0.45rem;
}

.form-input,
.form-textarea {
  width: 100%;
  font-family: var(--font-trade-gothic);
  font-size: var(--text-body);
  color: var(--color-heading);
  background: rgba(14, 15, 25, 0.6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1rem;
  outline: none;
  transition: border-color var(--transition-fast), background-color var(--transition-fast);
}
.form-input:focus,
.form-textarea:focus {
  border-color: var(--color-accent-light);
  background: rgba(14, 15, 25, 0.85);
}
.form-textarea { resize: vertical; min-height: 120px; }

.form-note {
  font-size: var(--text-micro);
  color: var(--color-secondary-text);
  margin-top: 0.9rem;
  text-align: center;
  max-width: none;
}

/* ---- Submission feedback ------------------------------------------------
   The endpoint answers with either a confirmation or a per-field error list.
   `.is-invalid` marks the fields it named; `.form-status` carries the
   sentence, and is announced because the element is aria-live in the markup. */
.form-input.is-invalid,
.form-textarea.is-invalid {
  border-color: #c0392b;
  background: rgba(120, 6, 6, 0.14);
}

.form-status {
  margin: 1rem 0 0;
  padding: 0.75rem 0.95rem;
  border: 1px solid var(--color-border);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  line-height: 1.55;
  max-width: none;
}

.form-status.is-success {
  border-left-color: #2f9e63;
  color: #a8dcc1;
  background: rgba(47, 158, 99, 0.1);
}

.form-status.is-error {
  border-left-color: #c0392b;
  color: #eda9a1;
  background: rgba(192, 57, 43, 0.12);
}

/* --------------------------------------------------------------------------
   9. Reduced motion
   --------------------------------------------------------------------------
   Everything visible, nothing moving. The world is not rendered at all (see
   device.js), pins are not created, and split text is shown as-is.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  [data-split],
  [data-reveal],
  .js-anim [data-split],
  .js-anim [data-reveal] {
    visibility: visible !important;
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   10. Print
   -------------------------------------------------------------------------- */
@media print {
  .header, .world-canvas, .world-vignette, .world-grain,
  .loader, .modal-overlay, .cursor, .page-transition, .scroll-cue { display: none !important; }

  body { background: #fff; color: #000; }
  [data-split], [data-reveal] { visibility: visible !important; opacity: 1 !important; transform: none !important; }
  .service-panel, .product-panel { position: static !important; opacity: 1 !important; transform: none !important; }
}
