/* LayerOne design tokens — single source of truth (Phase 0 of the frontend overhaul).
   Loaded first in every layout. New components consume these variables so the
   brand, spacing, radius, and type scales stay consistent across the marketing
   site, client area, and admin console. Dark mode is a token swap, not a
   per-component override. */

:root {
  color-scheme: light;

  /* Brand — one hue family across the whole product. Royal blue; the LayerOne
     rebrand moved the whole product off the previous indigo/violet family. */
  --l1-brand: #2563eb;
  --l1-brand-strong: #1d4ed8;
  --l1-brand-soft: #eff4ff;
  --l1-brand-border: #bfd3fe;
  --l1-brand-contrast: #ffffff;

  --l1-accent: #0f9f76;
  --l1-accent-soft: #e6f4f1;

  /* Semantic status. --info is deliberately NOT blue: the brand is blue now, so
     a blue "info" pill was indistinguishable from a brand-coloured one. It sits
     on teal-cyan instead — still cool, still reads as informational, but clearly
     not the brand. Do not move it back to a blue hue. */
  --l1-ok: #0f7a4a;
  --l1-ok-soft: #ecfdf3;
  --l1-warn: #9a5b0a;
  --l1-warn-soft: #fff7ed;
  --l1-danger: #b42318;
  --l1-danger-soft: #fef2f2;
  --l1-info: #0e7490;
  --l1-info-soft: #ecfeff;

  /* Surfaces + text (light).
     Ink sits a step darker than a stock grey ramp so body copy and captions
     stay readable instead of washing out — most noticeable on long-form
     pages like the API reference. */
  --l1-surface-1: #ffffff;
  --l1-surface-2: #f6f8fc;
  --l1-surface-3: #eef1f7;
  --l1-border: #d9dee8;
  --l1-border-strong: #b8c0cf;
  --l1-ink: #0e131c;
  --l1-ink-soft: #2f3744;
  --l1-ink-muted: #5b6371;
  --l1-on-brand: #ffffff;

  /* Spacing scale */
  --l1-space-1: 4px;
  --l1-space-2: 8px;
  --l1-space-3: 12px;
  --l1-space-4: 16px;
  --l1-space-5: 24px;
  --l1-space-6: 32px;
  --l1-space-7: 48px;
  --l1-space-8: 64px;

  /* Radius */
  --l1-radius-sm: 8px;
  --l1-radius-md: 10px;
  --l1-radius-lg: 14px;
  --l1-radius-pill: 999px;

  /* Type scale */
  --l1-text-xs: 0.75rem;
  --l1-text-sm: 0.875rem;
  --l1-text-base: 1rem;
  --l1-text-lg: 1.125rem;
  --l1-text-xl: 1.25rem;
  --l1-text-2xl: 1.5rem;
  --l1-text-3xl: 1.875rem;

  /* Weights (standard steps only) */
  --l1-fw-normal: 400;
  --l1-fw-medium: 500;
  --l1-fw-semibold: 600;
  --l1-fw-bold: 700;

  /* Elevation */
  --l1-shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.06);
  --l1-shadow-md: 0 6px 20px rgba(17, 24, 39, 0.10);
  --l1-shadow-lg: 0 18px 42px rgba(17, 24, 39, 0.16);

  /* Fonts — native system stack, no webfont. This is the Bootstrap 5
     --bs-font-sans-serif list on purpose: Bootstrap is still on the page for its
     classes, and when the body font and Bootstrap's own components disagree the
     mismatch shows up as two slightly different typefaces in the same form.
     Nothing is downloaded, so there is no FOUT and no third-party font request.
     Headings share the body stack — a separate display face (this was Space
     Grotesk) reads as marketing voice on dense console screens. */
  --l1-font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji",
    "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  --l1-font-head: var(--l1-font-body);

  /* Motion */
  --l1-transition: 150ms ease;

  /* Marketing hero band.
     Every public page opens on a dark full-bleed band — homepage hero, inner
     page heroes, the CTA band and .l1-section-dark. That ground was the literal
     #172235 repeated with !important across three marketing layers, so retuning
     it meant finding all six copies; it is a token now so it can be tuned once.

     Lighter and slightly bluer than the #172235 it replaces: hsl(218, 39%, 15%)
     to hsl(220, 45%, 23%). Most of the change is the lightness lift — the hue
     moves under 2 degrees, which is what "slightly more blue" needs, since the
     brand blue does the saturating and the band only has to sit under it.

     --l1-hero-glow-rgb is the corner/beam glow layered over that ground. It was
     rgba(160, 167, 178, …), a neutral grey that lightened the band without
     tinting it. Stored as a bare triple, not a colour, because the six call
     sites each use their own alpha — same reason --bs-primary-rgb is a triple in
     components.css. */
  --l1-hero-ground: #203255;
  --l1-hero-glow-rgb: 125, 168, 232;

  /* The scrim laid over the hero ground, top-to-bottom, so white headline text
     stays legible over the world-map artwork underneath.

     This — not the ground — is what actually decides how dark a hero looks. It
     used to be rgba(16, 21, 34, .66) fading to rgba(12, 14, 24, .88): a
     near-neutral black at up to 88% opacity, which covered the ground almost
     completely. Retuning --l1-hero-ground alone moved the rendered colour barely
     at all, because only 12% of it was showing through at the bottom.

     Both stops are now blue-tinted rather than neutral, and the per-rule alphas
     that consume these were eased back by about a third, so the ground and its
     glow are visible instead of merely present. Keep enough scrim to hold text
     contrast: the hero headline is pure white and the sub is white at 82%. */
  --l1-hero-scrim-top-rgb: 24, 38, 68;
  --l1-hero-scrim-bottom-rgb: 18, 28, 52;

  /* Marketing-specific (not used by app components directly) */
  --l1-primary-glow: rgba(37, 99, 235, 0.16);
  --l1-shadow-soft: var(--l1-shadow-md);
  --l1-shadow-glow: 0 18px 48px rgba(37, 99, 235, 0.16);
  --l1-portal: var(--l1-surface-2);

  /* Marketing compatibility aliases (legacy --l1-* in marketing CSS) */
  --l1-primary: var(--l1-brand);
  --l1-primary-2: var(--l1-brand-strong);
  --l1-primary-dark: #1e3a8a;
  --l1-primary-soft: color-mix(in srgb, var(--l1-brand) 12%, transparent);
  --l1-bg: var(--l1-surface-2);
  --l1-bg-2: var(--l1-surface-1);
  --l1-bg-3: var(--l1-surface-3);
  --l1-surface: var(--l1-surface-1);
  --l1-text: var(--l1-ink);
  --l1-text-muted: var(--l1-ink-muted);
  --l1-text-dim: #6b7486;
  --l1-text-soft: var(--l1-ink-muted);
  --l1-muted: var(--l1-ink-muted);
  --l1-heading-font: var(--l1-font-head);
  --l1-radius: var(--l1-radius-sm);
}

