/* The hidden attribute must always win: without !important, any
   author rule that sets display (e.g. .filter-bar { display: flex })
   silently overrides it and "hidden" elements stay on screen. */
[hidden] {
  display: none !important;
}
/* ============================================================
   ZeroQuarry — CSS-variable driven theme
   ============================================================ */

/* ---- Theme variables ------------------------------------------ */
/* The palette itself lives in the vendored design system (--zq-* tokens,
   loaded before this file); the aliases below re-export it under the
   historic --bg-* / --text-* / --sev-* names so existing rules keep
   working. Per-tenant branding tokens (--dark-* / --light-*, injected per
   request by base.html) still take precedence over the default palette. */
:root, [data-theme="dark"] {
  /* Native dropdowns / scrollbars / date pickers match the theme. */
  color-scheme: dark;
  --bg-body:      var(--dark-account-page-bg, var(--zq-color-bg-body));
  --bg-surface:   var(--dark-account-sidebar-bg, var(--zq-color-bg-surface));
  --bg-highlight: var(--dark-account-highlight, var(--zq-color-bg-highlight));
  --bg-surface2:  var(--zq-color-bg-surface-2);
  --bg-inset:     var(--zq-color-bg-inset);
  --bg-hover:     var(--zq-color-bg-hover);
  --border:       var(--zq-color-border-base);
  --border-light: var(--zq-color-border-subtle);
  --text:         var(--dark-account-text-primary, var(--zq-color-text-base));
  --text-heading: var(--dark-account-text-primary, var(--zq-color-text-heading));
  --text-muted:   var(--dark-account-text-secondary, var(--zq-color-text-muted));
  --text-code:    var(--zq-color-text-code);
  --link:         var(--zq-color-link-base);
  --accent:       var(--dark-accent, var(--zq-color-accent-base));
  --accent-hover: var(--dark-accent-hover, var(--zq-color-accent-hover));
  --btn-bg:       var(--zq-color-control-bg);
  --btn-border:   var(--zq-color-control-border);
  --btn-hover:    var(--zq-color-control-hover);
  --input-bg:     var(--zq-color-control-input-bg);
  --input-border: var(--zq-color-control-input-border);
  --warn-bg:      var(--zq-color-notice-warn-bg);
  --warn-border:  var(--zq-color-notice-warn-border);
  --warn-text:    var(--zq-color-notice-warn-text);
  --error:        var(--zq-color-status-danger);
  --error-pre-bg: var(--zq-color-notice-error-bg);
  --error-pre-brd:var(--zq-color-notice-error-border);
  --success:      var(--zq-color-status-success);
  --running:      var(--zq-color-status-warning);
  --sev-critical-bg: var(--dark-sev-critical-bg, var(--zq-color-severity-critical-bg));
  --sev-critical-fg: var(--dark-sev-critical-fg, var(--zq-color-severity-critical-fg));
  --sev-high-bg:     var(--dark-sev-high-bg, var(--zq-color-severity-high-bg));
  --sev-high-fg:     var(--dark-sev-high-fg, var(--zq-color-severity-high-fg));
  --sev-medium-bg:   var(--dark-sev-medium-bg, var(--zq-color-severity-medium-bg));
  --sev-medium-fg:   var(--dark-sev-medium-fg, var(--zq-color-severity-medium-fg));
  --sev-low-bg:      var(--dark-sev-low-bg, var(--zq-color-severity-low-bg));
  --sev-low-fg:      var(--dark-sev-low-fg, var(--zq-color-severity-low-fg));
  --sev-info-bg:     var(--dark-sev-info-bg, var(--zq-color-severity-info-bg));
  --sev-info-fg:     var(--dark-sev-info-fg, var(--zq-color-severity-info-fg));
  --scan-node:       var(--zq-color-brand-node);

  /* ---- Previously referenced but never defined ---------------------
     These names were used with var() but had no definition anywhere, so
     they silently fell back to inherit / currentColor (or to the literal
     fallback in the var() call). They are aliases, so the value is resolved
     at use time and follows the active theme. ---- */
  --text-primary:   var(--text);
  --text-secondary: var(--text-muted);
  --text-faint:     var(--text-muted);
  --bg-subtle:      var(--bg-surface2);
  --bg-elevated:    var(--bg-surface);
  --bg-card:        var(--bg-surface);
  --page-bg:        var(--bg-body);
  --bg:             var(--bg-body);
  --highlight-color:var(--bg-highlight);
  --ok:             var(--success);
  --danger:         var(--error);
  --warning:        var(--warn-text);
  --sev-high:       var(--sev-high-fg);
  --sev-info:       var(--sev-info-fg);
  --card-stroke:    var(--text-muted);
  --accent-contrast:var(--zq-color-accent-contrast);
  --accent-soft:    var(--zq-color-accent-soft);
  --shadow-lg:      none;
  --stage-progress: 0%;
}

[data-theme="light"] {
  color-scheme: light;
  --bg-body:      var(--light-account-page-bg, var(--zq-color-bg-body));
  --bg-surface:   var(--light-account-sidebar-bg, var(--zq-color-bg-surface));
  --bg-highlight: var(--light-account-highlight, var(--zq-color-bg-highlight));
  --bg-surface2:  var(--zq-color-bg-surface-2);
  --bg-inset:     var(--zq-color-bg-inset);
  --bg-hover:     var(--zq-color-bg-hover);
  --border:       var(--zq-color-border-base);
  --border-light: var(--zq-color-border-subtle);
  --text:         var(--light-account-text-primary, var(--zq-color-text-base));
  --text-heading: var(--light-account-text-primary, var(--zq-color-text-heading));
  --text-muted:   var(--light-account-text-secondary, var(--zq-color-text-muted));
  --text-code:    var(--zq-color-text-code);
  --link:         var(--zq-color-link-base);
  --accent:       var(--light-accent, var(--zq-color-accent-base));
  --accent-hover: var(--light-accent-hover, var(--zq-color-accent-hover));
  --btn-bg:       var(--zq-color-control-bg);
  --btn-border:   var(--zq-color-control-border);
  --btn-hover:    var(--zq-color-control-hover);
  --input-bg:     var(--zq-color-control-input-bg);
  --input-border: var(--zq-color-control-input-border);
  --warn-bg:      var(--zq-color-notice-warn-bg);
  --warn-border:  var(--zq-color-notice-warn-border);
  --warn-text:    var(--zq-color-notice-warn-text);
  --error:        var(--zq-color-status-danger);
  --error-pre-bg: var(--zq-color-notice-error-bg);
  --error-pre-brd:var(--zq-color-notice-error-border);
  --success:      var(--zq-color-status-success);
  --running:      var(--zq-color-status-warning);
  --sev-critical-bg: var(--light-sev-critical-bg, var(--zq-color-severity-critical-bg));
  --sev-critical-fg: var(--light-sev-critical-fg, var(--zq-color-severity-critical-fg));
  --sev-high-bg:     var(--light-sev-high-bg, var(--zq-color-severity-high-bg));
  --sev-high-fg:     var(--light-sev-high-fg, var(--zq-color-severity-high-fg));
  --sev-medium-bg:   var(--light-sev-medium-bg, var(--zq-color-severity-medium-bg));
  --sev-medium-fg:   var(--light-sev-medium-fg, var(--zq-color-severity-medium-fg));
  --sev-low-bg:      var(--light-sev-low-bg, var(--zq-color-severity-low-bg));
  --sev-low-fg:      var(--light-sev-low-fg, var(--zq-color-severity-low-fg));
  --sev-info-bg:     var(--light-sev-info-bg, var(--zq-color-severity-info-bg));
  --sev-info-fg:     var(--light-sev-info-fg, var(--zq-color-severity-info-fg));
  --scan-node:       var(--zq-color-brand-node);
}

/* ---- Reset-ish + base ------------------------------------------ */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Hash links and programmatic scrolls land below the sticky global topbar. */
html { scroll-padding-top: 4rem; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
               Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
  background: var(--bg-body);
  color: var(--text);
  line-height: 1.5;
}
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
code, .mono { font-family: var(--zq-font-family-mono); font-size: 0.92em; color: var(--text-code); }
.small { font-size: 0.85em; }
.muted { color: var(--text-muted); }
pre { overflow-x: auto; }

/* ---- Form controls ---------------------------------------------
   Element-level adoption of the design system's form primitives
   (vendor forms.css: .zq-input / .zq-select / .zq-textarea). Every
   bare text-ish control gets the primitive's control treatment, which
   let the per-family restyle blocks (scan-form, disc-form, login…)
   collapse to their layout residue. Layout stays element-default:
   pages that want the primitive's block/full-width behaviour class
   the control .zq-input / .zq-select / .zq-textarea explicitly, and
   sizing overrides remain per-family. Composite widget inputs (filter
   bars, chat, pickers) keep their own inset treatment via
   --input-bg, the control-input-bg role the primitive reserves. */
input[type="text"], input[type="password"], input[type="url"],
input[type="email"], input[type="search"], input[type="tel"],
input[type="date"], input[type="number"], select, textarea {
  padding: var(--zq-space-2) var(--zq-space-3);
  background: var(--zq-color-control-bg);
  border: var(--zq-border-width-hairline) solid var(--zq-color-control-border);
  border-radius: var(--zq-radius-md);
  color: var(--zq-color-text-base);
  font: inherit;
  font-size: var(--zq-font-size-3);
}
textarea { resize: vertical; }
input[type="text"]:focus-visible, input[type="password"]:focus-visible,
input[type="url"]:focus-visible, input[type="email"]:focus-visible,
input[type="search"]:focus-visible, input[type="tel"]:focus-visible,
input[type="date"]:focus-visible, input[type="number"]:focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: var(--zq-border-width-thick) solid var(--zq-color-accent-base);
  outline-offset: -1px;
}
input[disabled], select[disabled], textarea[disabled],
input[aria-disabled="true"], select[aria-disabled="true"],
textarea[aria-disabled="true"] {
  opacity: var(--zq-opacity-disabled);
  cursor: not-allowed;
}

/* ---- App shell / sidebar -------------------------------------- */
.app-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  grid-template-rows: auto 1fr;
}
body.sidebar-collapsed .app-shell {
  grid-template-columns: 76px minmax(0, 1fr);
}
.global-topbar {
  grid-column: 2;
  grid-row: 1;
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  padding: 0.55rem 1rem;
  background: var(--bg-body);
  border-bottom: 1px solid var(--border);
}
.mobile-sidebar-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.35rem;
  height: 2.35rem;
  margin-right: 0.65rem;
  border-radius: 10px;
  color: var(--text-muted);
}
.mobile-sidebar-toggle:hover {
  background: var(--bg-hover);
  color: var(--text);
  text-decoration: none;
}
.sidebar {
  grid-column: 1;
  grid-row: 1 / span 2;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.2rem 1rem;
  background: linear-gradient(180deg, var(--bg-surface), var(--bg-surface2));
  border-right: 1px solid var(--border);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}
.sidebar-brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.brand {
  font-weight: 700; letter-spacing: 0.05em; font-size: 1.1rem;
  color: var(--text-heading);
  display: inline-flex;
  align-items: center;
  min-width: 0;
}
.brand-wordmark {
  max-height: 2rem;
  max-width: 100%;
  width: auto;
  height: auto;
  display: block;
  object-fit: contain;
}
/* Dark + light wordmark variants render together; the inactive one is
   hidden via the `data-theme` attribute on <html>, which base.html keeps
   in sync on theme switches. When only one variant is uploaded the other
   simply isn't in the DOM, so this is also harmless. */
[data-theme="dark"] .brand-wordmark--light,
[data-theme="light"] .brand-wordmark--dark {
  display: none !important;
}
body.sidebar-collapsed .brand-wordmark {
  max-height: 1.6rem;
  max-width: 2.4rem;
}
.wordmark-preview {
  display: inline-block;
  max-height: 2.5rem;
  max-width: 16rem;
  vertical-align: middle;
  background: var(--bg-surface2);
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
}
/* Branding admin page — three slot grid with theme-tinted preview frames
   so admins can see the dark logo against a dark surface, the light logo
   against a light surface, and the PDF logo against white. */
.branding-wordmark-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 1rem;
  margin-top: 0.75rem;
}
.branding-wordmark-slot {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
  background: var(--bg-surface);
}
.branding-wordmark-slot h3 {
  margin: 0 0 0.25rem 0;
  font-size: 1rem;
}
.wordmark-preview-frame {
  display: inline-block;
  border-radius: 6px;
  border: 1px solid var(--border);
  padding: 0.35rem 0.6rem;
}
.wordmark-preview-frame--dark   { background: var(--bg-surface); }
.wordmark-preview-frame--light  { background: #ffffff; }
.wordmark-preview-frame--pdf    { background: #ffffff; }
.wordmark-preview-frame .wordmark-preview {
  background: transparent;
  border: none;
  padding: 0;
}
.branding-agent-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 1rem;
  margin-top: 0.75rem;
}
.branding-agent-slot {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.85rem;
  align-items: start;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
  background: var(--bg-surface);
}
.branding-agent-preview {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  color: var(--text);
  font-weight: 700;
}
.branding-agent-preview img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.branding-agent-slot h3 {
  margin: 0 0 0.25rem 0;
  font-size: 1rem;
}
.sidebar-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  color: var(--text-muted);
  flex: 0 0 auto;
}
.sidebar-toggle:hover {
  background: var(--bg-hover);
  text-decoration: none;
  color: var(--text);
}
.sidebar-toggle-closed {
  display: none;
}
/* Close (×) button for the mobile drawer. Desktop hides it; the ≤980px
   block near the end of this file shows it instead of the chevron. */
.sidebar-drawer-close {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  color: var(--text-muted);
  flex: 0 0 auto;
}
.sidebar-drawer-close:hover {
  background: var(--bg-hover);
  text-decoration: none;
  color: var(--text);
}
.sidebar-meta {
  transition: opacity 0.15s ease;
}
.sidebar-top { display: flex; flex-direction: column; gap: 0.35rem; }
.sidebar-nav {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  /* Condensed from 1.1rem: each section already pays its own inner gap, so
     the two combined made ~18px of dead space per item boundary. Vertical
     room is the scarce resource here — every rem saved is another project
     row the operator can see without scrolling the nav. */
  gap: 0.45rem;
  min-height: 0;
  overflow-y: auto;
  padding-right: 0.2rem;
}
.sidebar-section { display: flex; flex-direction: column; gap: 0.15rem; }
/* Divider between the work group and the account group. Not a section, so
   it does not inherit the section gap on both sides. */
.sidebar-group-divider {
  height: 1px;
  margin: 0.1rem 0;
  background: var(--border);
  flex: 0 0 auto;
}
/* The nav scrolls only as a last resort; normally the project list is
   the element that yields: it keeps its content height when there is
   room and shrinks (scrolling internally) when the viewport is short,
   so the other sections and .sidebar-bottom stay put. */
.sidebar-nav > .sidebar-section,
.sidebar-bottom { flex-shrink: 0; }
/* More specific than the flex-shrink:0 rule above on purpose — the
   projects section is the one that yields. The bottom padding matters now
   that the rhythm is condensed: the list can scroll-clip mid-row, and
   without it the last visible project reads as part of the next item. */
.sidebar-nav > .sidebar-section-projects {
  flex: 0 1 auto;
  min-height: 0;
  padding-bottom: 0.4rem;
}
.sidebar-section-head {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.sidebar-section-head .sidebar-link-parent {
  flex: 1 1 auto;
  min-width: 0;
}
.sidebar-fold-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-right: 0.15rem;
  border-radius: 999px;
  color: var(--text-muted);
  flex: 0 0 auto;
}
.sidebar-fold-toggle:hover {
  background: var(--bg-hover);
  color: var(--text);
  text-decoration: none;
}
.sidebar-fold-toggle .material-symbols-outlined {
  font-size: 1.25rem;
  transition: transform 0.15s ease;
}
/* Unfolded = chevron points up (click to fold); folded = down. */
body:not(.projects-folded) .sidebar-fold-toggle .material-symbols-outlined {
  transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) {
  .sidebar-fold-toggle .material-symbols-outlined { transition: none; }
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  /* Condensed from 0.45rem: at ~38px per row the sidebar could show only a
     handful of projects at a laptop viewport. */
  padding: 0.3rem 0.65rem;
  border-radius: 8px;
  color: var(--text);
}
.sidebar-link:hover { background: var(--bg-hover); text-decoration: none; }
.sidebar-link.active {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--text-heading);
}
.sidebar-link.active-project {
  background: var(--bg-highlight);
  color: var(--text-heading);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 24%, transparent);
}
.sidebar-link.active-project:hover {
  background: color-mix(in srgb, var(--bg-highlight) 88%, var(--bg-hover));
}
.sidebar-link-parent { font-weight: 600; }
.sidebar-icon, .material-symbols-outlined {
  font-family: "Material Symbols Outlined";
  font-weight: 400;
  font-style: normal;
  font-size: 1.4em;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  font-feature-settings: "liga";
  -webkit-font-feature-settings: "liga";
  -webkit-font-smoothing: antialiased;
}

.material-symbols-outlined.sidebar-icon {
  font-size: 1.15rem;
  line-height: 1;
  flex: 0 0 auto;
}
.sidebar-text {
  min-width: 0;
}
.sidebar-badge {
  /* count pill: the chip look is the design system's .zq-badge; this only
     keeps the sidebar-specific placement */
  margin-left: 0.45rem;
}
.sidebar-icon-link {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.35rem;
  height: 2.35rem;
  border-radius: 10px;
  color: var(--text-muted);
}
.sidebar-icon-link:hover {
  background: var(--bg-hover);
  color: var(--text);
  text-decoration: none;
}
.sidebar-project-link { margin-left: 0.35rem; font-size: 0.94rem; line-height: 1.35; }
.sidebar-project-list-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 0 1 auto;
  min-height: 0;
}
.sidebar-project-list {
  flex: 0 1 auto;
  /* Raised from 4rem (~2 projects): the condensed rhythm above buys real
     height, so spend it on the list the operator actually scrolls. */
  min-height: 9rem;
  overflow-y: auto;
  padding: 2px 6px 2px 0;
}
body.projects-folded .sidebar-project-list-wrap {
  display: none;
}
.sidebar-search {
  width: 100%;
  padding: 0.45rem 0.6rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 8px;
  color: var(--text);
}
.sidebar-popover {
  position: absolute;
  left: calc(100% + 0.85rem);
  top: 0;
  width: min(22rem, 60vw);
  padding: 0.8rem;
  background: color-mix(in srgb, var(--bg-surface) 95%, var(--bg-body));
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
  z-index: 20;
}
.sidebar-popover[hidden] {
  display: none !important;
}
.sidebar-popover-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.sidebar-popover-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
}
.sidebar-popover-list {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  max-height: min(65vh, 34rem);
  overflow-y: auto;
  margin-top: 0.65rem;
}
.sidebar-bottom {
  margin-top: auto;
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: 0.35rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}
.sidebar-actions {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.35rem 0.65rem;
}
/* Mobile drawer backdrop; only ever shown by the ≤980px block when
   app.js has opted in via body.sidebar-ready. */
.sidebar-scrim {
  display: none;
}
body.sidebar-collapsed .sidebar {
  padding-left: 0.65rem;
  padding-right: 0.65rem;
}
body.sidebar-collapsed .sidebar-toggle-open {
  display: none;
}
body.sidebar-collapsed .sidebar-toggle-closed {
  display: inline;
}
body.sidebar-collapsed .sidebar-top {
  align-items: center;
}
body.sidebar-collapsed .brand {
  display: none;
}
body.sidebar-collapsed .sidebar-meta,
body.sidebar-collapsed .sidebar-search,
body.sidebar-collapsed .sidebar-fold-toggle {
  display: none;
}
body.sidebar-collapsed .sidebar-nav,
body.sidebar-collapsed .sidebar-bottom {
  align-items: center;
}
body.sidebar-collapsed .sidebar-section {
  width: 100%;
  align-items: center;
  position: relative;
}
body.sidebar-collapsed .sidebar-link {
  width: 100%;
  min-height: 2.35rem;
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}
body.sidebar-collapsed .sidebar-link .sidebar-text {
  display: none;
}
body.sidebar-collapsed .sidebar-project-list-wrap {
  display: none;
}
body.sidebar-collapsed .sidebar-project-search-toggle {
  display: inline-flex;
}
body.sidebar-collapsed .sidebar-project-link {
  margin-left: 0;
}
body.sidebar-collapsed .sidebar-popover .sidebar-link {
  width: 100%;
  justify-content: flex-start;
  padding-left: 0.65rem;
  padding-right: 0.65rem;
}
body.sidebar-collapsed .sidebar-popover .sidebar-link .sidebar-text {
  display: inline;
}
body.sidebar-collapsed .sidebar-actions {
  flex-direction: column;
  gap: 0.45rem;
  padding-left: 0;
  padding-right: 0;
}
body.sidebar-collapsed .logout .btn-link {
  width: 100%;
}
.is-hidden { display: none !important; }

/* Theme toggle */
#theme-toggle { font-size: 1.15rem; line-height: 1; }
[data-theme="dark"] .theme-icon-light { display: none; }
[data-theme="dark"] .theme-icon-dark  { display: inline; }
[data-theme="light"] .theme-icon-dark { display: none; }
[data-theme="light"] .theme-icon-light { display: inline; }

/* ---- Layout ---------------------------------------------------- */
.container { max-width: 1180px; margin: 1.5rem auto; padding: 0 1.25rem; }
.container.with-sidebar {
  grid-column: 2;
  grid-row: 2;
  max-width: none;
  width: 100%;
  margin: 0;
  padding: 1.5rem 2rem 2rem;
}
h1, h2, h3 { color: var(--text-heading); }
h1 { margin-top: 0; }
/* Page chrome headers use the design system's .zq-page-header. */
.page-actions-menu {
  position: relative;
}
.page-actions-menu > summary {
  list-style: none;
}
.page-actions-menu > summary::-webkit-details-marker,
.action-menu-disclosure > summary::-webkit-details-marker {
  display: none;
}
.page-actions-trigger {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.35rem;
  white-space: nowrap;
  cursor: pointer;
}
.page-actions-trigger .material-symbols-outlined {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  line-height: 1;
}
.page-actions-popover {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 80;
  min-width: min(24rem, calc(100vw - 2.5rem));
  padding: 0.35rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.32);
}
.page-actions-popover form {
  margin: 0;
}
.action-menu-item {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.55rem 0.65rem;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.92rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.action-menu-item:hover,
.action-menu-item:focus {
  background: var(--bg-hover);
  color: var(--text-heading);
  text-decoration: none;
  outline: none;
}
.action-menu-item .material-symbols-outlined {
  flex: 0 0 auto;
  width: 1.25rem;
  color: var(--text-muted);
  font-size: 1.2rem;
  line-height: 1;
}
.action-menu-disclosure {
  margin: 0;
  padding: 0;
}
.action-menu-disclosure > summary {
  list-style: none;
}
.action-menu-form {
  display: grid;
  gap: 0.65rem;
  margin: 0.25rem 0.25rem 0.35rem 2.55rem;
  padding: 0.7rem;
  border: 1px solid var(--border-light);
  border-radius: 4px;
  background: var(--bg-surface2);
}
.action-menu-form label {
  display: block;
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 600;
}
.action-menu-form p {
  margin: 0;
}

.finding-decision-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0 0 1rem;
  padding: 1rem;
  border: 1px solid var(--input-border);
  border-left: 4px solid var(--accent);
  border-radius: 6px;
  background: var(--bg-surface2);
}
.finding-decision-copy {
  min-width: 0;
}
.decision-kicker {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.finding-decision-panel h2 {
  margin: 0 0 0.25rem;
  font-size: 1.25rem;
}
.finding-decision-panel p {
  margin: 0;
}
.growth-conversion-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  margin: 0 0 1.25rem;
  padding: 1.15rem 1.25rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  border-left: 4px solid var(--accent);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-surface2));
}
.growth-conversion-copy {
  max-width: 58rem;
}
.growth-conversion-panel h2 {
  margin: 0 0 0.35rem;
  font-size: 1.25rem;
}
.growth-conversion-panel p {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1.5;
}
.growth-conversion-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.55rem;
  flex: 0 0 auto;
}
.finding-decision-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.55rem;
  flex-wrap: wrap;
}
.decision-action-form {
  margin: 0;
}
.decision-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 2.35rem;
  white-space: nowrap;
}
.decision-button .material-symbols-outlined {
  font-size: 1.2rem;
  line-height: 1;
}
.decision-reject-menu {
  position: relative;
}
.decision-reject-menu > summary {
  list-style: none;
  cursor: pointer;
}
.decision-reject-menu > summary::-webkit-details-marker {
  display: none;
}
.decision-reject-trigger {
  border-color: #8c3535;
  color: #ffb8b8;
}
.decision-reject-trigger:hover,
.decision-reject-menu[open] > .decision-reject-trigger {
  background: var(--error-pre-brd);
  color: #ffd6d6;
}
.decision-reject-form {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 75;
  display: grid;
  gap: 0.65rem;
  width: min(24rem, calc(100vw - 2.5rem));
  margin: 0;
  padding: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.32);
}
.decision-reject-form label {
  display: grid;
  gap: 0.3rem;
  color: var(--text-muted);
  font-size: 0.82rem;
  font-weight: 600;
}

[data-theme="light"] .decision-reject-trigger {
  border-color: #dc3545;
  color: #721c24;
}
[data-theme="light"] .decision-reject-trigger:hover,
[data-theme="light"] .decision-reject-menu[open] > .decision-reject-trigger {
  background: #f8d7da;
  color: #721c24;
}
.action-menu-form select,
.action-menu-form textarea {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--input-border);
  border-radius: 4px;
  background: var(--input-bg);
  color: var(--text-code);
  font: inherit;
  font-size: 0.9rem;
}
.action-menu-form textarea {
  resize: vertical;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: var(--accent);
  color: #fff;
  padding: 8px 16px;
  z-index: 10000;
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 4px 0;
  transition: top 0.1s;
}

.skip-link:focus {
  top: 0;
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.project-title-form { margin: 0; }
.project-title-wrap { margin-bottom: 0; }
.project-title-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.08rem 0.3rem;
  margin-left: -0.3rem;
  border: none;
  background: transparent;
  color: var(--text-heading);
  font: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  border-radius: 6px;
  box-shadow: 0 0 0 1px transparent;
}
.project-title-input:hover,
.project-title-input:focus {
  background: var(--bg-surface2);
  box-shadow: 0 0 0 1px var(--border);
  outline: none;
}
/* The projects listing reuses the inline title input inside the
   Name cell — size it to the value instead of the detail header's
   full-width stretch. field-sizing hugs the text exactly where
   supported; the size attribute is the fallback elsewhere. */
.project-name-row .project-title-input {
  width: auto;
  min-width: 6ch;
  field-sizing: content;
}
/* Stat tiles render with the design system's .zq-stat; this row is the
   app-side layout wrapper (the tile itself styles only one). */
.stat-row {
  display: flex; gap: var(--zq-space-5); margin-bottom: var(--zq-space-4);
  flex-wrap: wrap;
}
.project-stats .zq-stat {
  min-width: 110px;
}
.bulk-action-row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
  align-self: start;
  padding-top: calc(1.5em + 0.25rem);
}

.bulk-more-menu { position: relative; }
.bulk-more-menu summary {
  list-style: none; cursor: pointer; font-size: 1.1rem; padding: 0.3rem 0.5rem; border-radius: 4px;
  background: var(--btn-bg); border: 1px solid var(--input-border); color: var(--text);
}
.bulk-more-menu summary::-webkit-details-marker { display: none; }
.bulk-more-menu summary::before { content: none; }
.bulk-more-dropdown {
  position: absolute; right: 0; bottom: 100%; z-index: 100;
  background: var(--bg-surface); border: 1px solid var(--input-border);
  border-radius: 6px; padding: 0.4rem; min-width: 200px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 4px;
}
.bulk-more-dropdown .zq-btn--danger { width: 100%; text-align: left; justify-content: flex-start; }
.bulk-controls {
  --bulk-control-height: 2.35rem;
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(220px, 1fr) auto;
  gap: 0.8rem;
  align-items: start;
  margin-bottom: 0.7rem;
}
.bulk-controls label {
  margin-bottom: 0;
}
.bulk-controls input[type="text"],
.bulk-controls select,
.bulk-action-row .zq-btn,
.bulk-action-row .bulk-more-menu summary {
  min-height: var(--bulk-control-height);
}
.bulk-action-row .zq-btn,
.bulk-action-row .bulk-more-menu summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* ---- Tables ---------------------------------------------------- */
/* Tables are the design system's .zq-table (wrapped in .zq-table-wrap for
   horizontal scroll). Only page-specific row/column treatments live here. */
