/*
 * WRCCDC pcap analysis — dashboard styles
 *
 * Design tokens follow the Vercel Geist dark-theme system: a tight surface
 * palette (page → card → elevated), neutral grays for chrome, a single
 * accent for interactive affordances, and traffic-light severity hues
 * tuned to roughly equal perceptual brightness so the heatmap reads
 * cleanly. Typography pairs Geist Sans (UI) with Geist Mono (numbers, IPs,
 * hashes); tabular-nums on numeric columns prevents jitter when sorting.
 *
 * Spacing is on a 4px grid (4/8/12/16/24/32/48). Radii collapse to three
 * stops: 4 (pills), 6 (inputs/buttons), 10 (cards). Borders carry most of
 * the elevation work — shadows are reserved for hover/focus and popovers
 * so the surface stays flat at rest.
 */

@import url("https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap");

:root {
  /* Surfaces — increasing elevation. The page sits on `bg`; cards on
     `surface`; popovers and hover states on `surface-2`. */
  --bg: #0a0c10;
  --surface: #11141a;
  --surface-2: #161a22;
  --surface-3: #1d222c;

  /* Borders — `border` for default chrome, `border-strong` for hover and
     for separators that need to read clearly against `surface`. */
  --border: #1f242e;
  --border-strong: #2b313d;

  /* Text — `fg` is body text, `fg-dim` is secondary metadata, `fg-muted`
     is for de-emphasized labels and disabled states. */
  --fg: #ededed;
  --fg-dim: #9098a4;
  --fg-muted: #5c6470;

  /* Accent — a single brand color for interactive affordances. Geist Blue
     9-ish, perceptually tuned to read clearly on `bg`. */
  --accent: #5dc6f7;
  --accent-strong: #79d0f8;
  --accent-soft: rgba(93, 198, 247, 0.12);

  /* Severity — traffic light, perceptually balanced. Pill backgrounds use
     the same hue at low alpha so the foreground color stays readable. */
  --sev-critical: #f85a5a;
  --sev-high: #f4a14b;
  --sev-medium: #f0c84a;
  --sev-low: #5fd0a0;
  --sev-info: #5dc6f7;

  /* Insight tones — caveat (read carefully), finding (signal in the data),
     fp-warning (the detector is noisy in a known way). */
  --tone-caveat: #f0b429;
  --tone-finding: #5bc0a7;
  --tone-fp: #ff7a7a;

  /* Heatmap stops — cool → warm → hot, paired with the severity hues. */
  --heat-0: var(--bg);
  --heat-1: rgba(93, 198, 247, 0.06);
  --heat-2: rgba(93, 198, 247, 0.14);
  --heat-3: rgba(240, 200, 74, 0.18);
  --heat-4: rgba(244, 161, 75, 0.24);
  --heat-5: rgba(248, 90, 90, 0.32);
  --heat-5-fg: #ffffff;

  /* Header backdrop alpha layer (used inside an rgba(...)). */
  --header-bg: rgba(10, 12, 16, 0.78);

  /* Type. */
  --font-sans: "Geist", -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  /* Radii — three stops. */
  --r-pill: 999px;
  --r-input: 6px;
  --r-card: 10px;

  color-scheme: dark;
}

/* Light theme — activated by `data-theme="light"` on <html>. Tokens are
   Geist-derived; severity hues shift slightly darker so the same pill
   alpha trick reads on the lighter background. */
:root[data-theme="light"] {
  --bg: #ffffff;
  --surface: #fafafa;
  --surface-2: #f4f4f5;
  --surface-3: #e8e8ea;

  --border: #ebebeb;
  --border-strong: #d4d4d4;

  --fg: #0a0a0a;
  --fg-dim: #525252;
  --fg-muted: #8a8a8a;

  --accent: #0070f3;
  --accent-strong: #0061d5;
  --accent-soft: rgba(0, 112, 243, 0.10);

  --sev-critical: #e5484d;
  --sev-high: #d8580f;
  --sev-medium: #b88500;
  --sev-low: #2b9a66;
  --sev-info: #0070f3;

  --tone-caveat: #c08700;
  --tone-finding: #2b9a66;
  --tone-fp: #e5484d;

  --heat-0: var(--surface);
  --heat-1: rgba(0, 112, 243, 0.06);
  --heat-2: rgba(0, 112, 243, 0.14);
  --heat-3: rgba(184, 133, 0, 0.18);
  --heat-4: rgba(216, 88, 15, 0.24);
  --heat-5: rgba(229, 72, 77, 0.30);
  --heat-5-fg: #ffffff;

  --header-bg: rgba(255, 255, 255, 0.82);

  color-scheme: light;
}