[data-l1-theme="dark"] {
  color-scheme: dark;
  /* Same blue family as light, lifted for contrast against a dark ground. Keep
     the hue in step with light mode — the pre-rebrand theme shifted dark mode a
     hue further into violet than light, and dark pages read as a different
     brand colour than the marketing site. */
  --l1-brand: #60a5fa;
  --l1-brand-strong: #93c5fd;
  --l1-brand-soft: rgba(96, 165, 250, 0.16);
  --l1-brand-border: rgba(96, 165, 250, 0.38);
  --l1-brand-contrast: #0b0f18;

  --l1-accent: #37d4a5;
  --l1-accent-soft: rgba(55, 212, 165, 0.16);

  --l1-ok: #34d399;
  --l1-ok-soft: rgba(52, 211, 153, 0.15);
  --l1-warn: #fbbf24;
  --l1-warn-soft: rgba(251, 191, 36, 0.15);
  --l1-danger: #f87171;
  --l1-danger-soft: rgba(248, 113, 113, 0.15);
  /* Teal-cyan, matching light mode: --info must not collide with the blue brand.
     This was #60a5fa, which is now exactly --l1-brand. */
  --l1-info: #22d3ee;
  --l1-info-soft: rgba(34, 211, 238, 0.15);

  /* Blue-tinted slate. These surfaces are the largest painted area in the
     product, so the cast is deliberately faint — enough that dark pages read as
     part of a blue theme, not enough to compete with the brand accents. Keep it
     subtle; a saturated navy ground makes every status colour vibrate. */
  --l1-surface-1: #191d28;
  --l1-surface-2: #131822;
  --l1-surface-3: #202634;
  --l1-border: rgba(255, 255, 255, 0.13);
  --l1-border-strong: rgba(255, 255, 255, 0.24);
  --l1-ink: #f8fafc;
  --l1-ink-soft: #d8dee8;
  --l1-ink-muted: #b0b8c6;
  --l1-on-brand: #ffffff;

  --l1-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --l1-shadow-md: 0 6px 20px rgba(0, 0, 0, 0.45);
  --l1-shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.5);

  --l1-primary-glow: rgba(96, 165, 250, 0.22);
  --l1-shadow-soft: 0 18px 48px rgba(0, 0, 0, 0.34);
  --l1-shadow-glow: 0 18px 52px rgba(0, 0, 0, 0.42);
  --l1-portal: #0b0f18;

  --l1-primary: var(--l1-brand);
  --l1-primary-2: var(--l1-brand-strong);
  --l1-primary-dark: #bfdbfe;
  --l1-primary-soft: var(--l1-brand-soft);
  --l1-bg: #0b0f18;
  --l1-bg-2: #121722;
  --l1-bg-3: #191d28;
  --l1-surface: #161b28;
  --l1-text: var(--l1-ink);
  --l1-text-muted: #b8c0ce;
  --l1-text-dim: #9aa3b2;
  --l1-text-soft: var(--l1-text-muted);
  --l1-muted: var(--l1-text-muted);
}

