/* ==========================================================================
   Vanguard Avionics — base
   Tokens, reset, typography.

   Design note: the whole palette is derived from the mark in logo.png, which
   is a two-stop blue — #0035A7 down to #001674. There is no second hue on
   this site on purpose. Hierarchy is carried by value and saturation, which
   is what keeps it looking like an instrument and not a template.

   Colour is authored once here as semantic tokens; every component below
   reads those tokens only, so .theme-paper can flip a whole section to the
   light treatment without a single component override.
   ========================================================================== */

:root {
  /* --- brand ramp — sampled from logo.png ------------------------------- */
  --vg-050: #eaf0ff;
  --vg-100: #cfe0ff;
  --vg-200: #a8c4ff;
  --vg-300: #6e9bff;
  --vg-400: #3d74f0;
  --vg-500: #0b4fd4;
  --vg-600: #0035a7; /* logo primary   */
  --vg-700: #002a8c;
  --vg-800: #002084; /* logo mid       */
  --vg-900: #001674; /* logo deep navy */

  /* --- neutrals — cooled toward the brand, never truly grey ------------- */
  --ink-950: #05080f;
  --ink-900: #080d1a;
  --ink-850: #0a1020;
  --ink-800: #111a2e;
  --ink-700: #1a2740;
  --ink-600: #27364f;
  --ink-500: #46587a;
  --ink-400: #6b7d9e;
  --ink-300: #94a3bd;
  --ink-200: #c3cddd;
  --ink-100: #dfe6f1;
  --ink-050: #f1f5fb;
  --paper: #f7f9fd;
  --white: #ffffff;

  /* --- semantic: dark treatment (site default) -------------------------- */
  --bg: var(--ink-950);
  --bg-raised: var(--ink-850);
  --bg-sunken: #030509;
  --bg-card: rgba(17, 26, 46, 0.55);
  --bg-card-hover: rgba(22, 34, 60, 0.78);
  --bg-inset: rgba(255, 255, 255, 0.03);

  --fg: #f2f6fd;
  --fg-strong: #ffffff;
  --fg-muted: var(--ink-300);
  --fg-subtle: var(--ink-400);

  --rule: rgba(255, 255, 255, 0.09);
  --rule-strong: rgba(255, 255, 255, 0.18);
  --rule-accent: rgba(110, 155, 255, 0.35);

  --accent: var(--vg-300);
  --accent-hover: var(--vg-200);
  --accent-ink: var(--ink-950); /* text placed on top of --accent */
  --accent-wash: rgba(0, 53, 167, 0.16);
  --accent-glow: rgba(61, 116, 240, 0.28);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 12px 32px -12px rgba(0, 0, 0, 0.65);
  --shadow-lg: 0 32px 72px -24px rgba(0, 0, 0, 0.8);

  /* --- type ------------------------------------------------------------- */
  --font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Fluid scale. The ratio tightens as it scales up so the hero stays
     dramatic on a 27" display without the h3s ballooning with it. */
  --t-display: clamp(3rem, 1.15rem + 6.2vw, 6.75rem);
  --t-title: clamp(2.4rem, 1.35rem + 3.6vw, 4.5rem);
  --t-h2: clamp(1.95rem, 1.35rem + 2.1vw, 3.15rem);
  --t-h3: clamp(1.35rem, 1.12rem + 0.82vw, 1.9rem);
  --t-h4: clamp(1.1rem, 1rem + 0.36vw, 1.3rem);
  --t-lead: clamp(1.06rem, 1rem + 0.32vw, 1.28rem);
  --t-body: 1rem;
  --t-sm: 0.9375rem;
  --t-xs: 0.8125rem;
  --t-label: 0.6875rem;

  /* --- space — 4px base -------------------------------------------------- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;
  --s-11: 10rem;

  /* --- layout ------------------------------------------------------------ */
  --page-max: 1320px;
  --page-gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 68ch;      /* long-form reading width  */
  --measure-tight: 46ch; /* intro / standfirst width */
  --nav-h: 76px;
  --radius-sm: 4px;
  --radius: 8px;
  --radius-lg: 14px;

  /* --- motion — hand-tuned, not library defaults ------------------------- */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.46, 0.64, 1);
  --dur-fast: 180ms;
  --dur: 320ms;
  --dur-slow: 620ms;
}

/* --- light treatment ---------------------------------------------------
   Applied to whole sections (.theme-paper) or whole pages (body.paper).
   Only the semantic layer moves; the brand ramp above is untouched.       */
.theme-paper,
body.paper {
  --bg: var(--paper);
  --bg-raised: var(--white);
  --bg-sunken: var(--ink-050);
  --bg-card: var(--white);
  --bg-card-hover: var(--white);
  --bg-inset: rgba(0, 53, 167, 0.04);

  --fg: #0c1526;
  --fg-strong: #05080f;
  --fg-muted: #4a5a75;
  --fg-subtle: #5d6f8c; /* 4.84:1 on --paper — #6b7d9e fell short of AA */

  --rule: rgba(10, 22, 48, 0.12);
  --rule-strong: rgba(10, 22, 48, 0.24);
  --rule-accent: rgba(0, 53, 167, 0.3);

  --accent: var(--vg-600);
  --accent-hover: var(--vg-700);
  --accent-ink: #ffffff;
  --accent-wash: rgba(0, 53, 167, 0.07);
  --accent-glow: rgba(0, 53, 167, 0.16);

  --shadow-sm: 0 1px 2px rgba(10, 22, 48, 0.06);
  --shadow-md: 0 14px 34px -16px rgba(10, 22, 48, 0.24);
  --shadow-lg: 0 34px 70px -30px rgba(10, 22, 48, 0.3);
}

