/* Provenant Investigator UI — light theme aligned with marketing site */
:root {
  --bg: #f4f7fb;
  --bg-elev: #eef3f9;
  --bg-card: #ffffff;
  --bg-card-2: #f8fafc;
  --border: #d5e0ec;
  --border-soft: #e4ebf3;
  --text: #0f1b28;
  /* --muted carries body-sized text, so it is held at 4.5:1 against
     --bg-card; --dim is for large or decorative text only. */
  --muted: #55697d;
  --dim: #5a6d80;
  --accent: #1a7fd4;
  --accent-hover: #156db8;
  --accent-soft: rgba(26, 127, 212, 0.1);
  --mint: #0d9f6e;
  --mint-soft: rgba(13, 159, 110, 0.1);
  --good: #0a7d57;
  --bad: #b8302f;
  --warn: #8a5d0b;
  --focus: #0b62ab;
  --verdict-ok-bg: #0a7d57;
  --verdict-ok-fg: #ffffff;
  --verdict-fail-bg: #b8302f;
  --verdict-fail-fg: #ffffff;
  --verdict-unk-bg: #55697d;
  --verdict-unk-fg: #ffffff;
  /* Decision IDs and hashes: deliberately cooler than body
     text, but it has to be legible on whichever surface. */
  --mono-text: #2a4a66;
  --radius: 12px;
  --radius-sm: 8px;
  --font: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
  --shadow: 0 8px 24px rgba(20, 45, 80, 0.06);
  --shadow-lg: 0 20px 48px rgba(20, 45, 80, 0.1);
  --sidebar-w: 248px;

  /* ── Glass ──────────────────────────────────────────────────────────
   * Three fills rather than one, because translucency trades legibility
   * for depth and the right trade differs by what sits on the surface.
   *
   *   chrome  — sidebar, topbar. Short labels, so it can be the most
   *             transparent and carry most of the effect.
   *   panel   — cards. Body text and data live here, so the fill stays
   *             opaque enough that contrast does not depend on what
   *             happens to be behind it.
   *   raised  — modals. They overlay arbitrary content, including dense
   *             tables, so they are nearly solid: a destructive
   *             confirmation must never be hard to read.
   */
  --glass-chrome: rgba(255, 255, 255, 0.66);
  --glass-panel: rgba(255, 255, 255, 0.86);
  --glass-raised: rgba(255, 255, 255, 0.94);
  --glass-edge: rgba(255, 255, 255, 0.85);
  --glass-highlight: rgba(255, 255, 255, 0.9);
  --glass-blur: 18px;
  --glass-saturate: 1.5;
  /* What the panes are blurring. Kept faint in light theme — the
     product should still read as a calm white page, not a gradient. */
  --wash-a: rgba(26, 127, 212, 0.13);
  --wash-b: rgba(13, 159, 110, 0.09);
  --wash-c: rgba(99, 102, 241, 0.08);
  color-scheme: light;
}

