/* ── Tokens (light green theme) ─────────────────────────────
   Neutral chrome carries a soft green tint instead of gray/off-white:
   page background a light green, cards a paler green-white for
   contrast against it, borders a step darker green-gray. The brand
   accent (interactive elements) stays blue on purpose, same as the
   prior gray theme - the accent that signals "this is clickable"
   isn't part of the background palette swap. */
:root {
  /* Cold, Gemini-like palette: cool gray page, white surfaces, a
     real Google-blue accent, superseding the earlier warm Claude-
     style cream/terracotta pass per explicit request ("make the
     colors more cold"). --bg darkened a step further per a later
     follow-up ("make the theme a bit darker background"); --surface
     stays white so cards/the sidebar read as a lighter layer on top
     of it, not a flat single-tone dark mode (a genuine dark theme
     would need its own, much larger pass: many specialized views
     still assume a light background directly, e.g. hardcoded
     #0f172a-on-white text and white card backgrounds, not routed
     through these variables). Semantic colors below (--cve/--risk
     and every view-scoped status color) are untouched on purpose,
     per this block's own comment: those carry meaning and stay
     recognizable regardless of which brand accent is in effect. */
  --bg: #cfd5dc;
  --surface: #ffffff;
  /* Genuinely transparent, no tint at all, per explicit repeated
     request ("no extra background color", "keep it transparent") --
     an earlier semi-opaque rgba(255,255,255,.5) still read as its
     own visible box, not actually transparent. --surface stays solid
     white for real chrome that overlays scrolling content (the
     sidebar, modals, dropdowns), where a see-through background
     would show whatever's scrolling underneath and hurt legibility.
     --view-card is for content-level "card" backgrounds within a
     view (feed groups, a CVE row, the Account profile card) that
     don't have that problem: transparent lets the page's own --bg
     show through completely, so these read as part of the page, not
     a floating box on top of it. The border/left-border-color on
     each of these elements is what still marks them as a distinct
     region/carries any meaningful color, not the fill. */
  --view-card: transparent;
  --text: #1a1c1e;
  --muted: #5f6368;
  --border: #dadce0;
  --chip-bg: #e8eaed;
  --chip-text: #3c4043;
  --brand: #1a73e8;
  --brand-light: #e8f0fe;
  --focus: #1a73e8;

  /* Two accents carry meaning; everything else is neutral ink on neutral
     surface — meaning comes from labels and layout, not colour.
       cve  = danger / security — act now
       risk = warning / behind — needs attention
     Interactive elements read as interactive through weight, underline,
     and a slate active-state — not a third hue. */
  --cve: #b91c1c;
  --cve-bg: #fdf2f2;
  --risk: #92400e;
  --risk-bg: #fbf6ee;
  /* "new", "llm", "hv" have no colour of their own — aliases onto neutral
     ink / surface so existing rules still resolve. */
  --new: #475569;
  --new-bg: #f1f5f9;
  --llm: #475569;
  --llm-bg: #f1f5f9;
  --hv: #475569;
  --hv-bg: #f1f5f9;

  --mono: ui-monospace, 'SF Mono', SFMono-Regular, 'Cascadia Mono', 'Segoe UI Mono', Menlo, Consolas, monospace;

  /* Flat by default — this UI separates with hairlines, not elevation. */
  --shadow-sm: 0 0 0 1px rgba(15,23,42,.02);
  --shadow-md: 0 2px 8px rgba(15,23,42,.08);
  --radius: 3px;
  --radius-sm: 2px;
  --radius-full: 999px;
  --topbar-h: 0px;
}

/* ── Reset ──────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; }
/* The Ask home and How it works views scroll the page itself, vertically only
   (syncHomeClass sets .page-scroll on <html>); other views keep their own panels. */
html.page-scroll { height: auto; min-height: 100%; overflow-y: auto; overflow-x: hidden; }
html.page-scroll body { height: auto; overflow: visible; }
body {
  background: var(--bg);
  color: var(--text);
  font: 13px/1.45 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}
/* A default for the many plain, unstyled <a> tags scattered through
   this file (e.g. the guardrails panel's dynamically-rendered "Sign
   in to change these") that would otherwise fall back to the
   browser's own default link blue rather than this exact palette's
   own brand blue. Lowest possible specificity (a bare element
   selector), so every already-styled link (#docsView a,
   .ua-topbar-chip, etc.) keeps overriding it exactly as before; this
   only fills in the ones nothing else claims. */
a { color: var(--brand); }
a:hover { color: #1558b0; }
/* Numbers, versions, dates and identifiers read as data, not prose. */
.mono, .datecol, .kpi em, .toggle .count,
code, kbd, samp { font-family: var(--mono); font-variant-numeric: tabular-nums; }
img { display: block; }

/* ── Skip link ──────────────────────────────────────────── */
.skip-link {
  position: absolute; top: -100%; left: 8px;
  padding: 8px 16px; background: var(--brand); color: #fff;
  border-radius: 0 0 var(--radius) var(--radius);
  font-weight: 700; text-decoration: none; z-index: 9999;
}
.skip-link:focus { top: 0; }

/* ── Topbar ─────────────────────────────────────────────── */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: box-shadow .2s;
}
.topbar.scrolled { box-shadow: var(--shadow-md); }

.topbar-main {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 14px;
}

.brand {
  font-size: 15px; font-weight: 800; white-space: nowrap;
  flex-shrink: 0; text-decoration: none; color: var(--text);
}
.brand em { color: var(--brand); font-style: normal; }
/* Just the version number once .brand relocates into #sidebarFooter
   (see relocateSidebarFooter's own comment in the script), per
   explicit request: no need to also spell out "Releasetrain" next
   to the app's own nav column. Still says the full name in the
   topbar on a narrow screen, where .brand never moves. */
#sidebarFooter .brand .brand-name { display: none; }

/* Line 1's right-aligned cluster (account chip + Search/Ask mode
   toggle), pushed to the row's far edge via margin-left:auto on
   this wrapper, so brand/title stays flush left with everything
   else flush right, no matter how wide the viewport is. */
.topbar-right {
  display: flex; align-items: center; gap: 8px;
  margin-left: auto; flex-shrink: 0;
}

/* Nav — now lives inside the sidebar drawer (see below) as a vertical
   list of views, rather than an inline row in the topbar. */
.nav-links {
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px; border-bottom: 1px solid var(--border);
}
.nav-link {
  display: flex; align-items: center; gap: 7px; padding: 8px 10px;
  border-radius: var(--radius); color: var(--text);
  font: 600 13px/1 inherit; text-decoration: none;
  transition: background .15s, color .15s;
}
.nav-link:hover { background: var(--chip-bg); }
.nav-link:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
/* #filtersToggleBtn (see its own markup comment): a real <button>,
   not an <a>, since it toggles a panel rather than navigating: reset
   to plain button chrome so it reads identically to its <a> siblings.
   `font: inherit` (the bare keyword as the WHOLE value - the only valid
   way to use it here) is what actually matters: .nav-link's own
   `font: 600 13px/1 inherit` above is invalid CSS (inherit can't be
   embedded as one component inside the font shorthand) and the browser
   silently drops that entire declaration, so every <a>.nav-link's
   13px/system-ui look was never really coming from that rule at all -
   it's pure ambient inheritance from the page's own default font, which
   an <a> picks up automatically but a <button> does not (browsers give
   buttons their own default control font instead, ~13.3333px Arial-ish
   here). A bare `font-family: inherit` alone only fixed the family, not
   the size, which is why this still measured 13.3333px vs the anchors'
   13px (confirmed via getComputedStyle, not eyeballed) even after that
   first attempt - `font: inherit` pulls the whole ambient value at
   once, matching the anchors' actual rendered look exactly rather than
   guessing at individual sub-properties. */
button.nav-link { background: none; border: none; width: 100%; text-align: left; cursor: pointer; font: inherit; }

/* Hamburger — the single control that opens the whole menu drawer
   (views + search/filters), at every screen width. */
.nav-toggle {
  display: flex; align-items: center; justify-content: center;
  padding: 7px 9px;
  background: none; border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer; color: var(--text); font-size: 16px; line-height: 1; flex-shrink: 0;
}
.nav-toggle:hover { background: var(--chip-bg); }

/* ── Nav loader ─────────────────────────────────────────── */
#navLoader {
  position: fixed; top: var(--topbar-h); left: 0; right: 0;
  height: 2px; background: transparent; overflow: hidden; z-index: 999; display: none;
}
#navLoader.active { display: block; }
#navLoader::after {
  content: ""; display: block; width: 40%; height: 100%;
  background: var(--text);
  animation: slide 1s linear infinite;
}
@keyframes slide { from { margin-left: -40%; } to { margin-left: 100%; } }

/* ── Layout ─────────────────────────────────────────────── */
/* Everything (views + search/filters) now lives in the off-canvas
   .sidebar drawer below, so the visible layout is a single column:
   just the feed (or whichever view is active) at full width. */
.layout {
  max-width: 1100px;
  margin: 0 auto;
  padding: calc(var(--topbar-h) + 12px) 8px 28px;
}
@media (max-width: 640px) {
  html, body { overflow-y: auto; overflow-x: hidden; height: auto; }
  .layout { padding: calc(var(--topbar-h) + 12px) 8px 32px; }
}

/* ── Inline answer rail / Ask intro panel ─────────────────────
   The right column is always there on a screen with room for it
   (see the min-width below, kept in sync with ASK_RAIL_MIN_WIDTH
   in the script), not only once a real answer exists. It shows
   #askIntroPanel (what Ask does, with sample questions) until a
   real question is asked, then swaps to #askAnswerRail. Below the
   breakpoint, or in Compare mode, the popup modal is used instead
   for a real answer, and the intro panel doesn't show at all (no
   spare width to give it).
   .ask-rail-col wraps #askOptionsPanel's landing spot (see
   relocateAskOptionsPanel in the script) plus both of the asides
   below: it, not the individual asides, is the actual flex/sticky
   column now, so the moved options panel scrolls and sticks
   together with whichever of intro/answer is currently showing
   instead of being positioned separately. */
.ask-rail-col { display: none; }
.ask-answer-rail, .ask-intro-panel { display: none; }
@media (min-width: 900px) {
  /* No max-width (was 1700px): with the persistent #sidebar now
     providing the page's own left/right split, every view uses the
     full width available to the right of it instead of centering
     in a capped column on top of that, per explicit request.
     body.view-home's own rule below already did this specially for
     the Ask home; this makes it the general case. */
  .layout { display: flex; align-items: flex-start; gap: 20px; max-width: none; }
  /* No rail, feed-main at full width, by default now: the 40/60
     split below only actually matters on body.view-home (its own
     rule further down re-enables display:block here), where an
     inline answer next to the prompt is the whole point. Every
     other view (Docs, Graph, CVE, Dashboard, Account, the eval
     tools, etc.) used to fall through to this same rule
     unconditionally, squeezing its own real content into a 2/5-
     width column beside an .ask-rail-col with nothing relevant in
     it. Caught after #askOptionsPanel and #askForm both moved out
     of it (see relocateAskOptionsPanel/relocateAskForm), making the
     wasted space impossible to miss; body.view-feed already had its
     own near-identical override for the same reason (a real
     question's answer uses the modal there instead, per
     canUseAskRail's own comment), just never generalized. Ratios via
     flex-grow with a 0 basis, not literal width:40%/60%, so the
     split (once re-enabled) stays proportional. */
  .layout > .feed-main { flex: 1 1 0; min-width: 0; }
  .layout .ask-rail-col {
    display: none;
    flex: 3 1 0; min-width: 0;
    position: sticky;
    top: calc(var(--topbar-h) + 12px);
    max-height: calc(100vh - var(--topbar-h) - 24px);
    overflow-y: auto;
    /* overflow-y:auto alone silently promotes overflow-x to auto too
       (same gotcha already fixed on every other scrolling view this
       session), so any unwrapped token in a generated answer could
       put a horizontal scrollbar on this rail and clip its own text
       at the edge. Pinned to hidden; the actual wrapping fixes below
       (.ask-answer-summary, its code spans) are what keep real
       content from needing it in the first place. */
    overflow-x: hidden;
  }
  .layout .ask-intro-panel { display: block; }
  .layout.has-ask-rail .ask-intro-panel { display: none; }
  .layout.has-ask-rail .ask-answer-rail { display: block; }
}
/* The close button, and #askOptionsPanel once relocateAskOptionsPanel
   lands it here on a wide screen (see that function's own comment).
   #askOptionsPanel itself can still wrap to several lines (its own
   flex-wrap); the close button is pinned to the top-right corner via
   position:absolute rather than sitting in the flex flow, so it
   stays put in that corner regardless of how many lines the panel
   wraps to, instead of dropping to the bottom once the panel grows
   taller than one line. padding-right on this row reserves room so
   the panel's own text never renders underneath the button. The
   question itself lives inside the card now, not here (see
   .ask-answer-heading/.ask-answer-question). */
.ask-rail-header { position: relative; margin-bottom: 10px; }
/* Ask-first home (desktop only). With no ?view= and no ?q=, body gets .view-home
   (see syncHomeClass in the script) and the two-column feed + rail layout collapses
   to one centered column: the prompt, the answer, and a short strip of the latest
   updates. The feed itself moves to ?view=feed ("Recent updates" in the menu).
   Below 900px nothing changes: the feed stays the home page and answers use the modal. */
@media (min-width: 900px) {
  body.view-home .feed-main { display: none; }
  body.view-home .layout { max-width: none; padding-left: 16px; padding-right: 16px; }
  body.view-home .layout .ask-rail-col { display: block; position: static; max-height: none; overflow: visible; flex: 1 1 0; }
  body.view-home #filtersToggleBtn { display: none; }
  body.view-home .ask-rail-header { display: none; }
  body.view-home .ask-home-samples { display: grid; grid-template-columns: repeat(2, 1fr); }
  body.view-home .ask-intro-panel { font-size: 13.5px; }
  body.view-home .ask-intro-panel h3 { font-size: 20px; }
}
/* ?view=feed (and a bare ?q= link): just the feed, nothing from Ask beside it. */
body.view-feed .layout .ask-rail-col { display: none !important; }
body.view-feed .layout > .feed-main { flex: 1 1 0; }
/* The answer in the rail has no outline or inner padding, and the tab bar no longer
   bleeds past the card's padding (it was cancelling the 14px this removes). */
#askRailBody .ask-answer-card { border: none; background: transparent; padding: 0; }
#askRailBody .ask-rail-tabs { margin: 0 0 10px; padding: 0; }
.ask-short-answer { font-size: 18px; line-height: 1.4; font-weight: 600; margin: 8px 0 6px; }
.ask-home-controls { display: none; }
.ask-home-controls > h4 { font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); margin: 0 0 8px; }
.ask-home-samples { list-style: none; margin: 10px 0 14px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.ask-home-latest { margin: 16px 0; }
.ask-home-latest ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.ask-home-latest li { display: flex; gap: 10px; align-items: baseline; padding: 5px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.ask-home-latest li strong { font-weight: 700; }
.ask-home-latest li .m { color: var(--muted); }
/* Plain, technical copy. No marketing language, no imagery beyond
   a small heading. .ask-sample-btn reuses the feed's own muted
   chip-like styling so the samples read as inline, clickable
   example text rather than a separate call-to-action. */
/* Tighter than the panel's own prior spacing on purpose: "Try
   asking" grew from 4 to 7 examples (one per intent plus the poll
   showcase), which pushed the whole panel's content past typical
   viewport height and forced a vertical scroll that wasn't there
   before, confirmed live. Every margin/padding/gap below is
   trimmed accordingly, not just for this panel's own sake. */
.ask-intro-panel { font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.ask-intro-panel a { color: var(--brand); text-decoration: underline; }
.ask-intro-panel h3 { font-size: 13px; color: var(--text); margin: 0 0 6px; }
.ask-intro-panel p { margin: 0 0 7px; }
.ask-intro-panel h4 { font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); margin: 10px 0 5px; }
.ask-intro-panel ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }
/* The one sign-in entry point, in the topbar's top-right corner (see
   #topSignInLink's own comment) rather than a call-to-action in the
   middle of the page, per explicit request. A filled pill so it
   still reads as the primary action next to the plain #ua-topbar-chip
   it swaps places with once signed in. */
.top-signin-btn {
  font: 700 12px inherit; background: var(--brand); color: #fff; border: none;
  border-radius: var(--radius-full); padding: 6px 14px; cursor: pointer; flex-shrink: 0;
}
.top-signin-btn:hover { background: #1558b0; }
/* #authStatusDot: see its own markup comment. Green while signed in;
   a small muted, low-contrast dot while signed out, deliberately not
   an alarming color (red/orange) since "not signed in" is this app's
   normal, expected default state, not an error. */
.auth-dot { flex-shrink: 0; }
/* Set/updated by uaUpdateAskIntroSignin() below, from GET
   /api/ask/anon-quota; hidden whenever anonymous questions are off
   (limit 0) or the visitor is signed in. Inherits .ask-intro-panel's
   own var(--muted) color, just needs its own spacing. */
.ask-anon-quota-note { display: block; text-align: center; margin-top: 6px; font-size: 11px; }
/* Its own tab bar, not a reuse of .ask-rail-tabs: that class's
   margin: -2px -14px 10px is a deliberate bleed-to-the-edge trick
   that cancels out .ask-answer-card's own 14px padding (see its own
   comment), which .ask-intro-panel never had to begin with -
   reusing it as-is would push the bar 14px past this panel's real
   content edges. .ask-rail-tab/.ask-rail-panel (the individual tab
   button and panel, no padding-cancelling assumption baked in) are
   still reused directly for a matching look. flex-wrap: six labels
   in this panel's own narrow-sidebar width wrap to two rows rather
   than overflow or force a horizontal scrollbar. */
.ask-intro-tabs { display: flex; flex-wrap: wrap; gap: 2px; margin: 8px 0 10px; border-bottom: 1px solid var(--border); }
.ask-sample-btn {
  display: block; width: 100%; text-align: left; font: inherit; font-size: 11.5px; line-height: 1.35;
  background: var(--chip-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  color: var(--text); padding: 5px 8px; cursor: pointer;
}
.ask-sample-btn:hover { border-color: var(--brand); }
/* Small font on purpose (this panel is a narrow sidebar column,
   never allowed to scroll sideways): four columns of real technical
   content (a plain type label, the literal internal intent tag, the
   process name, a clickable example) need every character kept, so
   the font shrinks rather than the content. table-layout:fixed plus
   overflow-wrap lets a long value like "comparison-question" wrap
   to a second line within its own cell instead of forcing a wider
   table or a horizontal scrollbar. */
.ask-intro-table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 9.5px; }
.ask-intro-table th, .ask-intro-table td {
  padding: 3px 4px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border); overflow-wrap: break-word;
}
.ask-intro-table th { font-size: 8.5px; text-transform: uppercase; letter-spacing: .2px; color: var(--muted); font-weight: 700; }
.ask-intro-table th:nth-child(1), .ask-intro-table td:nth-child(1) { width: 24%; }
.ask-intro-table th:nth-child(2), .ask-intro-table td:nth-child(2) { width: 12%; }
.ask-intro-table th:nth-child(3), .ask-intro-table td:nth-child(3) { width: 20%; }
.ask-intro-table th:nth-child(4), .ask-intro-table td:nth-child(4) { width: 22%; }
.ask-intro-table th:nth-child(5), .ask-intro-table td:nth-child(5) { width: 22%; }
.ask-intro-table .ask-sample-btn {
  display: inline; width: auto; background: transparent; border: none; padding: 0;
  color: var(--brand); text-decoration: underline; font: inherit; font-size: 9.5px; line-height: 1.3;
}
.ask-intro-table .ask-sample-btn:hover { color: var(--text); }
/* Full paper citations, once, below the table rather than repeated
   in every "Research type" cell (see the table's own comment): a
   superscript number in the cell is enough to point back here. */

/* ── Sidebar (menu drawer) ──────────────────────────────────
   Off-canvas at every width, not just mobile — this is the single
   "everything else" panel behind the ☰ toggle: views on top, then
   search/filters/stats. Slides in from the left over the feed. */
.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: min(300px, 86vw);
  background: var(--surface);
  border-right: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  overflow-x: hidden;
  overflow-y: auto;
  min-width: 0;
  /* Not var(--topbar-h): the drawer's own z-index (1300) already sits
     above the topbar (1000), so it covers rather than needs to clear
     it - the old full-topbar-height padding just pushed "Home" down
     by however tall the topbar happened to be (more when Ask mode's
     extra checkbox row was showing), for no visual reason. */
  padding-top: 10px;
  transform: translateX(-100%);
  transition: transform .22s ease;
  z-index: 1300;
}
.sidebar.open { transform: translateX(0); }
/* Filters panel: the same .sidebar shape/mechanics, mirrored to the
   right edge instead of the left, so it reads as a distinct, second
   drawer rather than a variant of the ☰ menu (which stays
   left-anchored). Same z-index/overlay/transition as .sidebar;
   only the anchor side and its own open-state transform differ. */
.filters-panel {
  left: auto; right: 0;
  border-right: none; border-left: 1px solid var(--border);
  transform: translateX(100%);
}
.filters-panel.open { transform: translateX(0); }

#sidebarOverlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, .45);
  z-index: 1250;
}
#sidebarOverlay.open { display: block; }

/* Splits the whole page left/right on a screen with room for it,
   per explicit request: the ☰ drawer (#sidebar specifically, by id
   -- #filtersPanel shares the base .sidebar class for its styling
   but is a separate, unrelated drawer on the opposite edge and
   must keep its own normal toggle behavior, not be forced open by
   this rule too) becomes a persistent column instead of an overlay
   that covers the page while open, and everything else (topbar,
   including the question input row, and .layout below it) shifts
   right to sit beside it rather than under it. Same 900px
   breakpoint as ASK_RAIL_MIN_WIDTH above and the .layout flex-row
   rule below, since both are "wide enough for this app's real
   desktop layout," not a separate threshold. The sidebar's own
   content (nav, filters, stats, about, account, eval links) is
   unchanged, just always visible now instead of toggled;
   #navToggle has nothing left to do at this width so it hides, and
   #sidebarOverlay would otherwise still darken the page if
   something toggled .open on it (including the unrelated
   #filtersPanel, which shares that same overlay), even though
   #sidebar itself no longer moves. */
@media (min-width: 900px) {
  /* display:flex so #sidebarFooter's own margin-top:auto (below) can
     push it to the true bottom edge even when the rest of the
     sidebar's content is shorter than the viewport. Position:sticky
     alone (the footer's other rule) only kicks in once there's
     something to scroll past, so a short sidebar left it sitting
     right under the nav instead of at the visual bottom. Scoped to
     #sidebar by id, not the shared .sidebar class, so #filtersPanel
     (which also uses .sidebar) keeps its normal block layout. */
  #sidebar { transform: none !important; box-shadow: none; display: flex; flex-direction: column; }
  #sidebarOverlay { display: none !important; }
  #navToggle { display: none; }
  /* Nothing of the topbar's own content is left in it at this width
     (relocateAskForm moves #askForm into #askFormDesktopSlot,
     relocateSidebarFooter moves .brand/#filtersToggleBtn/
     .topbar-right into #sidebarFooter, both in the script), so the
     topbar itself is hidden entirely, per explicit request: the
     right side is just the question input, and the version number
     and sign-in live at the bottom of the sidebar instead. */
  .topbar { display: none; }
  body { padding-left: var(--sidebar-w, 300px); }
}

.sidebar-section { padding: 8px; }
.sidebar-section:last-child { padding-bottom: 12px; }
/* Landing spot for .brand/#filtersToggleBtn/.topbar-right on a wide
   screen (see relocateSidebarFooter's own comment in the script).
   Sticky to the bottom of #sidebar's own scroll area, not the whole
   page: #sidebar is itself the nearest scrolling ancestor
   (overflow-y:auto), so position:sticky works here with no need to
   also wrap the sidebar's other, unrelated content in a flex column
   just to pin this one. Empty and hidden on a narrow screen, where
   all three stay in the topbar exactly as before. */
.sidebar-footer { display: none; }
@media (min-width: 900px) {
  /* Row, split left/right: .brand (the version) on the left,
     .topbar-right (sign-in/account) on the right, per explicit
     request. #filtersToggleBtn (only shown outside the Ask home)
     sits between them when present. A prior version stacked these
     in a column (version above sign-in) per an earlier request to
     put sign-in at the actual bottom; superseded by this one. */
  .sidebar-footer {
    display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 8px;
    position: sticky; bottom: 0; margin-top: auto;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding: 8px;
  }
  /* Small and muted here specifically, not the bold brand-colored
     look .brand normally has (still true in the topbar on a narrow
     screen, where it never relocates) -- a footer detail, not a
     heading, per explicit request ("make the version more subtle"). */
  .sidebar-footer .brand { font-size: 11px; font-weight: 400; color: var(--muted); }
  .sidebar-footer .brand em { color: var(--muted); }
  /* Was margin-left:auto to push itself to the far right of a column
     layout; inert now that .sidebar-footer's own justify-content
     already pushes this to the row's right edge, so it's cleared
     explicitly rather than left as unused dead weight. */
  .sidebar-footer .topbar-right { margin-left: 0; }
  /* Smaller and outlined, not a big solid-fill pill, per explicit
     request ("make the sign in button less dominant"); this is
     footer chrome sitting next to a plain muted version number, not
     a call-to-action competing for attention the way the topbar's
     own sign-in entry point (line ~340's .top-signin-btn, shown only
     on a narrow screen where this footer doesn't exist) still is. */
  .sidebar-footer .top-signin-btn {
    background: none; color: var(--brand); border: 1px solid var(--border);
    font-size: 11px; font-weight: 600; padding: 4px 10px;
  }
  .sidebar-footer .top-signin-btn:hover { background: var(--chip-bg); color: var(--brand); }
}

