/* =========================================================================
   LastEvidence Console — enterprise-dark theme
   Refined, restrained security-product look for a conservative bank buyer.
   Green is a sparse trust/verified accent only. No neon.
   ========================================================================= */

:root {
  /* Cool blue-slate neutrals (hue-biased, layered for depth) */
  --bg:        #090c12;
  --surface:   #0f141d;   /* card ground */
  --surface-2: #161c27;   /* inputs / raised */
  --surface-3: #1b2330;   /* hover */
  --border:    #1a212e;   /* barely-there separation */
  --border-lt: #273140;   /* stronger edge where needed */
  --text:      #eef2f8;
  --muted:     #97a4ba;
  --faint:     #5f6c84;
  --green:     #3ddc84;  /* brand + verified accent */
  --green-bg:  rgba(61,220,132,0.11);
  --amber:     #f5b544;
  --amber-bg:  rgba(245,181,68,0.11);
  --red:       #f26d6d;
  --red-bg:    rgba(242,109,109,0.11);
  --blue:      #6aa5ff;
  --blue-bg:   rgba(106,165,255,0.11);
  --purple:    #b98fe6;
  --mono:      'SF Mono', 'JetBrains Mono', 'Cascadia Code', 'Consolas', ui-monospace, monospace;
  --ui:        -apple-system, BlinkMacSystemFont, 'Segoe UI Variable', 'Segoe UI', system-ui, Roboto, 'Helvetica Neue', sans-serif;
  --topbar-h:  58px;
  --sidebar-w: 244px;
  --radius:    12px;
  --radius-sm: 9px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.30);
  --shadow:    0 1px 2px rgba(0,0,0,0.4), 0 10px 34px rgba(0,0,0,0.30);
  --ring:      0 0 0 3px rgba(61,220,132,0.25);
}

* , *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background:
    radial-gradient(900px 500px at 80% -8%, rgba(61,220,132,0.05), transparent 60%),
    radial-gradient(1000px 600px at 10% -5%, rgba(106,165,255,0.045), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.55;
  letter-spacing: -0.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* figures line up */
.stat .value, .hm-val, .g-val, .sev, .table td, .kv .v, .stat-pill b, .feed-row .f-time { font-variant-numeric: tabular-nums; }

/* motion + focus */
.btn, .nav-item, .role-select, .input, .table tr.clickable, .linkbtn, .modal-close, a {
  transition: background-color .13s ease, border-color .13s ease, color .13s ease, box-shadow .13s ease, transform .13s ease;
}
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 6px; }
.input:focus-visible, .role-select:focus-visible { border-color: var(--green); box-shadow: var(--ring); }
::selection { background: rgba(61,220,132,0.28); }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-lt); border-radius: 6px; border: 3px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: #33405280; background-clip: padding-box; }

.mono { font-family: var(--mono); }
.hidden { display: none !important; }

/* Small utilities added by the real console (not from the mock). */
.form-error { color: var(--red); font-size: 12.5px; margin-top: 10px; min-height: 1em; }
/* F-224 Fix #3 — request_id shown under a search failure's user_message,
   subtle enough not to compete with it, present so a support flow can
   correlate this screen with a server log line. */
.ev-search-err-ref { margin-top: 6px; font-size: 11.5px; }
/* F-155 — shown when the login screen was reached because a session
   timed out, not because this is a fresh visit. Same left-accent
   convention as .dash-stale-banner (color on the accent, not the text)
   so it reads as informational rather than as another form error. */
.login-notice { font-size: 12.5px; line-height: 1.5; margin-bottom: 16px;
                 padding: 8px 12px; border-left: 3px solid var(--blue);
                 background: var(--surface-2); border-radius: var(--radius-sm); }
.form-ok { color: var(--accent); font-size: 12.5px; margin-top: 4px; min-height: 1em; }
/* F-271 — settings_ingestion.js's single save/restart-progress status
   banner (Piece D: one seven-state machine, one visible banner at a
   time — see settings_ingestion.js's header comment). Same left-accent/
   background convention as .dash-stale-banner: colour lives on the
   accent border and (for the ok/restart/error states) the background
   tint, not just the text, so the state reads even to someone scanning
   quickly. `:empty` hides the element entirely rather than reserving
   blank space, matching #dash-stale-banner's idiom.
   --wait    : states A (Saving...) and B (Waiting for bridge...) — amber
               accent, no background tint, so C reads as visually
               distinct despite being the same hue.
   --restart : state C (Bridge restarting..., live elapsed counter) —
               amber accent WITH background tint. Reused as-is from the
               pre-Piece-D "restart required" persistent banner this
               replaced; that banner is gone (the operator rejected it
               as breaking Save-is-the-abstraction — see
               settings_ingestion.js), but its amber-with-tint styling
               fit state C's "something is actively happening, still
               amber not red" case well enough not to need a new rule.
   --ok      : state D (Applied at ...) — green, auto-fades.
   --error   : states E/F/G (timeout / restart-too-long / restart-loop)
               — red, persists until the next Save attempt. */
.si-status-banner:empty { display: none; }
.si-status-banner { font-size: 12.5px; line-height: 1.5; margin-top: 10px;
                     padding: 8px 12px; border-left: 3px solid var(--faint);
                     background: var(--surface-2); border-radius: var(--radius-sm); }
.si-status-banner--wait  { border-left-color: var(--amber); color: var(--text); }
.si-status-banner--ok    { border-left-color: var(--green); color: var(--green); background: var(--green-bg); }
.si-status-banner--error { border-left-color: var(--red); color: var(--red); background: var(--red-bg); }
.si-status-banner--restart { border-left-color: var(--amber); color: var(--text); background: var(--amber-bg); }
.field-flexrow { display: flex; gap: 16px; align-items: flex-start; }
.field-flexrow .col-1 { flex: 1 1 0; min-width: 0; }
.mw-danger { background: rgba(217, 83, 79, 0.06); }
.mw-danger td:first-child { border-left: 3px solid var(--red); }
/* R-011 finding 4 — same left-accent/age-in-words convention as
   dashboard.js's .dash-stale-banner, scaled to one field. */
.mw-lastevt-stale { font-size: 11.5px; margin-top: 4px; }
.dash-tile-chip { margin-top: 8px; font-size: 11.5px; color: var(--muted); }
.dash-tile-chip .badge { margin-right: 6px; }
.ev-recover-note { margin-top: 10px; font-size: 12.5px; padding: 8px 12px;
                   border-left: 3px solid var(--yellow, #a37c11); }
.ev-recover-note--alert { border-left-color: var(--red); color: var(--text); }
.qr-frame   { display: flex; justify-content: center; margin: 14px 0; }
.qr-frame img { border-radius: 8px; background: #fff; padding: 8px; }
.secret-line { font-family: var(--mono); font-size: 12.5px; color: var(--muted); word-break: break-all; user-select: all; }
.recovery-pre { font-family: var(--mono); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px; font-size: 12.5px; white-space: pre; overflow-x: auto; margin: 12px 0; user-select: all; }

/* ---------- Topbar ---------- */
#topbar {
  position: fixed; inset: 0 0 auto 0; height: var(--topbar-h); z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 22px;
  background: linear-gradient(180deg, rgba(17,22,31,0.92), rgba(11,14,20,0.86));
  backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 rgba(255,255,255,0.02), 0 6px 24px rgba(0,0,0,0.25);
}
.brand { display: flex; align-items: center; gap: 11px; }
.brand .mark { width: 26px; height: 26px; filter: drop-shadow(0 2px 6px rgba(61,220,132,0.25)); }
.brand .wordmark { font-size: 17px; font-weight: 750; letter-spacing: -0.3px; }
.brand .wordmark .last { color: #e6edf3; }
.brand .wordmark .evidence { color: #e63956; }
.brand .tag {
  margin-left: 10px; padding-left: 12px; border-left: 1px solid var(--border-lt);
  font-size: 11px; letter-spacing: 1.5px; color: var(--faint); text-transform: uppercase;
}
.brand .tag--version { font-family: var(--mono); letter-spacing: 0; text-transform: none;
                        color: var(--muted); cursor: help; }
.topbar-right { display: flex; align-items: center; gap: 16px; }
.tenant { font-size: 13px; color: var(--muted); }
.tenant strong { color: var(--text); font-weight: 600; }

/* ---------- Update banner (F-249d) — long-lived-tab staleness ----------
   Fixed to the viewport bottom rather than woven into the topbar/sidebar/
   #view fixed offsets above, so it can appear or disappear without ever
   shifting any other fixed element. Two colored states only (never a
   third "healthy" style — the hidden class IS the healthy/no-op state,
   per rule 7: there is nothing to name when the commit matches). */
#update-banner {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  padding: 10px 22px; font-size: 13px; line-height: 1.4; text-align: center;
  border-top: 1px solid var(--border-lt);
  backdrop-filter: blur(14px) saturate(140%);
}
#update-banner.hidden { display: none; }
.update-banner--available { background: var(--green-bg); }
.update-banner--available:hover { background: rgba(61,220,132,0.20); }
.update-banner-btn {
  background: none; border: none; color: var(--text); font: inherit;
  cursor: pointer; width: 100%; padding: 0;
}
.update-banner--unable {
  background: var(--amber-bg); color: var(--text);
}

/* ---------- Timezone picker (topbar) — plan-tz-preference.md §5.4 ---------- */
.tzpick-warn { font-size: 12px; color: var(--amber); max-width: 260px; }
.tzpick { position: relative; }
.tzpick-toggle {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border-lt);
  border-radius: 7px; padding: 7px 11px; font-family: var(--mono); font-size: 12.5px; cursor: pointer;
}
.tzpick-toggle:hover { border-color: var(--faint); }
.tzpick-toggle:focus-visible { border-color: var(--green); box-shadow: var(--ring); }
.tzpick-panel {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0; width: 320px;
  background: var(--surface-2); border: 1px solid var(--border-lt); border-radius: var(--radius-sm);
  padding: 10px; box-shadow: var(--shadow);
}
.tzpick-panel .tzpick-input { margin-bottom: 8px; }
.tzpick-list { list-style: none; max-height: 280px; overflow-y: auto; }
.tzpick-opt {
  padding: 7px 9px; border-radius: 7px; font-size: 13px; font-family: var(--mono);
  color: var(--text); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tzpick-opt:hover { background: var(--surface-3); }
.tzpick-opt--sel { background: var(--green-bg); color: var(--green); }
.tzpick-sep { height: 1px; margin: 6px 2px; background: var(--border-lt); list-style: none; }
.tzpick-empty, .tzpick-degraded { font-size: 12.5px; padding: 6px 2px; }
.tzpick-error { font-size: 12.5px; color: var(--red); padding: 6px 2px 0; }
.role-select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-lt); border-radius: 7px;
  padding: 7px 11px; font-family: var(--ui); font-size: 13px; cursor: pointer;
}
.role-select:hover { border-color: var(--faint); }
.linkbtn { background: none; border: none; color: var(--muted); font-size: 13px; cursor: pointer; font-family: var(--ui); }
.linkbtn:hover { color: var(--text); }

/* ---------- Sidebar ---------- */
#sidebar {
  position: fixed; top: var(--topbar-h); bottom: 0; left: 0; width: var(--sidebar-w);
  background: linear-gradient(180deg, #0d121b, #0a0e15);
  border-right: 1px solid var(--border);
  padding: 18px 14px; overflow-y: auto; z-index: 40;
}
.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 13px; border-radius: var(--radius-sm); margin-bottom: 3px;
  color: var(--muted); font-size: 13.5px; font-weight: 550; cursor: pointer;
  user-select: none;
}
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; stroke: currentColor; opacity: 0.85; }
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item.active { background: var(--green-bg); color: var(--green); }
.nav-item.active svg { opacity: 1; }
.nav-item.active::before {
  content: ""; position: absolute; left: -14px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--green);
  box-shadow: 0 0 12px rgba(61,220,132,0.6);
}
.nav-foot { margin-top: 26px; padding: 14px 12px 0; font-size: 11px; color: var(--faint); line-height: 1.6; border-top: 1px solid var(--border); }
.nav-foot img { height: 15px; opacity: 0.6; vertical-align: middle; margin-right: 6px; border-radius: 3px; }