* { box-sizing: border-box; }
html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "ss01", "cv11";
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 2px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* --- Header / nav -------------------------------------------------- */

header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  gap: 24px;
  align-items: center;
  padding: 14px 28px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand .logo {
  font-size: 22px;
  color: var(--accent);
  line-height: 1;
}
.brand h1 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--fg);
}
nav#tabs { display: flex; gap: 2px; flex: 1; }
nav#tabs button {
  position: relative;
  background: transparent;
  border: none;
  color: var(--fg-dim);
  padding: 8px 12px;
  border-radius: var(--r-input);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.12s ease, background-color 0.12s ease;
}
nav#tabs button:hover { color: var(--fg); background: var(--surface); }
nav#tabs button.active { color: var(--fg); background: var(--surface); }
nav#tabs button.active::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 1px;
  background: var(--fg);
}

/* Theme toggle — small icon button at the far right of the header. The
   icons are inline SVG (sun/moon); CSS swaps which one is visible based
   on the active theme so there's no flash during hydration. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-left: auto;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-input);
  color: var(--fg-dim);
  cursor: pointer;
  transition: color 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}
.theme-toggle:hover { color: var(--fg); background: var(--surface); border-color: var(--border); }
.theme-toggle svg { width: 16px; height: 16px; display: block; }
.theme-toggle .icon-sun  { display: none; }
.theme-toggle .icon-moon { display: block; }
:root[data-theme="light"] .theme-toggle .icon-sun  { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: none; }

/* --- Layout -------------------------------------------------------- */

main {
  padding: 32px 28px 96px;
  max-width: 1600px;
  margin: 0 auto;
}
.tab { display: none; }
.tab.active { display: flex; flex-direction: column; gap: 32px; }

.grid { display: grid; gap: 20px; }
.grid-2 { grid-template-columns: 1fr 1fr; }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .grid-2, .grid-4 { grid-template-columns: 1fr; }
  main { padding: 24px 16px 80px; }
  header { padding: 12px 16px; }
}

/* "Cards" are dechroma'd — no background, no border, no padding. Each
   section just flows on the page surface, separated by whitespace from the
   tab's flex gap and by the hairline rule under each h2. This reads as a
   single continuous canvas rather than a stack of boxed-up widgets. */
.card {
  background: transparent;
  padding: 0;
}
.card h2 {
  margin: 0 0 4px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--fg);
}
.card h3 {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  text-transform: uppercase;
}
.muted { color: var(--fg-dim); font-size: 12px; margin: 8px 0 14px; }

/* KPI tiles. Large display number in mono with tabular figures so
   sorting/animated counts don't jitter the layout. Stays dechroma'd too —
   just label, big number, subtext. */
.card.kpi { display: flex; flex-direction: column; gap: 0; padding: 0; }
.card.kpi h3 { margin-bottom: 12px; padding-bottom: 0; border-bottom: none; }
.kpi .big {
  font-size: 32px;
  font-weight: 600;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.kpi .sub { margin-top: 6px; color: var(--fg-dim); font-size: 12px; }

/* --- Tables -------------------------------------------------------- */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
th, td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
th {
  color: var(--fg-muted);
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--surface);
  user-select: none;
}
th[data-key] { cursor: pointer; transition: color 0.12s ease; }
th[data-key]:hover { color: var(--fg); }
td { vertical-align: top; color: var(--fg); }
tbody tr { transition: background-color 0.12s ease; }
tbody tr:hover { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: none; }

td.mono, .mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
}
.tool-row { cursor: pointer; }
.tool-row.tool-row-selected {
  background: var(--accent-soft);
  box-shadow: inset 2px 0 0 var(--accent);
}
.table-scroll { max-height: 70vh; overflow: auto; border-radius: var(--r-input); }
.table-scroll table th { position: sticky; top: 0; z-index: 1; }

/* --- Pills (severity + category) ---------------------------------- */

.sev-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.sev-critical { background: color-mix(in srgb, var(--sev-critical) 18%, transparent); color: var(--sev-critical); }
.sev-high     { background: color-mix(in srgb, var(--sev-high)     18%, transparent); color: var(--sev-high); }
.sev-medium   { background: color-mix(in srgb, var(--sev-medium)   18%, transparent); color: var(--sev-medium); }
.sev-low      { background: color-mix(in srgb, var(--sev-low)      18%, transparent); color: var(--sev-low); }
.sev-info     { background: color-mix(in srgb, var(--sev-info)     18%, transparent); color: var(--sev-info); }