/* Dark theme.
 *
 * Two selectors, deliberately. The media query is the default so the
 * app matches the OS without anyone choosing anything; [data-theme] is
 * stamped on <html> by the toggle and must win in *both* directions,
 * which is why the light values are restated rather than just left to
 * :root — otherwise a viewer whose OS is dark could not choose light.
 *
 * Surfaces lighten as they come forward, rather than darkening: on a
 * dark background a raised card that is darker reads as a hole. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d141c;
    --bg-elev: #131c26;
    --bg-card: #161f2b;
    --bg-card-2: #1b2634;
    --border: #2a3a4c;
    --border-soft: #223040;
    --text: #e8eef5;
    --muted: #9fb2c6;
    --dim: #8497ab;
    --accent: #4ea3e8;
    --accent-hover: #6fb6ef;
    --accent-soft: rgba(78, 163, 232, 0.16);
    --mint: #3ec99a;
    --mint-soft: rgba(62, 201, 154, 0.16);
    --good: #3ec99a;
    --bad: #f0736f;
    --warn: #e0a94a;
    --focus: #7cc0f5;
    --verdict-ok-bg: #3ec99a;
    --verdict-ok-fg: #08131b;
    --verdict-fail-bg: #f0736f;
    --verdict-fail-fg: #1a0b0b;
    --verdict-unk-bg: #8497ab;
    --verdict-unk-fg: #0d141c;
    --mono-text: #a9c2da;
    /* Dark glass is a lightened tint of the surface, not a darkened
       one: a translucent panel that is darker than its backdrop reads
       as a hole punched in the page rather than a pane over it. */
    --glass-chrome: rgba(30, 43, 58, 0.68);
    --glass-panel: rgba(26, 37, 50, 0.88);
    --glass-raised: rgba(28, 40, 54, 0.95);
    --glass-edge: rgba(150, 185, 220, 0.14);
    --glass-highlight: rgba(190, 215, 240, 0.13);
    --wash-a: rgba(38, 116, 190, 0.30);
    --wash-b: rgba(16, 138, 105, 0.20);
    --wash-c: rgba(88, 80, 200, 0.20);
    --shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 20px 48px rgba(0, 0, 0, 0.55);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: #0d141c;
  --bg-elev: #131c26;
  --bg-card: #161f2b;
  --bg-card-2: #1b2634;
  --border: #2a3a4c;
  --border-soft: #223040;
  --text: #e8eef5;
  --muted: #9fb2c6;
  --dim: #8497ab;
  --accent: #4ea3e8;
  --accent-hover: #6fb6ef;
  --accent-soft: rgba(78, 163, 232, 0.16);
  --mint: #3ec99a;
  --mint-soft: rgba(62, 201, 154, 0.16);
  --good: #3ec99a;
  --bad: #f0736f;
  --warn: #e0a94a;
  --focus: #7cc0f5;
  --verdict-ok-bg: #3ec99a;
  --verdict-ok-fg: #08131b;
  --verdict-fail-bg: #f0736f;
  --verdict-fail-fg: #1a0b0b;
  --verdict-unk-bg: #8497ab;
  --verdict-unk-fg: #0d141c;
  --mono-text: #a9c2da;
  --glass-chrome: rgba(30, 43, 58, 0.68);
  --glass-panel: rgba(26, 37, 50, 0.88);
  --glass-raised: rgba(28, 40, 54, 0.95);
  --glass-edge: rgba(150, 185, 220, 0.14);
  --glass-highlight: rgba(190, 215, 240, 0.13);
  --wash-a: rgba(38, 116, 190, 0.30);
  --wash-b: rgba(16, 138, 105, 0.20);
  --wash-c: rgba(88, 80, 200, 0.20);
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 20px 48px rgba(0, 0, 0, 0.55);
  color-scheme: dark;
}

/* A visible focus ring on everything that takes focus. :focus-visible so
   it appears for keyboard users without ringing every mouse click. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Respect the OS setting. Motion here is decorative — nothing in this
   app communicates state by moving. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Keyboard users need a way past 22 nav items to reach the content. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: 0.6rem 1rem;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.skip-link:focus {
  left: 0.75rem;
  top: 0.75rem;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; margin: 0; }

body {
  font-family: var(--font);
  /* Three blobs, not two, and further apart: a blurred pane over a flat
     colour is just a lighter rectangle. The effect needs variation
     behind it to pick up. Fixed attachment so panes reveal different
     parts of it as the page scrolls. */
  background:
    radial-gradient(ellipse 70% 45% at 8% -8%, var(--wash-a), transparent 60%),
    radial-gradient(ellipse 50% 38% at 96% 4%, var(--wash-b), transparent 55%),
    radial-gradient(ellipse 60% 50% at 55% 105%, var(--wash-c), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  line-height: 1.5;
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
}

.hidden { display: none !important; }
.muted { color: var(--muted); }
.xs { font-size: 0.75rem; }
code {
  font-family: var(--mono);
  font-size: 0.86em;
  color: var(--accent-hover);
  background: var(--accent-soft);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}