/* ---------- Main view ---------- */
#view {
  margin: var(--topbar-h) 0 0 var(--sidebar-w);
  padding: 32px 36px 48px; min-height: calc(100vh - var(--topbar-h));
  /* F-240: was 1320px, leaving a large unused dark band on the right of
     every screen on any monitor wider than ~1650px total (sidebar +
     1320 + browser chrome). Raised so the console uses the available
     width on normal desktop/laptop viewports. Still capped (not 100%)
     so table rows and prose don't stretch into uncomfortable line
     lengths on ultrawide (3440px+) monitors. */
  max-width: 2400px;
}
.page-head { margin-bottom: 24px; }
.page-title { font-size: 25px; font-weight: 780; letter-spacing: -0.6px; text-wrap: balance; }
.page-sub { color: var(--muted); font-size: 13.5px; margin-top: 5px; max-width: 70ch; }

/* ---------- Cards & layout ---------- */
.card {
  background: linear-gradient(180deg, var(--surface), #0c111a);
  border: 1px solid var(--border);
  border-radius: var(--radius); padding: 22px;
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 16px; }
.card-title { font-size: 11.5px; font-weight: 650; color: var(--faint); text-transform: uppercase; letter-spacing: 0.09em; margin-bottom: 16px; }
.grid { display: grid; gap: 16px; }
.grid-5 { grid-template-columns: repeat(5, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 1100px) { .grid-5, .grid-4 { grid-template-columns: repeat(2, 1fr); } .grid-2 { grid-template-columns: 1fr; } }

/* ---------- Stat tiles ---------- */
.stat { background: linear-gradient(180deg, var(--surface), #0c111a); border: 1px solid var(--border); border-radius: var(--radius); padding: 17px 19px; box-shadow: var(--shadow-sm); }
.stat .label { font-size: 11.5px; color: var(--muted); margin-bottom: 9px; text-transform: uppercase; letter-spacing: 0.05em; }
.stat .value { font-size: 27px; font-weight: 760; letter-spacing: -0.7px; }
.stat .value.good { color: var(--green); }
.stat .value.warn { color: var(--amber); }
.stat .value.bad  { color: var(--red); }
.stat .sub { font-size: 12px; color: var(--faint); margin-top: 4px; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10.5px; font-weight: 650; padding: 3px 10px; border-radius: 20px;
  letter-spacing: 0.04em; text-transform: uppercase; border: 1px solid transparent;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; box-shadow: 0 0 6px currentColor; }
.badge--ok    { color: var(--green); background: var(--green-bg); border-color: rgba(61,220,132,0.22); }
.badge--warn  { color: var(--amber); background: var(--amber-bg); border-color: rgba(245,181,68,0.22); }
.badge--alert { color: var(--red);   background: var(--red-bg);   border-color: rgba(242,109,109,0.22); }
.badge--info  { color: var(--blue);  background: var(--blue-bg);  border-color: rgba(106,165,255,0.22); }
.badge--muted { color: var(--muted); background: var(--surface-2); border-color: var(--border-lt); }
.badge.no-dot::before { display: none; }

/* ---------- Tables ---------- */
.table { width: 100%; border-collapse: collapse; }
.table th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--faint); font-weight: 650; padding: 12px 14px; border-bottom: 1px solid var(--border-lt);
  background: rgba(255,255,255,0.015); position: sticky; top: 0;
}
.table td { padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: 13px; }
.table tbody tr:last-child td { border-bottom: none; }
.table tr.clickable { cursor: pointer; }
.table tr.clickable:hover td { background: var(--surface-2); }
.table td.mono { font-size: 12px; color: var(--muted); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-lt); border-radius: var(--radius-sm);
  padding: 9px 16px; font-size: 13px; font-weight: 600; font-family: var(--ui); cursor: pointer;
}
.btn:hover { border-color: var(--faint); background: var(--surface-3); }
.btn:active { transform: translateY(1px); }
.btn--primary {
  background: linear-gradient(180deg, rgba(61,220,132,0.20), rgba(61,220,132,0.12));
  color: var(--green); border-color: rgba(61,220,132,0.35);
}
.btn--primary:hover { background: rgba(61,220,132,0.24); border-color: rgba(61,220,132,0.55); box-shadow: 0 4px 16px rgba(61,220,132,0.15); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn:disabled:active { transform: none; }
.btn--sm { padding: 6px 12px; font-size: 12px; }

.input, select.input {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border-lt);
  border-radius: var(--radius-sm); padding: 9px 13px; font-size: 13px; font-family: var(--ui); width: 100%;
}
.input::placeholder { color: var(--faint); }
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }

/* ---------- Sparkline ---------- */
.sparkline { width: 100%; height: 56px; display: block; }

/* ---------- Incident lead card ---------- */
.lead {
  border: 1px solid rgba(240,168,58,0.35); background: var(--amber-bg);
  border-radius: var(--radius); padding: 18px 20px;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.lead .lead-title { font-weight: 700; color: var(--amber); font-size: 15px; margin-bottom: 4px; }
.lead .lead-body { color: var(--text); font-size: 13px; }
.lead .lead-body .t { font-family: var(--mono); color: var(--amber); }

/* ---------- Verify: proof chain ---------- */
.verify-banner {
  display: flex; align-items: center; gap: 16px; padding: 22px 24px;
  border-radius: var(--radius); margin-bottom: 20px; border: 1px solid;
}
.verify-banner .glyph { font-size: 34px; line-height: 1; }
.verify-banner .vb-title { font-size: 20px; font-weight: 800; letter-spacing: 0.5px; }
.verify-banner .vb-sub { font-size: 13px; opacity: 0.85; }
.verify-banner.ok    { background: var(--green-bg); border-color: rgba(61,220,132,0.4); color: var(--green); }
.verify-banner.bad   { background: var(--red-bg);   border-color: rgba(239,83,80,0.4);  color: var(--red); }

.proof { list-style: none; position: relative; margin-left: 8px; }
.proof li { position: relative; padding: 0 0 22px 30px; border-left: 2px solid var(--border-lt); }
.proof li:last-child { border-left-color: transparent; padding-bottom: 0; }
.proof li::before {
  content: ""; position: absolute; left: -7px; top: 2px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--surface); border: 2px solid var(--green);
}
.proof .step-label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.proof .step-val { font-family: var(--mono); font-size: 13px; word-break: break-all; margin-top: 3px; }
.proof .step-val.tampered { color: var(--red); text-decoration: line-through wavy; }
mark.hashdiff { background: var(--red); color: #fff; border-radius: 3px; padding: 0 2px; }

/* ---------- Timeline ---------- */
.timeline { list-style: none; margin-left: 10px; }
.timeline li { position: relative; padding: 0 0 24px 28px; border-left: 2px solid var(--border-lt); }
.timeline li:last-child { border-left-color: transparent; }
.timeline li::before {
  content: ""; position: absolute; left: -8px; top: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--surface); border: 2px solid var(--blue);
}
.timeline li.impact::before { border-color: var(--red); }
.timeline li.silent::before { border-color: var(--amber); background: var(--amber); }
.tl-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tl-clocks { display: flex; gap: 18px; margin: 6px 0; font-size: 12px; }
.tl-clock { display: flex; flex-direction: column; }
.tl-clock .ck-label { color: var(--faint); font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
.tl-clock .ck-val { font-family: var(--mono); }
.tl-clock.siem .ck-val { color: var(--amber); }
.tl-clock.chain .ck-val { color: var(--green); }
.tl-desc { color: var(--text); font-size: 13px; }
.tl-host { color: var(--muted); font-family: var(--mono); font-size: 12px; }
.mitre-chip { font-family: var(--mono); font-size: 11px; background: var(--blue-bg); color: var(--blue); padding: 2px 7px; border-radius: 5px; }
.silence-callout { background: var(--amber-bg); border: 1px dashed rgba(240,168,58,0.4); border-radius: 8px; padding: 12px 14px; color: var(--amber); font-size: 13px; margin-top: 4px; }

/* ---------- Signed artifact preview ---------- */
.artifact {
  background: #0a0d13; border: 1px solid var(--border-lt); border-radius: 8px;
  padding: 16px; font-family: var(--mono); font-size: 12px; color: var(--muted);
  white-space: pre-wrap; word-break: break-all; margin-top: 16px;
}
.artifact .sig { color: var(--green); }
.artifact a.artlink { color: var(--blue); text-decoration: underline; word-break: break-all; }

/* ---------- Source cards ---------- */
.source-row { display: flex; align-items: center; justify-content: space-between; padding: 14px 0; border-bottom: 1px solid var(--border); }
.source-row:last-child { border-bottom: none; }
.source-name { font-weight: 600; }
.source-meta { color: var(--muted); font-size: 12px; font-family: var(--mono); }

/* ---------- Settings roadmap sections ---------- */
.roadmap-tag { font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--amber); background: var(--amber-bg); padding: 3px 8px; border-radius: 5px; margin-left: 10px; }