.zq-table th a {
  color: inherit;
  text-decoration: none;
}
.zq-table th a:hover {
  color: var(--text-heading);
  text-decoration: underline;
}
.zq-table tr.llm-price-missing td {
  background: color-mix(in srgb, var(--error) 12%, transparent);
  color: var(--error);
}
.zq-table tr.llm-price-missing:hover td {
  background: color-mix(in srgb, var(--error) 18%, transparent);
}
.zq-table tr.llm-price-missing .muted,
.zq-table tr.llm-price-missing .tier-link {
  color: var(--error);
}
/* Keyboard parity with the old .table-scroll: the wrap is a scroll
   container, so it needs a visible focus ring. (Candidate for the
   library's table.css.) */
.zq-table-wrap:focus-visible {
  outline: 2px solid var(--zq-color-accent-base);
  outline-offset: 2px;
}
.zq-table-wrap .zq-table {
  min-width: 680px;
}
.usage-agent-details > summary {
  cursor: pointer;
  color: var(--text-primary);
}
.usage-agent-breakdown {
  margin: 0.35rem 0 0;
  padding-left: 1.1rem;
}
.usage-agent-breakdown li + li { margin-top: 0.25rem; }
.project-reports-table {
  min-width: 760px;
}

/* ---- Forms ----------------------------------------------------- */
.scan-form label, .rescan-form label, .settings-form label {
  display: block; margin-bottom: 1rem; font-weight: 500;
}
.scan-form input[type="text"],
.scan-form input[type="url"],
.scan-form select,
.scan-form textarea,
.rescan-form textarea,
.inline-form input[type="text"],
.inline-form select {
  /* control treatment comes from the form-controls element bridge;
     display/width are the primitive's .zq-input layout behaviour */
  display: block; width: 100%; margin-top: 0.35rem;
}
.scan-form textarea, .rescan-form textarea {
  font-family: var(--zq-font-family-mono); font-size: var(--zq-font-size-2);
}
.scan-form label.checkbox { display: flex; align-items: center; gap: 0.5rem; }
.form-actions { margin-top: 1rem; }

.scan-form input[type="number"] { width: 6rem; min-width: 5rem; }

button, input[type="submit"] {
  display: inline-block; padding: 0.5rem 0.95rem;
  background: var(--btn-bg); color: var(--text);
  border: 1px solid var(--btn-border); border-radius: 4px;
  cursor: pointer; font-size: 0.95rem;
}
button:hover { background: var(--btn-hover); }
.btn-link { background: none; border: none; color: var(--link); padding: 0; cursor: pointer; }
.btn-link:hover { text-decoration: underline; }

.finding-counts { display: inline-flex; gap: 0.3rem; flex-wrap: wrap; }
.finding-count-link:hover,
.finding-count-link:focus-visible {
  text-decoration: none;
  filter: brightness(1.08);
  outline: 1px solid currentColor;
  outline-offset: 2px;
}
.retracted-count-link {
  display: inline-block;
  margin-left: 0.35rem;
  white-space: nowrap;
}
.retracted-count-link:hover,
.retracted-count-link:focus-visible {
  color: var(--text);
}

/* ---- Scan-type picker ----------------------------------------- */
.scan-picker-page {
  width: min(1080px, 100%);
  margin: clamp(2rem, 8vh, 5.5rem) auto 4rem;
}
.scan-picker-head {
  max-width: 720px;
  margin: 0 auto;
  text-align: center;
}
.scan-picker-eyebrow {
  margin: 0 0 0.55rem;
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}
.scan-picker-head h1 {
  margin: 0 0 0.65rem;
  font-size: clamp(2rem, 5vw, 3.15rem);
  line-height: 1.08;
}
.scan-picker-head .muted {
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
}
.scan-type-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin-top: 2.4rem;
}
.scan-type-card {
  --scan-type-color: var(--accent);
  position: relative;
  display: flex;
  min-height: 300px;
  box-sizing: border-box;
  flex-direction: column;
  padding: 1.45rem;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-surface2);
  color: inherit;
  box-shadow: 0 12px 32px color-mix(in srgb, #000 8%, transparent);
  transition: transform 140ms ease, border-color 140ms ease, background 140ms ease, box-shadow 140ms ease;
}
.scan-type-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: var(--scan-type-color);
}
.scan-type-card.remote { --scan-type-color: #2fae92; }
.scan-type-card.binary { --scan-type-color: #a66ddd; }
a.scan-type-card:hover,
a.scan-type-card:focus-visible {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--scan-type-color) 60%, var(--border));
  background: var(--bg-hover);
  box-shadow: 0 18px 42px color-mix(in srgb, #000 13%, transparent);
  text-decoration: none;
}
a.scan-type-card:focus-visible { outline: 2px solid var(--scan-type-color); outline-offset: 3px; }
.scan-type-kicker {
  margin-top: 0.2rem;
  color: var(--scan-type-color);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.scan-type-card h2 {
  margin: 0.8rem 0 0.65rem;
  font-size: 1.35rem;
}
.scan-type-card p {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.92rem;
  line-height: 1.55;
}
.scan-type-examples {
  display: block;
  margin-top: 1.2rem;
  color: var(--text-muted);
  font-size: 0.78rem;
  line-height: 1.45;
}
.scan-type-action {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: auto;
  padding-top: 1.5rem;
  color: var(--scan-type-color);
  font-size: 0.88rem;
  font-weight: 700;
}
.scan-type-card.disabled {
  opacity: 0.52;
  box-shadow: none;
  cursor: not-allowed;
}
.scan-type-card.disabled .scan-type-action { color: var(--text-muted); }
.scan-picker-footnote {
  max-width: 680px;
  margin: 1.35rem auto 0;
  text-align: center;
}
@media (max-width: 820px) {
  .scan-type-grid { grid-template-columns: 1fr; }
  .scan-type-card { min-height: 225px; }
}

/* ---- Usage-mode onboarding picker ------------------------------ */
/* The scan-type card paradigm above, driven by radio state instead of
   anchor navigation: each card is a label around one of the form's
   usage_mode radios, so hover/checked/focus hang off the input. */
label.scan-type-card { cursor: pointer; }
label.scan-type-card:hover,
label.scan-type-card:focus-within {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--scan-type-color) 60%, var(--border));
  background: var(--bg-hover);
  box-shadow: 0 18px 42px color-mix(in srgb, #000 13%, transparent);
}
label.scan-type-card:has(input:focus-visible) {
  outline: 2px solid var(--scan-type-color);
  outline-offset: 3px;
}
label.scan-type-card:has(input:checked) {
  border-color: var(--scan-type-color);
  box-shadow: 0 0 0 1px var(--scan-type-color),
              0 12px 32px color-mix(in srgb, #000 8%, transparent);
}
.scan-type-card.mode-security_research { --scan-type-color: #a66ddd; }
.scan-type-card.mode-appsec_triage { --scan-type-color: #2fae92; }
.usage-mode-grid {
  min-inline-size: 0;
  margin-inline: 0;
  border: 0;
  padding: 0;
}
.usage-mode-grid input[type="radio"] {
  position: absolute;
  top: 1.35rem;
  right: 1.25rem;
  margin: 0;
}
.usage-mode-grid .scan-type-title {
  display: block;
  margin: 0.8rem 0 0.65rem;
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.2;
}
.usage-mode-grid .scan-type-desc {
  display: block;
  color: var(--text-muted);
  font-size: 0.92rem;
  line-height: 1.55;
}
.scan-picker-actions {
  display: flex;
  justify-content: center;
  margin-top: 2.2rem;
}

/* Re-run sub-form helpers */
.rescan-mode-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.rescan-advanced-row {
  margin-top: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* ---- Key/value list ------------------------------------------- */
.kv {
  display: grid; grid-template-columns: 140px 1fr;
  gap: 0.3rem 1rem; margin: 0 0 1.2rem;
}
.kv dt { color: var(--text-muted); font-size: 0.88rem; }
.kv dd { margin: 0; }

/* Slim usage bar for quota-style readouts (storage, etc.). The label
   text stays as the primary readout; the bar gives at-a-glance fill. */
.usage-bar {
  display: block;
  width: 100%;
  max-width: 280px;
  height: 6px;
  margin-top: 0.35rem;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
}
.usage-bar > span {
  display: block;
  height: 100%;
  background: var(--accent);
  transition: width 0.2s ease;
}
.usage-bar.warn > span { background: var(--running); }
.usage-bar.crit > span { background: var(--error); }

.target-list { list-style: none; padding-left: 0; }
.target-list li { padding: 0.2rem 0; }
.target-list .kind {
  display: inline-block; background: var(--btn-bg); color: var(--text);
  padding: 0 0.4rem; font-size: 0.72rem; border-radius: 3px; margin-right: 0.3rem;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.1rem 0 0.35rem;
}
.section-head h2 {
  margin: 0;
}

/* Notices are the design system's .zq-notice (base flashes included). */

.error { color: var(--error); }
.error-text { color: var(--error); }
.error-pre {
  background: var(--error-pre-bg); border: 1px solid var(--error-pre-brd);
  color: var(--error); padding: 0.6rem; border-radius: 4px;
  white-space: pre-wrap; font-size: 0.86rem;
}

/* Workflow cards — default vertical (used outside accordion) */
.workflow-cards {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
/* Side-by-side variant used inside accordion folds */
.workflow-cards-h {
  flex-direction: row;
  align-items: stretch;
}
.workflow-cards-h .workflow-card { flex: 1; }

.workflow-card {
  position: relative;
  display: block;
  cursor: pointer;
}
.workflow-card input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.workflow-card-inner {
  display: block;
  height: 100%;
  padding: 0.75rem 1rem;
  border: 1.5px solid var(--border, #ccc);
  border-radius: 6px;
  background: var(--bg-subtle, #f9f9f9);
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
  box-sizing: border-box;
}
.workflow-card input:checked + .workflow-card-inner {
  border-color: var(--accent, #22c7e8);
  background: color-mix(in srgb, var(--accent, #22c7e8) 8%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #22c7e8) 20%, transparent);
}
.workflow-card-inner strong { display: block; margin-bottom: 0.2rem; }

/* ---- Log pane (live) ------------------------------------------ */
/* ==== Scan hero band (scan detail page) ===========================
   One surface that leads with "what's happening": identity row
   (title + status + lifecycle-sorted actions), a fact strip where the
   old nine-row <dl> used to be, and the progress panel as the in-card
   hero. Everything reference-shaped lives in the fact-sheet dialog
   (.scan-factsheet) behind the ⋯ menu. */
.scan-hero {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1.1rem 1.5rem 1.25rem;
}
.scan-hero-top {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.scan-hero-top h1 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.scan-hero-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
/* Status chip — the one element whose color tracks the lifecycle. */
.scan-hero .status-queued,
.scan-hero .status-running,
.scan-hero .status-awaiting_batch,
.scan-hero .status-completed,
.scan-hero .status-failed,
.scan-hero .status-cancelled {
  display: inline-flex;
  align-items: center;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
}
.scan-hero .status-queued { background: var(--bg-inset); color: var(--text-muted); }
.scan-hero .status-running { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.scan-hero .status-awaiting_batch { background: var(--warn-bg); color: var(--warn-text); }
.scan-hero .status-completed { background: var(--accent-soft); color: var(--accent); }
.scan-hero .status-failed { background: color-mix(in srgb, var(--error) 12%, transparent); color: var(--error); }
.scan-hero .status-cancelled { background: var(--bg-inset); color: var(--text-muted); }

/* Overflow (⋯) menu — rare/administrative actions. */
.hero-menu-root { position: relative; }
.hero-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  right: 0;
  min-width: 250px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  padding: 0.3rem;
}
.hero-menu button {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.7rem;
  border: 0;
  border-radius: 6px;
  background: none;
  font: inherit;
  font-size: 0.875rem;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.hero-menu button:hover { background: var(--bg-hover); }

/* Fact strip — the reference table compressed to one wrapping line.
   Stage-aware: facts that don't apply to the current lifecycle don't
   render ("Completed" while running is gone; running shows a live
   elapsed count instead). */
.scan-fact-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem 0.55rem;
  margin-top: 0.65rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}
.scan-fact-strip .fact {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}
.scan-fact-strip .dot::before {
  content: "·";
  color: var(--border);
  font-weight: 700;
}
.scan-fact-strip .fact-target code,
.scan-fact-strip .fact-target a code { font-size: 0.875rem; color: var(--text); }
.scan-fact-strip .fact-target .kind {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--bg-inset);
  border-radius: 3px;
  padding: 0.12rem 0.35rem;
}
.scan-fact-strip .fact-more {
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--link);
  cursor: pointer;
  padding: 0.1rem 0.2rem;
}
.scan-fact-strip .fact-more:hover { text-decoration: underline; }
.scan-fact-strip .fact-time .fact-elapsed {
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.scan-fact-strip .fact-id .id-short { font-size: 0.8125rem; }
.id-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  padding: 0.15rem 0.3rem;
  margin: 0;
  border-radius: 4px;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 0.8125rem;
  line-height: 1;
}
.id-copy:hover { background: var(--bg-hover); color: var(--text); }
.id-copy.copied { color: var(--success); }
.scan-fact-strip .fact-project a { color: var(--link); }

/* The progress panel rides inside the hero band — tighten its outer
   spacing so the band reads as one surface. */
.scan-hero .scan-progress-panel {
  margin: 1.1rem 0 0;
  padding-top: 1rem;
  padding-bottom: 0;
  border: 0;
  border-top: 1px solid var(--border-light);
  border-radius: 0;
  background: transparent;
}

/* Fact-sheet dialog — the reference home (exact timestamps, every
   target, notes, required headers) plus the move-to-project form. */
.sheet-scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: transparent;
}
.scan-factsheet {
  position: fixed;
  z-index: 100;
  top: 4.5rem;
  right: max(1rem, calc((100vw - 1180px) / 2));
  width: 420px;
  max-width: calc(100vw - 2rem);
  max-height: calc(100vh - 6rem);
  overflow: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18), 0 24px 80px rgba(0, 0, 0, 0.14);
}
.scan-factsheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.25rem 0.8rem;
  border-bottom: 1px solid var(--border-light);
}
.scan-factsheet-head h2 { margin: 0; font-size: 1rem; color: var(--text-heading); }
.scan-factsheet-close {
  border: 0;
  background: none;
  font-size: 1.05rem;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.2rem 0.4rem;
  border-radius: 4px;
}
.scan-factsheet-close:hover { background: var(--bg-hover); color: var(--text); }
.scan-factsheet section {
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--border-light);
}
.scan-factsheet section:last-child { border-bottom: 0; }
.scan-factsheet h3 {
  margin: 0 0 0.55rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.scan-factsheet-rows { margin: 0; }
.scan-factsheet-rows .row {
  display: flex;
  gap: 0.75rem;
  padding: 0.18rem 0;
  font-size: 0.875rem;
}
.scan-factsheet-rows dt { flex: 0 0 118px; color: var(--text-muted); }
.scan-factsheet-rows dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}
.scan-factsheet .id-row {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.scan-factsheet .id-row .mono { font-size: 0.8125rem; }
.scan-factsheet .target-line { display: block; font-size: 0.8125rem; }
.scan-factsheet-notes { margin: 0; font-size: 0.875rem; }
.scan-factsheet-move {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.2rem;
}
.scan-factsheet-move select {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 0.875rem;
  padding: 0.45rem 0.5rem;
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--input-border);
  border-radius: 6px;
}
.scan-factsheet .muted.small { margin: 0.5rem 0 0; }

.scan-progress-panel {
  margin: 1.25rem 0 1.5rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface2);
}
.scan-progress-rail {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.scan-progress-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: center;
  min-width: 0;
  color: var(--text-muted);
  font-size: 0.86rem;
  text-align: center;
}
.scan-progress-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: calc(50% + 0.75rem);
  right: calc(-50% + 0.25rem);
  top: 0.55rem;
  height: 2px;
  background: var(--border);
  z-index: 0;
}
.scan-progress-step.state-done:not(:last-child)::after {
  background: color-mix(in srgb, var(--accent) 62%, var(--border));
}
.scan-progress-dot {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--bg-surface);
  z-index: 1;
}
.scan-progress-label {
  position: relative;
  z-index: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  line-height: 1.25;
}
.scan-progress-count {
  display: block;
  margin-top: 0.12rem;
  color: var(--text-muted);
  font-size: 0.78rem;
  font-weight: 500;
}
.scan-progress-count:empty {
  display: none;
}
.scan-progress-round {
  display: block;
  color: var(--text-muted);
  font-size: 0.72rem;
}
.scan-progress-round:empty {
  display: none;
}
.scan-progress-step.state-done,
.scan-progress-step.state-current {
  color: var(--text);
}
.scan-progress-step.state-current .scan-progress-label {
  font-weight: 700;
}
.scan-progress-step.state-done .scan-progress-dot {
  background: var(--success);
  border-color: var(--success);
}
.scan-progress-step.state-current .scan-progress-dot {
  background:
    radial-gradient(circle, var(--bg-surface) 0 42%, transparent 44%),
    conic-gradient(var(--running) var(--stage-progress, 0%), var(--border) 0);
  border-color: var(--running);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--running) 20%, transparent);
  animation: scan-progress-pulse 1.4s ease-in-out infinite;
}
.scan-progress-step.state-current[data-progress-total="0"] .scan-progress-dot {
  background: var(--running);
}
.scan-progress-step.state-skipped .scan-progress-dot {
  border-style: dashed;
}
.scan-progress-step.state-interrupted .scan-progress-dot {
  background: var(--error);
  border-color: var(--error);
}
@keyframes scan-progress-pulse {
  0%, 100% {
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--running) 18%, transparent);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 0 8px color-mix(in srgb, var(--running) 6%, transparent);
    transform: scale(1.08);
  }
}
.scan-actor-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.75rem;
  align-items: center;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}
.scan-agent-avatar {
  display: grid;
  place-items: center;
  width: 2.35rem;
  height: 2.35rem;
  border-radius: 50%;
  color: white;
  font-weight: 700;
  font-size: 0.82rem;
  overflow: hidden;
}
.scan-agent-avatar.has-image { background: var(--bg-inset); border: 1px solid var(--border); }
.scan-agent-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.scan-agent-avatar.agent-coordinator { background: #526071; }
.scan-agent-avatar.agent-researcher { background: #267c6b; }
.scan-agent-avatar.agent-vendor { background: #9157a8; }
.scan-agent-avatar.agent-h1 { background: #b85f24; }
.scan-agent-avatar.agent-artifact { background: var(--accent); }
.scan-agent-avatar.agent-triage { background: #83742f; }
.scan-action-headline {
  font-weight: 650;
  color: var(--text-heading);
}
.scan-action-detail {
  overflow-wrap: anywhere;
}
.scan-log-section {
  margin-top: 1.5rem;
}
.scan-log-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}
.scan-log-header h2 {
  margin-bottom: 0.15rem;
}
.log-pane {
  background: var(--bg-inset); border: 1px solid var(--border-light);
  border-radius: 4px; padding: 0.6rem; max-height: 60vh; overflow-y: auto;
  font-family: var(--zq-font-family-mono); font-size: 0.82rem;
}
.log-row { display: grid; grid-template-columns: 145px 110px 110px 110px 1fr; gap: 0.5rem; padding: 0.15rem 0; min-width: 0; }
.log-row[hidden] { display: none; }
.log-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: end;
  margin: -0.25rem 0 0.75rem;
}
.log-filters label { display: grid; gap: 0.25rem; color: var(--text-muted); font-size: 0.85rem; }
.log-filters select { min-width: 12rem; }
.log-timezone-note { margin: 0; }
.log-row .log-ts { color: var(--text-muted); }
.log-row .log-level { color: var(--text-muted); text-transform: uppercase; font-size: 0.78rem; }
.log-row .log-agent { color: var(--link); }
.log-row .log-msg { word-break: break-word; overflow-wrap: break-word; }
.log-row.level-error .log-msg { color: var(--error); }
.log-row.level-tool  .log-msg { color: var(--link); white-space: pre-wrap; }
.log-row.level-agent .log-msg { color: var(--text); white-space: pre-wrap; }
.log-row.level-info  .log-msg { color: var(--text-muted); }

@media (max-width: 760px) {
  .scan-progress-rail {
    grid-template-columns: 1fr;
  }
  .scan-progress-step {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 0.45rem;
    align-items: center;
    text-align: left;
  }
  .scan-progress-step:not(:last-child)::after {
    left: 0.55rem;
    right: auto;
    top: 1.35rem;
    bottom: -0.45rem;
    width: 2px;
    height: auto;
  }
  .scan-log-header {
    align-items: flex-start;
    flex-direction: column;
  }
  .log-row {
    grid-template-columns: 1fr;
    gap: 0.15rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border-light);
  }
}

/* ---- Finding detail ------------------------------------------- */
.finding-list { list-style: none; padding: 0; }
.finding-list li a { display: block; padding: 0.4rem 0.6rem; border-radius: 4px; }
.finding-list li a:hover { background: var(--bg-surface2); }

.scan-version-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.scan-version-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.25);
  min-width: 260px;
  z-index: 100;
  padding: 0.5rem 0;
}
.version-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.version-list li a {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  text-decoration: none;
  color: var(--text);
  font-size: 0.85rem;
}
.version-list li a:hover {
  background: var(--bg-surface2);
}
.version-list li .vnum {
  font-weight: 600;
  min-width: 2ch;
}
.version-list li .vstatus {
  font-size: 0.75rem;
  color: var(--text-muted);
}
.version-list li .vdate {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-left: auto;
}
.version-list li .vcount {
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-left: auto;
}
.version-list li .vcount {
  font-size: 0.7rem;
  color: var(--text-muted);
}
.version-list li.more-link {
  border-top: 1px solid var(--border);
  margin-top: 0.25rem;
  padding-top: 0.25rem;
}
.version-list li.more-link a {
  color: var(--accent);
  font-size: 0.8rem;
}

/* Live-state badge on the in-progress findings list. "proposed" is the
   default during scanning; review flips it to sustained/rejected. */
/* Finding-state chips: shape from .zq-badge, this keeps only the
   inline-row spacing and the per-state tones. */
.finding-state-badge {
  margin-right: 0.3rem;
  vertical-align: baseline;
}
.state-proposed {
  color: var(--text-muted);
  background: var(--bg-surface2);
}
.state-sustained {
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}
.state-reviewing {
  color: var(--zq-color-status-warning);
  background: color-mix(in srgb, var(--zq-color-status-warning) 18%, transparent);
}
.state-rejected {
  color: var(--text-muted);
  border-color: var(--text-muted);
  background: transparent;
}
.finding-row.finding-state-rejected .finding-title {
  text-decoration: line-through;
  opacity: 0.7;
}
.finding-row.finding-state-rejected .finding-type {
  text-decoration: line-through;
}
/* Triage tombstones: findings the triage stage deleted as false
   positives, kept visible (struck-through) instead of silently
   vanishing from the live list. */
.state-removed {
  color: var(--text-muted);
  border-color: var(--text-muted);
  background: transparent;
}
.finding-row.finding-state-removed {
  cursor: help;
}
.finding-row.finding-state-removed .finding-title {
  text-decoration: line-through;
  opacity: 0.7;
}
.finding-row.finding-state-removed .finding-type {
  text-decoration: line-through;
}
/* The report's "Removed by triage" section reuses the retracted
   findings table chrome; only the title cell needs the strike. */
.triage-removed-findings td.triage-removed-title {
  text-decoration: line-through;
  opacity: 0.75;
}

.summary-box {
  background: var(--bg-surface2); border-left: 3px solid var(--accent);
  padding: 0.6rem 0.9rem; border-radius: 0 4px 4px 0; margin-bottom: 1rem;
}
.summary-box.markdown-body {
  max-width: none;
  width: 100%;
}
.summary-box > :first-child,
.non-issues-list .markdown-body > :first-child {
  margin-top: 0;
}
.summary-box > :last-child,
.non-issues-list .markdown-body > :last-child {
  margin-bottom: 0;
}
.notes-box {
  background: var(--bg-surface2); border-left: 3px solid var(--success);
  padding: 0.6rem 0.9rem; border-radius: 0 4px 4px 0; margin-bottom: 1rem;
  white-space: pre-wrap;
}

/* Summary truncation on dashboard */
.summary-cell { max-width: 360px; }
.truncate {
  display: inline-block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom;
}
.summary-row td {
  background: var(--bg-surface2);
  border-bottom: 1px solid var(--border);
}
.zq-table tbody tr.summary-row:last-child td {
  border-bottom: none;
}
.report-row td {
  border-bottom: none;
}
.summary-row .summary-gutter {
  background: var(--bg-surface2);
  border-top: none;
}
.summary-row .summary-cell {
  max-width: none;
  padding-top: 0.1rem;
  padding-bottom: 0.85rem;
}
.zq-table tbody tr.report-row:hover td,
.zq-table tbody tr.summary-row:hover td {
  background: var(--bg-surface2);
}

/* Version pill on the report row + the inline prior-versions subrow it
   toggles open. The row hides via the [hidden] attribute (set in markup
   on first render and toggled in JS), so no display rule is needed for
   the closed state. */
.version-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-left: 0.4rem;
  padding: 0.05rem 0.45rem;
  background: var(--bg-surface2);
  border: 1px solid var(--border);
  border-radius: 999px;
  font: inherit;
  font-size: 0.8rem;
  color: var(--text-muted);
  cursor: pointer;
  vertical-align: baseline;
}
.version-toggle:hover { color: var(--text); border-color: var(--accent); }
.version-toggle[aria-expanded="true"] {
  color: var(--accent);
  border-color: var(--accent);
}
.version-toggle[aria-expanded="true"] .version-chev { transform: rotate(180deg); }
.version-toggle .version-count {
  font-size: 0.7rem;
  opacity: 0.8;
}
.version-toggle .version-chev {
  display: inline-block;
  font-size: 0.7rem;
  transition: transform 0.15s ease;
}

.scan-hero-heading {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
  flex-wrap: wrap;
}
.scan-title-form {
  /* h1 edit-in-place for running/finished scans. Occupies the same
     slot the queued title input does so the status badge keeps its
     place on the row (the input lives inside the form, so the form
     carries the flex sizing). */
  flex: 1 1 18rem;
  min-width: min(100%, 18rem);
  max-width: 42rem;
  margin: 0;
}
.scan-title-input {
  width: 100%;
  padding: 0.08rem 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--text-heading);
  font: inherit;
  font-weight: 700;
}
.scan-title-input:hover,
.scan-title-input:focus {
  border-bottom-color: var(--input-border);
  outline: 0;
}
.scan-title-input::placeholder {
  color: var(--text-muted);
}
.queued-scan-title-input {
  min-width: min(100%, 18rem);
  max-width: 42rem;
  flex: 1 1 18rem;
  padding: 0.08rem 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--text-heading);
  font: inherit;
  font-weight: 700;
}
.queued-scan-title-input:hover,
.queued-scan-title-input:focus {
  border-bottom-color: var(--input-border);
  outline: 0;
}
.queued-scan-title-input::placeholder {
  color: var(--text-muted);
}

