/* ===========================================================================
   DESIGN SYSTEM FOUNDATION
   Built before any section so the whole site inherits one character.

   COLOR LANGUAGE (locked, documented rule):
     Blue  is the single accent. Structure, navigation, links, CTAs, geometry.
     Green is a STATE colour only. Live, running, success, terminal prompt.
           It is never used decoratively. If something is green, it is
           reporting a real condition.
     This is why two colours do not violate the one-accent rule: they are not
     interchangeable, and the visitor learns the difference within one screen.

   SHAPE LOCK: radius 2px on every surface. Nothing rounder, nothing sharper.

   MOTION SYSTEM: three eases, three durations, one stagger. Every animation
   on the site, CSS or GSAP, draws from this set and nothing else.
   =========================================================================== */

:root {
  /* ---- surface ---- */
  --paper: #fbfbfa;
  --paper-sunk: #f4f4f2;
  --paper-raised: #ffffff;
  --rule: #e4e4e1;
  --rule-strong: #cfcfcb;

  /* ---- ink ---- */
  --ink: #0e0f10;
  --ink-soft: #55595e;
  /* 4.9:1 on paper. The lighter grey this replaced failed AA at 3.1:1,
     and this token carries placeholders, helper text and metadata. */
  --ink-faint: #6b7075;

  /* ---- accent: structure ---- */
  --blue: #0a5cff;
  --blue-deep: #0741b8;
  --blue-wash: #eef3ff;
  --blue-line: rgba(10, 92, 255, 0.16);

  /* ---- state: live ---- */
  --green: #0a7a3d;          /* passes AA on paper, safe for text */
  --green-signal: #00c853;   /* glyphs and indicators only, never text */
  --green-wash: #ecfaf1;

  --red: #b3261e;
  --red-wash: #fdf0ef;

  /* ---- type ---- */
  --font-display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Scale planned against the column width, not chosen for impact alone.
     A six word headline in a seven column track needs to land in two
     lines; 96px produced four and that is a font-size error. */
  --t-display: clamp(2.35rem, 4.05vw, 3.6rem);
  --t-h2: clamp(1.75rem, 3.2vw, 2.75rem);
  --t-h3: clamp(1.3rem, 2.1vw, 1.75rem);
  --t-body: clamp(1rem, 1.05vw, 1.1rem);
  --t-small: 0.875rem;
  --t-micro: 0.75rem;

  /* ---- space ---- */
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --section-y: clamp(5.5rem, 11vw, 10rem);
  --maxw: 1400px;
  --maxw-text: 62ch;

  /* ---- shape ---- */
  --r: 2px;

  /* ---- elevation: tinted to the ground, never pure black ---- */
  --shadow-1: 0 1px 2px rgba(14, 15, 16, 0.05);
  --shadow-2: 0 12px 32px -12px rgba(14, 15, 16, 0.16);
  --shadow-3: 0 28px 60px -24px rgba(10, 40, 90, 0.22);

  /* ---- motion tokens: the whole system, nothing else ---- */
  --d-fast: 0.3s;
  --d-base: 0.6s;
  --d-slow: 1.2s;
  --e-entrance: cubic-bezier(0.16, 1, 0.3, 1);   /* mirrors power3.out */
  --e-transition: cubic-bezier(0.65, 0, 0.35, 1); /* mirrors power2.inOut */
  --e-spring: cubic-bezier(0.34, 1.56, 0.64, 1);  /* interactive feedback only */
  --stagger: 0.08s;

  /* ---- layer scale: documented, never ad hoc ---- */
  --z-canvas: 0;
  --z-content: 1;
  --z-sticky: 20;
  --z-nav: 30;
  --z-overlay: 40;
}

/* Dark is a deliberate second skin, not an inversion accident. The brand mode
   is light, so system preference does not flip it. The toggle does. */