/* Collapsible sidebar blocks */
.sb-details { border-top: 1px solid var(--border); }
/* No filled background: per explicit request, just the label and the
   border-top divider ("edges") between entries, not a boxed chip. The
   global `summary { background: var(--chip-bg) }` rule below would
   otherwise fill each summary's own container edge to edge, which
   looked inconsistent between "Menu" (no padded wrapper, spans the
   full sidebar width) and "Model & pipeline"/"Advanced checks" (inset
   8px inside #askOptionsPanel's own padding); removing the
   background entirely sidesteps that mismatch rather than trying to
   match the inset instead. */
.sb-details > summary { background: none; }
.sb-details > summary {
  /* flex-direction: row spelled out explicitly, same reason as
     .ua-admin-header: the global `summary { flex-direction: column }`
     rule below wins on any property this rule doesn't itself
     redeclare, stacking the chevron and label into two centered
     lines instead of one row. */
  list-style: none; display: flex; flex-direction: row; align-items: center; gap: 5px;
  /* Vertical padding trimmed (was 8px top/bottom) per explicit
     request: with 4 of these stacked in the sidebar (Menu, Model &
     pipeline, Advanced checks, Guardrails) and Guardrails alone now
     listing 15 checks, the collapsed headers' own padding was
     eating into the room needed to see that list without scrolling. */
  padding: 4px 12px; cursor: pointer; user-select: none;
  font: 700 9px/1 var(--mono); color: var(--muted);
  text-transform: uppercase; letter-spacing: .5px;
}
.sb-details > summary::-webkit-details-marker { display: none; }
.sb-details > summary::before {
  content: '›'; font-size: 13px; line-height: 1;
  display: inline-block; transition: transform .15s;
}
.sb-details[open] > summary::before { transform: rotate(90deg); }
.sb-details > summary:hover { color: var(--text); background: rgba(255,255,255,.04); }

/* .demo-q-btn: sized to the sidebar's own column (min(300px, 86vw),
   see .sidebar), never a fixed width of its own -- width:100% plus
   box-sizing:border-box so its padding/border stay inside whatever
   that column actually is, including the 86vw fallback on a
   narrower screen. white-space:normal (not nowrap) since several
   of these questions run longer than the column is wide; they wrap
   to 2-3 lines rather than overflowing or getting cut off. */
/* Capped and internally scrollable so 8 real questions (2-3 lines each)
   don't push the rest of the sidebar (Menu, Model & pipeline, ...) below
   the fold and force the whole sidebar to scroll - only this list does,
   same hidden-scrollbar treatment as this file's other internally-
   scrolling views (see the shared #evalRewriterView-and-friends rule). */
.demo-q-list {
  display: flex; flex-direction: column; gap: 6px; padding: 4px 12px 10px;
  max-height: 260px; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: none;
}
.demo-q-list::-webkit-scrollbar { display: none; }
.demo-q-row { display: flex; align-items: stretch; gap: 6px; }
.demo-q-btn {
  flex: 1 1 auto; min-width: 0; box-sizing: border-box; text-align: left; white-space: normal;
  font: 400 12px/1.35 inherit; color: var(--text);
  background: var(--chip-bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 7px 9px; cursor: pointer;
}
.demo-q-btn:hover { background: rgba(255,255,255,.06); border-color: var(--brand); }
.demo-q-btn:active { transform: translateY(1px); }
/* Small, muted open-on-Reddit icon beside its question button - its own
   sibling element, not nested inside the button (invalid HTML). */
.demo-q-link {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 26px; font-size: 12px; text-decoration: none;
  background: var(--chip-bg); border: 1px solid var(--border); border-radius: 6px;
  opacity: .7;
}
.demo-q-link:hover { opacity: 1; border-color: var(--brand); }
/* .demo-q-meta: the question's own classified intent + real agent
   count, so a presenter (or anyone reading this list) can see the
   full spread of intents before clicking, not just discover it from
   the answer badge afterward. "1 agent (fixed path)" on the
   comparison button specifically calls out that a comparison
   question always bypasses the single/multi-agent choice entirely
   (see runComparisonAsk) -- labeling it plain "multi-agent" here
   would repeat the exact confusion a live tester hit picking the
   multi-agent preset on a comparison question and still seeing
   "1 AGENT" in the answer badge. */
.demo-q-meta {
  display: block; margin-top: 4px; font: 700 9px/1.3 inherit;
  color: var(--muted); text-transform: uppercase; letter-spacing: .4px;
}

.sidebar-label {
  font: 700 9px/1 inherit; color: var(--muted);
  text-transform: uppercase; letter-spacing: .6px; margin-bottom: 7px;
}
.sidebar-divider { border: none; border-top: 1px solid var(--border); margin: 0; }

/* ── Search bar ──────────────────────────────────────────────
   One row with everything else in the topbar (brand, hamburger)
   rather than a second line. #askForm just flexes to take whatever
   width is left, and the whole row wraps on narrow screens instead
   of the form wrapping internally against a fixed-width row.
   Search and Ask used to be two separate forms toggled by a mode
   switch; they're now one form (#askForm). A bare vendor/category
   lookup and a real question both go through the same box, and
   /api/ask itself decides which one it is (see the submit handler
   and classifyAskLookup on the server). #filterForm still exists,
   but only as the internal versions-fetch/pagination engine, driven
   programmatically, never shown. */
.topbar-form {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  /* Always its own full-width row below the hamburger/brand line,
     never sharing a flex line with them, since a sibling that wraps
     internally to 2-3 lines can't safely share a row with another
     item in the same flex container (the other item can end up
     overlapping wherever the wrapped content lands). This flex-child
     sizing only matters while #askForm is still inside .topbar-main
     (a narrow screen): once relocateAskForm moves it into
     #askFormDesktopSlot on a wide one, it's a plain block there and
     these two properties are simply inert, not conflicting with
     anything. */
  flex: 1 1 100%; min-width: 0;
}
/* Empty and hidden until relocateAskForm (in the script) moves the
   real #askForm node in here on a wide screen; see that div's own
   comment in the markup. A plain block inside #stickyAskHeader (see
   that element's own CSS comment), which is what's actually pinned
   in place now; this itself just needs its own horizontal centering. */
.ask-form-desktop-slot { display: none; }
@media (min-width: 900px) {
  .ask-form-desktop-slot {
    /* Was max-width:780px, centered - narrower than #askWorkflowTop
       (the diagram right above it, which stretches the full available
       width with no cap - see its own comment) for no real reason once
       the input row grew a second field. Caught live from a screenshot:
       a wide diagram sitting directly above a visibly much-narrower,
       centered input row read as inconsistent, and the whole point of
       giving context more room (a separate fix earlier) is undercut by
       capping the row itself well below the space actually available.
       Matches #askWorkflowTop's own treatment exactly now: same
       padding, no max-width, so both align edge to edge. */
    display: block;
    padding: 8px 24px 0;
  }
  /* #stickyAskHeader (see its own markup comment): position:fixed at
     one constant offset, the SAME on every view including the Ask
     home, per explicit request ("never move this up or down even if
     you load a view"). A prior version used a much larger 22vh top
     padding on the Ask home specifically (a deliberate "landing
     page" look, prompt sitting "1/4 down the page") and a smaller,
     sticky-not-fixed treatment everywhere else, which visibly jumped
     position when switching between the two. Explicit left/right
     (not margin:0 auto alone) since position:fixed takes this out of
     the flow that used to align it with the persistent #sidebar's
     own width; --topbar-h (see updateOffsets in the script) still
     correctly tracks this element's real height either way, so
     .layout/every view's own top offset/height math is unaffected by
     the switch from sticky to fixed. Background is --surface (a light
     card color, white), not --bg (the page's own darker blue-gray) -
     per explicit request ("pick a consistent background for the
     static part at the top... make it a light color"): this whole
     fixed area (diagram + input row together) now reads as one
     consistent light panel sitting above the page, rather than the
     diagram floating on the plain page background while only the
     input row had its own separate gray card (removed - see
     .ask-input-row's own comment). Still opaque either way, so a
     view's own content scrolling up behind this header is actually
     hidden by it, not visible through it. */
  #stickyAskHeader {
    position: fixed; top: 0; left: var(--sidebar-w, 300px); right: 0; z-index: 400;
    /* Light green, per explicit request - reused from #askWorkflowDiagram's
       own "done" node fill (g.askwfg-done rect) right below it, rather than
       inventing an unrelated new green: this way the panel's background
       and the diagram's own completed-step color read as the same family. */
    background: #f0fdf4;
  }
}
/* The vertical scrollbar hidden, per explicit request, while
   scrolling itself (mouse wheel, trackpad, keyboard) stays fully
   functional; only the visible track/thumb is gone. html's own
   page-level scrollbar (see page-scroll's own comment in the
   script) is one target. Each view's own internal scroll container
   (#usersView, #docsView, etc., the actual "view details on the
   right side" this request named, each already position:sticky with
   its own overflow-y:auto, see updateOffsets's own comment above) is
   the other, and is the one most likely actually visible day to day
   now that --topbar-h correctly reflects #stickyAskHeader. #sidebar's
   own, separate internal scrollbar is deliberately left alone: a
   different, narrower scroll area, not "the view details". */
html { scrollbar-width: none; }
html::-webkit-scrollbar { display: none; }
#evalRewriterView, #evalEvaluatorView, #evalOrchestratorView,
#cveView, #dashboardView, #usersView, #feedPanel, #changelogView,
#networkView, #docsView, #ackView, #graphView {
  scrollbar-width: none;
}
#evalRewriterView::-webkit-scrollbar, #evalEvaluatorView::-webkit-scrollbar, #evalOrchestratorView::-webkit-scrollbar,
#cveView::-webkit-scrollbar, #dashboardView::-webkit-scrollbar, #usersView::-webkit-scrollbar, #feedPanel::-webkit-scrollbar, #changelogView::-webkit-scrollbar,
#networkView::-webkit-scrollbar, #docsView::-webkit-scrollbar, #ackView::-webkit-scrollbar, #graphView::-webkit-scrollbar {
  display: none;
}
/* Every control on this row shares one height, so the bar reads as
   one aligned strip instead of inputs/buttons/select sitting at
   slightly different sizes next to each other. */
.topbar-form .search-input,
.topbar-form .btn,
.ask-preset-select {
  height: 32px; box-sizing: border-box;
}
.topbar-form .btn { display: inline-flex; align-items: center; justify-content: center; }
.btn-icon { padding: 0 10px; font-size: 14px; }
/* padding/font trimmed down (was 0 8px / 12px) so three of these fit
   a tighter line before wrapping, per request to reduce line breaks
   in the narrower rail column. */
.ask-preset-select {
  padding: 0 6px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font: 11px/1 inherit; cursor: pointer; flex-shrink: 0;
}
/* Ask form: input, Clear, bookmark, and submit share one row on top
   (.ask-input-row) on every screen size, no gear button or popover
   to click open first. The agentic-AI-specific controls that used to
   live in a second row below it (model/size/pipeline, the three
   toggles, usage) are grouped into #askOptionsPanel inside
   .ask-options-row, which relocateAskOptionsPanel() moves out of
   this row entirely into the top of the answer rail's column on a
   wide screen (leaving .ask-options-row empty, which just collapses
   to nothing); on a narrow one, with no rail to move it to, it stays
   here as this form's own second row. Stacked vertically via
   flex-direction:column, overriding .topbar-form's default row-wrap
   behavior for just this form. */
.ask-form-stacked { flex-direction: column; align-items: stretch; flex-wrap: nowrap; gap: 6px; }
/* Grid, not flex-wrap - see this row's own markup comment for why (a
   flex-wrap version broke visibly at real container widths around
   ~470px: question+context wrapped to uneven widths and Clear/Submit
   ended up vertically centered against their combined two-line height,
   floating in a gap). Named areas place all four pieces predictably at
   every width instead of relying on wrap order + flex-basis arithmetic.
   Narrow/default: question+Clear+Submit share one row, context sits full
   width below. */
.ask-input-row {
  display: grid; gap: 10px; align-items: center;
  /* minmax(0, 1fr), not a bare 1fr: a bare 1fr track still respects its
     content's own min-content width first, so a long unbroken string can
     stop the track (and its sibling) from actually filling 100% of the
     row - minmax(0, ...) lets it shrink freely and genuinely claim all
     available width, matching "both inputs should use the available
     width more automatically" (the .search-input/.ask-context-input
     children are width:100% of whatever their own track ends up, either
     way - this is about the TRACK'S width, not the input's). */
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas:
    "question clear submit"
    "context  context submit2";
  /* No shared gray card here anymore - that was an earlier attempt at
     "integrated," superseded by giving #stickyAskHeader itself (the
     diagram + this row together) one consistent light background
     instead, per explicit follow-up request ("remove the gray around
     the two input boxes"). The two inputs go back to sitting directly
     on that shared panel, same as the diagram above them. */
}
/* "submit2" is a throwaway area name, not a real duplicate of the submit
   button - grid-template-areas requires every cell in the ASCII grid to
   be filled by some name, and the submit button (grid-area: submit) only
   occupies the row-1 cell, leaving row 2's third column with nothing
   assigned unless it's given its own placeholder name here. */
.ask-input-row .search-wrap { grid-area: question; }
.ask-input-row .ask-context-wrap { grid-area: context; }
.ask-input-row #clearBtn { grid-area: clear; }
.ask-input-row #askSubmitBtn { grid-area: submit; }
/* Wide enough (this container is already known to comfortably fit both -
   see .ask-form-desktop-slot's own max-width, which kicks in at this
   same breakpoint) - context joins the question on one row instead of
   sitting full-width below it. */
@media (min-width: 900px) {
  .ask-input-row {
    /* Context gets a bit more of the row than the question, not an even
       split - a typed question is usually short, but context is often a
       full pasted sentence/paragraph. Mild tilt (0.85fr vs 1fr), not a
       stronger one: an earlier 0.7/1 split (paired with a much longer
       placeholder) visibly cramped the question box instead - shortening
       the context placeholder ("Optional context (e.g. paste extra
       details)" -> "Add context (optional)") did more of the actual work
       than the column ratio did. */
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1fr) auto auto;
    grid-template-areas: "question context clear submit";
  }
}
.ask-context-input {
  /* No icon on this field (unlike .search-wrap's question input, whose
     28px left padding makes room for 🔍) - back to a plain left inset. */
  width: 100%; padding-left: 10px; resize: vertical; min-height: 32px;
  font-family: inherit;
  /* !important needed: .search-input's own base rule (below this one in
     the file) sets font:13px/1 ... - same specificity, later in source
     order, so its line-height:1 (13px) was silently winning over this
     rule's line-height:1.3 regardless. line-height:18px, not 1.3: an
     <input> auto-centers its single line of text vertically, but a
     <textarea> does NOT (renders text flush from the top of its content
     box, browser default) - this is the standard fix for a single-line-
     styled textarea, setting line-height to exactly the content box's
     own height (32px box - 7px top/bottom padding = 18px) so its one
     line of text centers the same way the question <input> beside it
     already does natively. Caught live from a screenshot: both
     placeholders read as sitting above center, though only the textarea
     genuinely needed this fix - the question <input> already centers on
     its own. */
  line-height: 18px !important;
  /* No scrollbar once typed text exceeds the visible area - per explicit
     request ("the corner works"): the resize handle already lets anyone
     drag it taller to see everything, so a scrollbar is redundant chrome
     on top of that, not a second way to reach the same content. */
  overflow-y: hidden;
}

/* ── Answer rail tabs (Answer+workflow / Sources) ──────────── */
/* Negative margin matches .ask-answer-card's own 14px padding, so
   the tab strip's border-bottom spans the full card edge to edge
   while the tab buttons themselves still line up with everything
   else in the card. */
.ask-rail-tabs { display: flex; gap: 2px; margin: -2px -14px 10px; padding: 0 14px; border-bottom: 1px solid var(--border); }
.ask-rail-tab {
  background: transparent; border: none; border-bottom: 2px solid transparent;
  padding: 7px 6px; margin-bottom: -1px; font: 700 11.5px inherit;
  color: var(--muted); cursor: pointer;
}
.ask-rail-tab:hover { color: var(--text); }
.ask-rail-tab.active { color: var(--brand); border-bottom-color: var(--brand); }
.ask-rail-panel[hidden] { display: none; }
/* The running phase caption ("Retriever #2: Searching CVE records…
   0.3s") used to be its own line below the input (#askWorkflowCaption,
   now removed). Per explicit request ("add this runtime status right
   to the benchmark, that way it does not take vertical space"), it
   now lives right in the tab row next to "Benchmark" instead -- the
   row is already there and already taking up space regardless of
   whether a question is running, so appending to it costs nothing
   extra vertically. Written by renderAskWorkflowCaption, which looks
   this element up fresh every tick rather than caching a reference,
   since the whole tab row (this span included) gets torn down and
   rebuilt every time showAskRailRunning/askRenderCard re-render the
   card. Empty and invisible once a run finishes (renderAskWorkflowCaption
   clears the text; an empty span takes no visible space on its own). */
.ask-benchmark-live-status {
  margin-left: auto; align-self: center;
  font: 400 10.5px var(--mono); color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 50%;
}
/* margin-left:auto still consumes all leftover flex-row space even
   with no visible content, which on the final answer card (more tabs
   after Benchmark: Model vs Rules, Guardrails, Feedback Loop) shoved
   every later tab to the far right the instant a run finished and
   this went empty -- caught from an actual screenshot. Zeroed out
   whenever empty so those tabs sit in their normal spot right after
   Benchmark unless there's real live status text to push right. */
.ask-benchmark-live-status:empty { margin-left: 0; }

/* ── Agent workflow diagram (Rewriter/Retriever/Evaluator/
   Orchestrator) ────────────────────────────────────────────
   Always the same shape (the real multi-agent-with-feedback
   architecture) regardless of which pipeline preset is running;
   only the node states differ, so a preset with no real role
   delegation (Single-agent) just leaves every node idle instead of
   hiding or reshaping the diagram itself. */
/* Plain text "nouns and edges" per explicit request: no per-node
   box/rect and no backing card of its own either (transparent,
   centered horizontally): just each role's name, colored by its
   own idle/active/done state, joined by a plain arrow character,
   sitting directly on the page. Lives in #askWorkflowTop, one
   persistent instance pinned above the question input itself (not
   inside the per-answer rail card, and not only once a question
   exists), visible in its dim "idle" state from page load, then
   lights up live as a real question runs. */
/* nowrap, not wrap, per explicit request ("no line break in one
   line"): the full 7-node pipeline (Vendor/Rewriter/Web Search/
   Verify/Retriever/Evaluator/Orchestrator) used to wrap "Orchestrator"
   onto its own second line once the row ran out of width. No
   horizontal scrolling either: stretched across #askWorkflowTop's
   own full available width (see that element's own comment, no
   longer capped at 780px like the question input below it) so the
   row has real room for every node without needing to wrap or
   scroll at all. justify-content: space-between, not center, per
   direct follow-up request ("use all width available") now that the
   full 7-node pipeline (see renderAskWorkflowDiagram) always renders
   regardless of whether this particular run escalated to a web
   search or not -- with real content now reliably wide enough to
   want spreading out, `space-between` uses the row's whole width
   rather than clumping every node into the middle with wasted space
   on both sides. Degrades safely the same way `safe center` used to:
   if the full row ever doesn't fit at all, `space-between` packs
   flush left and overflows to the right, same as `flex-start` would,
   rather than clipping the left edge off-screen the way plain
   `center` could. */
.ask-workflow-diagram {
  display: flex; align-items: center; justify-content: center; flex-wrap: nowrap; gap: 6px;
  font: 400 13px/1.3 var(--mono); white-space: nowrap;
  background: none; border: none; padding: 6px 6px;
  /* The agent graph is an SVG that scales down to the column, so this row never
     needs to scroll sideways; anything wider than the column is clipped, not scrolled. */
  overflow-x: hidden;
}
/* Colors re-picked for a transparent background (see .ask-workflow-diagram's
   own comment): the earlier bright neon green/glow only worked
   against a dark card; on the page's own light surface a strong,
   saturated but darker green reads as "active" just as clearly
   without needing a backdrop to glow against. */
/* The graph fills the whole width of the column and stays centered: the renderer
   writes its own inline max-width (the natural pixel width), so that is overridden here.
   The height cap keeps a very wide window from pushing the input down the page. */
