/* styles/ledger.css — triage queue, ledger toolbar + table, empty states. Order in VulnerabilityCore.html is the cascade order. */

/* ============================================================ triage */
.triage {
  display: flex;
  flex-direction: column;
}
.triage-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  cursor: pointer;
  padding: 13px 8px;
  border-top: 1px solid var(--line);
  transition: 0.12s;
}
.triage-row:first-child {
  border-top: none;
}
.triage-row:hover {
  background: var(--surface-2);
}
.triage-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.triage-top {
  display: flex;
  align-items: center;
  gap: 9px;
}
.triage-id {
  font: 600 12.5px/1 var(--font-mono);
  color: var(--text);
}
.triage-desc {
  font: 13px/1.35 var(--font);
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.triage-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
  flex: none;
  width: 190px;
}
.triage-ecu {
  font: 12px/1.2 var(--font);
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.triage-chev {
  color: var(--text-faint);
  flex: none;
}

/* ============================================================ ledger toolbar */
.toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.search {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 240px;
  height: 40px;
  padding: 0 12px;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
/* --focus, not raw --accent: #49299a on the dark canvas is 1.5-1.8:1, so focusing
   the search box changed nothing a dark-theme user could see. --accent-soft is a
   color-mix() and does fork by theme, so the glow stays. */
.search:focus-within {
  border-color: var(--focus);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.search-ic {
  color: var(--text-faint);
}
.search input {
  flex: 1;
  border: none;
  background: none;
  outline: none;
  color: var(--text);
  font: 13.5px/1 var(--font);
}
.search input::placeholder {
  color: var(--text-faint);
}
/* 14px icon + 10px padding = a 24x24 target (WCAG 2.2 SC 2.5.8). The negative
   margin keeps the field's optical right edge where it was. */
.search-clear {
  background: none;
  border: none;
  color: var(--text-faint);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 5px;
  margin-right: -3px;
  border-radius: 6px;
}
.search-clear:hover {
  color: var(--text);
}
.tool-spacer {
  flex: 1;
}
.dd {
  position: relative;
}
.dd-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font: 13px/1 var(--font);
  cursor: pointer;
}
.dd-btn:hover,
.dd-btn.is-open {
  border-color: var(--line-2);
  color: var(--text);
}
.dd-btn .ic:first-child {
  color: var(--text-faint);
}
.dd-lab {
  color: var(--text-faint);
}
.dd-val {
  color: var(--text);
  font-weight: 600;
}
.dd-caret {
  color: var(--text-faint);
  margin-left: 1px;
}
.dd-small .dd-btn {
  height: 32px;
  padding: 0 10px;
  font-size: 12px;
}
/* A dropdown that is actually filtering something. With five filter triggers in a
   row, reading five value strings left-to-right to find the set one is work a
   border does pre-attentively. Same recipe as .admin-nav-btn.is-on: --accent-soft
   over the dark chip composites to roughly the unset chip colour, so the fill is
   only a hint and the --focus BORDER is what carries both themes (--accent-3 on
   dark, --accent at 10.15:1 on light). Placed after .dd-small so it wins the
   (0,2,0) tie with .dd-btn:hover / .dd-btn.is-open above. */
.dd-btn.is-set {
  border-color: var(--focus);
  background: var(--accent-soft);
  color: var(--text);
}
/* is-set beats :hover on border-color, so hover/open feedback moves to the fill. */
.dd-btn.is-set:hover,
.dd-btn.is-set.is-open {
  background: var(--surface-2);
}
.dd-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  min-width: 170px;
  background: var(--bg-panel);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 6px;
}
.dd-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  border: none;
  background: none;
  color: var(--text);
  font: 500 13px/1 var(--font);
  padding: 8px 9px;
  border-radius: 7px;
  cursor: pointer;
  text-align: left;
}
.dd-item:hover {
  background: var(--surface-2);
}
.dd-item-clear {
  margin-top: 4px;
  border-top: 1px solid var(--line-2);
  border-radius: 0 0 7px 7px;
  color: var(--text-dim);
  justify-content: center;
}
.dd-item.is-on {
  color: var(--focus);
}
/* `.dd-item .ic { color: var(--accent) }` was deleted here. The tick only ever
   renders on an is-on row (every call site gates it on the same condition) and
   Icon strokes with currentColor, so it now inherits the row's --focus. On dark,
   raw --accent put that tick at 1.82:1 — the one mark saying "this filter is
   applied" was the least visible thing in the menu. */

.filterbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding-bottom: 4px;
}
.filterbar-group {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.filterbar-lab {
  display: flex;
  align-items: center;
  gap: 6px;
  font: 600 11px/1 var(--font);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  white-space: nowrap;
}
.filterbar-lab .ic {
  color: var(--text-faint);
}
.filterbar-div {
  width: 1px;
  height: 18px;
  background: var(--line-2);
  margin: 0 3px;
  flex-shrink: 0;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: 600 12px/1 var(--font);
  color: var(--text-dim);
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 6px 10px;
  border-radius: 20px;
  cursor: pointer;
  transition: 0.12s;
}
.chip:hover {
  border-color: var(--line-2);
  color: var(--text);
}
.chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sc, var(--text-faint));
}
.chip.sev-critical.is-on {
  background: color-mix(in oklab, var(--sev-critical) 16%, transparent);
  border-color: var(--sev-critical);
  color: var(--sev-critical);
}
.chip.sev-high.is-on {
  background: color-mix(in oklab, var(--sev-high) 16%, transparent);
  border-color: var(--sev-high);
  color: var(--sev-high);
}
.chip.sev-medium.is-on {
  background: color-mix(in oklab, var(--sev-medium) 16%, transparent);
  border-color: var(--sev-medium);
  color: var(--sev-medium);
}
.chip.sev-low.is-on {
  background: color-mix(in oklab, var(--sev-low) 16%, transparent);
  border-color: var(--sev-low);
  color: var(--sev-low);
}
.chip-status.is-on {
  background: color-mix(in oklab, var(--sc) 18%, transparent);
  border-color: var(--sc);
  color: var(--text);
}
.filterbar-clear {
  background: none;
  border: none;
  /* --focus: as raw --accent this link measured 1.93:1 on the dark canvas — the
     only control that undoes every active filter, and it read as dark-on-dark. */
  color: var(--focus);
  font: 600 12px/1 var(--font);
  cursor: pointer;
  padding: 6px;
  flex-shrink: 0;
}
.filterbar-count {
  font: 12px/1 var(--font-mono);
  color: var(--text-faint);
  margin-left: auto;
  flex-shrink: 0;
}
/* Keyboard focus for the whole control strip. Required, not decorative:
   `.toolbar :focus-visible` is (0,2,0) and beats the (0,1,1) `.search input
   { outline: none }` that would otherwise swallow the ring on the text field. */
.toolbar :focus-visible,
.filterbar :focus-visible,
.dd-menu :focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
/* The field itself keeps its :focus-within treatment above; a second ring inside
   the border would double up. */
.search input:focus-visible {
  outline: none;
}

/* ============================================================ ledger table */
.table-card {
  padding: 0;
  overflow-x: auto;
  overflow-y: hidden;
  /* The column set follows the TABLE's width, not the viewport's (see the
     @container ladder below): with the sidebar and the page's 1320px cap, a 1920px
     and a 1700px screen both give it 1268px, and a 1440px laptop 1140px. */
  container: ledger / inline-size;
}
/* severity · CVE · description · affects · supplier · published · assignee · due ·
   jira · status. The description is the one flexible track and it has a floor:
   without one it got whatever the nine fixed tracks left over (52px on the widest
   page, 0 on a laptop) and its header label ran into "Affects". */
.lrow {
  display: grid;
  grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 96px 76px 128px 112px 108px 128px;
  align-items: center;
  gap: 14px;
  padding: 13px 18px;
  min-width: min-content;
}
.lrow-head {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  font: 600 12px/1 var(--font);
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-dim);
}
/* A header label truncates inside its own track instead of running into the next
   one. Several cells are flex containers, hence min-width:0 on both levels. */