.queued-scan-settings {
  max-width: 58rem;
  margin: 1.4rem 0 1.6rem;
  padding: 1rem;
  background: var(--bg-surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.queued-scan-settings-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.85rem;
}
.queued-scan-settings h2 {
  margin: 0;
}
.queued-scan-settings p {
  margin: 0.25rem 0 0;
}
.queued-model-editor {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: wrap;
  justify-content: flex-end;
  min-width: min(100%, 19rem);
}
.queued-model-label {
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 600;
}
.queued-model-current {
  color: var(--text);
}
.queued-model-change {
  font-size: 0.9rem;
}
.queued-model-editor select {
  min-width: 12rem;
  padding: 0.45rem 0.6rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font: inherit;
}
.queued-notes-field {
  display: block;
  font-weight: 600;
}
.queued-notes-field textarea {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.55rem 0.7rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font-family: var(--zq-font-family-mono);
  font-size: 0.88rem;
  resize: vertical;
}
.queued-scan-actions {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  margin-top: 0.85rem;
}
.queued-scan-actions form {
  margin: 0;
}

.versions-row td {
  background: var(--bg-surface2);
  border-top: 1px dashed var(--border);
  border-bottom: 1px solid var(--border);
  padding: 0.4rem 0.6rem;
}
.prior-versions {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.prior-versions li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  font-size: 0.85rem;
}
.version-delta.up { color: var(--sev-high, var(--error)); }
.version-delta.down { color: var(--sev-info, #4a8); }
.lineage-actions {
  margin-top: 0.45rem;
  padding-top: 0.45rem;
  border-top: 1px dashed var(--border);
}
.summary-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: pre-line;
  word-break: break-word;
}

/* Version history list */
.version-list { list-style: none; padding-left: 0; }
.version-list li {
  padding: 0.25rem 0; display: flex; gap: 0.75rem;
  align-items: baseline; flex-wrap: wrap;
}

.markdown-body { max-width: 85ch; }
.markdown-body code { background: var(--bg-inset); padding: 0.08rem 0.35rem; border-radius: 3px; }
.markdown-body pre { background: var(--bg-inset); padding: 0.7rem; border-radius: 4px; }
.markdown-body h1 { font-size: 1.4rem; } .markdown-body h2 { font-size: 1.15rem; }
.markdown-body table { border-collapse: collapse; }
.markdown-body table th, .markdown-body table td { border: 1px solid var(--border); padding: 0.3rem 0.6rem; }

/* ---- Code + copy button wrapper ------------------------------- */
.code-block-wrap { position: relative; }
.code-block-wrap .copy-btn {
  position: absolute; top: 0.4rem; right: 0.4rem;
  background: var(--btn-bg); color: var(--text-muted); border: 1px solid var(--border);
  padding: 0.2rem 0.5rem; font-size: 0.75rem; border-radius: 3px; cursor: pointer;
  opacity: 0.7; transition: opacity 0.15s;
}
.code-block-wrap:hover .copy-btn { opacity: 1; }
.code-block-wrap .copy-btn:hover { background: var(--btn-hover); color: var(--text); }

/* On Firefox/macOS the log pane's scroll bar is an overlay (it doesn't
   take layout space), so the floating copy/download button lands right
   on top of the bar at right: 0.4rem. Push it a bit further in for the
   log wrap only — other copy buttons sit on flat code blocks and don't
   have a scroll bar to clear. */
.log-pane-wrap.code-block-wrap .copy-btn { right: 0.8rem; }

.poc-wrap { border: 1px solid var(--border-light); border-radius: 4px; overflow: auto; }
.poc-code { background: var(--bg-inset) !important; padding: 0.6rem; }
.poc-code .linenos,
.poc-code .lineno,
.source-code .linenos,
.source-code .lineno {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.shiki-code-block {
  border: 1px solid var(--border-light);
  border-radius: 4px;
  overflow: auto;
  background: var(--bg-inset);
}
.shiki-code-block[hidden] { display: none; }
.shiki-code-block pre.shiki {
  margin: 0;
  padding: 0.65rem 0;
  min-width: max-content;
  background: transparent !important;
  font-family: var(--zq-font-family-mono);
  font-size: 0.85rem;
  line-height: 1.45;
}
.shiki-code-lines {
  display: block;
}
.shiki-code-line {
  display: block;
  min-height: 1.45em;
  padding: 0 0.85rem 0 0;
  white-space: pre;
}
.shiki-line-number {
  display: inline-block;
  width: 4.25rem;
  padding-right: 0.85rem;
  color: var(--text-muted);
  text-align: right;
  text-decoration: none;
  user-select: none;
  -webkit-user-select: none;
}
.shiki-line-number:hover {
  color: var(--text);
}
.shiki-code-line.highlight-line {
  background: #3a2a0055;
}
[data-theme="light"] .shiki-code-line.highlight-line {
  background: #fff3c455;
}

.email-draft { background: var(--bg-surface2); padding: 1rem; border-radius: 4px; }

/* ---- Source viewer -------------------------------------------- */
.source-viewer { max-height: 80vh; overflow: auto; }
.source-viewer pre { margin: 0; }
.source-viewer .highlight-line { background: #3a2a0055; }
[data-theme="light"] .source-viewer .highlight-line { background: #fff3c455; }

/* ---- Chat ----------------------------------------------------- */
.chat-messages { display: flex; flex-direction: column; gap: 0.7rem; margin-bottom: 0.8rem; }
.chat-msg {
  padding: 0.65rem 0.85rem;
  border-radius: 16px;
  max-width: min(76ch, 86%);
  border: 1px solid var(--border);
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.10);
}
.chat-msg.role-user {
  align-self: flex-end;
  background: var(--bg-surface2);
  border-right: 3px solid var(--accent);
  border-bottom-right-radius: 5px;
}
.chat-msg.role-assistant {
  align-self: flex-start;
  background: var(--bg-inset);
  border-left: 3px solid var(--success);
  border-bottom-left-radius: 5px;
}
.chat-msg .chat-meta { display: flex; gap: 0.6rem; font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.3rem; }
.chat-msg .chat-content { white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; }
.chat-msg .chat-content.markdown-body { max-width: 100%; }
.chat-msg .chat-content.markdown-body > :first-child { margin-top: 0; }
.chat-msg .chat-content.markdown-body > :last-child { margin-bottom: 0; }
.chat-msg .chat-content.markdown-body p { margin: 0.4rem 0; }
.chat-msg .chat-content.markdown-body ul,
.chat-msg .chat-content.markdown-body ol { margin: 0.4rem 0 0.4rem 1.2rem; padding: 0; }
.chat-msg .chat-content.markdown-body li { margin: 0.15rem 0; }
.chat-msg .chat-content.markdown-body h1,
.chat-msg .chat-content.markdown-body h2,
.chat-msg .chat-content.markdown-body h3 { margin: 0.6rem 0 0.3rem; line-height: 1.25; }
.chat-msg .chat-content.markdown-body h1 { font-size: 1.15rem; }
.chat-msg .chat-content.markdown-body h2 { font-size: 1.05rem; }
.chat-msg .chat-content.markdown-body h3 { font-size: 0.98rem; }
.chat-msg .chat-content.markdown-body pre { overflow-x: auto; max-width: 100%; white-space: pre; }
.chat-msg .chat-content.markdown-body table { width: 100%; }
.chat-msg .chat-content.markdown-body a { word-break: break-word; }
/* "Drafting…" indicator inside the chat popover. While the model is
   working on a turn (no tokens yet), the user should see an obvious,
   always-on indicator that something is happening. Two pieces work
   together:

   1. The .chat-msg.is-typing bubble itself becomes sticky at the
      bottom of the chat panel (with a subtle backdrop) so it stays
      visible even when the operator has scrolled the transcript.
   2. The dots are larger and higher-contrast than the discussion
      variant because the chat-fab panel is small (max-width 26rem)
      and the old 0.42rem dots got visually lost.

   The companion `.chat-fab-root.is-drafting` style below mirrors this
   on the FAB button so the model is clearly working even when the
   popover is closed. */
.chat-msg.is-typing {
  position: sticky;
  bottom: 0.4rem;
  align-self: flex-start;
  z-index: 3;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-left: 3px solid var(--success);
  box-shadow: 0 12px 28px rgb(0 0 0 / 0.18);
  /* A faint gradient mask on the bottom edge hints that the bubble
     is "above" the transcript instead of "in" it, so it reads as a
     status pill rather than another message. */
  background-image: linear-gradient(180deg, color-mix(in srgb, var(--success) 6%, transparent), transparent 60%);
}
.chat-msg.is-typing .chat-content {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--text);
  font-weight: 500;
}
.chat-typing-label { font-size: 0.9rem; letter-spacing: 0.01em; }
/* Override the inherited 0.42rem dot size in the chat-fab so the
   indicator reads at the smaller panel scale. The .typing-dots
   shared class still drives the animation; we just make each dot
   chunkier and the color closer to the bubble's success accent. */
.chat-msg.is-typing .typing-dots span {
  width: 0.55rem;
  height: 0.55rem;
  background: var(--success);
  opacity: 0.55;
}

.chat-form textarea {
  width: 100%; padding: 0.55rem 0.7rem;
  background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: 4px; color: var(--text-code); font-family: inherit; font-size: 0.95rem;
}
.chat-form-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  justify-content: flex-end;
}
.chat-form-bar .zq-btn { margin: 0; }

/* ---- Floating chat bubble (FAB + popover) ---------------------- */
.chat-fab-root {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 800;
}
.chat-fab {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border));
  background: var(--accent);
  color: #fff;
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.35);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.chat-fab:hover { background: var(--accent-hover); transform: translateY(-1px); }
.chat-fab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.chat-fab-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}
.chat-fab-icon {
  font-size: 1.7rem;
  line-height: 1;
}
.chat-fab-root.is-open .chat-fab {
  background: var(--bg-surface2);
  color: var(--text);
  border-color: var(--border);
}

/* While the model is drafting a response, the FAB shows an animated
   "…" badge. The old cue — a single green corner dot plus a faint
   box-shadow pulse — read as static presence ("online?") and was easy
   to miss at the 3.25rem button scale. The badge is a real element
   rather than a ::after because three independently animated dots
   can't live in one pseudo-element. It mirrors the .typing-dots bounce
   of the in-panel "Thinking" bubble (same 1.2s timing and delays) so
   the closed-FAB and open-panel cues read as one state. */
.chat-fab { position: relative; }
.chat-fab-typing {
  position: absolute;
  top: -0.2rem;
  right: -0.3rem;
  display: none;
  align-items: center;
  gap: 0.12rem;
  padding: 0.24rem 0.3rem;
  border-radius: 999px;
  background: var(--success);
  border: 2px solid var(--bg-surface);
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.25);
  pointer-events: none;
  z-index: 1;
}
.chat-fab-root.is-drafting .chat-fab-typing { display: inline-flex; }
.chat-fab-typing span {
  width: 0.26rem;
  height: 0.26rem;
  border-radius: 999px;
  background: #fff;
  animation: chat-fab-typing-bounce 1.2s infinite ease-in-out;
}
.chat-fab-typing span:nth-child(2) { animation-delay: 0.16s; }
.chat-fab-typing span:nth-child(3) { animation-delay: 0.32s; }
@keyframes chat-fab-typing-bounce {
  0%, 80%, 100% { transform: translateY(0); opacity: 0.45; }
  40%           { transform: translateY(-0.16rem); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  /* Keep the state visible without the motion: dots hold full opacity. */
  .chat-fab-typing span { animation: none; opacity: 1; }
}

.chat-fab-panel {
  position: fixed;
  right: 1.25rem;
  bottom: calc(1.25rem + 3.25rem + 0.6rem);
  width: min(26rem, calc(100vw - 2.5rem));
  max-height: min(70vh, 38rem);
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgb(0 0 0 / 0.45);
  overflow: hidden;
  z-index: 800;
}
.chat-fab-panel[hidden] { display: none; }
.chat-fab-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface2);
}
.chat-fab-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-heading);
}
.chat-fab-close {
  background: transparent;
  border: 0;
  padding: 0.25rem;
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
}
.chat-fab-close:hover { background: var(--bg-hover); color: var(--text); }
.chat-fab-close .material-symbols-outlined { font-size: 1.2rem; }

.chat-fab-hint {
  margin: 0.55rem 0.9rem 0;
}
.chat-fab-panel .chat-messages {
  flex: 1 1 auto;
  min-height: 8rem;
  max-height: 100%;
  overflow-y: auto;
  padding: 0.6rem 0.9rem 0.2rem;
  margin: 0;
}
.chat-fab-panel .chat-form {
  border-top: 1px solid var(--border);
  padding: 0.6rem 0.9rem 0.7rem;
  background: var(--bg-surface2);
}
.chat-msg-placeholder {
  font-style: italic;
}

@media (max-width: 600px) {
  .chat-fab-root { right: 0.85rem; bottom: 0.85rem; }
  .chat-fab-panel {
    right: 0.5rem;
    left: 0.5rem;
    bottom: calc(0.85rem + 3.25rem + 0.5rem);
    width: auto;
  }
}

/* Admin preview frame for the chat bubble graphic. */
.chat-bubble-preview {
  display: inline-flex;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-inset);
  vertical-align: middle;
}
.chat-bubble-preview img { width: 100%; height: 100%; object-fit: cover; }

/* Inline tool-call lines in the chat transcript. Read-only tools render
   muted; destructive tools (finding mutations, h1 rerun) render in a
   warning style with the args inline so the operator sees what changed. */
.chat-tool-line {
  font-size: 0.78rem;
  color: var(--text-muted, var(--text-secondary));
  padding: 0.15rem 0;
}
.chat-tool-line .chat-tool-icon { display: inline-block; min-width: 1ch; }
.chat-tool-line .chat-tool-name { font-family: var(--zq-font-family-mono); }
.chat-tool-line .chat-tool-args { color: var(--text-secondary); }
.chat-tool-line .chat-tool-ts {
  color: var(--text-faint, var(--text-muted));
  font-size: 0.7rem;
  margin-left: 0.2rem;
  font-variant-numeric: tabular-nums;
}
.chat-tool-line.destructive {
  color: var(--sev-high-fg, #ffd8b5);
  background: var(--sev-high-bg, rgba(122, 52, 16, 0.18));
  border-left: 3px solid var(--sev-high-fg, #ffd8b5);
  padding: 0.25rem 0.5rem;
  border-radius: 3px;
  margin: 0.2rem 0;
}
.chat-tool-line.destructive .chat-tool-icon { font-weight: 700; }
.chat-tool-line.destructive .chat-tool-ts { color: var(--sev-high-fg, #ffd8b5); opacity: 0.85; }

/* "Finding updated" notice in the chat transcript. The agent mutated the
   finding/report, so the page behind the chat is stale — but reloading
   mid-turn would kill the stream, so we offer a button instead of
   navigating away. One notice per turn (the backend fires the event per
   mutation and again at end of turn). */
.chat-updated-note {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0;
}
.chat-updated-note .chat-updated-note-text { flex: 1; }
.chat-updated-note .chat-updated-reload {
  font-size: 0.72rem;
  padding: 0.15rem 0.55rem;
  border-radius: 4px;
  border: 1px solid var(--border, var(--text-muted));
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
}
.chat-updated-note .chat-updated-reload:hover {
  background: var(--bg-hover, rgba(128, 128, 128, 0.12));
  color: var(--text-primary, var(--text-secondary));
}

/* Sticky activity footer for the chat transcript.
   A long agentic turn can fan out 10–20 tool calls (run_shell, read_file,
   …). Showing each one as its own line floods the scrollback. Instead we
   collapse the run to a single sticky footer pinned to the bottom of
   the chat panel that always shows the latest tool + a counter, with a
   "view all" expander for the full list. Destructive tools (mutations
   in DESTRUCTIVE_CHAT_TOOLS) still render inline above the footer so
   they're impossible to miss. */
.chat-activity {
  position: sticky;
  bottom: 0;
  margin-top: 0.4rem;
  background: linear-gradient(to top,
    var(--bg-surface) 70%,
    color-mix(in srgb, var(--bg-surface) 0%, transparent));
  padding-top: 0.4rem;
  z-index: 2;
}
.chat-activity[hidden] { display: none; }
.chat-activity-summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  font: inherit;
  font-size: 0.78rem;
  color: var(--text-muted);
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.32rem 0.6rem;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.chat-activity-summary:hover {
  background: var(--bg-hover);
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
}
.chat-activity-summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.chat-activity-dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--accent);
  flex: 0 0 auto;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent);
  animation: chat-activity-pulse 1.4s ease-out infinite;
}
@keyframes chat-activity-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); }
  70%  { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
.chat-activity-text {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  flex: 1 1 auto;
}
.chat-activity-count {
  font-weight: 600;
  color: var(--text);
}
.chat-activity-sep { color: var(--text-faint, var(--text-muted)); }
.chat-activity-latest {
  color: var(--text-secondary);
  font-size: 0.74rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.chat-activity-caret {
  margin-left: auto;
  color: var(--text-faint, var(--text-muted));
  font-size: 0.78rem;
}
.chat-activity-list {
  margin-top: 0.35rem;
  padding: 0.35rem 0.5rem 0.45rem;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 6px;
  max-height: 12rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
}
.chat-activity-list[hidden] { display: none; }
.chat-activity-list .chat-tool-line {
  font-size: 0.74rem;
  padding: 0.1rem 0;
}

.deployment-thread {
  margin-top: 0.85rem;
}
.deployment-log-bubble {
  display: block;
  color: var(--text);
  text-decoration: none;
}
.deployment-log-bubble:hover {
  text-decoration: none;
  border-color: color-mix(in srgb, var(--link) 45%, var(--border));
}
.deployment-log-bubble.deployment-log-error {
  border-color: color-mix(in srgb, var(--error) 50%, var(--border));
}

/* Re-run a stage controls in the report Manage section. Each form is a
   single inline row: stage tag, model select, button. */
.rerun-stage-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  flex-wrap: wrap;
}
.rerun-stage-pick {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 26rem;
  min-width: min(100%, 18rem);
}
.rerun-stage-form select {
  width: 100%;
  min-width: 0;
  margin: 0;
}
.rerun-stage-form .zq-btn { margin: 0; }

/* Resume panel — visible only on failed scans. Visually distinct from
   the manual rerun section below it so it reads as "the recommended
   recovery action" rather than "another rerun option." */
.zq-card.resume-panel {
  border-left: 3px solid var(--running);
  background: var(--bg-surface2);
  padding: 0.75rem 1rem;
}
.resume-form .resume-radio-row {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border-light);
}
.resume-form .resume-radio-row:last-of-type { border-bottom: 0; }
.resume-form .resume-radio-row input[type="radio"] { margin-top: 0.25rem; }
.resume-form .resume-radio-row strong { display: block; }
.resume-model-row {
  display: flex; align-items: center; gap: 0.5rem;
  flex-wrap: wrap; margin-top: 0.5rem;
}
.resume-model-row select { width: auto; min-width: 0; margin: 0; }
.resume-model-row .zq-btn { margin: 0; }

/* Per-finding re-run section: same compact inline-row pattern as the
   whole-scan rerun, one row per stage. */
.finding-rerun-grid { display: flex; flex-direction: column; gap: 0.4rem; }
.finding-rerun-form {
  display: flex; align-items: center; gap: 0.5rem;
  margin: 0; flex-wrap: wrap;
}
.finding-rerun-form select { width: auto; min-width: 0; margin: 0; }
.finding-rerun-form .zq-btn { margin: 0; }

/* Inline model picker used inside other forms (patch generate, deployment
   regen). Renders as a tight pill that sits next to the submit button. */

/* Bulk-rerun: thin selection column on the findings table + a single
   inline toolbar above it. The toolbar sits flush to the table so the
   relationship between the two is visually unambiguous. */
.bulk-rerun-form { margin: 0; }
.bulk-rerun-toolbar {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  padding: 0.4rem 0.6rem;
  margin-bottom: 0;
  background: var(--bg-surface2);
  border: 1px solid var(--input-border);
  border-bottom: 0;
  border-radius: 4px 4px 0 0;
  font-size: 0.85rem;
}
.bulk-toolbar-group {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.bulk-decision-group {
  padding: 0.25rem;
  border: 1px solid var(--border-light);
  border-radius: 4px;
  background: var(--bg-surface);
}
.bulk-toolbar-label {
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.bulk-rerun-toolbar select {
  width: auto; min-width: 0; margin: 0;
  padding: 0.25rem 0.4rem; font-size: 0.85rem;
}
.bulk-rerun-toolbar .bulk-state-note {
  width: clamp(9rem, 22vw, 16rem);
  min-width: 0;
  margin: 0;
  padding: 0.25rem 0.45rem;
  font-size: 0.85rem;
}
.bulk-rerun-toolbar .zq-btn { margin: 0; }
.bulk-rerun-toolbar .bulk-rerun-count {
  color: var(--text-secondary);
  white-space: nowrap;
}
.bulk-rerun-form .findings-table { border-radius: 0 0 4px 4px; }
.findings-table .bulk-rerun-cell {
  width: 1.5rem; padding-right: 0.25rem;
  text-align: center;
}
.findings-table .bulk-rerun-cell input[type="checkbox"] {
  margin: 0; cursor: pointer;
}

/* CVE column: chip-style links so multiple references read as
   distinct, clickable tokens instead of a wall of space-separated
   anchors. */
.cve-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.cve-list .cve-link {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-surface2);
  font-size: 0.82rem;
  font-family: var(--zq-font-family-mono);
  white-space: nowrap;
  text-decoration: none;
  color: var(--link);
}
.cve-list .cve-link:hover {
  background: var(--bg-hover);
  border-color: var(--accent);
}

/* Audit log table — reverse-chronological record of LLM events on a
   scan or finding. Sits on the design system's .zq-table and adds a
   colour-coded status pill column. */
.audit-table { font-size: 0.9rem; }

/* Audit-log expand toggle: a small chevron in the leading column that
   reveals an inline sub-row with the scan's three bucket models. The
   sub-row hides via the [hidden] attribute set in markup; the JS in
   app.js toggles aria-expanded + the hidden attribute on click. */
.audit-table th.audit-expand-cell,
.audit-table td.audit-expand-cell {
  width: 1.6rem;
  padding-right: 0;
}
.audit-expand-toggle {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 0.25rem;
  font: inherit;
  line-height: 1;
}
.audit-expand-toggle:hover { color: var(--text); }
.audit-expand-toggle .audit-expand-chev {
  display: inline-block;
  font-size: 0.75rem;
  transition: transform 0.15s ease;
}
.audit-expand-toggle[aria-expanded="true"] {
  color: var(--accent);
}
.audit-expand-toggle[aria-expanded="true"] .audit-expand-chev {
  transform: rotate(90deg);
}
.audit-expand-row td {
  background: var(--bg-surface2);
  border-top: 1px dashed var(--border);
  padding: 0.5rem 0.75rem;
}
.audit-expand-body {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.audit-bucket-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.audit-bucket-list li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  font-size: 0.85rem;
}

/* Retracted findings subsection — collapsed by default below the main
   findings table, using the same table grammar so operators can compare
   entries without mentally translating a second list layout. */
.retracted-findings {
  margin-top: 1rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border-light);
  border-radius: 4px;
  background: var(--bg-surface2);
}
.retracted-findings > summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: 0.95rem;
  user-select: none;
}
.retracted-findings > summary:hover { color: var(--text); }
.retracted-table-wrap {
  overflow-x: auto;
  margin-top: 0.6rem;
}
.retracted-findings-table { margin: 0; }
.retracted-reason { margin-top: 0.2rem; }
.retracted-promote-cell { min-width: 8rem; }
.retracted-promote { position: relative; }
.retracted-promote > summary {
  display: inline-flex;
  list-style: none;
  cursor: pointer;
}
.retracted-promote > summary::-webkit-details-marker { display: none; }
.retracted-promote form {
  width: min(22rem, 70vw);
  margin-top: 0.45rem;
  padding: 0.65rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-surface);
}
.retracted-promote label {
  display: grid;
  gap: 0.3rem;
  color: var(--text-secondary);
  font-size: 0.82rem;
}
.retracted-promote textarea {
  width: 100%;
  min-width: 15rem;
  margin: 0;
  resize: vertical;
}
.retracted-promote form .zq-btn { margin-top: 0.5rem; }

/* ---- Notable non-issues --------------------------------------- */
.non-issues-list { list-style: none; padding-left: 0; }
.non-issues-list li {
  padding: 0.35rem 0.6rem; border-radius: 4px; margin-bottom: 0.3rem;
  background: var(--bg-surface2); border-left: 3px solid var(--success);
}
.non-issues-list .ni-label { color: var(--success); font-weight: 600; margin-right: 0.5rem; }
.non-issues-list .markdown-body { max-width: none; }

/* ---- Section cards --------------------------------------------- */
/* Every .zq-card carries the design system's part model
   (__header/__titles/__title/__subtitle/__actions/__body), so the old
   :has() padding shim that compensated for bare cards is gone. The
   compensators below are scoped to the body: they keep the app's dense
   content rhythm inside cards without touching header titles. */
.zq-card__body h3 { margin: 0 0 0.25rem 0; font-size: 0.875rem; color: var(--text); }
.zq-card__body > :last-child { margin-bottom: 0; }
.zq-card__body p { margin: 0.15rem 0 0.3rem; }
/* some headers carry more than one action; let them wrap like the old
   inline-group rows did */
.zq-card__header .zq-card__actions { flex-wrap: wrap; }
.manage-inline-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
}
.manage-inline-group :is(h2, h3) {
  margin: 0;
}
.manage-project-form {
  margin-left: auto;
}
.evidence-filter-form {
  display: flex;
  align-items: end;
  gap: 0.8rem;
  flex-wrap: wrap;
}
.evidence-filter-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 180px;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.evidence-filter-form select {
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text);
  padding: 0.45rem 0.6rem;
}
/* Attestation engagement start form — a field grid on a soft panel,
   not the one-row filter-bar treatment, so labels align and the
   notes/credential fields get full-width room. */