#askWorkflowDiagram svg { width: 100% !important; max-width: none !important; height: auto; max-height: 24vh; overflow: visible; }
#askWorkflowDiagram text.askwf-secs { font-size: 11px; fill: var(--muted) !important; font-weight: 400 !important; }
#askWorkflowDiagram g.askwfg-idle rect { fill: #f2f0ff !important; stroke: #8b83d6 !important; }
#askWorkflowDiagram g.askwfg-idle text { fill: #3b3766 !important; }
#askWorkflowDiagram g.askwfg-active rect { fill: #dcfce7 !important; stroke: #15803d !important; }
#askWorkflowDiagram g.askwfg-active text { fill: #14532d !important; font-weight: 700; }
#askWorkflowDiagram g.askwfg-done rect { fill: #f0fdf4 !important; stroke: #16a34a !important; }
#askWorkflowDiagram g.askwfg-done text { fill: #166534 !important; }
#askWorkflowDiagram g.askwfg-input rect { fill: #e5e7eb !important; stroke: #6b7280 !important; }
#askWorkflowDiagram g.askwfg-input text { fill: #374151 !important; }
#askWorkflowDiagram g.askwfg-skipped rect { fill: transparent !important; stroke: #9ca3af !important; stroke-dasharray: 4 3; }
#askWorkflowDiagram g.askwfg-skipped text { fill: #9ca3af !important; }
.ask-console { position: fixed; left: var(--console-left, 0px); right: 0; bottom: 0; z-index: 900; height: 170px; overflow-y: auto; border-radius: 10px 10px 0 0; box-shadow: 0 -6px 16px rgba(0,0,0,.25); background: #0a0a0a; color: #d4d4d4; padding: 10px 14px; font: 12px/1.5 Consolas, ui-monospace, monospace; white-space: pre-wrap; }
body.has-ask-console { padding-bottom: 180px; }
body.has-ask-console.has-ask-console-min { padding-bottom: 40px; }
.ask-console.ask-console-min { height: 32px; overflow: hidden; padding-top: 6px; padding-bottom: 6px; }
/* Keep the floating close button above the bottom run log instead of under it. */
body.has-ask-console .view-close-btn { bottom: 186px; }
body.has-ask-console.has-ask-console-min .view-close-btn { bottom: 48px; }
/* Phone view: only the latest updates. Everything Ask / agentic AI
   (question box, agent graph, run log, demo questions, pipeline
   options, eval pages, credits, changelog) is hidden, and the page
   opens on the Recent updates feed instead of the Ask home. */
@media (max-width: 640px) {
  #askForm, #askWorkflowTop, #askFormDesktopSlot, #demoQuestionsDetails, #askOptionsPanel,
  #askConsoleFixed, .ask-rail-col, #homeLink, #ackLink, #changelogLink,
  #evalRewriterLink, #evalEvaluatorLink, #evalOrchestratorLink, #viewCloseBtn { display: none !important; }
  body.has-ask-console, body.has-ask-console.has-ask-console-min { padding-bottom: 0; }
}
.ask-console-close { position: sticky; top: 0; float: right; background: #262626; color: #d4d4d4; border: 0; border-radius: 4px; cursor: pointer; font-size: 12px; padding: 1px 7px; }
.ask-console .ac-t { color: #7c7c7c; }
.ask-console .ac-note { color: #7dd3fc; }
#askWorkflowDiagram g.askwfg-active { animation: askwfRobotBlink 1.2s ease-in-out infinite; }
/* Robot in front of each node's name (see renderAskWorkflowDiagram),
   per explicit request. Only the robot blinks while its own node is
   "active" -- the node's own name/timer text stays fully static
   (opacity untouched), per direct follow-up ("only blink the robot
   in front, this way the text stays static") -- so the robot is its
   own inner span the blink animation targets, separate from the
   outer .askwf-${state} span that colors the text. Idle/done robots
   have no animation at all, just sit at full opacity in whatever
   color the emoji itself renders in (CSS `color` has no effect on an
   emoji glyph, so there's nothing to re-color here regardless). */
@keyframes askwfRobotBlink { 50% { opacity: 0.15; } }
/* #askWorkflowTop: the one persistent home for the diagram (the
   running-phase caption used to live here, then move to its own
   element below the input; it now lives in the answer card's own
   Benchmark tab row instead -- see .ask-benchmark-live-status's own
   comment), a sibling of #askFormDesktopSlot (right before it
   in the markup) rather than nested inside the rail/tabs, per
   explicit request ("top of the right side, not below the input
   field"). Hidden on a narrow screen, matching #askFormDesktopSlot's
   own breakpoint -- this is specifically the wide two-pane layout's
   "top center of the right side", which doesn't exist as a concept
   below that width. Full width of #stickyAskHeader (not capped/
   centered at 780px like the form below it), left to right, per
   explicit request ("no horizontal scrolling, stretch it along the
   full available width, start from left to right"): the diagram
   needs real room to lay out every node on one line without
   wrapping or scrolling (see .ask-workflow-diagram's own comment),
   which the form's own capped, centered width doesn't give it. Its
   own top padding is a plain small constant, not the form's 22vh;
   it belongs at the true top of the column, not vertically centered
   with the input. */
#askWorkflowTop { display: none; }
@media (min-width: 900px) {
  #askWorkflowTop { display: block; padding: 24px 24px 0; }
}
/* #viewCloseBtn: see its own markup comment. Same "reachable from
   every view" breakpoint as #askWorkflowTop/#askFormDesktopSlot --
   below 900px the topbar itself still shows Home directly, so there's
   nothing extra to close back to. */
.view-close-btn { display: none; }
@media (min-width: 900px) {
  .view-close-btn {
    /* Moved from top-right to bottom-right and enlarged (30px -> 40px),
       per explicit request: at top-right it visibly overlapped the
       pipeline diagram's own right end ("Orchestrator"), caught live
       from a real screenshot. */
    position: fixed; bottom: 16px; right: 16px; z-index: 500;
    width: 40px; height: 40px; border-radius: 50%;
    border: 1px solid var(--border); background: var(--surface); color: var(--muted);
    font-size: 16px; line-height: 1; cursor: pointer;
    box-shadow: var(--shadow-md);
    display: flex; align-items: center; justify-content: center;
  }
  .view-close-btn:hover { background: var(--chip-bg); color: var(--text); }
  .view-close-btn[hidden] { display: none; }
}
.ask-options-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 11px; color: var(--muted);
}
/* Self-contained flex row (not just a plain block) so its own layout
   (selects/toggles/usage wrapping sensibly) works identically in
   both places relocateAskOptionsPanel() can put it: nested one level
   inside .ask-options-row (a narrow screen) or inside
   .ask-rail-header (a wide one, sharing that row with the close
   button). flex:1 1 auto only matters in the first case, letting it
   absorb the row's available width so Clear/bookmark/submit still
   end up flush right, same as before these controls were grouped
   into their own node. Tighter gap (6px, was 10px) so more of the
   row's content fits per line before wrapping, per request to
   reduce line breaks in the narrower rail column. */
.ask-options-panel {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 11px; color: var(--muted);
  flex: 1 1 auto; min-width: 0;
  margin-bottom: 6px;
}
.ask-toggle-inline { display: flex; align-items: center; gap: 4px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }
.ask-toggle-inline input[type="checkbox"] { accent-color: var(--brand); cursor: pointer; }
/* Keeps the three toggles together as one wrapping unit (see the
   markup's own comment): nowrap internally so they never split
   apart from each other, flex-shrink:0 so the group as a whole is
   what wraps to the next line, not one toggle peeling off alone. */
.ask-toggle-group { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; flex-shrink: 0; }
/* Was an inline style on each of the three top-level .sb-details
   groups (Model & pipeline / Advanced checks / Guardrails). Moved
   to a real rule so the #sidebar column-mode override below (higher
   specificity, an id) can actually beat it. An inline style always
   wins over any stylesheet rule regardless of specificity, so the
   override had no effect while this lived as style="..." on the
   elements themselves (caught live: every closed accordion still
   claimed 100% of the column's height and wrapped into a separate
   side-by-side "column" instead of stacking). */
.ask-options-panel > .sb-details { flex: 1 0 100%; margin-top: 2px; }
/* #askOptionsPanel permanently lives in the narrow #sidebar column
   now (relocateAskOptionsPanel, in the script), where the row/wrap
   layout above (built for the wide topbar this used to sit in)
   reads cramped: a ~300px column has no room for selects and
   toggles to share a row. Stacks everything one item per line
   instead, full width, per explicit request. Guardrails' own
   checkbox list (#askGuardrailsBody) already renders as a column
   via its own inline style, so it needs no separate rule here. */
@media (min-width: 900px) {
  #sidebar .ask-options-panel {
    /* gap/padding trimmed (was 8px/8px), same "fit Guardrails' own
       now-15-entry list without scrolling" request as
       .sb-details > summary's own padding cut just above.
       Horizontal padding dropped to 0 (was 4px, both sides): the three
       .sb-details groups inside (Model & pipeline / Advanced checks /
       Guardrails) each already get their own 12px left inset from
       .sb-details > summary's own padding, same as Menu/Recent Reddit
       Update Risk Questions above them - this wrapper's extra 4px was
       shifting only these three 4px further right than the other
       sidebar groups, a visible left-edge mismatch caught live. */
    display: flex; flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 3px;
    padding: 4px 0; margin-bottom: 0;
  }
  /* The three top-level groups (Model & pipeline / Advanced checks /
     Guardrails, each a .sb-details) carry their own flex:1 0 100%
     inline style for the narrow/row-wrap layout above, where basis
     100% (of width, the main axis there) is what forces each onto
     its own full-width row. In THIS column-direction context,
     flex-basis instead sizes the main axis, which is now height --
     a 100% basis forced every closed accordion to claim the panel's
     full height, and (combined with the base rule's flex-wrap:wrap,
     only now overridden above) made them wrap into side-by-side
     "columns" instead of a plain vertical stack. Reset to auto
     height here so each item is only as tall as its own content. */
  /* margin-top: 0, not the base rule's 2px: the flex gap: 3px set
     just above already spaces these; the base rule's margin would
     just add on top of that gap redundantly. */
  #sidebar .ask-options-panel > .sb-details { flex: 0 0 auto; margin-top: 0; }
  #sidebar .ask-toggle-group { flex-direction: column; align-items: flex-start; gap: 6px; }
  #sidebar .ask-preset-select { width: 100%; }
}
.ask-intent-badge {
  flex-shrink: 0; align-self: center;
  /* border-radius: var(--radius), not the old var(--radius-full) pill
     shape, per explicit request ("make the chips a bit more square
     cornered") -- same small radius most other chrome in this app
     already uses, now that there are two of these shown side by
     side (domain + fact/opinion) rather than just one. */
  font-size: 10px; font-weight: 700; padding: 3px 8px; border-radius: var(--radius);
  background: var(--brand-light); color: var(--brand); white-space: nowrap;
}
/* Left-aligned row under the input for #askIntentBadge (see its own
   markup comment). display:flex so an empty/hidden badge collapses
   this row to nothing, same reasoning already established for
   .ask-options-row just below it. gap: 6px added now that a second,
   independent chip (#askQuestionTypeBadge) can show alongside it. */
.ask-intent-badge-row { display: flex; gap: 6px; margin-top: 4px; }
/* Was a fixed full-width strip below the header (any real overlay
   needs the page's own top padding bumped to make room for it, see
   .layout's own history); moved per explicit request to sit inline
   right above the workflow diagram in the Answer panel instead, so
   it reads as "here's what this question actually searched for"
   rather than a page-wide typing hint. Small and muted since it's a
   secondary technical detail next to the diagram/answer, not the
   main content of the panel. */
.ask-query-preview {
  font-size: 10px; line-height: 1.3; color: var(--muted); font-family: var(--mono);
  margin: 0 0 8px;
}
.ask-query-preview strong { color: var(--text); font-weight: 600; }

/* ── Ask answer modal ───────────────────────────────────────── */
#askOverlay {
  display: none; position: fixed; inset: 0;
  background: rgba(15, 23, 42, .45); z-index: 1450;
}
#askOverlay.open { display: block; }
#askModal {
  display: none; position: fixed; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(720px, 92vw); max-height: 82vh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-md); z-index: 1500; padding: 16px;
}
#askModal.open { display: block; }
#askModal.ask-compare-mode { width: min(1320px, 96vw); }
.ask-modal-header {
  display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px;
  padding-bottom: 10px; border-bottom: 1px solid var(--border);
}
.ask-modal-header strong { flex: 1; font-size: 14px; line-height: 1.4; }
.ask-compare-grid { display: flex; flex-wrap: wrap; gap: 12px; }
.ask-compare-grid .ask-answer-card { flex: 1 1 240px; min-width: 0; }
/* Duo demo mode (see the "duo" pipeline option / askRenderDuoBody):
   only ever 2 cards, and unlike the 5-way Compare grid they each show
   a full answer, not a "primary answer + a benchmark table tab"
   summary. They get more width per card than the 5-way grid's 240px. */
.ask-duo-grid .ask-answer-card { flex: 1 1 380px; }
/* The "what they do/don't do" legend shown in Compare mode's
   Benchmark tab; see askCompareLegendHTML(). A stacked list, not a
   table with a horizontal-scroll fallback: every line wraps to fit
   whatever width it's given (rail column, narrow-screen modal, or a
   phone), no minimum width to force a scrollbar. */
.ask-legend-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 4px; }
.ask-legend-item {
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 10px;
  font-size: 11.5px;
}
.ask-legend-name { font-weight: 700; margin-bottom: 4px; }
.ask-legend-facts { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-bottom: 6px; font-size: 10.5px; }
.ask-legend-example { font-family: var(--mono); font-size: 10.5px; line-height: 1.5; color: var(--muted); }
.ask-cy { color: var(--ok); }
.ask-cn { color: var(--muted); }
/* Compare mode's Benchmark tab: a CSS-grid block, not a real <table> -
   a genuine 4-column table doesn't fit the rail's ~360px column (see
   askRenderBenchmarkTable's own comment), so each pipeline gets a
   compact 3-cell header row (name/time/source count) then a
   full-width answer row right below it. */
.ask-bm-legend-details { margin-bottom: 12px; font-size: 11px; }
.ask-bm-legend-details summary { font-size: 11px; }
.ask-bm-table {
  display: grid; grid-template-columns: 1fr auto auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; font-size: 11px;
}
.ask-bm-head {
  padding: 6px 8px; border-bottom: 1px solid var(--border);
  background: var(--chip-bg); font-weight: 700; white-space: nowrap;
}
.ask-bm-col-head {
  font-size: 10px; text-transform: uppercase; letter-spacing: .3px;
  color: var(--muted); font-weight: 700;
}
.ask-bm-answer-row {
  grid-column: 1 / -1; padding: 6px 10px 10px; border-bottom: 1px solid var(--border);
  line-height: 1.5;
}
.ask-bm-table > *:nth-last-child(-n+4) { border-bottom: none; }
.ask-bm-rate { display: inline-flex; gap: 4px; margin-left: 8px; vertical-align: middle; }
.ask-bm-rate .ask-rate-btn { font-size: 11px; padding: 2px 6px; }
.ask-answer-card {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 14px;
}
.ask-answer-label {
  font: 700 10px/1 inherit; text-transform: uppercase; letter-spacing: .4px;
  color: var(--brand); margin-bottom: 6px;
}
/* Rail-only alternative to .ask-answer-label: the actual question,
   moved inside the card per explicit request (it used to sit
   outside, in the rail's own static header), plus the pipeline name
   right next to it (no brackets, see askRenderCard's own comment)
   instead of as its own separate uppercase line. */
/* nowrap, not wrap: a long question plus a long preset name (e.g.
   "Multi-agent, feedback loop &middot; 4 agents") wrapped to a second line,
   costing real vertical space in a column already tight on it. The
   question truncates with an ellipsis instead (min-width:0 on the
   flex item, overflow/text-overflow on the text itself); the preset
   stays flex-shrink:0 so it's always fully visible on that same line. */
.ask-answer-heading {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: nowrap;
  margin-bottom: 6px;
}
.ask-answer-question {
  font: 700 13px/1.4 inherit; color: var(--text);
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ask-answer-preset {
  font: 700 10px/1 inherit; text-transform: uppercase; letter-spacing: .4px;
  color: var(--brand); white-space: nowrap; flex-shrink: 0;
}
.ask-answer-summary { font-size: 13px; line-height: 1.6; margin: 0 0 10px; overflow-wrap: anywhere; }
/* Set by askWireAnswerReveal (below): the initial, hidden state of
   each word-span it wraps a freshly-rendered answer's text in, so
   an answer appears word by word instead of all at once. */
.ask-reveal-word { opacity: 0; transition: opacity .15s ease-out; }
.ask-reveal-word.shown { opacity: 1; }
/* The one substring (a version number, so far) that most directly
   answers the question, per the server's own highlightTerm (see
   ask.js's highestVersionSource). Never a client-side guess at
   what looks important. A translucent green wash, like a
   highlighter pen, rather than a solid background + explicit text
   color: the existing background and font color underneath show
   through unchanged, so this reads correctly regardless of which
   ancestor card/rail styling it's sitting inside. */
.ask-answer-summary mark.ask-answer-mark {
  background: rgba(74, 222, 128, .45); color: inherit; border-radius: 3px; padding: 0 2px;
}
.ask-answer-summary p { margin: 0 0 8px; }
.ask-answer-summary p:last-child { margin-bottom: 0; }
.ask-answer-summary ul, .ask-answer-summary ol { margin: 0 0 8px; padding-left: 20px; }
.ask-answer-summary li { margin-bottom: 3px; }
.ask-answer-summary code {
  font-family: var(--mono); font-size: 12px; background: var(--chip-bg);
  color: var(--chip-text); padding: 1px 4px; border-radius: var(--radius-sm);
  overflow-wrap: anywhere;
}
/* Sources flow left to right as compact chips, wrapping to a new
   line only once a row genuinely runs out of width, not one
   source per line. Avoids a tall, scrollable stack of one-per-line
   sources for a question with many citations; each chip is sized
   to its own content, so short titles pack several per line. */
.ask-sources { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.ask-sources li { font-size: 12px; line-height: 1.4; min-width: 0; max-width: 100%; }
.ask-sources a { color: var(--text); text-decoration: none; }
.ask-sources a:hover { text-decoration: underline; color: var(--brand); }
.ask-source-row {
  display: inline-flex; align-items: baseline; gap: 4px; max-width: 100%;
  padding: 3px 8px; border-radius: var(--radius-sm); border: 1px solid var(--border);
  background: var(--chip-bg);
}
.ask-source-icon { flex: 0 0 auto; }
/* min-width:0 lets this flex child shrink below its content so a long
   title wraps inside the chip instead of forcing the whole card to
   scroll sideways; overflow-wrap breaks a giant unbroken token too. */
.ask-source-title { min-width: 0; overflow-wrap: anywhere; }
.ask-source-date { flex: 0 0 auto; color: var(--muted); font-size: 11px; white-space: nowrap; }
/* Groups the answer's actual documented evidence (release notes, CVE)
   apart from community/web discussion, so the two read as separate
   things instead of one flat, undifferentiated list. */
.ask-source-group { margin: 0 0 12px; }
.ask-source-group:last-child { margin-bottom: 10px; }
/* Artifact always renders (see askRenderSources), even with nothing in
   it - a dashed border reads as "checked, found nothing" rather than
   looking like an accidentally-empty populated list. */
.ask-source-group-empty { padding: 6px 8px; border: 1px dashed var(--border); border-radius: var(--radius-sm); }
.ask-source-group-empty .ask-source-heading { margin-bottom: 4px; }
.ask-source-group-empty .ask-muted { margin: 0; }
.ask-source-heading {
  font: 700 10px/1 inherit; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); margin-bottom: 6px;
}
/* The evidence behind a pipeline escalation (see verifyVendorViaWeb on
   the server): left column is what was searched and the verdict, right
   column is the actual raw results that verdict was judged from. Wraps
   to a single stacked column once the rail is too narrow for both. */
.ask-webverify-grid { display: flex; flex-wrap: wrap; gap: 14px; }
.ask-webverify-col { flex: 1 1 220px; min-width: 180px; font-size: 12px; line-height: 1.5; }
.ask-webverify-col > div { margin-bottom: 4px; }
.ask-webverify-results { list-style: none; margin: 0; padding: 0; }
.ask-webverify-result { margin-bottom: 8px; }
.ask-webverify-result:last-child { margin-bottom: 0; }
.ask-webverify-result a { color: var(--text); text-decoration: none; font-size: 12px; }
.ask-webverify-result a:hover { text-decoration: underline; color: var(--brand); }
.ask-webverify-snippet { color: var(--muted); font-size: 11px; line-height: 1.4; margin-top: 2px; }
/* "Model vs Rules" tab: which part of each role actually ran on this
   one answer, the model or a deterministic check (see
   askRenderModelVsRules). Meaning column wraps normally (real
   sentences, not a short label like the other two), so the table
   itself gets its own scroll container rather than ever forcing the
   whole card wider than its column. */
.ask-mvr-wrap { overflow-x: hidden; }
.ask-mvr-wrap table { width: 100%; }
.ask-mvr-wrap th, .ask-mvr-wrap td { overflow-wrap: anywhere; }
.ask-mvr-table { width: 100%; min-width: 420px; border-collapse: collapse; font-size: 12px; }
.ask-mvr-table th { text-align: left; padding: 6px 8px; border-bottom: 2px solid var(--border); color: var(--muted); font-weight: 600; white-space: nowrap; }
.ask-mvr-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.ask-mvr-table tr:last-child td { border-bottom: none; }
.ask-mvr-table th:nth-child(1), .ask-mvr-table td:nth-child(1) { white-space: nowrap; }
.ask-mvr-table th:nth-child(2), .ask-mvr-table td:nth-child(2),
.ask-mvr-table th:nth-child(3), .ask-mvr-table td:nth-child(3) { text-align: center; width: 52px; }
.ask-mvr-table td:nth-child(4) { color: var(--muted); line-height: 1.4; }
.ask-mvr-table input[type="checkbox"] { width: 15px; height: 15px; }
.ask-mvr-reason + .ask-mvr-reason { margin-top: 4px; }
.ask-mvr-reason strong { color: var(--text); }
.ask-mvr-note { font-size: 12px; color: var(--muted); line-height: 1.4; margin: 0 0 8px; }
.ask-mvr-note strong { color: var(--text); }
/* html/body disable native page scroll (see the global `overflow:
   hidden` rule). Every other view supplies its own scroll region
   (see #ackView's identical shape) and this one needs the same
   treatment, or its content just gets clipped with no way to reach
   it once it grows past one screen (reported live: 13+ delta
   sources on one side). */
#evalRewriterView, #evalEvaluatorView, #evalOrchestratorView {
  position: sticky; top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
}
@media (max-width: 640px) {
  #evalRewriterView, #evalEvaluatorView, #evalOrchestratorView { position: static; height: auto; overflow-y: visible; }
}
/* Global rule for this page: vertical scroll only, never horizontal.
   Anything long enough to otherwise force a sideways scrollbar
   (a long unbroken Rewriter Prompt line, a URL with no spaces)
   breaks onto another line instead. */
.eval-rewriter-wrap { overflow-wrap: anywhere; }
/* Eval Rewriter (admin-only): a real two-column grid, not flex-wrap,
   so the split is reliable rather than depending on how much width
   happens to be left over; stacks under 700px. */
.er-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
@media (max-width: 700px) { .er-grid { grid-template-columns: 1fr; } }
/* A grid item's default min-width is auto, not 0 like a flex item's -
   it won't shrink below its content's own natural width, which
   silently defeats a descendant's text-overflow:ellipsis (there's
   nothing to truncate against if the column just grows to fit the
   long text instead). Every direct .er-grid child needs this. */
.er-grid > div { min-width: 0; }
/* Denser than the normal Ask rail's own source chips: two full
   evidence lists side by side is the whole point of this page, so
   more sources visible per screen matters more here than it does
   for a single answer's citations. */
.er-compare .ask-sources li { font-size: 10.5px; }
.er-compare .ask-source-row { padding: 2px 7px; }
.er-compare .ask-source-heading { margin-bottom: 4px; }
/* One source per line here (the shared .ask-sources default flows
   them as wrapping chips, several per line), each truncated to a
   single line with an ellipsis instead of wrapping its title across
   several. A dense side-by-side comparison reads far easier as a
   short scannable list than a wall of multi-line chips. */
.er-compare .ask-sources { display: block; }
.er-compare .ask-sources li { display: block; margin-bottom: 2px; max-width: 100%; }
.er-compare .ask-source-row { display: flex; width: 100%; box-sizing: border-box; }
.er-compare .ask-source-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask-rate-row { display: flex; align-items: center; gap: 6px; }
.ask-rate-btn { font-size: 11px; padding: 4px 8px; }
.ask-rate-btn.ask-rate-chosen { background: var(--brand-light); color: var(--brand); border-color: var(--brand); }
.ask-error { color: var(--cve); font-size: 13px; }
.ask-muted { color: var(--muted); font-size: 12px; }

.ask-answer-abstained { border-color: var(--cve); background: var(--cve-bg); }
.ask-abstain-badge {
  display: inline-block; margin-left: 8px; font-size: 10px; font-weight: 700;
  color: var(--cve); text-transform: none; letter-spacing: 0;
}
.ask-meta-chips { display: flex; flex-wrap: wrap; gap: 5px; margin: -2px 0 8px; }
.ask-meta-chip {
  font-size: 10px; padding: 2px 7px; border-radius: var(--radius-full);
  background: var(--chip-bg); color: var(--chip-text);
}
.ask-details { margin-top: 8px; font-size: 11px; }
.ask-details summary { cursor: pointer; color: var(--muted); }
.ask-details summary:hover { color: var(--text); }
.ask-calls { margin: 6px 0; padding-left: 18px; }
.ask-calls li { margin-bottom: 3px; }
.ask-calls code { font-size: 10px; }
.ask-system-prompt {
  white-space: pre-wrap; word-break: break-word; margin: 6px 0 0;
  padding: 8px; background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 10px; line-height: 1.5; color: var(--muted);
}
/* .topbar-form already wraps at every width; on narrow screens the
   question input additionally claims a full row of its own so
   typing isn't cramped next to the toggles/preset select. */
@media (max-width: 640px) {
  .search-wrap:has(#askQuestion) { flex-basis: 100%; }
}

.search-wrap { position: relative; flex: 1 1 160px; min-width: 160px; }
@media (max-width: 560px) { .search-wrap { flex-basis: 100%; min-width: 0; } }
.search-icon {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  color: var(--muted); pointer-events: none; font-size: 13px;
}
.search-input {
  width: 100%; padding: 7px 10px 7px 28px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font: 13px/1 var(--mono);
  transition: border-color .15s, box-shadow .15s;
}
.search-input:focus {
  outline: none; border-color: var(--text);
  box-shadow: 0 0 0 2px rgba(15,23,42,.10);
}
.search-actions { display: flex; gap: 6px; flex-shrink: 0; }
.search-actions .btn { text-align: center; white-space: nowrap; }

/* ── Buttons ────────────────────────────────────────────── */
.btn {
  padding: 5px 12px; border: 1px solid transparent;
  border-radius: var(--radius); font: 600 12px/1 inherit;
  cursor: pointer; white-space: nowrap; transition: all .15s;
}
.btn-primary { background: var(--text); color: #fff; }
.btn-primary:hover { background: #000; }
.btn-ghost { background: transparent; color: var(--muted); border-color: var(--border); }
.btn-ghost:hover { background: var(--chip-bg); color: var(--text); }
.btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ── Autocomplete ───────────────────────────────────────── */
#suggestions {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 500;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
  padding: 4px 0; max-height: 200px; overflow-y: auto;
  list-style: none; margin: 0; display: none;
}
#suggestions.open { display: block; }
#suggestions li {
  padding: 7px 12px; cursor: pointer; font-size: 13px; color: var(--text);
}
#suggestions li:hover, #suggestions li.active {
  background: var(--brand-light); color: var(--brand);
}
#suggestions li strong { font-weight: 700; }

/* Same dropdown treatment as #suggestions, plus a small subreddit tag
   per row so a picked question's real source is visible before
   clicking it, not just after. */
#askSuggestions {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 500;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
  padding: 4px 0; max-height: 240px; overflow-y: auto;
  list-style: none; margin: 0; display: none;
}
#askSuggestions.open { display: block; }
#askSuggestions li {
  padding: 7px 12px; cursor: pointer; font-size: 13px; color: var(--text);
  display: flex; align-items: baseline; gap: 6px;
}
#askSuggestions li:hover, #askSuggestions li.active {
  background: var(--brand-light); color: var(--brand);
}
#askSuggestions .ask-suggestion-text { flex: 1; min-width: 0; }
#askSuggestions .ask-suggestion-sub { font-size: 10px; color: var(--muted); flex-shrink: 0; white-space: nowrap; }
#askSuggestions .ask-suggestion-ver { font-size: 10px; color: var(--muted); white-space: nowrap; }