/* ---------- Login overlay ---------- */
#login {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(700px 360px at 50% 8%, rgba(61,220,132,0.10), transparent 60%),
    radial-gradient(1200px 600px at 50% -10%, #131b28 0%, var(--bg) 60%);
}
.login-card {
  width: 392px; background: linear-gradient(180deg, #141b26, #0d121b);
  border: 1px solid var(--border-lt);
  border-radius: 16px; padding: 36px; box-shadow: var(--shadow);
}
.login-card .brand { justify-content: center; margin-bottom: 6px; }
.login-card .brand .wordmark { font-size: 22px; }
.login-sub { text-align: center; color: var(--muted); font-size: 13px; margin-bottom: 24px; }
.login-note { text-align: center; color: var(--faint); font-size: 11px; margin-top: 16px; }
.login-recovery-row { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.login-recovery-toggle { font-size: 12px; color: var(--accent); text-decoration: none; }
.login-recovery-toggle:hover { text-decoration: underline; }
#use-recovery-hint { font-size: 11.5px; line-height: 1.4; }

/* ---------- Dashboard hero ---------- */
.hero {
  display: grid; grid-template-columns: 210px 1fr; gap: 32px; align-items: center;
  position: relative; overflow: hidden;
  background:
    radial-gradient(420px 200px at 12% 0%, rgba(61,220,132,0.08), transparent 70%),
    linear-gradient(180deg, #141b26, #0d121b);
  border: 1px solid var(--border-lt); border-radius: var(--radius); padding: 26px 30px;
  box-shadow: var(--shadow);
}
.gauge { display: flex; flex-direction: column; align-items: center; }
.gauge .g-val { font-size: 30px; font-weight: 800; letter-spacing: -0.5px; color: var(--green); }
.gauge .g-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; margin-top: 2px; }
.hero-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.hm .hm-val { font-size: 24px; font-weight: 700; letter-spacing: -0.4px; }
.hm .hm-label { font-size: 12px; color: var(--muted); margin-top: 2px; }
.live-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--green); margin-right: 7px; box-shadow: 0 0 0 0 rgba(61,220,132,0.6); animation: pulse 2s infinite; }
@keyframes pulse { 0%{box-shadow:0 0 0 0 rgba(61,220,132,0.5);} 70%{box-shadow:0 0 0 8px rgba(61,220,132,0);} 100%{box-shadow:0 0 0 0 rgba(61,220,132,0);} }

/* ---------- Chart ---------- */
.chart-wrap { position: relative; }
.chart-wrap svg { width: 100%; height: auto; display: block; }
.chart-grid line { stroke: var(--border); stroke-width: 1; }
.chart-axis text { fill: var(--faint); font-size: 10px; font-family: var(--mono); }
.chart-tip {
  position: absolute; pointer-events: none; background: #0a0d13; border: 1px solid var(--border-lt);
  border-radius: 6px; padding: 6px 9px; font-size: 12px; color: var(--text); white-space: nowrap;
  transform: translate(-50%, -115%); opacity: 0; transition: opacity 0.08s; z-index: 5;
}
.chart-tip .tip-v { font-family: var(--mono); font-weight: 700; }
.chart-annot { fill: var(--red); font-size: 11px; font-weight: 700; font-family: var(--ui); }

/* ---------- Recent anchors feed ---------- */
.feed-row { display: grid; grid-template-columns: 64px 1fr auto auto; gap: 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.feed-row:last-child { border-bottom: none; }
.feed-row .f-time { font-family: var(--mono); color: var(--muted); font-size: 12px; }
.feed-row .f-host { font-family: var(--mono); }
.feed-row .f-tx { font-family: var(--mono); font-size: 12px; }

/* ---------- Source health mini-bars ---------- */
.srcbar { display: grid; grid-template-columns: 120px 1fr 70px; gap: 12px; align-items: center; padding: 9px 0; }
.srcbar .sb-name { font-size: 13px; }
.srcbar .sb-track { height: 8px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
.srcbar .sb-fill { height: 100%; border-radius: 4px; background: var(--green); }
.srcbar .sb-fill.stale { background: var(--amber); }
.srcbar .sb-fill.down { background: var(--red); }
.srcbar .sb-meta { font-family: var(--mono); font-size: 11px; color: var(--muted); text-align: right; }

/* ---------- Log explorer: query bar + filters + severity + stats ---------- */
/* Full-width query bar on its own row so long queries stay fully visible. */
.qbar { position: relative; display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--surface-2); border: 1px solid var(--border-lt); border-radius: var(--radius-sm);
  padding: 4px 6px 4px 12px; margin-bottom: 6px; }
.qbar:focus-within { border-color: var(--green); box-shadow: var(--ring); }
.qbar-ico { display: flex; color: var(--faint); flex: none; }
.qbar-ico svg { width: 16px; height: 16px; stroke: currentColor; }
.qinput { flex: 1 1 auto; min-width: 0; background: none; border: none; outline: none;
  color: var(--text); font-family: var(--mono); font-size: 13px; padding: 8px 4px; }
.qinput::placeholder { color: var(--faint); }
.qa-ex-btn { flex: none; }
.qhint { min-height: 16px; font-size: 12px; color: var(--faint); margin: 0 0 12px 2px; }
.qhint.err { color: var(--amber); }

/* Autocomplete + examples popovers (share the query-bar's relative wrapper) */
.qa-panel, .ex-panel { position: absolute; z-index: 30; top: calc(100% + 4px); background: var(--surface-2);
  border: 1px solid var(--border-lt); border-radius: var(--radius-sm); box-shadow: var(--shadow); overflow: hidden; }
.qa-panel { left: 34px; min-width: 260px; max-height: 280px; overflow-y: auto; padding: 5px; }
.qa-item { padding: 7px 10px; border-radius: 6px; font-family: var(--mono); font-size: 12.5px; color: var(--text); cursor: pointer; }
.qa-item:hover, .qa-item.active { background: var(--surface-3); }
.ex-panel { right: 6px; width: 340px; padding: 6px; }
.ex-item { padding: 9px 11px; border-radius: 7px; cursor: pointer; }
.ex-item:hover { background: var(--surface-3); }
.ex-item .ex-label { font-size: 13px; color: var(--text); }
/* F-285: query text is a <code> element now (was a <div>) for semantic
   correctness — display:block keeps it stacking below .ex-label exactly
   as before, since margin-top has no effect on an inline box. */
.ex-item .ex-q { display: block; font-size: 12px; color: var(--green); margin-top: 3px; }

.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 14px; }
.filters .input { width: auto; }
.filters input.input { min-width: 220px; }
.flex-spacer { flex: 1 1 auto; }
/* MITRE multi-select */
.ms { position: relative; display: inline-block; }
.ms-trigger { cursor: pointer; text-align: left; min-width: 190px; display: inline-flex; align-items: center; justify-content: space-between; gap: 10px; }
.ms-trigger::after { content: "▾"; color: var(--faint); font-size: 11px; }
.ms-panel { position: absolute; z-index: 25; top: calc(100% + 5px); left: 0; min-width: 260px; max-height: 300px; overflow-y: auto;
  background: var(--surface-2); border: 1px solid var(--border-lt); border-radius: var(--radius-sm); padding: 6px; box-shadow: var(--shadow); }
.ms-opt { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 7px; font-size: 13px; cursor: pointer; color: var(--text); }
.ms-opt:hover { background: var(--surface-3); }
.ms-opt input { accent-color: var(--green); width: 15px; height: 15px; cursor: pointer; }

.stat-pills { display: flex; gap: 20px; margin-bottom: 16px; flex-wrap: wrap; }
.stat-pill { font-size: 13px; color: var(--muted); }
.stat-pill b { color: var(--text); font-size: 15px; margin-right: 4px; }
.stat-pill.crit b { color: var(--red); }

.sev { display: inline-block; min-width: 22px; text-align: center; font-family: var(--mono); font-size: 12px; font-weight: 700;
  padding: 2px 7px; border-radius: 5px; }
.sev.crit { background: var(--red-bg); color: var(--red); }
.sev.warn { background: var(--amber-bg); color: var(--amber); }
.sev.info { background: var(--surface-2); color: var(--muted); }
.tampered-row td { background: rgba(239,83,80,0.06); }