.engagement-create-form {
  display: grid;
  grid-template-columns: minmax(230px, 1.6fr) minmax(150px, 1fr) minmax(200px, 1.2fr) minmax(160px, 1fr);
  gap: 0.8rem 1rem;
  align-items: start;
  margin-bottom: 1.25rem;
  padding: 1rem;
  background: var(--bg-surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.engagement-create-form > label {
  display: block;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.engagement-create-form > label > select,
.engagement-create-form > label > input,
.engagement-create-form > label > textarea {
  display: block;
  width: 100%;
  margin: 0.3rem 0 0;
}
.engagement-create-form .engagement-create-notes,
.engagement-create-form .engagement-credential-access,
.engagement-create-form .engagement-create-actions {
  grid-column: 1 / -1;
}
.engagement-create-form .engagement-create-actions {
  display: flex;
  justify-content: flex-end;
}
@media (max-width: 1080px) {
  .engagement-create-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .engagement-create-form { grid-template-columns: minmax(0, 1fr); }
  .engagement-create-form .engagement-create-actions .zq-btn { width: 100%; }
}
/* Credential pre-grant rows (engagement start form and fix-attestation
   request form): checkbox + name + badges on one aligned row. */
.engagement-credential-access {
  margin: 0;
  padding: 0.65rem 0.9rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface);
}
.engagement-credential-access legend {
  padding: 0 0.3rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}
.engagement-credential-access p { margin: 0.15rem 0 0.5rem; }
.engagement-credential-option {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding: 0.2rem 0;
  font-size: 0.9rem;
}
.issued-evidence-table .evidence-selection-column {
  width: 2.4rem;
  text-align: center;
}
.evidence-report-table {
  min-width: 760px;
}
.evidence-report-table td {
  vertical-align: middle;
}
.evidence-report-table .evidence-project-column { width: 16%; }
.evidence-report-table .evidence-report-column { width: 38%; }
.evidence-report-table .evidence-findings-column { width: 10%; }
.evidence-report-table .evidence-date-column { width: 13%; }
.evidence-report-table .evidence-integrity-column { width: 16%; }
.evidence-report-table .evidence-actions-column {
  width: 7rem;
  text-align: right;
  white-space: nowrap;
}
.table-icon-actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.2rem;
}
.table-icon-actions form {
  display: inline-flex;
  margin: 0;
}
.icon-action {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  color: var(--link);
  cursor: pointer;
}
.icon-action:hover,
.icon-action:focus-visible {
  border-color: var(--border);
  background: var(--bg-hover);
  color: var(--text-heading);
  text-decoration: none;
  outline: none;
}
.icon-action .material-symbols-outlined {
  font-size: 1.2rem;
  line-height: 1;
}
.icon-action-issued { color: var(--success); }
.finding-summary,
.report-target-context {
  position: relative;
  display: inline-block;
}
.finding-summary > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  min-width: 2.5rem;
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.finding-summary > summary::-webkit-details-marker { display: none; }
.finding-summary > summary:focus-visible,
.report-target-context:focus-visible {
  border-radius: 3px;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.finding-summary-total { font-weight: 600; }
.finding-summary-chevron,
.report-target-context-icon {
  font-size: 0.95rem;
  line-height: 1;
  color: var(--text-muted);
}
.finding-summary[open] .finding-summary-chevron { transform: rotate(180deg); }
.finding-summary-popover,
.report-target-popover {
  display: none;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 30;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-surface);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
  color: var(--text);
  text-align: left;
}
.finding-summary:hover .finding-summary-popover,
.finding-summary:focus-within .finding-summary-popover,
.finding-summary[open] .finding-summary-popover,
.report-target-context:hover .report-target-popover,
.report-target-context:focus .report-target-popover,
.report-target-context:focus-within .report-target-popover {
  display: grid;
}
.finding-summary-popover {
  width: 13rem;
  gap: 0.3rem;
}
.finding-summary-title,
.report-target-kind {
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.finding-summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.8rem;
}
.finding-summary-severity {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.finding-summary-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
}
.finding-summary-dot-critical { background: var(--sev-critical-bg); border: 1px solid var(--sev-critical-fg); }
.finding-summary-dot-high { background: var(--sev-high-bg); border: 1px solid var(--sev-high-fg); }
.finding-summary-dot-medium { background: var(--sev-medium-bg); border: 1px solid var(--sev-medium-fg); }
.finding-summary-dot-low { background: var(--sev-low-bg); border: 1px solid var(--sev-low-fg); }
.finding-summary-dot-info { background: var(--sev-info-bg); border: 1px solid var(--sev-info-fg); }
.report-target-context {
  cursor: help;
  white-space: nowrap;
}
.report-target-context-icon {
  vertical-align: -0.12rem;
}
.report-target-popover {
  width: max-content;
  max-width: min(30rem, 70vw);
  gap: 0.25rem;
  white-space: normal;
}
.report-target-popover .mono {
  overflow-wrap: anywhere;
  user-select: text;
}
@media (min-width: 900px) {
  .evidence-table-scroll { overflow: visible; }
}
.verification-outcome {
  display: inline-flex;
  align-items: center;
  min-height: 1.5rem;
  padding: 0.12rem 0.5rem;
  border-radius: 3px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
}
.outcome-fixed { background: #1e4d2b; color: #9ee6b0; }
.outcome-confirmed { background: var(--error-pre-brd); color: #ffb8b8; }
.outcome-rejected { background: #213e59; color: #a7d4ff; }
.outcome-severity_adjusted { background: #4a3b10; color: #ffd98a; }
[data-theme="light"] .outcome-fixed { background: #d4edda; color: #155724; }
[data-theme="light"] .outcome-confirmed { background: #f8d7da; color: #721c24; }
[data-theme="light"] .outcome-rejected { background: #d8ecff; color: #174a72; }
[data-theme="light"] .outcome-severity_adjusted { background: #fff3cd; color: #856404; }
.outcome-partially_fixed { background: #4a3b10; color: #ffd98a; }
.outcome-not_fixed { background: var(--error-pre-brd); color: #ffb8b8; }
.outcome-unable_to_verify { background: #343a40; color: var(--text); }
.outcome-accepted_risk { background: #213e59; color: #a7d4ff; }
[data-theme="light"] .outcome-partially_fixed { background: #fff3cd; color: #856404; }
[data-theme="light"] .outcome-not_fixed { background: #f8d7da; color: #721c24; }
[data-theme="light"] .outcome-unable_to_verify { background: #e9ecef; color: #343a40; }
[data-theme="light"] .outcome-accepted_risk { background: #d8ecff; color: #174a72; }
.verification-downloads,
.verification-save-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.verification-publish .zq-btn:disabled {
  cursor: not-allowed;
  filter: saturate(0.35);
  opacity: 0.45;
}
.verification-results-table {
  min-width: 980px;
  table-layout: fixed;
}
.verification-results-table th:nth-child(1) { width: 24%; }
.verification-results-table th:nth-child(2) { width: 10%; }
.verification-results-table th:nth-child(3) { width: 18%; }
.verification-results-table th:nth-child(4) { width: 48%; }
.verification-results-table select,
.verification-results-table textarea {
  width: 100%;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text);
  padding: 0.45rem 0.55rem;
}
.verification-results-table textarea {
  resize: vertical;
  font: inherit;
  line-height: 1.4;
}
.verification-field {
  display: block;
  margin-bottom: 0.55rem;
  color: var(--text-muted);
  font-size: 0.78rem;
}
.verification-field:last-child { margin-bottom: 0; }
.verification-field > span { display: block; margin-bottom: 0.2rem; }
/* Field controls fill their label. The element bridge deliberately leaves
   control layout element-default, and this family's blocks are the layout
   residue — without this the controls collapse to browser-default width
   (the verification page never noticed because its editors sit in
   .verification-results-table, which sizes its own controls). */
.verification-field > input[type="text"],
.verification-field > input[type="password"],
.verification-field > input[type="url"],
.verification-field > input[type="email"],
.verification-field > select,
.verification-field > textarea {
  display: block;
  width: 100%;
}
.verification-method { display: block; margin-top: 0.35rem; }
.verification-save-row { margin-top: 0.75rem; }
.verification-evidence-list { margin: 0.4rem 0; padding-left: 1.2rem; }
.verification-row-status {
  display: inline-block;
  margin-top: 0.4rem;
  padding: 0.08rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 600;
  white-space: nowrap;
}
.verification-row-status.is-ready { color: var(--success); border-color: var(--success); }
.verification-row-status.is-incomplete {
  color: var(--warn-text);
  background: var(--warn-bg);
  border-color: var(--warn-border);
}
.verification-results-table tr[data-finding-row] { scroll-margin-top: 4.5rem; }
.verification-evidence-count { margin-left: 0.35rem; font-weight: 400; }
.verification-field-error {
  display: block;
  margin-top: 0.25rem;
  color: var(--error);
  font-size: 0.78rem;
}
/* display:block above would defeat the hidden attribute's UA display:none. */
.verification-field-error[hidden] { display: none; }
.verification-saved-note { color: var(--success); font-size: 0.8rem; }
.verification-jump-link { margin-left: auto; }
.verification-save-error {
  flex-basis: 100%;
  margin-top: 0.4rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--warn-border);
  border-radius: 6px;
  background: var(--warn-bg);
  color: var(--warn-text);
  font-size: 0.85rem;
}
.compact-kv-grid { margin-top: 0.65rem; }
.danger-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* Engagement added findings: the per-finding edit form toggles open as a
   full-width subrow under its own row (same [hidden]-in-markup pattern as
   the version subrow). The Manage cell is only as wide as its buttons, so
   an in-cell form has nowhere to go. */
.added-finding-edit-row > td { background: var(--bg-surface2); }
.added-finding-edit-row form { margin: 0; }
.added-finding-edit-toggle[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

/* Scheduled-scans form: a responsive grid for the cadence/time/tz/mode
   controls, with `data-cadence-only` rows hidden by JS based on the
   active cadence. */
/* Class-based display rules above outrank the UA's `[hidden]` selector,
   so the schedule grid + cadence-only labels + Save button would stay
   visible even when the toggle is off. Restore `hidden`. */
#schedule-save[hidden] { display: none; }
.cadence-schedule [data-cadence-only] {
  display: none !important;
}
.cadence-schedule:has(select[name="cadence"] option[value="weekly"]:checked) [data-cadence-only="weekly"],
.cadence-schedule:has(select[name="cadence"] option[value="monthly"]:checked) [data-cadence-only="monthly"] {
  display: block !important;
}
.rescan-form textarea {
  display: block; width: 100%; padding: 0.55rem 0.7rem; margin-top: 0.35rem;
  background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: 4px; color: var(--text-code);
  font-family: var(--zq-font-family-mono); font-size: 0.88rem;
}
.inline-form {
  display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;
}
.inline-form input[type="text"],
.inline-form select {
  min-width: 180px;
  flex: 1;
  margin-top: 0;
}
.account-pref-form {
  align-items: flex-start;
  flex-wrap: nowrap;
}
.account-pref-form label:not(.checkbox) {
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
  flex: 0 1 200px;
  min-width: 160px;
  font-size: 0.875rem;
}
.account-pref-form label.checkbox {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0;
  flex: 0 1 auto;
  font-size: 0.875rem;
}
.account-pref-form input[type="number"] {
  min-width: 6rem;
}
/* Align Save with the input field next to a stacked label. */
.account-pref-form:not(.checkbox-form) .zq-btn {
  align-self: flex-start;
  margin-top: 0;
  margin-bottom: 0;
  position: relative;
  top: -1px;
}
.account-pref-form.checkbox-form {
  align-items: center;
}
.account-pref-form.checkbox-form .zq-btn {
  margin: 0;
}
.source-input-choice {
  margin: 0 0 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-surface2);
}
.source-input-choice legend {
  padding: 0 0.35rem;
  font-weight: 600;
  color: var(--text-heading);
}
.source-input-option {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.65rem;
  align-items: start;
  margin-bottom: 0.7rem;
}
.source-input-option:last-child {
  margin-bottom: 0;
}
.source-input-option input {
  margin-top: 0.25rem;
}
[data-source-input-panel][hidden] {
  display: none;
}

/* ---- Guided scan setup ----------------------------------------- */
.scan-wizard-shell {
  width: min(900px, 100%);
  margin: 0 auto 3rem;
}
.scan-wizard-head {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.9rem 1rem;
  align-items: center;
  margin-bottom: 1.5rem;
}
.scan-wizard-head .breadcrumbs { grid-column: 1 / -1; margin: 0; }
.scan-wizard-head h1 { margin: 0 0 0.25rem; }
.scan-wizard-head p { margin: 0; }
.scan-kind-icon {
  display: inline-flex;
  width: 3.2rem;
  height: 3.2rem;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-surface2));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  color: var(--accent);
  font: 700 0.95rem var(--zq-font-family-mono);
}
.scan-kind-icon.remote { color: #2fae92; background: color-mix(in srgb, #2fae92 14%, var(--bg-surface2)); border-color: color-mix(in srgb, #2fae92 34%, var(--border)); }
.scan-kind-icon.binary { color: #b77be8; background: color-mix(in srgb, #b77be8 14%, var(--bg-surface2)); border-color: color-mix(in srgb, #b77be8 34%, var(--border)); }
.scan-kind-icon.material-symbols-outlined {
  font-family: "Material Symbols Outlined";
  font-size: 1.5rem;
  font-weight: 400;
  font-feature-settings: "liga";
  -webkit-font-feature-settings: "liga";
}
.scan-wizard {
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-surface2);
  box-shadow: 0 16px 45px color-mix(in srgb, #000 14%, transparent);
}
.scan-stepper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  margin: 0;
  padding: 1rem 1.5rem;
  list-style: none;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-inset) 72%, transparent);
}
.scan-stepper li {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 600;
}
.scan-stepper li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: calc(50% + 2.7rem);
  right: calc(-50% + 2.7rem);
  top: 50%;
  height: 1px;
  background: var(--border);
}
.scan-stepper li span {
  display: inline-flex;
  width: 1.55rem;
  height: 1.55rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-surface2);
  font-size: 0.75rem;
  z-index: 1;
}
.scan-stepper li.active { color: var(--text-heading); }
.scan-stepper li.active span,
.scan-stepper li.complete span { border-color: var(--accent); background: var(--accent); color: white; }
.scan-stepper li.complete { color: var(--text); }
.scan-wizard-step { padding: 2rem; min-height: 350px; }
.scan-wizard-step[hidden] { display: none; }
.step-heading { margin-bottom: 1.5rem; }
.step-heading > span { color: var(--accent); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.step-heading h2 { margin: 0.3rem 0 0.35rem; }
.step-heading p { margin: 0; }
.scan-choice-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.8rem;
  align-items: stretch;
  margin: 0 0 1.25rem;
  padding: 0;
  border: 0;
  background: none;
}
.scan-choice-card {
  position: relative;
  display: flex;
  min-height: 118px;
  flex-direction: column;
  gap: 0.7rem;
  margin: 0;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, transform 120ms ease;
}
.scan-choice-grid .scan-choice-card,
.scan-choice-grid .scan-choice-card:last-child {
  height: 100%;
  box-sizing: border-box;
  margin: 0;
}
.scan-choice-card:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: var(--bg-hover); }
.scan-choice-card:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg-inset)); }
.scan-choice-card:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }
.scan-choice-card:has(input:disabled):hover { transform: none; border-color: var(--border); background: var(--bg-inset); }
.scan-choice-card input { position: absolute; top: 0.8rem; right: 0.8rem; }
.scan-choice-card strong,
.scan-choice-card .muted { display: block; }
.scan-choice-card .muted { margin-top: 0.25rem; font-weight: 400; line-height: 1.45; }
.scan-choice-icon:not(.material-symbols-outlined) {
  display: inline-flex;
  width: 2.2rem;
  height: 2.2rem;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-surface2));
  color: var(--accent);
  font: 700 0.75rem var(--zq-font-family-mono);
}
.source-input-panel { padding: 1rem; border: 1px solid var(--border); border-radius: 9px; background: var(--bg-inset); }
.repo-search-label input[type="search"],
.scan-form input[type="password"],
.scan-form input[type="search"] {
  display: block; width: 100%; margin-top: 0.35rem;
}
.repo-picker-list { max-height: 230px; overflow: auto; margin-top: 0.75rem; border: 1px solid var(--border); border-radius: 6px; }
.repo-picker-row { display: grid !important; grid-template-columns: auto 1fr; gap: 0.7rem; align-items: start; margin: 0 !important; padding: 0.7rem 0.8rem; border-bottom: 1px solid var(--border); cursor: pointer; }
.repo-picker-row:last-child { border-bottom: 0; }
.repo-picker-row:hover { background: var(--bg-hover); }
.repo-picker-row span span { display: block; margin-top: 0.15rem; font-weight: 400; }
.connect-panel { padding: 1rem; text-align: center; }
.connect-panel h3 { margin-top: 0; }
.drop-zone { padding: 0; border: 1px dashed color-mix(in srgb, var(--accent) 55%, var(--border)); background: color-mix(in srgb, var(--accent) 5%, var(--bg-inset)); }
.drop-zone.dragging { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--bg-inset)); }
.drop-zone label { display: flex; min-height: 155px; align-items: center; justify-content: center; flex-direction: column; gap: 0.45rem; margin: 0; padding: 1.2rem; text-align: center; cursor: pointer; }
.drop-zone input[type="file"] { width: min(420px, 100%); margin-top: 0.5rem; }
.drop-zone-icon { display: inline-flex; width: 2.6rem; height: 2.6rem; align-items: center; justify-content: center; border-radius: 999px; background: color-mix(in srgb, var(--accent) 15%, var(--bg-surface2)); color: var(--accent); font-size: 1.3rem; }
.scan-fields-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.scan-default-summary { display: flex; gap: 0.8rem; padding: 1rem; margin-bottom: 1rem; border: 1px solid color-mix(in srgb, var(--success) 40%, var(--border)); border-radius: 8px; background: color-mix(in srgb, var(--success) 7%, var(--bg-inset)); }
.scan-default-summary p { margin: 0.2rem 0 0; }
.summary-check { display: inline-flex; width: 1.5rem; height: 1.5rem; flex: 0 0 auto; align-items: center; justify-content: center; border-radius: 999px; background: var(--success); color: white; font-weight: 700; }
.scan-advanced { border: 1px solid var(--border); border-radius: 8px; background: var(--bg-inset); }
.scan-advanced > summary { padding: 0.9rem 1rem; cursor: pointer; }
.scan-advanced > summary > span,
.scan-advanced > summary span span { display: block; }
.scan-advanced > summary span span { margin-top: 0.15rem; font-weight: 400; }
.scan-advanced-body { padding: 1rem; border-top: 1px solid var(--border); }
.scan-advanced-body > :last-child { margin-bottom: 0; }
.scan-wizard-actions { display: flex; align-items: center; gap: 0.9rem; padding: 1rem 1.5rem; border-top: 1px solid var(--border); background: color-mix(in srgb, var(--bg-inset) 72%, transparent); }
.scan-wizard-actions [hidden] { display: none; }
.scan-wizard-spacer { flex: 1; }
.scan-step-error { padding: 0.7rem 0.8rem; margin: 1rem 0 0; border-radius: 6px; background: color-mix(in srgb, var(--error) 12%, transparent); color: var(--error); font-weight: 600; white-space: pre-line; }
.authorization-check { padding: 0.85rem; border: 1px solid var(--border); border-radius: 7px; background: var(--bg-inset); }
.access-option-grid { display: grid; gap: 0.75rem; }
.access-card { margin: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-inset); }
.access-card > summary { padding: 0.9rem 1rem; cursor: pointer; }
.access-card > summary strong,
.access-card > summary span { display: block; }
.access-card > summary span { margin: 0.2rem 0 0; font-weight: 400; }
.access-card-body { padding: 0 1rem 1rem; }
.auth-subsection { margin: 0 0 1rem; padding: 1rem; border: 1px solid var(--border); border-radius: 7px; }
.auth-subsection legend { padding: 0 0.35rem; font-weight: 600; }

/* ---- First-scan project state ---------------------------------- */
.project-empty-state { width: min(1040px, 100%); margin: clamp(2rem, 8vh, 6rem) auto 4rem; text-align: center; }
.project-profile-heading { display: flex; justify-content: center; align-items: center; gap: 0.55rem; margin-bottom: 0.65rem; color: var(--text-muted); font-size: 0.85rem; }
/* Profile chip: .zq-badge base with the accent tint; profile names
   read as names, so no uppercase. */
.project-profile-badge {
  text-transform: none;
  border-color: color-mix(in srgb, var(--accent) 42%, var(--border));
  background: color-mix(in srgb, var(--accent) 9%, var(--bg-inset));
  color: var(--text-heading);
}
.project-profile-line { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin: 0.35rem 0; }
.project-empty-state h1 { margin: 0 0 0.5rem; font-size: 2.25rem; }
.project-empty-state > p { max-width: 620px; margin: 0 auto; }
.empty-state-footnote { font-size: 0.85rem; }
.project-empty-actions { display: flex; justify-content: center; gap: 0.65rem; margin: 1.5rem 0 1rem; }
.project-name-row { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; }
.project-profile-current { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 0.8rem; align-items: center; max-width: 780px; }
.project-profile-current p { margin: 0.2rem 0 0; }

