/* ═══════════════════════════════════════════════════════════════════════
   COLLECTION BROWSER (.colb-*) — ui/collection-browser.js
   ─────────────────────────────────────────────────────────────────────
   Only what the shared library shell adds on top of the reused atoms:
   the sidebar section label + toned counts, the panel toolbar (title,
   count, rows⇄cards toggle), the dense ROW KIT (generalises the
   .compliance-row shape), sticky group headers, the chunker button and
   the default cards grid. The two-pane frame is `.kb-tree-layout`
   (css/04); the mobile drill is `.psheet-fold` / `.asset-folder-nav`
   (css/16 + css/13). Variables only — both themes ride css/01 + css/11.
   ≤599px full-width trims live at the END of this file (source order —
   a media query adds zero specificity).
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Sidebar additions ──────────────────────────────────────────────── */
.colb-tree-sect {
  font: 700 var(--text-xs) / 1 var(--body);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  padding: 14px 8px 6px;
}
/* Smart-node counts that are ACT-NOW signals (loud only when firing). */
.kb-tree-count.colb-count--warn   { background: var(--rag-warn-fill); border-color: transparent; color: #fff; }
.kb-tree-count.colb-count--breach { background: var(--rag-fail-fill); border-color: transparent; color: #fff; }

/* ─── Panel: header slot + toolbar ───────────────────────────────────── */
.colb-panel [data-colb-header] { display: flex; flex-direction: column; gap: 14px; }
.colb-panel [data-colb-header]:empty { display: none; }

.colb-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 14px 0 10px;
}
.colb-toolbar:empty { display: none; }
.colb-toolbar-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font: 700 var(--text-lg) / 1.2 var(--display, var(--body));
  color: var(--text-primary);
}
.colb-toolbar-count {
  font: 600 var(--text-xs) / 1 var(--body);
  color: var(--text-muted);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-full, 999px);
  padding: 3px 8px;
}
.colb-toolbar-q { font: 500 var(--text-sm) / 1.2 var(--body); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.colb-view-toggle {
  display: flex;
  gap: 2px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 2px;
  flex-shrink: 0;
}
.colb-view-btn {
  width: 30px;
  height: 26px;
  display: grid;
  place-items: center;
  background: transparent;
  border: none;
  border-radius: calc(var(--radius-md) - 2px);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.colb-view-btn svg { width: 15px; height: 15px; }
.colb-view-btn:hover { color: var(--text-primary); }
.colb-view-btn.is-active { background: var(--bg-surface); color: var(--text-primary); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18); }

/* ─── Row kit (desktop dense list) ───────────────────────────────────── */
.colb-list { display: flex; flex-direction: column; gap: 6px; }
.colb-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  font-family: inherit;
  color: inherit;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px 10px 14px;
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.colb-row:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 4%, var(--bg-surface)); }
/* Left accent bar — an act-now signal; transparent when nothing fires. */
.colb-row-accent { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--s, transparent); }
.colb-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.colb-row-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* A long location must not consume the whole chip line and push the classifier
   chips onto a second row (Radek's gate note). Cap it in a dense row so the
   shared .card-loc-chip truncates its own text (ellipsis) instead of eating the
   line. Rows are desktop-only, so this never touches the mobile cards. */
.colb-row-top .card-loc-chip { max-width: 160px; }
.colb-row-title {
  font: 600 var(--text-base) / 1.3 var(--body);
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.colb-row-sub { font: 500 var(--text-xs) / 1.5 var(--body); color: var(--text-secondary); }
/* Right-aligned meta/signal columns — loud ONLY when firing. */
.colb-row-cols { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }
.colb-row-col { display: flex; align-items: center; gap: 8px; font: 500 var(--text-xs) / 1.3 var(--body); color: var(--text-secondary); white-space: nowrap; }
.colb-row-col--dim { color: var(--text-muted); }
.colb-row-arrow { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-muted); }

/* Row-with-inline-actions variant (Audits Templates, 2026-07-05): the row splits
   into a clickable HIT button (whole-row open) + an action cluster. Scoped to the
   --has-actions modifier so every other adapter's single-button .colb-row is
   byte-untouched. Rows are desktop-only, so this never renders on mobile. */
.colb-row--has-actions { padding: 0; gap: 0; cursor: default; }
.colb-row-hit {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  position: relative;
  background: transparent; border: 0;
  font-family: inherit; color: inherit; text-align: left;
  padding: 10px 4px 10px 14px;
  cursor: pointer;
}
.colb-row-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; padding: 0 10px 0 4px; }
/* Compact the reused .audit-btn buttons to sit calmly in a dense row. */
.colb-row-actions .audit-btn { padding: 7px 12px; font-size: var(--text-xs); }
.colb-row-actions .audit-btn-ghost { padding: 7px; }