/* ── Toggles (shields.io flat-badge style) ─────────────── */
.toggles { display: flex; gap: 5px; flex-wrap: wrap; }

/* Secondary quick-filters, tucked away by default */
.toggle-more { flex: 1 0 100%; margin-top: 2px; }
.toggle-more > summary {
  list-style: none; cursor: pointer; user-select: none;
  font: 600 10px/1.4 var(--mono); color: var(--muted);
  text-transform: uppercase; letter-spacing: .4px;
  padding: 2px 0; display: inline-flex; flex-direction: row; align-items: center; gap: 4px;
}
.toggle-more > summary::-webkit-details-marker { display: none; }
.toggle-more > summary::before { content: '›'; display: inline-block; transition: transform .15s; }
.toggle-more[open] > summary::before { transform: rotate(90deg); }
.toggle-more > summary:hover { color: var(--text); }
.toggle-more > .toggles { margin-top: 5px; }

.toggle {
  display: inline-flex; align-items: stretch;
  border-radius: var(--radius-sm); overflow: hidden;
  border: 1px solid var(--border); padding: 0; background: none;
  cursor: pointer; white-space: nowrap;
  font: 600 10px/1 var(--mono);
  outline: 2px solid transparent; outline-offset: 1px;
  transition: border-color .12s, background .12s, outline-color .12s;
}
.toggle:hover { border-color: var(--muted); }
.toggle:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.toggle.disabled { opacity: .4; cursor: not-allowed; pointer-events: none; }
.toggle[aria-pressed="true"] { border-color: var(--text); }

/* Left label half */
.toggle .lbl {
  padding: 3px 6px; background: var(--chip-bg); color: var(--chip-text);
  display: inline-flex; align-items: center; gap: 3px;
}
.toggle[aria-pressed="true"] .lbl { background: var(--text); color: #fff; }
.toggle[aria-pressed="true"] .lbl::before {
  content: "✓"; font-size: 9px; font-weight: 900; margin-right: 1px;
}

/* Right count half: neutral by default; only true alerts get a hue */
.toggle .count {
  padding: 3px 6px; color: #fff;
  display: inline-flex; align-items: center;
  background: var(--muted);
}
.toggle[data-key="cve"]               .count,
.toggle[data-key="reddit-risk-cve"]   .count { background: var(--cve); }
.toggle[data-key="potential-cve"]     .count,
.toggle[data-key="reddit-risk"]       .count,
.toggle[data-key="reddit-risk-latest"].count,
.toggle[data-key="so-risk"]           .count { background: var(--risk); }
.toggle[aria-pressed="true"] .count { filter: brightness(.88); }

/* ── Active filters ─────────────────────────────────────── */
#activeFilters {
  display: none; gap: 4px; flex-wrap: wrap; align-items: center;
  font-size: 11px; color: var(--muted);
  background: var(--chip-bg); border-top: 1px solid var(--border);
  padding: 7px 12px;
}
#activeFilters.visible { display: flex; }
#activeFilters > span { font-weight: 700; color: var(--text); }
.af-tag {
  display: inline-flex; align-items: center; padding: 1px 7px;
  background: var(--text); color: #fff;
  border-radius: var(--radius-sm); font: 600 10px/1.5 var(--mono);
}
.af-clear {
  margin-left: auto; cursor: pointer; font: 600 12px/1 inherit;
  color: var(--brand); background: none; border: none; padding: 0;
  text-decoration: underline; text-underline-offset: 2px;
}
.af-clear:hover { color: var(--text); }

/* ── KPIs (sidebar) ─────────────────────────────────────── */
.kpis { display: flex; flex-direction: column; gap: 3px; }
.kpi {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  padding: 4px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--muted); font: 600 11px/1.3 inherit;
}
.kpi em { font-style: normal; color: var(--text); font-weight: 700; white-space: nowrap; }
#kpi-range { flex-direction: column; align-items: flex-start; gap: 2px; }
#kpi-range em { font-size: 10px; font-weight: 600; }

/* ── Feed main (right column) ───────────────────────────── */
.feed-main { min-width: 0; }
/* Now the narrower (40%) column of the two-column layout above; a
   modest base-size drop (13px body default down to 12px) keeps its
   plain-prose content comfortable at that width. Only affects text
   that inherits font-size rather than setting its own explicit px
   value: most feed/card/prose text here does. A handful of
   already-explicitly-sized elements (e.g. .kpi's own numbers)
   won't shrink further from this alone. */
@media (min-width: 900px) {
  #main-content { font-size: 12px; }
}

/* ── Panel ──────────────────────────────────────────────── */
.panel {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden;
}
#feedPanel {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  max-height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* No card boundary here on purpose: the feed reads as part of the
     page itself, not a separate panel floating on top of it. */
  background: transparent;
  border: none;
  box-shadow: none;
}
/* Un-stuck AND un-capped on mobile, not just un-stuck: the sticky
   two-column desktop pattern above (feed + Ask rail each pinned and
   independently scrollable) doesn't apply here, since there's only
   one column, so a leftover max-height/overflow-y just boxed the
   feed into 70% of the screen with its own nested scroll, on top of
   the page's own scroll (already enabled for mobile, see html/body
   above). That trapped the panel header (sort dropdown, Expand all)
   inside the same scrolling box as the list, so scrolling through
   updates also scrolled the controls out of reach. Letting the feed
   flow with the page instead means the header only leaves view the
   same way any page header normally would. Confirmed live:
   infinite-scroll pagination (setupObserver) doesn't depend on
   #feedPanel being the scrolling element; its IntersectionObserver
   has no `root` set, so it already watches the real viewport. */
@media (max-width: 640px) { #feedPanel { position: static; max-height: none; overflow: visible; } }
.panel-header {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 12px; border-bottom: 1px solid var(--border);
}
/* min-width:0 lets a flex:1 heading actually shrink/wrap inside its
   own share of the row instead of forcing the row wider than the
   (now narrower, 40%-column) panel and pushing the sort/expand
   controls to wrap onto their own line too. */
.panel-header h2 { margin: 0; font-size: 12px; font-weight: 700; flex: 1; min-width: 0; }
.panel-header h2 small { font-weight: 400; color: var(--muted); font-size: 10px; }
/* Native <select> chrome renders taller than a plain .btn at the same
   font-size (its own UA line-height + dropdown-arrow padding), so an
   explicit shared height on both is the only reliable way to line
   them up, matched to whichever is naturally shorter (the button). */
#feedSortSelect, #expandAllBtn {
  height: 24px;
}
#feedSortSelect {
  font: inherit; font-size: 11px; line-height: 1; padding: 0 6px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface); color: var(--text); cursor: pointer;
}
/* Tighter than .btn's own site-wide default padding (5px 12px), just
   for this instance: reported live as crowding out the "Recent
   Updates" heading beside it in the panel's now-narrower (40%)
   column, wrapping the heading's own "components)" onto a second
   line. */
#expandAllBtn { padding: 0 8px; font-size: 11px; }
#status { color: var(--muted); font-size: 12px; }

/* ── Empty state ────────────────────────────────────────── */
/* One surface for both "nothing matched" and "the request itself
   failed" (see showEmptyState): .emptyState-error just recolors the
   headline red, everything else (icon, detail line, centered layout)
   stays the same between the two so a viewer isn't shown a
   completely different-looking block depending on which of the two
   it is. */
#emptyState { display: none; padding: 48px 20px; text-align: center; color: var(--muted); }
#emptyState.show { display: block; }
#emptyState p { margin: 6px 0 0; font-size: 13px; }
#emptyState.emptyState-error #emptyStateMsg { color: var(--cve); font-weight: 600; }
#emptyStateDetail { font-size: 12px; }

/* ── Feed ───────────────────────────────────────────────── */
#feed { padding: 6px 10px 4px; }

.feedGroup {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; margin-bottom: 4px; background: var(--view-card);
  transition: border-color .15s;
}
.feedGroup:hover { border-color: var(--muted); }

summary {
  cursor: pointer; list-style: none; user-select: none;
  display: flex; flex-direction: column; gap: 5px;
  padding: 7px 12px; font-weight: 600; font-size: 12px;
  background: var(--view-card); transition: background .15s;
}
summary:hover { background: #e6eaef; }
summary:focus-visible { outline: 3px solid var(--focus); outline-offset: -2px; }
summary::-webkit-details-marker { display: none; }
/* Name + latest-version share one row; the arrow lives on THIS row
   (.groupHead), not on <summary> itself. A group with any summary
   chips renders a second row below it, and a bare arrow on
   <summary>'s own ::before would sit on its own line above
   everything else once <summary> switched to a column layout. */
.groupHead {
  display: flex; align-items: center; gap: 8px;
}
.groupHead::before {
  content: "▶"; font-size: 8px; color: var(--muted);
  flex-shrink: 0; transition: transform .18s ease;
}
details[open] > summary .groupHead::before { transform: rotate(90deg); }
details[open] > summary { background: var(--view-card); color: var(--text); border-bottom: 1px solid var(--border); }

/* The group's own CVE/Reddit/SO/Major/Minor/Patch total chips get
   their own row below the name, flush-left with the arrow on the
   row above (not indented to the name text), instead of crowding
   onto the same line as the name and version bracket. */
.groupChips {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
}
/* Plain icon+label+count here, no pill box: a real .chip (CVE link,
   RISK, poll button, etc. elsewhere in the feed) still earns its box
   because it's a single, more consequential flag on one row. Six of
   these sitting together in a group's own summary read as too heavy
   as boxes, so they're just colored text instead, separated by a
   plain "|" rather than the box's own edge. */
/* .chip.bad/.warn/etc. below (their own colored background) match
   .groupChips .chip at equal specificity (two classes each), so
   whichever is later in the stylesheet was winning regardless of
   which makes sense: the CVE chip kept its red box even though
   the plain-text rule right above was clearly meant to win here.
   .chip.CLASS pins the same specificity these rules already carry,
   so this box-removal always applies inside .groupChips. */
.groupChips .chip,
.groupChips .chip.bad,
.groupChips .chip.warn,
.groupChips .chip.ok,
.groupChips .chip.reddit,
.groupChips .chip.soft,
.groupChips .chip.llm,
.groupChips .chip.hv {
  background: transparent; border: none; padding: 0; font-weight: 600;
}
.groupChips .chip:not(:first-child)::before {
  content: "|"; margin-right: 10px; color: var(--border); font-weight: 400;
}
/* Which bot(s) produced this component's own content: replaces the
   old global "Recent Updates" source breakdown, which listed raw
   totals with no way to tell which component each count belonged
   to. Flush-left with the arrow/chips above it, same convention. */
.groupSource { font-size: 10px; color: var(--muted); }
.group-latest-ver { font-weight: 400; font-size: 10px; color: var(--muted); margin-left: auto; }

/* ── Timeline items ─────────────────────────────────────── */
.updates { padding: 2px 12px 2px; }
.list { display: flex; flex-direction: column; }

.li {
  display: grid; grid-template-columns: 92px 22px 1fr;
  column-gap: 10px; padding: 10px 0 10px 8px;
  border-bottom: 1px solid var(--border);
  /* Rounded on the left-border side only, so a colored indicator
     reads as a soft accent instead of a hard rectangular bar. */
  border-left: 2px solid transparent; border-radius: 0 4px 4px 0;
  align-items: start;
  transition: background .1s;
}
.li:hover { background: var(--bg); }
.li:last-child { border-bottom: none; }

/* Was a distinct tinted background per kind (a pink cve-bg, an amber
   risk-bg) on top of --surface/--view-card elsewhere, three or four
   different background colors competing at once; per explicit
   request ("too many background colors"), every row now shares the
   same --view-card tone and leans on its own left-border color alone
   (already a real, distinct color per kind) to carry the meaning. */
.li.kind-cve { border-left-color: var(--cve); background: var(--view-card); }
.li.kind-cve:hover { background: var(--view-card); }
.li.kind-reddit { border-left-color: var(--muted); }
.li.kind-reddit.risk { border-left-color: var(--risk); background: var(--view-card); }
.li.kind-stackoverflow { border-left-color: var(--muted); }
.li.kind-stackoverflow.risk { border-left-color: var(--risk); background: var(--view-card); }
/* var(--text) (near-black) read as too heavy/dominant for a plain
   "posted today" indicator. These three already have their own
   (currently-unused) softer neutral tokens defined for exactly
   this purpose; use them instead of the page's darkest ink color. */
.li.is-new { border-left-color: var(--new); }
.li.kind-llm { border-left-color: var(--llm); }
.li.kind-hv { border-left-color: var(--hv); }
/* Stands in for the removed per-row "major" text chip: the one
   channel with no icon of its own, so it keeps some visual cue. */
.li.kind-update.major { border-left-color: var(--ok); }

@media (max-width: 600px) {
  .li { grid-template-columns: 28px 1fr; grid-template-rows: auto auto; }
  .datecol {
    grid-column: 1 / -1; grid-row: 2;
    flex-direction: row; justify-content: flex-start;
    gap: 6px; padding: 4px 0 0; align-items: center;
  }
}

.datecol {
  color: var(--muted); font-size: 10px; display: flex;
  flex-direction: column; align-items: flex-end; padding-top: 1px; white-space: nowrap;
}
.datecol .day { font-weight: 700; color: var(--chip-text); font-size: 10px; }
.datecol .day.today { color: var(--text); }
.datecol .time { opacity: .7; }

.avatar {
  width: 22px; height: 22px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); object-fit: cover;
  background: var(--chip-bg); margin-top: 1px;
}
.redditIcon { border-color: var(--border); background: var(--chip-bg); }
.redditIcon.risky { border-color: var(--risk); background: var(--risk-bg); }
.soIcon { border-color: var(--border); background: var(--chip-bg); }
.soIcon.risky { border-color: var(--risk); background: var(--risk-bg); }

/* ── Chips ──────────────────────────────────────────────── */
.chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 5px; }
/* Rounder + bolder than this UI's other flat chrome (radius-sm is
   2px elsewhere), closer to a GitHub/shields.io badge's silhouette -
   but kept to this same muted, pastel palette rather than picking
   up their loud solid-fill colors, per "like GitHub, but subtle". */
.chip {
  display: inline-flex; align-items: center; padding: 2px 8px;
  font: 700 10px/1.4 inherit; letter-spacing: .1px; border-radius: 4px;
  border: 1px solid var(--border); background: var(--chip-bg);
  color: var(--chip-text); white-space: nowrap;
}
.chip.bad { background: var(--cve-bg); border-color: var(--cve); color: var(--cve); }
.chip.warn { background: var(--risk-bg); border-color: var(--risk); color: var(--risk); }
.chip.ok { background: var(--chip-bg); border-color: var(--border); color: var(--chip-text); }
.chip.reddit { background: var(--chip-bg); border-color: var(--border); color: var(--chip-text); }
.chip.llm { background: var(--chip-bg); border-color: var(--border); color: var(--chip-text); }
.chip.hv { background: var(--chip-bg); border-color: var(--border); color: var(--chip-text); }
.chip.soft { opacity: .75; }
.chip.link a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.chip.link a:hover { color: var(--text); }
/* Yes/No community poll button - a real <button>, not a <span>, so it
   can carry a click handler; visually just another chip until clicked. */
button.chip.poll-btn {
  font-family: inherit; cursor: pointer; border-color: var(--brand); color: var(--brand);
  background: var(--brand-light);
}
button.chip.poll-btn:hover { background: var(--brand); color: #fff; }
button.chip.poll-btn:disabled { cursor: default; }
button.chip.poll-btn.chip-done { border-color: var(--border); color: var(--chip-text); background: var(--chip-bg); }
button.chip.poll-btn.chip-done:hover { background: var(--chip-bg); color: var(--chip-text); }
button.chip.poll-btn.chip-err { border-color: var(--cve); color: var(--cve); background: var(--cve-bg); }
.chip.potentialCveBadge { margin-right: 2px; }
.potentialCveChips { margin-top: 3px; gap: 3px; }
.chip.potentialCveChip { background: var(--surface); border-color: var(--risk); color: var(--risk); }
.chip.potentialCveChip:hover { background: var(--risk-bg); }

.titleRow { display: flex; gap: 5px; align-items: flex-start; flex-wrap: wrap; margin-bottom: 1px; }
.titleRow a {
  color: var(--text); font-weight: 600; text-decoration: none;
  word-break: break-word; font-size: 13px;
}
.titleRow a:hover { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.titleRow a:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 2px; }

.meta { color: var(--muted); font-size: 12px; line-height: 1.5; margin-top: 2px; word-break: break-word; }

/* ── Skeleton ───────────────────────────────────────────── */
.skeleton {
  border-radius: var(--radius);
  background: linear-gradient(90deg, var(--chip-bg), var(--border), var(--chip-bg));
  background-size: 200% 100%; animation: pulse 1.4s ease-in-out infinite; margin-bottom: 6px;
}
@keyframes pulse { from { background-position: 0 0; } to { background-position: 200% 0; } }
.sentinel { font-size: 12px; text-align: center; color: var(--muted); padding: 12px 0 6px; }
/* #sentinel's job is reporting infinite-scroll status ("Loading
   more…", "End of results"), which is meaningless once #emptyState
   is already showing its own, more specific "no results" message.
   Every codepath that shows emptyState also sets #sentinel's text to
   some flavor of "No results", so without this a viewer saw the same
   message twice in a row (a big "No results found for the last N
   days" immediately followed by a small "🔍 No results"). One rule
   here covers every such codepath instead of hunting down each one
   that sets that text. */
#emptyState.show ~ #sentinel { display: none; }

/* ── Graph view (vis-network) ── */
#graphView {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg);
}
@media (max-width: 640px) {
  #graphView { position: static; height: 70vh; }
}
#g-networkContainer { width: 100%; height: 100%; }
#g-nodeInfoPanel {
  position: absolute; bottom: 10px; left: 10px; right: 10px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 12px;
  font-size: 11px; max-height: 110px; overflow-y: auto;
  z-index: 10; box-shadow: var(--shadow-md); color: var(--text);
}
#g-graphBadge {
  position: absolute; top: 8px; left: 8px; z-index: 10;
  background: rgba(255,255,255,.88); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 3px 9px;
  font-size: 11px; font-weight: 600; color: var(--muted);
  pointer-events: none; white-space: nowrap;
}
#g-zoomBar {
  position: absolute; top: 8px; right: 8px; z-index: 10;
  display: flex; flex-direction: column; gap: 2px;
}
#g-zoomBar button {
  width: 28px; height: 28px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: rgba(255,255,255,.92);
  color: var(--text); font-size: 15px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-md);
}
#g-zoomBar button:hover { background: var(--surface); }
.g-legend-dot {
  display: inline-block; width: 9px; height: 9px;
  border-radius: 50%; margin-right: 4px; vertical-align: middle;
}
.nav-link.nav-active { background: var(--brand-light); color: var(--brand); }

/* ── Arch view ──────────────────────────────────────────── */
#archView {
  position: sticky;
  top: calc(var(--topbar-h) + 8px);
  height: calc(100vh - var(--topbar-h) - 16px);
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
@media (max-width: 640px) { #archView { position: static; height: 82vh; } }
/* Real header row (not floating) so the Diagram/Table toggle has its
   own right-aligned slot that never competes for the same corner as
   #a-loader (which anchors to .a-canvas now, not #archView -- see
   its own comment) or overlaps the canvas/table content below it. */
.a-view-header {
  display: flex; align-items: center; flex: 0 0 auto;
  padding: 8px 12px; border-bottom: 1px solid var(--border);
}
#a-loader {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--border); border-top-color: var(--brand);
  animation: a-spin 1s linear infinite; display: none;
}
@keyframes a-spin { to { transform: rotate(360deg); } }
.a-canvas {
  position: relative; flex: 1 1 auto; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  background: #fff; overflow-y: auto; overflow-x: hidden; padding: 2px;
}
#a-ecosysImage { width: 100%; height: 100%; overflow-y: auto; overflow-x: hidden; }
/* No max-width/height:auto here anymore -- aFitDiagramSvg() sets an
   explicit pixel width+height on the <svg> itself, scaled to
   whichever axis of .a-canvas is the tighter fit (see its own
   comment), so this rule would only fight that computed size. */
#a-ecosysImage a text { text-decoration: underline; }
/* Arch view: drift table mode.
   #a-table (the scrolling ancestor for the sticky <th> below) must not
   carry its own top padding: a sticky element's "top: 0" sticks to the
   padding EDGE, not the content edge, so a top-padded scroll container
   leaves a gap the first data row can still scroll up into and sit
   visible inside, peeking above the "stuck" header - reported live as a
   stray row rendering above the Component/Installed/... header row.
   The same visual spacing now comes from .a-score's own margin-top
   instead, which scrolls away normally with the rest of the content. */
#a-table { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 0 14px 12px; background: var(--surface); }
/* Mermaid flowchart view: same flex-child sizing as #a-table/.a-canvas so
   it fills the same slot in #archView's layout regardless of which of the
   three view modes is active. The SVG itself is left at its own natural
   size (no forced width:100%, which would stretch a wide-and-short
   flowchart into blurry oversized text) and just scrolls within this box
   when it's larger than the available area - same reasoning as
   #a-ecosysImage above it not being force-fit either. */
#a-mermaid { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 14px; background: #fff; text-align: center; }
/* Mermaid sets its own inline max-width (its "useMaxWidth" default) on the
   rendered <svg> - !important is required here to actually override an
   inline style, not just a matter of selector specificity. */
#a-mermaid svg { max-width: none !important; height: auto; }
.a-score { font-size: 12px; color: var(--muted); margin: 12px 0 10px; }
.a-score b { color: var(--text); font-size: 13px; }
/* "Lightweight to read": airier row padding, a lighter (600, not 700)
   header weight, and a hairline border instead of the table's own
   full-strength one - the data should read as a plain, calm list, not a
   dense boxed grid. */
table.a-drift { width: 100%; border-collapse: collapse; font-size: 12px; }
table.a-drift th, table.a-drift td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border); white-space: nowrap; }
table.a-drift th { position: sticky; top: 0; z-index: 1; background: var(--chip-bg); font-weight: 600; color: var(--text); }
table.a-drift tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--surface) 97%, var(--text)); }
table.a-drift tr:hover td { background: var(--bg); }
table.a-drift td.mono { font-family: Consolas, Monaco, monospace; }
.a-chip-t { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; color: #0f172a; border: 1px solid rgba(0,0,0,.12); }
.a-muted-note { color: var(--muted); font-size: 12px; }
.a-stack-select {
  padding: 5px 8px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg); color: var(--text); font: inherit; font-size: 12px;
  cursor: pointer;
  /* Was width:100% for its old full-width sidebar slot; now it's one
     flex item among several in .a-view-header's horizontal row, where
     100% would mean 100% of the whole row and push every button next
     to it out of view. Sized to its own content instead. */
  width: auto;
}
/* Arch view: default landing state (no component picked) */
#a-empty { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 32px 24px; background: var(--bg); }
.a-empty-head { max-width: 780px; margin: 0 auto 22px; text-align: center; }
.a-empty-head h3 { margin: 0 0 6px; font-size: 16px; font-weight: 800; color: var(--text); }
.a-empty-head p { margin: 0 auto; max-width: 620px; font-size: 12.5px; line-height: 1.6; color: var(--muted); }
/* Real-machine CTA: the primary suggestion on this screen (no more
   sample-stack cards to pick from instead) - point at either the
   Account tab's saved-inventory upload, or the CLI scanner package. */