[data-theme="dark"] {
  --paper: #0d0f11;
  --paper-sunk: #08090b;
  --paper-raised: #14171a;
  --rule: #23282d;
  --rule-strong: #333940;

  --ink: #f2f3f4;
  --ink-soft: #a7aeb5;
  --ink-faint: #7d858d;   /* 5.1:1 on the dark ground */

  --blue: #5b93ff;
  --blue-deep: #8db3ff;
  --blue-wash: #101a2e;
  --blue-line: rgba(91, 147, 255, 0.22);

  --green: #35d47a;
  --green-signal: #35d47a;
  --green-wash: #0c2018;

  --red: #ff6b61;
  --red-wash: #2a1210;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-2: 0 12px 32px -12px rgba(0, 0, 0, 0.7);
  --shadow-3: 0 28px 60px -24px rgba(0, 0, 0, 0.8);
}

/* ---------------------------------------------------------------- reset */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background-color var(--d-base) var(--e-transition),
    color var(--d-base) var(--e-transition);
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  text-wrap: balance;
}

p {
  margin: 0;
}

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

a {
  color: var(--blue);
  text-decoration-color: var(--blue-line);
  text-underline-offset: 0.25em;
  transition: color var(--d-fast) var(--e-transition);
}

a:hover {
  color: var(--blue-deep);
}

button {
  font: inherit;
  color: inherit;
}

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

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

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

/* ------------------------------------------------------------ primitives */

.shell {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.section--sunk {
  background: var(--paper-sunk);
}

.mono {
  font-family: var(--font-mono);
  font-size: var(--t-small);
  letter-spacing: -0.01em;
}

.lede {
  color: var(--ink-soft);
  max-width: var(--maxw-text);
  font-size: clamp(1.05rem, 1.4vw, 1.25rem);
  line-height: 1.55;
}

.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
  margin: 0;
}

/* Blueprint grid. It organises real content columns rather than decorating,
   so it is aligned to the layout grid and fades out where content is dense. */
.blueprint {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-canvas);
  background-image: linear-gradient(to right, var(--blue-line) 1px, transparent 1px);
  background-size: calc(100% / 6) 100%;
  opacity: 0.5;
  mask-image: linear-gradient(to bottom, transparent, #000 12%, #000 78%, transparent);
}

/* ------------------------------------------------------------- controls */

.btn {
  --btn-bg: var(--blue);
  --btn-fg: #ffffff;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  white-space: nowrap;
  padding: 0.9rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--r);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-mono);
  font-size: var(--t-small);
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--d-fast) var(--e-spring),
    background-color var(--d-fast) var(--e-transition),
    box-shadow var(--d-fast) var(--e-transition);
}

.btn:hover {
  --btn-bg: var(--blue-deep);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}

.btn:active {
  transform: translateY(0) scale(0.985);
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--rule-strong);
}

.btn--ghost:hover {
  --btn-bg: var(--paper-raised);
  --btn-fg: var(--blue);
  border-color: var(--blue);
}

[data-theme="dark"] .btn {
  --btn-fg: #06111f;
}

[data-theme="dark"] .btn:hover {
  color: #06111f;
}

[data-theme="dark"] .btn--ghost {
  --btn-fg: var(--ink);
}

[data-theme="dark"] .btn--ghost:hover {
  --btn-fg: var(--blue);
}

/* Live indicator. Green here reports an actual condition read from the
   database, which is the only reason a coloured dot is allowed on this site. */
.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green-signal);
  flex: none;
  position: relative;
}

.live-dot::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid var(--green-signal);
  opacity: 0;
  animation: pulse-ring 2.4s var(--e-transition) infinite;
}

.live-dot--off {
  background: var(--ink-faint);
}

.live-dot--off::after {
  animation: none;
}

@keyframes pulse-ring {
  0% { transform: scale(0.7); opacity: 0.9; }
  70%, 100% { transform: scale(1.6); opacity: 0; }
}

/* --------------------------------------------------------- accessibility */

.visually-hidden {
  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;
  left: var(--gutter);
  top: -100px;
  z-index: var(--z-overlay);
  background: var(--ink);
  color: var(--paper);
  padding: 0.75rem 1.25rem;
  border-radius: var(--r);
  font-family: var(--font-mono);
  font-size: var(--t-small);
  text-decoration: none;
  transition: top var(--d-fast) var(--e-entrance);
}

.skip-link:focus {
  top: 1rem;
  color: var(--paper);
}

/* Reduced motion yields a genuinely reduced experience: content is present
   and static, not the same choreography played faster. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

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

  .live-dot::after {
    display: none;
  }

  [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }
}
