/* Digital Tap dashboard theme — tokens sampled from the logo.
 *
 * WHY THIS IS A SEPARATE FILE AND NOT A PAGE'S STYLES
 * ---------------------------------------------------
 * The dashboard already styles through CSS custom properties. Re-theming means
 * redefining the tokens, not restyling the components — so this file overrides
 * `:root` and every existing section follows. A dark Agents page inside a light
 * dashboard would look broken, and restyling one page at a time is how that
 * happens.
 *
 * It also re-declares the legacy token names the existing dashboard.css uses
 * (--primary, --accent, --surface-2, --text-muted, …) so that adopting this
 * file re-themes those sections too rather than leaving them on the old palette.
 *
 * FONTS AND CHART.JS ARE SELF-HOSTED
 * ----------------------------------
 * WHAT THE LIVE CSP ACTUALLY SAYS
 * -------------------------------
 * Recorded verbatim because an earlier version of this comment got it wrong,
 * and the wrong version was an argument for a decision:
 *
 *   script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net ...
 *   style-src  'self' 'unsafe-inline' https://fonts.googleapis.com
 *   font-src   'self' https://fonts.gstatic.com
 *   connect-src 'self' https://<project>.supabase.co https://api.digitaltap.ai ...
 *
 * So jsdelivr IS allowed for scripts, Google Fonts IS allowed for both the
 * stylesheet and the font files, and inline style IS allowed. Charts on the
 * live dashboard render. The console error was the Chart.js SOURCE MAP, which
 * the browser fetches under connect-src, and jsdelivr is not in connect-src.
 *
 * WHY SELF-HOSTING STAYS ANYWAY
 * -----------------------------
 * The CSP was never the good reason. The two that hold are the ones
 * website/js/vendor/README.md already makes for supabase-js and Chart.js:
 *
 *   1. Availability. A locked-down enterprise network, an ad blocker or a
 *      proxy allowlist can drop a CDN that our own CSP permits. Our ICP is
 *      life-sciences IT estates, which are exactly the networks most likely to
 *      block a public CDN, and a blocked webfont fails SILENTLY -- the page
 *      renders in a fallback stack and nothing reports it.
 *   2. "This page makes no third-party requests from your browser" is a
 *      sentence worth being able to say to a pharma security reviewer, and it
 *      stops being true at the first cross-origin fetch, permitted or not.
 *
 * IBM Plex is SIL OFL 1.1, so self-hosting is the licence's intended use.
 * Chart.js is already vendored in this repo; see website/js/vendor/README.md.
 *
 * CONTRAST
 * --------
 * Every text-on-surface pair below clears WCAG AA 4.5:1. The measured ratios
 * are in the comments. Keep them there when changing a value, and check the
 * pair you changed — --text-3 on --surface is the tightest at 5.7:1 and has the
 * least room.
 */

/* ── Fonts ─────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'IBM Plex Serif';
  src: url('../fonts/IBMPlexSerif-Regular-Latin1.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Serif';
  src: url('../fonts/IBMPlexSerif-SemiBold-Latin1.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-Regular-Latin1.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/IBMPlexSans-SemiBold-Latin1.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('../fonts/IBMPlexMono-Regular-Latin1.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ── Tokens ────────────────────────────────────────────────────────────── */

:root {
  /* Surfaces — the logo's navy field, getting lighter as things nest. */
  --bg: #030E2A;          /* page */
  --nav: #041334;         /* nav — the logo's glow */
  --surface: #08193D;     /* cards */
  --inset: #051535;       /* chart panels inside cards */
  --hairline: #16294D;    /* grid lines */
  --border: #1B3159;      /* card borders */
  --axis: #223A64;        /* strong borders, chart axes */
  --control: #2E4A78;     /* inputs and secondary buttons */

  /* Text. Ratios measured against --surface (#08193D). */
  --text: #EAF1FB;        /* 15.3:1 */
  --text-2: #A3B3CD;      /*  7.9:1 */
  --text-3: #8196B8;      /*  5.7:1 — labels; the tightest pair here */

  /* Status. Never used as the only signal — see the glyphs in agents.css. */
  --cyan: #4DE0EF;        /* watching, links, data lines */
  --mint: #64F4C6;        /* acting, verified, primary action */
  --amber: #FFB547;       /* escalating */
  --coral: #FF7A7A;       /* blocked, refused */

  /* Ink for text ON --mint, which is far too light to carry white text. */
  --on-mint: #02241A;

  --font-head: 'IBM Plex Serif', Georgia, 'Times New Roman', serif;
  --font-body: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', 'SF Mono', ui-monospace, monospace;

  --radius: 14px;
  --radius-sm: 9px;
  --radius-xs: 5px;

  /* ── Legacy aliases ──────────────────────────────────────────────────
   * dashboard.css and the older pages read these names. Pointed at the new
   * palette so the whole dashboard re-themes rather than only the sections
   * rewritten against the tokens above. Delete an alias once nothing reads it.
   */
  --primary: var(--cyan);
  --primary-dark: #2FB9C8;
  --accent: var(--mint);
  --success: var(--mint);
  --warning: var(--amber);
  --danger: var(--coral);
  --purple: #9B8CFF;
  --bg-deep: #020A1E;
  --surface-2: var(--inset);
  --surface-3: var(--border);
  --border-light: var(--axis);
  --text-muted: var(--text-3);
  --white: var(--text);
  --font: var(--font-body);
  --font-mono-legacy: var(--font-mono);
}

/* ── Top header ────────────────────────────────────────────────────────────
 * The header was styled only by css/main.css, which the older marketing pages
 * share, so it followed whatever theme that file had: on the live dashboard a
 * light nav with the wordmark and links in near-white, nearly invisible. These
 * rules come after main.css and own the header here. Ratios against --nav
 * (#041334): --text 16.1:1, --text-2 8.6:1.
 * Checked in a browser by backend/tests/test_dashboard_header.py.
 */
.nav,
.nav.scrolled {
  background: var(--nav);
  border-bottom: 1px solid var(--border);
}
.nav-logo,
.nav-logo:hover {
  color: var(--text);
}
.nav-links a {
  color: var(--text-2);
}
.nav-links a:hover,
.nav-links a.active {
  color: var(--text);
}
.mobile-toggle {
  color: var(--text);
}
.mobile-toggle span {
  background: var(--text);
}
@media (max-width: 768px) {
  .nav-links {
    background: var(--nav);
    border-bottom: 1px solid var(--border);
  }
}

/* An explicit background on body, so a page that sets none does not render on
 * the browser's white default and flash on load. */
html {
  background: var(--bg);
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 600;
  letter-spacing: -0.01em;
}

code, kbd, samp, pre, .dt-mono {
  font-family: var(--font-mono);
}

a {
  color: var(--cyan);
}

/* Focus must stay visible on a dark field: the browser default outline is
 * nearly invisible here, and this page is operated by keyboard in a console. */
:where(a, button, [tabindex], summary, input, select):focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

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