/* ── Auth ─────────────────────────────────────────────────────────── */
.auth-screen {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}
.auth-card {
  width: min(420px, 100%);
  /* Frosted, but themed: the literal white made the sign-in card a
     white slab in dark mode with dark text nowhere to be seen. */
  background: var(--glass-raised);
  backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-edge);
  border-radius: 16px;
  padding: 2rem 1.85rem 1.75rem;
  box-shadow: var(--shadow-lg), inset 0 1px 0 var(--glass-highlight);
}
.brand {
  display: flex;
  gap: 0.85rem;
  align-items: center;
  margin-bottom: 1rem;
}
.brand h1 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--text);
}
.brand.compact {
  margin-bottom: 1.1rem;
  padding: 0 0.2rem;
}
.brand.compact strong {
  font-size: 0.95rem;
  letter-spacing: -0.01em;
}
.logo {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: linear-gradient(145deg, #2a8ee0, #1a5f9a);
  border: 1px solid #3d9cf0;
  position: relative;
  flex-shrink: 0;
  box-shadow: 0 4px 14px rgba(26, 127, 212, 0.28);
}
.logo::after {
  content: "";
  position: absolute;
  inset: 10px;
  border: 2px solid #fff;
  border-radius: 3px;
  border-top-color: transparent;
  border-left-color: transparent;
  transform: rotate(-45deg);
}
.logo.sm { width: 32px; height: 32px; border-radius: 8px; }
.logo.sm::after { inset: 7px; }
.lede {
  color: var(--muted);
  font-size: 0.92rem;
  margin: 0 0 1.35rem;
  line-height: 1.55;
}
/* Any class that sets display beats the user-agent [hidden] rule, so
   hiding an element by attribute silently did nothing on .field, .card
   and friends. Stated once here rather than per-component. */
[hidden] {
  display: none !important;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 0.85rem;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--muted);
}
/* `input` with no type attribute is a text input, but
   input[type="text"] does not match it — the attribute has to be
   present. 51 of the app's inputs omit it, so they were falling through
   to the browser default. In light mode that default is white and
   looked correct by accident; in dark mode it is grey, which is how the
   gap finally became visible. Matched by exclusion instead. */
.field input:not([type="checkbox"]):not([type="radio"]),
.filters input,
.filters label input,
.jump-box input {
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  font: inherit;
  font-weight: 400;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.field input:focus,
.filters input:focus,
.jump-box input:focus,
.form-grid textarea:focus,
.field select:focus,
select:focus {
  /* No `outline: none` here. It used to suppress the ring in favour of
     a 10%-opacity box-shadow, which is not a focus indicator anyone can
     actually see. The shadow stays as decoration; the global
     :focus-visible outline is what makes the focused field findable. */
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field.check, .filters .check {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
}
.hint { font-size: 0.78rem; margin-top: 1rem; line-height: 1.45; }
.error { color: var(--bad); font-size: 0.88rem; margin-top: 0.75rem; font-weight: 500; }
.auth-advanced {
  margin-top: 1.1rem;
  border-top: 1px solid var(--border-soft);
  padding-top: 0.85rem;
}
.auth-advanced summary {
  cursor: pointer;
  user-select: none;
  font-weight: 500;
}
.auth-advanced summary:hover { color: var(--text); }
#auth-submit, #auth-submit-key { width: 100%; margin-top: 0.25rem; }

/* ── Shell ────────────────────────────────────────────────────────── */
.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}
.sidebar {
  /* Frosted, but themed. Hardcoded white left the whole navigation
     a near-white slab under light-grey text in dark mode — the
     surface a signed-in person looks at most. */
  background: var(--glass-chrome);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border-right: 1px solid var(--border-soft);
  padding: 1.15rem 0.75rem 1rem;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  z-index: 20;
}
.nav-group {
  margin-bottom: 0.85rem;
}
.nav-group-label {
  font-size: 0.68rem;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 0.35rem 0.7rem 0.4rem;
}
.nav-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 0.48rem 0.7rem;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 500;
  cursor: pointer;
  margin-bottom: 0.12rem;
  transition: background 0.12s, color 0.12s;
}
.nav-item:hover {
  background: var(--accent-soft);
  color: var(--text);
}
.nav-item.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--accent);
}
.sidebar-foot {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--border-soft);
}
.main {
  padding: 1.35rem 1.75rem 3rem;
  max-width: 1180px;
  min-width: 0;
}
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1.25rem;
  gap: 1rem;
  flex-wrap: wrap;
}
.topbar h2 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--text);
}
.topbar-actions {
  display: flex;
  gap: 0.55rem;
  align-items: center;
  flex-wrap: wrap;
}
.jump-box { display: flex; gap: 0.35rem; align-items: center; }
.jump-box input {
  min-width: 200px;
  font-size: 0.85rem;
  padding: 0.4rem 0.65rem;
}