/* Pagination bar under the evidence table */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-top: 12px; font-size: 13px; color: var(--muted); }
.pager-left { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.pager-rpp { display: flex; align-items: center; gap: 8px; }
.pager-size { width: auto; padding: 5px 8px; font-size: 12.5px; }
.pager-info { font-variant-numeric: tabular-nums; }
.pager-ctl { display: flex; align-items: center; gap: 8px; }
.pager-pg { font-variant-numeric: tabular-nums; color: var(--text); padding: 0 4px; min-width: 118px; text-align: center; }

/* ---------- Export dialog ---------- */
.exp-scope { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
.exp-field { display: flex; flex-direction: column; gap: 5px; }
.exp-lbl { font-size: 12px; color: var(--muted); }
.exp-field .input, .exp-field .ms, .exp-field .ms-trigger { width: 100%; }
.exp-qnote { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.exp-qnote input { accent-color: var(--green); width: 15px; height: 15px; }
.exp-qnote code { color: var(--green); font-size: 12px; }
.exp-formats { display: flex; flex-direction: column; gap: 4px; }
.exp-fmt { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px; }
.exp-fmt:hover { background: var(--surface-3); }
.exp-fmt input { accent-color: var(--green); width: 15px; height: 15px; }
.exp-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
.exp-summary { font-size: 13px; color: var(--muted); }
.exp-summary b { color: var(--text); font-size: 15px; }
.exp-btns { display: flex; gap: 10px; }

/* ---------- Detail modal ---------- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(3,5,9,0.7); z-index: 200;
  display: flex; align-items: flex-start; justify-content: center; padding: 48px 20px; overflow-y: auto; }
.modal {
  width: 720px; max-width: 100%; background: var(--surface); border: 1px solid var(--border-lt);
  border-radius: 12px; box-shadow: var(--shadow); overflow: hidden;
}
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 20px 24px; border-bottom: 1px solid var(--border); }
.modal-head .m-title { font-size: 16px; font-weight: 700; }
.modal-head .m-sub { font-size: 12px; color: var(--muted); font-family: var(--mono); margin-top: 4px; }
.modal-body { padding: 8px 24px 24px; max-height: 70vh; overflow-y: auto; }
/* F-292 — groups the maximize toggle with the existing close button so
   both sit at the head's trailing edge without disturbing modal-head's
   existing space-between/flex-start layout (only two children now: the
   title block and this actions group). */
.modal-head-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.modal-close { background: none; border: none; color: var(--muted); font-size: 22px; cursor: pointer; line-height: 1; }
.modal-close:hover { color: var(--text); }
/* F-292 — maximize/restore icon button; sized and coloured to match
   .modal-close's quiet default so it doesn't compete with it, distinct
   glyph size since ⤢/⤡ read smaller than × at the same font-size. */
.modal-icon-btn { background: none; border: none; color: var(--muted); font-size: 17px; line-height: 1;
  cursor: pointer; padding: 4px 6px; border-radius: 6px; }
.modal-icon-btn:hover { color: var(--text); background: var(--surface-3); }
/* F-187: same disabled treatment as .btn:disabled above, so a modal-close
   button behaves visibly the same way Cancel already does mid-request. */
.modal-close:disabled { opacity: 0.4; cursor: not-allowed; }
.modal-close:disabled:hover { color: var(--muted); }

.sec-hdr { font-size: 11px; text-transform: uppercase; letter-spacing: 0.7px; color: var(--faint);
  font-weight: 700; margin: 20px 0 8px; }
.kv { display: grid; grid-template-columns: 150px 1fr; gap: 8px 16px; padding: 5px 0; font-size: 13px; border-bottom: 1px solid rgba(35,44,61,0.5); }
.kv .k { color: var(--muted); }
.kv .v { color: var(--text); word-break: break-word; }
.kv .v.mono { font-family: var(--mono); font-size: 12px; }
.tag-mitre { display: inline-block; font-family: var(--mono); font-size: 11px; background: var(--blue-bg); color: var(--blue); padding: 2px 7px; border-radius: 5px; margin: 0 4px 4px 0; }
.tag-comp { display: inline-block; font-size: 11px; background: rgba(138,55,150,0.16); color: #c98fe0; padding: 2px 7px; border-radius: 5px; margin: 0 4px 4px 0; }
.proof-box { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; background: var(--green-bg);
  border: 1px solid rgba(61,220,132,0.3); border-radius: 8px; padding: 12px 14px; margin: 8px 0 4px; font-size: 13px; }
.proof-box.bad { background: var(--red-bg); border-color: rgba(239,83,80,0.35); }
.proof-box .pb-badge { font-weight: 700; color: var(--green); font-size: 12px; }
.proof-box.bad .pb-badge { color: var(--red); }
.fulllog { background: #0a0d13; border: 1px solid var(--border-lt); border-radius: 8px; padding: 12px 14px;
  font-family: var(--mono); font-size: 12px; color: var(--muted); white-space: pre-wrap; word-break: break-all; margin-top: 6px; }

/* ---------- Add-source wizard ---------- */
.wizard-steps { display: flex; gap: 18px; margin-bottom: 18px; }
.wstep { font-size: 11px; color: var(--faint); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 650; display: flex; align-items: center; gap: 7px; }
.wstep .num { width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border-lt); display: inline-flex; align-items: center; justify-content: center; font-size: 11px; }
.wstep.active { color: var(--green); }
.wstep.active .num { border-color: var(--green); background: var(--green-bg); }
.wstep.done .num { border-color: var(--green); background: var(--green); color: #04140b; }

.choice-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.choice-card { border: 1px solid var(--border-lt); border-radius: var(--radius-sm); padding: 14px; cursor: pointer; background: var(--surface-2); }
.choice-card:hover { border-color: var(--faint); background: var(--surface-3); }
.choice-card.selected { border-color: var(--green); background: var(--green-bg); }
.choice-card .cc-title { font-weight: 650; font-size: 14px; }
.choice-card .cc-desc { font-size: 12px; color: var(--muted); margin-top: 4px; }

.modal-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 16px 24px; border-top: 1px solid var(--border); background: rgba(0,0,0,0.15); }
/* F-37 S8 change 5 — .modal-foot is a row, right for a button bar; the
   wizard's success panel needs it stacked for two sentences of required
   reading. Additive modifier only — no existing rule above is edited. */
.modal-foot--notice { flex-direction: column; align-items: stretch; gap: 12px; }
.modal-foot--notice .notice-actions { display: flex; justify-content: flex-end; }
.modal-notice { font-size: 13px; color: var(--text); line-height: 1.5; }
.test-ok { color: var(--green); font-size: 13px; display: inline-flex; align-items: center; gap: 8px; }
.test-run { color: var(--muted); font-size: 13px; }
.grid-2c { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.copy-hint { font-size: 11px; color: var(--faint); margin-top: 6px; }

/* Access control */
.btn--danger { background: var(--red-bg); color: var(--red); border-color: rgba(242,109,109,0.35); }
.btn--danger:hover { background: rgba(242,109,109,0.24); border-color: rgba(242,109,109,0.55); box-shadow: 0 4px 16px rgba(242,109,109,0.14); }
.confirm-box { border: 1px solid rgba(242,109,109,0.35); background: var(--red-bg); border-radius: var(--radius-sm); padding: 12px 14px; }
.confirm-text { font-size: 12.5px; color: var(--text); line-height: 1.5; }
.policy-note { font-size: 12px; line-height: 1.5; color: var(--muted); border-radius: 8px; padding: 9px 12px; margin-top: 6px;
  border: 1px solid var(--border-lt); background: var(--surface-2); }
.policy-note.on { border-color: rgba(61,220,132,0.3); background: var(--green-bg); }
.policy-note.on b { color: var(--green); }
.policy-note.off b { color: var(--amber); }
.drift-row { display: flex; align-items: center; gap: 12px; padding: 6px 0; border-bottom: 1px solid rgba(35,44,61,0.5); font-size: 13px; }
.drift-row:last-child { border-bottom: none; }
.drift-src { min-width: 140px; font-weight: 600; }
.drift-note { color: var(--muted); font-size: 12px; }
.nav-group { margin: 16px 12px 6px; font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--faint); border-top: 1px solid var(--border); padding-top: 14px; }
.suspended-row td { opacity: 0.55; }
.matrix th:first-child, .matrix td:first-child { text-align: left; }
.matrix .cap-on { color: var(--green); font-weight: 700; }
.matrix .cap-off { color: var(--faint); }
.matrix .cap-toggle { cursor: pointer; display: inline-block; min-width: 22px; padding: 1px 6px; border-radius: 5px;
  border: 1px solid var(--border-lt); }
.matrix .cap-toggle.on { color: var(--green); background: var(--green-bg); border-color: rgba(61,220,132,0.35); font-weight: 700; }
.matrix .cap-toggle.off { color: var(--faint); }
.matrix .cap-toggle:hover { border-color: var(--faint); }

/* Correlated-detection card */
.detect { background: var(--surface); border: 1px solid var(--border-lt); border-left: 3px solid var(--muted);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm); }
.detect.verdict-critical { border-left-color: var(--red); }
.detect.verdict-warning  { border-left-color: var(--amber); }
.detect.verdict-info     { border-left-color: var(--muted); }
.detect-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.detect-verdict { font-weight: 800; font-size: 15px; letter-spacing: 0.5px; }
.verdict-critical .detect-verdict { color: var(--red); }
.verdict-warning  .detect-verdict { color: var(--amber); }
.verdict-info     .detect-verdict { color: var(--muted); }
.detect-conf { margin-left: 10px; font-size: 12px; color: var(--muted); }
.detect-window { font-size: 12px; color: var(--faint); font-family: var(--mono); }
.detect-headline { margin: 10px 0 12px; font-size: 14px; line-height: 1.5; }
.detect-scope { font-size: 12px; color: var(--muted); background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; margin: 0 0 16px; line-height: 1.5; }
.detect-scope b { color: var(--text); font-weight: 650; }
.detect-fams { display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px; align-items: stretch; }
.detect-fam { border: 1px solid var(--border-lt); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--surface-2); }
.detect-fam.integrity.lit  { border-color: rgba(242,109,109,0.4); }
.detect-fam.continuity.lit { border-color: rgba(245,181,68,0.4); }
.detect-fam.preview { border-style: dashed; opacity: 0.72; }
.detect-fam.preview .df-sig { color: var(--muted); }
.df-head { display: flex; align-items: center; gap: 8px; font-weight: 650; font-size: 13px; }
.df-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex-shrink: 0; }
.detect-fam.integrity.lit  .df-dot { background: var(--red);   box-shadow: 0 0 8px var(--red); }
.detect-fam.continuity.lit .df-dot { background: var(--amber); box-shadow: 0 0 8px var(--amber); }
.df-blurb { font-size: 11.5px; color: var(--muted); margin: 6px 0 10px; line-height: 1.45; }
.df-sig { display: flex; gap: 8px; align-items: center; font-size: 12.5px; padding: 4px 0; }
.sig-id { font-family: var(--mono); font-size: 11px; background: var(--surface-3); color: var(--muted); padding: 1px 6px; border-radius: 4px; flex-shrink: 0; }
.detect-and { display: flex; align-items: center; font-weight: 800; font-size: 12px; color: var(--faint); }
.detect-why { margin-top: 16px; border-top: 1px solid var(--border); padding-top: 14px; }
.detect-reason { margin: 0; padding-left: 18px; }
.detect-reason li { font-size: 12.5px; color: var(--muted); margin-bottom: 6px; line-height: 1.5; }
.detect-corr { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.corr-chip { font-size: 11.5px; color: var(--muted); background: var(--surface-2); border: 1px solid var(--border-lt); border-radius: 6px; padding: 4px 9px; }
.corr-chip b { color: var(--green); margin-right: 6px; }

/* Tooltips + info dots */
.tooltip { position: fixed; z-index: 300; max-width: 280px; background: #05070b; color: var(--text);
  border: 1px solid var(--border-lt); border-radius: 8px; padding: 9px 12px; font-size: 12px; line-height: 1.45;
  box-shadow: 0 8px 26px rgba(0,0,0,0.55); opacity: 0; pointer-events: none; transition: opacity 0.12s ease; }
.tooltip.on { opacity: 1; }
.infodot { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px;
  margin-left: 6px; border-radius: 50%; font-size: 10px; font-weight: 700; cursor: help; vertical-align: middle;
  color: var(--faint); background: var(--surface-2); border: 1px solid var(--border-lt); }
.infodot:hover { color: var(--green); border-color: var(--green); }

/* Topbar Help button */
.help-btn { width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--border-lt);
  background: var(--surface-2); color: var(--muted); font-weight: 700; font-size: 13px; cursor: pointer; line-height: 1; }