/* ---- Guided project profile setup ----------------------------- */
.project-wizard-shell { width: min(1040px, 100%); }
.project-wizard-shell .scan-stepper { grid-template-columns: repeat(2, 1fr); }
.project-profile-choice-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.project-profile-choice {
  --profile-color: var(--accent);
  grid-column: span 2;
  min-height: 190px;
  padding: 1.1rem;
}
.project-profile-choice:nth-of-type(4) { grid-column: 2 / span 2; }
.project-profile-choice.profile-black_box { --profile-color: #2fae92; }
.project-profile-choice.profile-grey_box { --profile-color: #d49b35; }
.project-profile-choice.profile-white_box { --profile-color: #a66ddd; }
.project-profile-choice.profile-custom { --profile-color: #78909c; }
.project-profile-choice:has(input:checked) {
  border-color: var(--profile-color);
  box-shadow: 0 0 0 1px var(--profile-color);
  background: color-mix(in srgb, var(--profile-color) 8%, var(--bg-inset));
}
.project-profile-choice .scan-choice-icon {
  background: color-mix(in srgb, var(--profile-color) 14%, var(--bg-surface2));
  color: var(--profile-color);
  font-family: "Material Symbols Outlined";
  font-size: 1.25rem;
}

/* Asset-kind picker on the project assets page. The default
   .scan-choice-icon rule uses a monospace font (it's designed for
   things like "SSH" or "GIT" type chips); the asset kinds here are
   Material Symbols ligature names that need the icon font to render
   properly. ``font-feature-settings: 'liga'`` is required for some
   browsers to actually pick up the ligature (otherwise the text
   shows the raw "globe" / "code" / "lan" string). */
.asset-kind-choice { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.asset-kind-choice .scan-choice-icon {
  font-family: "Material Symbols Outlined";
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 1;
  width: 2.6rem;
  height: 2.6rem;
  font-feature-settings: "liga";
  -webkit-font-feature-settings: "liga";
}

/* List table: kind and source chips. Small, but color-coded to match
   the form-card colors above so the eye carries the association
   across the two surfaces. Shape and typography come from .zq-badge;
   these rules keep the mono code-treatment and the per-kind hue. The
   color rules are unscoped so every surface that shows an asset kind
   (assets table, reports table, scan-move plan) shares the same hue. */
.asset-kind-chip {
  font: 600 0.7rem/1 var(--zq-font-family-mono);
  color: var(--asset-chip-color, var(--text-muted));
  background: color-mix(in srgb, var(--asset-chip-color, var(--text-muted)) 14%, var(--bg-inset));
}
.asset-kind-chip.kind-url  { --asset-chip-color: #2fae92; }
.asset-kind-chip.kind-repo { --asset-chip-color: #3f8ae0; }
.asset-kind-chip.kind-host { --asset-chip-color: #d49b35; }

.project-reports-table .asset-kind-chip { vertical-align: middle; }

a.asset-kind-chip { text-decoration: none; }
/* Asset target link in the Assets tab. The whole URL cell
   becomes a link, but we keep the monospace code-style
   treatment so the URL still reads as code. */
.asset-target-link {
  text-decoration: none;
  color: inherit;
}
.asset-target-link:hover code.asset-target {
  background: var(--bg-hover);
}
.asset-scanned-cell { white-space: nowrap; }

/* Asset coverage line on the project page head. Sits
   under the "N reports" line as a secondary stat that
   links to the Assets tab. The unscanned-count tag uses a
   subtle warm tint so the gap is visible without being
   alarming. */
.asset-coverage-line { margin-top: 0.15rem; }
.asset-coverage-line a { text-decoration: none; color: var(--text); }
.asset-coverage-line a:hover strong { color: var(--link); }
.asset-coverage-gap {
  margin-left: 0.35rem;
  color: var(--warning, #b15b00);
  font-size: 0.78rem;
  font-weight: 500;
}

/* Scan-move wizard. The page is a single column with a
   per-target table; the action chip is color-coded by the
   kind of action (link / create / none) so the eye can
   scan the table quickly. */
.scan-move-shell { max-width: 1100px; margin: 0 auto; }
.scan-move-head h1 { margin: 0.4rem 0 0.5rem; }
.scan-move-head .breadcrumbs { font-size: 0.85rem; }
.scan-move-plan { font-size: 0.85rem; }
.scan-move-plan code.mono { font-size: 0.78rem; word-break: break-all; }
.scan-move-plan .asset-kind-chip { display: inline-block; }
.scan-move-row.scan-move-link .scan-move-action { background: color-mix(in srgb, var(--link) 14%, var(--bg-inset)); color: var(--link); }
.scan-move-row.scan-move-create .scan-move-action { background: color-mix(in srgb, #d49b35 18%, var(--bg-inset)); color: #b15b00; }
.scan-move-row.scan-move-none .scan-move-action { background: var(--bg-inset); color: var(--text-muted); }
.scan-move-action {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  font: 600 0.7rem/1 var(--zq-font-family-mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.scan-move-form { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.75rem; }
.scan-move-form textarea { width: 100%; }
.scan-move-actions { display: flex; align-items: center; gap: 1rem; justify-content: flex-end; }

/* History section on the scan detail page. Sits between the
   KV metadata and the queued-scan / progress / findings
   sections, so the operator sees the project moves in the
   same place they see the version dropdown. Newest-first
   list with the source and destination project names as
   links — the audit story is "this scan was at X, now it's
   at Y, here's what came with it." */
.scan-history-section {
  margin: 1.25rem 0 0.5rem;
  padding: 0.85rem 1rem 0.65rem;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.scan-history-section h2 {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 0.55rem;
}
.scan-history-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.scan-history-list li { line-height: 1.4; }

/* Asset detail page. Two-column grid on wider screens so
   the Target (left) and Scan coverage (right) sections sit
   side by side; on narrow screens the grid collapses to a
   single column. The chip + button layout reuses the asset
   kind color tokens so the detail page feels like the rest
   of the library. */
.asset-detail-shell { max-width: 960px; margin: 0 auto; }
.asset-detail-head { margin-bottom: 1.5rem; }
.asset-detail-head-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.25rem;
  justify-content: space-between;
  margin-top: 0.5rem;
}
.asset-detail-title { flex: 1 1 320px; min-width: 0; }
.asset-detail-title h1 {
  margin: 0.5rem 0 0;
  font-size: 1.6rem;
  line-height: 1.2;
}
.asset-detail-title p { margin: 0.25rem 0 0; word-break: break-all; }
/* Inline asset-name editor — same affordances as the project
   title. The input replaces the static <h1> text; hover/focus
   shows the editing surface (subtle background + border ring).
   No visible button — Enter / blur / Escape are the controls,
   matching the project-title UX so a "let me click here to
   rename" gesture is consistent across the app. */
.asset-title-form { margin: 0; }
.asset-title-wrap { margin: 0.5rem 0 0; }
.asset-title-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.08rem 0.3rem;
  margin-left: -0.3rem;
  border: none;
  background: transparent;
  color: var(--text-heading);
  font: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  border-radius: 6px;
  box-shadow: 0 0 0 1px transparent;
}
.asset-title-input:hover,
.asset-title-input:focus {
  background: var(--bg-surface2);
  box-shadow: 0 0 0 1px var(--border);
  outline: none;
}
.asset-detail-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
/* Scan-status badge on the asset detail coverage list. Reuses
   the same status colors as the scan detail page / Scans tab so
   an in-progress scan looks the same everywhere. */
.asset-detail-scan-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.asset-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1.25rem;
}
.asset-detail-section {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
}
.asset-detail-section h2 {
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 0.85rem;
}
.asset-detail-dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.45rem 1rem;
  margin: 0;
}
.asset-detail-dl dt {
  color: var(--text-muted);
  font-size: 0.85rem;
  align-self: center;
}
.asset-detail-dl dd { margin: 0; min-width: 0; word-break: break-all; }
.asset-detail-dl .asset-target {
  background: var(--bg-inset);
  padding: 0.25rem 0.55rem;
  border-radius: 6px;
  font-size: 0.85rem;
}
.asset-detail-scan-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.asset-detail-scan-list li {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.asset-detail-scan-list li .mono { font-weight: 500; }

/* Source chips are neutral badges; only the mono code-treatment is
   app-side. */
.asset-source-chip {
  font: 500 0.7rem/1 var(--zq-font-family-mono);
  letter-spacing: 0.04em;
}
.project-assets-table .asset-target {
  font: 500 0.85rem/1.4 var(--zq-font-family-mono);
  color: var(--text-code);
  word-break: break-all;
}
.project-assets-table .inline-form { display: inline; }

/* Icon-only action buttons. Used in two places:
   - the per-row "Run scan" / "Remove" / "Edit" buttons
     on the project's Assets tab (column stays narrow —
     the asset name + URL is what the operator scans,
     not button text);
   - the asset detail page's action bar (Run / Remove /
     Edit) so the three actions read as a single
     consistent icon group rather than a mismatched
     blue button + blue link + blue icon.

   The visible affordance is the Material Symbol; the
   ``aria-label`` carries the action to AT and the
   ``title`` carries it to mouse hover. Color follows
   the existing danger / primary / link conventions:
   - ``.icon-btn`` (default) — neutral, muted text
   - ``.icon-btn.primary`` — the primary action
     (Run scan) in the accent color so it still reads
     as the most-affordant action even without the
     full button background
   - ``.icon-btn.danger`` — destructive (Remove)
     in the error color. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: 6px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.icon-btn:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.icon-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.icon-btn .material-symbols-outlined {
  font-size: 1.15rem;
  line-height: 1;
}
.icon-btn.primary {
  color: var(--accent);
}
.icon-btn.primary:hover {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.icon-btn.danger {
  color: var(--error);
}
.icon-btn.danger:hover {
  background: color-mix(in srgb, var(--error) 12%, transparent);
  color: var(--error);
}
/* Disabled / aria-disabled placeholder — same shape
   as the real button so the action bar doesn't shift
   when the gate toggles on/off (e.g. an in-progress
   scan suppresses the "Run new scan" CTA). */
.icon-btn.disabled,
.icon-btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

/* Archived assets section on the project page. Default-
   collapsed <details> so the archived list doesn't
   clutter the main view, but one click expands the
   same table shape (unarchive / delete-permanently
   actions per row). The summary marker uses the
   archive icon so the collapsed state is recognizable
   even before the operator clicks in. */
.project-archived-section {
  margin-top: 1.25rem;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1.1rem;
}
.project-archived-section > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.project-archived-section > summary::-webkit-details-marker {
  display: none;
}
.project-archived-section > summary::before {
  content: "▶";
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.project-archived-section[open] > summary::before {
  transform: rotate(90deg);
}
.project-archived-section > summary > .material-symbols-outlined {
  color: var(--text-muted);
  font-size: 1.15rem;
}
.project-assets-archived-table {
  margin-top: 0.85rem;
  opacity: 0.85;
}
.project-assets-archived-table .asset-source-chip,
.project-assets-archived-table .asset-kind-chip {
  filter: saturate(0.6);
}
.project-assets-archived-row td {
  font-style: italic;
  color: var(--text-muted);
}
/* Asset-archived banner on the asset detail page. Sits
   above the page header so the operator can't miss it —
   the asset is no longer in the active list, but the
   page is reachable via scan-history links. */
.asset-archived-banner {
  margin: 0 auto 1rem;
  max-width: 960px;
}

/* Per-kind form panels: the kind picker above reveals a panel
   (url / host / repo) with kind-specific fields. We layer the
   asset-specific layout tweaks on top of the scan form's
   `.source-input-panel` so the visual treatment stays in lock-
   step with the new-scan wizard. */
.asset-kind-panel[hidden] { display: none; }
.asset-kind-panel {
  margin-top: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.asset-kind-panel[hidden] { display: none; }
/* Auth-type row of radio buttons: a horizontal list of "None /
   Basic / Bearer / Cookie / Username/password" inside the access
   card. Mirrors the access-option-grid pattern from the remote
   scan form. Custom headers is a separate section (a peer to
   this row), not gated by a radio, so the user can combine
   custom headers with any auth type. */
.asset-auth-choice {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.85rem;
  margin: 0.25rem 0 0.5rem;
}
.asset-auth-choice label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.88rem;
  cursor: pointer;
}
/* CSS-only radio-toggle for auth sub-panels. The JS in app.js
   (initAssetForm → showPanel/hidePanel) does the same job, but
   this CSS guarantees the right behaviour even when the JS
   hasn't loaded yet (slow connection, blocked by an extension,
   etc.) — the user always sees the credentials fields for the
   auth type they picked. ``:has()`` is supported in all
   modern browsers (Chrome 105+, Safari 15.4+, Firefox 121+);
   for older browsers the JS path still works. The
   ``!important`` here is load-bearing: it has to beat both
   the user-agent ``details[open] > *:not(summary) { display:
   block; }`` rule and the ``.is-hidden`` class fallback, so
   the panel actually shows when the matching radio is on. */
/* Default: every auth sub-panel is hidden. */
.access-card-body [data-asset-auth-panel] {
  display: none;
}
/* Show the panel that matches the currently-checked radio. */
.access-card-body:has(input[name="url_auth_type"][value="basic"]:checked) [data-asset-auth-panel="basic"],
.access-card-body:has(input[name="url_auth_type"][value="bearer"]:checked) [data-asset-auth-panel="bearer"],
.access-card-body:has(input[name="url_auth_type"][value="cookie"]:checked) [data-asset-auth-panel="cookie"],
.access-card-body:has(input[name="url_auth_type"][value="form_login"]:checked) [data-asset-auth-panel="form_login"],
.access-card-body:has(input[name="host_auth_type"][value="credentials"]:checked) [data-asset-auth-panel="host_credentials"] {
  display: block !important;
}
.asset-summary-line {
  display: block;
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 0.15rem;
}
  margin-top: 0.15rem;
}
.project-profile-choice-copy { display: flex; flex: 1; flex-direction: column; }
.project-profile-choice-copy strong { margin-top: 0.35rem; font-size: 1rem; }
.project-profile-choice-copy .muted { margin-top: 0.35rem; }
.project-profile-choice-kicker {
  color: var(--profile-color);
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
}
.project-profile-choice-examples {
  margin-top: auto;
  padding-top: 0.75rem;
  color: var(--text-muted);
  font-size: 0.72rem;
}
.project-details-step { min-height: 300px; }
.project-name-field { display: block; max-width: 620px; }
.project-profile-summary { max-width: 620px; margin-top: 1.25rem; }
.project-profile-edit-step { min-height: 0; }

@media (max-width: 760px) {
  .scan-choice-grid { grid-template-columns: 1fr; }
  .project-profile-choice,
  .project-profile-choice:nth-of-type(4) { grid-column: 1; }
  .scan-choice-card { min-height: 105px; }
  .scan-fields-grid { grid-template-columns: 1fr; gap: 0; }
  .scan-wizard-step { padding: 1.25rem; }
  .scan-stepper { padding-inline: 0.8rem; }
  .scan-stepper li:not(:last-child)::after { display: none; }
  .scan-wizard-actions { padding-inline: 1rem; }
  .project-empty-state h1 { font-size: 1.75rem; }
  .project-empty-actions { align-items: stretch; flex-direction: column; width: min(280px, 100%); margin-inline: auto; }
  .project-profile-current { grid-template-columns: auto 1fr; }
  .project-profile-current .zq-btn { grid-column: 1 / -1; justify-self: start; }
}

/* ---- Private Git credential onboarding ------------------------ */
.git-credentials-page {
  width: min(1000px, 100%);
  margin: 0 auto 4rem;
}
.git-credentials-head {
  margin-bottom: 1rem;
}
.git-credentials-head .breadcrumbs { margin-bottom: 1.25rem; }
.git-setup-eyebrow {
  margin: 0 0 0.35rem;
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.git-credentials-head h1 { margin: 0 0 0.4rem; }
.git-credentials-head .muted { margin: 0; font-size: 1rem; }
.git-plan-notice { margin-top: 1.5rem; }
.git-saved-section,
.git-setup-section {
  margin-top: 1.5rem;
}
.git-section-heading {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: end;
  margin-bottom: 0.75rem;
}
.git-section-heading h2 { margin: 0; }
.git-section-heading p { margin: 0.25rem 0 0; }
.git-credential-count {
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-muted);
  font-size: 0.75rem;
}
.git-credential-list {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg-surface2);
}
.git-credential-row {
  display: grid;
  grid-template-columns: auto minmax(180px, 1fr) auto auto;
  gap: 0.9rem;
  align-items: center;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
}
.git-credential-row:last-child { border-bottom: 0; }
.git-credential-kind {
  display: inline-flex;
  min-width: 3.4rem;
  justify-content: center;
  padding: 0.25rem 0.4rem;
  border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-inset));
  color: var(--accent);
  font-size: 0.68rem;
  font-weight: 750;
  letter-spacing: 0.05em;
}
.git-credential-kind.ssh { color: #a66ddd; background: color-mix(in srgb, #a66ddd 12%, var(--bg-inset)); }
.git-credential-main strong,
.git-credential-main span { display: block; }
.git-credential-main span { margin-top: 0.15rem; color: var(--text-muted); font-size: 0.8rem; }
.git-credential-safety { color: var(--success); font-size: 0.75rem; }
.danger-text { color: var(--error); }
.git-setup-wizard { width: 100%; }
.git-setup-wizard .scan-wizard-step { min-height: 400px; }
.git-setup-wizard .step-heading h3 { margin: 0.3rem 0 0.35rem; font-size: 1.35rem; }
.git-provider-grid,
.git-auth-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.7rem;
  margin: 0;
  padding: 0;
  border: 0;
}
.git-auth-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.git-provider-card,
.git-auth-card {
  position: relative;
  display: flex;
  min-height: 100px;
  box-sizing: border-box;
  align-items: center;
  margin: 0;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
  cursor: pointer;
}
.git-auth-card { min-height: 112px; align-items: flex-start; }
.git-provider-card:hover,
.git-auth-card:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: var(--bg-hover); }
.git-provider-card:has(input:checked),
.git-auth-card:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-inset));
  box-shadow: 0 0 0 1px var(--accent);
}
.git-provider-card input,
.git-auth-card input { position: absolute; top: 0.75rem; right: 0.75rem; }
.git-provider-card strong,
.git-provider-card span span,
.git-auth-card strong,
.git-auth-card span span { display: block; }
.git-provider-card span span { margin-top: 0.25rem; color: var(--text-muted); font-size: 0.75rem; font-weight: 400; }
.git-auth-card .muted { margin-top: 0.45rem; padding-right: 1rem; font-weight: 400; line-height: 1.4; }
.git-auth-card.disabled { opacity: 0.48; cursor: not-allowed; }
.recommended-label {
  display: inline-block !important;
  width: fit-content;
  margin-top: 0.35rem;
  padding: 0.12rem 0.4rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success);
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
}
.git-github-app-hint {
  margin-top: 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
  border-radius: 7px;
  background: color-mix(in srgb, var(--accent) 5%, var(--bg-inset));
  font-size: 0.85rem;
}
.git-permission-guide {
  margin: 1rem 0;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
}
.git-permission-guide[hidden],
[data-git-auth-panel][hidden],
.git-github-app-hint[hidden] { display: none; }
.git-permission-guide-head {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--border);
}
.git-permission-guide-head span { color: var(--text-muted); font-size: 0.78rem; }
.git-permission-guide ol { margin: 0.8rem 0; padding-left: 1.25rem; }
.git-permission-guide li { margin-bottom: 0.45rem; color: var(--text); font-size: 0.84rem; line-height: 1.45; }
.git-permission-result {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.65rem;
  align-items: center;
  padding: 0.7rem 0.8rem;
  margin: 0.8rem 0;
  border-radius: 6px;
  background: color-mix(in srgb, var(--success) 8%, var(--bg-surface2));
  font-size: 0.8rem;
}
.git-permission-result span { color: var(--text-muted); }
.git-save-summary {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  padding: 1rem;
  margin: 0.25rem 0 1rem;
  border: 1px solid color-mix(in srgb, var(--success) 35%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--success) 6%, var(--bg-inset));
}
.git-save-summary p { margin: 0.2rem 0 0; }

@media (max-width: 820px) {
  .git-provider-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .git-credential-row { grid-template-columns: auto 1fr auto; }
  .git-credential-safety { display: none; }
}
@media (max-width: 560px) {
  .git-provider-grid,
  .git-auth-grid { grid-template-columns: 1fr; }
  .git-credential-row { grid-template-columns: auto 1fr; }
  .git-credential-row form { grid-column: 2; }
  .git-permission-guide-head { display: block; }
  .git-permission-guide-head span { display: block; margin-top: 0.2rem; }
}

/* ---- Private runner onboarding -------------------------------- */
.private-runners-page {
  width: min(1000px, 100%);
  margin: 0 auto 4rem;
}
.private-runners-head { margin-bottom: 1rem; }
.private-runners-head h1 { margin: 0 0 0.4rem; }
.private-runners-head .muted { max-width: 720px; margin: 0; font-size: 1rem; }
.runner-safety-strip,
.runner-review-summary {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  padding: 0.9rem 1rem;
  border: 1px solid color-mix(in srgb, var(--success) 32%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--success) 6%, var(--bg-inset));
}
.runner-safety-strip { margin-top: 1.5rem; }
.runner-safety-strip p,
.runner-review-summary p { margin: 0.2rem 0 0; }
.runner-setup-section,
.runner-inventory-section { margin-top: 1.75rem; }
.runner-setup-wizard { width: 100%; }
.runner-setup-wizard .scan-wizard-step { min-height: 390px; }
.runner-setup-wizard .step-heading h3 { margin: 0.3rem 0 0.35rem; font-size: 1.35rem; }
.runner-pool-name {
  display: block;
  max-width: 580px;
  margin: 1.2rem 0;
  font-weight: 650;
}
.runner-pool-name input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 0.45rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--input-border);
  border-radius: 7px;
  background: var(--input-bg);
  color: var(--text-code);
  font-size: 1rem;
}
.runner-example-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.65rem;
  margin: 1rem 0;
}
.runner-example-grid > div {
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--bg-inset);
}
.runner-example-grid strong,
.runner-example-grid span { display: block; }
.runner-example-grid strong { color: var(--text-muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }
.runner-example-grid span { margin-top: 0.25rem; font-size: 0.86rem; }
.runner-mode-grid,
.runner-policy-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  border: 0;
}
.runner-choice-card {
  position: relative;
  display: flex;
  min-height: 145px;
  box-sizing: border-box;
  align-items: flex-start;
  margin: 0;
  padding: 1.1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
  cursor: pointer;
}
.runner-choice-card:hover {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  background: var(--bg-hover);
}
.runner-choice-card:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-inset));
  box-shadow: 0 0 0 1px var(--accent);
}
.runner-choice-card input { position: absolute; top: 0.9rem; right: 0.9rem; }
.runner-choice-card > span { padding-right: 1.1rem; }
.runner-choice-card strong,
.runner-choice-card > span > span { display: block; }
.runner-choice-card > span > span:not(.recommended-label) {
  margin-top: 0.5rem;
  color: var(--text-muted);
  font-size: 0.83rem;
  font-weight: 400;
  line-height: 1.45;
}
.runner-permission-note {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border-left: 3px solid var(--accent);
  border-radius: 0 7px 7px 0;
  background: color-mix(in srgb, var(--accent) 5%, var(--bg-inset));
  color: var(--text-muted);
  font-size: 0.84rem;
}
.runner-permission-note strong { color: var(--text); }
.runner-review-summary { margin-top: 1rem; }

.runner-enrollment-card {
  margin-top: 1.5rem;
  padding: clamp(1.1rem, 3vw, 1.6rem);
  border: 1px solid color-mix(in srgb, var(--success) 42%, var(--border));
  border-radius: 10px;
  background: color-mix(in srgb, var(--success) 4%, var(--bg-surface2));
  box-shadow: var(--shadow-lg);
}
.runner-enrollment-success {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
.runner-enrollment-success h2 { margin: 0.15rem 0 0.3rem; }
.runner-enrollment-success p { margin: 0; }
.runner-enrollment-check {
  display: inline-flex;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--success) 16%, var(--bg-inset));
  color: var(--success);
  font-size: 1.2rem;
  font-weight: 750;
}
.runner-enrollment-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.8rem;
  margin: 1.4rem 0;
  padding: 0;
  list-style: none;
}
.runner-enrollment-steps li {
  display: flex;
  gap: 0.65rem;
  align-items: flex-start;
}
.runner-enrollment-steps li > span {
  display: inline-flex;
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--bg-inset);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 750;
}
.runner-enrollment-steps strong,
.runner-enrollment-steps small { display: block; }
.runner-enrollment-steps small { margin-top: 0.25rem; color: var(--text-muted); line-height: 1.4; }
.runner-command-shell {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
}
.runner-command-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-inset);
}
.runner-command-head > span { color: var(--text-muted); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }
.runner-command-shell pre {
  overflow-x: auto;
  margin: 0;
  padding: 1rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--text-code);
  font-size: 0.8rem;
  line-height: 1.55;
}
.runner-command-notice {
  margin-top: 0.8rem;
  color: var(--text-muted);
  font-size: 0.8rem;
}
.runner-command-notice strong { color: var(--running); }
.runner-connection-state {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  margin-top: 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-inset);
}
.runner-connection-state p { margin: 0.2rem 0 0; }
.runner-connection-pulse {
  flex: 0 0 auto;
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: var(--running);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--running) 35%, transparent);
  animation: runner-connection-pulse 1.8s ease-out infinite;
}
.runner-connection-state.connected {
  border-color: color-mix(in srgb, var(--success) 38%, var(--border));
  background: color-mix(in srgb, var(--success) 6%, var(--bg-inset));
}
.runner-connection-state.connected .runner-connection-pulse {
  background: var(--success);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--success) 12%, transparent);
  animation: none;
}
.runner-connection-state.expired {
  border-color: color-mix(in srgb, var(--running) 38%, var(--border));
}
.runner-connection-state.expired .runner-connection-pulse {
  background: var(--running);
  animation: none;
}
@keyframes runner-connection-pulse {
  70%, 100% { box-shadow: 0 0 0 8px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .runner-connection-pulse { animation: none; }
}

.runner-pool-list,
.runner-worker-list {
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg-surface2);
}
.runner-pool-card {
  display: grid;
  grid-template-columns: minmax(200px, 1.15fr) auto minmax(170px, 0.8fr) auto;
  gap: 1rem;
  align-items: center;
  padding: 1rem;
  border-bottom: 1px solid var(--border);
}
.runner-pool-card:last-child,
.runner-worker-row:last-child { border-bottom: 0; }
.runner-pool-card.archived { opacity: 0.58; }
.runner-pool-primary { display: flex; gap: 0.7rem; align-items: center; min-width: 0; }
.runner-pool-primary strong,
.runner-pool-primary span { display: block; }
.runner-pool-primary .mono {
  overflow: hidden;
  margin-top: 0.2rem;
  color: var(--text-muted);
  font-size: 0.68rem;
  text-overflow: ellipsis;
}
.runner-pool-state {
  padding: 0.2rem 0.42rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--success) 12%, var(--bg-inset));
  color: var(--success);
  font-size: 0.65rem;
  font-weight: 750;
  text-transform: uppercase;
}
.runner-pool-state.archived { background: var(--bg-inset); color: var(--text-muted); }
.runner-pool-stats { display: flex; gap: 0.9rem; }
.runner-pool-stats div { min-width: 3.2rem; text-align: center; }
.runner-pool-stats strong,
.runner-pool-stats span { display: block; }
.runner-pool-stats strong { color: var(--text-heading); font-size: 1rem; }
.runner-pool-stats span { margin-top: 0.1rem; color: var(--text-muted); font-size: 0.67rem; }
.runner-pool-meta span {
  display: block;
  color: var(--text-muted);
  font-size: 0.76rem;
}
.runner-pool-meta span + span { margin-top: 0.25rem; }
.runner-pool-actions,
.runner-worker-actions { display: flex; gap: 0.65rem; align-items: center; justify-content: flex-end; }
.runner-pool-actions form,
.runner-worker-actions form { margin: 0; }

.runner-worker-row {
  display: grid;
  grid-template-columns: auto minmax(190px, 1fr) auto minmax(115px, auto) minmax(90px, auto) auto;
  gap: 0.9rem;
  align-items: center;
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--border);
}
.runner-worker-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--text-muted);
}
.runner-worker-dot.active,
.runner-worker-dot.online { background: var(--success); box-shadow: 0 0 0 4px color-mix(in srgb, var(--success) 12%, transparent); }
.runner-worker-dot.draining,
.runner-worker-dot.stale { background: var(--running); }
.runner-worker-dot.revoked { background: var(--error); }
.runner-worker-main strong,
.runner-worker-main span { display: block; }
.runner-worker-main span { margin-top: 0.15rem; }
.runner-worker-detail span,
.runner-worker-detail strong { display: block; }
.runner-worker-detail span { color: var(--text-muted); font-size: 0.65rem; }
.runner-worker-detail strong { margin-top: 0.15rem; font-size: 0.75rem; font-weight: 500; }
.runner-audit-section {
  margin-top: 1.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-surface2);
}
.runner-audit-section > summary {
  padding: 0.9rem 1rem;
  cursor: pointer;
  font-weight: 650;
}
.runner-audit-section > summary span { margin-left: 0.4rem; font-weight: 400; }
.runner-audit-section > .zq-table-wrap,
.runner-audit-section > p { margin: 0 1rem 1rem; }

@media (max-width: 900px) {
  .runner-pool-card { grid-template-columns: minmax(200px, 1fr) auto auto; }
  .runner-pool-meta { grid-column: 1 / 3; }
  .runner-worker-row { grid-template-columns: auto minmax(180px, 1fr) auto auto; }
  .runner-worker-detail { display: none; }
}
@media (max-width: 680px) {
  .runner-example-grid,
  .runner-mode-grid,
  .runner-policy-grid,
  .runner-enrollment-steps { grid-template-columns: 1fr; }
  .runner-choice-card { min-height: 115px; }
  .runner-pool-card { grid-template-columns: 1fr; }
  .runner-pool-meta { grid-column: auto; }
  .runner-pool-stats { justify-content: flex-start; }
  .runner-pool-stats div { text-align: left; }
  .runner-pool-actions { justify-content: flex-start; }
  .runner-worker-row { grid-template-columns: auto 1fr auto; }
  .runner-worker-actions { grid-column: 2 / 4; justify-content: flex-start; }
}
@media (max-width: 460px) {
  .runner-worker-row { grid-template-columns: auto 1fr; }
  .runner-worker-actions { grid-column: 2; }
  .runner-enrollment-success { display: block; }
  .runner-enrollment-check { margin-bottom: 0.75rem; }
}
.scan-mode-summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 0;
  margin: -0.2rem 0 1rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.scan-mode-summary p {
  margin: 0.15rem 0 0;
}

/* Per-stage default-model picker — three compact selects in a single row. */
.bucket-defaults-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
}
.bucket-defaults-row .zq-btn { margin: 0; }
.bucket-pick {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.bucket-pick select {
  min-width: 0;
  width: auto;
  margin: 0;
}
.bucket-tag {
  font-size: 0.78rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.model-preference-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 1rem 0;
}
.model-preference-stage h3 { margin-top: 0; }
.model-preference-stage ol {
  margin: 0;
  padding-left: 2rem;
  /* Cap the list so a big model catalog scrolls inside its
     column instead of stretching the whole grid. */
  max-height: 22rem;
  overflow-y: auto;
}
.model-preference-block-heading {
  margin: 1.4rem 0 0.2rem;
  font-size: 0.95rem;
}
.model-preference-block-heading + .muted.small { margin-bottom: 0.4rem; }
.model-preference-stage li {
  padding: 0.45rem 0.35rem;
  border-bottom: 1px solid var(--border);
  cursor: grab;
  transition: opacity 120ms ease, background-color 120ms ease;
}
.model-preference-stage li,
.model-preference-stage li > span:nth-of-type(2) { display: flex; align-items: center; }
.model-preference-stage li { gap: 0.5rem; }
.model-preference-stage li > span:nth-of-type(2) {
  min-width: 0;
  flex: 1;
  flex-direction: column;
  align-items: flex-start;
}
.model-preference-stage li:active { cursor: grabbing; }
.model-preference-stage li.is-dragging {
  opacity: 0.45;
  background: var(--highlight-color);
}
.model-preference-handle {
  color: var(--text-secondary);
  font-size: 1.15rem;
  letter-spacing: -0.2rem;
  line-height: 1;
  padding-right: 0.2rem;
  user-select: none;
}
.model-preference-stage small { color: var(--text-secondary); }
@media (max-width: 900px) {
  .model-preference-grid { grid-template-columns: 1fr; }
}

/* Per-scan "Advanced model selection" disclosure on scan-new pages.
   Inline-compact: a small clickable summary that reveals the bucket
   row beneath, with no extra section padding. */
details.model-advanced {
  margin: -0.4rem 0 0.6rem;
  font-size: 0.9rem;
}
details.model-advanced > summary {
  cursor: pointer;
  color: var(--text-secondary);
  user-select: none;
  padding: 0.15rem 0;
  list-style: revert;
}
details.model-advanced > summary:hover { color: var(--text-primary); }
details.model-advanced[open] > summary { color: var(--text-primary); }
details.model-advanced > p.muted { margin: 0.4rem 0 0.5rem; }
details.model-advanced .bucket-defaults-row { margin-bottom: 0.2rem; }

/* ---- Report page ---------------------------------------------- */

.report-tab-panel { display: none; }
.report-tab-panel.active { display: block; }
.report-tab-panel > h2:first-child { margin-top: 0; }

/* Assets tab: heading + copy on the left, "complete list" button on
   the right; wraps under the button on narrow screens. */
.report-assets-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.9rem;
}
.report-assets-head h2 { margin: 0 0 0.2rem; }
.report-assets-head p { margin: 0; max-width: 60ch; }
@media (max-width: 640px) {
  .report-assets-head { flex-direction: column; }
}

/* .zq-tabs owns no outer margin by design, so migrated section navs carry
   the page rhythm. Transitional: this goes away once the surrounding page
   layout is on the design system too. */
.section-tabs { margin-bottom: var(--zq-space-4); }
.report-decision-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 1rem 0;
  padding: 0.85rem 1rem;
  border: 1px solid var(--input-border);
  border-left: 4px solid var(--accent);
  border-radius: 6px;
  background: var(--bg-surface2);
}
.report-decision-panel h3 {
  margin: 0 0 0.2rem;
  font-size: 1rem;
}
.report-decision-panel p {
  margin: 0;
}
.report-decision-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.finding-validation-panel {
  margin: 1.2rem 0 1.5rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface2);
}
.validation-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.validation-head h2 {
  margin: 0 0 0.2rem;
  font-size: 1.05rem;
}
.validation-head p {
  margin: 0;
}
.validation-signal-list {
  display: grid;
  gap: 0.55rem;
  margin-top: 0.9rem;
}
.validation-signal-row {
  padding-top: 0.55rem;
  border-top: 1px solid var(--border-light);
}
.validation-signal-note {
  margin-top: 0.25rem;
  color: var(--text);
  font-size: 0.9rem;
}
.report-page-title {
  min-width: 0;
  flex: 1 1 56rem;
}
.report-title-form {
  margin: 0;
}
.report-title-wrap {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: nowrap;
  margin: 0;
  font-size: clamp(1.7rem, 2vw, 2.15rem);
  line-height: 1.15;
}
.report-title-input {
  flex: 1 1 44rem;
  min-width: 22rem;
  max-width: none;
  width: 100%;
  box-sizing: border-box;
  padding: 0.08rem 0.3rem;
  margin-left: -0.3rem;
  border: none;
  background: transparent;
  color: var(--text-heading);
  font: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  border-radius: 6px;
  box-shadow: 0 0 0 1px transparent;
}
.report-title-input:hover,
.report-title-input:focus {
  background: var(--bg-surface2);
  box-shadow: 0 0 0 1px var(--border);
  outline: none;
}
.report-version {
  flex: 0 0 auto;
  font-size: 0.9rem;
}
.report-tags-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  margin-top: 0.4rem;
}
.tag-add-form {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.tag-add-form input[type="text"] {
  /* pill-shaped compact input; control treatment from the element bridge */
  width: 8.5rem;
  padding: 0.35rem 0.5rem;
  border-radius: 999px;
  font-size: 0.85rem;
}
.tag-add-form .zq-btn {
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
}

/* ---- Settings ------------------------------------------------- */
.settings-form fieldset {
  border: 1px solid var(--border); border-radius: 4px;
  padding: 0.8rem 1rem; margin-bottom: 1rem;
}
.settings-form legend { color: var(--text-heading); font-weight: 600; padding: 0 0.4rem; }
.profile-details {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
.profile-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 1px solid var(--border);
  object-fit: cover;
  flex: 0 0 auto;
}
.profile-detail-fields {
  flex: 1 1 auto;
  min-width: 0;
}
.checkbox-grid {
  display: flex;
  gap: 0.75rem 1rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
}
.color-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.settings-form input[type="color"] {
  border: 1px solid var(--border); border-radius: 3px; width: 48px; height: 28px; cursor: pointer;
}
.color-settings-table input[type="color"] {
  width: 100%;
  min-width: 56px;
  height: 34px;
  background: transparent;
  border: none;
}
.color-settings-table th {
  white-space: nowrap;
}

/* Profile preferences use a two-column section grid, while controls inside
   each section stay stacked for readability. */
.profile-settings-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem 1rem;
}
.profile-settings-form fieldset {
  min-width: 0;
  margin-bottom: 0;
  padding: 0.7rem 0.9rem 0.8rem;
}
.profile-settings-form label {
  margin-bottom: 0;
}
.profile-settings-form input[type="text"],
.profile-settings-form select {
  padding: 0.35rem 0.5rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font-family: inherit;
  font-size: 0.9rem;
}
.profile-settings-form .form-actions {
  grid-column: 1 / -1;
  margin-top: 0.15rem;
}
.profile-settings-form .profile-avatar {
  width: 56px;
  height: 56px;
}
.profile-settings-form .profile-name-field {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.profile-settings-form .profile-name-field input[type="text"] {
  width: min(100%, 14rem);
  margin-top: 0;
}
.profile-settings-form .profile-kv {
  margin: 0.75rem 0 0;
}
.profile-settings-form .settings-option-row,
.profile-settings-form .report-settings-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.65rem;
}
.profile-settings-form .setting-option {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  line-height: 1.35;
}
.profile-settings-form .setting-option input[type="radio"],
.profile-settings-form .setting-option input[type="checkbox"] {
  flex: 0 0 auto;
  margin: 0.25rem 0 0;
}
.profile-settings-form .profile-select-field {
  display: block;
}
.profile-settings-form .profile-select-field span {
  display: block;
}
.profile-settings-form .profile-select-field input,
.profile-settings-form .profile-select-field select {
  display: block;
  width: min(100%, 18rem);
  margin-top: 0.35rem;
}
.profile-settings-form .profile-severity-grid {
  margin-top: 0;
}
.profile-settings-form fieldset > p:last-child {
  margin: 0.65rem 0 0;
}