/* ── Buttons ──────────────────────────────────────────────────────── */
.btn {
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.55rem 1rem;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 550;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s, filter 0.12s;
  box-shadow: 0 1px 2px rgba(15, 40, 70, 0.04);
}
.btn:hover {
  border-color: var(--dim);
  background: var(--bg-elev);
}
.btn.primary {
  background: linear-gradient(180deg, #2a8ee0, var(--accent));
  border-color: var(--accent-hover);
  color: #fff;
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(26, 127, 212, 0.25);
}
.btn.primary:hover {
  filter: brightness(1.05);
  background: linear-gradient(180deg, #3396e6, var(--accent-hover));
}
.btn.secondary {
  background: var(--accent-soft);
  border-color: rgba(26, 127, 212, 0.28);
  color: var(--accent-hover);
  font-weight: 600;
}
.btn.secondary:hover {
  background: rgba(26, 127, 212, 0.16);
}
.btn.ghost {
  background: transparent;
  box-shadow: none;
  border-color: transparent;
  color: var(--muted);
}
.btn.ghost:hover {
  background: var(--bg-elev);
  color: var(--text);
  border-color: var(--border-soft);
}
.btn.sm {
  padding: 0.38rem 0.7rem;
  font-size: 0.82rem;
}
.btn-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}
/* In flight. Reads as "working", not as "broken" — the cursor matters
   as much as the dimming, because a dimmed button with a pointer cursor
   invites the second click this exists to prevent. */
.btn:disabled,
.btn[aria-busy="true"] {
  opacity: 0.55;
  cursor: progress;
  pointer-events: none;
}

/* ── List paging ──────────────────────────────────────────────────── */
.list-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.6rem;
  padding: 0 0.2rem;
}

/* ── Cards / layout ───────────────────────────────────────────────── */
.card {
  background: var(--glass-panel);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-edge);
  border-radius: var(--radius);
  padding: 1.15rem 1.25rem;
  /* The inset line is the whole trick: a bright hairline along the top
     edge is what makes a pane look lit rather than merely transparent. */
  box-shadow: var(--shadow), inset 0 1px 0 var(--glass-highlight);
}
.card h3 {
  margin: 0 0 0.85rem;
  font-size: 0.78rem;
  color: var(--dim);
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}
.stat {
  background: var(--bg-card);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 0.95rem 1.05rem;
  box-shadow: var(--shadow);
}
.stat .label {
  color: var(--dim);
  font-size: 0.7rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.stat .value {
  font-size: 1.4rem;
  font-weight: 650;
  margin-top: 0.3rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--text);
}
.grid-2 {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 0.9rem;
}
@media (max-width: 960px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    position: static;
    height: auto;
    max-height: none;
    border-right: 0;
    border-bottom: 1px solid var(--border-soft);
  }
  .grid-2 { grid-template-columns: 1fr; }
  .main { padding: 1rem 1rem 2.5rem; }
}

/* ── Tables ───────────────────────────────────────────────────────── */
.table-wrap { overflow: auto; }
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
table.data th {
  text-align: left;
  color: var(--dim);
  font-weight: 650;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.045em;
  padding: 0.55rem 0.55rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-card-2);
  position: sticky;
  top: 0;
}
table.data td {
  padding: 0.6rem 0.55rem;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: top;
  color: var(--text);
}
table.data tr:hover td { background: rgba(26, 127, 212, 0.04); }
table.data tr.clickable { cursor: pointer; }
table.data tr.clickable:hover td { background: var(--accent-soft); }