/* Generic calm classifier chip (modules with their own chip classes — e.g.
   .safety-type-chip — keep using those; this is for modules without one). */
.colb-chip {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  font: 600 var(--text-xs) / 1 var(--body);
}
.colb-chip-dot { width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; flex-shrink: 0; background: var(--s, var(--text-muted)); }

/* Mini read/progress bar for a row column. */
.colb-read-bar { width: 64px; height: 6px; border-radius: 999px; overflow: hidden; background: var(--bg-elevated); display: flex; }
.colb-read-bar span { display: block; min-width: 2px; }

/* ─── Groups (months / cross-node results) ───────────────────────────── */
.colb-group { display: flex; flex-direction: column; gap: 8px; }
.colb-group + .colb-group,
.colb-list + .colb-group,
.colb-cards + .colb-group { margin-top: 12px; }
.colb-group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  cursor: pointer;
  font: 700 var(--text-sm) / 1 var(--body);
  color: var(--text-secondary);
  font-family: var(--body);
}
.colb-group-head:hover { border-color: var(--accent); color: var(--text-primary); }
/* Sticky on desktop: the default panel is the scroll container; pageFlow
   deliberately makes `.main` the scroll container instead. */
.colb-panel .colb-group-head { position: sticky; top: 0; z-index: 2; }
.colb-group-chev { display: grid; place-items: center; }
.colb-group-chev svg { width: 14px; height: 14px; transition: transform 0.18s; }
.colb-group.is-collapsed .colb-group-chev svg { transform: rotate(-90deg); }
.colb-group.is-collapsed > [data-colb-glist] { display: none; }
.colb-group-count { margin-left: auto; font: 600 var(--text-xs) / 1 var(--body); color: var(--text-muted); }

/* ─── Chunker ("Show N more") ────────────────────────────────────────── */
.colb-more {
  width: 100%;
  padding: 9px;
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font: 600 var(--text-sm) / 1 var(--body);
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s;
}
.colb-more:hover { border-color: var(--accent); color: var(--accent); }

/* ─── Default cards grid (modules may pass their own cardsClass) ─────── */
.colb-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 10px; align-items: start; }

/* ─── Mobile wrapper ─────────────────────────────────────────────────── */
.colb-mwrap { display: flex; flex-direction: column; gap: 14px; }
.colb-mwrap [data-colb-header] { display: flex; flex-direction: column; gap: 14px; }
.colb-mwrap [data-colb-header]:empty { display: none; }

/* ─── Desktop: health ring + KPI strip share ONE line (≥1024px) ──────── */
/* The ring row otherwise wastes its whole right half and pushes the first
   document ~90px further down. Scoped to the browser panel — the same
   compliance-* classes on the Compliance dashboard are NOT affected. The
   alert banner keeps its own full-width line above. */
