/* ──────────────────────────────────────────────────────────────────
   VirtuProbe Studio: shared base for the landing site.

   This file exists because the palette used to be pasted into all 27
   pages, which had already drifted into nine variants of the same
   :root block. Tokens, fonts and the theme contract live here now.
   Page-specific section CSS stays inline in each page.

   THEMING

   Light is the default and matches the product: every app screenshot
   on this site is a light capture. Dark is opt-in through
   [data-theme="dark"], set before first paint by a snippet in each
   page head so the theme never flashes.

   The values mirror virtuprobe-ui/src/main/resources/css/tokens.css,
   which is the source of truth. The names are short here (--bg, --neon)
   rather than --vp-* because every rule in every page already uses
   them; do not rename without rewriting all 27 files.
   ────────────────────────────────────────────────────────────────── */

/* Roboto and Roboto Mono, variable, subsetted to the same charset as the
   two Geist faces. Roboto is the default face as of 2026-08-28; Geist is
   kept because the app still offers it in Settings and the two properties
   must be able to render either. Self-hosted, as everything here is. */
@font-face {
  font-family: "Roboto";
  src: url("fonts/roboto-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Roboto Mono";
  src: url("fonts/roboto-mono-variable.woff2") format("woff2");
  font-weight: 100 700;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("fonts/geist-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("fonts/geist-mono-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

:root {
  color-scheme: light dark;

  /* surfaces */
  --bg: #f4f7f5;
  --bg-1: #ffffff;
  --bg-2: #edf1ee;
  --bg-3: #e2e8e3;
  --line: #d4dcd6;
  --line-2: #c2cdc6;

  /* foreground */
  --fg: #111a15;
  --fg-dim: #3a4f42;
  --fg-mute: #5a7265;
  --fg-faint: #6f8776;

  /* brand */
  --neon: #1a7a42;
  --neon-mint: #0d6e5a;
  --neon-lime: #2d6a32;
  --neon-glow: #1a7a4233;

  /* Readable text on a --neon fill. Was a hardcoded #06140d on every
     page, which is near-black: correct on the bright dark-theme green
     and unreadable on the darker light-theme one. */
  --on-neon: #ffffff;

  /* semantic */
  --info: #00639a;
  --warn: #7a4f00;
  --danger: #ba1a1a;
  --violet: #6b3fa0;

  /* pricing tier lanes, darkened for a light ground */
  --tier-eng: #0f7d74;
  --tier-eng-glow: rgba(15, 125, 116, 0.12);
  --tier-sec: #6b3fa0;
  --tier-sec-glow: rgba(107, 63, 160, 0.10);
  --tier-ent: #00639a;
  --on-tier: #ffffff;

  /* shadows */
  --shadow-sm: 0 2px 6px -2px rgba(0, 0, 0, 0.10);
  --shadow-md: 0 8px 24px -8px rgba(0, 0, 0, 0.14);
  --shadow-lg: 0 30px 80px -30px rgba(0, 0, 0, 0.22);

  /* fonts. Display and body are one family; hierarchy is weight, size
     and tracking. The display slot stays a separate token so a distinct
     display voice is a one-line change. */
  /* Mirrors --vp-font-* in tokens.css under the short names every rule on these
     pages already uses. Roboto throughout as of 2026-08-28. Both families are
     self-hosted in assets/fonts; nothing calls a font CDN. */
  --font-display: "Roboto", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-body: "Roboto", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: "Roboto Mono", ui-monospace, "Geist Mono", monospace;
}

/* The second selector keeps the top bar dark even in light mode. The brand
   mark is a hairline gradient outline drawn against near-black: 15.8:1 there
   and 1.54:1 on white, so on a light bar it is not on the page at all. The
   mark is not touched; the panel it sits in gets the ground it was drawn for.

   Because the whole palette is re-declared on the bar, every rule inside it
   already reads the right value: links, buttons, hairlines and the primary
   button's label all flip with it. Nothing about the bar's layout changes,
   so there is no shift when the theme is toggled. */
:root[data-theme="dark"],
:root:not([data-theme="dark"]) .topbar,
:root:not([data-theme="dark"]) footer {
  --bg: #0a0d0c;
  --bg-1: #0f1413;
  --bg-2: #141a18;
  --bg-3: #1b231f;
  --line: #1f2a25;
  --line-2: #2a3830;

  --fg: #e6f2ec;
  --fg-dim: #a3b3ac;
  --fg-mute: #7d8c85;
  --fg-faint: #5c6a64;

  --neon: #6ff39b;
  --neon-mint: #5ef0c2;
  --neon-lime: #8df860;
  --neon-glow: #6ff39b33;
  --on-neon: #06140d;

  --info: #5ec3f0;
  --warn: #f5c453;
  --danger: #ff6b6b;
  --violet: #c79df5;

  --tier-eng: #38d9c9;
  --tier-eng-glow: rgba(56, 217, 201, 0.12);
  --tier-sec: #c79df5;
  --tier-sec-glow: rgba(199, 157, 245, 0.10);
  --tier-ent: #5ec3f0;
  --on-tier: #0a0d0c;

  --shadow-sm: 0 2px 6px -2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px -8px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 30px 80px -30px rgba(0, 0, 0, 0.7);
}

/* No preference and no explicit choice: still light, because the
   screenshots are light. The guard keeps an explicit light choice from
   being overridden for a reader on a dark OS who wants the light page. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]):not([data-theme="light"]) {
    /* intentionally empty: dark is opt-in on this site, not automatic */
  }
}

/* ── Theme toggle ─────────────────────────────────────────────────── */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: transparent;
  color: var(--fg-dim);
  cursor: pointer;
  line-height: 1;
  font-size: 14px;
  transition: color 0.15s, border-color 0.15s;
}
.theme-toggle:hover { color: var(--fg); border-color: var(--fg-mute); }
.theme-toggle svg { width: 15px; height: 15px; }
.theme-toggle .icon-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-dark { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }

/* ── Brand mark on a light ground ─────────────────────────────────
   logo-mark.png is a hairline gradient outline running #84e448 to #40f7d1,
   drawn against near-black. Measured, it is 15.8:1 there and 1.54:1 on
   white, so in light mode it is not on the page at all.

   The mark itself is not touched. It gets the ground it was drawn for: a
   dark band that runs the full height of the bar, with the original mint
   to lime gradient reading against it exactly as it does on the dark site.

   The band is drawn with box-shadow spread, which paints outside the
   element without occupying any layout space. That is the point: the img
   keeps the same box in both themes, so nothing moves or resizes when the
   theme flips. An earlier attempt used padding and the logo jumped.

   The colour is literal on purpose. It is the ground the mark was drawn
   against, a brand constant rather than a theme surface, and every token
   in this file inverts with the theme. */
/* Both panels are opaque in light mode. The bar's default is a 70% wash of
   --bg, written for a dark bar over a dark page; the same wash over a light
   page turns it grey. */
:root:not([data-theme="dark"]) .topbar,
:root:not([data-theme="dark"]) footer {
  background: var(--bg);
}