.mono {
  font-family: var(--mono);
  font-size: 0.8rem;
  word-break: break-all;
  color: var(--mono-text);
}
.pill {
  display: inline-block;
  padding: 0.14rem 0.5rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 650;
  letter-spacing: 0.03em;
  border: 1px solid transparent;
}
.pill.go {
  background: var(--mint-soft);
  color: var(--good);
  border-color: rgba(13, 159, 110, 0.28);
}
.pill.warn {
  background: rgba(196, 133, 26, 0.1);
  color: var(--warn);
  border-color: rgba(196, 133, 26, 0.28);
}
.pill.bad {
  background: rgba(201, 60, 60, 0.1);
  color: var(--bad);
  border-color: rgba(201, 60, 60, 0.28);
}
.pill.neutral {
  background: var(--bg-elev);
  color: var(--muted);
  border-color: var(--border);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: end;
  margin-bottom: 0.9rem;
}
.filters label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--muted);
}
.filters.inline { margin-bottom: 0.75rem; }
.filters input { min-width: 140px; }

.tabs {
  display: flex;
  gap: 0.35rem;
  margin: 0.9rem 0 0.7rem;
  flex-wrap: wrap;
}
.tab {
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 999px;
  padding: 0.38rem 0.9rem;
  font: inherit;
  font-size: 0.84rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
}
.tab:hover { color: var(--text); border-color: var(--dim); }
.tab.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: rgba(26, 127, 212, 0.35);
  font-weight: 600;
}
.detail-header { margin-top: 0.75rem; }
.verdict {
  display: inline-block;
  padding: 0.4rem 0.8rem;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  margin: 0.5rem 0;
}
.verdict.ok { background: var(--verdict-ok-bg); color: var(--verdict-ok-fg); }
.verdict.fail { background: var(--verdict-fail-bg); color: var(--verdict-fail-fg); }
.verdict.unk { background: var(--verdict-unk-bg); color: var(--verdict-unk-fg); }

.code-block {
  background: var(--bg-card-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  overflow: auto;
  font-family: var(--mono);
  font-size: 0.78rem;
  max-height: 420px;
  white-space: pre-wrap;
  word-break: break-word;
  /* Was a hardcoded navy: the background followed the theme but the
     text did not, so every code panel — SDK wiring, manifests,
     control policy, ledger, the flag histogram — went dark-on-dark. */
  color: var(--text);
  line-height: 1.5;
}
.kv {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 0.4rem 0.85rem;
  font-size: 0.9rem;
}
/* Now a real <dl>; the UA margin has to go for the grid to sit flat. */
.kv { margin: 0; }
.kv dt { color: var(--muted); font-weight: 500; }
.kv dd { margin: 0; color: var(--text); }

.toast {
  position: fixed;
  bottom: 1.35rem;
  right: 1.35rem;
  /* Was hardcoded #fff, which put light-theme white behind
     light-theme text once the dark palette existed. */
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.75rem 1.1rem;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  z-index: 50;
  max-width: 360px;
  font-size: 0.9rem;
  font-weight: 500;
}
.empty {
  color: var(--muted);
  padding: 1.25rem 0.35rem;
  font-size: 0.9rem;
}
.narrative {
  font-size: 0.95rem;
  line-height: 1.6;
  margin: 0.5rem 0 1rem;
  color: var(--text);
}
.section-title {
  font-size: 0.72rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--dim);
  margin: 1.1rem 0 0.45rem;
}