.a-empty-real { text-align: center; }
.a-empty-real-cli { margin: 10px 0 0; font-size: 12px; color: var(--muted); }
.a-empty-real-cli code {
  background: var(--chip-bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 3px 8px; font-family: var(--mono); font-size: 12px; color: var(--text);
}
/* Secondary action, visually separated below the primary CTA above it. */
.a-empty-foot { max-width: 780px; margin: 26px auto 0; padding-top: 18px; border-top: 1px solid var(--border); text-align: center; }

/* ── Credits / Ack view ─────────────────────────────────── */
#ackView {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--view-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 0;
}
@media (max-width: 640px) { #ackView { position: static; height: auto; overflow-y: visible; } }

/* ── Changelog view ────────────────────────────────────── */
#changelogView {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--view-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
@media (max-width: 640px) { #changelogView { position: static; height: auto; } }
.cl-header {
  padding: 18px 20px 14px; position: sticky; top: 0; z-index: 2;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.cl-header h2 { margin: 0 0 4px; font-size: 15px; font-weight: 700; }
.cl-header p  { margin: 0; font-size: 12px; color: var(--muted); }
.cl-body { padding: 12px 16px 32px; display: flex; flex-direction: column; gap: 0; }
.cl-release {
  display: grid; grid-template-columns: 90px 1fr;
  gap: 0 16px; padding: 14px 0; border-bottom: 1px solid var(--border);
}
.cl-release:last-child { border-bottom: none; }
.cl-date-col { padding-top: 3px; }
.cl-date { font-size: 11px; font-weight: 700; color: var(--muted); white-space: nowrap; }
.cl-ver  {
  display: inline-flex; align-items: center;
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: var(--brand-light); color: var(--brand); margin-top: 4px; white-space: nowrap;
}
.cl-ver.cl-ver-minor { background: #f1f5f9; color: #475569; }
.cl-ver.cl-ver-patch { background: #f8fafc; color: var(--muted); border: 1px solid var(--border); }
.cl-content h3 { margin: 0 0 6px; font-size: 13px; font-weight: 700; }
.cl-content ul { margin: 0; padding: 0 0 0 16px; display: flex; flex-direction: column; gap: 3px; }
.cl-content li { font-size: 12px; color: var(--muted); line-height: 1.5; overflow-wrap: anywhere; }
.cl-content li strong { color: var(--text); }
.cl-tag {
  display: inline-block; font: 700 10px/1.5 var(--mono); padding: 0 5px;
  border-radius: var(--radius-sm); margin-right: 4px; vertical-align: middle;
  background: var(--chip-bg); color: var(--chip-text); border: 1px solid var(--border);
}
.cl-tag-ux { background: var(--risk-bg); color: var(--risk); border-color: var(--risk); }

/* ── Phone: graph sidebar collapses to bottom overlay ─── */
@media (max-width: 640px) {
  #graphControls {
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 900;
    background: var(--surface); border-top: 1px solid var(--border);
    border-radius: 16px 16px 0 0; box-shadow: 0 -4px 24px rgba(0,0,0,.12);
    max-height: 45vh; overflow-y: auto; overscroll-behavior: contain;
    padding-bottom: env(safe-area-inset-bottom, 8px);
  }
  #graphControls.graph-ctrl-hidden { display: none !important; }
}

/* ── Reduced motion ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
.ack-header {
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
  background: transparent;
}
.ack-header h2 { margin: 0 0 6px; font-size: 15px; font-weight: 700; }
.ack-header p  { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.6; }
.ack-sub { border-top: 1px solid var(--border); }
.ack-list {
  list-style: none; margin: 0; padding: 10px 14px 24px;
  display: flex; flex-direction: column; gap: 2px;
}
.ack-list li {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 8px 10px; border-radius: var(--radius);
  transition: background .12s;
}
.ack-list li:hover { background: var(--brand-light); }
.ack-list li a {
  font-size: 13px; font-weight: 600; color: var(--brand);
  text-decoration: none; white-space: nowrap;
}
.ack-list li a:hover { text-decoration: underline; text-underline-offset: 2px; }
.ack-list li span { font-size: 12px; color: var(--muted); }

/* ── User account management view ──────────────────────── */
/* max-width used to be a narrow fixed 580px though #usersView has
   had the whole main column to itself since Filters/nav became
   their own off-canvas drawers; a fair amount of unused width sat
   to its right at any normal desktop size, forcing content (the
   profile card's stat row, in particular) to wrap onto extra lines
   it didn't need to. min(900px, 96vw) uses that space, still capped
   so lines of text don't get uncomfortably long on a very wide
   monitor, and still shrinks correctly on narrow screens. */
/* Bottom slack trimmed from 16px to 8px (kept asymmetric with the
   16px top gap on purpose): every extra px here directly shrinks
   the box available for content before the "all closed" admin
   panel needs to scroll at all, which matters more than a perfectly
   even gap on both sides. */
#usersView {
  max-width: min(900px, 96vw); padding: 14px 16px;
  position: sticky; top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 24px);
  overflow-y: auto; overscroll-behavior: contain;
}
@media (max-width: 640px) { #usersView { position: static; height: auto; overflow-y: visible; } }

/* ── No view scrolls the whole page (or its own panel) sideways ──
   Each of these containers sets overflow-y:auto, which per the CSS
   spec silently promotes overflow-x to auto as well, so any child a
   few px too wide (a long unbreakable token) drops a horizontal
   scrollbar across the entire view. Pin overflow-x to hidden on the
   container; a piece of content that genuinely can't reflow (a wide
   diagram, a code block) gets its own small overflow-x: hidden box
   instead, so any scroll stays contained to it, never the view. */
#usersView, #feedPanel, #changelogView, #dashboardView,
#networkView, #docsView, #ackView { overflow-x: hidden; }
/* #ua-se-list keeps a defensive overflow-x: hidden box here for the
   admin search-events table even though that table now uses a fixed
   percentage-column layout (see .ua-se-table's own comment) that
   guarantees it fits its container at any width; the box stays as a
   fallback (an unusually long unbroken token slipping past ellipsis
   truncation, say) rather than something expected to actually
   engage. */
#ua-se-list { overflow-x: hidden; overflow-y: hidden; }
.ua-tabs {
  display: flex; border-bottom: 2px solid var(--border); margin-bottom: 0;
}
.ua-tab {
  padding: 9px 18px; background: none; border: none; cursor: pointer;
  font: 600 13px/1 inherit; color: var(--muted);
  border-bottom: 2px solid transparent; margin-bottom: -2px;
  transition: color .15s, border-color .15s;
}
.ua-tab:hover { color: var(--text); }
.ua-tab.ua-tab-active { color: var(--brand); border-bottom-color: var(--brand); }
.ua-card {
  background: var(--view-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 20px; margin-top: 16px;
}
/* Capped and centered specifically for the signed-out Sign in/
   Register card, per explicit request ("too cluttered"): the wide,
   unconstrained .ua-card read as a big mostly-empty box with the
   two-field form stranded on the left and a large dead gap to its
   right, since #usersView itself is wide (see .ua-field's own
   comment on this same tension) but a one- or two-field auth form
   has nothing to fill that width with. The signed-in profile panel
   keeps the full-width .ua-card unchanged (its stat rows/dashboard
   cards genuinely use the space). */
#ua-auth-panel { max-width: 420px; margin: 0 auto; }
/* Capped, not full-width: #usersView is now wide enough (up to
   900px) that a single password/text input stretching edge to edge
   would look stray rather than using the space well. Wide use of
   the panel's own width belongs to things that actually benefit
   from it (stat rows, dashboard cards, the search-events table),
   not a one-line form field. */
.ua-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; max-width: 420px; }
.ua-field label { font: 600 12px/1 inherit; color: var(--text); }
/* Honeypot for the register form (see ua-reg-website in index.html and
   the server's own matching comment on the "website" field in
   POST /api/auth/register). Off-screen via position, not display:none
   or visibility:hidden - a bot script that checks computed visibility
   before filling a field would skip either of those, but this still
   renders (just off the visible viewport), so it still gets filled by a
   naive "fill every input" script. */
.ua-hp { position: absolute; left: -9999px; top: -9999px; width: 1px; height: 1px; overflow: hidden; }
.ua-opt { font-weight: 400; color: var(--muted); }
.ua-msg {
  padding: 8px 12px; border-radius: var(--radius-sm);
  font-size: 12px; margin-bottom: 12px; line-height: 1.5;
}
.ua-msg-error { background: var(--cve-bg); color: var(--cve); border: 1px solid #fca5a5; }
.ua-msg-ok    { background: var(--new-bg); color: var(--new); border: 1px solid #e2e8f0; }
.ua-badge {
  /* .ua-profile-info is a row flexbox now (see its own comment), so
     align-items:center there already keeps this a compact pill; no
     align-self override needed (it was needed only for the column
     layout this replaced, where a plain inline-block child stretches
     to the parent's full cross-axis width by default). */
  display: inline-block; flex-shrink: 0; padding: 2px 10px; border-radius: var(--radius-full);
  font: 700 11px/1.4 inherit; text-transform: uppercase; letter-spacing: .4px;
}
.ua-badge-user  { background: var(--chip-bg); color: var(--chip-text); }
.ua-badge-admin { background: var(--brand-light); color: var(--brand); }
/* Admin's aggregate stats/notice used to sit as their own always-
   visible lines right above "System overview", easy to miss (blank
   space, nothing calling attention to it) and inconsistent with
   everything else being genuinely immediate. Moved inside the
   profile card itself ("the top box") per explicit request, so it's
   part of the one thing every visitor already looks at first. */
.ua-profile-header {
  display: flex; flex-direction: column; gap: 6px; padding: 10px 14px;
  background: var(--view-card); border: 1px solid var(--border);
  border-radius: var(--radius); margin-bottom: 8px;
}
.ua-profile-header-top { display: flex; align-items: center; gap: 12px; }
/* Name, email, and the role badge used to stack as three lines in
   their own column; with the badge no longer needing to sit under
   the email (see .ua-badge's own comment), all three read fine as
   one row instead, wrapping to a second line only if the panel is
   too narrow to fit them (min-width:0 lets the email actually
   shrink/wrap rather than forcing the row wider than its container). */
.ua-profile-info {
  display: flex; flex-direction: row; align-items: center; flex-wrap: wrap;
  gap: 6px 10px; flex: 1; min-width: 0;
}
.ua-profile-name { font: 700 14px/1.2 inherit; }
.ua-profile-email { font-size: 11px; color: var(--muted); }
.ua-muted { color: var(--muted); }
.ua-reg-notice {
  background: var(--brand-light); color: var(--brand); border: 1px solid var(--brand);
  border-radius: var(--radius-sm); padding: 0.4rem 0.6rem; font-size: 12px;
  font-weight: 600;
}
/* Six chips (accounts, queries, versions, CVEs, Reddit, StackOverflow,
   stale bots, storage) wrap to 2-3 lines at any normal panel width;
   a smaller font and tighter gap keep that wrap from costing as much
   vertical space. */
.ua-reg-stats {
  display: flex; flex-wrap: wrap; gap: 3px 14px; font-size: 10px;
  color: var(--muted); border-top: 1px solid var(--border); padding-top: 6px;
}
.ua-reg-stats strong { font-size: 11px; color: var(--text); }
.ua-reg-stats .ua-reg-stat-alert { color: var(--cve); }
.ua-admin-header {
  /* flex-direction/text-align/justify-content spelled out explicitly:
     the global `summary { flex-direction: column; ... }` rule above
     only loses on the properties .ua-admin-header actually redeclares
     (display/padding here) — flex-direction wasn't one of them, so
     without this the row stacked vertically and centered instead of
     reading as one compact line (chevron, title, count, Refresh). */
  display: flex; flex-direction: row; align-items: center; text-align: left;
  gap: 0.5rem; padding: 0.25rem 0;
  /* A row with a Refresh button (font-size:12px, padding:4px 10px,
     1px border) is taller than a plain text-only row (Change
     password, Model provider keys, Organization namespaces), so
     the two kinds of rows read as different heights side by side.
     min-height matches that button's own outer height (12px
     line-height + 8px padding + 2px border); align-items:center
     (already set above) then centers a text-only row's shorter
     content within the same guaranteed height instead of it
     shrinking to fit. */
  min-height: 22px;
}
/* Each admin section is a <details>/<summary> using .ua-admin-header
   as the summary row; the global `summary { }` rule above hides the
   native marker, so this adds back a rotating chevron (same pattern
   as .groupHead::before on the feed) as the section's own
   open/closed affordance. Zero margin, relying only on the
   border-bottom for visual separation between closed rows: with
   several of these stacked (the whole Account panel is now built
   from them), every extra px of margin multiplies, and the goal
   when they're all closed is to fit as many as possible without
   scrolling on a laptop screen. */
.ua-admin-details { border-bottom: 1px solid var(--border); margin: 0; }
.ua-admin-details:last-child { border-bottom: none; }
.ua-admin-header::before {
  content: "▶"; font-size: 8px; color: var(--muted); flex-shrink: 0;
  transition: transform .15s ease;
}
details[open] > .ua-admin-header::before { transform: rotate(90deg); }
/* table-layout: fixed + percentage columns, not a content-driven
   auto layout: a per-cell max-width alone only caps how wide ONE
   cell can grow, it doesn't stop the four columns' natural content
   widths from summing past the container on a narrow phone. Fixed
   layout makes each column exactly its declared % of the table's
   own width (which is 100% of its container) regardless of content,
   so the row can never be wider than the space it's given; no
   horizontal scroll needed at any width, only the existing
   ellipsis/nowrap truncation inside each now-guaranteed-narrow cell. */
.ua-se-table { width: 100%; table-layout: fixed; border-collapse: collapse; font-size: 12px; margin-top: 8px; }
.ua-se-table th { text-align: left; padding: 6px 8px; border-bottom: 2px solid var(--border); color: var(--muted); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ua-se-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); vertical-align: top; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-se-table tr:last-child td { border-bottom: none; }
.ua-se-table th:nth-child(1), .ua-se-table td:nth-child(1) { width: 16%; }
.ua-se-table th:nth-child(2), .ua-se-table td:nth-child(2) { width: 44%; }
.ua-se-table th:nth-child(3), .ua-se-table td:nth-child(3) { width: 24%; }
.ua-se-table th:nth-child(4), .ua-se-table td:nth-child(4) { width: 16%; }
.ua-se-anon { color: var(--muted); font-style: italic; }
@media (max-width: 640px) { .ua-se-table { font-size: 11px; } }
.ua-se-type { font-size: 11px; white-space: nowrap; }
.ua-se-type-ask { color: var(--brand); font-weight: 600; }
/* .ua-se-type-ask is now a real <button> (see uaLoadSearchEvents),
   so its own default UA chrome (border/background/padding) needs
   resetting back to reading as plain colored text, same as it did
   as a <span> before -- only the pointer cursor + hover underline
   are new, to actually read as clickable. */
.ua-se-ask-btn { background: none; border: none; padding: 0; margin: 0; font: inherit; cursor: pointer; }
.ua-se-ask-btn:hover { text-decoration: underline; }
.ua-user-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  margin-bottom: 6px; background: var(--surface); font-size: 13px;
}
.ua-user-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ua-user-info strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-user-info .ua-muted { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-user-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.ua-role-sel {
  padding: 3px 6px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font: inherit; font-size: 12px; background: var(--bg); color: var(--text); cursor: pointer;
}
.ua-settings-list { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.ua-settings-row {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); font-size: 13px; flex-wrap: wrap;
}
.ua-settings-info { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; min-width: 0; }
.ua-settings-info strong { font-weight: 600; }
.ua-settings-info .ua-muted { font-size: 11px; }
/* Per-answer Guardrails tab only (askRenderGuardrailsTab): a
   guardrail that actually did something for THIS specific answer,
   not just "is enabled in general". */
.ask-guardrail-used { font-size: 11px; color: var(--ok, #16a34a); margin-top: 2px; }
.ask-guardrail-used a { color: inherit; text-decoration: underline; margin-left: 2px; }
/* Per-answer Feedback Loop tab only (askRenderFeedbackLoopTab): a
   vendor currently flagged by an admin-set threshold - a caution,
   not a "this worked" note, so it gets --warn rather than
   .ask-guardrail-used's --ok green. */
.ask-feedback-flagged { font-size: 11px; color: var(--warn, #b45309); margin-top: 2px; }
.ua-settings-input {
  width: 80px; padding: 4px 6px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font: inherit; font-size: 13px; background: var(--bg); color: var(--text);
}
/* An enum setting's <select> needs real width for its longer option
   labels (e.g. "Multi-agent, feedback loop"); the 80px default above
   (sized for a short number input) would just clip the closed-state
   text. A boolean setting's checkbox needs the opposite: its
   intrinsic small square, not a stretched 80px-wide box. */
select.ua-settings-input { width: auto; max-width: 100%; }
.ua-settings-checkbox { width: 18px; height: 18px; padding: 0; accent-color: var(--brand); cursor: pointer; }
.ua-topbar-chip {
  font-size: 12px; font-weight: 600; white-space: nowrap;
  color: var(--brand); background: var(--brand-light);
  border: 1px solid #aecbfa; border-radius: var(--radius-full);
  padding: 3px 10px; cursor: pointer; flex-shrink: 0;
}
.ua-topbar-chip:hover { background: #e8f0fe; }
.ua-bm-list { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.ua-bm-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: 13px;
}
.ua-bm-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-bm-actions { display: flex; gap: 5px; flex-shrink: 0; }
.ua-org-chip {
  display: inline-block; padding: 1px 7px; border-radius: var(--radius-full);
  font-size: 11px; font-weight: 600; background: var(--brand-light);
  color: var(--brand); border: 1px solid #aecbfa;
}
.ua-why-list { margin: 8px 0 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.ua-why-list li { font-size: 12px; color: var(--muted); display: flex; gap: 8px; align-items: flex-start; }
.ua-why-list li span { flex-shrink: 0; }

/* Installed versions: #ua-inv-add-form's four inputs share .search-input's
   look, but that class's own 28px left padding is reserved for a search
   icon (see the main Ask/component search bars) that none of these four
   plain fields have, and its 13px font, combined with that wasted padding,
   left no room for even a short placeholder to render fully at this
   field's ~130px width (e.g. "version (e.g" got clipped). .ua-inv-field
   drops the font size and reclaims that padding for every field in this
   row; .ua-inv-field-grow (component, the one field worth giving more room
   to) and .ua-inv-field-sm (version/vendor/machine) then split the row's
   width between them, same flex-basis values as before. The vendor/machine
   chips on a saved row reuse .ua-org-chip's own look but in a neutral gray,
   distinct from the version chip's brand color, since they describe the
   entry rather than being the value itself. */
.ua-inv-field { font-size: 11px !important; padding-left: 8px !important; }
.ua-inv-field-grow { flex: 1 1 150px !important; min-width: 0 !important; }
.ua-inv-field-sm { flex: 0 1 130px !important; min-width: 0 !important; }
.ua-inv-vendor-chip, .ua-inv-machine-chip {
  display: inline-block; padding: 1px 7px; border-radius: var(--radius-full);
  font-size: 11px; font-weight: 600; background: var(--chip-bg);
  color: var(--muted); border: 1px solid var(--border);
}
.ua-inv-fetched { font-size: 11px; }

/* ── Admin dashboard (system overview) ─────────────────────
   Cards use flex-wrap so they reflow to a single column on a
   narrow/phone screen with no separate media query needed - each
   card just has a min-width floor to wrap at. */
.ua-dash-grid { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
.ua-dash-card {
  flex: 1 1 150px; min-width: 150px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px 12px;
}
.ua-dash-card-label { font-size: 11px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .3px; }
.ua-dash-card-value { font-size: 20px; font-weight: 700; margin-top: 4px; line-height: 1.2; }
.ua-dash-card-sub { font-size: 11px; color: var(--muted); margin-top: 3px; }
.ua-dash-card-alert .ua-dash-card-value { color: var(--cve); }
.ua-dash-card-ok .ua-dash-card-value { color: var(--new); }
.ua-dash-bar { height: 6px; border-radius: var(--radius-full); background: var(--chip-bg); margin-top: 8px; overflow: hidden; }
.ua-dash-bar-fill { height: 100%; background: var(--brand); border-radius: var(--radius-full); }
.ua-dash-bar-fill.ua-dash-bar-alert { background: var(--cve); }
.ua-dash-bot-group { margin-top: 16px; }
.ua-dash-bot-group-title { font-size: 12px; font-weight: 700; margin-bottom: 6px; display: flex; align-items: center; gap: 6px; }
.ua-bot-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border: 1px solid var(--border); border-left: 3px solid var(--border);
  border-radius: var(--radius-sm); margin-bottom: 5px; background: var(--surface); font-size: 12px;
}
.ua-bot-row-stale   { border-left-color: var(--cve); }
.ua-bot-row-healthy { border-left-color: var(--new); }
.ua-bot-row-nodata  { border-left-color: var(--border); color: var(--muted); }
.ua-bot-row-name { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ua-bot-row-detail { flex-shrink: 0; white-space: nowrap; color: var(--muted); }
@media (max-width: 640px) {
  .ua-dash-card { flex-basis: calc(50% - 5px); min-width: 0; }
  .ua-bot-row { flex-wrap: wrap; gap: 3px 10px; }
  .ua-bot-row-name { flex-basis: 100%; }
}

/* ── Docs view ──────────────────────────────────────────── */
#docsView {
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto;
  background: var(--view-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  scroll-behavior: smooth;
}
@media (max-width: 640px) { #docsView { position: static; height: 80vh; } }
/* Reset feed's global summary/details styles inside docsView */
#docsView summary { padding: 0 !important; background: transparent !important; color: inherit !important; font-weight: inherit !important; font-size: inherit !important; gap: 0 !important; transition: none !important; }
#docsView summary::before { display: none !important; content: none !important; }
#docsView details[open] > summary { background: transparent !important; color: inherit !important; }
/* Docs content: scoped */
#docsView { font-size: 13px; line-height: 1.6; color: #0f172a; }
#docsView .d-wrap { padding: 10px 16px 20px; }
#docsView h2 { font-size: 1rem; font-weight: 700; margin: 0 0 .35rem; color: #0f172a; }
#docsView h3 { font-size: .9rem; font-weight: 700; margin: .4rem 0 .25rem; color: #0f172a; }
#docsView h4 { font-size: .85rem; font-weight: 700; margin: 0 0 .2rem; color: #0f172a; }
#docsView p { margin: .28rem 0; font-size: 13px; color: #0f172a; }
#docsView ul, #docsView ol { margin: .28rem 0; font-size: 13px; padding-left: 1.2em; }
#docsView a { color: #1a73e8; text-decoration: none; }
#docsView a:hover { text-decoration: underline; }
#docsView .muted { color: #64748b; }
#docsView .small { font-size: .85rem; }
#docsView section.block { border: 1px solid #e2e8f0; border-radius: var(--radius); background: var(--view-card); padding: .72rem .78rem; margin-bottom: .72rem; }
#docsView .section-sort-note { color: #64748b; font-size: .84rem; margin: .15rem 0 .45rem; }
#docsView .callout { border: 1px solid #e2e8f0; border-radius: 8px; background: #f8fafc; padding: .55rem .7rem; margin: .45rem 0; }
#docsView .api-grid { display: block; margin-top: .45rem; }
#docsView .endpoint { width: 100%; box-sizing: border-box; border: 1px solid #d9dee3; border-left-width: 6px; border-radius: 6px; margin: 0 0 8px; overflow: hidden; background: var(--view-card); padding: 0; }
#docsView details.endpoint > summary { list-style: none; }
#docsView details.endpoint > summary::-webkit-details-marker { display: none; }
#docsView .endpoint summary.endpoint-head { display: flex !important; flex-direction: row !important; align-items: center !important; gap: .55rem !important; flex-wrap: wrap !important; margin: 0 !important; padding: 7px 10px !important; cursor: pointer !important; border-bottom: 1px solid transparent !important; font-size: 13px !important; }
#docsView details.endpoint[open] summary.endpoint-head { border-bottom-color: #e2e8f0 !important; }
#docsView .endpoint-body { padding: 7px 10px 10px; }
#docsView .endpoint.method-get { border-left-color: #2563eb; }
#docsView .endpoint.method-post { border-left-color: #64748b; }
#docsView .endpoint.method-put { border-left-color: #b45309; }
#docsView .endpoint.method-get summary.endpoint-head { background: rgba(97,175,254,.10) !important; }
#docsView .endpoint.method-post summary.endpoint-head { background: rgba(73,204,144,.10) !important; }
#docsView .endpoint.method-put summary.endpoint-head { background: rgba(252,161,48,.10) !important; }
#docsView details.endpoint[open] summary.endpoint-head { color: #0f172a !important; }
#docsView .method { display: inline-block; min-width: 44px; text-align: center; padding: .2rem .45rem; border-radius: 4px; font-size: .76rem; font-weight: 700; color: #fff !important; border: none; line-height: 1.4; }
#docsView .method.get { background: #2563eb; }
#docsView .method.post { background: #64748b; }
#docsView .method.put { background: #b45309; }
#docsView .path { font-family: Consolas, Monaco, "SFMono-Regular", Menlo, monospace; font-size: .9rem; font-weight: 700; overflow-wrap: anywhere; color: #0f172a; }
#docsView .tag { display: inline-block; padding: .1rem .35rem; border: 1px solid #e2e8f0; border-radius: 999px; font-size: .72rem; background: var(--view-card); margin-right: .3rem; margin-top: .2rem; color: #64748b; }
#docsView table { width: 100%; border-collapse: collapse; margin: .45rem 0 .7rem; table-layout: fixed; font-size: 12px; }
#docsView th, #docsView td { border: 1px solid #e2e8f0; padding: .42rem .5rem; text-align: left; vertical-align: top; word-break: break-word; overflow-wrap: anywhere; color: #0f172a; }
#docsView thead th { background: #f1f5f9; }
#docsView code { font-family: Consolas, Monaco, "SFMono-Regular", Menlo, monospace; font-size: 12px; color: #0f172a; }
#docsView pre { margin: .3rem 0 0; white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; }
#docsView pre code { display: block; background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 6px; padding: .5rem .6rem; font-size: 12px; }
#docsView code.inline { padding: .06rem .25rem; border: 1px solid #e2e8f0; border-radius: 4px; background: #f1f5f9; font-size: 12px; }
#docsView .status { display: inline-block; font-size: .76rem; padding: .16rem .45rem; border-radius: 999px; border: 1px solid #e2e8f0; vertical-align: middle; }
#docsView .status.ok   { background: #f1f5f9; color: #475569; border-color: #e2e8f0; }
#docsView .status.warn { background: #fffbeb; color: #b45309; border-color: #fde68a; }
#docsView .status.err  { background: #fef2f2; color: #b91c1c; border-color: #fca5a5; }
#docsView .note { border-left: 4px solid #cbd5e1; padding-left: .75rem; margin-top: .5rem; color: #64748b; }
#docsView .toplink { display: inline-block; margin-top: .3rem; font-size: .85rem; color: #1a73e8; }
#docsView .mermaid { text-align: center; margin: .8rem 0 1.2rem; overflow-x: hidden; }
/* Mermaid's own computed width lands as an inline style="max-width:
   NNNpx" on the <svg> it renders, which wins over this width:100%
   rule at equal specificity regardless of source order (same root
   cause already documented for the live Ask answer workflow
   diagram, see renderAskWorkflowDiagram's own comment) -- runMermaid
   below clears that inline max-width right after rendering so this
   rule can actually apply and the diagram stretches to fill its
   column instead of rendering narrower than the space available. */
#docsView .mermaid svg { width: 100%; height: auto; }
/* arch-sub: collapsible details blocks inside #d-architecture */
#docsView details.arch-sub { border: 1px solid #e2e8f0; border-radius: 8px; background: var(--view-card); margin-top: .6rem; overflow: hidden; }
#docsView summary.d-arch-sum { list-style: none; display: flex !important; flex-direction: row !important; align-items: center !important; gap: .45rem !important; padding: .58rem .8rem !important; cursor: pointer; font-size: .88rem !important; font-weight: 700 !important; color: #0f172a !important; background: #f1f5f9 !important; border-bottom: 1px solid transparent; transition: background .12s !important; }
#docsView details.arch-sub[open] > summary.d-arch-sum { border-bottom-color: #e2e8f0 !important; }
#docsView summary.d-arch-sum:hover { background: #f1f5f9 !important; }
#docsView summary.d-arch-sum::-webkit-details-marker { display: none !important; }
#docsView summary.d-arch-sum::before { content: '\203A' !important; display: inline-block !important; font-size: 15px !important; line-height: 1 !important; transition: transform .15s !important; }
#docsView details.arch-sub[open] > summary.d-arch-sum::before { transform: rotate(90deg) !important; }
#docsView .arch-sub-body { padding: .55rem .8rem .8rem; }
/* arch-view: nested frontend-view details inside arch-sub */
#docsView details.arch-view { border: 1px solid #e2e8f0; border-radius: 6px; margin: .28rem 0; background: #f8fafc; overflow: hidden; }
#docsView summary.d-arch-view-sum { list-style: none; display: flex !important; flex-direction: row !important; align-items: center !important; gap: .4rem !important; padding: .38rem .6rem !important; cursor: pointer; font-size: .82rem !important; font-weight: 600 !important; color: #0f172a !important; background: transparent !important; transition: background .12s !important; }
#docsView details.arch-view[open] > summary.d-arch-view-sum { background: #f1f5f9 !important; border-bottom: 1px solid #e2e8f0 !important; }
#docsView summary.d-arch-view-sum:hover { background: #f1f5f9 !important; }
#docsView summary.d-arch-view-sum::-webkit-details-marker { display: none !important; }
#docsView summary.d-arch-view-sum::before { content: '\203A' !important; display: inline-block !important; font-size: 13px !important; line-height: 1 !important; transition: transform .15s !important; }
#docsView details.arch-view[open] > summary.d-arch-view-sum::before { transform: rotate(90deg) !important; }
#docsView .arch-view-body { padding: .35rem .62rem .5rem; font-size: .82rem; color: #44505c; line-height: 1.55; }
#docsView .arch-view-body code { font-family: Consolas,Monaco,monospace; font-size: 11px; background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 3px; padding: .05rem .25rem; }
#docsView .endpoint-actions { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 6px; }
#docsView .test-link { display: inline-flex; align-items: center; padding: .26rem .55rem; border: 1px solid #94a3b8; border-radius: 5px; background: #fff; color: #1f2937; font-size: .8rem; font-weight: 600; text-decoration: none; }
#docsView .test-link:hover { background: #f1f5f9; text-decoration: none; }
#docsView .sample-url { display: none; }
#docsView .copy-wrap { position: relative; margin-top: 4px; }
#docsView .copy-wrap .copy-btn { position: absolute; top: 6px; right: 6px; }
#docsView .copy-wrap pre { margin: 0; }
#docsView .copy-btn, #docsView .copy-api-btn, #docsView .d-copy-btn { display: inline-flex; align-items: center; padding: .22rem .5rem; font-size: .76rem; border: 1px solid #94a3b8; border-radius: 5px; background: #fff; color: #1f2937; cursor: pointer; }
#docsView .d-copy-btn { position: absolute; top: 6px; right: 6px; padding: 3px 8px; }
#docsView .d-copylink-btn { font-size: .75rem; padding: 2px 7px; border: 1px solid #cbd5e1; border-radius: 4px; background: #f1f5f9; cursor: pointer; margin-left: 8px; }
#docsView .d-test-link { font-size: .78rem; margin-left: 8px; color: var(--brand); text-decoration: none; }
#docsView .d-test-link:hover { text-decoration: underline; }
#docsView .copy-btn:hover, #docsView .copy-api-btn:hover { background: #f1f5f9; }
#docsView .copy-api-btn { margin-left: auto; font-size: 11px; }
#docsView .kv { margin: .35rem 0 0; padding-left: 1rem; }
#docsView .kv li { margin: .15rem 0; font-size: 12px; }
/* Docs sidebar TOC */
.d-toc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.d-toc a { display: block; padding: 5px 8px; border-radius: 6px; font-size: 12px; color: var(--brand); text-decoration: none; }
.d-toc a:hover { background: var(--brand-light); }
.d-toc a.d-active { background: var(--brand-light); font-weight: 700; }
/* Sidebar live stats widget */
.sb-stat-group { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; margin-bottom: 6px; }
.sb-stat-group:last-child { margin-bottom: 0; }
.sb-stat-head { list-style: none; display: flex; flex-direction: row; align-items: center; gap: 5px; padding: 5px 9px; cursor: pointer; font: 700 10px/1.4 var(--mono); text-transform: uppercase; letter-spacing: .4px; color: var(--muted); background: var(--chip-bg); border-bottom: 1px solid transparent; }
.sb-stat-group[open] > .sb-stat-head { border-bottom-color: var(--border); }
.sb-stat-head::-webkit-details-marker { display: none; }
.sb-stat-head::before { content: '›'; font-size: 12px; display: inline-block; transition: transform .13s; }
.sb-stat-group[open] > .sb-stat-head::before { transform: rotate(90deg); }
.sb-stat-body { padding: 5px 8px 7px; }
.sb-stat-row { display: flex; justify-content: space-between; align-items: center; padding: 2px 0; font-size: 11px; color: #0f172a; border-bottom: 1px solid #f1f5f9; }
.sb-stat-row:last-child { border-bottom: none; }
.sb-stat-row span:first-child { color: var(--muted); }
.sb-stat-row span:last-child { font-weight: 700; color: var(--text); font-family: var(--mono); }
.sb-stat-row.size-row span:last-child { color: #475569; font-size: 10px; }
.sb-stat-divider { border: none; border-top: 1px dashed #e2e8f0; margin: 4px 0; }
/* A plain (non-clickable) group label, same visual weight as
   .sb-stat-head minus its chevron/cursor, used to sub-divide the
   combined Stats section (Types/Summary/Activity/Top searches) into
   labeled blocks without making each one its own extra toggle click
   on top of the outer one. */
.sb-group-label {
  font: 700 10px/1.4 var(--mono); text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); margin: 10px 0 6px;
}
.sb-group-label:first-child { margin-top: 0; }

/* ── Back to top FAB ────────────────────────────────────── */
#backToTop {
  position: fixed; bottom: 24px; right: 20px; z-index: 100;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-md); color: var(--muted); font-size: 18px;
  cursor: pointer; display: none; align-items: center; justify-content: center;
  transition: all .2s; line-height: 1;
}
#backToTop.visible { display: flex; }
#backToTop:hover { background: var(--brand); color: #fff; border-color: var(--brand); box-shadow: none; }
#backToTop:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* ── CVE controls sidebar (aggregates) ─────────────────── */
#cveControls {
  --bad:    #b91c1c;  --bad-bg:  #fef2f2;
  --warn:   #b45309;  --warn-bg: #fffbeb;
  --ok:     #475569;  --ok-bg:   #f1f5f9;
  --info:   #475569;  --info-bg: #f1f5f9;
  --reddit: #475569;  --reddit-bg: #f1f5f9;
  --purple: #475569;
  --chip:   #e8eaed;  --chipText: #3c4043;
  --line:   #dadce0;  --panel:    #ffffff;
  --rad:    10px;
}

/* ── CVE view (scoped) ──────────────────────────────────── */
#cveView {
  /* light-theme token overrides, harmonized with :root's own cold
     Gemini-like palette above; --bad/--warn/--ok/--info/--reddit/
     --purple stay as they were, same "meaning over hue" reasoning as
     :root's own comment. */
  --bg:       #cfd5dc;
  --panel:    #ffffff;
  --text:     #1a1c1e;
  --muted:    #5f6368;
  --brand:    #1a73e8;
  --brand-fg: #ffffff;
  --line:     #dadce0;
  --chip:     #e8eaed;
  --chipText: #3c4043;
  --focus:    #1a73e8;
  --bad:    #b91c1c;  --bad-bg:  #fef2f2;
  --warn:   #b45309;  --warn-bg: #fffbeb;
  --ok:     #475569;  --ok-bg:   #f1f5f9;
  --info:   #475569;  --info-bg: #f1f5f9;
  --reddit: #475569;  --reddit-bg: #f1f5f9;
  --purple: #475569;  --purple-bg: #f1f5f9;
  --link:   #1558b0;
  --shadow: 0 1px 5px rgba(26,28,30,.07), 0 2px 12px rgba(0,0,0,.05);
  --rad:    10px;
  background: var(--bg); color: var(--text);
  font: 14px/1.6 system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  position: sticky;
  top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow: hidden;
  border: 1px solid #e2e8f0;
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
}
/* Panel inside cveView fills remaining height; scroll-list takes the rest */
#cveView .panel { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
#cveView .panel-head, #cveView .src-tabs, #cveView .timeline-controls { flex: 0 0 auto; }
/* Collapsible sections inside #cveView */
#cveView > .cv-details { flex: 0 0 auto; border-bottom: 1px solid var(--line); }
#cveView .panel > .cv-details { flex: 0 0 auto; border-bottom: 1px solid var(--line); }
#cveView .cv-search-bar { flex: 0 0 auto; padding: 8px 12px; border-bottom: 1px solid var(--line); }
#cveView .cv-search-bar .cv-search-input { width: 100%; box-sizing: border-box; }
#cveView .cv-filter-group { display: flex; gap: 8px; flex-wrap: wrap; padding: 8px 12px 10px; }
/* cv-details summary styles (restore after the blanket reset) */
#cveView .cv-details > summary { padding: 7px 12px !important; cursor: pointer !important; display: flex !important; flex-direction: row !important; align-items: center !important; gap: 6px !important; font-size: 11px !important; font-weight: 700 !important; color: var(--muted) !important; text-transform: uppercase !important; letter-spacing: .5px !important; user-select: none; background: transparent !important; }
#cveView .cv-details > summary::before { display: inline !important; content: "▶" !important; font-size: 8px !important; color: var(--muted) !important; transition: transform .2s !important; flex-shrink: 0 !important; }
#cveView .cv-details[open] > summary::before { transform: rotate(90deg) !important; }
/* Suppress inner borders that duplicate the details border-bottom */
#cveView .cv-details .src-tabs { border-bottom: none; }
@media (max-width: 640px) { #cveView { position: static; height: 85vh; } }
/* Reset feed's global summary/details styles inside cveView (not needed in sidebar cveControls) */
#cveView summary { padding: 0 !important; background: transparent !important; color: inherit !important; font-weight: inherit !important; font-size: inherit !important; gap: 0 !important; transition: none !important; }
#cveView summary::before { display: none !important; content: none !important; }
#cveView details[open] > summary { background: transparent !important; color: inherit !important; }
/* Restore legend-toggle and post-summary arrow/styles in both hosts */
.cv-host .legend-toggle { padding: 10px 12px !important; cursor: pointer !important; display: flex !important; flex-direction: row !important; align-items: center !important; gap: 6px !important; }
.cv-host .legend-toggle::before { display: inline !important; content: "▶" !important; font-size: 9px !important; color: var(--muted) !important; transition: transform .2s !important; flex-shrink: 0 !important; }
.cv-host details[open] > .legend-toggle::before { transform: rotate(90deg) !important; }
.cv-host .post-summary { padding: 14px 16px !important; cursor: pointer !important; display: flex !important; flex-direction: row !important; align-items: flex-start !important; gap: 10px !important; }
.cv-host .post-summary::before { display: inline !important; content: "▶" !important; font-size: 9px !important; color: var(--muted) !important; flex-shrink: 0 !important; margin-top: 5px !important; transition: transform .2s !important; }
.cv-host details[open] > .post-summary::before { transform: rotate(90deg) !important; }
.cv-host .cv-page { padding: 12px 14px 48px; }
#cveView .nvd-pipeline { margin: 0; border-radius: 0; border-left: none; border-right: none; border-top: none; border-bottom: none; }
.cv-host #statusBar { font-size:12px;color:var(--muted);padding:6px 0 10px;display:flex;align-items:center;gap:8px; }
.cv-host #statusBar .dot { width:8px;height:8px;border-radius:50%;background:var(--brand);flex-shrink:0;animation:cv-pulse 1.2s ease-in-out infinite; }
.cv-host #statusBar.done .dot { background:var(--ok);animation:none; }
.cv-host #statusBar.error .dot { background:var(--bad);animation:none; }
@keyframes cv-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }
.cv-host #loadProgress { height:3px;background:var(--chip);border-radius:999px;margin-bottom:12px;overflow:hidden;display:none; }
.cv-host #loadProgressFill { height:100%;background:var(--brand);border-radius:999px;transition:width .3s ease; }
.cv-host .main-grid { display:grid;grid-template-columns:300px 1fr;gap:14px;align-items:start; }
@media (max-width:860px) { .cv-host .main-grid { grid-template-columns:1fr; } }
.cv-host .panel { background:var(--panel);border:1px solid var(--line);border-radius:var(--rad);overflow:hidden; }
.cv-host .panel-head { padding:10px 12px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:8px; }
.cv-host .panel-head h2 { margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted); }
.cv-host .panel-head .count-badge { margin-left:auto;font-size:10px;font-weight:700;background:var(--chip);color:var(--chipText);border-radius:999px;padding:1px 7px; }
.cv-host .agg-section { padding:12px; }
.cv-host .agg-section + .agg-section { border-top:1px solid var(--line); }
.cv-host .bar-row { display:flex;align-items:center;gap:8px;margin-bottom:4px;font-size:11px; }
.cv-host .bar-label { flex:0 0 120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.cv-host .bar-track { flex:1;height:8px;background:var(--chip);border-radius:999px;overflow:hidden; }
.cv-host .bar-fill { height:100%;border-radius:999px;background:var(--brand);transition:width .4s ease; }
.cv-host .bar-fill.bad { background:var(--bad); }
.cv-host .bar-fill.warn { background:var(--warn); }
.cv-host .bar-fill.ok { background:var(--ok); }
.cv-host .bar-fill.info { background:var(--info); }
.cv-host .bar-fill.purple { background:var(--purple); }
.cv-host .bar-fill.muted { background:var(--muted); }
.cv-host .bar-fill.brand { background:var(--brand); }
.cv-host .bar-count { flex:0 0 24px;text-align:right;color:var(--muted);font-size:10px; }
.cv-host .pill-list { display:flex;flex-wrap:wrap;gap:5px; }
.cv-host .pill { display:inline-flex;align-items:center;gap:4px;background:var(--chip);color:var(--chipText);border-radius:999px;padding:2px 9px;font-size:10px;font-weight:600; }
.cv-host .pill .pct { color:var(--muted);font-weight:400; }
.cv-host .nvd-badge { display:inline-block;font-size:9px;font-weight:700;border-radius:999px;padding:1px 7px;white-space:nowrap;letter-spacing:.3px; }
.cv-host .nvd-received   { background:var(--info-bg); color:var(--info); }
.cv-host .nvd-awaiting   { background:var(--chip);    color:var(--chipText); }
.cv-host .nvd-undergoing { background:var(--warn-bg); color:var(--warn); }
.cv-host .nvd-enriched   { background:var(--ok-bg);   color:var(--ok); }
.cv-host .nvd-modified   { background:var(--warn-bg); color:var(--warn); }
.cv-host .nvd-deferred   { background:var(--chip);    color:var(--muted); }
.cv-host .nvd-rejected   { background:var(--bad-bg);  color:var(--bad); }
.cv-host .nvd-unknown    { background:var(--chip);    color:var(--muted); }
.cv-host .timeline-controls { padding:8px 12px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:8px;flex-wrap:wrap; }
.cv-host .cv-search-input { flex:1;min-width:120px;border:1px solid var(--line);border-radius:7px;background:var(--bg);color:var(--text);padding:5px 9px;font-size:13px; }
.cv-host .cv-search-input:focus { outline:2px solid var(--focus);outline-offset:2px;border-color:transparent; }
.cv-host .cv-sort-select { border:1px solid var(--line);border-radius:7px;background:var(--bg);color:var(--text);padding:5px 7px;font-size:12px;cursor:pointer; }
.cv-host .cv-sort-select:focus { outline:2px solid var(--focus);outline-offset:2px; }
.cv-host .src-tabs { display:flex;gap:6px;padding:8px 12px;border-bottom:1px solid var(--line);flex-wrap:wrap; }
.cv-host .src-tab { padding:4px 12px;font-size:12px;font-weight:600;border-radius:999px;border:1px solid var(--line);background:var(--bg);color:var(--muted);cursor:pointer;transition:background .15s,color .15s,border-color .15s; }
.cv-host .src-tab:hover { background:var(--chip);color:var(--text); }
.cv-host .src-tab.active { background:var(--brand);color:var(--brand-fg);border-color:var(--brand); }
.cv-host .src-tab .tab-count { font-size:10px;opacity:.8;margin-left:4px; }
.cv-host #postList { list-style:none;margin:0;padding:0; }
.cv-host .post-card { border-bottom:1px solid var(--line); }
.cv-host .post-card:last-child { border-bottom:none; }
.cv-host .post-summary { display:flex;flex-direction:row;align-items:flex-start;gap:10px;padding:14px 16px;cursor:pointer;list-style:none; }
.cv-host .post-summary::-webkit-details-marker { display:none; }
.cv-host .post-summary::before { content:"▶";font-size:9px;color:var(--muted);flex-shrink:0;margin-top:5px;transition:transform .2s; }
.cv-host details[open] > .post-summary::before { transform:rotate(90deg); }
.cv-host .post-meta { flex:1;min-width:0; padding: 6px;}
.cv-host .post-title { font-size:13px;font-weight:600;line-height:1.4;margin-bottom:4px; }
.cv-host .post-title a { color:var(--text);text-decoration:none; }
.cv-host .post-title a:hover { color:var(--link); }
.cv-host .post-chips { display:flex;flex-wrap:wrap;gap:4px;margin-bottom:4px; }
.cv-host .chip { font-size:10px;font-weight:700;border-radius:999px;padding:1px 7px;white-space:nowrap; }
.cv-host .chip.cve     { background:var(--bad-bg);  color:var(--bad); }
.cv-host .chip.sub     { background:var(--reddit-bg);color:var(--reddit); }
.cv-host .chip.sec     { background:var(--bad-bg);  color:var(--bad); }
.cv-host .chip.info    { background:var(--info-bg); color:var(--info); }
.cv-host .chip.ok      { background:var(--ok-bg);   color:var(--ok); }
.cv-host .chip.neutral { background:var(--chip);    color:var(--chipText); }
.cv-host a.chip { text-decoration:none;cursor:pointer; }
.cv-host a.chip:hover { filter:brightness(.92); }
.cv-host .post-row2 { display:flex;gap:10px;align-items:center;font-size:11px;color:var(--muted);flex-wrap:wrap; }
.cv-host .score-bar { display:inline-block;width:32px;height:4px;background:var(--chip);border-radius:999px;vertical-align:middle;overflow:hidden; }
.cv-host .score-fill { height:100%;border-radius:999px;background:var(--ok); }
.cv-host .post-detail { padding:6px 16px 20px 40px; }
.cv-host .detail-description { font-size:12px;color:var(--muted);line-height:1.6;background:var(--chip);border-radius:7px;padding:8px 10px;margin-bottom:12px;white-space:pre-wrap;word-break:break-word; }
.cv-host .tl-section-label { font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.6px;margin-bottom:8px; }
.cv-host .tl-wrap { position:relative;padding-left:20px;margin-bottom:14px; }
.cv-host .tl-wrap::before { content:'';position:absolute;left:6px;top:10px;bottom:10px;width:2px;background:var(--line);border-radius:1px; }
.cv-host .tl-item { position:relative;margin-bottom:0;padding:0 0 12px 0; }
.cv-host .tl-item:last-child { padding-bottom:0; }
.cv-host .tl-dot { position:absolute;left:-16px;top:4px;width:10px;height:10px;border-radius:50%;background:var(--muted);border:2px solid var(--panel);box-shadow:0 0 0 1px var(--muted); }
.cv-host .tl-dot.dot-post     { background:var(--reddit);box-shadow:0 0 0 1px var(--reddit); }
.cv-host .tl-dot.dot-comment  { background:var(--brand); box-shadow:0 0 0 1px var(--brand); }
.cv-host .tl-dot.dot-received { background:var(--info);  box-shadow:0 0 0 1px var(--info); }
.cv-host .tl-dot.dot-awaiting { background:var(--muted); box-shadow:0 0 0 1px var(--muted); }
.cv-host .tl-dot.dot-undergoing { background:var(--warn); box-shadow:0 0 0 1px var(--warn); }
.cv-host .tl-dot.dot-enriched { background:var(--ok);   box-shadow:0 0 0 1px var(--ok); }
.cv-host .tl-dot.dot-modified { background:var(--warn);  box-shadow:0 0 0 1px var(--warn); }
.cv-host .tl-dot.dot-deferred { background:var(--muted); box-shadow:0 0 0 1px var(--muted); }
.cv-host .tl-dot.dot-rejected { background:var(--bad);   box-shadow:0 0 0 1px var(--bad); }
.cv-host .tl-dot.dot-release     { background:var(--purple); box-shadow:0 0 0 1px var(--purple); }
.cv-host .tl-dot.dot-release-cve { background:var(--bad);   box-shadow:0 0 0 1px var(--bad);border-radius:3px; }
.cv-host .tl-item.tl-latest { background:var(--ok-bg);border-left:3px solid var(--ok);border-radius:0 6px 6px 0;padding:5px 8px 5px 0;margin-bottom:3px; }
.cv-host .tl-item.tl-latest .tl-label { color:var(--ok);font-weight:800;font-size:13px; }
.cv-host .tl-item.tl-latest .tl-dot { background:var(--ok);box-shadow:0 0 0 3px var(--ok);width:12px;height:12px;top:5px; }
.cv-host .tl-item.tl-release .tl-label { color:var(--muted);font-weight:500; }
.cv-host .tl-item.tl-release .tl-date { opacity:.7; }
.cv-host .tl-version-loading { font-size:11px;color:var(--muted);padding:5px 0;display:flex;align-items:center;gap:6px; }
.cv-host .tl-version-loading::before { content:'';display:inline-block;width:8px;height:8px;border-radius:50%;border:2px solid var(--muted);border-top-color:var(--brand);animation:cv-spin .8s linear infinite; }
@keyframes cv-spin { to { transform:rotate(360deg); } }
.cv-host .tl-header { display:flex;align-items:center;gap:6px;margin-bottom:2px;flex-wrap:wrap; }
.cv-host .tl-date { font-size:10px;color:var(--muted);flex-shrink:0; }
.cv-host .tl-label { font-size:12px;font-weight:600; }
.cv-host .tl-sublabel { font-size:10px;color:var(--muted); }
.cv-host .tl-body { font-size:11px;color:var(--muted);line-height:1.5;white-space:pre-wrap;word-break:break-word;background:var(--chip);border-radius:6px;padding:6px 8px;margin-top:3px; }
.cv-host .tl-body.reddit-body  { border-left:3px solid var(--reddit); }
.cv-host .tl-body.comment-body { border-left:3px solid var(--brand); }
.cv-host a.cve-highlight { background:var(--bad-bg);color:var(--bad);border-radius:3px;padding:1px 4px;font-family:Consolas,monospace;font-size:10px;font-weight:700;text-decoration:none;white-space:nowrap; }
.cv-host a.cve-highlight:hover { background:var(--bad);color:#fff; }
.cv-host .skeleton { background:linear-gradient(90deg,var(--chip) 25%,var(--line) 50%,var(--chip) 75%);background-size:200% 100%;animation:cv-shimmer 1.4s infinite;border-radius:6px; }
@keyframes cv-shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }
.cv-host .skel-row { height:12px;margin-bottom:6px; }
.cv-host .skel-row.short { width:55%; }
.cv-host .skel-row.long { width:90%; }
.cv-host .skel-card { padding:10px 12px;border-bottom:1px solid var(--line); }
.cv-host .empty-state { text-align:center;padding:30px 16px;color:var(--muted);font-size:13px; }
.cv-host .empty-state .icon { font-size:2rem;margin-bottom:6px; }
.cv-host .legend-toggle { display:flex;flex-direction:row;align-items:center;gap:6px;padding:10px 12px;cursor:pointer;list-style:none;border-bottom:1px solid transparent;transition:border-color .15s; }
.cv-host .legend-toggle::-webkit-details-marker { display:none; }
.cv-host .legend-toggle::before { content:"▶";font-size:9px;color:var(--muted);transition:transform .2s;flex-shrink:0; }
.cv-host details[open] > .legend-toggle::before { transform:rotate(90deg); }
.cv-host details[open] > .legend-toggle { border-bottom-color:var(--line); }
.cv-host .legend-toggle h2 { margin:0;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted); }
.cv-host .legend-body { padding:10px 12px;display:flex;flex-direction:column;gap:0; }
.cv-host .legend-section-title { font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin:10px 0 5px;border-top:1px solid var(--line);padding-top:8px; }
.cv-host .legend-section-title:first-child { margin-top:0;border-top:none;padding-top:0; }
.cv-host .legend-term { display:grid;grid-template-columns:88px 1fr;gap:5px 8px;padding:4px 0;border-bottom:1px solid var(--chip);font-size:11px;line-height:1.4;align-items:baseline; }
.cv-host .legend-term:last-child { border-bottom:none; }
.cv-host .lt-key { font-weight:700;white-space:nowrap;display:flex;align-items:center;gap:4px; }
.cv-host .lt-dot { width:8px;height:8px;border-radius:50%;flex-shrink:0; }
.cv-host .lt-dot.d-info   { background:var(--info); }
.cv-host .lt-dot.d-warn   { background:var(--warn); }
.cv-host .lt-dot.d-ok     { background:var(--ok); }
.cv-host .lt-dot.d-bad    { background:var(--bad); }
.cv-host .lt-dot.d-muted  { background:var(--muted); }
.cv-host .lt-dot.d-reddit { background:var(--reddit); }
.cv-host .lt-dot.d-brand  { background:var(--brand); }
.cv-host .lt-val { color:var(--muted); }
.cv-host .nvd-pipeline { background:var(--panel);border:1px solid var(--line);border-radius:var(--rad);padding:12px 14px 14px;margin-bottom:16px; }
.cv-host .nvd-pipeline-title { font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin-bottom:10px;display:flex;align-items:center;justify-content:space-between;gap:10px; }
.cv-host .nvd-pipeline-range { font-size:11px;font-weight:600;color:var(--brand);text-transform:none;letter-spacing:0;white-space:nowrap; }
.cv-host .nvd-pipeline-flow { display:flex;align-items:stretch;gap:0;flex-wrap:wrap;row-gap:6px; }
.cv-host .npp-arrow { display:flex;align-items:center;color:var(--muted);font-size:18px;font-weight:700;padding:0 4px;flex-shrink:0;user-select:none; }
.cv-host .npp-divider { width:1px;background:var(--line);margin:0 10px;align-self:stretch;flex-shrink:0; }
.cv-host .npp-step { display:flex;flex-direction:column;align-items:center;text-align:center;padding:6px 12px;border-radius:8px;border:1.5px solid var(--line);background:var(--bg);min-width:76px;gap:2px;cursor:default;transition:border-color .15s,box-shadow .15s; }
.cv-host .npp-step:hover { box-shadow:var(--shadow); }
.cv-host .npp-step.s-source  { border-color:var(--reddit); background:var(--reddit-bg); }
.cv-host .npp-step.s-cvelist { border:1.5px dashed var(--muted);background:var(--bg);opacity:.85; }
.cv-host .npp-step.s-info    { border-color:var(--info);  background:var(--info-bg); }
.cv-host .npp-step.s-muted   { border-color:var(--line);  background:var(--bg); }
.cv-host .npp-step.s-warn    { border-color:var(--warn);  background:var(--warn-bg); }
.cv-host .npp-step.s-ok      { border-color:var(--ok);    background:var(--ok-bg); }
.cv-host .npp-step.s-bad     { border-color:var(--bad);   background:var(--bad-bg); }
.cv-host .npp-count { font-size:1.4rem;font-weight:800;line-height:1; }
.cv-host .npp-step.s-source  .npp-count { color:var(--reddit); }
.cv-host .npp-step.s-cvelist .npp-count { color:var(--muted); }
.cv-host .npp-step.s-info    .npp-count { color:var(--info); }
.cv-host .npp-step.s-muted   .npp-count { color:var(--muted); }
.cv-host .npp-step.s-warn    .npp-count { color:var(--warn); }
.cv-host .npp-step.s-ok      .npp-count { color:var(--ok); }
.cv-host .npp-step.s-bad     .npp-count { color:var(--bad); }
.cv-host .npp-label { font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);white-space:nowrap; }
.cv-host .npp-sub   { font-size:9px;color:var(--muted);white-space:nowrap; }
.cv-host .scroll-list { overflow-y:auto;overscroll-behavior:contain; }
#cveView .scroll-list { flex: 1 1 0; min-height: 0; }

/* ── Risk Report view ────────────────────────────────────── */
#dashboardView {
  position: sticky; top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg); overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column;
}
#dashboardView .ri-idle {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1; padding: 32px; text-align: center; color: var(--muted);
}
#dashboardView .ri-idle-icon { font-size: 36px; margin-bottom: 12px; }
#dashboardView .ri-idle-title { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
#dashboardView .ri-idle-sub { font-size: 12px; line-height: 1.5; max-width: 280px; }
#dashboardView .ri-score-bar {
  padding: 16px 20px; flex-shrink: 0; display: flex; align-items: center; gap: 16px;
  border-bottom: 1px solid var(--border);
}
#dashboardView .ri-score-num { font-size: 42px; font-weight: 800; line-height: 1; min-width: 60px; text-align: center; }
#dashboardView .ri-score-info { flex: 1; min-width: 0; }
#dashboardView .ri-score-level { font-size: 15px; font-weight: 700; margin-bottom: 2px; }
#dashboardView .ri-score-comp { font-size: 11px; color: var(--muted); }
#dashboardView .ri-score-rec { font-size: 11px; margin-top: 4px; line-height: 1.4; color: var(--text); }
#dashboardView .ri-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 14px; }
#dashboardView .ri-card {
  background: var(--view-card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 11px 13px;
  display: flex; flex-direction: column; gap: 6px;
}
#dashboardView .ri-card-title { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
#dashboardView .ri-card-body { font-size: 11px; line-height: 1.5; color: var(--text); }
#dashboardView .ri-card-body a { color: var(--brand); text-decoration: none; }
#dashboardView .ri-card-body a:hover { text-decoration: underline; }
#dashboardView .ri-pill { display: inline-block; font-size: 10px; font-weight: 600; padding: 1px 7px; border-radius: 999px; margin: 2px 2px 0 0; }
#dashboardView .ri-pill-red    { background:#fef2f2; color:#b91c1c; border:1px solid #fca5a5; }
#dashboardView .ri-pill-amber  { background:#fffbeb; color:#b45309; border:1px solid #fcd34d; }
#dashboardView .ri-pill-green  { background:#f1f5f9; color:#475569; border:1px solid #e2e8f0; }
#dashboardView .ri-pill-blue   { background:#eff6ff; color:#1d4ed8; border:1px solid #bfdbfe; }
#dashboardView .ri-pill-gray   { background:#f3f4f6; color:#374151; border:1px solid #d1d5db; }
#dashboardView .ri-post-item { font-size:11px; margin-bottom:4px; border-bottom:1px solid var(--border); padding-bottom:4px; }
#dashboardView .ri-post-item:last-child { border-bottom:none; margin-bottom:0; padding-bottom:0; }
#dashboardView .ri-post-link { color:var(--brand); font-weight:500; text-decoration:none; }
#dashboardView .ri-post-link:hover { text-decoration:underline; }
#dashboardView .ri-post-meta { font-size:10px; color:var(--muted); margin-top:1px; }
#dashboardControls .ri-ctrl-label { font-size:11px; color:var(--muted); margin-bottom:3px; }

/* ── Network view ────────────────────────────────────────── */
#networkView {
  padding: 20px; max-width: 700px;
  position: sticky; top: calc(var(--topbar-h) + 16px);
  height: calc(100vh - var(--topbar-h) - 32px);
  overflow-y: auto; overscroll-behavior: contain;
  box-sizing: border-box;
}
@media (max-width: 640px) { #networkView { position: static; height: auto; overflow-y: visible; padding: 12px; } }
#networkView .nk-tabs {
  display: flex; border-bottom: 2px solid var(--border); margin-bottom: 16px;
}
#networkView .nk-tab {
  padding: 8px 18px; background: none; border: none; cursor: pointer;
  font: 600 13px/1 inherit; color: var(--muted);
  border-bottom: 2px solid transparent; margin-bottom: -2px;
  transition: color .15s, border-color .15s;
}
#networkView .nk-tab:hover { color: var(--text); }
#networkView .nk-tab.nk-tab-active { color: var(--brand); border-bottom-color: var(--brand); }
#networkView .nk-tab-panel { display: none; }
#networkView .nk-tab-panel.nk-tab-panel-active { display: block; }
#networkView .nk-form { display: flex; flex-direction: column; gap: 12px; }
#networkView .nk-field { display: flex; flex-direction: column; gap: 4px; }
#networkView .nk-label { font: 600 12px/1 inherit; color: var(--text); }
#networkView .nk-hint { font-size: 10px; color: var(--muted); margin-top: 2px; }
#networkView .nk-input {
  padding: 7px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--text); font: inherit; font-size: 13px;
  width: 100%; box-sizing: border-box;
}
#networkView .nk-input:focus { outline: none; border-color: var(--brand); }
#networkView .nk-textarea { min-height: 80px; resize: vertical; }
#networkView .nk-msg {
  padding: 8px 12px; border-radius: var(--radius-sm);
  font-size: 12px; margin-bottom: 6px; line-height: 1.5;
}
#networkView .nk-msg-error { background: #fef2f2; color: #b91c1c; border: 1px solid #fca5a5; }
#networkView .nk-msg-ok    { background: #f1f5f9; color: #475569; border: 1px solid #e2e8f0; }
#networkView .nk-release-list { display: flex; flex-direction: column; gap: 8px; }
#networkView .nk-release-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
#networkView .nk-release-head {
  display: flex; align-items: center; gap: 8px; padding: 10px 14px; cursor: pointer; flex-wrap: wrap;
}
#networkView .nk-release-head:hover { background: var(--brand-light); }
#networkView .nk-release-ns {
  font-size: 11px; font-weight: 700; color: var(--brand);
  background: var(--brand-light); border: 1px solid #aecbfa;
  border-radius: var(--radius-full); padding: 1px 8px; flex-shrink: 0;
}
#networkView .nk-release-comp { font: 600 13px/1 inherit; flex: 1; min-width: 0; }
#networkView .nk-release-ver  { font-size: 12px; color: var(--muted); white-space: nowrap; }
#networkView .nk-release-meta { font-size: 10px; color: var(--muted); white-space: nowrap; }
#networkView .nk-release-body { border-top: 1px solid var(--border); padding: 12px 14px; display: none; }
#networkView .nk-release-body.open { display: block; }
#networkView .nk-report-item {
  padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 12px;
}
#networkView .nk-report-item:last-child { border-bottom: none; padding-bottom: 0; }
#networkView .nk-outcome-ok      { color: #475569; font-weight: 600; }
#networkView .nk-outcome-issue   { color: #b91c1c; font-weight: 600; }
#networkView .nk-outcome-upgrade { color: #1d4ed8; font-weight: 600; }
#networkView .nk-empty { color: var(--muted); font-size: 12px; text-align: center; padding: 24px 0; }