@media (max-width: 900px) {
  .profile-settings-form {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 520px) {
  .profile-settings-form fieldset {
    padding: 0.65rem 0.75rem 0.75rem;
  }
  .profile-settings-form .profile-details,
  .profile-settings-form .profile-name-field {
    align-items: flex-start;
  }
  .profile-settings-form .profile-name-field {
    flex-direction: column;
  }
  .profile-settings-form .profile-name-field input[type="text"],
  .profile-settings-form .profile-select-field input,
  .profile-settings-form .profile-select-field select {
    width: 100%;
  }
  .profile-settings-form .profile-kv {
    grid-template-columns: max-content minmax(0, 1fr);
  }
}

.invite-form {
  margin-bottom: 1rem;
}
.invite-inline {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  flex-wrap: wrap;
}
.invite-inline select,
.invite-form input[type="email"] {
  display: block;
  padding: 0.45rem 0.6rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font-size: 0.9rem;
}
.invite-form input[type="email"] {
  flex: 1 1 20rem;
  min-width: 16rem;
}
.invite-inline select {
  flex: 0 0 10rem;
}
.role-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.role-form select {
  display: block;
  padding: 0.35rem 0.5rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font-size: 0.85rem;
}
.llm-key-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  font-size: 0.78rem;
  border: 1px solid var(--border);
  background: var(--bg-body);
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s, background 0.15s;
  font: inherit;
}
button.llm-key-badge:hover { border-color: var(--accent); }
.key-configured .llm-dot { background: var(--success); }
.key-platform .llm-dot   { background: var(--text-muted, #888); }
.key-missing .llm-dot    { background: var(--error, #c66); }
.llm-model-name { font-weight: 500; }
.key-missing              { color: var(--error, #c66); border-color: color-mix(in srgb, var(--error, #c66) 40%, transparent); }
.llm-search-input {
  width: 220px;
  padding: 0.3rem 0.6rem;
  font-size: 0.88rem;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text);
}
select.llm-search-input { width: auto; }
.llm-table-filters {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.llm-provider-keys { margin: 0 0 1rem; }
.llm-provider-keys h3 { margin: 0 0 0.25rem; font-size: 0.95rem; }
.llm-provider-key-grid {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin-top: 0.6rem;
}
.llm-provider-key-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.65rem;
  background: var(--bg-body);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.llm-provider-key-name {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.llm-provider-key-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1 1 260px;
  max-width: 420px;
}
.llm-table-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.llm-table-hint .ok { color: var(--success); }
.llm-table-hint .err { color: var(--error); }
.llm-rounds-form {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex: 0 0 auto;
  padding: 0.55rem 0.65rem;
  background: var(--bg-body);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.llm-rounds-form label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0;
  color: var(--text-muted);
}
.llm-rounds-controls {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.llm-rounds-form input[type="number"] {
  width: 4.5rem;
  padding: 0.32rem 0.45rem;
  margin: 0;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 4px;
  color: var(--text-code);
  font-size: 0.9rem;
}
.llm-table-wrap {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}
/* Legacy per-card LLM list (kept for other pages that still use it). */
.llm-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.llm-table thead {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-surface2);
}
.llm-table th {
  padding: 0.3rem 0.6rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  text-align: left;
}
.llm-th-stage {
  text-align: center;
  width: 4.5rem;
  cursor: help;
}
.llm-th-key { width: 7.5rem; }
.llm-table tbody tr.llm-row {
  border-bottom: 1px solid var(--border);
  transition: background 0.1s;
}
.llm-table tbody tr.llm-row:last-child { border-bottom: none; }
.llm-table tbody tr.llm-row:hover { background: var(--bg-hover); }
.llm-table-scroll {
  max-height: 260px;
  overflow-y: auto;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.8rem 0.9rem;
  background: var(--bg-body);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.llm-table td {
  padding: 0.3rem 0.6rem;
  vertical-align: middle;
  border-radius: 8px;
}
.llm-td-model {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  gap: 0.15rem;
}
/* Compact single-row editor with a provider picker. */
.llm-key-editor {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.llm-key-editor select {
  flex: 0 0 auto; min-width: 12rem;
}
.llm-key-editor input[type="password"] {
  flex: 1 1 18rem; min-width: 14rem; margin-top: 0;
}

/* Two-column account overview on wide screens. */
.account-grid {
  display: grid; gap: 0.65rem;
  grid-template-columns: 1fr 1fr;
}
.account-grid > .zq-card.span-2 { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .account-grid { grid-template-columns: 1fr; }
  .account-grid > .zq-card.span-2 { grid-column: auto; }
  .llm-rounds-form {
    justify-content: space-between;
  }
}

/* ---- Login ---------------------------------------------------- */
.login-body {
  background: linear-gradient(135deg, var(--bg-body) 0%, var(--bg-inset) 100%);
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem;
}
.login-shell {
  width: min(100%, 980px);
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(320px, 0.75fr);
  gap: 1rem;
  align-items: stretch;
}
.login-intro {
  padding: clamp(1.5rem, 4vw, 3rem);
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(20, 24, 32, 0.72);
}
.login-kicker {
  margin: 0 0 0.75rem;
  color: var(--accent-hover);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.login-intro h1 {
  margin: 0;
  color: var(--text-heading);
  font-size: 2.8rem;
  line-height: 1.05;
}
.login-lede {
  max-width: 38rem;
  margin: 1rem 0 1.5rem;
  color: var(--text);
  font-size: 1.04rem;
}
.registration-offer {
  display: inline-flex;
  margin: -0.25rem 0 1.25rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--accent) 42%, var(--border));
  border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--text-heading);
  font-family: var(--zq-font-family-mono);
  font-size: 0.78rem;
  line-height: 1.4;
}
.login-reasons {
  display: grid;
  gap: 0.85rem;
}
.login-reason {
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr);
  gap: 0.8rem;
  align-items: start;
  padding: 0.9rem 0;
  border-top: 1px solid var(--border);
}
.login-reason .material-symbols-outlined {
  width: 2.2rem;
  height: 2.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-surface2);
  color: var(--accent-hover);
  font-size: 1.2rem;
}
.login-reason h2 {
  margin: 0;
  color: var(--text-heading);
  font-size: 0.98rem;
}
.login-reason p {
  margin: 0.2rem 0 0;
  color: var(--text-muted);
  font-size: 0.9rem;
}
.login-card {
  background: var(--bg-surface);
  padding: clamp(1.35rem, 3vw, 2rem);
  border: 1px solid var(--border);
  border-radius: 8px;
  min-width: 0;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.22);
}
.login-card-head { margin-bottom: 1rem; }
/* The "check your inbox" confirmation after a magic-link request. It is the
   one thing the user must do next, so it leads the card at display size
   instead of competing with the sign-in form below it. */
.login-email-sent {
  font-size: 1.02rem;
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}
.login-email-sent .zq-notice__title {
  font-size: 1.25rem;
  margin-bottom: 0.3rem;
}
.login-email-sent .zq-notice__icon { font-size: 1.9rem; }
.login-card h2 {
  margin: 0 0 0.35rem;
  color: var(--text-heading);
  font-size: 1.35rem;
}
.login-card-head p { margin: 0; }
.login-card input[type="password"],
.login-card input[type="email"] {
  display: block; width: 100%; margin-top: 0.35rem;
}
.login-card button { margin-top: 1rem; width: 100%; }
.login-card button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.login-providers { display: flex; flex-direction: column; gap: 0.5rem; margin: 1rem 0; }
.login-provider-form { margin: 0; }
.login-provider-form .zq-btn { margin-top: 0; }
.login-divider {
  display: flex; align-items: center; gap: 0.6rem;
  color: var(--text-muted); font-size: 0.85rem; margin: 1rem 0 0.75rem;
}
.login-divider::before, .login-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}
.login-accept-terms {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 1rem 0 0;
  color: var(--text-muted);
  font-size: 0.85rem;
  line-height: 1.4;
}
.login-accept-terms input {
  flex: 0 0 auto;
  margin-top: 0.15rem;
}
.login-accept-terms a { color: var(--accent); }
.login-terms { margin: 1.5rem 0 0; }
.registration-signin { margin: 0.6rem 0 0; }
.registration-signin a { color: var(--accent); }
@media (max-width: 820px) {
  .login-body {
    display: block;
    padding: 1rem;
  }
  .login-shell {
    grid-template-columns: 1fr;
  }
  .login-intro h1 {
    font-size: 2.2rem;
  }
}
@media (max-width: 460px) {
  .login-body { padding: 0; }
  .login-shell { gap: 0; }
  .login-intro,
  .login-card {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
  }
  .login-intro {
    padding: 1.25rem;
  }
  .login-card {
    padding: 1.25rem;
  }
}

/* ---- Misc ----------------------------------------------------- */
/* ---- H1 eligibility review ------------------------------------ */
.h1-summary {
  display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;
  margin: 0.6rem 0 1rem 0; padding: 0.55rem 0.8rem;
  background: var(--bg-surface2); border: 1px solid var(--border);
  border-radius: 4px;
}
.h1-filter-toggle { margin-left: auto; font-size: 0.88rem; }
.h1-filter-toggle input { margin-right: 0.3rem; }

/* Integration status chips — the single treatment for integration
   status everywhere (index cards, sub-pages). States and labels come
   from integrations/registry.py; see _integration_status.html. */

.finding-state-summary {
  align-items: center;
  flex-wrap: wrap;
}
/* Lifecycle state chips carry only their tone; the shape and
   typography come from the design system's .zq-badge. */
/* Lifecycle tones come from the design system's color.lifecycle.*
   group (the .zq-badge--<state> variants); the state-* classes stay as
   the app's semantic hook for backend-driven state names, mapped onto
   the tokens — theme switching is the token layer's job now. */
.state-candidate        { background: var(--zq-color-lifecycle-candidate-bg);        color: var(--zq-color-lifecycle-candidate-fg); }
.state-needs-validation { background: var(--zq-color-lifecycle-needs-validation-bg); color: var(--zq-color-lifecycle-needs-validation-fg); }
.state-validated        { background: var(--zq-color-lifecycle-validated-bg);        color: var(--zq-color-lifecycle-validated-fg); }
.state-disputed         { background: var(--zq-color-lifecycle-disputed-bg);         color: var(--zq-color-lifecycle-disputed-fg); }
.state-mitigated        { background: var(--zq-color-lifecycle-mitigated-bg);        color: var(--zq-color-lifecycle-mitigated-fg); }
.state-retested         { background: var(--zq-color-lifecycle-retested-bg);       color: var(--zq-color-lifecycle-retested-fg); }
.state-regression       { background: var(--zq-color-lifecycle-regression-bg);       color: var(--zq-color-lifecycle-regression-fg); }
.state-accepted-risk    { background: var(--zq-color-lifecycle-accepted-risk-bg);    color: var(--zq-color-lifecycle-accepted-risk-fg); }
.state-archived         { background: var(--zq-color-lifecycle-archived-bg);         color: var(--zq-color-lifecycle-archived-fg); }
.state-active           { background: var(--zq-color-lifecycle-active-bg);           color: var(--zq-color-lifecycle-active-fg); }
.state-closed           { background: var(--zq-color-lifecycle-closed-bg);           color: var(--zq-color-lifecycle-closed-fg); }

/* Dim ineligible rows slightly */
tr.h1-row-ineligible td { opacity: 0.55; }
tr.h1-row-ineligible td a { text-decoration: line-through; }

/* Hidden mode when filter toggle is on */
body.h1-hide-ineligible tr.h1-row-ineligible { display: none; }
body.hide-low-confidence tr.conf-row-low { display: none; }
.finding-filter-pill {
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
}
.finding-filter-pill:hover,
.finding-filter-pill:focus-visible {
  text-decoration: none;
  filter: brightness(1.08);
}
.finding-filter-pill.active {
  border-color: currentColor;
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px currentColor;
}
.finding-filter-clear {
  margin-left: 0.15rem;
}
.finding-active-filter {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.5rem 0;
  padding: 0.35rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-surface2);
  color: var(--text-secondary);
  font-size: 0.85rem;
}
.finding-active-filter[hidden] { display: none; }

/* ---- Confidence badges --------------------------------------- */
tr.conf-row-low td { opacity: 0.65; }

/* ---- Required headers (remote scan form) ---------------------- */
.required-headers { display: flex; flex-direction: column; gap: 0.4rem; }
.required-header-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 0.4rem;
  align-items: center;
}
.required-header-row input {
  padding: 0.4rem 0.55rem;
  background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: 4px; color: var(--text-code);
  font-family: var(--zq-font-family-mono); font-size: 0.88rem;
}
.required-headers-actions { margin-top: 0.5rem; }
.required-headers-display {
  display: flex; flex-direction: column; gap: 0.25rem;
  background: var(--bg-surface2);
  border: 1px solid var(--border-light);
  padding: 0.5rem 0.75rem; border-radius: 4px;
}
.required-headers-display code { white-space: nowrap; }

/* ---- Auth indicator on report --------------------------------- */
.auth-indicator {
  color: #e6b422; font-size: 1.05em;
  margin-right: 0.25rem;
}

/* ---- Auth section on scan form -------------------------------- */
.auth-details {
  background: var(--bg-surface2); border: 1px solid var(--border);
  border-radius: 4px; padding: 0.6rem 1rem; margin-bottom: 1rem;
}
.auth-details > summary {
  cursor: pointer; font-weight: 600; color: var(--text-heading);
  padding: 0.2rem 0;
}
.auth-details > summary:hover { color: var(--accent); }
.auth-subsection {
  border: 1px solid var(--border-light); border-radius: 4px;
  padding: 0.6rem 0.9rem; margin: 0.5rem 0;
}
.auth-subsection legend { padding: 0 0.4rem; font-weight: 500; }

/* ---- Disclosures ----------------------------------------------- */
.disc-form label { display: block; margin-bottom: 0.6rem; font-weight: 500; }
.disc-form input[type="text"],
.disc-form input[type="password"],
.disc-form input[type="url"],
.disc-form input[type="date"],
.disc-form input[type="number"],
.disc-form select,
.disc-form textarea {
  display: block; width: 100%; margin-top: 0.25rem;
}
.disc-form .checkbox { flex-direction: row; display: flex; align-items: center; gap: 0.5rem; }
.disc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0 1rem; }
.disc-notes { font-family: inherit; }

/* Timeline */
.timeline { position: relative; margin: 0.5rem 0 1.5rem 1rem; padding-left: 1.5rem; border-left: 2px solid var(--border); }
.timeline-event { position: relative; padding: 0.4rem 0; }
.timeline-dot {
  position: absolute; left: -1.85rem; top: 0.55rem;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--text-muted); border: 2px solid var(--bg-body);
}
.timeline-dot.event-reported { background: var(--accent); }
.timeline-dot.event-ack      { background: var(--running); }
.timeline-dot.event-fix      { background: var(--success); }
.timeline-dot.event-bounty   { background: #e6b422; }
.timeline-dot.event-credit   { background: #c060e0; }
.timeline-dot.event-public   { background: var(--link); }
.timeline-dot.event-closed   { background: var(--success); }
.timeline-type { font-weight: 600; text-transform: capitalize; margin-right: 0.3rem; }

.event-form {
  display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin-bottom: 1rem;
}
.event-form select, .event-form input {
  padding: 0.4rem 0.5rem; background: var(--input-bg);
  border: 1px solid var(--input-border); border-radius: 4px;
  color: var(--text); font-size: 0.88rem;
}

/* ---- Filter bar ------------------------------------------------ */
.filter-bar {
  display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center;
  margin-bottom: 1rem; padding: 0.6rem 0;
}
.filter-bar select, .filter-bar input[type="date"] {
  padding: 0.4rem 0.5rem; background: var(--input-bg);
  border: 1px solid var(--input-border); border-radius: 4px;
  color: var(--text); font-size: 0.88rem; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23aaa' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.5rem center; padding-right: 1.8rem;
}
@media (pointer: coarse) {
  .filter-bar select { appearance: auto; -webkit-appearance: auto; background-image: none; padding-right: 0.5rem; }
}
.filter-search {
  padding: 0.4rem 0.6rem; background: var(--input-bg);
  border: 1px solid var(--input-border); border-radius: 4px;
  color: var(--text); font-size: 0.88rem; min-width: 200px; flex: 1;
}

/* ---- Tag pills ------------------------------------------------- */
/* Tags render as neutral .zq-badge chips; only the spacing between
   siblings is app-side. */
.tag-pill {
  margin-right: 0.2rem;
}
.tag-pill:hover { background: var(--btn-hover); text-decoration: none; }
.tag-row { display: flex; gap: 0.25rem; flex-wrap: wrap; }
.tier-link {
  color: var(--text-heading);
  text-decoration: none;
}
.tier-link:hover {
  color: var(--link);
  text-decoration: underline;
}
.tier-models {
  max-width: 26rem;
  word-break: break-word;
}
.tier-scan-types {
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
}
.tag-pill-form {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}
.tag-pill-form .tag-pill {
  margin-right: 0;
}
.tag-remove-btn {
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 0.9rem;
  line-height: 1;
}
.tag-remove-btn:hover {
  color: var(--text);
  background: transparent;
}

/* ---- Pagination ------------------------------------------------ */

/* ---- Misc ------------------------------------------------------- */
.breadcrumbs { margin-top: 0; }
.row-actions { margin: 1rem 0; display: flex; gap: 0.6rem; }
.actions a { margin-right: 0.5rem; }

/* Single source of truth for the mobile shell breakpoint: app.js's
   mobileMq must match this 980px value. */
@media (max-width: 980px) {
  .app-shell {
    grid-template-columns: 1fr;
  }
  /* Safety net for the frame where a resize crosses the breakpoint
     before app.js drops the desktop rail class. */
  body.sidebar-collapsed .app-shell {
    grid-template-columns: 1fr;
  }
  .global-topbar {
    grid-column: 1;
    grid-row: 1;
  }
  .mobile-sidebar-toggle {
    display: inline-flex;
  }
  /* The desktop collapse chevron has no meaning inside the drawer;
     the drawer gets its own close button instead. */
  .sidebar-toggle {
    display: none;
  }
  .sidebar-drawer-close {
    display: inline-flex;
  }
  /* No-JS fallback: the sidebar stays a plain stacked block above the
     content. app.js adds body.sidebar-ready to switch the drawer on,
     so the nav is never locked away when scripts don't run. */
  .sidebar {
    grid-column: 1;
    grid-row: 2;
    position: static;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  body.sidebar-ready .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(18rem, 86vw);
    height: auto;
    z-index: 80;
    overflow-y: auto;
    overflow-x: hidden;
    /* Swipes that exhaust the drawer's scroll must not chain into the
       page behind it (URL bar movement / pull-to-refresh). */
    overscroll-behavior: contain;
    border-right: 1px solid var(--border);
    border-bottom: none;
    transform: translateX(-102%);
  }
  body.sidebar-ready.sidebar-open .sidebar {
    transform: translateX(0);
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.35);
  }
  body.sidebar-ready .sidebar-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 70;
    background: rgba(0, 0, 0, 0.45);
    opacity: 0;
    pointer-events: none;
  }
  body.sidebar-ready.sidebar-open .sidebar-scrim {
    opacity: 1;
    pointer-events: auto;
  }
  body.sidebar-ready.sidebar-open {
    overflow: hidden;
  }
  /* If the collapsed-rail project popover is open while the viewport
     narrows, keep it in the drawer's flow rather than letting its
     absolute offset poke a horizontal scrollbar out the right side. */
  .sidebar-popover {
    position: static;
    width: 100%;
    margin-top: 0.35rem;
    box-shadow: none;
  }
  .container.with-sidebar {
    grid-column: 1;
    grid-row: 3;
    padding: 0.75rem;
  }
  /* With JS on, the fixed drawer leaves the grid flow, so content
     moves up under the topbar. */
  body.sidebar-ready .container.with-sidebar {
    grid-row: 2;
  }
  .bulk-controls {
    grid-template-columns: 1fr;
  }
  .bulk-action-row {
    padding-top: 0;
  }
  .invite-inline {
    align-items: stretch;
  }
  .section-head,
  .manage-inline-group {
    align-items: flex-start;
  }
  .manage-project-form {
    width: 100%;
    margin-left: 0;
  }
  .report-title-input {
    min-width: 0;
    width: 100%;
  }
  .report-title-wrap {
    flex-wrap: wrap;
  }
}
/* Drawer slide/fade only for users who haven't asked for reduced
   motion; the rest get an instant show/hide. */
@media (prefers-reduced-motion: no-preference) {
  body.sidebar-ready .sidebar {
    transition: transform 0.2s ease;
  }
  body.sidebar-ready .sidebar-scrim {
    transition: opacity 0.15s ease;
  }
}

/* ------------------------------------------------------------------
   Accordion Re-run wizard
   ------------------------------------------------------------------ */
.rescan-accordion {
  border: 1.5px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  margin-top: 0.75rem;
}
.accordion-fold {
  border-top: 1.5px solid var(--border);
}
.accordion-fold.path-hidden {
  display: none;
}
.accordion-fold:first-child { border-top: none; }

.accordion-fold-hd {
  width: 100%;
  background: none;
  border: none;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.8rem 1rem;
  text-align: left;
  cursor: pointer;
  color: var(--text);
  font-size: 0.95rem;
  transition: background 0.15s;
}
.accordion-fold-hd:hover:not(:disabled) { background: var(--bg-hover); }

.accordion-fold.locked > .accordion-fold-hd {
  opacity: 0.4;
  cursor: default;
  pointer-events: none;
}
.accordion-fold.open > .accordion-fold-hd {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* Step number badge */
.acc-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  flex-shrink: 0;
  transition: background 0.2s;
}
.accordion-fold.locked .acc-num {
  background: var(--border);
  color: var(--text-muted);
}
.accordion-fold.done .acc-num {
  background: var(--success);
}

.acc-title {
  font-weight: 600;
  flex: 1;
}

/* Selected value shown in the collapsed header */
.acc-pick {
  font-size: 0.82rem;
  color: var(--accent);
  font-weight: 500;
  margin-right: 0.1rem;
  white-space: nowrap;
}

.accordion-chevron {
  color: var(--text-muted);
  font-size: 0.78rem;
  transition: transform 0.2s;
  flex-shrink: 0;
}
.accordion-fold.open .accordion-chevron  { transform: rotate(180deg); }
.accordion-fold.locked .accordion-chevron { opacity: 0; }

.accordion-fold-bd {
  padding: 0 1rem 1rem;
}

/* ---- Superadmin impersonation banner --------------------------- */
.impersonation-banner {
  position: sticky;
  top: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 1rem;
  background: #b45309;              /* amber-700 */
  color: var(--warn-bg);
  border-bottom: 2px solid #78350f; /* amber-900 */
  font-size: 0.9rem;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}
.impersonation-banner .material-symbols-outlined {
  font-size: 1.25rem;
}
.impersonation-banner .impersonation-banner-text {
  flex: 1 1 auto;
  min-width: 0;
}
.impersonation-banner .impersonation-banner-text .muted {
  color: #fde68a;
}
.impersonation-banner strong {
  font-weight: 600;
}
.impersonation-banner .impersonation-stop {
  flex: 0 0 auto;
  margin: 0;
}
.impersonation-banner .impersonation-stop .zq-btn {
  background: #78350f;
  color: var(--warn-bg);
  border-color: #451a03;
}
.impersonation-banner .impersonation-stop .zq-btn:hover {
  background: #92400e;
  color: #fff;
}

/* ============================================================
   Global search — topbar input + autocomplete dropdown
   ============================================================ */
.global-search {
  position: relative;
  flex: 1;
  max-width: 720px;
  margin: 0 auto;
}
.global-search-icon {
  position: absolute;
  left: 0.65rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: 1.1rem;
  pointer-events: none;
}
/* Scoped under .global-search so the rules out-rank the bare
   input[type="search"] baseline (style.css line ~159) that would
   otherwise strip the 2.2rem left padding reserved for the icon. */