/* --- forcing the dark treatment back on -------------------------------
   Long-form pages (stories, blog posts) run on .paper for readability, but
   the footer and the closing CTA band are dark on every page in the site.
   Rather than special-case them, they re-declare the dark semantics locally
   so the components inside them keep working unchanged.                   */
.theme-dark {
  --bg: var(--ink-950);
  --bg-raised: var(--ink-850);
  --bg-sunken: #030509;
  --bg-card: rgba(17, 26, 46, 0.55);
  --bg-card-hover: rgba(22, 34, 60, 0.78);
  --bg-inset: rgba(255, 255, 255, 0.03);

  --fg: #f2f6fd;
  --fg-strong: #ffffff;
  --fg-muted: var(--ink-300);
  --fg-subtle: var(--ink-400);

  --rule: rgba(255, 255, 255, 0.09);
  --rule-strong: rgba(255, 255, 255, 0.18);
  --rule-accent: rgba(110, 155, 255, 0.35);

  --accent: var(--vg-300);
  --accent-hover: var(--vg-200);
  --accent-ink: var(--ink-950);
  --accent-wash: rgba(0, 53, 167, 0.16);
  --accent-glow: rgba(61, 116, 240, 0.28);

  color: var(--fg);
}

/* ==========================================================================
   Scrollbar
   Firefox gets the standard property; everything else gets the WebKit
   pseudo-elements. Same brand ramp as the rest of the site rather than the
   browser default, on both the page and inside any element that scrolls
   internally (the mobile nav drawer, the region-chip row on old builds).
   ========================================================================== */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--vg-700) transparent;
}

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--vg-700);
  border-radius: 100px;
  border: 2px solid var(--ink-950);
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--vg-500);
  background-clip: padding-box;
}

body.paper ::-webkit-scrollbar-thumb {
  border-color: var(--paper);
}

/* ==========================================================================
   Reset
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

/* The browser's own `[hidden] { display: none }` is a user-agent rule, so ANY
   author rule that sets display beats it — `.post { display: flex }` is enough
   to leave a `hidden` element fully visible. Every filter on the site sets the
   hidden property, so this reset is what makes filtering work at all. */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + var(--s-5));
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.65;
  font-feature-settings: "kern", "liga", "cv05";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
  /* Long unbreakable tokens (email addresses, part numbers, URLs) must never
     be able to push a narrow layout wider than the viewport. */
  overflow-wrap: break-word;
}

img,
svg,
video,
canvas {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

table {
  border-collapse: collapse;
  width: 100%;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection {
  background: var(--vg-600);
  color: #fff;
}

/* ==========================================================================
   Typography
   ========================================================================== */

h1,
h2,
h3,
h4,
h5 {
  font-family: var(--font-display);
  color: var(--fg-strong);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

h1 {
  font-size: var(--t-title);
}
h2 {
  font-size: var(--t-h2);
}
h3 {
  font-size: var(--t-h3);
  line-height: 1.18;
  letter-spacing: -0.018em;
}
h4 {
  font-size: var(--t-h4);
  line-height: 1.3;
  letter-spacing: -0.01em;
}

p {
  text-wrap: pretty;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.6;
  color: var(--fg-muted);
}

.muted {
  color: var(--fg-muted);
}
.subtle {
  color: var(--fg-subtle);
}
.measure {
  max-width: var(--measure);
}
.measure-tight {
  max-width: var(--measure-tight);
}

/* The mono label is the site's signature: it appears as section numbering,
   spec keys, telemetry, datelines and image credits. Kept at one size. */
.label {
  font-family: var(--font-mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
}

.label--muted {
  color: var(--fg-subtle);
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Numerals in specs, stats and telemetry must not shimmy as they update. */
.tabular {
  font-variant-numeric: tabular-nums;
}

a.link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--rule-accent);
  transition: text-decoration-color var(--dur-fast) var(--ease-out-quart);
}

a.link:hover {
  text-decoration-color: currentColor;
}

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

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--s-4);
  z-index: 2000;
  background: var(--vg-600);
  color: #fff;
  padding: var(--s-3) var(--s-5);
  border-radius: 0 0 var(--radius) var(--radius);
  font-weight: 600;
  transition: top var(--dur) var(--ease-out-expo);
}

.skip-link:focus {
  top: 0;
}

/* ==========================================================================
   Reduced motion — everything animated on this site is opt-out here.
   ========================================================================== */

/* ==========================================================================
   Film grain
   A near-invisible noise layer over the whole site. On its own this is the
   difference between a page that looks rendered and one that looks printed —
   it is what stops large flat dark sections (the hero, the CTA band, cards)
   from reading as a flat digital fill.
   ========================================================================== */

body::after {
  content: "";
  position: fixed;
  inset: 0;
  /* Below the nav (900) and the mobile drawer, and NOT using mix-blend-mode:
     that combined with position:fixed at a high z-index is a known WebKit/
     mobile Safari bug — it can make other fixed elements (the nav bar, in
     particular) paint solid black or corrupt entirely. Plain low-opacity
     texture gives almost the same effect with none of the risk. */
  z-index: 1;
  pointer-events: none;
  opacity: 0.025;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