/* ==========================================================================
   Console 2.0 — authenticated shells only
   --------------------------------------------------------------------------
   The tokens above are shared with the marketing site and must keep their
   current values. Everything below is additive and scoped to .l1-console-body
   so public pages keep the marketing brand, type, and radii.
   See docs/phase-49-console-2.md.
   ========================================================================== */

:root {
  /* Control sizing — one ladder for buttons, inputs, selects, pills */
  --l1-control-h-sm: 30px;
  --l1-control-h-md: 36px;
  --l1-control-h-lg: 42px;
  --l1-control-pad-x: 14px;

  /* Data tables */
  --l1-row-h: 48px;
  --l1-row-h-compact: 40px;
  --l1-cell-pad-x: 16px;
  --l1-cell-pad-y: 8px;
  --l1-table-head-h: 40px;

  /* Shell geometry */
  --l1-topbar-h: 56px;
  --l1-sidebar-w: 296px;
  --l1-sidebar-w-collapsed: 72px;
  --l1-content-max: 1440px;
  --l1-content-pad: var(--l1-space-5);
  --l1-workbench-inset: 0px;
  --l1-workbench-radius: 0px;

  /* Focus — one visible ring everywhere, never removed without replacement */
  --l1-focus-ring: 0 0 0 3px color-mix(in srgb, var(--l1-brand) 34%, transparent);
  --l1-focus-ring-offset: 1px;

  /* Numeric/identifier text: aligned digits so columns scan vertically */
  --l1-font-data: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  --l1-font-feature-tabular: "tnum" 1, "lnum" 1;

  /* Dense-surface type ramp (smaller than the marketing ramp by design) */
  --l1-text-micro: 0.6875rem;  /* 11px — column heads, meta */
  --l1-text-dense: 0.8125rem;  /* 13px — table cells */
}

