/* iRage design tokens — frozen 2026-09-16
   Layer 1: scale tokens (the ramps). Layer 2: role aliases — USE THESE IN MARKUP.
   Ramps are complete on purpose. Some steps are not referenced by any page yet — they are
   reserved for future work, not dead code. Do not prune them. */

:root {
  /* ---- Blue — the one cool ramp. Links, surfaces, beams, tinted fills. ---- */
  --blue-50:  #F7FAFF;
  --blue-100: #E8EEF7;
  --blue-200: #C9DEFB;
  --blue-300: #85BAFF;
  --blue-400: #60A5FA;
  --blue-500: #2C7BE2;
  --blue-600: #1D5BD6;
  --blue-700: #153A96;
  --blue-800: #0D3B77;
  --blue-900: #09274E;
  --blue-950: #071527;

  /* ---- Navy — dark section grounds ONLY. Three steps, no light end. ---- */
  --navy-800: #0C2E6B;
  --navy-900: #182B40;
  --navy-950: #0F172A;
  --black-950: #07090C;

  /* ---- Slate — text and dividers. ---- */
  --slate-200: #CBD5E1;
  --slate-300: #B4BFCF;
  --slate-400: #98A3B7;
  --slate-600: #64748B;
  --slate-700: #475569;
  --slate-800: #323F52;
  --slate-950: #11161D;

  /* ---- Neutral — true grey. Grid decorations and rings only, never text. ---- */
  --neutral-100: #E2E2E2;
  --neutral-400: #919191;
  --neutral-700: #474747;
  --neutral-950: #111111;

  /* ---- Orange — accent and primary action. ---- */
  --orange-100: #FDEADD;
  --orange-300: #FFB685;
  --orange-500: #EA6E24;
  --orange-700: #A2450D;
  --orange-950: #2A1303;

  /* ---- Category set — the six perk chips. Closed set, in order.
       Every step carries a #FFFFFF label at 4.5:1 or better. ---- */
  --cat-1: #8E4A72;
  --cat-2: #475569;
  --cat-3: #A2450D;
  --cat-4: #5F4490;
  --cat-5: #00672E;
  --cat-6: #1D5BD6;

  /* ---- State ---- */
  --green-500: #16A34A;
  --green-700: #00672E;
  --green-tint: #D8EDE1;

  /* Error. #C0392B measures 5.13:1 on --surface and 4.72:1 on --surface-alt — AA at
     body size on both form grounds. Never the only signal: it always rides with an
     icon and a written message. */
  --error-500: #C0392B;
  --error-tint: #FBEAE7;

  /* ---- Constants ---- */
  --white: #FFFFFF;
  --black: #000000;

  /* ---- Beam — closed set. Scroll-driven gradients only. ---- */
  --beam-100: #4D8DFF;
  --beam-500: #007DD6;
  --beam-900: #1B48B5;

  /* ---- Torch artwork — closed set. The about-us / contact torch scene only. ---- */
  --torch-core:       #FFD700;
  --torch-ink:        #FFFAC8;   /* copy inside the torch scene while the flame is out */
  --torch-glow:       rgba(255,255,151,0.67);
  --torch-lamp-warm:  rgba(255,216,0,0.67);
  --torch-lamp-cool:  rgba(255,255,255,0.67);
  --torch-lamp-amber: rgba(255,143,0,0.67);

  --torch-aura-1:     rgba(255,223,89,0.9);
  --torch-aura-2:     rgba(255,183,43,0.4);
  --torch-halo-1:     rgba(255,154,51,0.45);
  --torch-halo-2:     rgba(255,154,51,0.2);
  --torch-bloom-1:    rgba(255,237,156,0.8);
  --torch-bloom-2:    rgba(255,227,101,0.5);
  --torch-inset:      rgba(255,183,43,0.2);
  --torch-text-halo:  rgba(255,154,51,0.35);
  --torch-sheen-1:    rgba(255,250,200,0.40);
  --torch-sheen-2:    rgba(255,250,200,0.14);
  --torch-sheen-3:    rgba(255,250,200,0.55);
  --torch-edge:       rgba(255,252,230,0.95);
  --torch-line:       rgba(255,250,200,0.5);
  --torch-text-glow:  rgba(255,250,200,0.4);
  --torch-smoke:      rgba(255,255,255,0.3);
  --cube-shade:       rgba(85,85,91,0.71);

  /* ---- Decorative — closed set. Illustration and markers only. Never UI. ---- */
  --dec-100:  #F7CDAC;
  --dec-400:  #FF7D0B;
  --dec-800:  #F2C14E;
  --dec-1200: #8464B4;

  /* =========================================================
     ROLE ALIASES — reference these in markup, not the ramps.
     ========================================================= */

  /* Grounds */
  --page:         var(--blue-50);
  --surface:      var(--white);
  --surface-alt:  var(--blue-50);
  --surface-sunk: var(--blue-100);
  --surface-lilac: #F1E9FA;   /* QuantInsti tab gradient — the one warm-cool tint on a light ground */
  --ground:       var(--navy-950);
  --ground-alt:   var(--navy-900);
  --ground-blue:  var(--navy-800);
  --ground-deep:  var(--black-950);

  /* Text. On any dark ground, text is #FFFFFF — no exceptions.
     Measured contrast, light grounds, --surface / --surface-alt:
       --text        17.85 / 17.06   AAA
       --text-subtle 10.67 / 10.20   AAA
       --text-muted   7.58 /  7.24   AAA — 0.24 of headroom on the page ground,
                                     the thinnest margin in the system and 579
                                     declarations wide. Lightening this token or
                                     the page ground by one ramp step drops all
                                     of them out of AAA at once.
       --link         5.97 /  5.70   AA only; AAA would need --blue-700 (10.11),
                                     held at AA because inline links are
                                     underlined and no longer rely on colour.
       --text-light   2.54 /  2.43   FAILS AA. Dark grounds only (7.02 on --ground). */
  --text:         var(--navy-950);
  --text-subtle:  var(--slate-800);
  --text-muted:   var(--slate-700);
  --text-light:   var(--slate-400);
  --text-invert:  var(--white);
  --link:         var(--blue-600);
  --link-hover:   var(--orange-500);

  /* Accent / action */
  --accent:       var(--orange-500);
  --accent-hover: var(--orange-700);
  --accent-tint:  var(--orange-100);
  --on-accent:    var(--orange-950);
  --focus-ring:   var(--orange-500);
  --link-accent:  var(--orange-700);   /* C19 text link — 6.19:1 on --surface */
  --error:        var(--error-500);    /* invalid field edge and message ink */
  --error-bg:     var(--error-tint);   /* error summary ground */

  /* Borders — exactly two weights per ground. Opaque, so contrast is computable. */
  --border-soft:          #DBDFE5;
  --border-strong:        #B4BFCF;
  --border-soft-invert:   var(--navy-900);
  --border-strong-invert: #5A6474;

  /* Alpha role tokens. Everything outside this block and the fill scale below is
     flattened to an opaque token; the artwork set (torch, cube) is the one exemption. */
  /* One nav fill for both grounds. The bar no longer flips with the theme —
     only the dropdown stays dark, and that has its own token below. */
  --nav-bg-fill:  rgba(255,255,255,0.90);
  /* The nav dropdown stays dark even though the bar is now light on both grounds. */
  --nav-dropdown-bg: rgba(8,28,64,0.97);
  --scrim-image:  linear-gradient(to right, rgba(4,16,38,0.62) 0%, rgba(4,16,38,0.40) 55%, rgba(4,16,38,0.22) 100%);
  --scrim-image-bottom: linear-gradient(to top, rgba(4,16,38,0.34) 0%, transparent 46%);
  --glass:        rgba(255,255,255,0.25);

  /* Fills on dark grounds — four steps, and they replace nineteen ad-hoc
     rgba(255,255,255,…) values. Anything between two steps rounds to a step. */
  --fill-invert-faint:  rgba(255,255,255,0.05);
  --fill-invert-weak:   rgba(255,255,255,0.10);
  --fill-invert-mid:    rgba(255,255,255,0.22);
  --fill-invert-strong: rgba(255,255,255,0.55);
  /* The one navy fill: dividers and faint widget ink on light grounds. */
  --fill-faint:         rgba(15,23,42,0.06);   /* icon-button rest and hover fills on light grounds */
  --fill-weak:          rgba(15,23,42,0.10);

  /* Hover washes on dark grounds — the only interactive alphas. */
  --hover-invert: rgba(242,245,249,0.14);
  --hover-accent: rgba(234,110,36,0.16);

  /* Grid overlay — ONE component, two grounds. Alpha is required here: the lines
     sit over flat grounds and photography alike. Invert runs louder than light:
     it sits over the hero photograph, where 0.08 disappeared into the scrim. */
  --grid-line:        rgba(15,23,42,0.07);
  --grid-line-invert: rgba(255,255,255,0.16);
  /* Third ground: flat dark, with no photograph to compete with. 0.16 was
     calibrated against the hero video and reads roughly twice too strong here. */
  --grid-line-invert-flat: rgba(255,255,255,0.03);

  /* Grid cell hover fill — its own token, not --hover-invert: that one is the
     CTA wash on dark grounds and must not get louder to suit the hero grid. */
  --hover-grid:       rgba(255,255,255,0.30);

  /* Preloader dial lattice. Now the faintest grid step in the set — the dial
     reads as artwork behind the sweep rather than a lattice of its own. */
  --loader-grid:      var(--grid-line-invert-flat);

  /* Frosted panel — set per ground by the theme script. Distinct from --glass,
     which is the contact-card fill. */
  --glass-panel-light: rgba(255,255,255,0.58);
  --glass-panel-dark:  rgba(20,26,34,0.55);
  --glass-panel:       var(--glass-panel-light);
  --glass-panel-line:  rgba(15,23,42,0.10);
  --glass-panel-sheen-light: rgba(255,255,255,0.75);
  --glass-panel-sheen-dark:  var(--hover-invert);   /* same wash the theme script uses on dark */
  --glass-panel-sheen: var(--glass-panel-sheen-light);

  /* Shadows — six. Three carry elevation (rest and hover come from the blog cards);
     three carry colour and belong to the accent CTA and the beam artwork. */
  --shadow-rest:    0 8px 18px -14px rgba(12,46,107,0.30);
  --shadow-hover:   0 16px 34px -16px rgba(12,46,107,0.21);
  --shadow-overlay: 0 18px 44px -30px rgba(15,23,42,0.35);
  /* Two glow shadows. Not card elevation — they belong to the accent CTA hover
     and the beam artwork, and they are the only shadows that carry colour. */
  --shadow-accent-glow: 0 10px 28px -10px rgba(234,110,36,0.85);
  --shadow-beam-glow:   0 0 7px 1px rgba(0,125,214,0.45);
  --shadow-overlay-dark: 0 10px 22px -8px rgba(4,16,38,0.75);

  /* Radii */
  --r-cta:    3px;
  --r-card:   10px;
  --r-pill:   100px;
  --r-circle: 50%;
  --r-tick:   1.5px;   /* decorative marks only — grid cells, tab underlines. Never a container. */

  /* Motion */
  --dur-fast: 150ms;
  --dur:      250ms;
  --dur-slow: 400ms;
  --ease:     cubic-bezier(.2,.6,.2,1);

  /* ---------------------------------------------------------------------
     Type — eight roles. A size that is not one of these is wrong, the same
     way a raw hex is wrong. Each token is the whole shorthand: weight,
     size/line-height, family. Tracking rides alongside because `font:`
     cannot carry letter-spacing.

     Families: Inter is the default, JetBrains Mono is 12px labels only,
     Playfair Display is the display face at weight 600, h1 only.
     --------------------------------------------------------------------- */
  --font-sans:    'Inter', Helvetica, Arial, sans-serif;
  --font-mono:    'JetBrains Mono', monospace;
  --font-display: 'Playfair Display', Georgia, serif;

  --type-display:    600 clamp(46px, 5.8vw, 96px)/1 var(--font-display);
  --type-h2:         400 clamp(28px, 3.1vw, 46px)/1.1 var(--font-sans);
  --type-h3-display: 500 clamp(22px, 2.4vw, 36px)/1.24 var(--font-sans);
  --type-h3:         600 clamp(22px, 1.6vw, 28px)/1.24 var(--font-sans);
  --type-lead:       500 18px/1.6 var(--font-sans);
  --type-body:       400 15px/1.6 var(--font-sans);
  --type-small:      400 14px/1.6 var(--font-sans);
  --type-fine:       400 13px/1.6 var(--font-sans);
  --type-mono:       500 12px/1.6 var(--font-mono);

  /* Tracking — five steps, always em so it scales with a clamp. */
  --track-display: -0.03em;
  --track-heading: -0.02em;
  --track-subhead: -0.01em;
  --track-body:     0;
  --track-mono:     0.16em;

  /* Line-height — four values, already inside the type tokens above.
     Named for the rare case that needs one on its own. */
  --lh-numeral: 1;
  --lh-display: 1.1;
  --lh-heading: 1.24;
  --lh-copy:    1.6;

  /* Nav chrome — set at runtime by the ground detector */
  --nav-fg:       var(--navy-950);
  --nav-fg-hover: var(--link-accent);   /* 6.19:1 on the light nav wash; --accent is only 3.11:1 */
  --nav-bg:     var(--nav-bg-fill);
  --nav-line:   var(--border-soft);
  --nav-shadow: var(--shadow-overlay);

}

/* Dark grounds flip borders and nav chrome. */
[data-nav-theme="dark"], [data-ground="dark"] {
  --border-soft:   var(--border-soft-invert);
  --border-strong: var(--border-strong-invert);
  --nav-fg:        var(--navy-950);
  --nav-line:      var(--border-soft);
  --glass-panel:       var(--glass-panel-dark);
  --glass-panel-line:  var(--hover-invert);
  --glass-panel-sheen: var(--glass-panel-sheen-dark);
}

/* Keyboard focus — WCAG 2.1 AA. Visible on both grounds. */
:where(a, button, [role="button"], input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Disabled — one treatment for every control. No alpha-washed label. */
:where(button, [role="button"], input, select, textarea, a[aria-disabled="true"]):disabled,
:where(button, [role="button"], input, select, textarea, a)[aria-disabled="true"] {
  background: var(--fill-faint) !important;
  color: var(--text-muted) !important;
  border-color: var(--border-soft) !important;
  box-shadow: none !important;
  cursor: not-allowed !important;
  transform: none !important;
}

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