.help-btn:hover { color: var(--green); border-color: var(--green); }

/* In-app Help modal */
.help-row { display: grid; grid-template-columns: 170px 1fr; gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--border); }
.help-row:last-of-type { border-bottom: none; }
.help-screen { font-weight: 650; font-size: 13.5px; color: var(--text); }
.help-body { font-size: 13px; color: var(--muted); line-height: 1.5; }
.help-tip { margin-top: 16px; font-size: 12px; color: var(--green); background: var(--green-bg); border-radius: 8px; padding: 10px 12px; }
.help-foot { margin-top: 10px; font-size: 11px; color: var(--faint); }

.muted { color: var(--muted); }
.faint { color: var(--faint); }
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mt-24 { margin-top: 24px; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 16px; }

/* Utility classes — replace inline style="" attributes so CSP can stay
   style-src 'self' (no unsafe-inline, no unsafe-hashes). */
.btn--block   { width: 100%; justify-content: center; }
.mb-0         { margin-bottom: 0 !important; }
.mb-6         { margin-bottom: 6px; }
.mb-12        { margin-bottom: 12px; }
.mb-14        { margin-bottom: 14px; }
.text-left    { text-align: left; }
.text-strong  { color: var(--text); }
.stat-label   { font-size: 12px; }
.screen-sub   { margin: -6px 0 14px; }
.pw-hint      { margin: -6px 0 12px; }