/* Console 2.0 sheet + command column. Brand and the command column use the
   same royal / hero blue as the public site (`--l1-brand` / `#152a52`). */
.l1-console-body {
  --l1-brand: #2563eb;
  --l1-brand-strong: #1d4ed8;
  --l1-brand-soft: #eff4ff;
  --l1-brand-border: #bfd3fe;
  --l1-on-brand: #ffffff;

  /* Desk and column match the live public hero band (marketing
     15-public-redesign.css --l1-hero-ground), not the ink-navy rail. */
  --l1-ground: #152a52;
  --l1-sheet: #ffffff;
  --l1-sheet-shadow: 0 24px 64px rgba(3, 8, 20, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.06);

  --l1-surface-1: #ffffff;
  --l1-surface-2: #f3f6fb;
  --l1-surface-3: #e8edf6;
  --l1-border: #dde3ee;
  --l1-border-strong: #c3cad8;
  --l1-ink: #0e141c;
  --l1-ink-soft: #2a3342;
  --l1-ink-muted: #5a6576;

  --l1-radius-sm: 10px;
  --l1-radius-md: 16px;
  --l1-radius-lg: 20px;

  --l1-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05), 0 8px 24px rgba(15, 23, 42, 0.06);
  --l1-shadow-md: 0 8px 28px rgba(15, 23, 42, 0.10);
  --l1-shadow-lg: 0 18px 48px rgba(15, 23, 42, 0.16);

  --l1-topbar-h: 56px;
  --l1-sidebar-w: 296px;
  --l1-workbench-inset: 0px;
  --l1-workbench-radius: 0px;
}

[data-l1-theme="dark"] .l1-console-body,
[data-l1-theme="dark"] .l1-client-portal-body,
.l1-console-body[data-l1-theme="dark"] {
  color-scheme: dark;
  --l1-brand: #4c8cff;
  --l1-brand-strong: #7eb0ff;
  --l1-brand-soft: rgba(76, 140, 255, 0.16);
  --l1-brand-border: rgba(76, 140, 255, 0.38);
  --l1-on-brand: #0b1220;

  --l1-ground: #0c1018;
  --l1-sheet: #121826;
  --l1-sheet-shadow: 0 24px 64px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.05);

  --l1-surface-1: #121826;
  --l1-surface-2: #171e2e;
  --l1-surface-3: #1e2638;
  --l1-border: rgba(255, 255, 255, 0.10);
  --l1-border-strong: rgba(255, 255, 255, 0.18);
  --l1-ink: #f4f7fb;
  --l1-ink-soft: #d5dce8;
  --l1-ink-muted: #9aa6bb;
  --l1-shadow-sm: none;
  --l1-radius-sm: 10px;
  --l1-radius-md: 16px;
  --l1-radius-lg: 20px;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --l1-transition: 0ms;
  }
}

/* ==========================================================================
   Shell neutrals — the Bootstrap decoupling layer.

   shell.css and app.css read ~262 var(--bs-*) values for the console and client
   shell: surfaces, borders, body text. Those resolved from Bootstrap's :root,
   so the shell could not render without Bootstrap on the page.

   These started as Bootstrap's neutral greys lifted verbatim, so the original
   substitution was a provable no-op. The LayerOne rebrand broke that equality on
   purpose: every value here now carries the same faint blue cast as the
   --l1-surface scale, because the shell greys paint the sidebar, topbar and
   table chrome, and leaving them Bootstrap-neutral left a grey frame around a
   blue product. The cast is small (roughly a 6-10 point B channel lift, hue
   only, luminance held) so text contrast ratios are unchanged.

   They are still deliberately NOT folded into the --l1-surface or --l1-ink scales
   (avoid writing a glob-slash pair in a CSS comment — it closes the comment and
   silently turns the rest of this block into parse garbage, which is exactly how
   this section broke the first time). The shell greys and the l1 palette
   genuinely differ (#dde2ec vs #d9dee8, #1b2130 vs
   #0e131c), and collapsing them is a visual decision, not a refactor. Keeping
   them separate makes the divergence visible and reviewable instead of silently
   restyling every console page in the same commit that removes Bootstrap.
   ========================================================================== */