.lrow-head > span {
  min-width: 0;
}
.lc-head-lab {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Columns step out, least-used first, whenever the table cannot give every track
   its width AND the description its 150px floor. Each threshold is that tier's
   tracks + gaps + the row's 36px padding + 150. Everything a hidden column shows
   stays one click away on the detail page, and its filter or sort stays in the
   toolbar (Date filter + "Newest" sort; Group by Supplier).
     >= 1334  all ten (wider than the page cap today, kept for a wider layout)
     <  1334  - Published      1268 (1700px+ screens)
     <  1244  - Supplier       1236 (1536), 1140 (1440)
     <  1134  - Jira           1066 (1366)
     <  1012  - Due             980 (1280)
     <   886  - Assignee        881 (1181), 800 (1100)
     <   744  - Affects         732 (1024), 609 (901)
   At <=760px viewports responsive.css turns the rows into cards instead.
   `.lrow > .lc-x` (0,2,0) because jira.css, later in the cascade, sets .lc-jira's
   display at (0,1,0). */
@container ledger (width < 1334px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 96px 128px 112px 108px 128px; }
  .lrow > .lc-date { display: none; }
}
@container ledger (width < 1244px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 128px 112px 108px 128px; }
  .lrow > .lc-sup { display: none; }
}
@container ledger (width < 1134px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 128px 112px 128px; }
  .lrow > .lc-jira { display: none; }
}
@container ledger (width < 1012px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 128px 128px; }
  .lrow > .lc-due { display: none; }
}
@container ledger (width < 886px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 150px 128px; }
  .lrow > .lc-assignee { display: none; }
}
@container ledger (width < 744px) {
  .lrow { grid-template-columns: 104px 120px minmax(150px, 1fr) 128px; }
  .lrow > .lc-ecu { display: none; }
}
.lrow-data {
  border-top: 1px solid var(--line);
  cursor: pointer;
  transition: 0.1s;
}
.lrow-data:hover {
  background: var(--surface-2);
}
.lc-id {
  color: var(--text);
  font-size: 12.5px;
}
/* EPSS sub-line under the CVE id — only rendered when the row has a score. */
.lc-epss {
  display: block;
  font: 500 10.5px/1 var(--font-mono);
  font-style: normal;
  color: var(--text-faint);
  margin-top: 3px;
  letter-spacing: 0.02em;
}
.lc-desc {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.lc-desc-tx {
  font: 13px/1.4 var(--font);
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lc-ecu {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font: 12.5px/1.2 var(--font);
  color: var(--text);
  min-width: 0;
}
.lc-ecu-if {
  font: 10.5px/1 var(--font-mono);
  color: var(--text-faint);
  font-style: normal;
}
.lc-sup {
  font: 12.5px/1 var(--font);
  color: var(--text-dim);
}
.lc-date {
  font-size: 11.5px;
  color: var(--text-dim);
}
.lc-stat {
  display: flex;
  justify-content: flex-start;
}
.lc-assignee {
  display: flex;
  justify-content: flex-start;
  min-width: 0;
}
.lgroup-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px 8px;
  background: var(--surface-2);
  border-top: 1px solid var(--line);
}
.lgroup-title {
  font: 600 12.5px/1 var(--font);
  color: var(--text);
}
.lgroup-count {
  font: 600 11px/1 var(--font-mono);
  color: var(--text-dim);
  background: var(--surface-3);
  padding: 3px 7px;
  border-radius: 20px;
}
.lgroup-line {
  flex: 1;
  height: 1px;
  background: var(--line);
}
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 60px 20px;
  color: var(--text-faint);
}
.empty .ic {
  color: var(--text-faint);
}
.empty p {
  font: 600 15px/1.2 var(--font);
  color: var(--text-dim);
  margin: 0;
}
.empty-sub {
  font: 13px/1.5 var(--font);
  color: var(--text-faint);
  max-width: 44ch;
  text-align: center;
  margin-top: -4px;
}
/* Full-width empty state for list pages (Components, Browse) — a contained,
   centered panel instead of a blank void below the page header. */
.empty-card {
  display: grid;
  place-items: center;
  min-height: 340px;
}

/* Compact in-card empty state (charts, triage queue) — fills the card so a
   zero-data panel keeps the same height as its populated siblings. */
.card-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 132px;
  padding: 20px;
  text-align: center;
}
.card-empty .ic {
  color: var(--text-faint);
  opacity: 0.65;
}
.card-empty-title {
  font: 600 13px/1.2 var(--font);
  color: var(--text-dim);
}
.card-empty-sub {
  font: 12px/1.45 var(--font);
  color: var(--text-faint);
  max-width: 30ch;
}
