/* tokens.css — the design language as data. THE single source (V2, 2026-08-02).
   ==========================================================================
   V1 was a source of truth that nothing consumed. web/public/map.css declared
   its own parallel :root — a different canvas (#0A0E14 vs #0B0F16), a different
   module (32px vs 24px), a different grid, a different text ramp, and a whole
   second status palette borrowed from GitHub (#3FB950/#F85149/#D29922). It also
   loaded a SECOND copy of JetBrains Mono on a different weight scale, so every
   page was synthesizing a weight it did not actually have.

   Two near-identical near-blacks side by side do not read as a system. They
   read as a mistake. So: one file, and it is this one.

   WHAT CAME FROM WHERE, and why:
     GEOMETRY AND NEUTRALS come from map.css — canvas, grid, module, elevation,
     hairlines, text ramp. Those values were tuned against the real canvas on a
     screen that was actually looked at, and they are what the brief specified
     (#0A0E14, 1px grid at 4%, 32px module).

     SEMANTIC COLOUR stays bespoke — #2FD07A / #E8A33D / #F0554E rather than
     GitHub's defaults. The brief asked for a named, non-generic direction, and
     a borrowed palette is the definition of generic.

   RULES THIS FILE ENFORCES (test/design_tokens_test.js asserts all three):
     - No other stylesheet may contain a raw hex or rgb() literal.
     - Every var(--x) used anywhere must be defined here.
     - Every surface must compute to the SAME body background.

   Client identity colours live in the DATABASE (clients.color), never here. */

/* ---- type: ONE copy, latin subset, 64KB total. The full 281KB family was a
   duplicate of this on weights 400/500/700, which is why 600 and 700 were both
   being faux-synthesized depending on which stylesheet a page happened to load.
   The scale is 400/500/600 and nothing above it exists — do not ask for 700. */
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  /* ---- canvas: #0A0E14, 1px grid at 4%, 32px module (the brief) ---- */
  --bg:            #0A0E14;
  --bg-raised:     #10151D;   /* solid panel */
  --bg-overlay:    #151B24;   /* detail panels, modals */
  --grid:          rgba(255,255,255,.04);
  --grid-size:     32px;

  /* Separation by ELEVATION, never by a heavy border. */
  --lift-1:        rgba(255,255,255,.03);
  --lift-2:        rgba(255,255,255,.04);

  /* ---- strokes ---- */
  --stroke:        rgba(255,255,255,.08);
  --stroke-strong: rgba(255,255,255,.14);
  --stroke-w:      1px;
  --edge:          rgba(255,255,255,.18);   /* graph edges at rest */

  /* ---- type ---- */
  --font-display:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-body:     ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --fs-xs:  11px;
  --fs-sm:  12px;
  --fs-md:  13px;
  --fs-lg:  16px;
  --fs-xl:  21px;
  --fs-2xl: 28px;
  --lh:        1.55;
  --tracking:  0.06em;   /* display type only; body prose stays at 0 */

  /* ---- text ---- */
  --text:          #E6EDF3;
  --text-dim:      #8B99A8;
  --text-faint:    #5A6673;

  /* ---- spacing, on the 32px module ---- */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px;

  /* ---- radii. --r-0 is explicit: the aesthetic is squared, and map.css was
     already using an UNDEFINED var(--r0), which silently dropped the property. */
  --r-0: 0; --r-sm: 3px; --r-md: 6px; --r-lg: 10px; --r-full: 999px;

  /* ---- STATUS — the only semantic colours. Meaning, never decoration. ---- */
  --ok:            #2FD07A;   /* ok / delivered / alive */
  --ok-dim:        rgba(47, 208, 122, 0.15);
  --pending:       #E8A33D;   /* pending / waiting / warn */
  --pending-dim:   rgba(232, 163, 61, 0.15);
  --crit:          #F0554E;   /* CRIT / error / red-by-meaning */
  --crit-dim:      rgba(240, 85, 78, 0.15);
  --unknown:       #6E7681;   /* no data — renders as unknown, and says why */
  --unknown-dim:   rgba(110, 118, 129, 0.15);
  --core:          #7FB4E6;   /* the knowledge core / platform accent */
  --core-glow:     rgba(127, 180, 230, 0.35);

  /* ---- motion (restrained) ---- */
  --t-fast:  150ms;
  --t-med:   220ms;
  --t-slow:  250ms;
  --ease:    cubic-bezier(.2,.7,.3,1);
}

/* =========================================================================
   SHARED PRIMITIVES — every surface uses these, nobody reimplements them.
   ========================================================================= */
*, *::before, *::after { box-sizing: border-box; }

.cr-body {
  margin: 0;
  background: var(--bg);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: var(--grid-size) var(--grid-size);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh);
}
.cr-display { font-family: var(--font-display); letter-spacing: var(--tracking); }
.cr-panel {
  background: var(--bg-raised);
  border: var(--stroke-w) solid var(--stroke);
  border-radius: var(--r-md);
}