@media (min-width: 1024px) {
  .colb-panel [data-colb-header] {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: stretch;
  }
  .colb-panel [data-colb-header] > .compliance-alert { flex: 1 1 100%; }
  /* Ring card SHRINKS (0 1 auto + min-width:0) instead of holding its content
     width — a long verdict ("Action needed") can no longer starve the KPI strip
     and push it off-screen. The strip wraps to its own full-width line before it
     gets cramped (raised basis), and its cards can compress (minmax(0) in css/15). */
  .colb-panel [data-colb-header] > .compliance-score-card { flex: 0 1 auto; min-width: 0; }
  .colb-panel [data-colb-header] > .compliance-kpis { flex: 1 1 340px; min-width: 0; margin-bottom: 0; }
  /* Final degrade: if the strip is genuinely tight, labels ellipsise on one line
     rather than wrap/overflow. Desktop-panel only — mobile keeps the 2-line wrap. */
  .colb-panel [data-colb-header] > .compliance-kpis .callout-kpi-label {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
  }
}

/* ─── Focus (keyboard) ───────────────────────────────────────────────── */
/* .colb-row-hit is the focusable open-affordance in the actions row variant
   (the outer .colb-row is a non-focusable <div> there) — include it so keyboard
   focus keeps the accent ring (§4 visible focus rings). outline-offset:-2px keeps
   the ring inside the parent's overflow:hidden. */
.colb-row:focus-visible,
.colb-view-btn:focus-visible,
.colb-group-head:focus-visible,
.colb-more:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.colb-row-hit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--radius-md);
}

/* ─── Detail peek (≥1280px): list + record side by side ──────────────── */
/* At rest BOTH wrappers are display:contents, so the resting layout is
   byte-identical to the pre-peek shell for every adapter (the panel stays
   the one scroll container). While .is-peeking the panel pins the header,
   the list pane keeps its toolbar and scrolls its content, and the peek
   pane is an independent scroller — the Tasks/Call-outs split model. */
.colb-split, .colb-list-pane { display: contents; }
/* The currently-open record's row (peek highlight). */
.colb-row.is-open {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--bg-surface));
}
@media (min-width: 1280px) {
  .colb-panel.is-peeking { display: flex; flex-direction: column; overflow: hidden; }
  .colb-panel.is-peeking .colb-split { display: flex; align-items: stretch; gap: 14px; flex: 1; min-height: 0; }
  .colb-panel.is-peeking .colb-list-pane { display: flex; flex-direction: column; flex: 0 0 400px; min-width: 0; }
  .colb-panel.is-peeking .colb-list-pane .colb-toolbar { flex-shrink: 0; }
  .colb-panel.is-peeking .colb-list-pane .colb-content { flex: 1; min-height: 0; overflow-y: auto; padding-right: 2px; }
  /* 400px of list: the right-hand meta columns would crush the title —
     the record beside it is now the detail. Accent bar + chips stay. */
  .colb-panel.is-peeking .colb-row-cols { display: none; }
  .colb-panel.is-peeking .colb-peek-pane {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
  }
}
/* §6: a class above sets display on the pane, so the hidden attribute needs
   an explicit rule or it is silently ignored (author styles beat UA). Same
   (0,3,0) specificity as the flex rule + later in source, so hidden wins. */
.colb-panel .colb-peek-pane[hidden] { display: none; }

/* ─── Natural-height desktop page flow (opt-in) ──────────────────────── */
/* `clip`, unlike `hidden`, does not create a scroll container. That lets the
   sidebar and group heads stick to the app's real `.main` page scroller while
   preserving the shared frame's rounded-edge clipping. */
.kb-tree-layout.colb-layout--flow { height: auto; overflow: clip; }
.colb-layout--flow > .kb-tree-sidebar {
  position: sticky;
  top: 0;
  /* The base layout stretches children; flex-start keeps the sidebar at its
     own height so sticky has real travel through the natural-height column. */
  align-self: flex-start;
  max-height: calc(100vh - var(--banner-h, 0px) - 96px);
  border-bottom: 1px solid var(--border);
  border-bottom-right-radius: var(--radius-md);
}
.colb-layout--flow > .kb-tree-panel { overflow: visible; }

/* ─── ≤599px full-width trims (keep LAST — §4 source-order law) ──────── */
@media (max-width: 599px) {
  .colb-row { padding-left: 10px; padding-right: 10px; }
  .colb-group-head { padding-left: 10px; padding-right: 10px; }
  .colb-mwrap { gap: 12px; }
}