.cat-pill {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 4px;
  font-size: 10.5px;
  font-family: var(--font-mono);
  background: var(--surface-2);
  color: var(--fg-dim);
  border: 1px solid var(--border);
  margin: 1px 2px 1px 0;
}

/* --- Filters / inputs --------------------------------------------- */

.filters {
  display: flex;
  gap: 8px;
  margin: 12px 0 18px;
  flex-wrap: wrap;
}
.filters input,
.filters select,
.filters button {
  background: var(--surface-2);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--r-input);
  padding: 7px 11px;
  font: inherit;
  font-size: 13px;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}
.filters input::placeholder { color: var(--fg-muted); }
.filters input:hover,
.filters select:hover { border-color: var(--border-strong); }
.filters input:focus,
.filters select:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-soft); }
.filters input { flex: 1; min-width: 260px; }
.filters button { cursor: pointer; color: var(--fg-dim); }
.filters button:hover { color: var(--fg); background: var(--surface-3); border-color: var(--border-strong); }

/* --- Detector × Year heatmap -------------------------------------- */

#matrix { overflow-x: auto; border-radius: var(--r-input); }
#matrix table { border-collapse: separate; border-spacing: 0; font-size: 12px; }
#matrix td, #matrix th {
  border: none;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  padding: 6px 10px;
  text-align: center;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
#matrix th { background: var(--surface-2); color: var(--fg-dim); }
#matrix td.label {
  text-align: left;
  font-family: var(--font-sans);
  font-size: 12px;
  min-width: 220px;
  max-width: 240px;
  color: var(--fg);
}
#matrix td.heat-0 { background: var(--heat-0); color: var(--fg-muted); }
#matrix td.heat-1 { background: var(--heat-1); }
#matrix td.heat-2 { background: var(--heat-2); }
#matrix td.heat-3 { background: var(--heat-3); }
#matrix td.heat-4 { background: var(--heat-4); }
#matrix td.heat-5 { background: var(--heat-5); color: var(--heat-5-fg); font-weight: 600; }

/* --- Charts -------------------------------------------------------- */

canvas { max-width: 100%; }
/* Chart.js with maintainAspectRatio:false needs an explicitly-sized
   parent or the resize observer feeds back and the canvas grows on every
   tick. .chart / .chart-tall absolutely position the canvas inside. */
.chart      { position: relative; height: 280px; width: 100%; margin-top: 6px; }
.chart-tall { position: relative; height: 480px; width: 100%; margin-top: 6px; }
.chart canvas, .chart-tall canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }

/* --- Insight callouts --------------------------------------------- */

.insight-host { position: relative; }
.insight-pip {
  position: absolute;
  /* Drop below the h2 + hairline + content margin so the pip sits next
     to the chart/table content, never on top of the section title. */
  top: 40px;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--fg);
  background: var(--surface-3);
  border: 1px solid var(--fg-muted);
  border-radius: 50%;
  cursor: help;
  z-index: 5;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.insight-pip:hover,
.insight-pip:focus-visible {
  background: var(--fg);
  border-color: var(--fg);
  color: var(--bg);
}
.insight-pip.side-left  { left: -22px; }
.insight-pip.side-right { right: -22px; }

.insight-popover .title {
  font-weight: 600;
  color: var(--fg);
  margin-bottom: 6px;
  font-size: 13px;
  letter-spacing: -0.005em;
}
.insight-popover .ev {
  display: block;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  color: var(--fg-muted);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
}

/* Popover always sits in the upper-right of the host card. Chart cards
   always render their y-axis labels on the left edge, so anchoring the
   popover to the right edge keeps it clear of those labels regardless
   of which side the pip is on. The pip itself stays in the outer margin
   for visual scent. */
.insight-popover {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 320px;
  max-width: calc(100% - 44px);
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--fg-dim);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: 30;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  pointer-events: none;
}
.insight-pip:hover + .insight-popover,
.insight-pip:focus + .insight-popover,
.insight-pip:focus-visible + .insight-popover,
.insight-popover:hover {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* --- Scrollbars (subtle, system-feeling) -------------------------- */

* { scrollbar-color: var(--border-strong) transparent; scrollbar-width: thin; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; border: 2px solid var(--bg); }
*::-webkit-scrollbar-thumb:hover { background: var(--fg-muted); }