/* ── Mobile scroll: all views ────────────────────────────────────── */
@media (max-width: 640px) {
  /* Unlock body scroll: all views stack and page scrolls naturally */
  html, body { height: auto; overflow-y: auto; }

  /* Risk Report */
  #dashboardView { position: static; height: auto; overflow: visible; }
  #dashboardView .ri-cards { grid-template-columns: 1fr; }

  /* Docs: position: static so sticky does not clip content */
  #docsView { position: static; height: auto; overflow-y: visible; }

  /* Ack: full height so all content is reachable */
  #ackView { position: static; height: auto; overflow-y: visible; }

  /* CVE: enable touch scroll; flex layout handled by its own media query */
  #cveView { height: auto; min-height: 85vh; overflow: visible; }
  #cveView .panel { overflow: visible; min-height: 0; }
  #cveView .scroll-list { touch-action: pan-y; -webkit-overflow-scrolling: touch; min-height: 55vh; flex: none; }

  /* Changelog */
  #changelogView { overflow-y: visible; }

  /* Touch-scroll hint for iOS */
  #feedPanel, #docsView, #ackView { touch-action: pan-y; -webkit-overflow-scrolling: touch; }
}

/* ── Extracted from inline styles (stage 2) ─────────────────────────
   Generated from static markup. Names are placeholders: rename to
   meaningful component classes as each view is touched. !important keeps the
   old inline-style priority; drop it when a rule becomes a real component rule. The comment on
   each rule is the first element that used it. ─────────────────────── */