.global-search .global-search-input {
  width: 100%;
  padding: 0.5rem 0.75rem 0.5rem 2.2rem;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
  border-radius: 6px;
  font-size: 0.95rem;
}
.global-search .global-search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(58, 122, 217, 0.18);
}
.global-search-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: min(70vh, 560px);
  overflow-y: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: 80;
  padding: 0.25rem 0;
}
.global-search-empty {
  padding: 1rem;
  color: var(--text-muted);
  text-align: center;
  font-size: 0.92rem;
}
.global-search-group {
  padding: 0.25rem 0;
  border-bottom: 1px solid var(--border-light);
}
.global-search-group:last-of-type {
  border-bottom: none;
}
.global-search-group-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.85rem 0.25rem;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.global-search-group-head .material-symbols-outlined {
  font-size: 1rem;
}
.global-search-item {
  display: block;
  padding: 0.45rem 0.85rem;
  text-decoration: none;
  color: var(--text);
  border-left: 2px solid transparent;
}
.global-search-item:hover,
.global-search-item.is-active {
  background: var(--bg-hover);
  border-left-color: var(--accent);
  text-decoration: none;
}
.global-search-item-title {
  font-weight: 600;
  font-size: 0.93rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.global-search-item-snippet {
  font-size: 0.85rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.global-search-item-snippet mark,
.search-result-snippet mark {
  background: var(--bg-highlight);
  color: var(--text-heading);
  padding: 0 1px;
  border-radius: 2px;
}

.search-kbd-hint {
  position: absolute;
  right: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  line-height: 1;
}
.search-kbd-hint kbd {
  display: inline-block;
  padding: 0.15rem 0.35rem;
  border: 1px solid var(--input-border);
  border-radius: 4px;
  background: var(--bg-subtle);
  color: var(--text-muted);
  font-family: inherit;
  font-size: 0.75rem;
  line-height: 1.4;
  box-shadow: 0 1px 0 var(--input-border);
}
.global-search-input:focus ~ .search-kbd-hint {
  display: none;
}

@media (max-width: 520px) {
  .container.with-sidebar {
    padding: 0.75rem;
  }
  .global-search .global-search-input {
    padding-right: 0.65rem;
  }
  .search-kbd-hint {
    display: none;
  }
  .filter-search {
    min-width: 0;
  }
}

.global-search-item-meta {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 0.1rem;
}
.global-search-footer {
  display: block;
  padding: 0.55rem 0.85rem;
  font-size: 0.85rem;
  color: var(--link);
  text-align: center;
  border-top: 1px solid var(--border-light);
}
.global-search-footer:hover {
  background: var(--bg-hover);
  text-decoration: none;
}

/* ---- Dedicated /search results page -------------------------- */
.search-page {
  max-width: 880px;
}
.search-page-form {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.search-page-input {
  flex: 1;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
  border-radius: 6px;
  font-size: 1rem;
}
.search-group-heading {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 1.25rem 0 0.5rem;
  font-size: 1.05rem;
}
.search-results {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.search-result-link {
  display: block;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--border-light);
  border-radius: 6px;
  background: var(--bg-surface);
  text-decoration: none;
  color: var(--text);
}
.search-result-link:hover {
  border-color: var(--accent);
  text-decoration: none;
}
.search-result-title {
  font-weight: 600;
  margin-bottom: 0.15rem;
}
.search-result-snippet {
  font-size: 0.9rem;
  color: var(--text-muted);
}
.search-result-meta {
  margin-top: 0.25rem;
}
.search-group-more {
  display: inline-block;
  margin-bottom: 0.75rem;
  font-size: 0.9rem;
}

/* ---- Error pages (404 etc.) ----------------------------------- */
.error-page {
  max-width: 560px;
  margin: 4rem auto;
  text-align: center;
}
.error-page-code {
  font-size: 3rem;
  letter-spacing: 0.1em;
  margin: 0 0 0.5rem;
}
.error-page h1 { margin: 0 0 0.5rem; }
.error-page-actions {
  margin-top: 1.5rem;
  display: flex;
  gap: 0.5rem;
  justify-content: center;
}

/* ---- Agent discussion bubble thread --------------------------- */
.agent-discussion {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.discussion-intro {
  margin-bottom: 1rem;
}
.discussion-rerun-error {
  margin-bottom: 1rem;
}
.discussion-thread {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
/* Bubble base */
.discussion-bubble {
  border-radius: 16px;
  padding: 0.75rem 1rem;
  max-width: min(76ch, 86%);
  border: 1px solid var(--border);
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.12);
}
.discussion-bubble.bubble-vendor {
  align-self: flex-start;
  background: var(--bg-inset, #1a2535);
  border-left: 3px solid var(--accent, #22c7e8);
  border-bottom-left-radius: 5px;
  margin-right: auto;
}
.discussion-bubble.bubble-researcher {
  align-self: flex-end;
  background: var(--bg-surface2, #1f2d3d);
  border-right: 3px solid var(--success, #34d399);
  border-bottom-right-radius: 5px;
  margin-left: auto;
  text-align: left;
}
.discussion-typing-bubble {
  display: block;
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.discussion-typing-bubble:hover {
  text-decoration: none;
  border-color: color-mix(in srgb, var(--link) 45%, var(--border));
}
.typing-dots {
  display: inline-flex;
  align-items: center;
  gap: 0.28rem;
  min-height: 1.3rem;
}
.typing-dots span {
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 999px;
  background: currentColor;
  opacity: 0.35;
  animation: discussionTypingDot 1.2s infinite ease-in-out;
}
.typing-dots span:nth-child(2) { animation-delay: 0.16s; }
.typing-dots span:nth-child(3) { animation-delay: 0.32s; }
.discussion-error-bubble {
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 45%, var(--border));
}
@keyframes discussionTypingDot {
  0%, 80%, 100% {
    transform: translateY(0);
    opacity: 0.35;
  }
  40% {
    transform: translateY(-0.18rem);
    opacity: 0.95;
  }
}
.bubble-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.bubble-identity {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}
/* Bubble role chips: pill shape on the .zq-badge base; the two
   role hues are accent / success tints. */
.bubble-role-badge {
  border-radius: var(--zq-radius-pill);
}
.role-vendor {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
}
.role-researcher {
  background: color-mix(in srgb, var(--success) 20%, transparent);
  color: var(--success);
}
.bubble-section {
  margin-bottom: 0.4rem;
}
.bubble-section:last-child {
  margin-bottom: 0;
}
.bubble-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.15rem;
}
.bubble-text {
  font-size: 0.9rem;
  color: var(--text);
  white-space: pre-wrap;
}
.bubble-text.muted {
  color: var(--text-secondary);
}
.bubble-timestamp {
  flex: 0 0 auto;
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
}
.continue-discussion-form {
  margin-top: 1rem;
  justify-content: flex-end;
}
@media (max-width: 640px) {
  .growth-conversion-panel {
    align-items: stretch;
    flex-direction: column;
  }
  .growth-conversion-actions {
    align-items: stretch;
    flex-direction: column;
  }
  .growth-conversion-actions .zq-btn {
    justify-content: center;
    width: 100%;
  }
  .finding-decision-panel,
  .report-decision-panel {
    align-items: stretch;
    flex-direction: column;
  }
  .finding-decision-actions,
  .report-decision-actions,
  .decision-action-form,
  .decision-reject-menu,
  .decision-button {
    width: 100%;
  }
  .decision-reject-form {
    position: static;
    width: 100%;
    margin-top: 0.5rem;
    box-shadow: none;
  }
  .bulk-toolbar-group,
  .bulk-rerun-toolbar select,
  .bulk-rerun-toolbar .bulk-state-note {
    width: 100%;
  }
  .bulk-toolbar-group .zq-btn {
    width: 100%;
    justify-content: center;
  }
  .discussion-bubble {
    max-width: 100%;
  }
  .bubble-header {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.25rem;
  }
}

/* ---- building interstitial (patch / auto-fix proposal) -------
   Used by templates/_building_interstitial.html while a
   background thread runs the LLM agent. Spinner (design system's
   .zq-spinner) + status pill (design system's .zq-badge) +
   error state (design system's .zq-error). The card lives in the
   same content column as the rest of the app so it visually feels
   like "this is just a page that hasn't finished yet". */
.building-interstitial {
  display: flex;
  justify-content: center;
  padding: 2rem 0 3rem;
}
.building-interstitial-card {
  width: 100%;
  max-width: 38rem;
  background: var(--bg-elevated, var(--bg-surface));
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 2rem 1.75rem 1.5rem;
  text-align: center;
  position: relative;
}
[data-building-state="failed"] .building-interstitial-card {
  border-color: var(--error);
}
.building-spinner {
  margin-bottom: 1.25rem;
  /* Keeps the spinner out of the document flow on the right of
     the title — the centered layout above is enough. */
}
[data-building-state="failed"] .building-spinner {
  display: none;
}
.building-title {
  font-size: 1.35rem;
  margin: 0 0 0.5rem;
  color: var(--text-primary);
}
.building-subtitle {
  margin: 0 0 1.25rem;
  line-height: 1.5;
}
.building-progress-meta {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
  font-size: 0.85rem;
}
.building-elapsed {
  color: var(--text-muted);
}
.building-details {
  text-align: left;
  margin: 1.25rem auto 0;
  max-width: 32rem;
  font-size: 0.9rem;
  color: var(--text-secondary);
}
.building-details summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.building-details[open] summary {
  margin-bottom: 0.5rem;
}
.building-error {
  margin-top: 1.25rem;
  text-align: left;
}

/* Live activity feed — the per-step progress lines the agent
   emits while the job runs (tool calls, retries, validation).
   Same visual language as the scan detailed log's .log-pane:
   mono text, muted timestamps, red error rows — just narrower,
   because it lives inside the interstitial card. */
.building-live {
  text-align: left;
  margin: 0.75rem auto 0;
  max-width: 32rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-surface);
  overflow: hidden;
}
.building-live-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated, var(--bg-surface));
}
.building-live-title {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.building-live-hint {
  font-size: 0.75rem;
}
.building-live-feed {
  max-height: 220px;
  overflow-y: auto;
  padding: 0.5rem 0.75rem;
  font-size: 0.78rem;
  line-height: 1.45;
  text-align: left;
}
.building-live-empty {
  padding: 0.15rem 0;
}
.building-log-row {
  display: flex;
  gap: 0.6rem;
  padding: 0.1rem 0;
  min-width: 0;
}
.building-log-ts {
  flex: none;
  color: var(--text-muted);
}
.building-log-msg {
  word-break: break-word;
  overflow-wrap: break-word;
  color: var(--text-secondary);
  white-space: pre-wrap;
}
.building-log-row.level-error .building-log-msg {
  color: var(--error);
}

/* ===========================================================
   Asset discovery (Phase 1)
   ===========================================================
   The Discovered sub-section lives under the project's
   Assets tab. CSS classes are scoped to the
   ``project-discovered-manual-*`` form so they don't bleed
   into the seeded-assets table above.

   Visual treatment:
   - Discovered rows get a subtle accent stripe + a "discovered"
     source chip in the row, matching the per-kind chip colors
     we already use elsewhere.
   - Ignored rows are italic / muted so the operator can scan
     past them; the "Show ignored" checkbox unhides them on
     demand.
   - The blacklist admin <details> uses the same custom
     triangle marker as the archived section so the two
     collapsible surfaces feel like siblings.
   - The asset detail page's Discovery timeline is a flat
     list of events with a small kind label + timestamp.

   Theme: all colors are CSS-variable driven so the
   section responds to the active theme (dark/light).
   We use ``--bg-surface`` for card backgrounds and
   ``--input-bg`` / ``--input-border`` for the manual
   form's fields — those tokens are defined for both
   themes at the top of this file. The existing
   ``.project-archived-section`` (Phase-0 archive) had a
   ``var(--bg-card)`` reference with no definition; we
   reuse ``--bg-surface`` for the same look.
*/

/* Empty state — the manual-exercise form is the Phase 1
   stand-in for the agent integration. The form's row
   layout collapses to a column on narrow screens via
   flex-wrap. */
.project-discovered-manual-form {
  margin-top: 0.85rem;
}
.project-discovered-manual-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem;
}
.project-discovered-manual-row label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--text-muted);
  flex: 1 1 130px;
  min-width: 130px;
}
.project-discovered-manual-row label.project-discovered-manual-url {
  flex: 2 1 280px;
  min-width: 240px;
}
.project-discovered-manual-row input,
.project-discovered-manual-row select {
  font: inherit;
  padding: 0.35rem 0.5rem;
  border-radius: 4px;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
}
/* "Select all" affordance for the bulk-update flow.
   Sits inline with the "show ignored" toggle so the
   two operator controls are visually grouped. The
   "select all" semantics apply only to visible,
   non-ignored rows — see ``initDiscoveredBulkUpdate``
   for the JS scoping. */
/* Per-row selection column. Narrow — the checkbox
   is the only content; no header label so the column
   reads as a UI affordance rather than a data field. */
/* Blacklist admin section. Mirrors the archived <details>
   marker style for visual consistency. */
.project-blacklist-section {
  margin-top: 1.25rem;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1.1rem;
}
.project-blacklist-section > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.project-blacklist-section > summary::-webkit-details-marker {
  display: none;
}
.project-blacklist-section > summary::before {
  content: "▶";
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.project-blacklist-section[open] > summary::before {
  transform: rotate(90deg);
}
.project-blacklist-section > summary > .material-symbols-outlined {
  color: var(--text-muted);
  font-size: 1.15rem;
}
.project-blacklist-table {
  margin-top: 0.85rem;
  opacity: 0.92;
}
.project-blacklist-add {
  position: relative;
  display: inline-block;
}
.project-blacklist-add > summary {
  list-style: none;
  cursor: pointer;
}
.project-blacklist-add > summary::-webkit-details-marker {
  display: none;
}
.project-blacklist-add-form {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 280px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.85rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
}
.project-blacklist-add-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.project-blacklist-add-form input,
.project-blacklist-add-form select {
  font: inherit;
  padding: 0.35rem 0.5rem;
  border-radius: 4px;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
}
.project-blacklist-add-form-free {
  position: static;
  margin-top: 0.85rem;
  min-width: 0;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem;
  box-shadow: none;
}
.project-blacklist-add-form-free label {
  flex: 1 1 140px;
  min-width: 140px;
}

/* Asset detail page: Discovery audit log. Same
   triangle-marker treatment for the wrapping <details>;
   the inner timeline is a flat list of events. */
.asset-discovery-section {
  margin-top: 1.25rem;
  max-width: 960px;
  margin-left: auto;
  margin-right: auto;
}
.asset-discovery-details {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1.1rem;
}
.asset-discovery-details > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.asset-discovery-details > summary::-webkit-details-marker {
  display: none;
}
.asset-discovery-details > summary::before {
  content: "▶";
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.asset-discovery-details[open] > summary::before {
  transform: rotate(90deg);
}
.asset-discovery-details > summary > .material-symbols-outlined {
  color: var(--text-muted);
  font-size: 1.15rem;
}
.asset-discovery-timeline {
  list-style: none;
  margin: 0.85rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.asset-discovery-event {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.4rem 0.55rem;
  border-left: 3px solid var(--border);
  background: var(--bg-inset);
  border-radius: 0 6px 6px 0;
}
.asset-discovery-event-discovered {
  border-left-color: var(--accent);
}
.asset-discovery-event-promoted {
  border-left-color: #2fae92;
}
.asset-discovery-event-ignored {
  border-left-color: var(--text-muted);
}
.asset-discovery-event-last_seen {
  border-left-color: #d49b35;
}
.asset-discovery-event-archived {
  border-left-color: var(--error);
}
.asset-discovery-event-kind {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.75rem;
  color: var(--text);
  font-weight: 600;
}
.asset-discovery-fingerprint {
  flex: 1 1 100%;
  margin: 0.4rem 0 0;
  padding: 0.4rem 0.55rem;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.8rem;
  white-space: pre-wrap;
  word-break: break-word;
}
.asset-discovery-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.85rem;
}

/* ===========================================================
   Phase 2: scan-time discoveries
   ===========================================================
   The scan detail page's Discoveries section + the asset
   detail page's Tech section. Same visual treatment as
   the existing History section (sits directly under it)
   so the operator's eye doesn't have to context-switch.

   Theme: all colors use the existing tokens so the
   section reads correctly in both dark and light mode.
*/

.scan-discoveries-section {
  margin: 1.25rem 0 0.5rem;
  padding: 0.85rem 1rem 0.65rem;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.scan-discoveries-section h2 {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 0.55rem;
}
/* Section header. The heading sits on the left by
   default — there's no companion control on the right,
   so ``justify-content: space-between`` would push it
   to the end of the row and look oddly right-aligned.
   The header is rendered as a ``<summary>`` inside
   the ``.scan-discoveries-panel`` ``<details>`` so
   the panel defaults to collapsed (just the count,
   not the full row list). */
.scan-discoveries-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.55rem;
}
.scan-discoveries-head h2 {
  margin: 0;
}
/* The discoveries panel is a native ``<details>``
   so the browser handles the expand/collapse
   interaction (click on the summary, keyboard
   focus, screen-reader announcement) for free.
   We just reset the default disclosure marker
   and draw our own chevron to match the rest of
   the section's visual vocabulary. */
.scan-discoveries-panel > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.scan-discoveries-panel > summary::-webkit-details-marker {
  display: none;
}
.scan-discoveries-panel > summary::marker {
  display: none;
  content: "";
}
.scan-discoveries-panel > summary::before {
  content: "▸";
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.scan-discoveries-panel[open] > summary::before {
  transform: rotate(90deg);
}
/* When the panel is closed, the body is gone —
   drop the summary's bottom margin so the panel
   collapses to a single tight line of header.
   The 0.65rem bottom padding on the section is
   enough breathing room on its own. */
.scan-discoveries-panel:not([open]) > .scan-discoveries-head {
  margin-bottom: 0;
}
.scan-discoveries-extract-form {
  margin: 0;
}
/* Method group (``code_analysis`` vs ``active_scan``)
   — a <details> per group so the operator can collapse
   a noisy method without losing the other. The
   summary carries the method chip + a row count. */
.scan-discoveries-group {
  margin: 0.55rem 0;
}
.scan-discoveries-group > summary {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  list-style: none;
  cursor: pointer;
  user-select: none;
  padding: 0.25rem 0;
}
.scan-discoveries-group > summary::-webkit-details-marker {
  display: none;
}
.scan-discoveries-group > summary::before {
  content: "▸";
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.scan-discoveries-group[open] > summary::before {
  transform: rotate(90deg);
}
/* Advanced <details> at the bottom of the section —
   the re-scan button is inside. Stays collapsed by
   default; opens on click. The whole <details>
   collapses to a single line of muted copy so it
   doesn't compete for attention with the discovery
   rows above it. */
.scan-discoveries-advanced {
  margin-top: 0.85rem;
  padding-top: 0.55rem;
  border-top: 1px dashed var(--border);
}
.scan-discoveries-advanced > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  list-style: none;
  cursor: pointer;
  user-select: none;
  color: var(--text-muted);
}
.scan-discoveries-advanced > summary::-webkit-details-marker {
  display: none;
}
.scan-discoveries-advanced > summary::before {
  content: "▸";
  font-size: 0.7rem;
  transition: transform 0.15s ease;
}
.scan-discoveries-advanced[open] > summary::before {
  transform: rotate(90deg);
}
.scan-discoveries-advanced[open] {
  padding: 0.55rem 0 0;
}
/* ==== Update-session pane (scan detail page) =====================
   A zq-card whose header is the <summary>: collapsed by default so it
   doesn't compete with the status and findings (it's only useful for
   session-auth scans, and even then rarely). ``.is-degraded`` — the
   auth-health tracker flagged the session as dead — tints the card
   and its hint so the auto-expanded pane reads as "what's happening
   now", not as a random form. */
.scan-auth-update-panel > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: var(--zq-space-4) var(--zq-space-5);
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.scan-auth-update-panel > summary::-webkit-details-marker {
  display: none;
}
.scan-auth-update-panel > summary::marker {
  content: "";
}
.scan-auth-update-chevron {
  flex: none;
  font-size: 0.7rem;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}
.scan-auth-update-chevron::before {
  content: "▸";
}
.scan-auth-update-panel[open] > summary {
  border-bottom: var(--zq-border-width-hairline) solid var(--zq-color-border-subtle);
}
.scan-auth-update-panel[open] .scan-auth-update-chevron {
  transform: rotate(90deg);
}
.scan-auth-update-body {
  padding: var(--zq-space-5);
}
.scan-auth-update.is-degraded {
  border-color: var(--warn-border);
}
.scan-auth-update.is-degraded > .scan-auth-update-panel > summary {
  background: var(--warn-bg);
}
.scan-auth-update-hint--alert {
  color: var(--warn-text);
  font-weight: 600;
}
.scan-auth-update-reason {
  margin: 0 0 0.6rem;
  padding: 0.55rem 0.75rem;
  border-left: 3px solid var(--warn-border);
  background: var(--warn-bg);
  border-radius: 0 6px 6px 0;
  font-size: 0.9rem;
}
.btn-link.small {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  font: inherit;
  font-size: 0.85rem;
}
.btn-link.small:disabled,
.btn-link.small[aria-disabled="true"] {
  color: var(--text-muted);
  text-decoration: none;
  cursor: not-allowed;
}
.scan-discoveries-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.scan-discovery-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  line-height: 1.45;
  padding: 0.3rem 0.55rem;
  border-left: 3px solid transparent;
  background: var(--bg-surface);
  border-radius: 0 6px 6px 0;
}
.scan-discovery-row:hover {
  border-left-color: var(--accent);
}
.scan-discovery-row.scan-discovery-status-ignored {
  font-style: italic;
  color: var(--text-muted);
  border-left-color: var(--text-muted);
}
.scan-discovery-url {
  flex: 1 1 240px;
  min-width: 0;
  word-break: break-all;
}
.scan-discovery-tech {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  background: var(--bg-highlight);
  color: var(--text);
  font-size: 0.8rem;
}

/* Tech section on the asset detail page. Sits in the
   asset-detail-grid next to the Target / Coverage
   sections; same ``<dl>`` shape so the layout stays
   consistent. */
.asset-tech-dl dt {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

/* ---- Unified asset list (approval axis + bulk wizard) ------------ */

/* Approval chip — the primary triage axis on the Assets tab.
   Approved rows are scan targets (green, matching the
   success token); pending rows are discoveries awaiting the
   operator's blessing (amber, matching the running token so
   it reads as "in progress" rather than "error"). Same pill
   grammar as the source chips. */

/* Environment chips — which deployment an asset belongs to
   (prod / staging / dev / test, or unknown when nothing is
   inferred and the operator hasn't picked). Shape from .zq-badge;
   these rules keep the pill + mono treatment and the fixed per-env
   hues so table + detail page + bulk preview read identically
   across themes. */
.asset-environment-chip {
  border-radius: var(--zq-radius-pill);
  font: 600 0.7rem/1.4 var(--zq-font-family-mono);
  text-transform: lowercase;
  letter-spacing: 0.03em;
  background: var(--bg-inset);
  border-color: var(--border);
  color: var(--text-muted);
}
.asset-environment-chip.env-prod {
  background: color-mix(in srgb, #e05a5a 16%, var(--bg-inset));
  color: #e05a5a;
  border-color: color-mix(in srgb, #e05a5a 40%, var(--border));
}
.asset-environment-chip.env-staging {
  background: color-mix(in srgb, #d49b35 16%, var(--bg-inset));
  color: #d49b35;
  border-color: color-mix(in srgb, #d49b35 40%, var(--border));
}
.asset-environment-chip.env-dev {
  background: color-mix(in srgb, #3f8ae0 16%, var(--bg-inset));
  color: #3f8ae0;
  border-color: color-mix(in srgb, #3f8ae0 40%, var(--border));
}
.asset-environment-chip.env-test {
  background: color-mix(in srgb, #c257b3 16%, var(--bg-inset));
  color: #c257b3;
  border-color: color-mix(in srgb, #c257b3 40%, var(--border));
}
/* Membership role: recon = extraction source (docs/specs/context),
   never scanned. Shape from .zq-badge; fixed hue like the
   environment palette. */
.asset-role-chip {
  border-radius: var(--zq-radius-pill);
  font: 600 0.7rem/1.4 var(--zq-font-family-mono);
  text-transform: lowercase;
  letter-spacing: 0.03em;
  background: var(--bg-inset);
  border-color: var(--border);
  color: var(--text-muted);
}
.asset-role-chip.role-recon {
  background: color-mix(in srgb, #4aa5a2 16%, var(--bg-inset));
  color: #4aa5a2;
  border-color: color-mix(in srgb, #4aa5a2 40%, var(--border));
}

/* Filter bar on the assets table — builds on .filter-bar with
   the show-ignored toggle + live match count. */
.project-assets-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.65rem;
  margin: 0.5rem 0;
}
.project-assets-filter-bar .filter-search { flex: 1 1 220px; min-width: 200px; }
/* The filters are a GET form (server-side facets ride the URL); the
   form itself must not become a block child of the flex bar or every
   control stacks vertically — dissolve it so its children ARE the
   flex items the .filter-bar rules were written for. */
.project-assets-filter-bar form { display: contents; }
.project-assets-filter-bar label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.78rem;
  color: var(--text-muted);
}
.project-assets-filter-bar label.checkbox {
  flex-direction: row;
  align-items: center;
  gap: 0.35rem;
}
.project-assets-select-all { display: inline-block; margin: 0.25rem 0 0.35rem; }

/* Bulk toolbar under the assets table — the selected count +
   one button per bulk op (each GETs into the wizard with its
   own formaction). Buttons stay disabled until a row is
   ticked (app.js). */
.project-assets-bulk-form-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.65rem;
  margin-top: 0.85rem;
  padding-top: 0.65rem;
  border-top: 1px dashed var(--border);
}
.project-assets-bulk-form-fields button {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.project-assets-bulk-form-fields button:disabled,
.project-assets-bulk-form-fields button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Ignored rows read as dormant: muted + italic, chips
   desaturated — same treatment as the old discovered queue. */
.project-assets-row-ignored td { color: var(--text-muted); font-style: italic; }
.project-assets-row-ignored .asset-kind-chip { filter: saturate(0.6); }

/* Collapsed "Add discovery" tester — mirrors the blacklist
   section's <details> card. */
.project-add-discovery-section {
  margin-top: 1rem;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.85rem 1.1rem;
}

/* ---- Bulk operations wizard -------------------------------------- */

.assets-bulk-shell { max-width: 1100px; margin: 0 auto; }
.assets-bulk-head h1 { margin: 0.4rem 0 0.5rem; }
.assets-bulk-head .breadcrumbs { font-size: 0.85rem; }
.assets-bulk-config-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 480px;
}
.assets-bulk-config-form label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.assets-bulk-config-form input[type="text"],
.assets-bulk-config-form select {
  font: inherit;
  padding: 0.4rem 0.55rem;
  border-radius: 4px;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
}
.assets-bulk-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  justify-content: flex-end;
  margin-top: 0.75rem;
}

/* Before/after preview table — mirrors the scan-move plan
   table's action-chip grammar so the two wizards read the
   same. */
.assets-bulk-plan { font-size: 0.85rem; }
.assets-bulk-plan code.mono { font-size: 0.78rem; word-break: break-all; }
.assets-bulk-plan .asset-kind-chip { display: inline-block; }
.assets-bulk-action {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  font: 600 0.7rem/1 var(--zq-font-family-mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.assets-bulk-row.assets-bulk-update .assets-bulk-action {
  background: color-mix(in srgb, var(--success) 16%, var(--bg-inset));
  color: var(--success);
}
.assets-bulk-row.assets-bulk-skip .assets-bulk-action {
  background: var(--bg-inset);
  color: var(--text-muted);
}
.assets-bulk-row.assets-bulk-skip td { color: var(--text-muted); }
.assets-bulk-confirm-form { margin-top: 1rem; }

/* Discovery-timeline notes (Phase 2 events): the LLM worker's
   evidence narrative under each observed event. */
.asset-discovery-notes { margin: 0.15rem 0 0; }
.scan-discovery-note-flag { cursor: help; }

/* Scan-policy eligibility chip (chunk 1b preview) — the derived
   "would this be scanned?" verdict on each asset row. Blocked
   rows show why via the native title; scannable rows stay quiet
   so the list doesn't fill with green noise. */

/* ---- Assets viewer: the discovery map ---------------------------- */

/* Shell — a glassy hero panel above the editor table. All colors
   ride the theme tokens so dark/light come free. */
.assets-viewer-shell {
  background:
    radial-gradient(1200px 400px at 20% -10%,
      color-mix(in srgb, var(--accent) 7%, transparent), transparent),
    var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.85rem 1rem 0.75rem;
  margin-bottom: 1rem;
}
.assets-viewer-toolbar {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.5rem;
}
.assets-viewer-title {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 1rem;
}
.flex-spacer { flex: 1; }

/* LIVE pulse while scans run. */
.viewer-live {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font: 600 0.68rem/1 var(--zq-font-family-mono);
  letter-spacing: 0.08em;
  color: var(--success);
}
.viewer-live-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--success);
  animation: viewer-pulse 1.4s ease-in-out infinite;
}
@keyframes viewer-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.8); }
}

/* Stage */
.assets-viewer-stage-wrap {
  position: relative;
  height: 440px;
  border-radius: 10px;
  overflow: hidden;
  background:
    radial-gradient(circle at 50% 50%,
      color-mix(in srgb, var(--bg-inset) 55%, transparent),
      transparent 70%);
}
.assets-viewer-svg {
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: grab;
  outline-offset: -2px;
}
.assets-viewer-svg:active { cursor: grabbing; }
.assets-viewer-svg:focus-visible {
  outline: 2px solid var(--accent);
}

/* Nodes — disc carries the kind color (same palette as the
   kind chips); pending wraps in a dashed amber ring. Hover dims
   everything not adjacent. */
.nv { cursor: pointer; }
.nv:focus-visible .nv-disc { stroke: var(--accent); stroke-width: 2.5; }
.nv-disc { transition: filter 0.15s ease; }
.nv:hover .nv-disc { filter: brightness(1.15); }
.nv-pending .nv-disc { opacity: 0.78; }
.nv-pending-ring {
  fill: none;
  stroke: var(--running, var(--running));
  stroke-width: 1.6;
  stroke-dasharray: 4 3;
}
.nv-cred {
  fill: #fff;
  stroke: rgba(0, 0, 0, 0.25);
  stroke-width: 0.6;
}
.nv-label {
  font-size: 10px;
  fill: var(--text-muted);
  pointer-events: none;
  user-select: none;
}
.nv-glyph { pointer-events: none; }
.nv.nv-spawn { animation: nv-pop 0.5s cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes nv-pop {
  from { opacity: 0; }
  to { opacity: 1; }
}
svg.has-hover .nv-dim { opacity: 0.18; transition: opacity 0.18s ease; }
svg.has-hover .nv { transition: opacity 0.18s ease; }

/* Edges */
.edge-layer { pointer-events: none; }
.edge { stroke-width: 1.6; fill: none; }
.edge-disc {
  stroke: color-mix(in srgb, var(--link) 55%, var(--border));
}
.edge-rel {
  stroke: var(--text-muted);
  stroke-dasharray: 5 4;
  opacity: 0.7;
}
.edge-arrow-head { fill: color-mix(in srgb, var(--link) 70%, var(--border)); }
.edge-arrow-head-dim { fill: var(--text-muted); opacity: 0.7; }
.edge-new { animation: edge-draw 0.9s ease forwards; }
@keyframes edge-draw {
  from { opacity: 0; stroke-dashoffset: 240; stroke-dasharray: 240; }
  to { opacity: 1; }
}
.edge.edge-dim { opacity: 0.06; transition: opacity 0.18s ease; }
.edge { transition: opacity 0.18s ease; }
/* Dash-flow on live maps: edges quietly move toward their target,
   signalling an active scan without shouting. */
svg.is-live:not(.has-hover) .edge-disc {
  stroke-dasharray: 6 10;
  animation: edge-flow 1.6s linear infinite;
}
@keyframes edge-flow {
  to { stroke-dashoffset: -16; }
}
@media (prefers-reduced-motion: reduce) {
  .viewer-live-dot, .nv.nv-spawn, .edge-new { animation: none !important; }
  svg.is-live:not(.has-hover) .edge-disc {
    animation: none !important;
    stroke-dasharray: none !important;
  }
}

/* Tooltip card */
.viewer-tooltip {
  position: absolute;
  max-width: 300px;
  padding: 0.55rem 0.7rem;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  z-index: 30;
  font-size: 0.82rem;
}
.tt-url {
  display: block;
  word-break: break-all;
  margin-bottom: 0.3rem;
  color: var(--text-code);
}
.tt-chips { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 0.3rem; }
.tt-chip {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font: 600 0.66rem/1.5 var(--zq-font-family-mono);
  text-transform: lowercase;
  background: var(--bg-inset);
  color: var(--text-muted);
}
.tt-chip.kind-url { color: #2fae92; }
.tt-chip.kind-repo { color: #3f8ae0; }
.tt-chip.kind-host { color: #d49b35; }
.tt-chip.ok { color: var(--success); }
.tt-chip.warn { color: var(--running, var(--running)); }
.tt-notes {
  border-left: 2px solid var(--border);
  padding-left: 0.5rem;
  margin-bottom: 0.3rem;
  color: var(--text);
}
.tt-scan { color: var(--text-muted); font-size: 0.74rem; }
.tt-hint { margin-top: 0.25rem; }

/* Empty state — the content box is the design system's .zq-empty; this
   rule only positions it over the map stage. */
.viewer-empty {
  position: absolute;
  inset: 0;
}
.viewer-empty[hidden] { display: none; }

/* Legend */
.assets-viewer-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8rem;
  margin-top: 0.55rem;
  font-size: 0.76rem;
  color: var(--text-muted);
}
.legend-item { display: inline-flex; align-items: center; gap: 0.32rem; }
.legend-swatch {
  width: 11px; height: 11px;
  border-radius: 50%;
  display: inline-block;
}
.legend-swatch.kind-url { background: #2fae92; }
.legend-swatch.kind-repo { background: #3f8ae0; }
.legend-swatch.kind-host { background: #d49b35; }
.legend-ring {
  width: 10px; height: 10px;
  border-radius: 50%;
  display: inline-block;
  background: var(--bg-inset);
}
.legend-ring.legend-approved { border: 2px solid var(--success); }
.legend-ring.legend-pending {
  border: 2px dashed var(--running, var(--running));
}
.legend-edge { display: block; }
.legend-edge-disc { stroke: color-mix(in srgb, var(--link) 55%, var(--border)); stroke-width: 1.6; }
.legend-edge-rel { stroke: var(--text-muted); stroke-width: 1.6; stroke-dasharray: 5 4; }

/* ---- Viewer v2: presence overhaul ---------------------------------
   The v1 graph was too quiet — hairline edges that vanished against
   the panel and shaking nodes from every poll re-wake. These rules
   give edges real weight (kind-tinted, glowing, arrowed), discs a
   lit-from-above finish, labels halos so they read over lines, the
   stage a dot-grid depth, and scan roots their pill treatment. */

/* Stage depth */
.assets-viewer-stage-wrap {
  background-color: var(--bg-inset);
  background-image:
    radial-gradient(circle at 50% 45%,
      color-mix(in srgb, var(--accent) 6%, transparent), transparent 65%),
    radial-gradient(circle,
      color-mix(in srgb, var(--text-muted) 22%, transparent) 1px,
      transparent 1.5px);
  background-size: auto, 24px 24px;
}
.assets-viewer-stage-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 80px 30px rgba(0, 0, 0, 0.28);
  border-radius: inherit;
}

/* Edges: visible strokes with glow; discovered_from is tinted by
   the child's kind via inline stroke set in JS. */
.edge-layer { filter: url(#edge-glow); }
.edge { stroke-width: 2.2; }
.edge-disc { stroke-linecap: round; }
svg.is-live:not(.has-hover) .edge-disc {
  animation: edge-flow 1.6s linear infinite;
}
.edge-obs {
  stroke: var(--scan-node, #8b7cf6);
  stroke-width: 1.6;
  stroke-dasharray: 2 5;
  opacity: 0.85;
}
.edge-arrow-head-obs { fill: var(--scan-node, #8b7cf6); }
svg.has-hover .edge-dim { opacity: 0.04; }

/* Nodes: lit discs. */
.nv-disc { stroke: rgba(255, 255, 255, 0.14); stroke-width: 1; }
.nv-shine { fill: url(#node-shine); pointer-events: none; }
.nv-halo {
  fill: none;
  stroke: transparent;
  transition: stroke 0.18s ease;
}
svg.has-hover .nv:not(.nv-dim) .nv-halo {
  stroke: color-mix(in srgb, var(--link) 35%, transparent);
}
.nv-label {
  font-size: 10.5px;
  font-weight: 500;
  paint-order: stroke;
  stroke: var(--bg-inset);
  stroke-width: 3px;
  stroke-linejoin: round;
}

/* Scan-root pill */
.nv-pill { stroke: rgba(255, 255, 255, 0.16); }
.nv-label-pill {
  fill: #ffffff;
  font-weight: 600;
  letter-spacing: 0.02em;
  stroke: none;
}

/* Filter box in the toolbar */
.viewer-filter-wrap { display: inline-flex; }
.viewer-filter {
  width: 190px;
  padding: 0.32rem 0.55rem;
  border-radius: 6px;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text);
  font-size: 0.8rem;
}
.viewer-filter:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  width: 230px;
}

/* Spec kind (chunk 3a) — same chip palette as the others, in the
   four rule groups that key off ``kind-<name>``. */
.scan-choice-card.kind-spec { --profile-color: #c257b3; }
.project-assets-table .asset-kind-chip.kind-spec { --asset-chip-color: #c257b3; }
.project-reports-table .asset-kind-chip.kind-spec { --asset-chip-color: #c257b3; }
.assets-viewer-legend .legend-swatch.kind-spec,
.viewer-tooltip .tt-chip.kind-spec { color: #c257b3; }
.legend-swatch.kind-spec { background: #c257b3; }
.tt-chip.kind-spec { color: #c257b3 !important; background: transparent; border: 1px solid #c257b355; }

/* Doc kind (chunk: documentation seeds) — terracotta, unscoped so
   the chip reads in the tables, the detail page, and the viewer. */
.scan-choice-card.kind-doc { --profile-color: #cf6b4e; }
.asset-kind-chip.kind-doc { --asset-chip-color: #cf6b4e; }
.project-assets-table .asset-kind-chip.kind-doc { --asset-chip-color: #cf6b4e; }
.project-reports-table .asset-kind-chip.kind-doc { --asset-chip-color: #cf6b4e; }
.assets-viewer-legend .legend-swatch.kind-doc,
.viewer-tooltip .tt-chip.kind-doc { color: #cf6b4e; }
.legend-swatch.kind-doc { background: #cf6b4e; }
.tt-chip.kind-doc { color: #cf6b4e !important; background: transparent; border: 1px solid #cf6b4e55; }

/* Binary kind (chunk: compiled-artifact seeds) — steel blue, same
   four rule groups as the other kinds. */
.scan-choice-card.kind-binary { --profile-color: #4e88c7; }
.asset-kind-chip.kind-binary { --asset-chip-color: #4e88c7; }
.project-assets-table .asset-kind-chip.kind-binary { --asset-chip-color: #4e88c7; }
.project-reports-table .asset-kind-chip.kind-binary { --asset-chip-color: #4e88c7; }
.assets-viewer-legend .legend-swatch.kind-binary,
.viewer-tooltip .tt-chip.kind-binary { color: #4e88c7; }
.legend-swatch.kind-binary { background: #4e88c7; }
.tt-chip.kind-binary { color: #4e88c7 !important; background: transparent; border: 1px solid #4e88c755; }

/* Doc extraction panel — the mini-scan live view on the doc
   asset's detail page: status chip, append-only log stream,
   stats row. Borrowed sizing from the scan log view. */
.doc-extract-panel { border: 1px solid var(--border); border-radius: 8px; padding: 1rem 1.1rem; background: var(--bg-inset); }
.doc-extract-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.doc-extract-title { display: flex; align-items: center; gap: 0.5rem; font-weight: 600; }
.doc-extract-status { font: 600 0.68rem/1 var(--zq-font-family-mono); text-transform: uppercase; letter-spacing: 0.05em; padding: 0.22rem 0.55rem; border-radius: 999px; border: 1px solid var(--border); }
.doc-extract-status.queued  { color: var(--text-muted); }
.doc-extract-status.running { color: var(--running, var(--running)); border-color: color-mix(in srgb, var(--running, var(--running)) 45%, transparent); }
.doc-extract-status.completed { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent); }
.doc-extract-status.failed { color: var(--danger, #e5646c); border-color: color-mix(in srgb, var(--danger, #e5646c) 45%, transparent); }
.doc-extract-stats { display: flex; gap: 1.1rem; flex-wrap: wrap; margin: 0.6rem 0 0.2rem; }
.doc-extract-stats .stat b { font-size: 0.95rem; }
.doc-extract-stats .stat .muted { display: block; font-size: 0.68rem; }
.doc-extract-log { margin-top: 0.7rem; max-height: 320px; overflow-y: auto; font: 0.74rem/1.5 var(--zq-font-family-mono); border-top: 1px solid var(--border); padding-top: 0.6rem; }
.doc-extract-log .log-line { display: flex; gap: 0.6rem; padding: 0.08rem 0; }
.doc-extract-log .log-ts { color: var(--text-muted); white-space: nowrap; }
.doc-extract-log .log-line.warn .log-msg { color: var(--running, var(--running)); }
.doc-extract-log .log-line.error .log-msg { color: var(--danger, #e5646c); }
.doc-extract-log .log-msg { white-space: pre-wrap; word-break: break-word; }

/* ---- Agent inbox ---------------------------------------------------- */
.inbox-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.inbox-toolbar h1 { margin: 0; }

.inbox-layout {
  display: grid; grid-template-columns: minmax(280px, 400px) 1fr;
  gap: 1rem; align-items: start; margin-top: 0.5rem;
}
@media (max-width: 900px) { .inbox-layout { grid-template-columns: 1fr; } }

.inbox-list {
  border: 1px solid var(--border); border-radius: 8px;
  overflow: hidden; background: var(--bg-surface);
}
.inbox-thread {
  display: block; padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--border);
  text-decoration: none; color: var(--text);
}
.inbox-thread:last-child { border-bottom: none; }
.inbox-thread:hover { background: var(--bg-surface2); }
.inbox-thread.active { background: var(--bg-surface2); box-shadow: inset 3px 0 0 var(--accent); }

.inbox-thread-top { display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline; }
/* The from-line shares the row with the timestamp: it must clip
   itself (sender ellipsizes, badge shrinks) instead of painting
   over the time when sender + project name overflow the column. */
.inbox-thread-from {
  display: flex; align-items: center; gap: 0.4rem;
  min-width: 0; flex: 1 1 auto; overflow: hidden; font-weight: 400;
}
.inbox-thread.unread .inbox-thread-from { font-weight: 700; }
.inbox-thread-sender { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Shrink-weighted above the sender and floored, so a long project
   name yields before the sender does but never disappears. */
.inbox-thread-from .zq-badge { display: block; flex: 0 2 auto; min-width: 2.5rem; overflow: hidden; text-overflow: ellipsis; }
.inbox-thread-time { color: var(--text-muted); font-size: 0.78rem; flex: 0 0 auto; white-space: nowrap; }
.inbox-thread-subject { margin: 0.15rem 0 0; font-size: 0.9rem; }
.inbox-thread.unread .inbox-thread-subject { font-weight: 600; }
.inbox-thread-excerpt {
  margin: 0.15rem 0 0; color: var(--text-muted); font-size: 0.82rem;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  white-space: pre-wrap;
}
.inbox-dot {
  width: 8px; height: 8px; border-radius: 999px;
  background: var(--accent); display: inline-block; flex: 0 0 auto;
}
.inbox-kind-icon { font-size: 1rem; color: var(--text-muted); flex: 0 0 auto; }

.inbox-reading {
  border: 1px solid var(--border); border-radius: 8px;
  padding: 1.1rem 1.25rem; background: var(--bg-surface); min-height: 320px;
}
.inbox-reading-head h2 {
  margin: 0 0 0.35rem; font-size: 1.15rem;
  display: flex; align-items: center; gap: 0.45rem;
}
.inbox-actions { display: flex; gap: 0.6rem; margin-top: 1rem; flex-wrap: wrap; align-items: center; }
/* ---- Message thread (reading pane) --------------------------------- */
.inbox-messages {
  list-style: none; padding: 0; margin: 1rem 0 0;
  display: flex; flex-direction: column; gap: 0.6rem;
}
.inbox-message {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.55rem 0.8rem;
  background: var(--bg-surface);
}
.inbox-message-incoming { border-left: 3px solid var(--accent); }
.inbox-message-outgoing { border-left: 3px solid var(--ok); background: var(--bg-surface2); }
.inbox-message-system { border-left: 3px solid var(--text-muted); background: var(--bg-surface2); }
.inbox-message-meta {
  display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline;
  font-size: 0.82rem;
}
.inbox-message-actor {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-weight: 600;
}
.inbox-msg-icon { font-size: 0.95rem; color: var(--text-muted); }
.inbox-message-time { flex: 0 0 auto; }
.inbox-message-subject { margin-top: 0.25rem; font-size: 0.9rem; font-weight: 600; }
.inbox-message-body {
  margin-top: 0.25rem;
  white-space: pre-wrap; word-break: break-word; font-size: 0.9rem;
  color: var(--text);
}

/* ---- Agent inbox · calendar view ----------------------------------- */
.inbox-calendar { display: flex; flex-direction: column; gap: 0.75rem; min-width: 0; }
.inbox-calendar-header {
  display: flex; align-items: center; gap: 0.6rem;
  flex-wrap: wrap;
}
.inbox-calendar-month {
  font-size: 1.15rem; font-weight: 600; flex: 1 1 auto;
  min-width: 8rem; text-align: center;
}
.inbox-calendar-today { margin-left: auto; }
.inbox-calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-surface);
}
.inbox-calendar-dow { display: contents; }
.inbox-calendar-dow-cell {
  padding: 0.4rem 0.5rem; font-size: 0.75rem; text-transform: uppercase;
  color: var(--text-muted); background: var(--bg-surface2);
  border-bottom: 1px solid var(--border);
  text-align: center; letter-spacing: 0.05em;
}
.inbox-calendar-week { display: contents; }
.inbox-calendar-day {
  min-height: 6.5rem; padding: 0.3rem 0.4rem;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 0.2rem;
  background: var(--bg-surface); font-size: 0.78rem;
  overflow: hidden;
}
.inbox-calendar-day:nth-child(7n) { border-right: none; }
.inbox-calendar-day.out-of-month { background: var(--bg-surface2); color: var(--text-muted); }
.inbox-calendar-day.today .inbox-calendar-day-num {
  background: var(--accent); color: var(--accent-contrast, #fff);
  border-radius: 999px; width: 1.5rem; height: 1.5rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.inbox-calendar-day-num { font-weight: 600; align-self: flex-start; }
.inbox-calendar-event {
  background: var(--accent-soft, rgba(80, 120, 200, 0.18));
  border-left: 3px solid var(--accent);
  border-radius: 3px;
  padding: 0.1rem 0.35rem;
  display: flex; gap: 0.3rem; align-items: baseline;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 0.72rem;
}
.inbox-calendar-event-time { font-weight: 600; flex: 0 0 auto; }
.inbox-calendar-event-label { overflow: hidden; text-overflow: ellipsis; }
.inbox-calendar-more { font-size: 0.7rem; color: var(--text-muted); padding: 0 0.35rem; }

@media (max-width: 700px) {
  .inbox-calendar-day { min-height: 4.5rem; font-size: 0.7rem; }
  .inbox-calendar-event-label { display: none; }
}

.inline-form { display: inline; }

/* ---- Audit tab: grouped execution notes ------------------------- */
.execution-notes { margin-bottom: 1.25rem; }
.execution-notes-title {
  font-size: 0.95rem;
  margin: 0 0 0.5rem;
}
.execution-note {
  border: 1px solid var(--border-light);
  border-radius: 4px;
  padding: 0.45rem 0.65rem;
  margin-bottom: 0.4rem;
  background: var(--bg-surface);
}
.execution-note-stage_failure { border-color: var(--warn-border); background: var(--warn-bg); }
.execution-note-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.execution-note-flag {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--warn-text);
  border: 1px solid var(--warn-border);
  border-radius: 999px;
  padding: 0 0.4rem;
}
.execution-note-links {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}
.execution-note-links .inline-form { margin: 0; }
.execution-note-samples { margin-top: 0.3rem; }
.execution-note-samples summary { cursor: pointer; }
.execution-note-sample {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0.25rem 0 0;
}
.execution-note-routine { margin: 0.5rem 0 0; }

/* Surface view — grouped-by-surface accordion on the assets tab.
   Clusters are computed server-side over the project's whole URL
   corpus; this is presentation only. */
.project-assets-view-toggle { display: inline-flex; gap: 0.3rem; }
.project-assets-view-toggle .zq-btn.active {
  border-color: var(--accent, #2fae92);
  color: var(--accent, #2fae92);
}
.surface-view { margin: 0.8rem 0 1.2rem; }
.surface-cluster {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.5rem;
  background: var(--bg-inset);
}
.surface-cluster > summary {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  padding: 0.55rem 0.9rem;
  cursor: pointer;
  list-style: none;
}
.surface-cluster > summary::-webkit-details-marker { display: none; }
.surface-cluster > summary::before {
  content: '▸';
  color: var(--text-muted);
  transition: transform 120ms ease;
}
.surface-cluster[open] > summary::before { transform: rotate(90deg); }
.surface-cluster-label { font-weight: 600; color: var(--accent, #2fae92); }
.surface-cluster-param {
  font: 600 0.64rem/1.4 var(--zq-font-family-mono);
  color: var(--running, var(--running));
  border: 1px solid color-mix(in srgb, var(--running, var(--running)) 40%, transparent);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
}
.surface-cluster-body { padding: 0.2rem 0.9rem 0.8rem; }
.surface-cluster-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.3rem 0 0.6rem;
}
.surface-cluster .surface-cluster {
  margin: 0.5rem 0 0.2rem 1.2rem;
}
.surface-cluster-table { margin-top: 0.2rem; }
.surface-cluster-table td { padding: 0.3rem 0.6rem; }

.asset-derived-label.llm { font-weight: 600; }
.asset-evidence-line { max-width: 46ch; }
.surface-cluster-host {
  font: 600 0.68rem/1.4 var(--zq-font-family-mono);
  color: var(--text-muted);
}
.assets-bulk-rewrite-preview {
  /* Full-width review surface — the narrow box made a 100-row
     check unreadable. Still height-capped so the action buttons
     stay reachable. */
  max-height: 60vh;
  overflow-y: auto;
  margin: 0.7rem 0;
  border: 1px solid var(--border);
  border-radius: 6px;
}
.assets-bulk-rewrite-preview table { margin: 0; }
.assets-bulk-rewrite-preview td { vertical-align: top; }
.assets-bulk-rewrite-preview tr.rewrite-no-match { opacity: 0.45; }
/* Host nodes root the grouped hierarchy — visually heavier than
   path clusters nested beneath them. */
.surface-cluster-hostnode > summary {
  padding: 0.65rem 0.9rem;
  background: color-mix(in srgb, var(--accent, #2fae92) 6%, var(--bg-inset));
}
.surface-cluster-hostnode > summary::before { color: var(--accent, #2fae92); }
.surface-cluster .surface-cluster .surface-cluster {
  margin-left: 1.6rem;
}
/* Grouped-view batch bar + approval-state color coding. */
.surface-batch-bar {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  border: 1px solid var(--accent, #2fae92);
  border-radius: 8px;
  padding: 0.5rem 0.9rem;
  margin-bottom: 0.6rem;
  background: color-mix(in srgb, var(--accent, #2fae92) 6%, var(--bg-inset));
}
.surface-batch-form { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.surface-cluster.surface-state-approved { border-left: 3px solid color-mix(in srgb, var(--success) 55%, transparent); }
.surface-cluster.surface-state-pending { border-left: 3px solid color-mix(in srgb, var(--running, var(--running)) 55%, transparent); }
.surface-cluster.surface-state-mixed { border-left: 3px solid var(--border); }
.surface-cluster-check { accent-color: var(--accent, #2fae92); }
/* Type families: the grouped view partitions into top-level groups
   per asset family (web surfaces, git repositories, servers), each
   with its own hierarchy presentation. Hue matches the discovery
   map's kind colors (assets.js KIND_COLOR). */
.surface-family { margin: 0 0 1.6rem; }
.surface-family-head {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  padding: 0.15rem 0.1rem 0.45rem;
  margin: 0 0 0.7rem;
}
.surface-family-head h3 { margin: 0; font-size: 0.95rem; }
/* Repo family: containers are not scan targets, so the header shows
   an approval-composition line instead of the target-state badge. */
.surface-cluster-composition {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}
.surface-repo-cluster > summary::before { color: #3f8ae0; }
.surface-repo-cluster .surface-cluster-label { color: #3f8ae0; }
.surface-repo-cluster.surface-cluster-hostnode > summary {
  background: color-mix(in srgb, #3f8ae0 7%, var(--bg-inset));
}
.surface-repo-cluster.surface-cluster-hostnode > summary::before { color: #3f8ae0; }
.surface-server-cluster > summary::before { color: #d49b35; }
.surface-server-cluster.surface-cluster-hostnode > summary {
  background: color-mix(in srgb, #d49b35 7%, var(--bg-inset));
}
.surface-server-cluster.surface-cluster-hostnode > summary::before { color: #d49b35; }
.nv-bubble {
  fill: var(--accent, #8b7cf6);
  stroke: var(--accent, #8b7cf6);
  stroke-width: 1;
  pointer-events: none;
}
/* Reachability topology edges (chunk E): distinct color + marker;
   stale edges render dashed and dimmed. */
.edge-reach {
  stroke: #cf6b4e;
  stroke-width: 2;
}
.edge-reach-stale {
  stroke: var(--text-muted);
  stroke-dasharray: 3 5;
  opacity: 0.75;
}
.edge-arrow-reach { fill: #cf6b4e; }
.legend-edge-reach {
  stroke: #cf6b4e;
  stroke-width: 2;
}
.edge-arrow-head-reach { fill: #cf6b4e; }
.surface-coverage-samples { margin: 0.2rem 0 0; padding-left: 1rem; }
.surface-coverage-samples li { list-style: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Two-tier asset cards on the map (header = where, body = what). */
.nv-card {
  fill: var(--bg-inset, #10161c);
  stroke: color-mix(in srgb, var(--card-stroke, var(--text-muted)) 45%, transparent);
  stroke-width: 1;
}
.nv-card-head { fill: var(--card-head, #2fae92); }
.nv-card-head-fill { fill: color-mix(in srgb, #0c1116 55%, var(--card-head, #2fae92)); }
.nv-card-header {
  font: 600 10px/1 var(--zq-font-family-mono);
  fill: #eef4f0;
}
.nv-card-body {
  font: 9.5px/1 var(--zq-font-family-mono);
  fill: var(--text-muted);
}
.nv.nv-url .nv-card-head { --card-head: #2fae92; }
.nv.nv-repo .nv-card-head { --card-head: #3f8ae0; }
.nv.nv-host .nv-card-head { --card-head: #d49b35; }
.nv.nv-doc .nv-card-head { --card-head: #cf6b4e; }
.nv.nv-spec .nv-card-head { --card-head: #c257b3; }
/* Container blobs hug members; not hoverable themselves. */
.nv-blob { pointer-events: none; }
/* Parent chip: which scan/group an asset (or a whole bubble)
   belongs to. The tone is the parent's hue — the same one the
   bubble washes with and the scan-root pill is filled with — and
   it never travels alone: the hub label and the hover tooltip
   name the run in words. Click-through, so hit targets are
   unchanged. */
.nv-parent-chip {
  pointer-events: none;
  stroke: rgba(12, 17, 22, 0.65);
  stroke-width: 1;
}


/* Surface coverage: the per-area table runs long, so the card collapses
   to the totals line until opened. */
.coverage-details > summary {
  list-style: none;
  cursor: pointer;
}

/* Live-access-lost banner: scan-live.js stops every poller and SSE
   stream once the server answers 401/403/404 (permanent for the page
   load — tenancy 404s are deliberate), and shows this instead. */
.live-access-lost {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 0.55rem 1rem;
  background: var(--warn-bg);
  border-bottom: 1px solid var(--warn-border);
  color: var(--warn-text);
}

/* ---- Engagement timeline ---------------------------------------- */
/* Note composer: the textarea only gets control treatment from the
   element bridge, which leaves it inline-width — unstyled, the label
   caption and the textarea collide on one line. */
.engagement-message-composer { margin-bottom: 1.5rem; }
.engagement-message-composer label {
  display: grid;
  gap: 0.35rem;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.engagement-message-composer textarea {
  display: block;
  width: 100%;
  resize: vertical;
}


/* Wizard "Test credentials" inline result (issue #375) */
.scan-auth-test-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; flex-wrap: wrap; }
.scan-auth-result { font-size: 0.85rem; }
.scan-auth-result.scan-auth-ok { color: var(--ok); }
.scan-auth-result.scan-auth-warn { color: var(--warning); }
.scan-auth-result.scan-auth-error { color: var(--error); }

/* Wizard API-login controls (issue #378): the advanced token / CSRF
   disclosure inside the form-login subsection. */
details.auth-advanced { margin: 0.5rem 0 0.75rem; }
details.auth-advanced > summary { cursor: pointer; font-size: 0.9rem; }
details.auth-advanced[open] > summary { margin-bottom: 0.5rem; }