/* =========================================================================
   VALUES — what web/fmt.js emits. The rules are visible in the styling:
   an unknown is dim and dashed, a zero carries its reason, a defect is loud.
   ========================================================================= */
.v {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  letter-spacing: var(--tracking);
  unicode-bidi: isolate;   /* the document is RTL; values are not */
}
.v__unit    { color: var(--text-faint); font-size: .85em; margin-inline-start: .25em; }
.v--unknown { color: var(--unknown); border-bottom: 1px dashed var(--unknown); cursor: help; }
.v--zero    { color: var(--text-dim); }
.v--up      { color: var(--ok); }
.v--down    { color: var(--crit); }
.v--fresh   { color: var(--ok); }
.v--stale   { color: var(--pending); }
.v--dead    { color: var(--crit); }

/* The reason a value is zero or unknown. Always present in the DOM so it can
   never be lost; revealed inline by the header's provenance toggle. */
.v__why {
  display: none;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  margin-inline-start: var(--sp-2);
}
[data-provenance='on'] .v__why { display: inline; }
[data-provenance='on'] .v[data-source]::after {
  content: attr(data-source);
  display: inline;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  margin-inline-start: var(--sp-2);
  letter-spacing: 0;
}

/* A number with no source, or a zero with no reason. Deliberately ugly: this is
   an omission that must be seen and fixed, not a state to live with. */
.fmt-defect {
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  color: var(--crit);
  background: var(--crit-dim);
  border: 1px dashed var(--crit);
  border-radius: var(--r-sm);
  padding: 0 var(--sp-1);
}

/* ---- status pills ---- */
.pill {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  font-family: var(--font-display); font-size: var(--fs-xs);
  letter-spacing: var(--tracking);
  padding: 1px var(--sp-2); border-radius: var(--r-full);
  border: var(--stroke-w) solid currentColor;
  unicode-bidi: isolate;
}
.pill--ok      { color: var(--ok);      background: var(--ok-dim); }
.pill--pending { color: var(--pending); background: var(--pending-dim); }
.pill--crit    { color: var(--crit);    background: var(--crit-dim); }
.pill--unknown { color: var(--unknown); background: var(--unknown-dim); }

/* =========================================================================
   SHELL — one header, one nav, one sync line. See web/shell.js.
   ========================================================================= */
.cr-head {
  display: flex; align-items: center; gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-5);
  border-bottom: var(--stroke-w) solid var(--stroke);
  background: var(--lift-1);
  backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 40;
}
.cr-brand {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--fs-sm); letter-spacing: .14em;
  color: var(--text); text-transform: uppercase; white-space: nowrap;
}
.cr-nav { display: flex; gap: var(--sp-4); align-items: center; flex-wrap: wrap; }
.cr-nav a {
  font-family: var(--font-display); font-size: var(--fs-sm);
  letter-spacing: var(--tracking);
  color: var(--text-dim); text-decoration: none; padding: 2px 0;
  border-bottom: 1px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.cr-nav a:hover { color: var(--text); }
.cr-nav a[aria-current='page'] { color: var(--text); border-bottom-color: var(--core); }

/* The sync line: what the system knows about ITSELF, on every page. */
.cr-sync {
  margin-inline-start: auto;
  display: flex; align-items: center; gap: var(--sp-4);
  font-family: var(--font-display); font-size: var(--fs-xs);
  color: var(--text-faint); white-space: nowrap;
}
.cr-sync__item { display: inline-flex; align-items: center; gap: var(--sp-1); unicode-bidi: isolate; }
.cr-sync__k { color: var(--text-faint); }
.cr-dot { width: 6px; height: 6px; border-radius: var(--r-full); background: var(--unknown); }
.cr-dot--ok      { background: var(--ok);      box-shadow: 0 0 6px var(--ok); }
.cr-dot--pending { background: var(--pending); box-shadow: 0 0 6px var(--pending); }
.cr-dot--crit    { background: var(--crit);    box-shadow: 0 0 6px var(--crit); }

.cr-toggle {
  font-family: var(--font-display); font-size: var(--fs-xs);
  letter-spacing: var(--tracking);
  color: var(--text-faint); background: none;
  border: var(--stroke-w) solid var(--stroke);
  border-radius: var(--r-sm); padding: 2px var(--sp-2); cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.cr-toggle:hover { color: var(--text); border-color: var(--stroke-strong); }
.cr-toggle[aria-pressed='true'] { color: var(--core); border-color: var(--core); }

.cr-main { padding: var(--sp-6) var(--sp-5); max-width: 1600px; margin: 0 auto; }
.cr-h1 {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--fs-xl); letter-spacing: .04em;
  margin: 0 0 var(--sp-2);
}
.cr-sub { color: var(--text-dim); font-size: var(--fs-sm); margin: 0 0 var(--sp-6); }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
