:root {
  --bg: #0e1116;
  --panel: #161b22;
  --panel-2: #1c222b;
  --border: #2a313c;
  --text: #d7dde5;
  --muted: #8a93a0;
  --accent: #4f8cff;
  --ok: #3fb950;
  --warn: #d29922;
  --bad: #f85149;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/* The HTML `hidden` attribute must win over our class-based display rules
   (.split uses display:grid, .insights uses display:flex — both override
   the user-agent default `[hidden] { display: none }` because class
   selectors have equal specificity to attribute selectors and our
   stylesheet comes later). Force it back. */
[hidden] { display: none !important; }

/* Dark-theme scrollbars. Firefox uses `scrollbar-*` properties; Chromium
   and WebKit use `::-webkit-scrollbar-*`. The thin variant + low-contrast
   thumb keeps scrollbars from competing with content. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 6px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: var(--muted);
  background-clip: padding-box;
  border: 2px solid transparent;
}
*::-webkit-scrollbar-corner { background: transparent; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand { font-weight: 600; letter-spacing: 0.4px; }

.tabs { display: flex; gap: 2px; }
.tab {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 5px 12px;
  border-radius: 4px;
  font-weight: 500;
  cursor: pointer;
  font-size: 12px;
}
.tab:hover { color: var(--text); }
.tab.active {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}

.filters { display: flex; align-items: center; gap: 12px; flex: 1; }
.filters label { display: flex; align-items: center; gap: 6px; color: var(--muted); }
.filters input[type=text], .filters input[type=number] {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 5px 8px;
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 12px;
}
.filters input[type=text] { width: 220px; }
.filters input[type=number] { width: 70px; }
.filters .auto { gap: 4px; }
button {
  background: var(--accent);
  border: 0;
  color: white;
  padding: 6px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: 500;
}
button:hover { filter: brightness(1.1); }

.status { color: var(--muted); margin-left: auto; font-family: var(--mono); font-size: 12px; }
.status.err { color: var(--bad); }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 520px;
  gap: 0;
  height: calc(100vh - 49px);
}

.list { overflow: auto; border-right: 1px solid var(--border); }

table { width: 100%; border-collapse: collapse; font-size: 12px; }
thead th {
  text-align: left;
  font-weight: 500;
  color: var(--muted);
  background: var(--panel);
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 1;
}
tbody td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 280px;
}
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--panel-2); }
tbody tr.selected { background: rgba(79, 140, 255, 0.12); }
tbody tr.empty { cursor: default; color: var(--muted); }
tbody tr.empty:hover { background: transparent; }

.mono { font-family: var(--mono); }
.muted { color: var(--muted); }

.badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 10px;
  font-size: 11px;
  font-family: var(--mono);
  background: var(--panel-2);
  border: 1px solid var(--border);
}
.badge.s2 { color: var(--ok); }
.badge.s3 { color: var(--warn); }
.badge.s4, .badge.s5 { color: var(--bad); }
.badge.zero { color: var(--muted); }
.badge.has { color: var(--warn); border-color: var(--warn); }

.detail { overflow: auto; padding: 16px; background: var(--bg); }
.detail-empty { color: var(--muted); padding-top: 30vh; text-align: center; }

.detail h2 { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.detail h2 .sub { color: var(--muted); font-weight: 400; font-size: 12px; margin-left: 8px; }
.detail h3 {
  margin: 18px 0 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
  font-weight: 600;
}

.kv {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 4px 12px;
  font-family: var(--mono);
  font-size: 12px;
}
.kv .k { color: var(--muted); }
.kv .v { word-break: break-all; }

pre.body {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px;
  font-family: var(--mono);
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 360px;
  overflow: auto;
  margin: 0;
}

.findings, .mutations {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.finding, .mutation {
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 3px solid var(--warn);
  border-radius: 4px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 12px;
}
.finding.sev-high { border-left-color: var(--bad); }
.finding.sev-low  { border-left-color: var(--ok); }
.finding .row { display: flex; gap: 10px; flex-wrap: wrap; }
.finding .pipe { color: var(--accent); }
.finding .cat  { color: var(--warn); }
.finding .sev  { color: var(--muted); }
.mutation .rule { color: var(--accent); }
.mutation .change { color: var(--muted); }
.mutation .arrow { color: var(--muted); margin: 0 4px; }
.mutation .before { color: var(--bad); text-decoration: line-through; }
.mutation .after  { color: var(--ok); }

/* ───────── Insights tab ───────── */

.insights {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 49px);
  background: var(--bg);
}

.insights-scroll {
  flex: 1;
  overflow: auto;
  padding: 16px 20px;
}

.insights-empty {
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 16px 18px;
  font-size: 13px;
  line-height: 1.6;
  margin: 8vh auto 0;
  max-width: 720px;
}
.insights-empty strong { color: var(--text); }
.insights-empty code {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
  font-family: var(--mono);
  font-size: 12px;
}
.insights-empty em { color: var(--accent); font-style: normal; }

.insights-chat {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 900px;
  margin: 0 auto;
}