.st-1 { padding: 8px 0 0 !important; } /* .ask-toggle-group */
.st-2 { font-size: 11px !important; margin: 0 !important; } /* .ua-muted */
.st-3 { padding-bottom: 10px !important; } /* .sidebar-section */
.st-4 { flex-direction: column !important; gap: 7px !important; } /* <div> */
.st-5 { align-items: center !important; gap: 6px !important; font-size: 12px !important; cursor: pointer !important; } /* <label> */
.st-6 { accent-color: var(--brand) !important; } /* #g-show-versions */
.st-7 { background: #64748b !important; } /* .g-legend-dot */
.st-8 { background: #dc2626 !important; } /* .g-legend-dot */
.st-9 { background: #2563eb !important; } /* .g-legend-dot */
.st-10 { background: #94a3b8 !important; } /* .g-legend-dot */
.st-11 { width: 100% !important; padding: 5px 8px !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; background: var(--bg) !important; color: var(--text) !important; font: inherit !important; font-size: 12px !important; cursor: pointer !important; } /* #g-window */
.st-12 { margin-top: 7px !important; font-size: 10px !important; color: var(--muted) !important; line-height: 1.5 !important; } /* <div> */
.st-13 { font-size: 11px !important; color: var(--muted) !important; line-height: 2 !important; padding-bottom: 8px !important; } /* .sidebar-section */
.st-14 { background: #2563eb !important; width: 13px !important; height: 13px !important; } /* .g-legend-dot */
.st-15 { background: #475569 !important; } /* .g-legend-dot */
.st-16 { background: #b45309 !important; } /* .g-legend-dot */
.st-17 { width: 100% !important; font-size: 12px !important; } /* #g-refreshBtn */
.st-18 { margin-left: auto !important; font: inherit !important; color: var(--muted) !important; } /* .g-iso-count */
.st-19 { font-size: 11px !important; line-height: 1.6 !important; padding-bottom: 8px !important; } /* .sidebar-section */
.st-20 { color: var(--muted) !important; margin-bottom: 4px !important; } /* <div> */
.st-21 { color: var(--muted) !important; } /* #g-isolatedList */
.st-22 { font-size: 11px !important; color: var(--muted) !important; } /* .sidebar-section */
.st-23 { padding-bottom: 6px !important; border-top: 1px solid var(--border) !important; } /* .sidebar-section */
.st-24 { margin-bottom: 6px !important; } /* .sidebar-label */
.st-25 { padding-bottom: 4px !important; } /* .sidebar-section */
.st-26 { font-size: 12px !important; padding: 5px 10px !important; align-items: center !important; gap: 5px !important; } /* .btn */
.st-27 { font-size: 12px !important; color: var(--muted) !important; line-height: 1.6 !important; margin: 0 0 10px !important; } /* <p> */
.st-28 { padding: 10px 14px 6px !important; border-bottom: 1px solid var(--line) !important; } /* <div> */
.st-29 { width: 0% !important; } /* #loadProgressFill */
.st-30 { padding: 10px 14px 16px !important; flex-direction: column !important; gap: 10px !important; } /* <div> */
.st-31 { margin-bottom: 3px !important; } /* .ri-ctrl-label */
.st-32 { font-size: 10px !important; color: var(--muted) !important; line-height: 1.4 !important; } /* <div> */
.st-33 { color: var(--muted) !important; font-size: 10px !important; } /* <span> */
.st-34 { width: 100% !important; box-sizing: border-box !important; } /* #ri-ver-select */
.st-35 { width: 100% !important; } /* #ri-analyze-btn */
.st-36 { font-size: 11px !important; color: var(--muted) !important; margin-top: 2px !important; padding: 0 2px !important; } /* #ri-sidebar-status */
.st-37 { margin-top: 12px !important; border-top: 1px solid var(--border) !important; padding-top: 10px !important; } /* .sidebar-section */
.st-38 { font-size: 11px !important; line-height: 1.8 !important; } /* <div> */
.st-39 { width: 10px !important; height: 10px !important; border-radius: 50% !important; background: #475569 !important; margin-right: 5px !important; vertical-align: middle !important; } /* <span> */
.st-40 { width: 10px !important; height: 10px !important; border-radius: 50% !important; background: #b45309 !important; margin-right: 5px !important; vertical-align: middle !important; } /* <span> */
.st-41 { width: 10px !important; height: 10px !important; border-radius: 50% !important; background: #b91c1c !important; margin-right: 5px !important; vertical-align: middle !important; } /* <span> */
.st-42 { margin-top: 8px !important; margin-bottom: 4px !important; } /* .ri-ctrl-label */
.st-43 { font-size: 10px !important; color: var(--muted) !important; line-height: 1.7 !important; } /* <div> */
.st-44 { font-size: 11px !important; color: var(--muted) !important; line-height: 1.5 !important; margin: 4px 0 0 !important; } /* <p> */
.st-45 { font-size: 11px !important; color: var(--muted) !important; padding: 0 2px !important; } /* #nk-sidebar-status */
.st-46 { padding-bottom: 12px !important; } /* .sidebar-section */
.st-47 { margin-top: 8px !important; } /* .sb-stat-group */
.st-48 { position: relative !important; height: 118px !important; } /* <div> */
.st-49 { margin: 2px 0 0 !important; font-size: 10px !important; color: var(--muted) !important; } /* <p> */
.st-50 { gap: 10px !important; justify-content: center !important; flex-wrap: wrap !important; font-size: 10px !important; color: var(--muted) !important; margin-top: 4px !important; } /* <div> */
.st-51 { color: #2563eb !important; font-size: 12px !important; } /* <span> */
.st-52 { color: #dc2626 !important; font-size: 12px !important; } /* <span> */
.st-53 { color: #64748b !important; font-size: 12px !important; } /* <span> */
.st-54 { color: #475569 !important; font-size: 12px !important; } /* <span> */
.st-55 { color: #0f766e !important; font-size: 12px !important; } /* <span> */
.st-56 { flex-direction: column !important; gap: 6px !important; } /* #top-searches-list */
.st-57 { font-size: 11px !important; font-weight: 600 !important; } /* #g-zoomFit */
.st-58 { gap: 6px !important; align-items: center !important; flex-wrap: wrap !important; margin-left: auto !important; } /* <div> */
.st-59 { font-size: 12px !important; } /* #a-stackSelect */
.st-60 { font-size: 12px !important; padding: 5px 10px !important; } /* #a-addStackBtn */
.st-61 { width: 1px !important; align-self: stretch !important; background: var(--border) !important; margin: 0 2px !important; } /* <span> */
.st-62 { font-size: 12px !important; padding: 5px 14px !important; } /* #a-viewDiagram */
.st-63 { margin-bottom: .35rem !important; } /* <h2> */
.st-64 { margin-bottom: .3rem !important; } /* .small */
.st-65 { margin-bottom: .15rem !important; } /* .small */
.st-66 { margin: .25rem 0 .5rem !important; } /* .small */
.st-67 { margin-top: .55rem !important; grid-template-columns: 1fr 1fr !important; gap: .4rem !important; } /* <div> */
.st-68 { padding: .45rem .6rem !important; } /* .callout */
.st-69 { font-weight: 700 !important; margin: 0 0 .18rem !important; color: #0f172a !important; } /* .small */
.st-70 { margin: 0 !important; } /* .small */
.st-71 { margin: .7rem 0 .3rem !important; font-size: .88rem !important; color: #64748b !important; text-transform: uppercase !important; letter-spacing: .04em !important; } /* <h3> */
.st-72 { font-size: .8rem !important; text-transform: none !important; } /* <code> */
.st-73 { margin: .9rem 0 .3rem !important; font-size: .88rem !important; color: #64748b !important; text-transform: uppercase !important; letter-spacing: .04em !important; } /* <h3> */
.st-74 { margin-top: 10px !important; } /* <p> */
.st-75 { width: 16% !important; } /* <th> */
.st-76 { width: 10% !important; } /* <th> */
.st-77 { width: 20% !important; } /* <th> */
.st-78 { width: 22% !important; } /* <th> */
.st-79 { margin: .2rem 0 .6rem !important; } /* .small */
.st-80 { font-size: .87rem !important; margin: .4rem 0 .28rem !important; } /* <h3> */
.st-81 { font-size: .87rem !important; margin: .55rem 0 .28rem !important; } /* <h3> */
.st-82 { margin: .2rem 0 .55rem !important; } /* .small */
.st-83 { margin: .2rem 0 .45rem !important; } /* .small */
.st-84 { width: 34% !important; } /* <th> */
.st-85 { font-size: .87rem !important; margin: 0 0 .3rem !important; } /* <h3> */
.st-86 { width: 28% !important; } /* <th> */
.st-87 { font-size: .87rem !important; margin: .65rem 0 .3rem !important; } /* <h3> */
.st-88 { width: 50% !important; } /* <th> */
.st-89 { width: 25% !important; } /* <th> */
.st-90 { margin-bottom: .55rem !important; } /* .callout */
.st-91 { font-size: .87rem !important; margin: 0 0 .28rem !important; } /* <h3> */
.st-92 { margin: 0 0 .35rem !important; } /* .small */
.st-93 { margin: .3rem 0 .4rem !important; } /* <table> */
.st-94 { margin: .2rem 0 .5rem !important; } /* .small */
.st-95 { width: 30% !important; } /* <th> */
.st-96 { width: 18% !important; } /* <th> */
.st-97 { margin-top: .5rem !important; } /* .callout */
.st-98 { width: 55% !important; } /* <th> */
.st-99 { margin-top: .45rem !important; } /* .callout */
.st-100 { grid-template-columns: 1fr 1fr !important; gap: .55rem !important; margin-bottom: .55rem !important; } /* <div> */
.st-101 { padding: .6rem .7rem !important; } /* .callout */
.st-102 { font-weight: 700 !important; margin: 0 0 .35rem !important; color: #0f172a !important; font-size: .88rem !important; } /* <p> */
.st-103 { margin: 0 !important; font-size: 12px !important; border: none !important; } /* <table> */
.st-104 { border: none !important; padding: 2px 0 !important; color: #64748b !important; width: 58% !important; } /* <td> */
.st-105 { border: none !important; padding: 2px 0 !important; font-weight: 800 !important; color: #2563eb !important; font-size: 1.1rem !important; } /* #d-stat-versions */
.st-106 { border: none !important; padding: 2px 0 !important; color: #64748b !important; } /* <td> */
.st-107 { border: none !important; padding: 2px 0 !important; font-weight: 700 !important; color: #dc2626 !important; } /* #d-stat-v-cve */
.st-108 { border: none !important; padding: 2px 0 !important; font-weight: 700 !important; color: #475569 !important; } /* #d-stat-v-noncve */
.st-109 { border: none !important; padding: 3px 0 0 !important; color: #64748b !important; } /* <td> */
.st-110 { border: none !important; padding: 3px 0 0 !important; font-weight: 600 !important; color: #475569 !important; font-size: 11px !important; } /* #d-stat-v-size */
.st-111 { border: none !important; padding: 2px 0 !important; font-weight: 700 !important; color: #64748b !important; } /* #d-stat-r-reddit */
.st-112 { padding: .42rem .6rem !important; } /* #d-stats-freshness */
.st-113 { font-weight: 400 !important; opacity: .7 !important; } /* <span> */
.st-114 { max-width: 1100px !important; margin: 0 auto !important; padding: 20px 16px 60px !important; } /* .eval-rewriter-wrap */
.st-115 { margin: 0 0 12px !important; } /* <h2> */
.st-116 { gap: 8px !important; align-items: center !important; flex-wrap: wrap !important; margin-bottom: 12px !important; } /* <div> */
.st-117 { flex: 1 1 320px !important; min-width: 240px !important; } /* #erQuestion */
.st-118 { margin-bottom: 10px !important; } /* #erStatus */
.st-119 { margin: 0 0 16px !important; font-size: 15px !important; font-weight: 700 !important; } /* <h2> */
.st-120 { font-size: 11px !important; margin: 4px 0 0 !important; } /* .ua-muted */
.st-121 { margin: 0 0 12px !important; font-size: 15px !important; font-weight: 700 !important; } /* <h2> */
.st-122 { font-weight: 700 !important; font-size: 13px !important; } /* <span> */
.st-123 { margin-top: 14px !important; } /* #ua-pw-form */
.st-124 { font-weight: 400 !important; font-size: 12px !important; } /* .ua-opt */
.st-125 { font-size: 12px !important; margin: 0 0 10px !important; } /* .ua-muted */
.st-126 { font-weight: 400 !important; } /* #ua-key-anthropic-status */
.st-127 { gap: 6px !important; } /* <div> */
.st-128 { flex: 1 !important; min-width: 0 !important; } /* #ua-key-anthropic */
.st-129 { font-size: 12px !important; padding: 4px 10px !important; margin-left: auto !important; } /* #ua-bm-refresh */
.st-130 { font-size: 12px !important; margin: 8px 0 6px !important; } /* .ua-muted */
.st-131 { font-size: 12px !important; margin: 8px 0 8px !important; } /* .ua-muted */
.st-132 { opacity: .8 !important; } /* <span> */
.st-133 { gap: 6px !important; flex-wrap: wrap !important; margin-bottom: 8px !important; } /* #ua-inv-add-form */
.st-136 { margin-bottom: 8px !important; } /* <details> */
.st-137 { cursor: pointer !important; font-size: 12px !important; color: var(--muted) !important; list-style: none !important; flex-direction: row !important; align-items: center !important; gap: 4px !important; } /* <summary> */
.st-138 { font-size: 10px !important; } /* <span> */
.st-139 { font-size: 11px !important; margin: 0 0 6px !important; } /* .ua-muted */
.st-140 { width: 100% !important; box-sizing: border-box !important; font: 12px/1.5 Consolas,Monaco,monospace !important; resize: vertical !important; } /* #ua-inv-bulk */
.st-141 { font-size: 12px !important; margin-top: 6px !important; } /* #ua-inv-bulk-btn */
.st-142 { font-size: 12px !important; padding: 8px 0 !important; } /* .ua-muted */
.st-143 { font-weight: 700 !important; font-size: 12px !important; margin: 10px 0 2px !important; } /* <p> */
.st-144 { font-size: 12px !important; margin: 0 0 6px !important; } /* .ua-muted */
.st-145 { font-weight: 700 !important; font-size: 12px !important; margin: 16px 0 2px !important; } /* <p> */
.st-146 { font-size: 12px !important; margin: 10px 0 6px !important; } /* .ua-muted */
.st-147 { font-size: 12px !important; margin: 8px 0 10px !important; } /* .ua-muted */
.st-148 { gap: 6px !important; flex-wrap: wrap !important; margin-bottom: 10px !important; } /* #ua-vendor-alias-form */
.st-149 { flex: 1 1 140px !important; min-width: 0 !important; } /* #ua-vendor-alias-input */
.st-150 { border: none !important; border-top: 1px solid var(--border) !important; margin: 16px 0 !important; } /* <hr> */
.st-151 { font-weight: 700 !important; font-size: 13px !important; margin: 0 0 4px !important; } /* <p> */
.st-152 { gap: 6px !important; flex-wrap: wrap !important; } /* #ua-vendor-gapfill-form */
.st-153 { flex: 1 1 200px !important; min-width: 0 !important; } /* #ua-vendor-gapfill-input */
.st-154 { text-align: center !important; padding: 48px 20px !important; } /* #nk-gate */
.st-155 { font-size: 36px !important; margin-bottom: 12px !important; } /* <div> */
.st-156 { font-size: 15px !important; font-weight: 700 !important; margin-bottom: 8px !important; } /* <div> */
.st-157 { font-size: 12px !important; color: var(--muted) !important; max-width: 340px !important; margin: 0 auto 18px !important; line-height: 1.7 !important; } /* <p> */
.st-158 { font-size: 11px !important; color: var(--muted) !important; margin: 0 auto 18px !important; max-width: 300px !important; line-height: 1.6 !important; } /* <p> */
.st-159 { padding: 16px !important; max-width: 680px !important; } /* #nk-main */
.st-160 { color: var(--muted) !important; font-weight: 400 !important; } /* <span> */
.st-161 { align-self: flex-start !important; } /* .btn */
.st-162 { font-size: 32px !important; } /* #emptyStateIcon */
.st-163 { height: 68px !important; } /* .skeleton */
.st-164 { border: 1px solid var(--border) !important; border-radius: var(--radius) !important; padding: 16px !important; background: var(--surface) !important; color: var(--text) !important; max-width: 520px !important; width: min(96vw,520px) !important; } /* #a-metricsDialog */
.st-165 { align-items: center !important; justify-content: space-between !important; gap: 8px !important; margin-bottom: 12px !important; } /* <div> */
.st-166 { padding: 4px 10px !important; } /* .btn */
.st-167 { flex-wrap: wrap !important; gap: 8px !important; font-size: 13px !important; } /* <div> */
.st-168 { padding: 6px 12px !important; border: 1px solid var(--border) !important; border-radius: 8px !important; background: var(--bg) !important; } /* <div> */
.st-169 { padding: 6px 12px !important; border: 1px solid #fca5a5 !important; border-radius: 8px !important; background: #fef2f2 !important; color: #b91c1c !important; } /* <div> */
.st-170 { padding: 6px 12px !important; border: 1px solid #fcd34d !important; border-radius: 8px !important; background: #fffbeb !important; color: #b45309 !important; } /* <div> */
.st-171 { border: 1px solid var(--border) !important; border-radius: var(--radius) !important; padding: 16px !important; background: var(--surface) !important; color: var(--text) !important; max-width: 700px !important; width: min(96vw,700px) !important; } /* #a-codeDialog */
.st-172 { background: #0a1220 !important; color: #f8fafc !important; border: 1px solid var(--border) !important; border-radius: 8px !important; padding: 12px 14px !important; white-space: pre-wrap !important; font: 12px/1.55 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace !important; max-height: 55vh !important; overflow-y: auto; overflow-x: hidden !important; margin: 0 !important; } /* #a-plantumlCode */
.st-173 { gap: 8px !important; margin-top: 10px !important; } /* <div> */
.st-174 { border: 1px solid var(--border) !important; border-radius: var(--radius) !important; padding: 16px !important; background: var(--surface) !important; color: var(--text) !important; max-width: 600px !important; width: min(96vw,600px) !important; } /* #a-detailsDialog */
.st-175 { grid-template-columns: 1fr 1fr !important; gap: 12px !important; font-size: 13px !important; } /* <div> */
.st-176 { background: var(--bg) !important; border: 1px solid var(--border) !important; border-radius: 8px !important; padding: 10px !important; } /* <div> */
.st-177 { font-weight: 700 !important; margin-bottom: 6px !important; } /* <div> */
.st-178 { line-height: 1.7 !important; color: var(--muted) !important; } /* #a-detComponents */
.st-179 { grid-template-columns: 140px 1fr auto !important; gap: 8px !important; align-items: center !important; font-size: 13px !important; } /* <div> */
.st-180 { padding: 7px 10px !important; border: 1px solid var(--border) !important; border-radius: 8px !important; background: var(--bg) !important; color: var(--text) !important; font: inherit !important; font-size: 12px !important; } /* #a-cfgApi */
.st-181 { font-size: 12px !important; color: var(--muted) !important; margin: 10px 0 0 !important; } /* <p> */

/* ── Extracted from inline styles in JS templates (stage 3) ── */
.st-182 { flex: 1 !important; } /* js: <span> */
.st-183 { font-size: 11px !important; margin: 0 !important; } /* js: .ua-muted */
.st-184 { font-size: 10px !important; } /* js: .ua-muted */
.st-185 { opacity: .7 !important; } /* js: .ask-toggle-inline */
.st-186 { font-size: 11px !important; margin: 0 0 6px !important; } /* js: .ua-muted */
.st-187 { flex-direction: column !important; gap: 3px !important; } /* js: <div> */
.st-188 { font-size: 10px !important; margin: 6px 0 3px !important; text-transform: uppercase !important; letter-spacing: .4px !important; } /* js: .ua-muted */
.st-189 { font-size: 12px !important; padding: 8px 0 !important; } /* js: .ua-muted */
.st-190 { font-size: 11px !important; padding: 8px 10px !important; } /* js: .ua-settings-row */
.st-191 { margin: 0 0 10px !important; } /* js: .ask-muted */
.st-192 { font-weight: 700 !important; font-size: 10px !important; text-transform: uppercase !important; letter-spacing: .4px !important; margin: 0 0 4px !important; color: var(--muted) !important; } /* js: <p> */
.st-193 { margin-top: 0 !important; } /* js: .ua-settings-list */
.st-194 { font-weight: 700 !important; font-size: 10px !important; text-transform: uppercase !important; letter-spacing: .4px !important; margin: 12px 0 4px !important; color: var(--muted) !important; } /* js: <p> */
.st-195 { font-weight: normal !important; } /* js: .ask-muted */
.st-196 { font-size: 11px !important; padding: 3px 8px !important; margin: -4px 0 8px !important; } /* js: .btn */
.st-197 { margin-left: auto !important; } /* js: .ask-muted */
.st-198 { font-size: 12px !important; } /* js: .btn */
.st-199 { color: var(--muted) !important; } /* js: <div> */
.st-200 { justify-content: space-between !important; gap: 8px !important; padding: 2px 0 !important; border-bottom: 1px solid var(--border) !important; } /* js: <div> */
.st-201 { overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; } /* js: <span> */
.st-202 { color: var(--muted) !important; flex-shrink: 0 !important; } /* js: <span> */
.st-203 { padding: 4px 10px !important; margin: 3px !important; border-radius: 99px !important; border: 1px solid var(--border) !important; background: var(--surface) !important; color: var(--brand) !important; font-size: 11px !important; text-decoration: none !important; cursor: pointer !important; } /* js: <a> */
.st-204 { flex-direction: column !important; align-items: center !important; justify-content: center !important; height: 100% !important; gap: 14px !important; padding: 24px !important; text-align: center !important; } /* js: <div> */
.st-205 { font-size: 13px !important; color: var(--muted) !important; } /* js: <div> */
.st-206 { max-width: 420px !important; } /* js: <div> */
.st-207 { float: right !important; background: none !important; border: none !important; cursor: pointer !important; font-size: 15px !important; line-height: 1 !important; color: var(--muted) !important; } /* js: <button> */
.st-208 { margin-top: 4px !important; color: var(--muted) !important; } /* js: <div> */
.st-209 { margin-top: 4px !important; } /* js: <div> */
.st-210 { font-size: 10px !important; color: var(--brand) !important; } /* js: <a> */
.st-211 { font-size: 11px !important; margin-bottom: 4px !important; } /* js: <strong> */
.st-212 { font-size: 10px !important; color: var(--muted) !important; white-space: pre-line !important; margin-bottom: 6px !important; } /* js: <div> */
.st-213 { font-size: 10px !important; color: var(--brand) !important; word-break: break-all !important; } /* js: <a> */
.st-214 { font-size: 10px !important; color: var(--muted) !important; } /* js: <span> */
.st-215 { margin: 0 !important; } /* js: .small */
.st-216 { margin-bottom: 16px !important; } /* js: .ask-answer-card */
.st-217 { font-size: 12px !important; margin: 0 !important; } /* js: .ask-muted */
.st-218 { font-size: 12px !important; margin: 0 0 8px !important; } /* js: .ask-muted */
.st-219 { margin-bottom: 0 !important; } /* js: .er-grid */
.st-220 { cursor: pointer !important; } /* js: .ask-answer-label */
.st-221 { margin-top: 8px !important; } /* js: <div> */
.st-222 { font-size: 13px !important; margin: 0 0 4px !important; } /* js: <p> */
.st-223 { font-size: 13px !important; margin: 0 !important; } /* js: <p> */
.st-224 { font-size: 11px !important; color: var(--muted) !important; } /* js: <span> */
.st-225 { align-items: center !important; justify-content: space-between !important; padding: 5px 8px !important; border: 1px solid var(--border) !important; border-radius: var(--radius-sm) !important; background: var(--surface) !important; text-decoration: none !important; color: var(--text) !important; font-size: 12px !important; } /* js: <a> */
.st-226 { font-size: 11px !important; color: var(--muted) !important; margin-left: 8px !important; flex-shrink: 0 !important; } /* js: <span> */
.st-227 { font-weight: 700 !important; } /* js: <span> */
.st-228 { font-size: 11px !important; opacity: .4 !important; } /* js: .npp-arrow */
.st-229 { font-size: 12px !important; color: var(--muted) !important; } /* js: <span> */
.st-230 { margin-bottom: 6px !important; } /* js: <div> */
.st-231 { line-height: 1.5 !important; } /* js: <div> */
.st-232 { margin-top: 8px !important; font-size: 10px !important; color: var(--muted) !important; } /* js: <div> */
.st-233 { margin-bottom: 5px !important; } /* js: <div> */
.st-234 { margin-bottom: 4px !important; } /* js: <div> */
.st-235 { margin-top: 6px !important; } /* js: <div> */
.st-236 { width: 100% !important; border-collapse: collapse !important; font-size: 11px !important; } /* js: <table> */
.st-237 { color: var(--muted) !important; padding: 2px 4px 2px 0 !important; white-space: nowrap !important; } /* js: <td> */
.st-238 { color: var(--muted) !important; padding: 2px 4px 2px 0 !important; } /* js: <td> */
.st-239 { color: var(--brand) !important; } /* js: <a> */
.st-240 { margin-top: 8px !important; padding: 6px 8px !important; background: #fffbeb !important; border-radius: 4px !important; font-size: 10px !important; color: #b45309 !important; } /* js: <div> */
.st-241 { font-size: 12px !important; margin: 0 0 10px !important; color: var(--text) !important; } /* js: <p> */
.st-242 { font-size: 11px !important; margin: 0 0 10px !important; } /* js: <p> */
.st-243 { margin-bottom: 8px !important; } /* js: #nk-reports-' + nkEsc(id) + ' */
.st-244 { font-size: 10px !important; color: var(--muted) !important; margin-top: 2px !important; } /* js: <div> */
.st-245 { border-top: 1px solid var(--border) !important; padding-top: 10px !important; margin-top: 8px !important; } /* js: <div> */
.st-246 { font-size: 11px !important; font-weight: 700 !important; margin-bottom: 8px !important; color: var(--muted) !important; } /* js: <div> */
.st-247 { min-height: 60px !important; margin-bottom: 8px !important; } /* js: #nk-rep-desc-' + releaseId + ' */
.st-248 { font-size: 11px !important; color: var(--muted) !important; margin-top: 5px !important; } /* js: #nk-rep-msg-' + releaseId + ' */
.st-249 { font-size: 12px !important; padding: 4px 10px !important; } /* js: .btn */
.st-250 { width: 55px !important; } /* js: .ua-settings-input */
.st-251 { width: 60px !important; } /* js: .ua-settings-input */
.st-252 { width: 70px !important; } /* js: .ua-settings-input */
.st-253 { font-size: 12px !important; padding: 4px 10px !important; color: var(--cve) !important; border-color: #fca5a5 !important; } /* js: .btn */
.st-254 { font-size: 11px !important; color: var(--muted) !important; padding: 4px 6px !important; } /* js: <span> */
.st-255 { flex: 1 !important; min-width: 0 !important; } /* js: <div> */
.st-256 { font-family: Consolas,Monaco,monospace !important; } /* js: .ua-org-chip */
.st-257 { margin-top: 3px !important; font-size: 11px !important; } /* js: .ua-inv-drift */
.st-258 { font-size: 12px !important; padding: 4px 8px !important; } /* js: .btn */
.st-259 { font-size: 12px !important; padding: 4px 8px !important; color: var(--cve) !important; border-color: #fca5a5 !important; } /* js: .btn */
.st-260 { color: var(--cve) !important; } /* js: <span> */
.st-261 { color: #0f172a !important; } /* js: .ua-org-chip */
.st-262 { white-space: nowrap !important; } /* js: <td> */
.st-263 { font-size: 12px !important; padding: 6px 0 !important; } /* js: .ua-muted */
.st-264 { margin-top: 3px !important; gap: 4px !important; flex-wrap: wrap !important; } /* js: <div> */

/* ── Visibility utilities (replace inline display styles) ────────────
   !important keeps the old inline-style priority. Toggle with setDisplay(). ─── */
.u-hide { display: none !important; }
.u-show-block { display: block !important; }
.u-show-flex { display: flex !important; }
.u-show-grid { display: grid !important; }
.u-show-inline-block { display: inline-block !important; }
.u-show-inline-flex { display: inline-flex !important; }

/* ── Runtime values (set from JS as custom properties, styled here) ──── */
.rt-bg { background: var(--rt-bg) !important; }
.rt-c { color: var(--rt-c) !important; }
.rt-w { width: var(--rt-w, 0) !important; }
.u-bold { font-weight: 700 !important; }
.u-pos-rel { position: relative !important; }
.u-max-none { max-width: none !important; }
.a-fit { width: var(--rt-fit-w) !important; height: var(--rt-fit-h) !important; margin: auto !important; }
.link-dotted { color: inherit !important; text-decoration: underline dotted !important; }
.msg-muted { color: #475569 !important; }
.msg-err { color: #b91c1c !important; }
.ua-cadence-reset-btn { font-size: 11px !important; padding: 4px 8px !important; }
.ua-inline-input { font-size: 12px; padding: 3px 6px; border: 1px solid var(--border); border-radius: var(--radius-sm); width: 100%; box-sizing: border-box; }
.ua-inline-btn { font-size: 12px !important; padding: 4px 8px !important; margin-top: 4px !important; }
.ua-inline-btn-2 { margin-left: 4px !important; }
.ua-inline-wrap { flex: 1; min-width: 0; }
.shared-banner { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 16px; font-size: 12px; box-shadow: var(--shadow-md); z-index: 9999; color: var(--muted); }
.fault-bar { position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 99999; max-width: min(92vw, 560px); display: flex; gap: 10px; align-items: center; padding: 8px 12px; border: 1px solid var(--cve, #b91c1c); border-radius: 3px; background: var(--surface, #fff); color: var(--text, #0f172a); font: 13px/1.4 system-ui, sans-serif; box-shadow: 0 2px 8px rgba(15, 23, 42, .12); }
.fault-dismiss { border: 1px solid var(--border, #e2e8f0); background: none; border-radius: 3px; padding: 2px 8px; cursor: pointer; font: inherit; }

/* ── Account page: sub-tabs, section cards and the server alert list ──
   Regroups the admin sections into tabs so the page is not one long list. ── */
.ua-tab-hidden { display: none !important; }
.ua-subtabs { margin: 14px 0 12px; flex-wrap: wrap; }
.ua-subtabs .ua-tab { padding: 8px 14px; }
#ua-profile-panel details.ua-admin-details { border: 1px solid var(--border); border-radius: 8px; background: var(--surface); margin: 0 0 10px; padding: 0 14px; }
#ua-profile-panel details.ua-admin-details[open] { padding-bottom: 12px; }
#ua-profile-panel .ua-admin-header { padding: 12px 0; }
.ua-badge-count { display: inline-block; min-width: 16px; padding: 0 5px; margin-left: 4px; border-radius: 8px; background: #dc2626; color: #fff; font-size: 11px; line-height: 16px; text-align: center; }
.ua-alerts-note { font-size: 12px; margin: 0 0 8px; }
.ua-alerts-list { display: flex; flex-direction: column; }
.ua-alert-row { display: grid; grid-template-columns: 10px 175px 1fr; gap: 10px; align-items: start; padding: 8px 0; border-top: 1px solid var(--border); font-size: 13px; }
.ua-alert-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; background: var(--muted); }
.ua-alert-critical .ua-alert-dot { background: #dc2626; }
.ua-alert-warn .ua-alert-dot { background: #d97706; }
.ua-alert-ok .ua-alert-dot { background: #16a34a; }
.ua-alert-critical .ua-alert-msg { font-weight: 600; }
.ua-alert-time { color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .ua-alert-row { grid-template-columns: 10px 1fr; } .ua-alert-time, .ua-alert-msg { grid-column: 2; } }

/* ── Visits: chart card at the top of the admin view, and the Visits tab ── */
.ua-visits-top { margin: 14px 0 0; padding: 10px 14px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; }
.ua-visits-top-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; font-size: 13px; }
.ua-visits-chart-box { position: relative; height: 200px; }
.ua-visits-days { font-size: 12px; padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--text); margin-left: auto; margin-right: 8px; }
.ua-visits-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin: 6px 0 12px; }
.ua-visits-card { border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px; }
.ua-visits-card b { display: block; font-size: 22px; line-height: 1.2; }
.ua-visits-card span { font-size: 12px; color: var(--muted); }
.ua-visits-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; margin-bottom: 12px; }
.ua-visits-cols h4, .ua-visits-h { margin: 0 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }
.ua-visits-table { overflow-x: hidden; }
.ua-data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ua-data-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .3px; color: var(--muted); font-weight: 600; padding: 4px 8px 4px 0; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ua-data-table td { padding: 5px 8px 5px 0; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ua-data-table .ua-num { text-align: right; padding-right: 0; padding-left: 8px; font-variant-numeric: tabular-nums; }
.ua-mono { font-family: Consolas, ui-monospace, monospace; }
.ua-visits-note { font-size: 12px; margin: 10px 0 0; }
.ua-data-table tr.ua-row-today td { background: rgba(22, 163, 74, 0.10); }
.ua-visits-today-key { margin-left: 8px; padding: 1px 8px; border-radius: 8px; background: rgba(22, 163, 74, 0.10); color: #166534; font-size: 11px; text-transform: none; letter-spacing: 0; font-weight: 500; }
.ua-data-table .ua-num + td { padding-left: 10px; }

/* Visits tables: compact, wrap instead of scrolling sideways */
.ua-visits-table { overflow-x: visible; }
.ua-data-table { font-size: 12px; }
.ua-data-table th { font-size: 10px; white-space: normal; padding-right: 6px; }
.ua-data-table td { white-space: normal; overflow-wrap: anywhere; padding: 4px 6px 4px 0; }
.ua-data-table .ua-num { white-space: nowrap; }
.ua-visits-cols { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
@media (max-width: 900px) { .ua-visits-cols { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) { #ua-visits-visitors tr > :nth-child(4), #ua-visits-visitors tr > :nth-child(6), #ua-visits-visitors tr > :nth-child(7) { display: none; } }

/* ── Collapsible sidebar (desktop) ─────────────────────────────────────────
   The sidebar shrinks to a slim rail that keeps the collapse toggle and the
   signed-in status dot; the main column takes the freed space (body padding
   and the sticky ask header follow --sidebar-w). Below 900px the sidebar is
   the slide-in drawer, so none of this applies. */
.sidebar-collapse-btn { display: none; }
@media (min-width: 900px) {
  body { --sidebar-w: 300px; }
  body.sidebar-collapsed { --sidebar-w: 56px; }
  #sidebar { width: var(--sidebar-w); }
  .sidebar-collapse-btn { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 1px solid transparent; border-radius: 6px; background: none; color: var(--muted); cursor: pointer; flex-shrink: 0; }
  .sidebar-collapse-btn:hover { background: var(--chip-bg); color: var(--text); }
  .sidebar-collapse-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
  .sidebar-collapse-btn svg { width: 16px; height: 16px; }
  body.sidebar-collapsed .sidebar-collapse-btn svg { transform: rotate(180deg); }
  body.sidebar-collapsed #sidebar > :not(#sidebarFooter) { display: none !important; }
  body.sidebar-collapsed #sidebarFooter { flex-direction: column; align-items: center; justify-content: flex-end; gap: 10px; padding: 10px 0; }
  body.sidebar-collapsed #sidebarFooter .brand,
  body.sidebar-collapsed #sidebarFooter .top-signin-btn,
  body.sidebar-collapsed #sidebarFooter .ua-topbar-chip { display: none !important; }
}
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
  body, #sidebar { transition: padding-left .2s ease, width .2s ease; }
}

/* Signed-in status dot: a real button (opens Account) with a 24px target. Filled
   green = signed in, hollow gray ring = signed out, so the state does not rely on
   color alone; the accessible name says it in words. */
button.auth-dot { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer; }
button.auth-dot::before { content: ""; box-sizing: border-box; width: 10px; height: 10px; border-radius: 50%; }
button.auth-dot.auth-dot-on::before { background: #1e8e3e; }
button.auth-dot.auth-dot-off::before { background: transparent; border: 2px solid var(--muted); }
button.auth-dot:hover { background: var(--chip-bg); }
button.auth-dot:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
@media (pointer: coarse) { button.auth-dot { width: 40px; height: 40px; } }