:root {
  --l1-line: #dde2ec;
  --l1-line-translucent: rgba(0, 0, 0, 0.175);
  --l1-shell-bg: #ffffff;
  --l1-shell-bg-subtle: #f7f9fc;
  --l1-shell-bg-muted: #e8ecf4;
  --l1-shell-hover: #fafbfe;
  --l1-shell-ink: #1b2130;
  --l1-shell-ink-muted: rgba(27, 33, 48, 0.86);
}

[data-l1-theme="dark"] {
  --l1-line: #464f61;
  --l1-line-translucent: rgba(255, 255, 255, 0.15);
  --l1-shell-bg: #1b2130;
  --l1-shell-bg-subtle: #232a3a;
  --l1-shell-bg-muted: #2c3446;
  --l1-shell-hover: #2c3446;
  --l1-shell-ink: #dde2ec;
  --l1-shell-ink-muted: rgba(221, 226, 236, 0.88);
}

/* ==========================================================================
   Command column.

   Light: public hero blue. Dark: the same charcoal-navy family as the sheet,
   not the saturated marketing band. Keep these literals in sync with the
   pre-paint block in templates/layouts/_theme_bootstrap.html.
   See docs/phase-49-console-2.md.
   ========================================================================== */

:root {
  --l1-rail-bg: #152a52;
  --l1-rail-bg-raised: #1c3a6e;
  --l1-rail-hover: rgba(255, 255, 255, 0.08);
  --l1-rail-line: rgba(255, 255, 255, 0.12);
  --l1-rail-line-strong: rgba(255, 255, 255, 0.22);
  --l1-rail-ink: #f3f6ff;
  --l1-rail-ink-muted: #b4c4e0;
  --l1-rail-accent: #60a5fa;
  --l1-rail-active-bg: rgba(37, 99, 235, 0.38);
  --l1-rail-active-border: rgba(96, 165, 250, 0.55);
  --l1-rail-cta: #2563eb;
  --l1-rail-cta-ink: #ffffff;
}

[data-l1-theme="dark"] {
  --l1-rail-bg: #101722;
  --l1-rail-bg-raised: #171e2c;
  --l1-rail-hover: rgba(255, 255, 255, 0.06);
  --l1-rail-line: rgba(255, 255, 255, 0.08);
  --l1-rail-line-strong: rgba(255, 255, 255, 0.16);
  --l1-rail-ink: #eef2f8;
  --l1-rail-ink-muted: #8b95a8;
  --l1-rail-accent: #4c8cff;
  --l1-rail-active-bg: rgba(76, 140, 255, 0.16);
  --l1-rail-active-border: rgba(76, 140, 255, 0.38);
  --l1-rail-cta: #4c8cff;
  --l1-rail-cta-ink: #0b1220;
}

/* The dark client portal runs a warmer, deeper palette than the admin console.
   Higher specificity than the block above, so file order does not matter. */
html[data-l1-theme="dark"] .l1-client-portal-body {
  --l1-line: rgba(255, 255, 255, 0.13);
  --l1-line-translucent: rgba(255, 255, 255, 0.1);
  --l1-shell-bg: #191d28;
  --l1-shell-bg-subtle: #131822;
  --l1-shell-bg-muted: #202634;
  --l1-shell-hover: rgba(255, 255, 255, 0.055);
  --l1-shell-ink: #f3f4f6;
  --l1-shell-ink-muted: #b8c0ce;
}