/* When on Insights, the table-mode filter inputs are irrelevant — hide
   them so the topbar feels like a different section. The Refresh button
   stays (re-labelled "New chat" in JS) and so does the status text. */
body.mode-insights .filters > label { display: none; }

.msg {
  display: flex;
  flex-direction: column;
  max-width: 100%;
  /* Without this, a long unbroken word inside a flex item can force the
     flex parent wider than its container, defeating overflow-wrap on
     the descendants. */
  min-width: 0;
}
.msg-bubble > * { max-width: 100%; }
.msg-bubble table {
  border-collapse: collapse;
  width: 100%;
  margin: 8px 0;
  font-size: 12px;
}
.msg-bubble table th, .msg-bubble table td {
  border: 1px solid var(--border);
  padding: 4px 8px;
  text-align: left;
}
.msg-bubble table th { background: var(--panel-2); font-weight: 600; }
.msg.msg-user .msg-bubble {
  align-self: flex-end;
  background: rgba(79, 140, 255, 0.12);
  border: 1px solid rgba(79, 140, 255, 0.35);
  margin-left: 60px;
}
.msg.msg-assistant .msg-bubble {
  background: var(--panel);
  border: 1px solid var(--border);
  margin-right: 60px;
}
.msg.msg-error .msg-bubble {
  background: rgba(248, 81, 73, 0.08);
  border: 1px solid rgba(248, 81, 73, 0.4);
  color: var(--bad);
  margin-right: 60px;
}
.msg-role {
  font-size: 11px;
  color: var(--muted);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.msg.msg-user .msg-role { align-self: flex-end; }
.msg-bubble {
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.55;
  word-wrap: break-word;
  overflow-wrap: anywhere;
}
/* User input was typed text — preserve their newlines verbatim. Assistant
   content is HTML produced by the markdown renderer and supplies its own
   block structure, so it doesn't need pre-wrap (and would render extra
   blank lines if it had it). */
.msg-user .msg-bubble { white-space: pre-wrap; }

.msg-bubble h2, .msg-bubble h3, .msg-bubble h4, .msg-bubble h5 {
  margin: 12px 0 4px;
  font-weight: 600;
  color: var(--text);
}
.msg-bubble h2 { font-size: 14px; }
.msg-bubble h3 { font-size: 13px; color: var(--accent); }
.msg-bubble h4, .msg-bubble h5 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.msg-bubble > :first-child { margin-top: 0; }
.msg-bubble > :last-child  { margin-bottom: 0; }

.msg-bubble p { margin: 0 0 8px; }
.msg-bubble ul, .msg-bubble ol { margin: 6px 0 8px; padding-left: 22px; }
.msg-bubble li { margin: 2px 0; }
.msg-bubble li > p:only-child { margin: 0; }

.msg-bubble blockquote {
  border-left: 3px solid var(--accent);
  margin: 8px 0;
  padding: 6px 12px;
  color: var(--text);
  background: var(--panel-2);
  border-radius: 0 4px 4px 0;
}
.msg-bubble blockquote :first-child { margin-top: 0; }
.msg-bubble blockquote :last-child  { margin-bottom: 0; }

.msg-bubble code {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
  font-family: var(--mono);
  font-size: 12px;
  /* Long tokens (JWTs, secrets, hashes) must break inside their bubble
     instead of pushing past it. anywhere lets the browser break at any
     point — uglier than respecting word boundaries, but the alternative
     is text spilling outside the bubble. */
  overflow-wrap: anywhere;
  word-break: break-all;
}
.msg-bubble pre, .msg-bubble pre.code {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  margin: 8px 0;
  overflow: auto;
  font-family: var(--mono);
  font-size: 12px;
  /* Wrap inside the block instead of growing horizontally. Preserves
     intentional newlines (pre-wrap) but breaks long lines. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
  max-width: 100%;
}
.msg-bubble pre code, .msg-bubble pre.code code {
  background: transparent;
  border: 0;
  padding: 0;
  /* Inside a <pre> the wrapping is owned by the parent. Don't let the
     inner <code> trigger its own break-all behavior twice. */
  word-break: normal;
  overflow-wrap: inherit;
}
.msg-bubble strong { color: var(--text); }
.msg-bubble a { color: var(--accent); }
.msg-bubble .muted { color: var(--muted); }

.insights-input-row {
  display: flex;
  gap: 8px;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
.insights-input-row textarea {
  flex: 1;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 10px;
  border-radius: 4px;
  font-family: inherit;
  font-size: 13px;
  resize: vertical;
  min-height: 38px;
  max-height: 200px;
}
.insights-input-row textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.insights-input-row button {
  align-self: flex-end;
  height: 38px;
}
.insights-input-row button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.thinking {
  color: var(--muted);
  font-style: italic;
}
.thinking::after {
  content: '';
  display: inline-block;
  width: 1em;
  text-align: left;
  animation: dots 1.2s steps(4, end) infinite;
}
@keyframes dots {
  0%   { content: ''; }
  25%  { content: '.'; }
  50%  { content: '..'; }
  75%  { content: '...'; }
  100% { content: ''; }
}