/* Posture / forms */
.posture-banner { margin-bottom: 1rem; }
.posture-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.posture-title {
  font-size: 1.05rem;
  font-weight: 600;
  margin-top: 0.25rem;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  letter-spacing: -0.01em;
}
.reason-list {
  margin: 0.5rem 0 0;
  padding-left: 1.2rem;
  color: var(--muted);
  line-height: 1.55;
}
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem 1rem;
  margin-bottom: 0.85rem;
}
@media (max-width: 720px) {
  .form-grid { grid-template-columns: 1fr; }
}
.form-grid textarea,
.field textarea,
.field select,
select {
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem;
  font: inherit;
  width: 100%;
}
.form-grid textarea {
  font-family: var(--mono);
  font-size: 0.82rem;
  resize: vertical;
  line-height: 1.45;
}
.field input.mono,
input.mono {
  font-family: var(--mono);
  font-size: 0.82rem;
}

/* Card spacing rhythm */
.view > .card + .card,
.view > .stat-grid + .grid-2,
.view > .card + .stat-grid {
  /* handled by inline margins in HTML */
}

/* Scrollbar polish */
.sidebar::-webkit-scrollbar,
.code-block::-webkit-scrollbar,
.table-wrap::-webkit-scrollbar {
  width: 8px;
  height: 8px;
  background: transparent;
}
.sidebar::-webkit-scrollbar-thumb,
.code-block::-webkit-scrollbar-thumb,
.table-wrap::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 8px;
}

/* ── Confirmation dialog ──────────────────────────────────────────── */
/* Replaces window.confirm for destructive actions. A native dialog
   cannot say what will actually happen, cannot be styled, and reads as
   unfinished on a product people are asked to trust with evidence. */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(8, 16, 26, 0.55);
  display: grid;
  place-items: center;
  z-index: 100;
  padding: 1.5rem;
}
.modal {
  width: min(460px, 100%);
  background: var(--glass-raised);
  backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) * 1.4)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-edge);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 1.4rem 1.5rem 1.2rem;
}
.modal h2 {
  margin: 0 0 0.5rem;
  font-size: 1.05rem;
  font-weight: 650;
  color: var(--text);
}
.modal p {
  margin: 0 0 1.15rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}
.modal-actions {
  display: flex;
  gap: 0.6rem;
  justify-content: flex-end;
}
.btn.danger {
  /* Same pairing as the fail badge. White on --bad works in light and
     is 2.8:1 in dark, where --bad is a light red — the foreground has
     to follow the theme, not be assumed. */
  background: var(--verdict-fail-bg);
  border-color: var(--verdict-fail-bg);
  color: var(--verdict-fail-fg);
  font-weight: 600;
}
.btn.danger:hover { filter: brightness(0.94); }

/* ── Table density ────────────────────────────────────────────────── */
/* Investigators scan long lists; compact fits ~40% more rows without
   dropping below a comfortable hit target. */
:root[data-density="compact"] table.data th,
:root[data-density="compact"] table.data td {
  padding-top: 0.34rem;
  padding-bottom: 0.34rem;
}

/* Role picker in the users tables. Sized to the table row rather than
   the form fields it inherits from. */
.role-select {
  font-size: 0.82rem;
  padding: 0.28rem 0.45rem;
  max-width: 15rem;
}

/* ── Glass: opt-outs ──────────────────────────────────────────────── */

/* Some people find translucency actively hard to read, and the OS lets
   them say so. Honour it by going solid rather than by softening the
   effect — half-transparency helps nobody who asked for none. */
@media (prefers-reduced-transparency: reduce) {
  .card, .auth-card, .sidebar, .modal {
    background: var(--bg-card);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: var(--shadow);
  }
  .sidebar { background: var(--bg-elev); }
  body { background-attachment: scroll; }
}

/* Windows high-contrast and similar forced-colour modes replace the
   palette wholesale; a blur on top of that is noise. */
@media (forced-colors: active) {
  .card, .auth-card, .sidebar, .modal {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* Evidence stays flat.
   The blur belongs to the chrome. Decision tables and JSON panels are
   what an investigator reads for minutes at a time, and a shifting
   backdrop under a column of hashes is the opposite of calm — so the
   pane holds them, and they sit on a solid surface inside it. */
.table-wrap {
  background: var(--bg-card);
  border-radius: var(--radius-sm);
}
.card > .table-wrap:only-child {
  /* A card that is nothing but a table: let the card be the surface
     rather than stacking two. */
  background: transparent;
}