/* Anchoring settings — dropzones, cert-pane summaries, env-lock banner */
.cert-pane           { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.cert-pane--disabled { opacity: 0.45; pointer-events: none; }
.dropzone            { border: 2px dashed var(--border-lt); border-radius: 8px; padding: 14px; text-align: center; color: var(--muted); margin: 8px 0; cursor: pointer; }
.dropzone--active    { border-color: var(--green); color: var(--text); }
.env-lock-banner     { display: block; margin: 12px 0; text-align: left; }
.settings-actions    { display: flex; gap: 12px; margin-top: 20px; flex-wrap: wrap; }
.settings-actions .btn { min-width: 140px; }
.cert-summary        { margin-top: 8px; font-size: 12px; }
.cert-error          { margin-top: 6px; font-size: 12px; }
.test-result         { margin-top: 12px; font-size: 13px; }
.test-result--ok     { color: var(--green); }
.test-result--fail   { color: var(--red); }
.save-flash          { margin-top: 12px; font-size: 13px; }
.save-flash--ok      { color: var(--green); }

/* Sources screen */
.stat-pill.stat-ok    { color: var(--green); }
.stat-pill.stat-warn  { color: var(--amber); }
.stat-pill.stat-crit  { color: var(--red); }
.stat-pill.stat-muted { color: var(--muted); }
.src-group           { margin-top: 18px; }
.src-group-header    { font-size: 13px; color: var(--muted); text-transform: uppercase;
                       letter-spacing: 0.06em; margin: 12px 0 6px; }
.src-group-count     { margin-left: 6px; font-size: 12px; }
.src-table td, .src-table th { padding: 8px 10px; }
.src-table code      { font-size: 12px; }
.src-table .btn--sm  { margin-right: 6px; }
.users-table .btn--sm { margin-right: 6px; white-space: nowrap; }
.unregistered-list   { list-style: none; padding: 0; margin: 8px 0 0; }
.unregistered-row    { padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.unregistered-row .btn { float: right; }
/* Identity evidence on an unregistered row (F-37 S3) — hostname reads as the
   most prominent thing on the row, per the design's own order of
   prominence; everything else here is additive, no existing rule touched. */
.unreg-hostnames      { font-size: 15px; font-weight: 650; color: var(--text); margin-bottom: 2px; }
.unreg-hostnames--none { font-size: 13px; font-weight: 500; font-style: italic; color: var(--muted); }
.unregistered-row .unreg-more { float: none; margin-left: 4px; padding: 1px 8px; font-size: 11px; }
.unreg-cap-note       { font-size: 11px; margin-top: 2px; }
.unreg-meta           { margin-top: 2px; }
.unreg-meta code      { font-family: var(--mono); font-size: 12px; }
.unreg-sample         { margin-top: 4px; font-family: var(--mono); font-size: 12px; white-space: pre-wrap; word-break: break-all; }
.modal-error         { color: var(--red); font-size: 13px; margin-top: 6px; }
/* Add-source wizard extras */
.modal--sm { width: 460px; }
.field { display: block; }
.field .input, .field textarea.input, .field select.input { width: 100%; box-sizing: border-box; }
.field textarea.input { min-height: 84px; resize: vertical; font-family: var(--ui); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.method-note { margin: 0; padding: 10px 14px; background: var(--surface-2);
               border: 1px solid var(--border); border-radius: var(--radius-sm);
               font-size: 13px; }

/* ============ Dashboard ============ */
.dash-hero { display: block; margin-bottom: 16px; }
/* R-011 finding 1 — one banner above the hero tiles when the poll behind
   them is failing, rather than dimming the tiles themselves (design
   question 2: dimming a green tile to grey while stale reads as "this
   got worse," a second false claim layered on the real one). Left-accent
   convention, same as .ev-prov-anchor-status--stale / .srcbar .sb-fill.stale
   elsewhere in this file — colour lives on the accent, not the text. */
#dash-stale-banner:empty { display: none; }
.dash-stale-banner { font-size: 13px; line-height: 1.5; margin-bottom: 12px;
                      padding: 8px 12px; border-left: 3px solid var(--faint);
                      background: var(--surface-2); border-radius: var(--radius-sm); }
.dash-stale-banner--warn  { border-left-color: var(--amber); }
.dash-stale-banner--alert { border-left-color: var(--red); }
#dash-hero-body { display: grid; grid-template-columns: 200px 1fr; gap: 24px; align-items: center; }
.dash-gauge-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.dash-gauge { display: block; }
.dash-gauge-label { font-size: 13px; color: var(--text); text-align: center; font-weight: 600; }
.dash-gauge-sub { display: block; font-size: 11px; margin-top: 2px; max-width: 200px; line-height: 1.4; }
.dash-gauge-text.metric-value--good  { fill: var(--green); }
.dash-gauge-text.metric-value--warn  { fill: var(--amber); }
.dash-gauge-text.metric-value--alert { fill: var(--red); }
.dash-gauge-text.metric-value--muted { fill: var(--muted); }

.dash-hero-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.dash-tile { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
             padding: 12px 14px; }
.dash-tile--alert { border-color: rgba(242,109,109,0.35); background: rgba(242,109,109,0.06); }
.dash-tile-value { font-size: 22px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.dash-tile-unit  { font-size: 12px; color: var(--muted); margin-left: 3px; font-weight: 500; }
.dash-tile-label { font-size: 12px; color: var(--muted); margin-top: 4px; }
.metric-value--good  { color: var(--green); }
.metric-value--warn  { color: var(--amber); }
.metric-value--alert { color: var(--red); }
.metric-value--muted { color: var(--muted); }

/* Chart */
.dash-chart { margin-bottom: 16px; }
.dash-chart-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.dash-window-picker { width: auto; padding: 6px 10px; font-size: 12px; }
.dash-chart-body { min-height: 240px; position: relative; }
/* Hover crosshair, tooltip, and data-point dot. Ported from the mockup's
   areaChart(); percentages match the SVG viewBox so the overlays track
   the responsive width of the chart. */
.dash-chart-cross {
  position: absolute; width: 1px; pointer-events: none;
  border-left: 1px dashed var(--faint, rgba(255,255,255,0.35));
  opacity: 0; transition: opacity .08s ease;
  transform: translateX(-0.5px);
}
.dash-chart-dot {
  position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: var(--green);
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 2px rgba(15,20,28,.9), 0 2px 6px rgba(0,0,0,.4);
  opacity: 0; pointer-events: none; transition: opacity .08s ease;
}
.dash-chart-tip {
  position: absolute; pointer-events: none;
  transform: translate(-50%, calc(-100% - 14px));
  background: var(--card-2, #12161f);
  color: var(--text, #e5e7eb);
  border: 1px solid var(--border-lt, #2d3140);
  border-radius: 6px;
  padding: 6px 10px;
  font: 500 12px/1.35 var(--ui, system-ui);
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(0,0,0,.5);
  opacity: 0; transition: opacity .08s ease;
  z-index: 3;
  display: inline-flex; gap: 8px; align-items: baseline;
}
.dash-chart-tip.dash-chart-tip--flip {
  transform: translate(calc(-100% - 12px), calc(-100% - 14px));
}
.dash-chart-tip .tip-ts   { color: var(--muted, #94a3b8); font-family: var(--mono, monospace); font-size: 11px; }
.dash-chart-tip .tip-v    { font-family: var(--mono, monospace); font-weight: 700; font-size: 14px; color: var(--text, #e5e7eb); }
.dash-chart-tip .tip-unit { color: var(--muted, #94a3b8); font-size: 11px; }
.dash-chart-tip .tip-note { color: var(--red); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; margin-left: 4px; }
/* LOAD-BEARING for T-1 (R-2a, timestamp-display-contract.md): this fixed
   height is what bounds the distance between the chart's shared zone
   marker (.dash-chart-head, dashboard.js) and every tick it governs, so
   no tick can ever render more than 240px below its marker. If this
   becomes flexible or is removed, the chart's ticks need a per-value
   marker again — see R-2a. */
.dash-chart-svg { width: 100%; height: 240px; }
.dash-chart-svg .chart-grid line { stroke: var(--border); stroke-width: 1; }
.dash-chart-svg .chart-axis text { fill: var(--muted); font-size: 11px; font-family: var(--ui); }
.dash-chart-empty { padding: 60px 20px; text-align: center; }
.dash-chart-caption { font-size: 12px; margin-top: 6px; }

/* R-025 — chart-local LIVE/WAITING/CONNECTION LOST indicator (Tomás's
   UX-B, r-025-triage-tomas.md), only shown when "Auto every 5s" is
   selected. Reuses the existing badge colour vocabulary (--green/--amber/
   --red — the same variables HEALTH_BADGE_CLASS's badge--ok/warn/alert
   already key off) rather than inventing a new colour token (C8). The
   pulsing dot itself reuses .live-dot's existing @keyframes pulse rather
   than defining a second animation. */
.dash-live-indicator { display: inline-flex; align-items: center; gap: 6px; margin-left: 2px; font-size: 11.5px; font-weight: 650; letter-spacing: 0.02em; }
.dash-live-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; }
.dash-live-dot--live    { background: var(--green); box-shadow: 0 0 0 0 rgba(61,220,132,0.6); animation: pulse 2s infinite; }
.dash-live-dot--waiting { background: var(--amber); }
.dash-live-dot--lost    { background: var(--red); }
.dash-live-state--live    { color: var(--green); }
.dash-live-state--waiting { color: var(--amber); }
.dash-live-state--lost    { color: var(--red); }

/* R-025 — newest-bucket muted-on-lost (Tomás's UX-B). The overlay rect is
   always present in the chart's SVG (dashboard.js renderChart) at
   opacity:0; renderLiveIndicator() toggles the mount's modifier class,
   never re-renders the chart itself — the already-drawn history stays at
   full opacity, only this one rightmost cell dims. */
.dash-chart-newest-cell { opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.dash-chart-mount--lost .dash-chart-newest-cell { opacity: 0.45; }

/* Lower two-column */
.dash-lower { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.dash-lower-sub { font-size: 12px; margin-bottom: 12px; }

.dash-recent-row { display: grid; grid-template-columns: 60px 100px 90px 1fr auto;
                   gap: 10px; align-items: center; padding: 8px 0;
                   border-bottom: 1px solid var(--border); font-size: 13px; }
.dash-recent-row:last-child { border-bottom: none; }
.dash-recent-time { color: var(--muted); font-variant-numeric: tabular-nums; }
.dash-recent-id { font-size: 11px; color: var(--faint); }
.dash-recent-events { font-size: 12px; }
.dash-recent-tx { font-size: 12px; color: var(--green); text-decoration: none; }
.dash-recent-tx:hover { text-decoration: underline; }
.dash-recent-tx-muted { font-size: 12px; }
.dash-recent-empty { padding: 20px; text-align: center; }

.dash-src-total { font-size: 12px; color: var(--muted); margin-bottom: 10px; }
.dash-src-bars { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.dash-src-row { display: grid; grid-template-columns: 80px 1fr 40px; align-items: center; gap: 10px; }
.dash-src-label { font-size: 12px; color: var(--muted); }
.dash-src-track { display: block; }
.dash-src-count { text-align: right; font-variant-numeric: tabular-nums; font-size: 13px; }
.dash-src-hint { font-size: 11px; }
.dash-src-empty { padding: 20px; text-align: center; }
.dash-src-link  { display: inline-block; margin-top: 6px; }

/* Dashboard chart — source picker + legend */
.dash-chart-controls { display: flex; gap: 10px; align-items: center; }
.dash-chart-legend { display: flex; gap: 16px; align-items: center; font-size: 12px;
                     margin: 0 0 6px 2px; flex-wrap: wrap; }
.dash-legend-item  { display: inline-flex; align-items: center; gap: 6px; color: var(--text); }
.dash-legend-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; }
.dash-legend-swatch--green { background: var(--green); opacity: 0.7; }
.dash-legend-swatch--red   { background: var(--red);   opacity: 0.7; }
.dash-legend-hint  { font-size: 11px; }
.chart-annot { font-size: 11px; font-family: var(--ui); font-weight: 600; }

/* Dashboard — system services strip */
.dash-services { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
                 gap: 12px; margin-top: 10px; }
/* R-011 finding 3 — /api/dashboard/services can fail while ingestion/
   audit-worker (separate calls) keep succeeding, so this note can render
   alongside their tiles in the same grid rather than replacing it. Spans
   the full row so it doesn't look like a fourth data tile. */
.dash-services-stale { grid-column: 1 / -1; font-size: 12px; line-height: 1.5;
                        padding: 8px 10px; border-left: 3px solid var(--amber);
                        background: var(--surface-2); border-radius: var(--radius-sm); }
.svc-tile { border: 1px solid var(--border); border-radius: 8px;
            padding: 12px 14px; background: var(--bg-2); }
.svc-tile-head { display: flex; justify-content: space-between; align-items: center;
                 gap: 8px; margin-bottom: 6px; }
.svc-tile-name { font-weight: 600; font-size: 13.5px; }
.svc-tile-url  { font-size: 11.5px; color: var(--muted); word-break: break-all; }
.svc-tile-url code { font-size: 11px; }
/* F-217 — operator, 2026-08-10: "the error message of self audit worker
   got overflow from its own card". A real error (e.g. a raw S3 XML fault
   body, 300+ chars, frequently one long run with few break points) must
   stay inside the tile's box rather than pushing past its border. Clamp
   to a few lines and let the box scroll for the rest — the honest DEGRADED
   verdict and the full error text are both still shown, just contained.
   overflow-wrap/word-break keep an unbroken run (a URL, a hash) from
   forcing the tile wider than its grid column. */
.svc-tile-reason { font-size: 12px; margin-top: 6px; line-height: 1.45;
                    max-height: 4.35em; overflow-y: auto; overflow-wrap: anywhere;
                    word-break: break-word; white-space: pre-wrap; padding-right: 2px; }
.svc-tile-foot { font-size: 11px; margin-top: 8px; }
.svc-tile--sealed      { border-color: var(--red); }
.svc-tile--unreachable { border-color: var(--red); }
.svc-tile--degraded    { border-color: var(--yellow, #a37c11); }
.svc-tile--unknown     { border-color: var(--yellow, #a37c11); }

/* Evidence screen */
.evidence-sub { display: block; font-size: 12.5px; margin-top: 6px; font-weight: 400; max-width: 90ch; }
/* R-011: a third auto column for the #ev-q-help tooltip that spells out
   the exact search semantics (prefix-match hostname, full-address IP —
   see the comment in evidence.js) the narrow placeholder can't fit.
   R-001a Sequence A-1: a fourth auto column for the "? examples" button
   (#ev-ex-btn). position: relative so #ev-ex-panel (position: absolute,
   .ex-panel rule below) anchors to this row, not to .card above it. */
.evidence-qbar { position: relative; display: grid; grid-template-columns: 1fr auto auto auto; gap: 10px; margin: 16px 0 12px; align-items: center; }
/* R-001c: a fifth column (Host) joins Source ahead of the two <select>s
   and the Export button — both list-shaped filters get the flexible 1fr
   track, same as Source had alone, since both grow/shrink with content
   the same way (mockup screens.js:319-323: fSource and fHost sit side by
   side, same treatment). */
.evidence-filters { display: grid; grid-template-columns: 1fr 1fr 200px 200px 140px; gap: 12px; margin-bottom: 14px; align-items: end; }
.ev-filter { display: flex; flex-direction: column; gap: 4px; }
.ev-filter--pad { justify-content: flex-end; }
.ev-flabel { font-size: 12px; color: var(--muted); }

/* R-001b/R-001c: selected-value chips under any createMultiSelect() widget
   — Source AND Host, on the page AND in the export dialog (four instances
   total share this one style; the .ms/.ms-trigger/.ms-panel/.ms-opt/
   .ex-panel/.ex-item rules below already existed in this file, ported from
   the mockup for the MITRE filter's multiSelect and the examples popover,
   unused by any live control until R-001b). Named generically (.ev-ms-*,
   not .ev-source-*) because R-001c reuses the identical style for Host —
   renamed from R-001b's .ev-source-chip(s) rather than duplicating an
   identical block under a second name. */
.ev-ms-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.ev-ms-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  background: var(--surface-2); border: 1px solid var(--border-lt); border-radius: 999px;
  padding: 3px 6px 3px 10px; color: var(--text); }
.ev-ms-chip button { background: none; border: none; color: var(--faint); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 2px 4px; border-radius: 50%; }
.ev-ms-chip button:hover { color: var(--text); background: var(--surface-3); }
.ev-ms-chip button:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }
/* The mockup's own .ms is display: inline-block (its filter row is flex,
   sized by content). Both places this build uses it (.ev-filter and
   .exp-field, the evidence-page filter row and the export dialog) are
   block-level columns that expect their control to fill the column width
   like the <select> elements beside it — block + width:100% here avoids
   the undefined "percentage width on a shrink-to-fit parent" case .input's
   own width:100% would otherwise hit inside an inline-block .ms. */
.ev-filter .ms, .exp-field .ms { display: block; width: 100%; }
.ev-filter .ms-trigger, .exp-field .ms-trigger { width: 100%; }

/* Absolute date/time filter (plan-tz-preference.md §5.5, step 7b) — a
   second row below the existing filter grid so the two datetime-local
   boxes get enough width, plus the zone label (T-4 obligation B) that
   must sit ADJACENT to them, not in a tooltip. */
.ev-daterange { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-bottom: 12px; }
.ev-daterange .ev-filter { width: 220px; }
.ev-tz-label { font-size: 12.5px; padding-bottom: 9px; }
.ev-daterange-err { flex-basis: 100%; margin-top: 0; }

/* F-282: the Source filter's own inline failure hint — same base look as
   #ev-daterange-err (.form-error), sized down and tightened to sit
   directly under a filter control rather than spanning a row. */
.ev-source-err { font-size: 11.5px; margin-top: 4px; }

/* F-282: the non-interactive "no sources configured" row inside an
   otherwise-empty Source filter panel. Same .ms-opt padding/sizing so it
   lines up with real options, but muted and not clickable — cursor:
   default (not pointer) and no hover background is what tells a sighted
   user it isn't a choice; aria-disabled (set in JS) carries the same to
   assistive tech. */
.ms-opt--hint { color: var(--muted); cursor: default; font-size: 12.5px; line-height: 1.4; }
.ms-opt--hint:hover { background: none; }
.ev-daterange-note { flex-basis: 100%; font-size: 12.5px; margin-top: 0; }
.ev-range-summary { font-size: 12.5px; margin: -4px 0 10px; }
.ev-busy-note { font-size: 12.5px; margin: -4px 0 10px; }
.ev-help { display: inline-flex; align-items: center; justify-content: center;
           width: 15px; height: 15px; border-radius: 50%; border: 1px solid var(--border-lt);
           color: var(--muted); font-size: 10px; font-weight: 700; cursor: help; margin-left: 4px;
           position: relative; }
.ev-help:hover { color: var(--text); border-color: var(--faint); }
/* Custom tooltip driven by data-tooltip (replaces browser-native `title`,
   which was unreliable — small yellow box, easy to miss, sometimes empty).
   Anchored at the icon's left so the tooltip extends RIGHT rather than
   centered. Prevents left-edge clipping when the icon sits near the left
   of a modal (e.g. Payload ? in the record modal). Icons on the far right
   still may need JS clamping, but every ev-help in this build is left-of-
   center in its container, so left-anchoring is universally safe. */
.ev-help[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 8px);    /* Below the icon — never clipped by a
                                scroll container's top edge (sticky
                                table headers routinely sit at top:0). */
  bottom: auto;
  left: 0;
  right: auto;
  transform: none;
  background: var(--card-2, #1a1e28);
  color: var(--text, #e5e7eb);
  border: 1px solid var(--border-lt, #2d3140);
  padding: 8px 12px;
  border-radius: 6px;
  white-space: normal;
  width: max-content;
  max-width: 320px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  z-index: 100;
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  pointer-events: none;
}
/* Roadmap-feature banner on inactive pages (e.g. Collectors). */
.callout--roadmap {
  border-left: 3px solid var(--amber, #f5a524);
  background: rgba(245,165,36,0.08);
  padding: 12px 16px;
  border-radius: 4px;
  margin: 12px 0 16px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text, #e5e7eb);
}
.callout--roadmap strong { color: var(--amber, #f5a524); display: block; margin-bottom: 4px; }
.callout--roadmap code { background: rgba(255,255,255,0.06); padding: 1px 5px; border-radius: 2px; font-size: 12px; }

.ev-help[data-tooltip]:hover::before {
  content: "";
  position: absolute;
  top: calc(100% + 2px);     /* Below-anchored to match the tooltip */
  bottom: auto;
  left: 4px;
  transform: none;
  border: 4px solid transparent;
  border-bottom-color: var(--border-lt, #2d3140);
  z-index: 100;
  pointer-events: none;
}

/* ---- JSON tree viewer for the Evidence record modal payload ---- */
.ev-payload-toggle { margin-left: 10px; display: inline-flex; gap: 4px; }
.ev-payload-tab {
  font: 500 11px/1 var(--sans, system-ui);
  padding: 4px 10px; border-radius: 3px;
  background: transparent; color: var(--muted, #94a3b8);
  border: 1px solid var(--border-lt, #2d3140);
  cursor: pointer; letter-spacing: .02em;
}
.ev-payload-tab.is-active {
  background: var(--accent, #10b981); color: #0a0d12;
  border-color: var(--accent, #10b981);
}
.ev-payload-tab:hover:not(.is-active) { color: var(--text, #e5e7eb); }
.ev-payload-tree {
  font-family: var(--mono, ui-monospace, Menlo, monospace);
  font-size: 12.5px; line-height: 1.55;
  background: var(--card, #0f141c);
  border: 1px solid var(--border-lt, #2d3140);
  border-radius: 6px;
  padding: 12px 16px; margin: 8px 0 12px;
  max-height: 480px; overflow: auto;
}
.jt-root, .jt-children { list-style: none; margin: 0; padding: 0; }
.jt-children { padding-left: 18px; border-left: 1px solid rgba(148,163,184,.15); margin-left: 4px; }
.jt-row { padding: 1px 0; display: block; }
.jt-key { color: var(--accent, #10b981); font-weight: 500; }
.jt-colon { color: var(--muted, #94a3b8); margin-right: 6px; }
.jt-val { color: var(--text, #e5e7eb); }
.jt-str { color: #e0d7a8; word-break: break-word; }
.jt-num { color: #93c5fd; }
.jt-bool { color: #f472b6; }
.jt-null { color: var(--muted, #94a3b8); font-style: italic; }
.jt-brace, .jt-empty, .jt-count { color: var(--muted, #94a3b8); }
.jt-count { margin: 0 6px; font-size: 11px; }
.jt-twist {
  display: inline-block; width: 14px; text-align: center;
  color: var(--muted, #94a3b8); cursor: pointer;
  transition: transform .12s ease;
  user-select: none;
}
.jt-twist:hover { color: var(--text, #e5e7eb); }
.jt-collapsed > .jt-twist { transform: rotate(-90deg); }
.jt-collapsed > .jt-children,
.jt-collapsed > .jt-count { display: none; }
.jt-collapsed > .jt-brace:first-of-type ~ .jt-brace {
  /* Show ... between the braces when collapsed */
}
.jt-collapsed > .jt-brace:first-of-type::after {
  content: " … ";
  color: var(--muted, #94a3b8);
}
/* R-029 — embedded-JSON display (Wazuh-over-syslog: the canonical bytes
   are the full wire line, envelope + JSON object together; the envelope
   itself is shown as plain text bracketing the tree, never dropped —
   the DISPLAY is reorganised, the preserved bytes are not). */
.jt-embedded-prefix, .jt-embedded-suffix {
  font-family: var(--mono, ui-monospace, Menlo, monospace);
  font-size: 12.5px; white-space: pre-wrap; word-break: break-word;
}
.jt-embedded-prefix { margin-bottom: 4px; }
.jt-embedded-suffix { margin-top: 4px; }
/* Honest fallback label (R-029 Rule 7 requirement) shown above the plain-
   text render for a payload with no JSON substring anywhere in it. */
.jt-fallback-note { font-size: 12px; margin-bottom: 6px; }
.evidence-table-wrap { overflow: auto; max-height: calc(100vh - 340px); min-height: 260px; }
/* Sticky header — was setting background to undefined --card, which fell
   back to transparent and let tbody rows show through when scrolling.
   Use the real defined var and give it a bottom rule so the visual
   separation is unambiguous. */
.evidence-table-wrap thead th {
  position: sticky; top: 0; z-index: 10;
  background: var(--surface, #0f141d);
  box-shadow: inset 0 -1px 0 var(--border, #2d3140);
}
/* Same fix for any other sticky headers that used the undefined var. */
.evidence-table-wrap thead tr { background: var(--surface, #0f141d); }
.ev-loading { text-align: center; padding: 24px; }
.ev-ts, .ev-evid, .ev-size { font-variant-numeric: tabular-nums; }
.ev-ts   { font-family: var(--mono); font-size: 12.5px; white-space: nowrap; }
.ev-evid { font-size: 12px; white-space: nowrap; }
.ev-size { font-size: 12.5px; text-align: right; white-space: nowrap; }
/* F-294: the Content search column was removed and its warning now
   renders inline after the description text, in this same cell (see
   renderRows in evidence.js). The cell itself no longer clips as a
   whole — only the description text truncates (.ev-desc-text below);
   the chip that can follow it must stay fully visible, never squeezed
   into the ellipsis along with the text it's warning about. */
.ev-desc { font-size: 12.5px; max-width: 420px; white-space: nowrap; }
.ev-desc-text { display: inline-block; max-width: 340px; overflow: hidden;
           text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
/* F-283: min-width (not just max-width) so a short name like "wazuh" doesn't
   leave the column collapsing to fit it — every row in a column should
   line up at a consistent width. 180px comfortably fits the ~20-character
   names already seen in this deployment (e.g. "wazuh_linux_hackgrid",
   21 chars) at this font-size/family without ellipsizing; longer names
   still ellipsize and carry the full value in `title` (see renderRows). */
.ev-logname { font-size: 12.5px; min-width: 150px; max-width: 220px; overflow: hidden;
              text-overflow: ellipsis; white-space: nowrap; }
/* S-1 disclosure line above the results table — always rendered as real
   text (never a tooltip) so it is visible without hovering, clicking or
   expanding anything (D0). */
.ev-search-scope { font-size: 12.5px; margin: -6px 0 14px; min-height: 1em; }
/* S-4/F-221: the same line carries the archive-wide backfill state
   (search-reach-plan-2026-08-09.md §8: "S-1's sentence must carry the
   backfill's own state"). Colour alone never carries the information —
   the text itself always states the counts in words — this is purely a
   visual cue that there IS a backlog worth reading closely. */
.ev-search-scope--backlog { color: var(--amber); }
/* S-1-incomplete / F-294 — the per-record content-search-coverage warning.
   Used to be its own column (.ev-search-state, removed by F-294 — the
   column stayed empty on the vast majority of rows); now renders inline
   after the description text in .ev-desc, on affected rows only. Reuses
   .badge/.badge--warn/.badge--muted so it reads consistently with the
   Integrity column rather than inventing a second visual language for
   "state of a thing". margin-left separates it from the text it follows
   without relying on the badge's own (already-used) internal padding. */
.ev-search-badge { font-size: 10.5px; padding: 1px 7px; margin-left: 6px; vertical-align: middle; }
/* F-240: Integrity is the LAST column, so its ev-help "?" icon sits
   flush against the right edge of .evidence-table-wrap (overflow:auto —
   see below). The icon's tooltip (.ev-help[data-tooltip]::after) is
   absolutely-positioned and anchors left of the icon, extending right —
   with the column squeezed to its content's natural width there was no
   room between the icon and the wrap's clip boundary, so the tooltip
   got cut off before its text finished. Explicit min-width gives that
   buffer without needing table-layout:fixed on the whole table. */
.ev-integrity-col { min-width: 190px; white-space: nowrap; }
/* F-240 FOLLOW-UP (2026-08-11) — the min-width buffer above did not fix
   the clipping. Confirmed live against v0.320 (which already carries the
   min-width change): the Integrity column header's "?" sits at the very
   right edge of the VIEWPORT itself, not just of the scrollable wrap —
   widening the column pushes MORE content to the icon's left, not more
   room to its right. The base .ev-help[data-tooltip]:hover::after rule
   (above) anchors `left:0`, growing the tooltip RIGHTWARD from the icon,
   which is exactly backwards for the one icon on this page that sits at
   the right edge — its own header comment already named this residual
   risk ("Icons on the far right still may need JS clamping"). Rather
   than add JS, flip anchor direction for this one icon only: grow
   LEFTWARD instead, which the table has ample width for regardless of
   viewport size. Scoped to `.ev-integrity-col` so every other ev-help on
   this page (all left-of-center, per the base rule's own comment) is
   unaffected. */
.ev-integrity-col .ev-help[data-tooltip]:hover::after {
  left: auto;
  right: 0;
}
.ev-integrity-col .ev-help[data-tooltip]:hover::before {
  left: auto;
  right: 4px;
}

/* F-291: plain-English tooltips explaining what HEALTHY / STALE / OFFLINE /
   NO DATA mean on the Sources page — per-row badge and the summary-line
   counts. Reuses the .ev-help[data-tooltip] content/box mechanics above but
   the tooltip text lives directly on the badge/pill itself (data-tooltip),
   not on a separate "?" icon, since the badge word IS the thing needing
   explanation here (adding a second icon per row would be a layout change,
   which F-291 is explicitly scoped to avoid). `cursor: help` + a dotted
   underline signal that hovering (or, for keyboard/screen-reader users,
   focusing — see :focus-visible below and the aria-label set in JS) reveals
   more. Right-anchored (`right: 0`) rather than the base rule's left-anchor:
   both the Health column (second-to-last, right of center in the sources
   table) and the summary pills (right end of a flex row) sit close enough
   to the page's right edge that growing the tooltip rightward risks running
   off-screen — same clipping class as F-240's Integrity column above, fixed
   the same way. */
.src-health-badge,
.src-status-pill {
  cursor: help;
  position: relative;
}
/* Badges already carry a full coloured border (see .badge above), so a
   second dotted underline would just muddy that shape — only the plain-text
   summary pills (no border of their own) get the dotted-underline hover
   affordance. Scope kept separate deliberately: this must NOT touch
   .badge's own border/colour rules (F-291 is copy-only, no layout/colour
   change to the badges). */
.src-status-pill {
  border-bottom: 1px dotted currentColor;
}
.src-health-badge[data-tooltip]:hover::after,
.src-health-badge[data-tooltip]:focus-visible::after,
.src-status-pill[data-tooltip]:hover::after,
.src-status-pill[data-tooltip]:focus-visible::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 8px);
  bottom: auto;
  left: auto;
  right: 0;
  background: var(--card-2, #1a1e28);
  color: var(--text, #e5e7eb);
  border: 1px solid var(--border-lt, #2d3140);
  padding: 8px 12px;
  border-radius: 6px;
  white-space: normal;
  width: max-content;
  max-width: 280px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  text-transform: none;
  letter-spacing: normal;
  z-index: 100;
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  pointer-events: none;
}
.src-health-badge[data-tooltip]:hover::before,
.src-health-badge[data-tooltip]:focus-visible::before,
.src-status-pill[data-tooltip]:hover::before,
.src-status-pill[data-tooltip]:focus-visible::before {
  content: "";
  position: absolute;
  top: calc(100% + 2px);
  bottom: auto;
  left: auto;
  right: 4px;
  border: 4px solid transparent;
  border-bottom-color: var(--border-lt, #2d3140);
  z-index: 100;
  pointer-events: none;
}
.src-health-badge:focus-visible,
.src-status-pill:focus-visible {
  outline: 2px solid var(--accent, #10b981);
  outline-offset: 2px;
}
.ev-mitre { font-size: 11.5px; white-space: nowrap; }
.mitre-chip { display: inline-block; padding: 1px 6px; margin-right: 3px;
              border: 1px solid var(--border); border-radius: 10px;
              background: var(--bg-2); color: var(--text);
              font-family: var(--mono); font-size: 11px;
              text-decoration: none; }
.mitre-chip:hover { border-color: var(--accent); color: var(--accent); }
.mitre-more { display: inline-block; padding: 1px 6px;
              border: 1px dashed var(--border); border-radius: 10px;
              color: var(--muted); font-size: 11px; cursor: help; }

.ev-pager { display: flex; justify-content: space-between; align-items: center;
            gap: 12px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.pager-left { display: flex; align-items: center; gap: 16px; color: var(--muted); font-size: 12.5px; }
.pager-rpp { display: flex; align-items: center; gap: 6px; }
.pager-size { width: auto; padding: 4px 8px; font-size: 12px; }
.pager-ctl { display: flex; align-items: center; gap: 6px; }
.pager-pg  { color: var(--muted); font-size: 12.5px; margin: 0 4px; }

/* Log detail modal */
.ev-modal { width: 900px; max-width: 100%; }
.ev-modal-body { max-height: 75vh; overflow-y: auto; }
/* F-292 — maximize toggle. `position: fixed` + `inset` takes the modal out
   of .modal-backdrop's flex flow entirely, so it sizes against the
   viewport rather than the backdrop's own padding/align-items:flex-start
   (which only sizes a child to its content, not the available space) —
   no need to also touch .modal-backdrop. flex-direction:column lets the
   head stay at its natural (small) height while the body is told to grow
   into whatever height remains; min-height:0 on the body is required for
   its overflow-y:auto to actually kick in inside a flex column (a flex
   item's default min-height is auto, which would let it push the modal
   taller than the viewport instead of scrolling internally). */
.ev-modal--maximized {
  position: fixed;
  inset: 4%;
  width: auto;
  max-width: none;
  height: auto;
  max-height: none;
  display: flex;
  flex-direction: column;
}
.ev-modal--maximized .modal-body,
.ev-modal--maximized .ev-modal-body {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}
.ev-prov { background: var(--surface-2); border: 1px solid var(--border);
           border-radius: var(--radius-sm); padding: 14px 16px; margin-bottom: 16px; }
.ev-prov--ok    { border-color: rgba(61,220,132,0.35); }
.ev-prov--alert { border-color: rgba(242,109,109,0.35); background: rgba(242,109,109,0.06); }
.ev-prov-head   { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.ev-prov-sealed { font-size: 12px; }
.ev-prov-copy   { font-size: 13px; line-height: 1.5; margin-bottom: 10px; }
/* A′: the "leaf N of M" line — the single sentence that explains why a
   multi-leaf batch's own merkle_root differs from the on-chain value
   shown below it. A left-accent callout (same convention as
   .ev-recover-note), neutral --faint since this is explanatory, not a
   warning — set apart from .ev-prov-copy's plain prose so it reads as
   the answer to that question, not another line of the same paragraph. */
.ev-prov-leaf   { font-size: 13px; line-height: 1.5; margin-bottom: 10px;
                  padding: 6px 10px; border-left: 3px solid var(--faint); }
/* F-139 — the anchor-status callout, separate from .ev-prov-copy (the
   self-audit sentence, always true) because the two claims are
   independent and must not read as one paragraph. --pending and --stale
   are deliberately NOT --alert: neither state is known to be an error,
   only an honest "still checking" vs "no longer checking" — color is a
   secondary cue here, the wording carries the distinction on its own. */
.ev-prov-anchor-status { font-size: 13px; line-height: 1.5; margin-bottom: 10px;
                          padding: 6px 10px; border-left: 3px solid var(--faint); }
.ev-prov-anchor-status--stale { border-left-color: var(--amber); }
/* F-204 (Access log anchor detail) — a genuine failure, distinct from
   --pending/--stale's "still honest, not an error" amber/faint. */
.ev-prov-anchor-status--alert { border-left-color: var(--red); }
.ev-prov-explorer { margin-top: 10px; font-size: 12.5px; }
.ev-payload { max-height: 340px; overflow-y: auto; }
.ev-detail-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
/* F-140 — the verification-bundle download control's confirmation line.
   Placed in .ev-detail-actions with Copy/Recover (one actions row for the
   whole modal, rather than a second place to look for a button) and kept
   right below that row so it stays adjacent to whichever action produced
   it — same convention as .ev-recover-note just below. */
.ev-bundle-status { margin-top: 8px; font-size: 12.5px; text-align: right; min-height: 1em; }
.ev-bundle-status--ok { color: var(--green); }

/* Export modal */
/* R-009: the scope panel is a set of live controls now, not read-only
   kv rows — stacked with breathing room between them so four selects/
   inputs in a --sm modal don't crowd together. */
.ev-exp-scope { background: var(--surface-2); border: 1px solid var(--border);
                border-radius: var(--radius-sm); padding: 12px 14px;
                display: flex; flex-direction: column; gap: 10px; }
.ev-exp-formats { display: flex; flex-direction: column; gap: 8px; }
.ev-exp-fmt { display: flex; gap: 10px; align-items: flex-start;
              padding: 10px 12px; border: 1px solid var(--border-lt);
              border-radius: var(--radius-sm); cursor: pointer; background: var(--surface-2); }
.ev-exp-fmt:hover { border-color: var(--faint); }
.ev-exp-fmt input[type="radio"] { margin-top: 3px; }
.ev-exp-fmt b { display: block; font-size: 13px; margin-bottom: 3px; }
.ev-exp-fmt .muted { font-size: 12px; }
.ev-exp-note { font-size: 12px; margin-top: 12px; padding: 10px 12px;
               background: var(--surface-2); border-radius: var(--radius-sm); }
/* F-151 — the Download button's own confirmation line, same convention as
   .ev-bundle-status (F-140) just above: left-aligned here since the export
   modal's body is a full-width column, not a compact detail-panel row. */
.ev-exp-status { margin-top: 8px; font-size: 12.5px; min-height: 1em; }
.ev-exp-status--ok { color: var(--green); }
/* F-151 follow-up: a truncated export succeeded but is incomplete — not
   the same thing as the .form-error path below, which is a real failure.
   Callout-styled (background + border, same convention as .silence-callout)
   rather than just recoloured text, so a partial download reads as
   distinctly not-plain-success rather than as a slightly different color. */
.ev-exp-status--warn { color: var(--text); background: var(--amber-bg);
                        border: 1px solid rgba(245,181,68,0.35);
                        border-radius: var(--radius-sm); padding: 10px 12px; }
.ev-exp-status--warn strong { color: var(--amber); }
/* S-6b — the bytes/elapsed ticker, deliberately a separate element from
   .ev-exp-status: that one is aria-live="assertive" and must only change
   at request-start and at the final outcome; this one ticks every second
   and stays aria-live="off" so a screen reader isn't forced to re-announce
   a growing byte count once a second. */
.ev-exp-progress { margin-top: 4px; font-size: 12px; font-family: var(--mono); min-height: 1em; }

/* R-009 follow-up: the live "N records · ~K KB" summary — the answer to
   "would this scope download anything at all". Bolder than .ev-exp-note
   since it's the headline the operator asked for, not a footnote. */
.ev-exp-count { font-size: 13px; font-weight: 600; margin-top: 10px;
                padding: 8px 12px; border-radius: var(--radius-sm);
                background: var(--surface-2); border: 1px solid var(--border-lt); }
.ev-exp-count.form-error { font-weight: 400; }
/* the "current search filter applied" callout under the Search box */
.ev-exp-qnote { font-size: 12px; margin: 4px 0 0; }
