/* dbr-ui — PrivacyPath session explorer, light editorial.
   Warm off-white ground, white card surfaces, purple accent.
   No tailwind. No frameworks. Hand-tuned spacing and typography. */

/* ===== reset / base ===================================================== */
*,*::before,*::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { font-size: 16px; overflow-x: clip; }
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: #f7f5f0;
  color: #1a1a1c;
  min-height: 100vh;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* very faint purple wash top-right + cooler wash bottom-left — atmosphere
     without competing with content. Saturation kept low so it reads as paper. */
  background-image:
    radial-gradient(900px 600px at 92% -10%, rgba(37,99,235,0.045), transparent 60%),
    radial-gradient(1200px 800px at -10% 110%, rgba(64,102,224,0.025), transparent 60%);
  background-attachment: fixed;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; padding: 0; }

/* ===== type scale ======================================================= */
.h-display { font-size: 2.25rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; color: #0a0a0c; }
.h1        { font-size: 1.625rem; font-weight: 700; letter-spacing: -0.015em; line-height: 1.15; color: #0a0a0c; }
.h2        { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; color: #6b6b71; }
.h3        { font-size: 0.9375rem; font-weight: 600; letter-spacing: -0.005em; color: #1a1a1c; }
.body      { font-size: 0.9375rem; font-weight: 400; line-height: 1.55; color: #2a2a2e; }
.small     { font-size: 0.8125rem; color: #6b6b71; }
.mono      { font-family: 'Fragment Mono', 'JetBrains Mono', 'Fira Code', Consolas, monospace; font-size: 0.8125rem; letter-spacing: 0; }
.muted     { color: #8a8a90; }
.accent    { color: #2563eb; }
.visually-hidden:not(:focus):not(:active) {
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

/* Global operator handoff. This is deliberately non-modal: a capture may ask
   for help while the operator is reading any console route, and focus stays
   where they left it until they choose to tab into these native buttons. */
.operator-handoff-stack {
  position: fixed; top: 112px; right: 24px; z-index: 70;
  width: min(560px, calc(100vw - 48px)); max-height: calc(100vh - 136px);
  display: flex; flex-direction: column; gap: 8px;
}
.operator-handoff-monitor-error {
  flex: 0 0 auto; margin: 0; padding: 12px 14px;
  border: 2px solid #991b1b; border-radius: 9px;
  background: #fff1f2; color: #7f1d1d;
  font-size: .875rem; font-weight: 600; line-height: 1.45;
  box-shadow: 0 12px 30px rgba(69, 10, 10, .18);
}
.operator-handoff-panel {
  min-height: 0;
  overflow-y: auto; padding: 18px;
  border: 2px solid #b45309; border-radius: 12px;
  background: #fffaf0; box-shadow: 0 18px 48px rgba(66, 38, 0, .24);
  animation: operator-handoff-enter 160ms ease-out;
}
.operator-handoff-head { display: flex; justify-content: space-between; gap: 16px; }
.operator-handoff-eyebrow, .operator-handoff-kind {
  display: block; color: #92400e; font-size: .6875rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
}
.operator-handoff-head h2 { margin: 3px 0 0; font-size: 1.25rem; line-height: 1.2; }
.operator-handoff-guidance { margin: 10px 0 14px; color: #4b3727; font-size: .875rem; line-height: 1.45; }
.operator-handoff-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.operator-handoff-card { padding: 13px; border: 1px solid #e7c995; border-radius: 9px; background: #fff; }
.operator-handoff-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.operator-handoff-card-head strong { display: block; margin-top: 3px; font-size: .9375rem; }
.operator-handoff-session { color: #5f5044; font-size: .6875rem; text-align: right; }
.operator-handoff-session span { display: block; font-weight: 700; text-transform: uppercase; }
.operator-handoff-session code { font-size: .6875rem; overflow-wrap: anywhere; }
.operator-handoff-session a { display: block; margin-top: 4px; color: #1d4ed8; font-weight: 700; }
.operator-handoff-instruction { margin: 10px 0; color: #2a211a; font-size: .875rem; line-height: 1.45; }
.operator-handoff-login { margin: -3px 0 10px; color: #493613; font-size: .8125rem; line-height: 1.45; }
.operator-handoff-login code { overflow-wrap: anywhere; }
.operator-handoff-auto { margin: -3px 0 10px; color: #3f6212; font-size: .8125rem; font-weight: 600; line-height: 1.4; }
.operator-handoff-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.operator-handoff-actions .btn { padding: 8px 12px; font-size: .8125rem; }
.operator-handoff-actions .btn[aria-disabled="true"] { opacity: .55; cursor: wait; }
.operator-handoff-panel :focus-visible { outline: 3px solid #1d4ed8; outline-offset: 2px; }
.operator-handoff-pending { color: #6b5c50; font-size: .75rem; }
.operator-handoff-error { margin: 8px 0 0; color: #991b1b; font-size: .8125rem; font-weight: 600; }
@keyframes operator-handoff-enter {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 640px) {
  .operator-handoff-stack { top: 88px; right: 12px; width: calc(100vw - 24px); max-height: calc(100vh - 100px); }
  .operator-handoff-card-head { display: block; }
  .operator-handoff-session { margin-top: 8px; text-align: left; }
}

/* ===== attorney-client privilege banner ================================= */
.privilege-banner {
  position: sticky; top: 0; z-index: 60;
  height: 30px; display: flex; align-items: center; justify-content: center;
  background: #2a2a30; color: #f3f1ea;
  font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
}

/* ===== header =========================================================== */
.site-header {
  position: sticky; top: 30px; z-index: 50;
  border-bottom: 1px solid #e8e5dc;
  background: rgba(255,255,255,0.82);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
}
.site-header .inner {
  max-width: 1280px; margin: 0 auto;
  padding: 18px 32px;
  display: flex; align-items: center; justify-content: space-between; gap: 32px;
}
.brand { display: flex; align-items: center; gap: 14px; }
.brand-name {
  font-size: 1.0625rem;
  display: flex; align-items: baseline; gap: 12px;
  color: #0a0a0c;
}
.brand-name .wordmark { font-weight: 700; letter-spacing: -0.03em; }
.brand-name .sep { font-weight: 400; color: #c8c5bd; font-size: 0.875rem; }
.brand-name .product { font-weight: 500; color: #6b6b71; letter-spacing: 0; font-size: 0.8125rem; }

/* align-items: center, not the flex default of `stretch`. Stretch made every
   item as tall as the whole nav row, which is invisible on links that have no
   background and doubles the height of the one that does — so the SELECTED item
   was the only one that looked wrong (Israel, 2026-08-22). Aligning centre
   sizes each item to its own text plus padding, so the highlight matches the
   link it highlights. */
.nav { display: flex; align-items: center; gap: 4px; }
.nav a, .nav button {
  font-size: 0.8125rem; font-weight: 500; color: #5a5a60;
  padding: 8px 14px; border-radius: 6px;
  transition: color 120ms, background 120ms;
}
.nav a:hover, .nav button:hover { color: #0a0a0c; background: rgba(15,15,20,0.04); }
.nav a.nav-active { color: #0a0a0c; background: rgba(37,99,235,0.08); }
/* No ::before dot on the active item. It added 4px of dot plus an 8px margin to
   whichever item was selected, so the nav's total width changed as you moved
   between tabs and the selected item wrapped onto its own line (Israel,
   2026-08-22). The active state is already carried by colour and background,
   which cost no width — an indicator that reflows the thing it indicates is
   worse than no indicator. */
/* Evaluations is the primary working surface — weight it up so the leftmost
   item reads as the main entry point even when another tab is active. */
.nav a.nav-primary { font-weight: 600; color: #0a0a0c; }

/* Plan-management dropdown hanging off the Evaluations nav item. Hover-reveal;
   the parent link still navigates to the evaluations list on click. The menu
   abuts the parent's bottom edge (top:100%) so there's no dead gap to cross. */
.nav-dd { position: relative; display: inline-flex; }
.nav-caret { font-size: 0.625rem; margin-left: 5px; opacity: 0.55; vertical-align: 1px; }
.nav-dd-menu {
  position: absolute; top: 100%; left: 0; min-width: 184px;
  background: #fff; border: 1px solid #e2e2e2; border-radius: 8px;
  box-shadow: 0 8px 28px rgba(10,10,20,0.12); padding: 5px;
  display: none; flex-direction: column; gap: 1px; z-index: 60;
}
.nav-dd:hover .nav-dd-menu, .nav-dd:focus-within .nav-dd-menu { display: flex; }
.nav-dd-menu a { font-weight: 500; white-space: nowrap; color: #3a3a42; padding: 7px 12px; }
.nav-dd-menu a:hover { color: #0a0a0c; background: rgba(37,99,235,0.08); }

/* ===== layout =========================================================== */
.main { max-width: 1280px; margin: 0 auto; padding: 40px 32px 96px; }

/* ===== page header (section title + meta row) =========================== */
.page-head { display: flex; align-items: end; justify-content: space-between; margin-bottom: 28px; gap: 32px; }
.page-head .label { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.page-head .label::before {
  content: ""; width: 6px; height: 6px; background: #2563eb; border-radius: 50%;
  box-shadow: 0 0 12px rgba(37,99,235,0.45);
}
.page-head .meta { display: flex; gap: 16px; align-items: center; color: #6b6b71; font-size: 0.8125rem; }
.page-head .meta a:hover { color: #2563eb; }
.page-head .meta button { color: #6b6b71; }
.page-head .meta button:hover { color: #0a0a0c; }
/* the gray-button rule above is for ghost buttons; colored buttons keep their
   own text colour (else +Add organization renders gray-on-blue, unreadable). */
.page-head .meta button.btn-primary { color: #ffffff; }
.page-head .meta button.btn-ghost.danger { color: #ffffff; }

/* ===== cards / surfaces ================================================= */
.surface {
  background: #ffffff;
  border: 1px solid #ece9e0;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,15,20,0.025), 0 4px 14px rgba(15,15,20,0.03);
}
.surface-pad { padding: 24px; }

/* ===== data list (replaces tables) ====================================== */
.data-list { display: flex; flex-direction: column; }
.data-list .row {
  display: grid;
  grid-template-columns: minmax(0,1.5fr) 104px 58px 96px 104px 76px 50px 112px;
  gap: 24px;
  padding: 18px 24px;
  border-top: 1px solid #f0ede4;
  align-items: center;
  cursor: pointer;
  transition: background 100ms;
  animation: rowin 360ms cubic-bezier(.2,.7,.3,1) both;
}
.data-list .row:first-child { border-top: none; }
.data-list .row:hover { background: #fbf9f3; }
.data-list .row:hover .row-arrow { color: #2563eb; transform: translateX(2px); }
.data-list .row .row-arrow { color: #c8c5bd; transition: color 120ms, transform 120ms; text-align: right; }
.data-list .row .primary-title { font-weight: 600; font-size: 0.9375rem; line-height: 1.2; color: #0a0a0c; }
.data-list .row .primary-sub { color: #8a8a90; font-size: 0.75rem; margin-top: 4px; font-family: 'Fragment Mono', monospace; }
.sid-copy {
  margin-left: 8px;
  padding: 1px 6px;
  border: 1px solid #dedbd2;
  border-radius: 4px;
  background: #f7f5f0;
  color: #4a4a52;
  font: inherit;
  cursor: copy;
}
.sid-copy:hover { border-color: #b9b4a7; color: #1f2937; }
.data-list .row .cell-small { font-size: 0.8125rem; color: #5a5a60; }
.data-list .row .cell-num { font-family: 'Fragment Mono', monospace; font-size: 0.8125rem; color: #2a2a2e; }
.header-row {
  display: grid;
  grid-template-columns: minmax(0,1.5fr) 104px 58px 96px 104px 76px 50px 112px;
  gap: 24px;
  padding: 12px 24px;
  background: #faf8f2;
  border-bottom: 1px solid #ece9e0;
  font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em;
  color: #6b6b71;
  cursor: default;
}
.header-row .text-right { text-align: right; }
/* Reap sits ABOVE Delete in the one actions cell, both the same size. The
   sizing rule used to name .session-delete alone, so Reap rendered at default
   button size beside a smaller Delete; and the row laid them out side by side,
   which cramped the cell whenever an in-flight session showed both. */
.session-row-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
/* Reap stacks ABOVE Delete; the arrow is the row affordance, not an action, so
   it stays beside the pair rather than joining the stack. */
.session-row-buttons {
  display: flex; flex-direction: column; align-items: stretch; gap: 4px;
}
.session-row-actions .session-delete,
.session-row-actions .session-reap {
  padding: 4px 8px; font-size: 0.75rem; text-align: center;
}
.session-detail-actions { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 24px; }
/* click-to-sort column headers (enableColumnSort in util.js) */
.header-row .sortable { cursor: pointer; user-select: none; }
.header-row .sortable:hover { color: #2563eb; }
.header-row .sortable[data-arrow]::after { content: " " attr(data-arrow); font-size: 0.78em; color: #2563eb; }

/* Stagger first ~10 rows on initial paint. (After that, no per-row delay.) */
.data-list .row:nth-child(1)  { animation-delay: 20ms;  }
.data-list .row:nth-child(2)  { animation-delay: 50ms;  }
.data-list .row:nth-child(3)  { animation-delay: 80ms;  }
.data-list .row:nth-child(4)  { animation-delay: 110ms; }
.data-list .row:nth-child(5)  { animation-delay: 140ms; }
.data-list .row:nth-child(6)  { animation-delay: 170ms; }
.data-list .row:nth-child(7)  { animation-delay: 200ms; }
.data-list .row:nth-child(8)  { animation-delay: 230ms; }
.data-list .row:nth-child(9)  { animation-delay: 260ms; }
.data-list .row:nth-child(10) { animation-delay: 290ms; }

@keyframes rowin {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ===== pills ============================================================ */
/* Soft tinted background + saturated darker text for readability on light. */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: lowercase;
}
.pill::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: 0.9;
}
.pill.status-recording { background: #fdf0d9; color: #a86a08; }
.pill.status-running   { background: #e7edfa; color: #2548b0; }
.pill.status-starting  { background: #dbeafe; color: #2563eb; }
.pill.status-done      { background: #dff4e6; color: #0f7a37; }
.pill.status-finished  { background: #dff4e6; color: #0f7a37; }
.pill.status-evidence-empty { background: #fdf0d9; color: #8a5a08; }
.pill.status-incomplete { background: #fff0c7; color: #8a5300; }
.pill.status-not-attempted { background: #eeece5; color: #5a5a60; }
.pill.status-verified  { background: #dff4e6; color: #0f7a37; }
.pill.status-verifying { background: #e7edfa; color: #2548b0; }

/* Grouped historical import: one durable session shell around repeatable child
   evidence rows. Kept in the shared operator stylesheet so screenshots and the
   production console use the exact same component foundation. */
.import-scope-note {
  padding: 12px 14px;
  border: 1px solid #d9c58f;
  background: #fffaf0;
  color: #5f4811;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.45;
  margin-bottom: 16px;
}
.import-fieldset {
  border: 1px solid var(--border, #d9dde5);
  border-radius: 10px;
  padding: 14px;
  margin: 0 0 14px;
  min-width: 0;
}
.import-fieldset > legend {
  padding: 0 7px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink, #1e2530);
}
.import-grid,
.import-inline-fields,
.import-row-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
}
.import-summary {
  margin: 12px 0 0;
  padding: 9px 11px;
  border-radius: 7px;
  background: #f2f5fa;
  color: #27364d;
  font-weight: 700;
}
.import-rows { display: grid; gap: 10px; }
.import-row {
  border: 1px solid var(--border, #d9dde5);
  border-radius: 9px;
  padding: 12px;
  background: #fff;
}
.import-row-head,
.import-row-actions,
.import-actions,
.import-resume {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.import-row-grid { margin-top: 10px; }
.import-row details { margin-top: 10px; }
.import-row summary { cursor: pointer; color: #34445c; font-size: 13px; }
.import-lineage {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 14px;
  margin: 10px 0 0;
}
.import-lineage div { min-width: 0; }
.import-lineage dt { font-size: 11px; font-weight: 700; color: #667085; }
.import-lineage dd { margin: 2px 0 0; font-size: 12px; overflow-wrap: anywhere; }
.import-row-actions { justify-content: flex-start; margin-top: 10px; }
.import-actions { justify-content: flex-start; margin-top: 14px; }
.import-resume { justify-content: flex-start; margin-top: 14px; }
.import-resume .fld { min-width: min(100%, 420px); margin: 0; }
.import-error { min-height: 1.4em; margin: 6px 0 0; color: #9d1c1c; }
@media (max-width: 720px) {
  .import-grid,
  .import-inline-fields,
  .import-row-grid,
  .import-lineage { grid-template-columns: 1fr; }
}

/* Capture-quality badge on the evaluations list: captured/total sessions. */
.cap-quality { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 0.8125rem;
               padding: 1px 7px; border-radius: 6px; background: #eeece5; color: #5a5a60; }
.cap-quality.cap-ok      { background: #dff4e6; color: #0f7a37; }
.cap-quality.cap-partial { background: #fdf0d9; color: #a86a08; }
.cap-quality.cap-bad     { background: #fbe7e7; color: #b91c1c; }
.pill.status-failed    { background: #fbe7e7; color: #b91c1c; }
.pill.status-verify-failed { background: #fbe7e7; color: #b91c1c; }
.pill.status-verify-unavailable { background: #fff0c7; color: #8a5300; }
.pill.status-unknown   { background: #eeece5; color: #5a5a60; }
.pill.status-stopped   { background: #e4e9f2; color: #3d4f6b; }
/* D15 wire-rescue: the leg's required action is independently proven on the
   wire despite an unclean agent exit — a known, non-fatal caveat, not a
   failure. Amber like cov-partial/cap-partial (known-cause, non-blocking),
   never red. Operator/session view only — the client report never emits
   this classification, so this class has no client-facing counterpart. */
.pill.status-wire-rescued { background: #fdf0d9; color: #a86a08; }
/* Named failure-category pills — deliberately NOT red: a login wall or a
   site-side Cloudflare block is a known cause, not a broken capture. Blue =
   needs a one-time login; slate = external anti-bot. */
.pill.cov-auth { background: #e7edfa; color: #2548b0; }
.pill.cov-bot  { background: #eceef2; color: #475569; }
/* A leg is held for a human right now (finish a form / clear a Turnstile on the
   live browser on the operator desktop). Bright amber + pulse so a stalled-for-a-human capture is
   impossible to miss on the sessions list. */
.pill.human-needed { background: #f59e0b; color: #4a2600; font-weight: 600; animation: humanNeededPulse 1.4s ease-in-out infinite; }
@keyframes humanNeededPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

/* Auth-wall badges — shown next to status when a run completed but never got
   past authentication. 2FA (amber, password worked but OTP blocked) vs
   identity (red, credentials never authenticated). */
.pill.auth-block { margin-left: 6px; }
.pill.auth-2fa      { background: #fdf0d9; color: #a86a08; }
.pill.auth-identity { background: #fbe7e7; color: #b91c1c; }
/* HIGH findings badge in the Detections column. */
.pill.det-high { background: #fbe7e7; color: #b91c1c; margin-left: 6px; }
/* DOM-capture validity gate badges. */
.pill.cov-blank   { background: #fbe7e7; color: #b91c1c; margin-left: 6px; }
.pill.cov-partial { background: #fdf0d9; color: #a86a08; margin-left: 6px; }
.cov-banner { padding: 12px 16px; border-radius: 8px; font-size: 0.875rem; margin: 0 0 20px; }
.cov-banner .mono { font-family: var(--font-mono, monospace); font-size: 0.8125rem; }
.cov-banner-blank   { background: #fbe7e7; color: #8a1414; border: 1px solid #f3c5c5; }
.cov-banner-partial { background: #fdf4e3; color: #8a5a08; border: 1px solid #f0dcb0; }
/* Google/SSO login steering (Google blocks the automated capture browser). */
.google-sso-flag { color: #8a5a08; font-weight: 600; margin-right: 4px; }

/* ===== session re-run grouping ========================================== */
/* Grouping is opt-in. Its visible row is an aggregate with no row-level action;
   every concrete run and its own controls live behind the expander. */
.session-group .rerun-others { display: none; }
.session-group.expanded .rerun-others { display: block; }
.session-group .rerun-others .row { background: #fcfbf7; }
.session-group-summary { cursor: default !important; background: #faf8f2; }
.session-group-summary:hover { background: #faf8f2 !important; }
.group-statuses { display: flex; flex-wrap: wrap; gap: 4px; }
.group-operational { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.group-operational .pill { margin-left: 0; }
.group-status { display: inline-flex; align-items: center; gap: 3px; color: #6b6b71; font-size: 0.6875rem; }
.group-status .pill { padding-left: 7px; padding-right: 7px; }
.rerun-bar { padding: 4px 24px; border-top: 1px dashed #ece9e0; background: #faf8f2; }
.rerun-toggle { display: inline-flex; align-items: center; gap: 6px;
                font-size: 0.75rem; color: #6b6b71; padding: 4px 0; }
.rerun-toggle:hover { color: #2563eb; }
.rerun-toggle .rerun-count::before { content: "▸"; display: inline-block; transition: transform 120ms; }
.session-group.expanded .rerun-toggle .rerun-count::before { transform: rotate(90deg); }

/* ===== filter bar additions ============================================= */
.filterbar .flt-search input[type=search] { min-width: 220px; }
.filterbar .flt-check { display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
                        font-size: 0.8125rem; color: #5a5a60; }
.filterbar .flt-check input { cursor: pointer; }

/* ===== buttons ========================================================== */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px;
       padding: 11px 22px; border-radius: 8px; font-weight: 600; font-size: 0.875rem;
       /* Fit to text — never stretch to the container width in flex/grid columns
          (forms use flex-direction:column, whose default align-items:stretch
          otherwise blows buttons out to full page width). */
       align-self: flex-start; justify-self: start; width: fit-content; max-width: 100%;
       transition: background 120ms, color 120ms, transform 80ms, box-shadow 120ms; }
.btn:active { transform: translateY(1px); }
/* `.btn`'s display above outranks the UA stylesheet's [hidden]{display:none},
   so EVERY button in this app carrying `hidden` was rendering anyway — and the
   edit controls are all driven by it (`e.save.hidden = !editing`). The effect
   was that the recommendations List and Matrix showed Edit, Save AND Cancel on
   every row at once, permanently, so pressing Edit changed nothing a reader
   could see except that a field unlocked. Counsel reported not being able to
   tell what was editable; three buttons that never change state is a fair
   reason. Specificity alone fixes it — .btn[hidden] (0,2,0) beats .btn (0,1,0)
   — so no !important, unlike the narrower .cv-host-rest fix further down which
   fights an inline display. */
.btn[hidden] { display: none; }
.btn-primary { background: #2563eb; color: #ffffff; box-shadow: 0 1px 2px rgba(37,99,235,0.18), 0 4px 12px rgba(37,99,235,0.15); }
.btn-primary:hover { background: #1d4ed8; }
.btn-primary:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.btn-secondary { background: #ffffff; color: #1a1a1c; border: 1px solid #d8d4ca; }
.btn-secondary:hover { border-color: #2563eb; color: #2563eb; }
.btn-ghost { color: #5a5a60; padding: 6px 10px; }
.btn-ghost:hover { color: #0a0a0c; }
.sp-import-status { min-height: 20px; margin: -16px 0 16px; }
/* armed destructive action (e.g. session-plan delete second-click) */
.btn-ghost.danger { color: #fff; background: #c0392b; border-radius: 6px; }
.btn-ghost.danger:hover { color: #fff; background: #a93226; }

/* ===== forms ============================================================ */
.field { display: flex; flex-direction: column; gap: 8px; }
.field label, .field .field-label {
  font-size: 0.75rem; font-weight: 500; color: #6b6b71;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.field input, .field select, .field textarea {
  background: #ffffff; color: #0a0a0c;
  border: 1px solid #d8d4ca; border-radius: 8px;
  padding: 11px 14px;
  font: inherit; font-size: 0.875rem;
  transition: border-color 120ms, box-shadow 120ms;
}
.field input::placeholder, .field textarea::placeholder { color: #b3b0a8; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37,99,235,0.14);
}

/* Native MinusOneDB client-user provisioning — one form, one client scope. */
.client-account-card { max-width: 720px; }
.client-account-form { display: flex; flex-direction: column; gap: 20px; }
.client-account-form > p,
.client-account-form .field > p,
.client-scope > p { margin: 0; }
.client-account-form .field input { max-width: 460px; }
.client-scope { border: 0; margin: 0; padding: 0; min-width: 0; }
.client-scope > legend {
  margin-bottom: 8px; padding: 0; color: #6b6b71;
  font-size: 0.75rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.client-scope-options { display: grid; gap: 8px; margin-top: 10px; }
.client-scope-option {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border: 1px solid #e2ded4; border-radius: 8px;
  cursor: pointer;
}
.client-scope-option:hover { border-color: #b7c8f8; background: #fafcff; }
.client-scope-option input { margin-top: 3px; }
.client-scope-option strong,
.client-scope-projects { display: block; }
.client-scope-projects { margin-top: 3px; color: #6b6b71; font-size: 0.8125rem; }
#client-account-status { min-height: 20px; margin: 0; color: #166534; }
#client-account-alert {
  margin: 0; padding: 10px 12px; color: #991b1b;
  background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px;
}
#client-account-alert[hidden] { display: none; }

/* ===== session detail =================================================== */
.session-hero {
  position: relative; padding: 32px;
  background: #ffffff;
  border: 1px solid #ece9e0; border-radius: 14px;
  margin-bottom: 24px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15,15,20,0.025), 0 6px 22px rgba(15,15,20,0.04);
}
.session-hero::before {
  content: ""; position: absolute; top: -60%; right: -10%;
  width: 480px; height: 480px;
  background: radial-gradient(circle, rgba(37,99,235,0.08) 0%, transparent 60%);
  filter: blur(40px); pointer-events: none;
}
.session-hero .row1 { display: flex; align-items: start; justify-content: space-between; gap: 24px; margin-bottom: 8px; position: relative; }
.session-hero .row1 h2 { margin: 0; }
.session-title-line {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.session-title-line .sid-copy { margin-left: 0; }
.session-hero .ids {
  font-family: 'Fragment Mono', monospace; font-size: 0.75rem; color: #8a8a90;
  display: flex; gap: 16px; flex-wrap: wrap; margin-top: 4px;
}
.session-hero .ids a:hover { color: #2563eb; }

.kv-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px 32px;
  padding-top: 24px; margin-top: 24px; border-top: 1px solid #f0ede4;
  position: relative;
}
.kv-grid .kv .k { font-size: 0.6875rem; color: #8a8a90; text-transform: uppercase;
                   letter-spacing: 0.12em; margin-bottom: 4px; }
.kv-grid .kv .v { font-size: 0.875rem; color: #0a0a0c; font-weight: 500; }
.kv-grid .kv .v.mono { font-family: 'Fragment Mono', monospace; font-weight: 400; }

/* ===== checklist (testSpecs sidebar) ==================================== */
.checklist { padding: 24px; background: #ffffff;
             border: 1px solid #ece9e0; border-radius: 14px;
             min-height: 100%;
             box-shadow: 0 1px 2px rgba(15,15,20,0.025), 0 6px 22px rgba(15,15,20,0.04); }
.checklist h3 { margin: 0 0 16px; }
.checklist ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.checklist li { display: flex; gap: 12px; align-items: start; }
.checklist .mark {
  flex-shrink: 0; width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid #dbd7cd; display: grid; place-items: center; margin-top: 2px;
  font-size: 11px; font-weight: 700; background: #ffffff;
}
.checklist .mark.done { background: #dff4e6; border-color: #16a34a; color: #0f7a37; }
.checklist .mark.failed { background: #fbe7e7; border-color: #dc2626; color: #a11414; }
.checklist .mark.verifyfail { background: #fdf2e0; border-color: #d8973a; color: #8a5a08; }
.checklist .mark.notattempted { background: #eeece5; border-color: #bdb8ad; color: #5a5a60; }
.checklist .ts-num { color: #9a9aa0; font-weight: 600; font-variant-numeric: tabular-nums; }
.checklist .verifyfail-badge { color: #8a5a08; background: rgba(216,151,58,0.14);
  padding: 1px 6px; border-radius: 4px; }
.checklist .notattempted-badge { color: #5a5a60; background: rgba(90,90,96,0.12);
  padding: 1px 6px; border-radius: 4px; }
.checklist .cookieflush-badge { color: #0f7a37; background: rgba(22,163,74,0.12);
  padding: 1px 6px; border-radius: 4px; }
.checklist .name { font-size: 0.875rem; font-weight: 500; }
.checklist .name.done { color: #0a0a0c; }
.checklist .name.todo { color: #8a8a90; }
.checklist .flags { font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
                    color: #8a8a90; margin-left: 8px; }
.checklist .instr { font-size: 0.75rem; color: #6b6b71; margin-top: 2px; line-height: 1.5; }

/* ===== tabs ============================================================= */
.tabs { display: flex; gap: 0; border-bottom: 1px solid #ece9e0; margin-bottom: 24px; }
.tabs button {
  padding: 12px 18px; font-size: 0.8125rem; font-weight: 500; color: #6b6b71;
  border-bottom: 2px solid transparent;
  transition: color 120ms, border-color 120ms;
}
.tabs button:hover:not(:disabled) { color: #0a0a0c; }
.tabs button.active { color: #0a0a0c; border-bottom-color: #2563eb; }
.tabs button:disabled { color: #c8c5bd; cursor: not-allowed; }

/* ===== per-test multi-lens view ========================================= */
/* "lenses ›" affordance on each testPlans-index row — opens the test view. */
.ts-open {
  margin-left: auto; margin-right: 10px; white-space: nowrap; flex: 0 0 auto;
  font-weight: 600; opacity: 0; transition: opacity 120ms;
}
.ts-item summary:hover .ts-open, .ts-open:focus { opacity: 1; }
.test-view-head { margin-bottom: 18px; }
.test-view-title { display: flex; flex-direction: column; }
.test-view-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* The per-test sub-tab bar is a lighter, tighter secondary of the main tabs. */
.tabs.subtabs { margin-bottom: 18px; }
.tabs.subtabs button { padding: 9px 14px; font-size: 0.78125rem; }
/* Verify badge as a standalone pill (the .vb-* colours are otherwise scoped to
   the replay feature badge). */
.vbadge {
  display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 999px;
  font-size: 0.6875rem; font-weight: 600; line-height: 1.6;
}
.vbadge.status-verifying    { background: #eef3fd; color: #2548b0; }
.vbadge.status-verified     { background: #dff4e6; color: #0f7a37; }
.vbadge.status-verify-failed { background: #fbe7e7; color: #b91c1c; }
.vbadge.status-verify-unavailable { background: #fff0c7; color: #8a5300; }

/* Persistent testPlan rail used by web session tabs. Tabs change the lens;
   the selected plan stays in ?test= so reviewers can compare replay/flows/etc. */
.testplan-lens {
  display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
  gap: 24px; align-items: start;
}
.testplan-rail {
  position: sticky; top: 16px; max-height: calc(100vh - 180px); overflow: auto;
  border: 1px solid #ece9e0; border-radius: 8px; background: #ffffff;
}
.rail-title {
  padding: 12px 14px; border-bottom: 1px solid #ece9e0;
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: #6b6b71;
}
.rail-list { display: flex; flex-direction: column; }
.tp-nav-item {
  width: 100%; display: grid; grid-template-columns: 28px 20px minmax(0, 1fr);
  gap: 8px; align-items: start; padding: 10px 12px; text-align: left;
  border-bottom: 1px solid #f0ede4; color: #3a3a40; background: transparent;
  transition: background 120ms, color 120ms;
}
.tp-nav-item:last-child { border-bottom: 0; }
.tp-nav-item:hover { background: #faf9f6; color: #0a0a0c; }
.tp-nav-item.active { background: #eef3fd; color: #0a0a0c; box-shadow: inset 3px 0 0 #2563eb; }
.tp-nav-num {
  font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
  color: #8a8a90; padding-top: 2px; text-align: right;
}
.tp-nav-item .mark {
  width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #d8d4ca; border-radius: 999px; font-size: 0.6875rem; font-weight: 700;
}
.tp-nav-item .mark.done { background: #dff4e6; border-color: #16a34a; color: #0f7a37; }
.tp-nav-item .mark.failed { background: #fbe7e7; border-color: #dc2626; color: #a11414; }
.tp-nav-item .mark.verifyfail { background: #fdf2e0; border-color: #d8973a; color: #8a5a08; }
.tp-nav-item .mark.notattempted { background: #eeece5; border-color: #bdb8ad; color: #5a5a60; }
.tp-nav-item .mark.todo { background: #ffffff; color: transparent; }
.tp-nav-copy { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tp-nav-name { font-size: 0.8125rem; font-weight: 600; line-height: 1.35; }
.tp-nav-error {
  color: #b91c1c; font-size: 0.6875rem; line-height: 1.35;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.testplan-lens-main { min-width: 0; }
.testplan-lens-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; padding-bottom: 14px; margin-bottom: 18px; border-bottom: 1px solid #ece9e0;
}
.testplan-lens-head .h2 { margin: 0 0 6px; }
.testplan-lens-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.testplan-lens-actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 960px) {
  .testplan-lens { grid-template-columns: 1fr; }
  .testplan-rail { position: static; max-height: 280px; }
  .testplan-lens-head { flex-direction: column; }
  .testplan-lens-actions { justify-content: flex-start; }
}

/* ===== timeline ========================================================= */
.timeline { background: #ffffff; border: 1px solid #ece9e0; border-radius: 14px;
            box-shadow: 0 1px 2px rgba(15,15,20,0.025), 0 6px 22px rgba(15,15,20,0.04); }
.timeline .feature { padding: 24px; border-top: 1px solid #f0ede4; }
.timeline .feature:first-child { border-top: none; }
.timeline .feature-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.timeline .feature-name { font-weight: 600; font-size: 0.9375rem;
                          display: flex; align-items: center; gap: 10px; color: #0a0a0c; }
.timeline .feature-name .idx {
  font-family: 'Fragment Mono', monospace; color: #2563eb; font-size: 0.75rem; font-weight: 600;
}
.timeline .feature-meta { color: #8a8a90; font-size: 0.75rem; margin-bottom: 12px; }
.timeline details { font-size: 0.8125rem; }
.timeline summary { cursor: pointer; color: #6b6b71; font-size: 0.75rem;
                    text-transform: uppercase; letter-spacing: 0.08em; }
.timeline summary:hover { color: #0a0a0c; }
.timeline .event-table { width: 100%; margin-top: 12px; border-collapse: collapse; }
.timeline .event-table th { text-align: left; padding: 8px 12px; font-size: 0.6875rem;
                            color: #8a8a90; font-weight: 600; text-transform: uppercase;
                            letter-spacing: 0.08em; border-bottom: 1px solid #ece9e0; background: #faf8f2; }
.timeline .event-table td { padding: 8px 12px; font-family: 'Fragment Mono', monospace;
                            font-size: 0.75rem; color: #2a2a2e;
                            border-bottom: 1px solid #f5f2ea; }
.timeline .event-table td.truncate { max-width: 320px; overflow: hidden;
                                     text-overflow: ellipsis; white-space: nowrap; color: #6b6b71; }

/* ===== empty / loading states =========================================== */
.empty { padding: 64px 24px; text-align: center; color: #8a8a90; }
.empty .marker { font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
                  letter-spacing: 0.2em; text-transform: uppercase; color: #b3b0a8;
                  margin-bottom: 12px; }
.empty .msg { font-size: 0.9375rem; color: #5a5a60; margin-bottom: 16px; }
.empty .hint { font-size: 0.8125rem; color: #8a8a90; }
.empty a.accent { color: #2563eb; }
.empty a.accent:hover { color: #1d4ed8; }

.loading { padding: 48px; text-align: center; color: #8a8a90; font-size: 0.875rem; }

/* ===== code / raw ======================================================= */
pre.code {
  background: #f4f1ea;
  border: 1px solid #ece9e0;
  border-radius: 10px;
  padding: 20px 24px;
  font-family: 'Fragment Mono', 'JetBrains Mono', monospace;
  font-size: 0.8125rem; line-height: 1.6;
  color: #1a1a1c;
  overflow: auto; max-height: 640px;
}
pre.code.tail {
  background: #0e0e10; color: #5fe88f;
  border-color: #0e0e10;
  font-size: 0.75rem;
}

/* ===== rrweb player wrap ================================================ */
.replay-frame {
  background: #ffffff; border: 1px solid #ece9e0; border-radius: 14px;
  padding: 24px; position: relative;
  box-shadow: 0 1px 2px rgba(15,15,20,0.025), 0 6px 22px rgba(15,15,20,0.04);
}
.replay-frame::before {
  content: "DOM REPLAY"; position: absolute; top: -8px; left: 24px;
  background: #f7f5f0; color: #8a8a90; font-family: 'Fragment Mono', monospace;
  font-size: 0.6875rem; letter-spacing: 0.18em; padding: 0 8px;
}
.replay-frame.screen-replay::before { content: "SCREEN REPLAY"; }
.replay-frame .player { background: #ffffff; border: 1px solid #ece9e0; border-radius: 6px; overflow: hidden; }
.replay-frame .caption { color: #8a8a90; font-size: 0.75rem; margin-top: 12px;
                         font-family: 'Fragment Mono', monospace; }

/* ===== run trigger card ================================================= */
.trigger-card { max-width: 720px; }
.trigger-card .plan-detail { margin-top: 12px; font-size: 0.8125rem; color: #5a5a60; }
.trigger-card .plan-detail ul { list-style: none; padding: 0; margin: 12px 0 0;
                                 display: flex; flex-direction: column; gap: 14px; }
.trigger-card .plan-detail li {
  padding-left: 16px; border-left: 2px solid #e0ddd3;
}
.trigger-card .plan-detail .pname { font-weight: 600; color: #0a0a0c; }
.trigger-card .plan-detail .pflags { color: #8a8a90; font-family: 'Fragment Mono', monospace;
                                       font-size: 0.6875rem; margin-left: 8px; }
.trigger-card .plan-detail .purl { font-size: 0.75rem; color: #2548b0; word-break: break-all; }
.trigger-card .plan-detail .pinstr { font-size: 0.8125rem; color: #5a5a60; margin-top: 4px; }
.android-device-readout {
  padding: 11px 14px;
  border: 1px solid #d8d4ca;
  border-radius: 8px;
  font-size: 0.875rem;
  line-height: 1.45;
}
.android-device-readout.loading {
  background: #f6f4ef;
  color: #5a5a60;
}
.android-device-readout.assigned {
  background: #edf7f0;
  border-color: #b8d9c2;
  color: #185c2d;
}
.android-device-readout.unassigned {
  background: #fdf4e3;
  border-color: #e6cc97;
  color: #704600;
}
.android-device-readout.misconfigured {
  background: #fbe7e7;
  border-color: #edb9b9;
  color: #8a1414;
}
.eval-run-card .android-device-readout { margin-top: 6px; }

.active-run { margin-top: 32px; max-width: 720px; }
.active-run .head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.active-run .head .id { font-family: 'Fragment Mono', monospace; }
.active-run .head .meta { font-size: 0.75rem; color: #8a8a90; margin-top: 4px;
                          font-family: 'Fragment Mono', monospace; }
.active-run .session-link { font-size: 0.8125rem; margin-bottom: 12px; color: #5a5a60; }
.active-run .session-link a { color: #2563eb; text-decoration: underline; text-underline-offset: 3px; }

/* ===== utilities ======================================================== */
.flex { display: flex; }
.gap-2 { gap: 8px; } .gap-3 { gap: 12px; } .gap-4 { gap: 16px; }
.mt-2 { margin-top: 8px; } .mt-4 { margin-top: 16px; } .mt-6 { margin-top: 24px; }
.mb-4 { margin-bottom: 16px; } .mb-6 { margin-bottom: 24px; }
.hidden { display: none !important; }
.grid-2to1 { display: grid; grid-template-columns: 2fr 1fr; gap: 24px; }
.text-right { text-align: right; }

/* replay feature picker — each feature is one continuous rrweb recording */
.replay-picker { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.replay-picker button {
  font: inherit; font-size: 0.8125rem; padding: 6px 12px; border-radius: 8px;
  border: 1px solid #e3e0e8; background: #fff; color: #3a3a40; cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px; text-align: left;
}
.replay-picker button:hover:not([disabled]) { border-color: #2563eb; color: #2563eb; }
.replay-picker button.active { background: #2563eb; border-color: #2563eb; color: #fff; }
.replay-picker button.active .rp-sub { color: rgba(255,255,255,0.7); }
.replay-picker button[disabled] { opacity: 0.55; cursor: not-allowed; }
.replay-picker .rp-name { font-weight: 500; }
.replay-picker .rp-sub { opacity: 0.7; font-size: 0.6875rem; font-family: 'Fragment Mono', monospace; }
.replay-picker .rp-mark { font-weight: 700; font-size: 0.75rem; }
.replay-picker .rp-mark.ok { color: #16a34a; }
.replay-picker .rp-mark.failed { color: #dc2626; }
.replay-picker .rp-mark.warn { color: #d97706; }
.replay-picker .rp-mark.notattempted { color: #6b6b71; }
.replay-picker button.active .rp-mark { color: #fff; }

/* Per-feature health strip above the player */
.replay-health {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px;
  margin-bottom: 12px; padding: 8px 12px; border-radius: 8px;
  background: #faf9f6; border: 1px solid #ece9e0; font-size: 0.8125rem;
}
.replay-health .rp-title { font-weight: 600; color: #2a2a30; }
.replay-health .rp-stats { color: #5a5a60; font-family: 'Fragment Mono', monospace; font-size: 0.75rem; }
.replay-health .rp-pages { color: #8a8a90; font-size: 0.75rem; }
.replay-health .rp-stall { color: #d97706; font-weight: 600; }
/* "what the agent was told to do" reference, shown next to a feature's replay */
.replay-instructions { margin-bottom: 12px; padding: 12px 14px; border-left: 3px solid #2563eb; background: #f6f8ff; border-radius: 0 8px 8px 0; font-size: 0.8125rem; line-height: 1.5; white-space: pre-wrap; }
.replay-instructions .ri-h { font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #2563eb; margin-bottom: 4px; }
.rp-reasons { list-style: none; padding: 0; margin: 16px auto 0; max-width: 520px;
  text-align: left; font-size: 0.8125rem; color: #5a5a60; }
.rp-reasons li { padding: 6px 0; border-top: 1px solid #ece9e0; }
.rp-reasons li b { color: #2a2a30; }

/* ---- GPC comparison view ---- */
.compare-pickers { display: flex; align-items: flex-end; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
.compare-pickers .field { flex: 1; min-width: 240px; }
.compare-pickers label { display: block; font-size: 0.6875rem; text-transform: uppercase;
  letter-spacing: 0.06em; color: #8a8a90; margin-bottom: 6px; }
.compare-pickers select { width: 100%; font: inherit; font-size: 0.8125rem; padding: 8px 10px;
  border: 1px solid #e3e0e8; border-radius: 8px; background: #fff; color: #2a2a30; }
.compare-pickers .vs { padding-bottom: 9px; color: #8a8a90; font-weight: 600; }

.compare-head { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
.compare-head .cmp-side { padding: 12px 16px; border: 1px solid #ece9e0; border-radius: 10px; background: #faf9f6; }
.compare-head .cmp-tag { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: #2563eb; font-weight: 700; margin-bottom: 4px; }
.compare-head .cmp-id { font-family: 'Fragment Mono', monospace; font-size: 0.875rem; color: #2a2a30; text-decoration: none; }
.compare-head .cmp-id:hover { color: #2563eb; text-decoration: underline; }
.compare-head .cmp-sub { font-size: 0.75rem; color: #8a8a90; margin-top: 2px; }

.compare-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.compare-table th { text-align: left; font-size: 0.6875rem; text-transform: uppercase;
  letter-spacing: 0.05em; color: #8a8a90; font-weight: 600; padding: 8px 12px; border-bottom: 1px solid #ece9e0; }
.compare-table td { padding: 10px 12px; border-bottom: 1px solid #f3f1ea; vertical-align: middle; }
.compare-table .cmp-name { font-weight: 500; color: #2a2a30; }
.compare-table .cmp-stats { font-family: 'Fragment Mono', monospace; font-size: 0.75rem; color: #5a5a60; }
.compare-table .cmp-mark { font-weight: 700; }
.compare-table .cmp-mark.ok { color: #16a34a; }
.compare-table .cmp-mark.failed { color: #dc2626; }
.compare-table .cmp-mark.warn { color: #d97706; }
.compare-table .cmp-none { color: #c4c4ca; }
.compare-table .cmp-total td { font-weight: 600; color: #2a2a30; border-top: 2px solid #ece9e0; border-bottom: none; }
.cmp-delta { font-family: 'Fragment Mono', monospace; font-size: 0.75rem; font-weight: 600; }
.cmp-delta.down { color: #16a34a; }   /* fewer events under GPC = good signal */
.cmp-delta.up { color: #dc2626; }
.cmp-delta.zero { color: #8a8a90; }
/* ran on one side only — a COVERAGE GAP, not an event change. Neutral amber so it
   never reads as a green "GPC reduced tracking" win. */
.cmp-delta.gap { color: #b26a00; font-weight: 500; font-family: inherit; }
.cmp-scope-warn { margin: 0 0 12px; padding: 8px 12px; border-radius: 8px;
  background: #fff7ed; border: 1px solid #fed7aa; color: #9a3412; font-size: 0.8125rem; }

.compare-note { margin-top: 20px; padding: 14px 16px; border-radius: 10px;
  background: #eff6ff; border: 1px solid #bfdbfe; font-size: 0.8125rem; color: #4a4a52; line-height: 1.5; }
.compare-note b { color: #2563eb; }
.compare-note .mono { font-family: 'Fragment Mono', monospace; font-size: 0.75rem; }

/* ---- Network flows + Detections tabs ---- */
.flows-summary, .det-summary { font-size: 0.8125rem; color: #5a5a60; margin-bottom: 12px; }
.det-summary b { color: #2a2a30; }
.flows-table td, .event-table td { font-size: 0.8125rem; }
.flows-table td.truncate, .event-table td.truncate { max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.det-h { font-size: 0.9375rem; font-weight: 600; color: #2a2a30; margin: 22px 0 10px; display: flex; align-items: center; gap: 10px; }
.det-count { font-family: 'Fragment Mono', monospace; font-size: 0.75rem; padding: 1px 8px; border-radius: 999px;
  background: #eceae3; color: #5a5a60; }
.det-count.bad { background: #fde2e2; color: #c0271f; }
.det-none { font-size: 0.8125rem; color: #8a8a90; padding: 8px 0; }
.det-hosts { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.det-hosts li { font-family: 'Fragment Mono', monospace; font-size: 0.75rem; padding: 4px 10px;
  background: #faf9f6; border: 1px solid #ece9e0; border-radius: 999px; color: #4a4a52; }
.det-foot { margin-top: 22px; font-size: 0.75rem; color: #9a9aa0; font-style: italic; }
.det-show-all { margin: 12px 0 4px; padding: 8px 16px; font-size: 0.8125rem; font-weight: 600; cursor: pointer;
  background: #faf9f6; border: 1px solid #ddd9cc; border-radius: 8px; color: #4a4a52; }
.det-show-all:hover { background: #f2efe6; border-color: #cfc9b8; }
.xform { font-family: 'Fragment Mono', monospace; font-size: 0.6875rem; padding: 1px 7px; border-radius: 4px;
  background: #eff6ff; color: #2563eb; }

/* Rows the CLIENT report withholds, shown to the operator rather than hidden from
   them: an operator who cannot see a suppressed finding cannot review or override
   the suppression. Muted, not alarming — these are non-findings, not problems. */
.withheld-badge { font-family: 'Fragment Mono', monospace; font-size: 0.625rem; padding: 1px 6px;
  border-radius: 4px; background: #f2f1ee; color: #8a8a90; border: 1px solid #e5e2da;
  margin-left: 6px; vertical-align: middle; letter-spacing: 0.02em; cursor: help; }
tr.det-withheld > td { opacity: 0.62; }
tr.det-withheld:hover > td { opacity: 1; }

/* rule-generated findings (dbr-infra/findings/) — top section on Detections tab */
.det-h-sub { font-size: 0.6875rem; color: #8a8a90; font-weight: 400; font-style: italic; }
.findings-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 22px; }
.finding { border: 1px solid #ece9e0; border-left-width: 3px; border-radius: 6px;
  padding: 12px 14px; background: #faf9f6; }
.finding.sev-high { border-left-color: #c0271f; background: #fff7f6; }
.finding.sev-medium { border-left-color: #d97706; background: #fffaf0; }
.finding.sev-low { border-left-color: #2563eb; }
.finding-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 0.8125rem; margin-bottom: 8px; }
.sev-badge { font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
  padding: 1px 8px; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.04em; }
.sev-badge.sev-high { background: #fde2e2; color: #c0271f; }
.sev-badge.sev-medium { background: #fef3c7; color: #92400e; }
.sev-badge.sev-low { background: #dbeafe; color: #1e40af; }
.finding-cat { font-weight: 600; color: #2a2a30; }
.finding-host { font-size: 0.75rem; color: #5a5a60; }
.finding-rule { font-size: 0.6875rem; color: #8a8a90; margin-left: auto; }
.finding-rec { font-size: 0.8125rem; color: #2a2a30; line-height: 1.5; margin-bottom: 8px; }
.finding-foot { font-size: 0.6875rem; color: #8a8a90; }

/* v3 detection taxonomy — numeric severity (3=high/red, 2=notice/amber, 1=info/grey) */
.sev-badge.sev-3 { background: #fde2e2; color: #c0271f; }
.sev-badge.sev-2 { background: #fef3c7; color: #92400e; }
.sev-badge.sev-1 { background: #ececf0; color: #5a5a60; }
.sev-badge.sev-unknown { background: #ececf0; color: #8a8a90; }

/* piiFields AND-group chips on a compound */
.pii-chip { font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
  padding: 2px 8px; border-radius: 4px; background: rgba(127,127,127,0.12); color: #2a2a30; }

/* compound detection cards — the headline finding, rendered above atomic */
.compound-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 22px; }
.compound-card { border: 1px solid #ece9e0; border-left-width: 3px; border-radius: 6px;
  padding: 12px 14px; background: #faf9f6; }
.compound-card.sev-3 { border-left-color: #c0271f; background: #fff7f6; }
.compound-card.sev-2 { border-left-color: #d97706; background: #fffaf0; }
.compound-card.sev-1 { border-left-color: #c4c4cc; }
.compound-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 0.8125rem; margin-bottom: 8px; }
.compound-rule { font-weight: 600; color: #2a2a30; }
.compound-scope { margin-left: auto; font-size: 0.6875rem; color: #8a8a90;
  font-family: 'Fragment Mono', monospace; }
.compound-fields { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.compound-foot { font-size: 0.75rem; color: #5a5a60; }
.compound-org { font-weight: 600; }
.compound-drill { margin-top: 8px; }
.compound-drill > summary { cursor: pointer; font-size: 0.6875rem; color: #5a5a60; }
.compound-atoms { list-style: none; padding: 6px 0 0; margin: 0;
  display: flex; flex-direction: column; gap: 4px; }
.compound-atoms li { display: flex; align-items: center; gap: 10px; font-size: 0.75rem; }
.atom-id { color: #2a2a30; }
.atom-host { font-size: 0.6875rem; color: #8a8a90; }

/* org → subdomain roll-up — recipient grouped by the host detections arrived on */
.org-sub-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 22px; }
.org-sub { border: 1px solid #ece9e0; border-radius: 6px; background: #faf9f6; }
.org-sub[open] { background: #fff; }
.org-sub-head { cursor: pointer; display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; padding: 10px 14px; font-size: 0.8125rem; }
.org-sub-name { font-weight: 600; color: #2a2a30; }
.org-sub-body { padding: 4px 14px 12px; display: flex; flex-direction: column; gap: 8px; }
.sub-row { border-top: 1px solid #f0ede4; padding-top: 8px; }
.sub-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sub-host { font-size: 0.75rem; color: #2a2a30; }
.cname-badge { font-size: 0.6875rem; padding: 2px 8px; border-radius: 4px;
  background: rgba(217,119,6,0.12); color: #b45309; font-family: 'Fragment Mono', monospace; }
.sub-idts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.sub-flows { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.sub-flow { cursor: pointer; font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
  padding: 2px 8px; border-radius: 4px; border: 1px solid #e0ddd4; background: #fff; color: #5a5a60; }
.sub-flow:hover { border-color: #c4c4cc; color: #2a2a30; }
.sub-flow-detail { margin: 8px 0 4px; }
/* session-view "fix owner" shortcut — inline owner-override form on a
   subdomain row (shares owner-override-form.js with the organizations editor) */
.fix-owner-btn { cursor: pointer; font-family: 'Fragment Mono', monospace; font-size: 0.6875rem;
  padding: 2px 8px; border-radius: 4px; border: 1px solid #e0ddd4; background: #fff; color: #2563eb;
  margin-left: auto; }
.fix-owner-btn:hover { border-color: #2563eb; }
.fix-owner-panel { margin-top: 10px; padding: 12px 14px; border: 1px solid #e0ddd4;
  border-radius: 6px; background: #fff; display: flex; flex-direction: column; gap: 12px;
  max-width: 460px; }
.fix-owner-actions { display: flex; gap: 10px; align-items: center; }

/* host diff in the compare view */
.cmp-hostdiff { margin-top: 24px; }
.cmp-hostcols { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; margin-top: 10px; }
.cmp-hostcol h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: #8a8a90; margin: 0 0 8px; }
.cmp-hostcol ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 4px; }
.cmp-hostcol li { font-family: 'Fragment Mono', monospace; font-size: 0.72rem; color: #4a4a52; }
.cmp-hostcol.only-a li { color: #c0271f; }   /* contacted only without GPC — suppressed when GPC on = good */
.cmp-hostcol.only-b li { color: #c0271f; }

/* ---- slim session hero (checklist moved to its own tab) ---- */
.session-hero.slim { display: block; }
.session-hero.slim .row1 { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; }
.hero-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; flex-shrink: 0; }
.hero-kv { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; font-size: 0.75rem; color: #8a8a90; font-family: 'Fragment Mono', monospace; }
.hero-error { margin-top: 14px; color: #c0271f; font-size: 0.8125rem; }
/* Tier-2 verification progress line under the hero headline. */
.verify-line { margin-top: 8px; font-size: 0.8125rem; color: #2548b0; font-family: 'Fragment Mono', monospace; }
.verify-line.verifying { animation: vb-pulse 1.2s ease-in-out infinite; }
/* Auth-wall banner on the detail hero — coloured callout matching the list
   badge (amber 2FA, red identity) instead of plain red text. */
.hero-error.auth-2fa, .hero-error.auth-identity {
  display: inline-block; margin-top: 14px; padding: 7px 12px; border-radius: 7px;
  font-weight: 500; border: 1px solid;
}
.hero-error.auth-2fa { background: #fdf0d9; color: #8a5606; border-color: #f0d9a8; }
.hero-error.auth-identity { background: #fbe7e7; color: #a01818; border-color: #f0c2c2; }
.verification-note, .tp-nav-note {
  color: #5a5a60;
  font-size: 0.8125rem;
}
.tp-nav-note {
  display: block;
  margin-top: 2px;
}
.tab-checklist { max-width: 760px; }

/* ---- replay per-feature picker: outcome badges + active highlight ---- */
.rp-feat-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 11px; border: 1px solid #e2ded3; border-radius: 7px;
  background: #fff; font-size: 0.8125rem; color: #3a3a40; cursor: pointer;
  transition: border-color 120ms, background 120ms, box-shadow 120ms;
}
.rp-feat-btn:hover { border-color: #c8c5bd; background: #fbf9f3; }
.rp-feat-active { border-color: #2563eb; background: #eef3fd;
                  box-shadow: 0 0 0 1px rgba(37,99,235,0.25); }
.rp-feat-badge {
  font-size: 0.625rem; font-weight: 600; letter-spacing: 0.04em;
  padding: 1px 6px; border-radius: 999px; text-transform: lowercase;
}
.rp-feat-badge.status-finished { background: #dff4e6; color: #0f7a37; }
.rp-feat-badge.fb-2fa      { background: #fdf0d9; color: #a86a08; }
.rp-feat-badge.fb-identity { background: #fbe7e7; color: #b91c1c; }
.rp-feat-badge.status-failed { background: #fbe7e7; color: #b91c1c; }
.rp-feat-badge.status-unknown { background: #eeece5; color: #5a5a60; }
.rp-feat-badge.status-not-attempted { background: #eeece5; color: #5a5a60; }
/* Tier-2 screen-verification badges (per feature). */
.rp-feat-badge.status-verifying { background: #eef3fd; color: #2548b0; }
.rp-feat-badge.status-verifying::before { content: ""; }
.rp-feat-badge.status-verified { background: #dff4e6; color: #0f7a37; }
.rp-feat-badge.status-verify-failed { background: #fbe7e7; color: #b91c1c; }
.rp-feat-badge.status-verify-unavailable { background: #fff0c7; color: #8a5300; }
@keyframes vb-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }
.rp-feat-badge.status-verifying { animation: vb-pulse 1.2s ease-in-out infinite; }
/* Black stage behind the player so a clip swap fades through black (not the
   previous clip's last frame) while the new first frame decodes. */
.screen-replay-stage { background: #000; border-radius: 8px; }
#screen-video { transition: opacity 140ms ease; }
#screen-video.rp-loading { opacity: 0; }

/* ---- per-feature grouping (flows / detections) + timeline timestamps ---- */
.feat-group { border: 1px solid #ece9e0; border-radius: 8px; margin-bottom: 10px; background: #fff; overflow: hidden; }
.feat-group > summary { cursor: pointer; padding: 12px 16px; display: flex; align-items: center; gap: 10px; list-style: none; font-size: 0.875rem; }
.feat-group > summary::-webkit-details-marker { display: none; }
.feat-group > summary::marker { content: ''; }
.feat-group > summary:hover { background: #faf9f6; }
.feat-group[open] > summary { border-bottom: 1px solid #f0ede4; }
.fg-name { font-weight: 600; color: #2a2a30; }
.fg-meta { margin-left: auto; font-size: 0.72rem; color: #8a8a90; font-family: 'Fragment Mono', monospace; }
.feat-group .event-table { margin: 0; }
.feature-head .feature-when { margin-left: auto; margin-right: 12px; font-size: 0.72rem; color: #8a8a90; font-family: 'Fragment Mono', monospace; }
.det-feat { margin-bottom: 18px; }
.det-feat-name { font-weight: 600; font-size: 0.8125rem; color: #2a2a30; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }
/* attorney review: expandable per-detection evidence + recommendation editor */
.det-row { cursor: pointer; }
.det-row:hover { background: #faf8f2; }
.det-caret { display: inline-block; width: 12px; color: #9a9690; font-size: 0.7rem; }
.det-edited td { background: #fffaf0; }
.det-edited-badge { font-size: 0.6875rem; font-weight: 600; color: #b45309; background: #fef3c7; border-radius: 999px; padding: 1px 7px; margin-left: 6px; }
.det-detail > td { background: #f7f9fc; padding: 16px 18px; border-bottom: 1px solid #ece9e0; }
.dd { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.2fr); gap: 28px; }
.dd-h { font-size: 0.6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #6b6b71; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; }
.dd-ev-row { display: grid; grid-template-columns: 130px 1fr; gap: 10px; padding: 3px 0; font-size: 0.8125rem; }
.dd-ev-k { color: #6b6b71; }
.dd-ev-v { color: #1a1a1c; word-break: break-all; }
.dd-ev-v.mono { font-family: ui-monospace, monospace; font-size: 0.78rem; }
.dd-rec-text { width: 100%; border: 1px solid #d8d4ca; border-radius: 8px; padding: 8px 10px; font-family: inherit; font-size: 0.8125rem; line-height: 1.5; resize: vertical; }
.dd-actions { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.dd-confirm { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 0.8125rem; }
.dd-muted { color: #6b6b71; }
.dd-cur { font-weight: 600; color: #2a2a30; }
.dd-status.saving { color: #6b6b71; } .dd-status.ok { color: #15803d; } .dd-status.err { color: #b91c1c; }
@media (max-width: 880px) { .dd { grid-template-columns: 1fr; } }
.dd-evidence { align-self: start; }
.det-host-requests-list { display: grid; gap: 4px; margin-top: 6px; }

/* client → project breadcrumb on the session detail */
.crumb { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; color: #2563eb;
  text-transform: none; margin-bottom: 8px; }

/* DBR logo next to PrivacyPath in the header */
.brand-logo { height: 34px; width: auto; display: block; }

/* clickable testSpec rows — full spec opens inline */
.ts-item { list-style: none; }
.ts-item details summary { list-style: none; cursor: pointer; display: flex; align-items: flex-start; gap: 10px; padding: 4px 0; }
.ts-item details summary::-webkit-details-marker { display: none; }
.ts-item details summary:hover .name { color: #2563eb; }
.ts-summary-text { flex: 1; min-width: 0; }
.ts-toggle { color: #c8c5bd; font-size: 0.875rem; transition: transform 120ms; user-select: none; }
.ts-item details[open] > summary .ts-toggle { transform: rotate(180deg); color: #2563eb; }
.ts-detail { margin: 10px 0 6px 36px; padding: 12px 14px; background: #faf9f6; border: 1px solid #ece9e0; border-radius: 8px; }
.ts-kvs { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 6px 18px; margin-bottom: 10px; }
.ts-kv { display: flex; flex-direction: column; gap: 2px; font-size: 0.75rem; }
.ts-kv .ts-k { color: #8a8a90; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.6875rem; }
.ts-kv .ts-v { color: #2a2a30; }
.ts-block { margin-top: 10px; }
.ts-block .ts-k { color: #8a8a90; text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.6875rem; margin-bottom: 4px; }
.ts-pre { background: #ffffff; border: 1px solid #ece9e0; border-radius: 6px; padding: 8px 10px;
  font-family: 'Fragment Mono', monospace; font-size: 0.75rem; color: #2a2a30; line-height: 1.45;
  white-space: pre-wrap; word-break: break-word; margin: 0; max-height: 320px; overflow: auto; }

/* shared filter toolbar (sessions / compare / trigger) */
.filterbar { display: flex; flex-wrap: wrap; align-items: end; gap: 14px; margin-bottom: 18px;
  padding: 12px 14px; background: #ffffff; border: 1px solid #ece9e0; border-radius: 10px; }
.filterbar label { display: flex; flex-direction: column; gap: 4px; font-size: 0.6875rem;
  text-transform: uppercase; letter-spacing: 0.05em; color: #8a8a90; }
.filterbar select, .filterbar input[type=date] { font: inherit; font-size: 0.8125rem; padding: 6px 8px;
  border: 1px solid #e3e0e8; border-radius: 6px; background: #fff; color: #2a2a30; min-width: 160px; }
.filterbar select:focus, .filterbar input:focus { outline: none; border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37,99,235,0.14); }
.filterbar .flt-clear { margin-left: auto; font-size: 0.75rem; color: #2563eb; }
.filterbar .flt-clear:hover { color: #1d4ed8; }

/* run tab — structured panels instead of just a tail blob */
.run-card .run-section { margin-top: 16px; }
.run-card .run-section .h2 { margin-bottom: 6px; }
.run-card .run-summary { font-size: 0.9375rem; color: #2a2a30; line-height: 1.5;
  padding: 12px 14px; background: #faf9f6; border: 1px solid #ece9e0; border-radius: 8px;
  white-space: pre-wrap; }
.run-card .run-summary.muted { color: #8a8a90; font-style: italic; }
.run-card .run-errors .ts-pre { background: #fdf0f0; border-color: #fde2e2; color: #c0271f; }
.run-card .run-raw { margin-top: 16px; }
.run-card .run-raw > summary { cursor: pointer; font-size: 0.8125rem; color: #5a5a60;
  padding: 6px 0; list-style: none; user-select: none; }
.run-card .run-raw > summary::-webkit-details-marker { display: none; }
.run-card .run-raw > summary::before { content: '▸ '; color: #c8c5bd; }
.run-card .run-raw[open] > summary::before { content: '▾ '; color: #2563eb; }
.run-card .run-raw > summary:hover { color: #2563eb; }

/* Run error banner (claude auth / rate-limit / box adb missing / etc.) */
.run-error {
  background: #fef2f2;
  border: 1px solid #fca5a5;
  color: #991b1b;
  padding: 10px 14px;
  border-radius: 6px;
  font-size: 0.8125rem;
  font-family: 'Fragment Mono', monospace;
  margin: 12px 0;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Agent action "selector hints" rail under the DOM replay (first-M3) */
.agent-actions { margin-top: 12px; border: 1px solid var(--border, #2a2f3a); border-radius: 8px; padding: 10px 12px; }
.agent-actions .ah-title { font-weight: 600; margin-bottom: 6px; }
.agent-actions .ah-list { list-style: none; margin: 0; padding: 0; max-height: 280px; overflow-y: auto; }
.agent-actions .ah-item { display: flex; align-items: baseline; gap: 8px; padding: 4px 6px; border-radius: 6px; cursor: pointer; font-size: 13px; }
.agent-actions .ah-item:hover { background: rgba(127,127,127,0.12); }
.agent-actions .ah-item.ah-active { background: rgba(90,150,255,0.22); }
/* the required action the verifier found never happened — not seekable, flagged red */
.agent-actions .ah-item.ah-missed { cursor: default; color: #b91c1c; }
.agent-actions .ah-item.ah-missed:hover { background: none; }
.agent-actions .ah-item.ah-missed .ah-step { color: #b91c1c; opacity: 1; }
.agent-actions .ah-step { min-width: 18px; text-align: right; opacity: 0.6; font-variant-numeric: tabular-nums; }
.agent-actions .ah-glyph { width: 14px; text-align: center; }
.agent-actions .ah-target { font-family: ui-monospace, Menlo, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 320px; }
.agent-actions .ah-reason { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Decoded consent (first-M4) — flows tab */
.consent-rollup { margin: 6px 0 12px; padding: 8px 12px; border-radius: 8px; background: rgba(127,127,127,0.08); font-size: 13px; }
.consent-rollup .optout-warn { color: #e0a030; font-weight: 600; }
.consent-states { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }
.consent-chip { font-size: 11px; font-family: ui-monospace, Menlo, monospace; padding: 2px 6px; border-radius: 4px; background: rgba(127,127,127,0.15); }
.cell-consent { white-space: nowrap; }
.consent-badge { font-size: 11px; padding: 1px 6px; border-radius: 4px; background: rgba(90,150,255,0.18); cursor: default; }
.consent-badge.consent-optout { background: rgba(224,160,48,0.22); color: #e0a030; }
tr.flow-optout > td { background: rgba(224,160,48,0.07); }
.consent-report-link { margin-left: 10px; font-size: 12px; }
.consent-report-table th, .consent-report-table td { border: 1px solid var(--border,#2a2f3a); padding: 4px 8px; font-size: 12px; }

/* 1st/3rd-party (v3 M2) — flows tab */
.party-rollup { margin: 6px 0 10px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.party-badge { font-size: 11px; padding: 1px 6px; border-radius: 4px; }
.party-first { background: rgba(90,200,120,0.20); color: #4caf6a; }
.party-third { background: rgba(224,140,90,0.20); color: #d9803a; }
.cell-party { white-space: nowrap; }
.third-domains { margin-left: 4px; }
.third-domains > summary { cursor: pointer; font-size: 12px; }
.third-domains[open] { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* Detector-error / unprocessed pills on the session list (surface silent fails) */
.pill.det-error { background: rgba(220,70,70,0.18); color: #e05555; }
.pill.det-pending { background: rgba(150,150,150,0.18); color: #999; }
.detector-error-banner { margin: 10px 0; padding: 10px 14px; border-radius: 8px; background: rgba(220,70,70,0.12); border: 1px solid rgba(220,70,70,0.35); color: #e05555; font-size: 13px; }

/* Login verification banner (#195): did the run authenticate as planned? */
.login-check-banner { margin: 10px 0; padding: 10px 14px; border-radius: 8px; font-size: 13px; border: 1px solid; }
.login-check-banner.bad { background: rgba(220,70,70,0.12); border-color: rgba(220,70,70,0.35); color: #e05555; }
.login-check-banner.ok { background: rgba(22,163,74,0.10); border-color: rgba(22,163,74,0.30); color: #0f7a37; }
.login-check-banner.unknown { background: rgba(120,120,130,0.10); border-color: rgba(120,120,130,0.30); color: #6b7280; }

/* Coverage readout (#112): what was NOT captured and why. */
.cov-readout { margin: 10px 0; padding: 10px 14px; border-radius: 8px; font-size: 13px; border: 1px solid; }
.cov-readout > summary { cursor: pointer; list-style: none; }
.cov-readout > summary::-webkit-details-marker { display: none; }
.cov-readout-clean { background: rgba(22,163,74,0.08); border-color: rgba(22,163,74,0.25); color: #0f7a37; }
.cov-readout-gaps { background: rgba(220,140,40,0.08); border-color: rgba(220,140,40,0.32); color: #8a5a08; }
.cov-body { margin-top: 12px; display: flex; flex-direction: column; gap: 12px; }
.cov-section { padding: 8px 10px; border-radius: 6px; background: rgba(0,0,0,0.03); }
.cov-sec-head { font-size: 13px; color: #3a3a3a; }
.cov-count { display: inline-block; min-width: 20px; padding: 0 6px; border-radius: 10px; background: rgba(220,90,40,0.18); color: #8a3a08; font-weight: 700; text-align: center; }
.cov-sec-neverRan .cov-count, .cov-sec-notAttempted .cov-count, .cov-sec-authBlocked .cov-count, .cov-sec-failed .cov-count, .cov-sec-noPage .cov-count { background: rgba(220,70,70,0.16); color: #a11414; }
.cov-sec-drifted .cov-count { background: rgba(220,140,40,0.18); color: #8a5a08; }

/* Sessions list "Captured" cell (successfully captured / planned testPlans) */
.cap-full { color: #0f7a37; font-weight: 600; }
.cap-partial { color: #8a5a08; font-weight: 600; }
.cap-none { color: #a11414; font-weight: 600; }
.cell-faint { color: #b8b8c0; }
.cap-running { color: #5a6ad0; font-weight: 600; }
.cov-blurb { color: #777; font-weight: 400; }
.cov-list { margin: 6px 0 0; padding-left: 18px; color: #444; }
.cov-list li { margin: 2px 0; }
.cov-tp-name { font-weight: 600; }
.cov-actions { display: inline-flex; gap: 10px; margin-left: 10px; white-space: nowrap; }
.cov-actions-block { margin: 8px 0 0; }
.cov-primary-action { background: rgba(90,106,208,0.10); border: 1px solid rgba(90,106,208,0.22); }
.cov-why { color: #8a5a08; font-family: var(--font-mono, monospace); font-size: 12px; }

/* AI privacy review tab (first-M4 LLM triage) */
.review-head { margin-bottom: 14px; }
.review-summary { font-size: 14px; line-height: 1.5; }
.review-finding { margin: 8px 0; padding: 10px 14px; border-radius: 8px; border-left: 3px solid #888; background: rgba(127,127,127,0.06); }
.review-finding.rev-high { border-left-color: #e05555; }
.review-finding.rev-notice { border-left-color: #e0a030; }
.review-finding.rev-info { border-left-color: #5a96ff; }
.review-finding .rf-title { font-weight: 600; }
.review-finding .rf-sev { font-size: 11px; padding: 1px 6px; border-radius: 4px; background: rgba(127,127,127,0.18); margin-right: 4px; }
.rev-high .rf-sev { background: rgba(224,85,85,0.2); color: #e05555; }
.rev-notice .rf-sev { background: rgba(224,160,48,0.2); color: #e0a030; }
.review-finding .rf-tag { font-size: 10px; padding: 1px 6px; border-radius: 4px; background: rgba(90,150,255,0.16); color: #5a96ff; margin-left: 6px; }
.review-finding .rf-tag.rf-dim { background: rgba(127,127,127,0.16); color: #999; }
.review-finding .rf-concern { margin-top: 5px; font-size: 13px; line-height: 1.5; }
.review-finding .rf-meta { margin-top: 5px; }

/* Organizations + domains editor (v3 M2) ----------------------------------- */
/* The list rows reuse .data-list/.header-row but override the 9-col session
   grid for the org/domain shapes. .party-badge/.party-first|third are reused
   from the flows tab (above). */
.org-grid    { grid-template-columns: minmax(0,2fr) 96px 84px 84px 24px !important; }
.domain-grid { grid-template-columns: minmax(0,1.35fr) minmax(130px,.72fr) minmax(0,1fr) minmax(0,1fr) 96px !important; }
.domain-search-grid { grid-template-columns: minmax(0,1.5fr) minmax(130px,.75fr) minmax(0,1fr) 24px !important; }
.project-grid { grid-template-columns: minmax(0,2fr) 110px 24px !important; }
.data-list .row.domain-grid,
.data-list .row.domain-search-grid,
.data-list .row.project-grid { cursor: pointer; }

/* Evaluations list filter bar (Organization › Project). */
.eval-filters { display: flex; align-items: end; gap: 16px; margin: 0 0 16px; flex-wrap: wrap; }
.eval-filters .field { margin: 0; min-width: 220px; }
.eval-filters #f-clear { align-self: center; padding-bottom: 8px; }

/* Organizations list search. */
.org-search { margin: 0 0 16px; }
.org-search input { width: 100%; max-width: 520px; padding: 9px 14px; font-size: 0.875rem;
  border: 1px solid #e2e2e2; border-radius: 8px; background: #fff; color: #0a0a0c; }
.org-search input:focus { outline: none; border-color: #2563eb; }
.data-list .row.row-hidden { display: none !important; }
.data-list .row.org-grid .party-badge,
.data-list .row.domain-grid .party-badge { justify-self: start; }
.domain-search-panel { margin-bottom: 14px; }
.domain-search-form { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; }
.domain-search-form .field { min-width: min(100%, 340px); margin: 0; }
.domain-search-form input { width: 100%; }
.domain-search-results { margin-top: 12px; }
@media (max-width: 760px) {
  .domain-search-grid { grid-template-columns: minmax(0,1fr) 24px !important; }
  .domain-search-grid > :nth-child(2),
  .domain-search-grid > :nth-child(3) { grid-column: 1 / -1; }
  .domain-search-grid > :nth-child(4) { grid-column: 2; grid-row: 1; }
}
.domain-class-badge {
  display: inline-flex; align-items: center; max-width: 100%;
  padding: 2px 7px; border-radius: 5px;
  background: #eef4ff; color: #1d4ed8; border: 1px solid #c7d8ff;
  font-size: 0.75rem; font-weight: 650; line-height: 1.25;
}
.domain-unclassified {
  display: inline-flex; align-items: center; max-width: 100%;
  padding: 2px 7px; border-radius: 5px;
  background: #f7f7f8; color: #595961; border: 1px solid #dedee3;
  font-size: 0.75rem; font-weight: 650; line-height: 1.25;
}

/* The org editor + the domains block stack as two surfaces on the detail page. */
.org-editor { margin-bottom: 20px; }
.org-editor .org-id { font-size: 0.8125rem; color: #5a5a60; }
.org-editor .org-form .field input,
.org-editor .org-form .field select { max-width: 460px; }

/* Alias chips — same visual language as .consent-chip but interactive. */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; min-height: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.8125rem; padding: 4px 8px 4px 10px; border-radius: 6px;
  background: #f1eee6; color: #2a2a2e; border: 1px solid #e4e0d6;
}
.chip .chip-x {
  cursor: pointer; color: #8a8a90; font-size: 1rem; line-height: 1;
  background: none; border: none; padding: 0;
}
.chip .chip-x:hover { color: #b91c1c; }
.chip-add { display: flex; gap: 8px; margin-top: 10px; align-items: stretch; }
.chip-add input { max-width: 340px; }

/* Domains block: header + add/edit form sit inside one surface. */
.domains-block { overflow: hidden; }
.domains-head { padding: 20px 24px 14px; display: flex; align-items: baseline; gap: 12px; }
.domains-block .empty-inline { padding: 20px 24px; }
.domain-add { border-top: 1px solid #f0ede4; background: #faf8f2; }
.domain-form { display: flex; flex-direction: column; gap: 16px; }
.domain-form .field input, .domain-form .field select { max-width: 460px; }
.domain-detail-body {
  padding: 0 24px 24px;
  display: grid;
  gap: 18px;
}
.domain-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0,1fr));
  gap: 16px;
  padding-top: 4px;
}
.domain-class-form {
  display: grid;
  gap: 14px;
  max-width: 520px;
}
.domain-class-form .field { margin: 0; }
.domain-class-form select { max-width: 460px; }
@media (max-width: 900px) {
  .domain-facts { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 620px) {
  .domain-facts { grid-template-columns: minmax(0,1fr); }
}

/* Evaluations (Feature A) -------------------------------------------------- */
/* List + per-session grids reuse .data-list/.header-row with their own cols. */
.eval-grid      { grid-template-columns: minmax(0,2fr) 110px 90px 110px 24px !important; }
.eval-sess-grid { grid-template-columns: minmax(0,2fr) 110px 90px 90px 110px 160px !important; }
.data-list .row.eval-sess-grid .pill.det-high { margin-left: 0; }
.eval-run-card { max-width: 720px; margin-bottom: 24px; }
.eval-run-card > .eval-run-summary { cursor: pointer; font-weight: 650; color: #2a2a30; }
.eval-run-card > .eval-run-summary:focus-visible { outline: 2px solid #2563eb; outline-offset: 4px; border-radius: 3px; }
.eval-run-card[open] > .eval-run-summary { margin-bottom: 20px; }
.eval-run-card .eval-run-content { display: flex; flex-direction: column; gap: 20px; }
/* Client picker + plan search above the plan select, narrowing the 30+ plans. */
.eval-run-card .run-pickers { display: flex; gap: 10px; margin-bottom: 10px; }
.eval-run-card .run-pickers #eval-client { flex: 0 0 220px; }
.eval-run-card .run-pickers #eval-plan-search { flex: 1; }
.eval-run-card .plan-detail { margin-top: 12px; font-size: 0.8125rem; color: #5a5a60; }
.eval-run-card .plan-detail ul { list-style: none; padding: 0; margin: 12px 0 0; display: flex; flex-direction: column; gap: 6px; }
.eval-run-card .plan-detail .pname { font-weight: 600; color: #0a0a0c; }
.eval-run-card .plan-preflight { margin-top: 12px; }
.eval-plan-gap {
  margin: 0 0 18px; padding: 13px 15px; border: 1px solid #e4c783;
  border-left-width: 4px; border-radius: 8px; background: #fff8e7; color: #604814;
}
.eval-plan-gap h2 { margin: 0 0 4px; font-size: 0.875rem; color: #513b0c; }
.eval-plan-gap p { margin: 0; font-size: 0.8125rem; line-height: 1.5; }
.eval-plan-gap-badge { margin-left: 6px; border-color: #e4c783; background: #fff8e7; color: #604814; }
.eval-plan-link-state,
.eval-plan-link-editor {
  margin: 0 0 18px; padding: 14px 16px; border: 1px solid #dedbd3;
  border-radius: 8px; background: #faf9f5;
}
.eval-plan-link-state h2,
.eval-plan-link-editor h2 { margin: 0 0 5px; font-size: 0.875rem; }
.eval-plan-link-editor p { margin: 0 0 12px; color: #5a5a60; font-size: 0.8125rem; }
.eval-plan-link-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.eval-plan-link-controls label { font-size: 0.8125rem; font-weight: 600; }
.eval-plan-link-controls select { min-width: 280px; }
#evaluation-plan-link-status { margin-top: 8px; }
.eval-recovery {
  margin: 0 0 18px; padding: 18px; border: 1px solid #e6c16e;
  border-left-width: 4px; border-radius: 8px; background: #fffaf0;
}
.eval-recovery h2 { margin: 0 0 6px; font-size: 1rem; }
.eval-recovery > p { margin: 0 0 14px; color: #604814; font-size: 0.875rem; line-height: 1.5; }
.eval-recovery-unavailable { border-color: #d8d4ca; background: #faf9f5; }
.eval-recovery-unavailable > p { margin-bottom: 0; color: #5a5a60; }
.eval-recovery-group { padding: 14px 0; border-top: 1px solid #eadfc5; }
.eval-recovery-group:last-child { padding-bottom: 0; }
.eval-recovery-group-head {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
}
.eval-recovery-group-head .btn { flex: 0 0 auto; }
.eval-recovery-group .cov-list { margin: 10px 0 0 18px; }
.eval-session-action { white-space: nowrap; }
.login-gaps {
  display: flex; flex-direction: column; gap: 7px; padding: 10px 12px;
  border: 1px solid #f1d7a8; border-radius: 8px; background: #fff8ec;
}
.login-gap-head { display: flex; align-items: center; gap: 8px; font-size: 0.8125rem; color: #6b4d1f; }
.login-gap {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 0.8125rem; color: #5a5a60;
}
.eval-run-card .field select, .eval-run-card .field input { max-width: 460px; }

/* Evaluation Plans (compose → run) ----------------------------------------- */
.evp-grid { grid-template-columns: minmax(0,2fr) minmax(0,1fr) 110px 150px 24px !important; }

/* Session Plans (Feature B) ------------------------------------------------ */
.sp-grid { grid-template-columns: minmax(0,2fr) 120px 160px minmax(0,1fr) 96px !important; }
.data-list .row.sp-grid { cursor: pointer; }
.sp-grid .sp-dup { padding: 4px 10px; font-size: 0.75rem; }
#sp-search { padding: 7px 12px; font-size: 0.8125rem; border: 1px solid #e2e2e2; border-radius: 8px; min-width: 200px; }
.tp-grid { grid-template-columns: minmax(0,2fr) 70px 110px 80px minmax(0,1.2fr) !important; }
.data-list .row.tp-grid { cursor: pointer; }
/* eval-plan viewer: the session-plan → zone table (see at a glance what each runs) */
.evp-sp-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.evp-sp-table th { text-align: left; font-weight: 600; color: #7a8194; font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: .03em; padding: 6px 10px; border-bottom: 1px solid #ececf0; }
.evp-sp-table td { padding: 8px 10px; border-bottom: 1px solid #f1f1f4; vertical-align: middle; }
.evp-sp-table tr:last-child td { border-bottom: 0; }
.evp-sp-table select.evp-zone { padding: 5px 8px; font-size: 0.8125rem; border: 1px solid #e2e2e2; border-radius: 7px; min-width: 150px; }
.evp-sp-table .text-right { text-align: right; }
.evp-sp-table .evp-remove { border: 0; background: none; color: #b91c1c; cursor: pointer; font-size: 1rem; line-height: 1; padding: 2px 6px; }
.evp-sp-table .evp-row-actions { white-space: nowrap; }
.evp-sp-table .evp-dup { border: 0; background: none; color: #3b5bdb; cursor: pointer; font-size: 0.95rem; line-height: 1; padding: 2px 6px; }
.evp-sp-table .evp-dup:disabled { opacity: .5; cursor: default; }
.evp-sp-table td a.accent { text-decoration: none; }
.evp-sp-table td a.accent:hover { text-decoration: underline; }
/* test-plan reorder arrows in the Order cell */
.tp-order { display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px; }
.tp-order .tp-ord-n { min-width: 16px; text-align: center; }
.tp-move { border: 0; background: transparent; color: #b8b4ac; cursor: pointer; font-size: 0.62rem; line-height: 1; padding: 2px; }
.tp-move:hover { color: #2563eb; }
/* drag-and-drop reorder */
.row.tp-grid[draggable="true"] { cursor: grab; }
.row.tp-grid.tp-dragging { opacity: 0.45; cursor: grabbing; }
.tp-grip { color: #c8c4bc; margin-right: 6px; cursor: grab; letter-spacing: -2px; }
.row.tp-grid:hover .tp-grip { color: #8a8a90; }

/* Organizations — client-scoped party + per-client override (Feature C) ---- */
.org-scoped-grid { grid-template-columns: minmax(0,1.6fr) minmax(0,1.4fr) 84px 84px 24px !important; }
.data-list .row.org-scoped-grid .party-badge { justify-self: start; }
.party-override { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.party-override .party-sel { padding: 4px 8px; font-size: 0.8125rem; max-width: 110px; }
.party-override .party-reset { padding: 4px 8px; font-size: 0.75rem; }
.party-override-badge {
  font-size: 10px; padding: 1px 6px; border-radius: 4px; margin-left: 6px;
  background: rgba(37,99,235,0.12); color: #2548b0; text-transform: uppercase;
  letter-spacing: 0.04em; font-weight: 600;
}

/* Catalogue coverage panel (plan step 7) — the three absence counts.
   Tone is carried by a border and a label, never by colour alone: an
   "undetermined" row has to read as unmeasured to someone who cannot see the
   amber, or the panel is back to conveying a state by rendering nothing. */
.coverage-panel { margin-bottom: 14px; }
.coverage-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.coverage-row {
  display: grid; grid-template-columns: minmax(0,1.3fr) minmax(150px,auto) minmax(0,2fr);
  gap: 12px; align-items: baseline; padding: 8px 0 8px 10px;
  border-left: 3px solid transparent; border-top: 1px solid #eee;
}
.coverage-row:first-of-type { border-top: none; }
.coverage-label { font-weight: 600; font-size: 0.8125rem; }
.coverage-value { font-variant-numeric: tabular-nums; font-size: 1.05rem; font-weight: 650; }
.coverage-detail { color: var(--muted, #6b7280); font-size: 0.8125rem; }
.coverage-sample { font-family: var(--font-mono, monospace); font-size: 0.75rem; margin-top: 3px; word-break: break-all; }
.coverage-panel a { text-decoration: underline; text-underline-offset: 3px; }
.coverage-panel a:focus-visible { outline: 2px solid #2563eb; outline-offset: 3px; }
.coverage-table-wrap { overflow-x: auto; }
.coverage-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.coverage-table th, .coverage-table td { text-align: left; vertical-align: top; padding: 12px; border-bottom: 1px solid #eee; overflow-wrap: anywhere; }
.coverage-table thead th { font-size: 0.75rem; color: #5a5a60; }
.coverage-table tbody th { font-weight: 500; }
.coverage-pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-top: 18px; font-size: 0.8125rem; }
@media (max-width: 680px) {
  .coverage-row { grid-template-columns: minmax(0,1fr) auto; }
  .coverage-detail { grid-column: 1 / -1; }
  .coverage-head { flex-wrap: wrap; }
}
/* The review queue's rows. FOUR columns, because unlike the coverage counts
   above them these rows carry a decision control — and the first version
   borrowed a class that exists in no stylesheet, so the control rendered into
   nothing. The fourth column is what makes the row actionable rather than
   merely informative. */
.review-row {
  display: grid;
  /* The action track has a MINIMUM, not a fixed width: at 250px flat it was the
     first thing squeezed when the panel narrowed, and a search field crushed to
     40px is not a search field. */
  grid-template-columns: minmax(0,1.2fr) 64px minmax(0,1.5fr) minmax(200px,0.9fr);
  gap: 12px; align-items: baseline; padding: 8px 0 8px 10px;
  border-left: 3px solid transparent; border-top: 1px solid #eee;
}
/* THE AFFIRM CONTROL — the common answer, so it reads as the primary one.
   Most rows in this queue are not mis-attributed: the operator is confirming
   what the pipeline already says. It sits left of the suggestion chips and
   carries weight so the eye lands on it first, but stays a ghost button —
   affirming changes nothing the client sees, so it should not shout like a
   destructive action. */
.review-affirm {
  font-weight: 600;
  border-color: #b7c4d8;
  color: #1a3a6b;
}
.review-affirm:hover { background: #eef3fb; }
.review-affirm[disabled] { opacity: 0.6; cursor: default; }

/* THE HOST IS THE ROW'S NAME, NOT ITS HEADLINE. `code` has no rule in this
   sheet, so it rendered at the browser default 1em while every line around it
   was 0.8125rem — the hostname ended up the largest thing on a row whose point
   is the decision. Size it with its neighbours and let weight carry it. */
.review-row code {
  font-size: 0.8125rem; font-weight: 600; color: #1a1a20;
  overflow-wrap: anywhere;
}
.review-row .coverage-sample code,
.review-row .coverage-sample { font-weight: 400; font-size: 0.75rem; }

/* Below this the four tracks stop fitting, so the detail and the control take
   their own full-width lines rather than being compressed into slivers. */
@media (max-width: 1180px) {
  .review-row { grid-template-columns: minmax(0,1fr) 64px; }
  .review-row > :nth-child(3), .review-row > .review-action {
    grid-column: 1 / -1;
  }
  .review-action { justify-content: flex-start; }
}
.review-row:first-of-type { border-top: none; }
/* A count in a row, not a headline. The coverage panel's .coverage-value is
   sized for three big numbers; eighty of them down a list is shouting. */
.review-count {
  font-variant-numeric: tabular-nums; font-size: 0.8125rem;
  color: #3a3a42; text-align: right;
}
/* A row whose decision just landed. Colour alone would not carry it, so the
   row also STATES 'owner recorded: <org>' — the border is confirmation for
   someone scanning, not the message itself. */
.review-row-recorded { border-left-color: #16a34a; }
/* The ONE owner-override control this panel writes through — the same fields
   the domain editor uses, so an attribution made from the list goes through the
   same picker, the same new-organisation path, the same host-vs-registrable-
   domain scope and the same guards. The rows only choose which host it is
   pointed at. */
.review-owner-form {
  margin: 10px 0 4px; padding: 12px; border: 1px solid #e2e2e2;
  border-radius: 8px; background: #fafafb;
}
.review-owner-form[hidden] { display: none; }
.review-owner-form select, .review-owner-form input { font-size: 0.8125rem; }

.review-action {
  display: flex; gap: 6px; align-items: center; justify-content: flex-end;
  /* Wrap rather than overflow: three suggested owners plus a search field
     will not fit on one line at every width, and a control that leaves the
     row is a control nobody can click. */
  flex-wrap: wrap;
}
.review-action input {
  /* A floor, not zero. `min-width: 0` let the field collapse to nothing when
     the suggestions took the row's width. */
  min-width: 120px; flex: 1 1 120px; font-size: 0.8125rem; padding: 5px 8px;
  border: 1px solid #d8d8dc; border-radius: 6px;
}
.review-action .btn-ghost { white-space: nowrap; font-size: 0.75rem; padding: 4px 8px; }

.coverage-clean { border-left-color: #16a34a; }
.coverage-clean .coverage-value { color: #16a34a; }
.coverage-gap { border-left-color: #d97706; }
.coverage-gap .coverage-value { color: #b45309; }
.coverage-undetermined { border-left-color: #9ca3af; background: #fafafa; }
.coverage-undetermined .coverage-value { color: #6b7280; font-size: 0.8125rem; font-style: italic; }

/* Expandable network-flow rows (Daniel 2026-06-10): click a row for full
   URL, query params, and request/response headers. */
tr.flow-row { cursor: pointer; }
tr.flow-row:hover { background: rgba(37,99,235,0.04); }
.flow-caret { display: inline-block; transition: transform 0.12s; color: #999; font-size: 10px; }
tr.flow-open .flow-caret { transform: rotate(90deg); color: #2563eb; }
tr.flow-detail-row > td { background: #fafafa; padding: 0; }
.flow-detail { padding: 12px 16px; font-size: 12px; }
.flow-detail.loading { color: #888; }
.fd-url { font-family: var(--font-mono, monospace); word-break: break-all; margin-bottom: 4px; }
.fd-meta { margin-bottom: 10px; }
.fd-block { margin-top: 10px; }
.fd-label { font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: #555; margin-bottom: 4px; }
table.fd-kv { width: 100%; border-collapse: collapse; }
table.fd-kv th { text-align: left; vertical-align: top; padding: 2px 10px 2px 0; color: #2563eb; font-weight: 500; white-space: nowrap; font-family: var(--font-mono, monospace); font-size: 11px; }
table.fd-kv td { padding: 2px 0; word-break: break-all; font-family: var(--font-mono, monospace); font-size: 11px; color: #333; }

/* Assisted-capture console (Daniel 2026-06-10): live DOM replay + Claude-Code
   style side column. Two-pane; the operator drives the real browser on the box. */
.manual-console { display: grid; grid-template-columns: minmax(0,1fr) minmax(360px, 420px); gap: 18px; align-items: start; }
.operator-desktop-note { max-width: 640px; margin: 0 0 18px; padding: 13px 15px; border: 1px solid #d9c48d; border-left: 4px solid #9b6a12; background: #fff9e9; color: #493613; display: grid; gap: 4px; }
.mc-replay { background: #161616; border: 1px solid #222; border-radius: 12px; padding: 12px; }
.mc-replay-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; color: #eee; }
.mc-player { min-height: 540px; background: #0a0a0a; border-radius: 8px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.mc-dot { width: 9px; height: 9px; border-radius: 50%; background: #dc2626; box-shadow: 0 0 0 0 rgba(220,38,38,.5); animation: mc-pulse 1.4s infinite; }
.mc-dot.off { background: #16a34a; animation: none; }
@keyframes mc-pulse { 0%{box-shadow:0 0 0 0 rgba(220,38,38,.5)} 70%{box-shadow:0 0 0 7px rgba(220,38,38,0)} 100%{box-shadow:0 0 0 0 rgba(220,38,38,0)} }
.mc-side { background: #fff; border: 1px solid #e2e2e2; border-radius: 12px; padding: 16px; position: sticky; top: 16px; }
.mc-side-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.mc-current { background: #eef4ff; border-left: 3px solid #2563eb; border-radius: 6px; padding: 10px 12px; margin-bottom: 14px; }
.mc-cur-name { font-weight: 600; }
.mc-cur-url { word-break: break-all; margin-top: 2px; }
.mc-instructions { margin-top: 10px; color: #222; font-size: 13px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
.mc-detail-block { margin-top: 10px; padding-top: 9px; border-top: 1px solid #dbe7ff; }
.mc-detail-label { font-size: 11px; font-weight: 600; color: #555; margin-bottom: 5px; }
.mc-kv { display: grid; grid-template-columns: minmax(84px, 0.42fr) minmax(0, 1fr); gap: 8px; font-size: 12px; line-height: 1.35; margin-top: 4px; }
.mc-kv span { color: #666; overflow-wrap: anywhere; }
.mc-kv b { color: #111; font-weight: 500; overflow-wrap: anywhere; }
.mc-specs-label { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: #6b6b71; margin-bottom: 6px; }
ol.mc-specs { list-style: none; padding: 0; margin: 0 0 14px; max-height: 320px; overflow: auto; }
.mc-spec { padding: 5px 4px; font-size: 13px; color: #555; display: flex; gap: 8px; border-radius: 5px; }
.mc-spec .mc-mark { color: #bbb; width: 12px; }
.mc-spec.cur { background: #eef4ff; color: #2d1a66; font-weight: 600; }
.mc-spec.cur .mc-mark { color: #2563eb; }
.mc-spec.done { color: #6b6b71; }
.mc-spec.done .mc-mark { color: #16a34a; }
.mc-stats { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; font-size: 12px; color: #555; }
.mc-stat b { color: #111; }
.mc-controls { display: flex; gap: 8px; }
.mc-controls button { flex: 1; }
.manual-console :is(button, input, a):focus-visible { outline: 3px solid #1d4ed8; outline-offset: 2px; }
.manual-console textarea:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 2px; }
#mc-block-reason { width: 100%; box-sizing: border-box; font: inherit; }
.mc-control-status { min-height: 1.2em; margin-top: 6px; color: #b91c1c; }
.mc-open { display: block; margin-top: 12px; color: #2563eb; font-weight: 600; text-decoration: none; }
.vbadge-live { background: rgba(220,38,38,.1); color: #b91c1c; }
.vbadge-ok { background: rgba(22,163,74,.12); color: #15803d; }
/* Save-login panel — snapshot a hand-done SSO login for agent reuse */
.mc-save { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border, #e8e5dc); }
.mc-save-label { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted, #6b7280); margin-bottom: 4px; }
.mc-save-row { display: flex; gap: 8px; margin-top: 8px; align-items: stretch; }
.compact-input { flex: 1; min-width: 0; background: var(--card, #fff); border: 1px solid var(--border, #e8e5dc); border-radius: 8px; padding: 8px 11px; font: inherit; font-size: 0.8125rem; color: var(--ink, #111); box-shadow: var(--shadow-sm); }
.compact-input:focus { outline: none; border-color: var(--accent, #2563eb); box-shadow: 0 0 0 3px rgba(37,99,235,0.12); }
.mc-save-row button { flex: 0 0 auto; white-space: nowrap; }
.mc-save-result { margin-top: 8px; min-height: 1em; }
.mc-save-result.ok { color: #15803d; }
.mc-save-result.err { color: #b91c1c; }
@media (max-width: 980px) { .manual-console { grid-template-columns: 1fr; } .mc-side { position: static; } }

/* Client-facing PrivacyPath view (v3 M4) — friendly, read-only privacy report. */
.client-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; margin-bottom: 18px; flex-wrap: wrap; }
.client-brand { font-weight: 700; letter-spacing: -0.5px; color: #2563eb; font-size: 15px; }
.client-controls { display: flex; gap: 16px; align-items: flex-end; }
.cv-proj { display: flex; flex-direction: column; gap: 3px; }
.cv-account { align-self: center; }
/* Evaluation/session multi-select scope bar — checkbox dropdowns above the report. */
.cv-scope-bar { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.cv-scope-field { min-width: 0; margin: 0; padding: 0; border: 0; }
.cv-scope-field > legend { margin: 0 0 5px; padding: 0; color: var(--cv-muted, var(--muted)); font-size: 0.75rem; font-weight: 650; }
.cv-multisel { position: relative; }
.cv-multisel > summary { list-style: none; cursor: pointer; background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 7px 30px 7px 11px; font-size: 0.8125rem; color: var(--ink); box-shadow: var(--shadow-sm); white-space: nowrap; position: relative; }
.cv-multisel > summary::-webkit-details-marker { display: none; }
.cv-multisel > summary::after { content: '\25BE'; position: absolute; right: 11px; top: 50%; transform: translateY(-50%); color: var(--muted); }
.cv-multisel[open] > summary { border-color: var(--accent); }
.cv-multisel-body { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 260px; max-height: 280px; overflow-y: auto; background: var(--card); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); padding: 6px; display: flex; flex-direction: column; gap: 1px; }
.cv-multisel-opt { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; font-size: 0.8125rem; cursor: pointer; }
.cv-multisel-opt:hover { background: var(--accent-wash); }
.cv-multisel-opt input { margin: 0; }
.cv-multisel-opt span:first-of-type { flex: 1; }
/* A withheld run stays in the picker for staff, light red, with its Hidden badge
   and Restore -- withholding is a state to display, never a removal. */
.cv-multisel-opt.cv-opt-withheld { background: var(--cv-withheld-bg, #fff1f1); }
.cv-multisel-opt.cv-opt-withheld:hover { background: #fde2e2; }
.cv-withheld-badge { flex: none; padding: 1px 6px; border-radius: 999px; background: #fee2e2; color: #991b1b; font-size: 0.6875rem; font-weight: 600; }
.cv-multisel-empty { padding: 6px 8px; }
.cv-scope-field .cv-multisel, .cv-scope-field .cv-multisel > summary { width: 100%; min-width: 0; }
.cv-scope-field .cv-multisel > summary { overflow: hidden; text-overflow: ellipsis; }
.cv-report-scope .cv-multisel-body {
  position: static;
  z-index: auto;
  width: 100%;
  min-width: 0;
  margin-top: 4px;
  box-shadow: var(--shadow-sm);
}
.linklike { border: 0; background: 0; padding: 0; color: #2563eb; font: inherit; cursor: pointer; text-decoration: underline; }
/* Client sign-in gate */
.cv-login { max-width: 360px; margin: 8vh auto 0; }
.cv-login .h1 { margin: 6px 0 4px; }
.cv-login-form { display: flex; flex-direction: column; gap: 12px; margin-top: 20px; }
.cv-login-fields { display: flex; flex-direction: column; gap: 12px; }
.cv-login-fields[hidden] { display: none; }
.cv-login-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 600; color: #555; }
.cv-login-form label.cv-show-pw { flex-direction: row; align-items: center; gap: 6px; font-weight: 400; color: #777; cursor: pointer; }
.cv-login-form label.cv-show-pw input { width: auto; padding: 0; }
.cv-login-form input { padding: 10px 12px; border: 1px solid #d8d8d8; border-radius: 8px; font-size: 14px; }
.cv-login-form button { padding: 10px 16px; border: 0; border-radius: 8px; background: #2563eb; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer; }
.cv-login-form button:disabled { opacity: 0.6; cursor: default; }
.cv-login-form button.cv-login-secondary {
  padding: 2px 0; align-self: flex-start; background: transparent;
  color: #1d4ed8; font-weight: 500;
}
.cv-login-form button.cv-login-secondary:hover { text-decoration: underline; }
#cv-login-status { min-height: 16px; margin: 0; color: #166534; font-size: 13px; }
.cv-login-err { color: #dc2626; font-size: 13px; min-height: 16px; }
/* A timed-out session is not an error the reader made, so it is informational
   rather than red — it replaces the "Sign in to view your report" line and
   tells them their place in the report is still waiting. */
.cv-login-expired {
  color: #92400e; background: #fffbeb; border: 1px solid #fde68a;
  border-radius: 6px; padding: 8px 10px; font-size: 13px; margin: 0 0 4px;
}
.cv-lens, .cv-group { display: inline-flex; border: 1px solid #e2e2e2; border-radius: 8px; overflow: hidden; }
.cv-lens button, .cv-group button { border: 0; background: #fff; padding: 8px 16px; font-size: 13px; font-weight: 600; color: #666; cursor: pointer; }
.cv-lens button.on, .cv-group button.on { background: #2563eb; color: #fff; }
.cv-group button { padding: 8px 13px; }
/* per-row severity chip — shown when the grouping axis isn't severity */
.cv-sevchip { font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px; margin-right: 7px; white-space: nowrap; }
.cv-sevchip.sev-high { background: #fee2e2; color: #b91c1c; }
.cv-sevchip.sev-notice { background: #fef3c7; color: #92600a; }
.cv-sevchip.sev-info { background: #e0edff; color: #1d4ed8; }
.cv-sevchip.sev-none { background: #eee; color: #666; }
.cv-reid { font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px; margin-right: 7px; white-space: nowrap; background: #4c1d95; color: #fff; letter-spacing: .2px; }
/* recipient legal class */
.cv-lens-note { margin-bottom: 14px; }
.cv-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin-bottom: 22px; }
.cv-card { background: #fff; border: 1px solid #e8e8e8; border-radius: 12px; padding: 18px 20px; }
.cv-card-hp { border-left: 3px solid #dc2626; }
.cv-card-unc { border-left: 3px solid #d4a017; }
.cv-card-click { cursor: pointer; text-align: left; font-family: inherit; transition: border-color .15s ease, box-shadow .15s ease; }
.cv-card-click:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
.cv-sub { margin-top: 3px; }
.cv-verdict { background: #eef4ff; border-left: 3px solid #2563eb; border-radius: 8px; padding: 14px 18px; margin-bottom: 20px; font-size: 0.95rem; line-height: 1.55; color: #1f2937; }
.cv-verdict b { color: #1d4ed8; }
.cv-legend { margin: -8px 0 20px; font-size: 0.8125rem; }
.cv-legend > summary { cursor: pointer; color: #6b7280; padding: 4px 0; }
.cv-legend-body { display: flex; flex-direction: column; gap: 7px; padding: 8px 0 4px; }
.cv-legend-row { display: flex; align-items: baseline; gap: 10px; }
.cv-legend-def { color: #4b5563; }
.cv-status-pill { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 999px; vertical-align: middle; letter-spacing: 0.3px; }
.cv-status-final { background: #dcfce7; color: #15803d; }
.cv-status-draft { background: #fef3c7; color: #92600a; }
.cv-status-unknown { background: #eeece5; color: #5a5a60; }
.cv-num { font-size: 30px; font-weight: 700; color: #2563eb; line-height: 1; }
.cv-card-hp .cv-num { color: #dc2626; }
.cv-lbl { font-size: 12px; color: #888; margin-top: 6px; }
.cv-bucket { margin-bottom: 24px; }
.cv-bucket-head { font-size: 16px; display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cv-sev-dot { width: 10px; height: 10px; border-radius: 50%; background: #999; }
.sev-high .cv-sev-dot { background: #dc2626; }
.sev-notice .cv-sev-dot { background: #d97706; }
.sev-info .cv-sev-dot { background: #2563eb; }
.cv-rows { display: flex; flex-direction: column; gap: 8px; }
.cv-row { background: #fff; border: 1px solid #ececec; border-radius: 10px; padding: 12px 14px; }
/* Client self-service remediation toggle (Ongoing <-> Remediated).
   It sits at the BOTTOM of a finding card, after the technical detail and the
   captured requests (Israel, 2026-09-16) -- it is the action a client takes
   once they have read the evidence, so it follows the evidence. The wrapper
   gives it the separation it needs as a standalone block and cancels the
   `margin-left` the button carries for its old life inside a toolbar row. */
.cv-finding-remediation { margin-top: 10px; padding-top: 10px; border-top: 1px solid #f1f1f1; }
.cv-finding-remediation .cv-remed { margin-left: 0; }
/* In a lens entry's own control row, beside Hide (Daniel 2026-09-25, image004):
   a control among controls, not a closing section. */
.cv-finding-main .cv-finding-remediation { margin: 0; padding: 0; border-top: 0; display: inline-flex; }
.cv-remed { margin-left: 8px; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px; border: 1px solid #cbd5e1; background: #fff; color: #475569; cursor: pointer; white-space: nowrap; }
.cv-remed:hover { border-color: #94a3b8; }
.cv-remed.is-remediated { background: #dcfce7; border-color: #86efac; color: #15803d; }
.cv-remed:disabled { opacity: .5; cursor: default; }
.cv-row:has(.cv-remed.is-remediated) { opacity: .62; }
.sev-high .cv-row { border-left: 3px solid #dc2626; }
.sev-notice .cv-row { border-left: 3px solid #d97706; }
.cv-row-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cv-journey { margin: 4px 0 24px; }
.cv-journey-row { background: #fff; border: 1px solid #dbe7fb; border-left: 3px solid #2563eb;
  border-radius: 10px; padding: 12px 14px; }
.cv-journey-note { font-size: 0.8125rem; color: #5a5a60; margin: -4px 0 10px; }
.cv-journey-badge { font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: 999px;
  white-space: nowrap; background: #dbeafe; color: #1d4ed8; }
.cv-item { font-weight: 600; }
.cv-to { color: #555; }
.cv-count { color: #999; font-size: 12px; margin-left: auto; }
.cv-rec { font-size: 13px; color: #333; margin-top: 6px; }
.cv-rec-empty { color: #aaa; font-style: italic; }
.cv-hosts { margin-top: 6px; }
.cv-hosts code { background: #f3f3f3; padding: 1px 5px; border-radius: 4px; font-size: 11px; margin-right: 4px; }

/* Recommendation editor (detection-type → recommendation; authored). */
.rec-group { margin-bottom: 22px; }
.rec-group-head { font-size: 15px; display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.rec-row { background: #fff; border: 1px solid #ececec; border-radius: 10px; padding: 12px 14px; margin-bottom: 8px; }
.sev-high .rec-row { border-left: 3px solid #dc2626; }
.sev-notice .rec-row { border-left: 3px solid #d97706; }
.sev-info .rec-row { border-left: 3px solid #2563eb; }
.rec-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
/* The rule name is an INPUT (authored by counsel, editable via Edit) but must
   read as plain text until the row is unlocked — otherwise every row looks like
   a form and the page stops looking like a list of rules. */
.rec-name {
  font-weight: 600;
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  font: inherit;
  padding: 1px 4px;
  border-radius: 4px;
  /* THE NAME MUST NOT BE CLIPPED BY ITS OWN BADGES.
     `width: auto` on an <input> is the browser's default size attribute — about
     22ch — not "as wide as the value", so a long rule name was silently cut off
     INSIDE the control while the severity, party, id and field chips sat beside
     it. Measured on the live operator console: 15 of 24 names clipped, the worst
     needing 473px in a 244px box ("Personal data and video information
     transmitted to third party" read as "...transmitted to").
     An input cannot size to its content in CSS, so it takes the row instead:
     it grows into the free space, and `.rec-meta` already wraps, so the badges
     drop below rather than squeezing the title (Israel, 2026-09-09). */
  flex: 1 1 32ch;
  min-width: 22ch;
  width: auto;
  text-overflow: ellipsis;
}
.rec-name[readonly] { cursor: default; }
.rec-name.editing {
  border-color: var(--line, #ccd);
  background: var(--card, #fff);
}
.rec-name.editing:focus { outline: 2px solid var(--accent, #36c); outline-offset: 1px; }
/* The severity SELECT mirrors .rec-name: it reads as a chip until the row is
   unlocked, then looks like a control. The palette is duplicated from
   .cv-sevchip rather than shared because those rules are scoped to that class —
   a bare `sev-high` on this element inherits nothing and renders as an unstyled
   dropdown, which is how it first shipped. */
.rec-sev {
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: inherit;
  white-space: nowrap;
  /* Without this the browser paints its own control chrome over the chip
     background on every platform except Firefox. */
  -webkit-appearance: none;
  appearance: none;
  /* A <select> is otherwise as wide as its WIDEST option, so an Info rule
     rendered a chip sized for "High Priority" — a long empty coloured tail that
     reads as a rendering fault. field-sizing shrinks it to the selected text. */
  field-sizing: content;
  max-width: 16ch;               /* fallback where field-sizing is unsupported */
  text-overflow: ellipsis;
}
.rec-sev:disabled { opacity: 1; cursor: default; }   /* greyed-out reads as broken */
/* Counsel must see the whole decision, not a clipped "Deliberately ...". */
.rec-sev:has(option[value="ungraded"]) { max-width: 28ch; }
.rec-sev.sev-high { background: #fee2e2; color: #b91c1c; }
.rec-sev.sev-notice { background: #fef3c7; color: #92600a; }
.rec-sev.sev-info { background: #e0edff; color: #1d4ed8; }
.rec-sev.sev-none { background: #eee; color: #666; }
.rec-sev.editing {
  border-color: var(--line, #ccd);
  -webkit-appearance: menulist;
  appearance: menulist;   /* the arrow is the affordance that says it is now a choice */
  border-radius: 6px;
  padding: 2px 4px;
}
.rec-sev.editing:focus { outline: 2px solid var(--accent, #36c); outline-offset: 1px; }
.rec-id { background: #f3f3f3; padding: 1px 6px; border-radius: 4px; font-size: 11px; color: #777; }
.rec-text { width: 100%; box-sizing: border-box; border: 1px solid #e2e2e2; border-radius: 8px; padding: 8px 10px; font: inherit; font-size: 13px; resize: vertical; }
.rec-text:focus { border-color: #2563eb; outline: none; }
.rec-text[readonly] { background: #fafafa; color: #444; cursor: default; }
.rec-actions { display: flex; gap: 8px; margin-top: 6px; }
.rec-status { font-size: 12px; margin-left: auto; }
.rec-status.saving { color: #999; }
.rec-status.ok { color: #16a34a; }
.rec-status.err { color: #dc2626; }

/* ===== polish pass (2026-06-10) ========================================== */
/* Design tokens — formalise the palette the app already uses by fallback, so
   new surfaces stay consistent and the whole thing is themeable in one place. */
:root {
  --ground: #f7f5f0;
  --card: #ffffff;
  --border: #e8e5dc;          /* warm hairline — the canonical border */
  --border-strong: #ddd9cd;
  --ink: #1a1a1c;
  --ink-soft: #4a4a50;
  --muted: #8a8a90;
  /* PrivacyPath accent = BLUE. Purple (#5e17eb) is the MinusOneDB brand and is
     intentionally NOT used on PrivacyPath surfaces. */
  --accent: #2563eb;
  --accent-strong: #1d4ed8;
  --accent-wash: #eef4ff;
  --radius: 10px;
  --radius-lg: 14px;
  --shadow-sm: 0 1px 2px rgba(20,18,12,0.04);
  --shadow: 0 2px 10px rgba(20,18,12,0.05), 0 1px 2px rgba(20,18,12,0.04);
  --shadow-card: 0 1px 3px rgba(20,18,12,0.05);
  --font-mono: 'Fragment Mono', 'JetBrains Mono', 'Fira Code', Consolas, monospace;
  --sev-high: #dc2626;
  --sev-notice: #d97706;
  --sev-info: #2563eb;
}

/* Form fields — the missing `.fld` component (assisted launch, upload, client
   picker all used it unstyled). Label above a clean control, editorial spacing. */
.fld { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
/* An inline yes/no INSIDE a .fld — the assisted launch form's "physical
   handset" opt-in. `.fld` stacks its children, which turns a checkbox and its
   label into two rows with the box orphaned above the words. */
.fld-check { display: flex; flex-direction: row; align-items: center; gap: 8px;
  font-weight: 400; text-transform: none; letter-spacing: 0; cursor: pointer; }
.fld-check input[type="checkbox"] { width: auto; margin: 0; cursor: pointer; }
.fld > span { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }
.fld > span .muted { text-transform: none; letter-spacing: 0; font-weight: 400; }
.fld select, .fld input[type="text"], .fld input[type="number"], .fld input:not([type]), .fld input[type="file"], .fld textarea {
  width: 100%; box-sizing: border-box; background: var(--card);
  border: 1px solid var(--border); border-radius: 8px; padding: 9px 12px;
  font: inherit; font-size: 0.875rem; color: var(--ink); transition: border-color .15s, box-shadow .15s;
}
.fld select { appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a8a90' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 32px; }
.fld :focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,0.12); }
.fld input[type="file"] { padding: 7px 10px; font-size: 0.8125rem; color: var(--ink-soft); }

/* Consistency: pull the surfaces built today onto the canonical border + card
   shadow so they sit in the same material as the rest of the app. */
.mc-side, .cv-card, .cv-row, .rec-row, tr.flow-detail-row > td { border-color: var(--border) !important; }
.cv-card, .cv-row, .rec-row { box-shadow: var(--shadow-card); }
.cv-card { border-radius: var(--radius-lg); }
.card { box-shadow: var(--shadow-card); }
.cv-lens, .fld select, .fld input { box-shadow: var(--shadow-sm); }

/* Buttons: gentle press + transition so the UI feels responsive. */
.btn-primary, .btn-secondary { transition: transform .04s ease, box-shadow .15s, background .15s, border-color .15s; }
.btn-primary:active, .btn-secondary:active { transform: translateY(1px); }

/* ===== polish pass 2 — client view + micro-interactions =================== */
/* Data-types collected (layer-1 "what data") chip row */
.cv-datatypes { margin: -8px 0 24px; }
.cv-dt-label { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 8px; }
.cv-dt-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.cv-dt-chip { display: inline-flex; align-items: center; gap: 7px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 5px 6px 5px 12px; font-size: 0.8125rem; color: var(--ink-soft); box-shadow: var(--shadow-sm); cursor: pointer; font-family: inherit; }
.cv-dt-chip:hover { border-color: var(--accent); }
/* search + filter chips */
.cv-filter { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
#cv-search { width: 100%; max-width: 480px; padding: 9px 13px; border: 1px solid var(--border); border-radius: 9px; font-size: 0.875rem; }
.cv-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-height: 0; }
.cv-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--accent-wash); color: var(--accent); border-radius: 999px; padding: 3px 6px 3px 11px; font-size: 0.8125rem; font-weight: 600; }
.cv-chip-x { border: 0; background: 0; color: inherit; cursor: pointer; font-size: 0.8125rem; line-height: 1; padding: 0 2px; }
.cv-chip-clear { font-size: 0.8125rem; }
.cv-urls { margin-top: 4px; font-size: 0.8125rem; }
.cv-urls a { color: var(--accent); }
/* DOM-replay add-on */
.cv-replay { margin-top: 24px; border: 1px solid var(--border); border-radius: 12px; padding: 8px 16px; background: var(--card); }
.cv-replay > summary { cursor: pointer; font-weight: 600; padding: 8px 0; }
.cv-replay-body { padding: 8px 0 12px; }
.cv-replay-sess { margin-bottom: 12px; }
.cv-replay-sess-h { margin-bottom: 5px; }
.cv-replay-feats { display: flex; flex-wrap: wrap; gap: 8px; }
.cv-replay-feats button { border: 1px solid var(--border); background: #fff; border-radius: 8px; padding: 6px 12px; font-size: 0.8125rem; cursor: pointer; font-family: inherit; }
.cv-replay-feats button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
.cv-replay-player { margin-top: 12px; }
.cv-dt-n { background: var(--accent-wash); color: var(--accent); border-radius: 999px; padding: 1px 8px; font-size: 0.6875rem; font-weight: 600; }

/* Severity visual hierarchy — High dominates, Info recedes */
.cv-bucket.sev-high .cv-bucket-head { font-size: 1.0625rem; }
.cv-bucket.sev-info .cv-bucket-head { color: var(--muted); }
.cv-bucket.sev-info .cv-row { opacity: 0.92; }

/* Micro-interactions: rows lift on hover, everything transitions smoothly */
.cv-row, .rec-row, .cv-dt-chip { transition: transform .12s ease, box-shadow .15s ease, border-color .15s ease; }
.cv-row:hover, .rec-row:hover { transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--border-strong); }
.cv-card { transition: transform .12s ease, box-shadow .15s ease; }
.cv-card:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.nav a, .cv-lens button, .vbadge { transition: color .15s, background .15s, border-color .15s; }

/* Loading: a gentle pulse instead of static text */
.loading { animation: dbr-pulse 1.3s ease-in-out infinite; }
@keyframes dbr-pulse { 0%,100% { opacity: 0.55; } 50% { opacity: 1; } }

/* Recommendation autosave indicator — fade in */
.rec-status.ok, .rec-status.saving, .rec-status.err { animation: dbr-fade .2s ease; }
@keyframes dbr-fade { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }

/* Header project picker — match the .fld control look */
.cv-proj select { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 7px 30px 7px 11px; font: inherit; font-size: 0.8125rem; color: var(--ink); cursor: pointer; appearance: none; -webkit-appearance: none; box-shadow: var(--shadow-sm);
  background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a8a90' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 11px center; }
.cv-proj select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,0.12); }

/* ===== dogfood fix — global form controls ================================ */
/* Every older view used bare native selects/date inputs (evaluations, compare,
   organizations, sessions), inconsistent with the new .fld forms. Style ALL form
   controls app-wide to the token system in one place. More-specific rules
   (.fld, .cv-proj, .rec-text) still win where they add chevrons/sizing. */
select, input[type="text"], input[type="search"], input[type="date"],
input[type="number"], input[type="email"], input[type="password"] {
  font: inherit; font-size: 0.8125rem; color: var(--ink);
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 11px; box-shadow: var(--shadow-sm);
  transition: border-color .15s, box-shadow .15s;
}
select {
  appearance: none; -webkit-appearance: none; cursor: pointer; padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a8a90' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}
select:focus, input:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,0.12);
}

/* Derived GPC/login state in the test-list GPC/Login columns (sessionplan
   builder). Shown where the other per-test data lives, not a separate bar.
   Green = on; login persists once a login step runs. */

/* What a testPlan will be graded on. Muted by default because it is context,
   not status — but a DECLARED criterion is stated by a person and an INFERRED
   one is guessed from prose, so they must not look identical. */
.tp-graded { font-size: 11px; font-weight: 500; color: #8a8a90; margin-left: 8px;
  white-space: nowrap; }
.tp-graded.declared { color: #0f7a37; }
.tp-graded.invalid { color: #b3261e; font-weight: 600; }

/* The same distinction on the TRIGGER page's selected-plan list, where being
   wrong costs three escalating model attempts and a wasted leg rather than a
   confusing row. Louder than .tp-graded for that reason — an operator is about
   to press Run. The declared/inferred difference is carried by the ✓ / ⚠ mark
   and by the word in the text as well as by colour: a colour-only difference is
   invisible in a monochrome screenshot and to a colourblind operator, and
   "inferred is the one to check" is the whole point of the line. */
.plan-graded { font-size: 11px; font-weight: 500; color: #8a8a90; margin-top: 4px;
  padding: 2px 0 2px 8px; border-left: 2px solid transparent; }
.plan-graded.declared { color: #0f7a37; border-left-color: #0f7a37; }
.plan-graded.inferred { color: #8a5a00; border-left-color: #d99500; font-weight: 600;
  background: rgba(217, 149, 0, 0.08); }
.plan-graded.invalid { color: #b3261e; border-left-color: #b3261e; font-weight: 700;
  background: rgba(180, 35, 24, 0.09); }
.plan-graded-mark { font-weight: 700; }
.plan-graded-action { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px; opacity: 0.85; }

.tp-state { font-weight: 600; }
.tp-state.on { color: #0f7a37; }
.tp-state.off { color: #9a9aa0; font-weight: 400; }
.tp-state.invalid {
  color: #9f2219; font-weight: 700; line-height: 1.3;
  background: rgba(180, 35, 24, 0.09); border: 1px solid rgba(180, 35, 24, 0.35);
  border-radius: 6px; padding: 3px 6px;
}

/* Two-column replay review (settled 2026-06-19): player rectangle with a
   green/red test list scrolling alongside it. The picker becomes a vertical rail. */
.replay-2col { display: flex; gap: 16px; align-items: flex-start; }
.replay-2col .replay-main { flex: 1; min-width: 0; }
.replay-rail {
  flex: 0 0 232px; flex-wrap: nowrap; flex-direction: column;
  max-height: 620px; overflow-y: auto; margin-bottom: 0;
  border: 1px solid #ece9e0; border-radius: 8px; padding: 8px; background: #faf9f7;
}
.replay-rail button { width: 100%; }
@media (max-width: 900px) {
  .replay-2col { flex-direction: column; }
  .replay-rail { flex-basis: auto; width: 100%; max-height: 200px; flex-direction: row; flex-wrap: wrap; }
  .replay-rail button { width: auto; }
}

/* Client-report headline: PII leaked despite a GPC opt-out (read-time finding). */
.cv-verdict-alert { margin: 0 0 12px; padding: 12px 16px; border-radius: 8px;
  background: rgba(220,70,70,0.10); border: 1px solid rgba(220,70,70,0.35);
  color: #b3261e; font-size: 14px; line-height: 1.5; }

/* Click-pulse overlay — make each agent click visible in the DOM replay (evidence). */
.click-pulse-layer { position: absolute; inset: 0; pointer-events: none; z-index: 30; overflow: hidden; }
/* Click cue: expands fast to a bold ring then HOLDS (doesn't fade to nothing),
   so the spot stays marked for the ~2.4s the element lives — visible even in fast
   playback. Bright red + white halo + glow makes it pop over any page. */
.click-pulse { position: absolute; width: 0; height: 0; transform: translate(-50%, -50%);
  border-radius: 50%; border: 5px solid #ef4444;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.9), 0 0 14px 2px rgba(239,68,68,0.7);
  animation: click-pulse-anim 0.45s cubic-bezier(.22,1,.36,1) forwards; }
@keyframes click-pulse-anim {
  0%   { width: 6px;  height: 6px;  opacity: 1;    border-width: 6px; }
  100% { width: 70px; height: 70px; opacity: 0.92; border-width: 5px; }
}
.click-pulse-label { position: absolute; transform: translate(-50%, -190%);
  background: #ef4444; color: #fff; font: 700 11px/1 system-ui, sans-serif;
  letter-spacing: 0.6px; padding: 3px 7px; border-radius: 4px; white-space: nowrap;
  box-shadow: 0 1px 5px rgba(0,0,0,0.35); animation: click-pulse-label-anim 0.3s ease-out; }
@keyframes click-pulse-label-anim { from { opacity: 0; transform: translate(-50%, -150%); }
  to { opacity: 1; transform: translate(-50%, -190%); } }
.replay-cov-note { margin: 0 0 10px; padding: 8px 12px; border-radius: 6px;
  background: #f6f5f1; border: 1px solid #ece9e0; }

/* session testPlans list: inline Retry / Capture-by-hand on a failed/stalled row */
.ts-actions { margin-top: 6px; display: flex; align-items: center; gap: 0; }
.ts-actions .ts-act { font-size: 0.78rem; }

/* recommendations page: per-type "what it catches" evidence line */
.rec-detail { margin: 4px 0 8px; line-height: 1.5; }
.rec-detail-label { color: #7a8194; font-weight: 600; }
.rec-detail code { background: #f1f1f4; border-radius: 5px; padding: 1px 6px; font-size: 0.72rem; color: #4a4a52; }
.rec-detail .rec-chips code { margin-right: 3px; }
.rec-trigger { margin: 8px 0 10px; border: 1px solid #ece9e0; border-radius: 8px; background: #fbfaf8; }
.rec-trigger > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; padding: 8px 10px; font-size: 0.8125rem; }
.rec-trigger > summary::-webkit-details-marker { display: none; }
.rec-trigger > summary::before { content: '▸'; color: #9aa0ad; font-size: 0.7rem; transition: transform .12s ease; }
.rec-trigger[open] > summary::before { transform: rotate(90deg); }
.rec-trigger-label { color: #7a8194; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; font-size: 0.6875rem; }
.rec-trigger-body { border-top: 1px solid #ece9e0; padding: 10px; }
.rec-trigger-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 10px 14px; }
.rec-k { color: #7a8194; font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; margin-bottom: 3px; }
.rec-term { display: inline-flex; align-items: center; gap: 5px; }
.rec-help { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border: 1px solid #c9ced8; border-radius: 50%; color: #697183; background: #fff; font-size: 0.625rem; font-weight: 700; line-height: 1; letter-spacing: 0; text-transform: none; cursor: help; }
.rec-help:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(37,99,235,0.14); }
.rec-help::after { content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); z-index: 20; display: none; width: max-content; max-width: min(300px, 72vw); padding: 8px 10px; border-radius: 7px; background: #25272d; color: #fff; box-shadow: 0 8px 24px rgba(15,15,20,0.16); font-size: 0.75rem; font-weight: 500; line-height: 1.4; letter-spacing: 0; text-transform: none; white-space: normal; }
.rec-help::before { content: ''; position: absolute; left: 50%; bottom: calc(100% + 3px); transform: translateX(-50%) rotate(45deg); z-index: 21; display: none; width: 8px; height: 8px; background: #25272d; }
.rec-help:hover::after, .rec-help:focus::after, .rec-help:hover::before, .rec-help:focus::before { display: block; }
.rec-v { color: #3f3f46; font-size: 0.8125rem; line-height: 1.45; }
.rec-v code, .rec-example code { background: #f1f1f4; border-radius: 5px; padding: 1px 6px; font-size: 0.72rem; color: #4a4a52; }
.rec-none { color: #9aa0ad; font-style: italic; }
.rec-examples { margin-top: 12px; display: flex; flex-direction: column; gap: 7px; }
.rec-examples-empty { margin-top: 8px; }
.rec-example { border: 1px solid #eeeae2; border-radius: 7px; background: #fff; padding: 8px 9px; }
.rec-example-main { color: #33333a; font-size: 0.8125rem; line-height: 1.45; }
.rec-example-sub { display: flex; flex-wrap: wrap; gap: 5px 10px; margin-top: 4px; color: #7a8194; font-size: 0.75rem; line-height: 1.4; }
.rec-example-sub a { color: var(--accent); max-width: 560px; overflow-wrap: anywhere; }
@media (max-width: 760px) {
  .rec-trigger-grid { grid-template-columns: 1fr; }
}

/* testPlan lens: the directions handed to the capture agent for the selected test */
.testplan-lens-instr { margin: 12px 0 4px; padding: 12px 14px; background: #f6f7f9; border: 1px solid #e6e8ec; border-radius: 8px; }
.testplan-lens-instr-label { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #7a8194; margin-bottom: 6px; }
.testplan-lens-instr-text { white-space: pre-wrap; line-height: 1.5; color: #333; font-size: 0.9rem; }

/* collapsible capture-notice banner group (minimize the amber boxes) */
.session-banners { margin: 0 0 6px; }
.session-banners-summary { cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 10px; font-size: 0.82rem; font-weight: 600; color: #8a6d1a; padding: 4px 0; user-select: none; }
.session-banners-summary::-webkit-details-marker { display: none; }
.session-banners-summary::before { content: '▸'; font-size: 0.7rem; color: #b0985a; transition: transform .12s; }
.session-banners[open] .session-banners-summary::before { transform: rotate(90deg); }
.session-banners-hint { font-size: 0.7rem; font-weight: 400; color: #9aa0ad; border: 1px solid #d7dae0; border-radius: 5px; padding: 1px 7px; }
.session-banners-body { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }

/* per-test lens (focusTpid): the replay rail holds a single feature — the same
   test already selected in the testPlans rail — so hide the redundant picker and
   let the player fill the width. */
.replay-solo .replay-picker { display: none; }

/* ===== recommendations: Trigger Matrix (List ⇄ Matrix toggle) ===========
   Expresses how party / data sensitivity / recipient class / opt-out state each bend a
   detectionType's severity + client recommendation — logic that already
   fires read-time in server.py but was invisible next to the rule it
   modifies. The recommendation column is per-cell EDITABLE (see
   `.tm-rec-cell`): third-party/base edits write straight to the detectionType
   (server.py api_detection_type_save); first-party and opt-out-state edits are
   a schema-free recommendationRule overlay (api_recommendation_rule_upsert/
   _delete) that wins over the default at read time — `.tm-authored-badge`
   flags a cell currently overridden. Local `--tm-*` tokens default to the
   app's light palette and are overridden under prefers-color-scheme:dark —
   the rest of the app has no dark theme yet, so this view carries its own
   self-contained one. */
.rec-view-toggle { margin-bottom: 18px; }
.trigger-matrix {
  --tm-surface: var(--card); --tm-surface-2: #f1eee6; --tm-hair: var(--border);
  --tm-ink: var(--ink); --tm-muted: var(--muted); --tm-faint: #9aa0ad;
  --tm-accent: var(--accent);
  --tm-hi: #2A3B6B; --tm-hi-bg: #E4E9F6; --tm-med: #6B7488; --tm-med-bg: #EBEDF2;
  --tm-lo: #9AA2B4; --tm-lo-bg: #F0F2F6;
}
@media (prefers-color-scheme: dark) {
  .trigger-matrix {
    --tm-surface: #161B25; --tm-surface-2: #1D232F; --tm-hair: #262D3B;
    --tm-ink: #E7EAF1; --tm-muted: #9AA2B4; --tm-faint: #6B7386; --tm-accent: #8CA0E4;
    --tm-hi: #8CA0E4; --tm-hi-bg: #1E2740; --tm-med: #9AA2B4; --tm-med-bg: #202632;
    --tm-lo: #6B7386; --tm-lo-bg: #1A1F2A;
  }
}
.trigger-matrix { color: var(--tm-ink); max-width: 100%; min-width: 0; }
.trigger-matrix .tm-lede { color: var(--tm-muted); max-width: 68ch; margin: 0 0 14px; font-size: 0.875rem; }
.trigger-matrix .tm-legend { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 0 0 16px; font-size: 0.78rem; color: var(--tm-muted); align-items: center; }
.trigger-matrix .tm-legend .grp { display: flex; align-items: center; gap: 7px; }
.tm-sens { display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 999px; font: 600 11px/1.4 var(--font-mono); letter-spacing: .02em; white-space: nowrap; }
.tm-sens.hi { color: var(--tm-hi); background: var(--tm-hi-bg); }
.tm-sens.med { color: var(--tm-med); background: var(--tm-med-bg); }
.tm-sens.lo { color: var(--tm-lo); background: var(--tm-lo-bg); }
.tm-wrap { width: 100%; max-width: 100%; overflow-x: auto; overflow-y: hidden; border: 1px solid var(--tm-hair); border-radius: var(--radius-lg); background: var(--tm-surface); }
.tm-wrap:focus-visible { outline: 3px solid var(--tm-accent); outline-offset: 2px; }
.trigger-matrix table { border-collapse: collapse; width: max-content; min-width: 100%; font-size: 0.84rem; }
.trigger-matrix thead th { position: sticky; top: 0; background: var(--tm-surface-2); text-align: left; font: 600 11px/1.3 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--tm-muted); padding: 12px 14px; border-bottom: 1px solid var(--tm-hair); vertical-align: bottom; z-index: 2; }
.trigger-matrix tbody td { padding: 13px 14px; border-bottom: 1px solid var(--tm-hair); vertical-align: top; }
.trigger-matrix tbody tr:last-child td { border-bottom: none; }
.trigger-matrix tbody tr:hover td { background: var(--accent-wash); }
.trigger-matrix .tm-grouprow td { background: var(--tm-surface-2); font: 600 11px/1 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--tm-faint); padding: 9px 14px; }
.tm-type .tm-nm { font-weight: 600; }
/* The name is an INPUT here as well as in the List view, and must read as plain
   text until unlocked — otherwise every matrix row looks like a form. The Edit
   control only appears on hover or keyboard focus so the table stays a table. */
.tm-name-edit { display: block; }
.tm-nm-input {
  font-weight: 600;
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  padding: 1px 4px;
  border-radius: 4px;
  width: 100%;
  box-sizing: border-box;
}
.tm-nm-input[readonly] { cursor: default; }
.tm-nm-input.editing {
  border-color: var(--line, #ccd);
  background: var(--card, #fff);
}
.tm-nm-input.editing:focus { outline: 2px solid var(--accent, #36c); outline-offset: 1px; }
/* ALWAYS VISIBLE, not hover-revealed. Daniel's complaint was that he could not
   find name editing at all; hiding the control until hover would reproduce
   exactly that, and every recommendation cell in this table already shows its
   Edit button permanently — the name was the odd one out. Kept small and muted
   so a table of rules still reads as a table. */
.tm-name-actions { display: flex; gap: 4px; margin-top: 2px; }
.btn-tiny { font-size: 11px; padding: 1px 6px; line-height: 1.6; }
.tm-name-status { display: block; margin-top: 2px; min-height: 0; }
.tm-name-status.err { color: #b91c1c; }
.tm-name-status.saving { color: #92600a; }
.tm-name-status.ok { color: #15803d; }
.tm-type .tm-key { display: block; font: 500 11.5px/1.4 var(--font-mono); color: var(--tm-faint); margin-top: 2px; }
/* The rule in words, under the rule's id. Prose, so it takes the body face and
   the muted tone rather than the mono of the key it sits beneath. */
.tm-type .tm-desc { display: block; font-size: 0.75rem; line-height: 1.45; color: var(--tm-muted); margin-top: 6px; }
.tm-cond { color: var(--tm-muted); font-size: 0.79rem; max-width: 26ch; }
.tm-cell-sub { display: block; color: var(--tm-muted); font-size: 0.75rem; margin-top: 4px; }
.tm-na { color: var(--tm-faint); font-size: 0.75rem; font-style: italic; }
.tm-rec { color: var(--tm-ink); font-size: 0.79rem; max-width: 30ch; }
.tm-members { color: var(--tm-muted); font-size: 0.75rem; margin-top: 4px; }
.tm-state-list { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.tm-state-pill { display: inline-flex; align-items: center; border: 1px solid var(--tm-hair); border-radius: 4px; padding: 2px 6px; font: 600 10.5px/1.3 var(--font-mono); color: var(--tm-muted); background: var(--tm-surface-2); }
.tm-state-recs { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--tm-hair); }
.tm-state-title { font: 600 10.5px/1.3 var(--font-mono); letter-spacing: 0; text-transform: uppercase; color: var(--tm-faint); margin-bottom: 8px; }
.tm-state-rec + .tm-state-rec { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--tm-hair); }
.tm-state-heading { font: 600 11px/1.35 var(--font-mono); color: var(--tm-muted); margin-bottom: 5px; }
/* What a compound rule REPLACES, attached under its own row. A compound absorbs
   its constituents' rows out of the report, so a compound graded below one of
   them silently downgrades what the reader is shown. The flagged variant is the
   only red thing in this table on purpose — counsel edits severity here. */
.trigger-matrix .tm-absorbs-row td { padding-top: 0; color: var(--tm-muted); font-size: 0.78rem; line-height: 1.55; border-bottom: 1px solid var(--tm-hair); }
.trigger-matrix .tm-absorbs-row code { font: 500 11.5px/1.4 var(--font-mono); }
.trigger-matrix .tm-absorbs-row .tm-absorbs-title { color: var(--tm-ink); }
.trigger-matrix .tm-absorbs-row .tm-absorbs-ungraded { display: block; margin-top: 4px; color: var(--tm-faint); }
.trigger-matrix .tm-absorbs-flag td { background: #fef2f2; color: #7f1d1d; border-left: 3px solid #b91c1c; }
.trigger-matrix .tm-absorbs-flag .tm-absorbs-title { color: #b91c1c; }
.trigger-matrix .tm-absorbs-flag .tm-absorbs-ungraded { color: #9f5b5b; }
.trigger-matrix tbody tr.tm-absorbs-row:hover td { background: inherit; }
.trigger-matrix .tm-note { margin-top: 18px; padding: 14px 16px; background: var(--tm-surface); border: 1px dashed var(--tm-hair); border-radius: var(--radius); color: var(--tm-muted); font-size: 0.8rem; }
.trigger-matrix .tm-note b { color: var(--tm-ink); }

/* Matrix recommendation cell editor (per detectionType × party). */
.tm-rec-cell { min-width: 220px; max-width: 34ch; }
.tm-rec-cell + .tm-rec-cell { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--tm-hair); }
.tm-rec-label { display: block; color: var(--tm-accent); font-size: 0.72rem; font-weight: 600; margin-bottom: 2px; }
.tm-rec-ta { display: block; width: 100%; box-sizing: border-box; border: 1px solid transparent; border-radius: 6px; padding: 0; font: inherit; font-size: 0.79rem; line-height: 1.4; color: var(--tm-ink); background: transparent; resize: none; }
.tm-rec-ta:not([readonly]) { border-color: var(--tm-hair); background: var(--tm-surface); padding: 6px 8px; resize: vertical; }
.tm-rec-ta:not([readonly]):focus { border-color: var(--tm-accent); outline: none; }
.tm-rec-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }
.tm-rec-actions .btn { padding: 3px 9px; font-size: 0.72rem; box-shadow: none; }
.tm-rec-status { font-size: 0.7rem; }
.tm-rec-status.saving { color: var(--tm-muted); }
.tm-rec-status.ok { color: #16a34a; }
.tm-rec-status.err { color: #dc2626; }
.tm-authored-badge { display: inline-block; font: 600 10px/1 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--tm-accent); border: 1px solid var(--tm-accent); border-radius: 4px; padding: 3px 6px; opacity: 0.85; }
.tm-fallback-badge { display: inline-block; font: 600 10px/1 var(--font-mono); letter-spacing: 0; text-transform: uppercase; color: var(--tm-muted); border: 1px solid var(--tm-hair); border-radius: 4px; padding: 3px 6px; opacity: 0.85; }

/* ===== client privacy report — verdict-led redesign ======================
   This surface deliberately carries a restrained legal-report palette within
   the wider operator app. The reading order mirrors the approved client
   mock-up: verdict first, progressively more evidence below. */
.cv-client-bar, #cv-body {
  --cv-navy: #16233d;
  --cv-ink: #1f2733;
  --cv-muted: #6b7280;
  --cv-faint: #9aa1ac;
  --cv-line: #e4e7ec;
  --cv-blue: #3b5bdb;
  --cv-high: #c0392b;
  --cv-high-bg: #fdecea;
  --cv-notice: #8a5a00;
  --cv-notice-bg: #fdf3e2;
  --cv-info: #5a6472;
  --cv-info-bg: #eef1f4;
  --cv-good: #0f7a37;
  --cv-withheld-bg: #fff1f1;
  --cv-shadow: 0 1px 3px rgba(16,24,40,.06), 0 1px 2px rgba(16,24,40,.04);
}

.cv-client-bar, #cv-body { width: 100%; max-width: 840px; margin-inline: auto; }
.cv-client-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  margin-bottom: 22px; color: var(--cv-muted); font-size: 0.75rem;
}
.cv-client-bar .client-brand {
  display: flex; align-items: center; gap: 9px; color: var(--cv-muted);
  font-size: 0.75rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.cv-brand-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px; background: var(--cv-navy);
  color: #fff; font-size: 0.6875rem; letter-spacing: 0;
}
.cv-brand-sep { color: #c4c9d1; }
.cv-brand-law { font-weight: 600; }
.cv-client-bar .cv-account { color: var(--cv-muted); font-size: 0.75rem; white-space: nowrap; }
.cv-client-bar .linklike { color: var(--cv-blue); }

.cv-report { color: var(--cv-ink); }
.cv-report-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.cv-report-head > div:first-child { min-width: 0; }
.cv-report-actions {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 10px; flex-wrap: wrap;
}
.cv-export-link, .cv-export-finding-link { padding: 7px 13px; font-size: 0.875rem; }
/* Outside the by-finding lens its export is [hidden]; .btn's display would
   otherwise outrank the UA rule and show it. */
.cv-export-finding-link[hidden] { display: none; }
.cv-report-head h1 {
  margin: 0; color: var(--cv-navy); font-size: 1.6875rem; line-height: 1.2;
  font-weight: 700; letter-spacing: -.01em;
}
.cv-report-sub { margin-top: 4px; color: var(--cv-muted); font-size: 0.875rem; }
.cv-status {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 13px;
  border: 1px solid; border-radius: 999px; font-size: 0.875rem;
  font-weight: 650; white-space: nowrap;
}
.cv-status-ring { width: 9px; height: 9px; border-radius: 50%; background: currentColor; }
.cv-status-high { color: var(--cv-high); background: var(--cv-high-bg); border-color: #f5c6c0; }
.cv-status-some { color: var(--cv-notice); background: var(--cv-notice-bg); border-color: #ead3a8; }
.cv-status-low { color: var(--cv-good); background: #eaf6ee; border-color: #b9ddc5; }
.cv-status-unavailable { color: var(--cv-info); background: var(--cv-info-bg); border-color: #d7dce2; }

.cv-report .cv-verdict {
  margin: 22px 0 4px; padding: 0; border: 0; border-radius: 0; background: none;
  color: var(--cv-ink); font-size: 1.3125rem; line-height: 1.4; font-weight: 450;
}
.cv-report .cv-verdict b { color: var(--cv-navy); font-weight: 700; }
.cv-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 22px 0 8px; }
.cv-tile {
  min-width: 0; padding: 18px 18px 16px; border: 1px solid var(--cv-line);
  border-radius: 14px; background: var(--card); box-shadow: var(--cv-shadow);
}
.cv-tile-number { color: var(--cv-navy); font-size: 2.75rem; font-weight: 750; line-height: 1; letter-spacing: -.02em; }
.cv-tile-alarm .cv-tile-number { color: var(--cv-high); }
.cv-tile-label { margin-top: 10px; color: var(--cv-ink, #1f2937); font-size: 1.0625rem; font-weight: 600; line-height: 1.35; }
.cv-tile-sub { margin-top: 4px; color: var(--cv-muted); font-size: 0.875rem; line-height: 1.4; }

.cv-section-title {
  margin: 38px 0 14px; color: var(--cv-muted); font-size: 0.8125rem;
  font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
}
.cv-unique-count {
  margin-left: 8px; color: var(--cv-navy); font-size: 0.8125rem; font-weight: 700;
  letter-spacing: 0; text-transform: none;
}
.cv-group-note {
  margin: 8px 0 4px; color: var(--cv-muted); font-size: 0.8125rem; line-height: 1.45;
}
/* By legal's one-line intro (Daniel 2026-09-25 00:51). */
.cv-legal-intro { margin: 10px 0 8px; color: var(--cv-muted); font-size: 0.875rem; line-height: 1.5; }
.cv-legal-intro[hidden] { display: none; }
/* The default-filter notice: "Showing only high-priority findings — 12 of 66.
   Show all priorities". Rendered in the reading column, not the control row,
   because a pressed chip does not tell a reader the page is a subset. Empty
   (and so invisible) when nothing is limited. */
.cv-filter-state:not(:empty) {
  margin: 0 0 8px; padding: 8px 12px; border-radius: 8px;
  background: #f3f4f7; border: 1px solid var(--cv-line); color: var(--cv-ink);
  font-size: 0.8125rem; line-height: 1.45;
}
.cv-filter-state .cv-filter-state-text { font-weight: 650; }
.cv-filter-state .linklike { margin-left: 4px; }
.cv-top-finding {
  display: flex; align-items: flex-start; gap: 13px; margin-bottom: 10px;
  padding: 15px 16px; border: 1px solid var(--cv-line); border-radius: 12px;
  background: var(--card); box-shadow: var(--cv-shadow);
}
.cv-top-icon {
  display: flex; flex: 0 0 34px; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 9px;
  background: var(--cv-high-bg); color: var(--cv-high); font-size: 1.0625rem; font-weight: 700;
}
.cv-top-finding-notice .cv-top-icon { color: var(--cv-notice); background: var(--cv-notice-bg); }
.cv-top-finding h3 { margin: 0; color: var(--cv-ink); font-size: 0.96875rem; line-height: 1.4; font-weight: 650; }
.cv-top-finding p { margin: 2px 0 0; color: var(--cv-muted); font-size: 0.875rem; line-height: 1.5; }

.cv-organize { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.cv-organize-label { margin-right: 2px; color: var(--cv-muted); font-size: 0.8125rem; }
/* The remainder beside a facet's buttons: what the buttons do not count, and
   why. Deliberately NOT styled as a control -- it is prose, so it must not read
   as a third option. */
.cv-organize-note { color: var(--cv-muted); font-size: 0.8125rem; line-height: 1.4; }
.cv-segmented { display: inline-flex; padding: 3px; border-radius: 10px; background: #eceef2; }
.cv-segmented button {
  padding: 7px 14px; border-radius: 8px; color: var(--cv-muted);
  font-size: 0.84375rem; font-weight: 650; line-height: 1.25;
}
.cv-segmented button:hover { color: var(--cv-navy); }
.cv-segmented button.on { color: var(--cv-navy); background: #fff; box-shadow: 0 1px 2px rgba(16,24,40,.12); }
.cv-filter-tools { margin: 0 0 12px; }
.cv-filter-tools > summary { display: inline-block; padding: 4px 0; color: var(--cv-blue); cursor: pointer; font-size: 0.8125rem; font-weight: 600; }
.cv-filter-tools .cv-filter { margin: 8px 0 4px; }
.cv-filter-tools #cv-search { max-width: none; border-color: var(--cv-line); background: var(--card); color: var(--cv-ink); }
.cv-filter-tools #cv-search:focus { outline: none; border-color: var(--cv-blue); box-shadow: 0 0 0 3px rgba(59,91,219,.14); }

.cv-finding-group {
  margin-bottom: 10px; overflow: hidden; border: 1px solid var(--cv-line);
  border-radius: 12px; background: var(--card); box-shadow: var(--cv-shadow);
}
/* A FEATURE IS A CONTAINER; A FINDING IS A ROW INSIDE IT.
 *
 * Counsel, 2026-08-23: "Can you make it visually more clear distinguishing
 * feature from finding either through formatting, coloring, whatever (I defer
 * to you)."
 *
 * The weight hierarchy was already there — feature 750, category 700, finding
 * 450 — and it was not enough: three levels of the same black text on the same
 * white ground, distinguishable only by comparing two headings side by side.
 * Weight tells you which is BIGGER, not which CONTAINS the other.
 *
 * So the feature summary gets a ground of its own and a left rail. Containment
 * is the thing being drawn, and a tinted header with an accent edge is what
 * every file browser, table and accordion uses to draw it. The findings inside
 * keep their plain ground, so the nesting is legible without reading a word.
 *
 * Deliberately NOT a severity colour: the rail is a structural cue and must not
 * be mistaken for a judgement about the feature. Neutral border tint, and the
 * severity dots inside are left as the only coloured judgement on the page.
 */
.cv-finding-group > summary {
  display: flex; align-items: center; gap: 14px; padding: 15px 17px;
  list-style: none; cursor: pointer;
  background: var(--cv-info-bg, #f6f7f9);
  border-left: 3px solid var(--cv-line);
  border-radius: 12px 12px 0 0;
}
.cv-finding-group:not([open]) > summary { border-radius: 12px; }
.cv-finding-group[open] > summary { border-bottom: 1px solid var(--cv-line); }
/* The body sits inside the same rail, so an open feature reads as one block
   rather than as a header floating above unrelated rows. */
.cv-finding-group[open] > .cv-group-body { border-left: 3px solid var(--cv-line); }
.cv-finding-group > summary::-webkit-details-marker { display: none; }
.cv-finding-group > summary::marker { content: ''; }
/* C33 — THE AFFORDANCE HAS TO BE READABLE WHEN THE CARD IS SHUT.
 *
 * The chevron existed and was drawn at --cv-faint / 0.8125rem, which is the
 * tint this sheet uses for de-emphasised METADATA. So it read as decoration
 * next to the bold feature name and counsel reported the cards as having no
 * affordance at all — twice. The marker was present and the SIGNAL was not,
 * which is why "there is a chevron" kept being an answer that did not settle
 * the complaint.
 *
 * Sized and toned as a control rather than as a label; the muted tint returns
 * once the card is open, where it has already done its job. */
.cv-group-chevron {
  flex: none; color: var(--cv-ink); font-size: 0.9375rem;
  opacity: .75; transition: transform .15s ease, opacity .15s ease;
}
.cv-finding-group > summary:hover .cv-group-chevron,
.cv-type-group > summary:hover .cv-group-chevron,
.cv-finding-group[open] > summary .cv-group-chevron,
.cv-type-group[open] > summary .cv-group-chevron,
.cv-finding-group[open] > summary .cv-group-chevron { transform: rotate(90deg); }
/* Host tier: the hostname is <code>, the organisation that received the data is
   prose beside it. Distinguishing them matters — a client must be able to tell
   "doubleclick.net" (evidence) from "Google LLC" (who got it). An unattributed
   host is italicised so a missing answer never looks like a stated one. */
.cv-type-host-org { color: var(--cv-faint); font-size: 0.8125rem; }
.cv-type-host-org-none { font-style: italic; }
/* The plain list of hosts a finding reached, under its one card — evidence,
   not N repeats of the same description/recommendation/remediate control. */
.cv-type-hostlist { display: flex; flex-wrap: wrap; gap: 6px 10px; margin: 2px 0 14px; }
.cv-type-host { display: inline-flex; }
.cv-type-host code { padding: 2px 7px; border-radius: 5px; background: #f3f4f7; color: var(--cv-ink); font-size: 0.78125rem; }
.cv-type-host-more { align-self: center; color: var(--cv-faint); font-size: 0.78125rem; font-style: italic; }
/* The top-level group is the heading of everything under it; the finding
   headlines below are its contents, so the weight steps DOWN as you descend
   (Israel, 2026-08-05). They used to sit at 650 and 680 — near-identical,
   which flattened the hierarchy the nesting was meant to show. */
.cv-group-title { flex: 1; min-width: 0; line-height: 1.35; }
.cv-group-name { color: var(--cv-ink); font-size: 0.96875rem; font-weight: 750; }
/* THE OBSERVED OPT-OUT TREATMENT, beside the feature it belongs to. Three
   states are drawable and the fourth deliberately is not: "no opt-out signal"
   IS the absence of this badge, so a journey the wire could not settle has to
   say so in words instead of sharing that silence.

   GPC and Do-Not-Sell are given different colours as well as different words —
   Daniel, 2026-08-17: "two very different things" — and the undetermined state
   is deliberately the quietest of the three, because it is a statement about
   our evidence rather than about the site. */
.cv-optout-badge {
  display: inline-block; margin-left: 8px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid transparent; font-size: 0.75rem; font-weight: 650;
  white-space: nowrap; vertical-align: 2px;
}
.cv-optout-gpc { color: #1e40af; background: #e7edfd; border-color: #c7d5f7; }
.cv-optout-dns { color: var(--cv-notice); background: var(--cv-notice-bg); border-color: #f0dcb4; }
.cv-optout-undetermined { color: var(--cv-info); background: var(--cv-info-bg); border-color: #d7dce2; font-weight: 600; }
/* THE OBSERVED OPT-OUT TREATMENT, STATED ON EVERY FEATURE GROUP. Counsel,
   2026-09-09: "If that flag is absent, I am assuming that the user is opted
   in." So unlike the badge above there is no state this draws nothing for, and
   no reader it is hidden from — every journey says which treatment it ran
   under, the two absences ("no opt-out signal", "not established") included.

   Deliberately NOT a pill. The count pills beside it are quantities and the
   badge is a flag; this is a sentence about the whole group, so it is set as
   text and given its own line at every width rather than competing with them
   for the heading row. GPC and Do-Not-Sell keep the badge's colours — Daniel,
   "two very different things" — and the two states that describe our own
   evidence rather than the site stay the quietest, which is the same ordering
   the badge already uses. */
.cv-group-optout {
  display: block; margin: 3px 0 0; font-size: 0.78125rem; font-weight: 600;
  color: var(--cv-faint); line-height: 1.4;
}
/* By-finding lens: what tells an entry from its same-named neighbours (grade,
   consent side, data, journey), set like the line above as one quiet sentence
   under the heading rather than as more pills beside it. */
.cv-group-subtitle {
  display: block; margin: 3px 0 0; font-size: 0.78125rem; font-weight: 500;
  color: var(--cv-faint); line-height: 1.4;
}
/* A one-journey entry names its journey only while shut; open, the journeys
   list beneath says it. */
.cv-finding-group[open] > summary .cv-group-subtitle-journey { display: none; }
/* A name's variants are cards inside its card; the sub-heading says which. */
.cv-finding-variants > .cv-finding-group:last-child { margin-bottom: 4px; }
/* By legal: the other categories a finding fits, one quiet line under its own;
   a sub-case's recommendation and a staff proposal sit above its entries. */
.cv-legal-also { font-style: italic; }
.cv-legal-subcase > .cv-legal-rec { margin: 6px 0 10px; }
.cv-legal-group > .cv-group-body > .cv-legal-rec { margin-bottom: 12px; }
.cv-legal-proposal { margin: 2px 0 8px; }
.cv-legal-staff-tag { background: #eef1ff; color: #3549a3; }
/* Edit category (By legal, staff): a quiet link above the heading's text, and
   an inline editor that fits a phone. */
.cv-legal-edit { margin: 0 0 10px; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
.cv-legal-edited { font-style: italic; }
.cv-legal-editor { flex-basis: 100%; display: grid; gap: 10px; padding: 12px; border: 1px solid var(--cv-line, #d9dce3);
  border-radius: 8px; background: var(--cv-surface, #fafbfc); }
.cv-legal-editor[hidden] { display: none; }
.cv-legal-editor-field { display: grid; gap: 4px; font-size: 0.8125rem; font-weight: 600; }
.cv-legal-editor-field input, .cv-legal-editor-field textarea { font: inherit; font-weight: 400; width: 100%;
  box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--cv-line, #c9ced8); border-radius: 6px; }
.cv-legal-editor-scope { border: 0; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 0.8125rem; }
.cv-legal-editor-scope legend { font-weight: 600; padding: 0; margin-bottom: 2px; }
.cv-legal-editor-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* The entry a reader came back to from its detail page ("By finding"). */
.cv-finding-group.cv-finding-target { outline: 2px solid var(--cv-blue); outline-offset: 2px;
  scroll-margin-top: 110px; }

/* THE LENS DETAIL PAGE'S NAVIGATION (Israel, 2026-09-24, item 7): breadcrumb,
   a compact bar that stays in view (name, grade, consent marker, prev/next),
   "On this page", the name's other variants, and per-leg evidence. Set in the
   card's own voices: section labels, meta text, the small outlined buttons. */
.cv-detail-nav { margin: 0 0 12px; }
.cv-detail-crumbs { margin: 2px 0 0; }
.cv-detail-nav-k { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-faint); margin-right: 4px; }
.cv-detail-crumbs ol { list-style: none; margin: 0 0 8px; padding: 0; display: flex;
  flex-wrap: wrap; gap: 2px 6px; font-size: 0.8125rem; line-height: 1.5; color: var(--cv-faint); }
.cv-detail-crumbs li + li::before { content: "\203a"; margin-right: 6px; color: var(--cv-faint); }
.cv-detail-crumbs a { color: var(--cv-blue); text-decoration: none; }
.cv-detail-crumbs a:hover { text-decoration: underline; }
.cv-detail-crumbs a[aria-current="page"] { color: var(--cv-ink); }
.cv-detail-bar { position: sticky; top: 100px; z-index: 20; display: flex; flex-wrap: wrap;
  align-items: center; gap: 6px 10px; padding: 9px 12px; border: 1px solid var(--cv-line);
  border-radius: 10px; background: var(--cv-info-bg, #f6f7f9); box-shadow: var(--cv-shadow); }
.cv-detail-bar-name { color: var(--cv-ink); font-size: 0.90625rem; font-weight: 750; }
.cv-detail-bar .cv-finding-severity { margin-left: 0; }
.cv-detail-pos { margin-left: auto; color: var(--cv-faint); font-size: 0.78125rem; white-space: nowrap; }
.cv-detail-steps { display: inline-flex; gap: 6px; }
.cv-detail-step { display: inline-flex; align-items: center; gap: 3px; padding: 3px 7px; min-height: 24px;
  border: 1px solid #7b8495; border-radius: 6px; background: #fff; color: var(--cv-blue);
  font-size: 0.6875rem; font-weight: 650; line-height: 1.3; text-decoration: none; white-space: nowrap; }
.cv-detail-step:hover { border-color: var(--cv-blue); background: #f7f8ff; }
.cv-detail-step.is-disabled { color: var(--cv-faint); border-color: var(--cv-line); background: none; }
.cv-detail-step:focus-visible, .cv-detail-jump-link:focus-visible, .cv-leg-jump:focus-visible,
.cv-leg-back:focus-visible, .cv-detail-crumbs a:focus-visible, .cv-detail-variants a:focus-visible {
  outline: 2px solid var(--cv-blue); outline-offset: 2px; }
.cv-detail-jump { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 10px 0 0; }
.cv-detail-jump-legs { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.cv-detail-jump-link, .cv-leg-jump, .cv-leg-back { padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--cv-blue); font-family: inherit; font-size: 0.78125rem; font-weight: 650; }
.cv-detail-jump-link:hover, .cv-leg-jump:hover, .cv-leg-back:hover { text-decoration: underline; }
.cv-detail-variants { margin: 10px 0 0; font-size: 0.8125rem; color: var(--cv-faint); }
.cv-detail-variants ul { margin: 2px 0 0; padding-inline-start: 1.3em; line-height: 1.5; }
.cv-detail-variants summary { cursor: pointer; }
.cv-detail-variants a { color: var(--cv-blue); text-decoration: none; }
.cv-detail-variants a:hover { text-decoration: underline; }
.cv-detail-foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin: 16px 0 4px; }
.cv-detail-foot .cv-detail-pos { margin-left: 0; }
.cv-leg-evidence-list { margin: 16px 0 0; }
.cv-leg-evidence { margin: 8px 0; padding: 10px 12px; border: 1px solid var(--cv-line); border-radius: 8px; }
.cv-leg-evidence .cv-feature-subheading { margin-bottom: 2px; }
.cv-finding-line.cv-leg-evidence-line { display: block; padding: 4px 0; border-bottom: 0; }
.cv-leg-back { margin-top: 6px; }
/* THE DETAIL PAGE'S EVIDENCE BY FEATURE (detailEvidenceByFeatureHtml): a proof
   summary, one collapsible section per feature, proof first, joined-with as a
   compact table, identical requests as one card ×N. */
.cv-proof-summary { margin: 12px 0 14px; padding: 10px 12px; border: 1px solid var(--cv-line);
  border-left: 3px solid var(--cv-blue); border-radius: 8px; background: #fbfcff; }
.cv-proof-claim { margin: 4px 0 2px; font-size: 0.875rem; line-height: 1.45; }
.cv-proof-total { margin: 0 0 8px; color: var(--cv-muted); font-size: 0.8125rem; }
.cv-proof-counts { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) minmax(0, 1fr); gap: 8px 22px; }
.cv-proof-hosts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.cv-proof-hosts .cv-host-request-actions { margin: 0; }
.cv-proof-count ul { margin: 2px 0 0; padding: 0; list-style: none; }
.cv-proof-count li { margin: 1px 0; }
.cv-proof-k { margin: 0 0 3px; color: var(--cv-muted); font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; }
.cv-proof-link { display: flex; justify-content: space-between; gap: 10px; width: 100%; padding: 1px 0;
  border: 0; background: none; cursor: pointer; color: var(--cv-blue); font: inherit; font-size: 0.8125rem;
  text-align: start; }
.cv-proof-link:hover .cv-proof-name { text-decoration: underline; }
.cv-proof-link:focus-visible { outline: 2px solid var(--cv-blue); outline-offset: 2px; }
.cv-proof-name { min-width: 0; overflow-wrap: anywhere; }
.cv-proof-n { flex: none; color: var(--cv-muted); font-variant-numeric: tabular-nums; }
.cv-journey-evidence { padding: 0; }
.cv-journey-evidence > summary { display: flex; gap: 8px; align-items: baseline; padding: 9px 12px;
  cursor: pointer; list-style: none; }
.cv-journey-evidence > summary::-webkit-details-marker { display: none; }
.cv-journey-evidence > summary::marker { content: ''; }
.cv-journey-evidence[open] > summary .cv-evidence-chevron,
.cv-join-row[open] > summary .cv-evidence-chevron { transform: rotate(90deg); }
.cv-journey-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; min-width: 0; }
.cv-journey-head .cv-feature-subheading { margin: 0; }
.cv-journey-facts { color: var(--cv-muted); font-size: 0.78125rem; }
.cv-journey-body { padding: 0 12px 10px; }
.cv-proof-block { margin: 8px 0 0; }
.cv-proof-none { margin: 8px 0 0; }
.cv-join { border: 1px solid var(--cv-line); border-radius: 6px; font-size: 0.8125rem; }
.cv-join-head, .cv-join-row > summary { display: grid; grid-template-columns: 14px minmax(0, 2fr) minmax(0, 1.4fr) auto;
  gap: 4px 10px; align-items: baseline; padding: 5px 8px; }
.cv-join-head { color: var(--cv-muted); font-size: 0.6875rem; font-weight: 700; border-bottom: 1px solid var(--cv-line); }
.cv-join-row + .cv-join-row { border-top: 1px solid var(--cv-line); }
.cv-join-row > summary { cursor: pointer; list-style: none; }
.cv-join-row > summary::-webkit-details-marker { display: none; }
.cv-join-row > summary::marker { content: ''; }
.cv-join-row > summary:hover { background: #f7f8fb; }
.cv-join-row[open] { padding-bottom: 8px; }
.cv-join-row[open] > :not(summary) { margin: 6px 8px 0; }
.cv-join-name, .cv-join-host { min-width: 0; overflow-wrap: anywhere; }
.cv-join-name code, .cv-join-host { font-size: 0.78125rem; }
.cv-join-count { color: var(--cv-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.cv-evidence-dup-count { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px;
  background: #eef1f6; color: #334155; font-size: 0.6875rem; font-weight: 700; }
.cv-evidence-dup-group { margin-bottom: 8px; }
.cv-evidence-dup-group > .cv-evidence-req { margin-bottom: 0; }
.cv-evidence-dups { margin: 0 0 0 14px; padding: 4px 10px; border-left: 2px solid var(--cv-line); font-size: 0.78125rem; }
.cv-evidence-dup-list { margin: 3px 0 0; padding-inline-start: 1.4em; }
.cv-evidence-dup > summary { cursor: pointer; color: var(--cv-blue); }
.cv-evidence-dup-when { font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .cv-proof-counts { grid-template-columns: minmax(0, 1fr); }
  .cv-join-head { display: none; }
  .cv-join-row > summary { grid-template-columns: 14px minmax(0, 1fr) auto; }
  .cv-join-row > summary .cv-join-host { grid-column: 2 / 4; grid-row: 2; color: var(--cv-muted); }
  .cv-journey-evidence > summary { padding: 8px 10px; }
  .cv-journey-body { padding: 0 8px 8px; }
  .cv-evidence-dups { margin-left: 6px; }
}
/* A jump lands below the sticky bar, not under it. */
.cv-finding-detail-page :is(.cv-type-rec, .cv-finding-cause-card, .cv-finding-legs, .cv-proof-summary,
  .cv-leg-evidence-list, .cv-leg-evidence, .cv-finding-tech, .cv-finding-tier-head, .cv-finding-line) {
  scroll-margin-top: 170px; }
@media (max-width: 640px) {
  /* The breadcrumb is "‹ By finding"; the bar is one line; prev/next stay. */
  .cv-detail-crumbs li:not(.cv-crumb-lens) { display: none; }
  .cv-detail-crumbs li.cv-crumb-lens::before { content: none; }
  .cv-detail-crumbs .cv-crumb-lens a::before { content: "\2039  "; }
  .cv-detail-bar { flex-wrap: nowrap; gap: 6px; padding: 7px 9px; }
  .cv-detail-bar-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cv-detail-bar .cv-detail-pos { display: none; }
  .cv-detail-bar .cv-detail-step-label, .cv-detail-bar .cv-violation .cv-detail-step-label {
    clip-path: inset(50%); height: 1px; width: 1px; overflow: hidden; position: absolute; white-space: nowrap; }
}
.cv-group-optout-gpc { color: #1e40af; }
.cv-group-optout-dns,
.cv-group-optout-attAcceptedCcpaOptOut { color: var(--cv-notice); }
.cv-group-optout-attDenied,
.cv-group-optout-attAccepted { color: var(--cv-ink); }
/* The group's leading severity, as a dot. It replaced a width-encoded bar that
   became a red underline beneath the heading at the mobile breakpoint, where
   the summary turns into a grid and a full-width child drops to the next row.
   The ratio the bar encoded is written out in the count pills beside it. */
.cv-sev-dot { flex: 0 0 10px; }
.cv-sev-dot.sev-high { background: #dc2626; }
.cv-sev-dot.sev-notice { background: #d97706; }
.cv-sev-dot.sev-info { background: #2563eb; }
.cv-sev-dot.sev-none { background: #999; }
.cv-count-pills { display: flex; flex: none; align-items: center; gap: 7px; }
.cv-count-pill { padding: 3px 9px; border-radius: 999px; font-size: 0.78125rem; font-weight: 650; white-space: nowrap; }
.cv-count-high { color: var(--cv-high); background: var(--cv-high-bg); }
.cv-count-muted { color: var(--cv-info); background: var(--cv-info-bg); }
.cv-group-body { padding: 2px 17px 15px; border-top: 1px solid var(--cv-line); }
.cv-evidence-loading { display: inline-flex; align-items: center; gap: 7px; padding: 8px 0; font-size: 0.8125rem; color: var(--cv-info); }
/* An empty evidence panel states why. Muted like the loading line: it is a
   legitimate answer for a journey finding, not a failure. */
.cv-evidence-empty { color: var(--muted, #667); margin: .4rem 0; }

.cv-spinner { width: 14px; height: 14px; border: 2px solid var(--cv-line); border-top-color: var(--cv-info); border-radius: 50%; animation: cv-spin 0.8s linear infinite; }
@keyframes cv-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cv-spinner { animation: none; } }
/* Counsel's journey narrative for the feature (Daniel #7) — steps carry
   meaningful line breaks, so preserve them. */
/* "Process" labels the steps; it is not the first words of them (Israel,
   2026-08-05) — an inline label ran straight into "1. Open the article…". */
.cv-feature-process { margin: 10px 0 4px; padding: 9px 12px; background: var(--cv-info-bg); border-radius: 7px; font-size: 0.875rem; color: var(--cv-ink); }
.cv-feature-process-k { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-faint); margin-bottom: 3px; }
.cv-feature-process-body { white-space: pre-line; line-height: 1.5; }
/* Journeys a generated process names, as a list (Israel, 2026-09-24). */
.cv-feature-process-list { margin: 4px 0 0; padding-inline-start: 1.5em; line-height: 1.5; }
.cv-feature-process-list li + li { margin-top: 2px; }
/* By-finding lens: the legs a deduplicated finding was observed on. ON THE
   CARD'S OWN SCALE (Israel, 2026-09-24): the heading is a section label like
   "Potential root cause", the lines one meta size with the journey told apart
   by weight, and "Evidence" the same inline link as "Technical detail". */
.cv-finding-legs { margin: 10px 0 12px; }
.cv-finding-legs > p, .cv-finding-legs > summary { margin: 0 0 2px; font-size: 0.6875rem;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--cv-faint); }
.cv-finding-legs > summary { cursor: pointer; }
.cv-finding-leg-list { font-size: 0.8125rem; color: var(--cv-faint); }
.cv-finding-leg-list .small { font-size: inherit; }
.cv-finding-leg-name { font-weight: 600; color: var(--cv-ink); }
.cv-finding-leg-link { white-space: nowrap; color: var(--cv-blue); font-size: 0.78125rem;
  font-weight: 650; text-decoration: none; }
.cv-finding-leg-link:hover { text-decoration: underline; }
/* Each feature's process under its line, small and muted (Daniel 2026-09-25:
   "in smallish text to avoid introducing a ton more text"). */
.cv-finding-leg-list .cv-finding-leg-process { margin: 1px 0 4px; font-size: 0.75rem;
  line-height: 1.45; color: var(--cv-faint); }
/* Stat and provenance lines inside a finding ("8284 requests checked: …", the
   request sender) are meta, set like the chips row, not body paragraphs. */
.cv-forwarding-evidence, .cv-request-sender, .cv-evidence-coverage-note {
  margin: 4px 0 6px; font-size: 0.8125rem; line-height: 1.5; color: var(--cv-faint); }
/* "Observed on" (feature lens) is the same kind of statement as the legs list
   above: a section label over meta-sized journey names. */
.cv-observed-on { margin: 6px 0; font-size: 0.8125rem; line-height: 1.5; color: var(--cv-faint); }
.cv-observed-on > p { margin: 0 0 2px; font-size: 0.6875rem; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; }
.cv-observed-on li { color: var(--cv-ink); }
/* The tier heading already names the finding, so the card's title line is
   empty and "Hide this finding from client" stood alone on a row of its own:
   it joins the toolbar's row instead (Israel, 2026-09-24). */
.cv-finding-title:empty { display: none; }
.cv-finding-main:has(> .cv-finding-title:empty):not(:has(> .cv-finding-shared-note)) {
  display: inline-flex; vertical-align: middle; margin-right: 6px; }
.cv-finding-main:has(> .cv-finding-title:empty):not(:has(> .cv-finding-shared-note)) ~ .cv-finding-toolbar:has(*) {
  display: inline-flex; vertical-align: middle; }
/* ...and when there is no control either (the client's card), neither holds a
   line open above the root cause. */
.cv-finding-main:has(> .cv-finding-title:empty):not(:has(> :not(.cv-finding-title))),
.cv-finding-copy > .cv-finding-toolbar:not(:has(*)) { display: none; }
/* THE VALUES WE SEEDED, under the journey they were seeded into. Counsel:
   "tell me what that email address is. Because if I don't know, then I don't
   know what to look for." Inside the process panel so it reads as part of the
   same account of the journey, but separated by a rule because it is OURS and
   the text above it is his — carried verbatim from legacy and not to be
   confused with a value we inserted. */
.cv-feature-seeded { margin-top: 9px; padding-top: 8px;
  border-top: 1px solid rgba(0,0,0,.08); }
.cv-feature-seeded-k { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-muted); margin-bottom: 4px; }
.cv-feature-seeded-list { list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 4px 14px; }
.cv-feature-seeded-list li { display: inline-flex; align-items: baseline; gap: 6px; }
/* The LABEL is the quiet half and the VALUE is what counsel scans for — he is
   looking for the literal string he will meet again in a request. */
.cv-seeded-k { color: var(--cv-muted); font-size: 0.78rem; }
.cv-feature-seeded-list code { color: var(--cv-ink); }
.cv-optout-reasons { margin: 10px 0; font-size: 0.875rem; line-height: 1.5; }
/* A sub-heading per sensitive type inside one feature (counsel, 2026-09-23). */
.cv-feature-subsection { margin: 14px 0 6px; }
.cv-feature-subsection + .cv-feature-subsection { border-top: 1px solid rgba(0,0,0,.08); padding-top: 10px; }
.cv-feature-subheading { margin: 0 0 6px; font-size: 0.8125rem; font-weight: 700;
  letter-spacing: .02em; color: var(--cv-ink); }
.cv-optout-reasons p { margin: 0 0 4px; }
.cv-optout-reasons ul { margin: 0; padding-inline-start: 1.5em; }
.cv-optout-reasons li + li { margin-top: 8px; }
.cv-optout-reason-findings { font-size: 0.8125rem; }

.cv-finding-line { display: flex; align-items: flex-start; gap: 11px; padding: 11px 0; border-bottom: 1px solid #f0f1f4; }
.cv-finding-line.cv-withheld { margin: 4px -8px; padding: 11px 8px; border-radius: 8px; background: var(--cv-withheld-bg); }
.cv-finding-line:last-child { border-bottom: 0; }
.cv-finding-dot { flex: 0 0 8px; width: 8px; height: 8px; margin-top: 7px; border-radius: 50%; background: var(--cv-faint); }
.cv-finding-line.sev-high .cv-finding-dot { background: var(--cv-high); }
.cv-finding-line.sev-notice .cv-finding-dot { background: var(--cv-notice); }
.cv-finding-line.sev-info .cv-finding-dot { background: var(--cv-faint); }
.cv-journey-group .cv-finding-dot { background: var(--cv-blue); }
/* The grade and its colour are one thing, wherever they sit. */
.cv-finding-severity { display: inline-flex; align-items: center; gap: 5px; }
.cv-finding-severity .cv-finding-dot { margin-top: 0; }
.cv-finding-severity.sev-high .cv-finding-dot { background: var(--cv-high); }
.cv-finding-severity.sev-notice .cv-finding-dot { background: var(--cv-notice); }
.cv-finding-severity.sev-info .cv-finding-dot { background: var(--cv-faint); }
/* ...so the card beneath a collapsed finding does not repeat it. The card's
   own indent came from this dot plus its gap, so replace it with padding. */
.cv-org-body .cv-finding-line > .cv-finding-dot { display: none; }
.cv-org-body .cv-finding-line { padding-left: 19px; }
.cv-finding-copy { flex: 1; min-width: 0; }
/* WRAPS, because the header holds three things — title, visibility controls and
   the shared-plan note — and the note is a paragraph, not a button. On one
   unwrapped flex row the note was laid out as a third column and painted across
   the "Hide this finding from client" button (Israel, 2026-09-17 07:23 EDT,
   screenshot). The note takes the full width of its own line beneath the
   controls. */
.cv-finding-main { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 6px 12px; }
.cv-finding-main > .cv-finding-shared-note { flex-basis: 100%; }
/* Matches .cv-finding-tier-headline: the collapsed heading and the card
   title name the SAME finding, so they must not differ in weight. */
.cv-finding-title { flex: 1; min-width: 0; color: var(--cv-ink); font-size: 0.90625rem; font-weight: 450; line-height: 1.45; }
.cv-headline-domain-class { color: var(--cv-muted); font-weight: 500; }
.cv-finding-severity { margin-left: 5px; color: var(--cv-muted); font-size: 0.6875rem; font-weight: 650; white-space: nowrap; }
.cv-attorney-edit-tag {
  display: inline-flex; margin-left: 6px; padding: 2px 6px; border-radius: 999px;
  background: #eef1ff; color: #3549a3; font-size: 0.625rem; font-weight: 700;
  letter-spacing: .025em; line-height: 1.4; white-space: nowrap;
}
.cv-client-hidden-tag {
  display: inline-flex; margin-left: 6px; padding: 2px 6px; border-radius: 999px;
  background: #fff1e8; color: #9a3412; font-size: 0.625rem; font-weight: 700;
  letter-spacing: .025em; line-height: 1.4; white-space: nowrap;
}
.cv-optout-attribution-tag {
  display: inline-flex; margin-left: 6px; padding: 2px 6px; border-radius: 999px;
  background: #edf7f6; color: #16645f; font-size: 0.625rem; font-weight: 700;
  letter-spacing: 0; line-height: 1.4; white-space: nowrap;
}
/* Staff only: counsel's edit is saved; the publication clients read has not
   caught up yet. Quiet (neutral, not an alert colour): nothing is wrong. */
.cv-pending-publish-tag { background: #f1f2f5; color: #4b5263; font-weight: 600; white-space: normal; }
.cv-staff-pending-publish {
  margin: 8px 0 12px; padding: 6px 10px; border-radius: 6px; background: #f1f2f5;
  color: #4b5263; font-size: 0.8125rem; line-height: 1.4;
}
/* Under the title on the left, not opposite it (Israel, 2026-08-05): pushed
   to the right edge they sat level with the headline and read as belonging to
   the row's counts rather than to the finding. */
/* A finding-wide hide is destructive at the row grain, so it sits in the
   finding header with wording that names that grain. It is deliberately not in
   the captured-request toolbar, where "Withhold this request" lives. */
.cv-finding-visibility-actions { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 6px 0 1px; }
/* ONE ROW OF NON-VISIBILITY CONTROLS (Israel, 2026-09-15: "can we fix the
   formatting in this area?"). The toolbar lays the remaining operator groups
   out on one wrapping line; visibility moved to the header because it writes a
   broader grain than the request-card controls below. */
.cv-finding-toolbar { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 7px 0 2px; }
.cv-finding-toolbar > * { margin: 0; }
.cv-finding-actions { display: inline-flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 4px 0 2px; }
.cv-finding-edit, .cv-finding-visibility, .cv-attribution-correct,
.cv-domain-class-correct {
  display: inline-flex; flex: none; align-items: center; gap: 4px; padding: 3px 7px;
  border: 1px solid #7b8495; border-radius: 6px; background: #fff;
  min-height: 24px; color: var(--cv-blue); font-size: 0.6875rem; font-weight: 650; line-height: 1.3;
}
.cv-finding-edit:hover, .cv-finding-visibility:hover, .cv-attribution-correct:hover,
.cv-domain-class-correct:hover { border-color: var(--cv-blue); background: #f7f8ff; }
.cv-finding-visibility { color: #9a3412; }
.cv-finding-actions button:disabled, .cv-attribution-actions button:disabled,
.cv-attribution-editor button:disabled, .cv-domain-class-actions button:disabled,
.cv-domain-class-editor button:disabled,
.cv-domain-class-editor select:disabled { opacity: .55; cursor: wait; }
.cv-attribution-actions { display: inline-flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 4px 0 2px; }
.cv-attribution-correct { color: #315f3d; }
.cv-domain-class-actions { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 4px 0 2px; }
.cv-domain-class-actions-inline { display: inline-flex; margin: 0 0 0 5px; }
.cv-host-with-category { display: inline-flex; flex-wrap: wrap; align-items: center;
  gap: 5px; margin-right: 4px; }
.cv-domain-class-correct { color: #4f46e5; }

/* PER-REQUEST OPERATOR CONTROLS. Inside a captured-request card, so they sit
   below the request they act on and are visually subordinate to it — the card
   is evidence, these are our marks on it. */
.cv-request-actions { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 7px 0 1px; padding-top: 6px; border-top: 1px dashed #dbe3ec; }
.cv-request-actions .cv-attribution-actions-inline,
.cv-request-actions .cv-domain-class-actions-inline { margin: 0; }
.cv-request-visibility-actions { display: inline-flex; flex-wrap: wrap;
  align-items: center; gap: 5px; }
.cv-request-withhold, .cv-request-restore,
.cv-host-requests-withhold, .cv-host-requests-restore {
  display: inline-flex; flex: none; align-items: center; gap: 4px; padding: 3px 7px;
  border: 1px solid #7b8495; border-radius: 6px; background: #fff;
  min-height: 24px; color: #9a3412; font-size: 0.6875rem; font-weight: 650; line-height: 1.3;
}
.cv-request-withhold:hover, .cv-request-restore:hover,
.cv-host-requests-withhold:hover, .cv-host-requests-restore:hover {
  border-color: var(--cv-blue); background: #f7f8ff; }
.cv-request-withhold:disabled, .cv-request-restore:disabled,
.cv-host-requests-withhold:disabled, .cv-host-requests-restore:disabled { opacity: .55; cursor: wait; }
.cv-request-withheld-marker {
  display: inline-flex; padding: 2px 6px; border-radius: 999px;
  background: #fee2e2; color: #991b1b; font-size: 0.625rem; font-weight: 700;
  letter-spacing: .025em; line-height: 1.4; text-transform: uppercase;
}
.cv-request-visibility-status:not(:empty), .cv-request-withheld-error:not(:empty),
.cv-host-request-status:not(:empty) {
  color: #9a3412; font-size: 0.6875rem; }
.cv-host-request-actions { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin: 0 0 8px; }
.cv-request-withheld { margin: 0 0 10px; padding: 8px 10px;
  border: 1px solid #e7cfa8; border-radius: 8px; background: #fdf8ef; }
.cv-request-withheld-list { margin: 4px 0 0; padding-left: 0; list-style: none; }
.cv-request-withheld-group { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin-bottom: 4px; font-size: 0.75rem; }
.cv-request-withheld-count { font-weight: 700; }
.cv-request-withheld-lapse { margin: 6px 0 0; color: #7c2d12; font-size: 0.75rem; }
/* STAFF ONLY: a withhold or hide that reaches other findings asks first
   (shared-withhold.js). Warned in the same amber as the withheld panel beside
   it, not styled as an error: nothing has gone wrong yet, the write is wider
   than the control it came from. */
.cv-shared-withhold { flex-basis: 100%; margin: 6px 0 4px; padding: 8px 10px;
  border: 1px solid #e7cfa8; border-radius: 8px; background: #fdf8ef;
  color: #5b3a0e; font-size: 0.75rem; line-height: 1.45; }
.cv-shared-withhold-lead, .cv-shared-withhold-consequence { margin: 0; }
.cv-shared-withhold-list { max-height: 14em; overflow: auto; margin: 4px 0; padding-left: 18px; }
.cv-shared-withhold-list li { margin: 1px 0; overflow-wrap: anywhere; }
.cv-shared-withhold-feature { color: var(--cv-muted); }
.cv-shared-withhold-flag { font-weight: 700; }
.cv-shared-withhold-flag.is-last { color: #991b1b; }
.cv-shared-withhold-flag.is-hidden { color: var(--cv-muted); font-weight: 600; }
.cv-shared-withhold-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.cv-shared-withhold-go, .cv-shared-withhold-cancel {
  display: inline-flex; align-items: center; min-height: 24px; padding: 3px 9px;
  border: 1px solid #7b8495; border-radius: 6px; background: #fff;
  font-size: 0.6875rem; font-weight: 650; line-height: 1.3; }
.cv-shared-withhold-go { border-color: #9a3412; background: #9a3412; color: #fff; }
.cv-shared-withhold-cancel { color: var(--cv-muted); }
/* STAFF ONLY: bulk changes over the findings ticked "Select" (Daniel,
   2026-09-26). Quiet until something is selected; sticky so it stays in reach
   while the reader ticks down a long feature list. */
.cv-bulk-bar { position: sticky; top: 0; z-index: 3; display: flex; flex-wrap: wrap;
  align-items: center; gap: 6px 10px; margin: 8px 0; padding: 6px 10px;
  border: 1px dashed #c7ccd6; border-radius: 8px; background: var(--cv-surface, #fff);
  color: var(--cv-muted); font-size: 0.75rem; }
.cv-bulk-bar.has-selection { border-style: solid; border-color: #7b8495; color: inherit; }
.cv-bulk-count { font-weight: 700; }
.cv-bulk-priority-label { display: inline-flex; align-items: center; gap: 4px; }
.cv-bulk-bar select, .cv-bulk-bar button { min-height: 24px; font-size: 0.75rem; }
.cv-bulk-bar > button:not(.linklike) { padding: 3px 9px; border: 1px solid #7b8495;
  border-radius: 6px; background: #fff; font-weight: 650; cursor: pointer; }
.cv-bulk-bar > button:disabled { opacity: 0.55; cursor: default; }
.cv-bulk-status { flex-basis: 100%; margin: 0; }
.cv-bulk-status:empty { display: none; }
.cv-bulk-pick { display: inline-flex; align-items: center; gap: 3px; color: var(--cv-muted);
  font-size: 0.6875rem; cursor: pointer; }
.cv-domain-class-correct-inline { padding-inline: 6px; }
.cv-domain-class-editor, .cv-attribution-editor { display: flex; flex-wrap: wrap;
  align-items: end; gap: 8px; margin: 5px 0 7px; padding: 8px 9px;
  border: 1px solid var(--cv-line); border-radius: 8px; background: #f7faf8; }
.cv-attribution-editor label, .cv-domain-class-editor label { display: flex; flex-direction: column; gap: 3px;
  min-width: min(100%, 230px); color: var(--cv-info); font-size: 0.6875rem;
  font-weight: 700; }
.cv-attribution-editor select, .cv-domain-class-editor select { min-height: 30px; max-width: 100%;
  border: 1px solid var(--cv-line); border-radius: 6px; background: #fff;
  color: var(--cv-ink); font-size: 0.8125rem; }
.cv-attribution-editor-actions, .cv-domain-class-editor-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.cv-attribution-editor-actions button, .cv-domain-class-editor-actions button { min-height: 30px; padding: 4px 9px;
  border: 1px solid var(--cv-blue); border-radius: 6px; background: var(--cv-blue);
  color: #fff; font-size: 0.75rem; font-weight: 700; }
.cv-attribution-editor-actions .cv-attribution-cancel,
.cv-domain-class-editor-actions .cv-domain-class-cancel { border-color: #7b8495;
  background: #fff; color: var(--cv-muted); }
.cv-attribution-status, .cv-domain-class-status,
.cv-domain-class-editor-error { min-height: 1.2em; margin: 0; color: #a93226;
  font-size: 0.75rem; }
.cv-attribution-status:empty, .cv-domain-class-status:empty,
.cv-domain-class-editor-error:empty { display: none; }
.cv-finding-detail { margin-top: 1px; color: var(--cv-muted); font-size: 0.8125rem; line-height: 1.45; }
/* Beside the hide control, because the reader is deciding about two journeys
   at the moment they press it — one finding is stored for both treatments of a
   plan (findingKey carries no treatment), so a hide taken on the opted-out
   journey also removes it from the control. Warned, not styled as an error:
   nothing has gone wrong, the scope is simply wider than the heading above it. */
.cv-finding-shared-note { margin: 2px 0 4px; color: #8a5a13; font-size: 0.75rem;
  line-height: 1.45; }
.cv-finding-visibility-error { margin: 5px 0 0; color: #a93226; font-size: 0.75rem; }
.cv-finding-visibility-error:empty { display: none; }
.cv-hidden-group { border-color: #e8cdbf; background: #fffaf7; }
.cv-hidden-group > summary { background: #fff7f2; }
.cv-finding-tech { margin-top: 5px; }
.cv-finding-tech > summary { display: inline-block; padding: 2px 0; list-style: none; cursor: pointer; color: var(--cv-blue); font-size: 0.78125rem; font-weight: 650; }
.cv-finding-tech > summary::-webkit-details-marker { display: none; }
.cv-finding-tech > summary::marker { content: ''; }
.cv-tech-panel { margin-top: 7px; padding: 9px 11px; border: 1px solid var(--cv-line); border-radius: 8px; background: #f7f8fa; color: var(--cv-muted); font-size: 0.78125rem; }
.cv-tech-list { display: flex; flex-direction: column; gap: 7px; margin: 0; }
.cv-tech-list > div { display: grid; grid-template-columns: minmax(90px, 112px) minmax(0, 1fr); gap: 8px; }
.cv-tech-list dt { color: var(--cv-info); font-weight: 650; }
.cv-tech-list dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
.cv-tech-list code { display: inline-block; margin: 1px 3px 1px 0; padding: 1px 5px; border-radius: 4px; background: #eceef2; color: #334; font-family: var(--font-mono); font-size: 0.75rem; }
.cv-tech-list a { color: var(--cv-blue); text-decoration: underline; text-underline-offset: 2px; }
.cv-tech-flag { margin-top: 8px; color: var(--cv-high); font-weight: 650; }
.cv-tech-panel .cv-remed { margin: 10px 0 0; }
/* SCOPED TO THE TOOLBAR so `.cv-row` and `.cv-tech-panel` keep the pill they
   already had. In the toolbar it sits beside .cv-finding-edit and must match it
   or the row reads as two different kinds of thing: same height, same radius,
   same type size, and no left margin of its own (the toolbar owns the gap). */
.cv-finding-toolbar .cv-remed { margin-left: 0; padding: 3px 7px; min-height: 24px;
  border-radius: 6px; font-size: 0.6875rem; font-weight: 650; line-height: 1.3; }
/* A status line is a whole row when it has something to say, and nothing at all
   when it does not -- an empty <p> between two buttons was breaking the row. */
.cv-finding-toolbar .cv-remed-status,
.cv-finding-toolbar .cv-attribution-status { flex-basis: 100%; margin: 0; }
.cv-finding-toolbar .cv-remed-status:empty,
.cv-finding-toolbar .cv-attribution-status:empty { display: none; }

/* A RULE BETWEEN FINDINGS (Israel, 2026-09-15: "right above that is where the
   divider ... was meant to go"). Now that a finding renders expanded rather than
   collapsed behind a summary, consecutive findings run together -- one
   finding's controls sit directly above the next one's headline with nothing
   saying where the first ended. The rule goes above every finding after the
   first, so it separates without drawing a box around anything. */
.cv-finding-tier + .cv-finding-tier { margin-top: 12px; padding-top: 12px;
  border-top: 1px solid rgba(0,0,0,.09); }
.cv-finding-line:has(.cv-remed.is-remediated) { opacity: .62; }
.cv-finding-line:has(.cv-client-hidden-tag) { opacity: .72; }
.cv-request-class { margin: 4px 0; font-size: 0.8125rem; }
.cv-finding-editor {
  display: grid; gap: 10px; padding: 12px; border: 1px solid #cbd3f5;
  border-radius: 9px; background: #f7f8ff;
}
.cv-finding-editor label {
  display: grid; gap: 4px; color: var(--cv-navy); font-size: 0.75rem; font-weight: 700;
}
.cv-finding-editor textarea {
  box-sizing: border-box; width: 100%; min-height: 82px; padding: 9px 10px;
  resize: vertical; border: 1px solid #7b8495; border-radius: 7px; background: #fff;
  color: var(--cv-ink); font: inherit; font-size: 0.8125rem; line-height: 1.45;
}
.cv-finding-editor textarea:focus { border-color: var(--cv-blue); }
.cv-finding-editor-actions { display: flex; align-items: center; gap: 8px; }
.cv-finding-editor-actions button {
  padding: 6px 11px; border: 1px solid transparent; border-radius: 7px;
  font-size: 0.75rem; font-weight: 700;
}
.cv-finding-save { background: var(--cv-navy); color: #fff; }
.cv-finding-save:hover { background: #22375f; }
.cv-finding-editor-actions .cv-finding-cancel { border-color: #7b8495; background: #fff; color: var(--cv-muted); }
.cv-finding-editor-actions button:disabled { opacity: .55; cursor: wait; }
.cv-finding-editor-error { min-height: 1.2em; margin: 0; color: #a93226; font-size: 0.75rem; }
.cv-findings-note { margin-top: 20px; color: var(--cv-muted); font-size: 0.78125rem; text-align: center; }



.cv-report-unavailable {
  display: block; margin-top: 22px; padding: 18px; border: 1px solid var(--cv-line);
  border-radius: 12px; background: var(--card); box-shadow: var(--cv-shadow); text-align: left;
}
.cv-report-unavailable .marker { color: var(--cv-notice); font-size: 0.75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.cv-report-unavailable .msg { margin-top: 5px; color: var(--cv-muted); line-height: 1.55; }
.cv-report-unavailable .msg b { color: var(--cv-navy); }
.cv-measurement-note { margin: 16px 0 24px; padding: 16px 20px; border-left: 3px solid var(--cv-notice); background: var(--card); color: var(--cv-navy); line-height: 1.55; }
.cv-measurement-note p { margin: 0 0 12px; }
.cv-measurement-note p:last-child { margin-bottom: 0; }
.cv-measurement-note h3 { margin: 16px 0 8px; font-size: 1rem; }
.cv-measurement-note li { margin: 12px 0; }
.cv-measurement-note summary { cursor: pointer; }
.cv-measurement-note details p { margin-top: 8px; white-space: pre-wrap; overflow-wrap: anywhere; }


/* Operator's client switcher — a visible bar at the top of the report, not buried. */
.cv-clientbar{display:flex;align-items:center;gap:10px;margin:0 0 16px;padding:9px 13px;
  background:#fff;border:1px solid #e4e7ec;border-radius:12px;box-shadow:0 1px 2px rgba(16,24,40,.04)}
.cv-clientbar .cv-proj{display:flex;align-items:center;gap:9px;margin:0}
.cv-clientbar select{font:inherit;font-weight:600;color:#16233d;padding:8px 11px;border:1px solid #cfd3da;
  border-radius:9px;background:#fff;min-width:230px;cursor:pointer}
.cv-clientbar select:focus-visible{outline:2px solid #3b5bdb;outline-offset:1px}

.cv-report-scope {
  margin: 0 0 24px; padding: 18px; border: 1px solid var(--cv-line);
  border-radius: 12px; background: var(--card); box-shadow: var(--cv-shadow);
}
.cv-scope-head { display: flex; justify-content: space-between; gap: 16px; margin-bottom: 15px; }
.cv-scope-head h2 { margin: 0; color: var(--cv-navy); font-size: 1rem; line-height: 1.3; }
.cv-scope-head p { margin: 4px 0 0; color: var(--cv-muted); font-size: 0.8125rem; line-height: 1.45; }
.cv-scope-actions { display: flex; align-items: center; gap: 12px; margin-top: 15px; }
.cv-scope-actions .btn { flex: 0 0 auto; }
.cv-report-details {
  margin-top: 42px; border-top: 1px solid var(--cv-line); color: var(--cv-muted);
}
.cv-report-details > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 16px 0; cursor: pointer; color: var(--cv-navy); font-size: 0.875rem; font-weight: 650;
}
.cv-details-hint { color: var(--cv-muted); font-size: 0.75rem; font-weight: 500; }
.cv-report-details-body { padding: 2px 0 8px; }
.cv-report-details .cv-legend { margin: 0 0 10px; }
.cv-report-details .cv-replay { margin-top: 16px; }
/* Methodology & definitions (the once-empty section the 2026-07-31 audit
   flagged). Quiet reference styling: the report above stays the headline. */
.cv-details-section { margin: 14px 0 0; max-width: 72ch; }
.cv-details-section h3 { margin: 0 0 4px; font-size: 0.8125rem; font-weight: 650;
  color: var(--cv-navy); }
.cv-details-section p, .cv-details-section li { font-size: 0.8125rem;
  line-height: 1.6; color: var(--cv-muted); }
.cv-details-section ul { margin: 4px 0; padding-left: 18px; }
.cv-details-section li { margin: 2px 0; }

.cv-client-bar :is(a, button):focus-visible,
.cv-report :is(a, button, summary, input, select, textarea):focus-visible,
.cv-report-scope :is(button, summary, input, select):focus-visible,
.cv-scope-head h2:focus-visible,
.cv-report-details :is(a, button, summary, input, select):focus-visible {
  outline: 3px solid var(--cv-blue); outline-offset: 2px;
}

@media (max-width: 900px) {
  .cv-scope-bar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cv-scope-field .cv-multisel-body { right: auto; left: 0; }
  .cv-scope-field:nth-child(even) .cv-multisel-body { right: 0; left: auto; }
}

@media (max-width: 640px) {
  .cv-client-bar { align-items: flex-start; flex-direction: column; gap: 10px; }
  .cv-client-bar .cv-account { white-space: normal; }
  .cv-report-head { flex-direction: column; }
  .cv-report-actions { justify-content: flex-start; }
  .cv-report-head h1 { font-size: 1.45rem; }
  .cv-report .cv-verdict { font-size: 1.125rem; }
  .cv-tiles { grid-template-columns: 1fr; }
  .cv-finding-group > summary { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px 11px; }
  .cv-group-chevron { grid-column: 1; grid-row: 1; }
  .cv-group-title { grid-column: 2; grid-row: 1; }
  .cv-count-pills { grid-column: 2; flex-wrap: wrap; }
  .cv-tech-list > div { grid-template-columns: 1fr; gap: 1px; }
  .cv-details-hint { display: none; }
  .cv-report-scope { padding: 15px; }
  .cv-scope-bar { grid-template-columns: 1fr; }
  .cv-scope-field, .cv-scope-field .cv-multisel { width: 100%; min-width: 0; }
  .cv-scope-field .cv-multisel-body { right: auto; left: 0; width: 100%; min-width: 0; }
  .cv-scope-actions { align-items: flex-start; flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
  .operator-handoff-panel { animation: none; }
  .cv-group-chevron { transition: none; }
  .pill.human-needed,
  .mc-dot { animation: none; }
}

/* Captured-request evidence (client report Technical detail) + kind filter */
.cv-evidence { margin: 8px 0 4px; }
.cv-evidence-btn { font-size: 12px; font-weight: 600; padding: 3px 10px; border-radius: 999px; border: 1px solid #cbd5e1; background: #fff; color: #475569; cursor: pointer; }
.cv-evidence-btn:hover { border-color: #94a3b8; }
.cv-evidence-btn:disabled { opacity: .55; cursor: default; }
.cv-evidence-out { margin-top: 6px; }
.cv-remed-status { margin: 8px 0 4px; color: var(--cv-high); font-size: 0.8125rem; line-height: 1.4; }
/* MARK REVIEWED, beside Hide. Deliberately quieter than the visibility
   controls: hiding changes what the client sees, reviewing changes only what
   the reviewer still owes himself, so it must not compete for the same
   attention. The checked state is the one worth reading at a glance, because
   scanning for what is NOT yet marked is the whole point of the queue.
   Quieter by COLOUR, not by size: at 0.8125rem it stood larger than every
   button beside it (Israel, 2026-09-24, normalising the card's type scale). */
.cv-finding-reviewed { border: 1px solid var(--cv-line); background: #fff;
  color: var(--cv-muted); border-radius: 6px; padding: 3px 7px; min-height: 24px;
  font-size: 0.6875rem; font-weight: 650; line-height: 1.3; cursor: pointer; }
.cv-finding-reviewed:hover:not(:disabled) { border-color: #94a3b8; }
.cv-finding-reviewed:disabled { opacity: .55; cursor: default; }
.cv-finding-reviewed.is-reviewed { border-color: #86c79a; background: #f2faf5;
  color: #1d6b3a; font-weight: 600; }
.cv-finding-reviewed-status { margin: 6px 0 0; color: var(--cv-high);
  font-size: 0.8125rem; line-height: 1.4; }
.cv-finding-reviewed-status:empty { display: none; }
/* THE REVIEW QUEUE TOGGLE. An operator control on a client-facing page, so it
   sits with the filter tools and reads as a filter rather than as a verdict —
   it changes what the READER is looking at, never what the report says. Loud
   when on, because a reader who forgets it is on is looking at a subset and
   would have no other way to tell. */
.cv-unreviewed-toggle { border: 1px solid var(--cv-line); background: #fff;
  color: var(--cv-muted); border-radius: 999px; padding: 4px 12px;
  font-size: 0.8125rem; cursor: pointer; white-space: nowrap; }
.cv-unreviewed-toggle:hover { border-color: #94a3b8; }
.cv-unreviewed-toggle.is-on { background: var(--cv-navy); border-color: var(--cv-navy);
  color: #fff; font-weight: 600; }
.cv-remed-status:empty { display: none; }
/* WHERE ONE REQUEST ENDS AND THE NEXT BEGINS.
   Counsel, reviewing the detail page: "when you're scrolling, there is no way I
   can figure out when the next finding begins… I need some space in between",
   and again on 2026-09-08 that the cards still need more differentiation. An
   8px gap between two pale boxes of monospace is not a boundary at speed, so:
   a real gap, a left rule that runs the height of the card, and a host name
   that reads as a heading rather than as the first line of the body. */
.cv-evidence-req { border: 1px solid #dbe3ec; border-left: 3px solid #94a3b8;
  border-radius: 8px; padding: 10px 12px; margin-bottom: 16px; background: #f8fafc; }
.cv-evidence-req:last-child { margin-bottom: 0; }
.cv-evidence-req > summary { cursor: pointer; list-style: none; }
/* The disclosure marker the summary suppressed. Without it a collapsed request
   reads as a static block: counsel could not tell the cards opened at all.
   Same glyph and rotation as .cv-group-chevron so the affordance is learned
   once. Positioned on its own line so the host heading below keeps its full
   width and its underline. */
.cv-evidence-req > summary { display: flex; gap: 8px; align-items: baseline; }
/* The summary's own column, so the chevron sits beside the whole block rather
   than only beside its first line. */
.cv-evidence-summary-body { flex: 1 1 auto; min-width: 0; }
.cv-evidence-req > summary .cv-evidence-matched { margin-top: 4px; }
.cv-evidence-chevron { flex: none; color: var(--cv-faint); font-size: 0.75rem;
  transition: transform .15s ease; }
.cv-evidence-req[open] > summary .cv-evidence-chevron { transform: rotate(90deg); }
.cv-evidence-req > summary > .cv-evidence-request-host { flex: none; }
.cv-evidence-req > summary .cv-evidence-line { flex: 1 1 auto; min-width: 0; }
@media (prefers-reduced-motion: reduce) { .cv-evidence-chevron { transition: none; } }
.cv-evidence-req > summary::-webkit-details-marker { display: none; }
.cv-evidence-req > summary::marker { content: ''; }
.cv-evidence-req code { display: block; white-space: pre-wrap; word-break: break-all; font-size: 11.5px; line-height: 1.55; background: transparent; color: #16202c; }
/* The host is the answer to "who received this", so it heads the card instead
   of sitting in it: larger than the request line beneath it, and separated by a
   hairline so the eye stops there on the way down. */
.cv-evidence-request-host { display: block; margin: 0 0 6px; padding-bottom: 5px;
  font-size: 0.9375rem; line-height: 1.3; color: var(--cv-ink);
  border-bottom: 1px solid #e6ebf1; }
.cv-evidence-request-host strong { font-weight: 700; letter-spacing: -0.01em; }
.cv-evidence-request-class { color: var(--cv-muted); font-weight: 500; }
/* Collapsed cards carry the host in the summary, where the hairline would sit
   between the host and the request line on the SAME row. */
.cv-evidence-req > summary .cv-evidence-request-host {
  border-bottom: 0; padding-bottom: 0; margin-bottom: 2px; }
.cv-evidence-line { margin-bottom: 4px; }
.cv-evidence-req > summary .cv-evidence-line { display: block; margin-bottom: 0; }
/* The match information now sits ABOVE the request line (counsel, 2026-09-23). */
.cv-evidence-matched ~ .cv-evidence-line, .cv-evidence-role ~ .cv-evidence-line { margin-top: 8px; }
.cv-evidence-req-body { margin-top: 6px; }
.cv-evidence-status { color: #64748b; font-size: 11.5px; }
.cv-evidence-part { margin-top: 6px; }
/* A legacy finding shows its OWN captured request first, then the requests
   behind the other hosts its record rolls up. Separated so the second block
   cannot read as more of the first. */
/* Per-host breakdown of a set: who received how many requests, read at a
   glance instead of as one blended count. */
/* A host in a finding's list is a control that routes to that host's requests. */
.cv-type-host.cv-host-jump { cursor: pointer; border: 0; padding: 0; background: none;
  font: inherit; text-align: left; }
.cv-type-host.cv-host-jump:hover code,
.cv-type-host.cv-host-jump:focus-visible code { background: rgba(37,99,235,.12);
  text-decoration: underline; }
/* Brief highlight on the host the reader was routed to, so the jump is visible. */
.cv-evidence-host.cv-host-hit { background: rgba(250,204,21,.45);
  transition: background .4s ease; }
/* Shown when a rendered body/URL is not the whole capture. */
.cv-evidence-truncated { margin: 3px 0; font-size: 0.75rem; color: var(--cv-notice, #b45309);
  font-style: italic; }
/* Each host group in the evidence drawer is its own unit of reading -- "20
   requests to bounceexchange.com" opens a NEW claim, and with no top margin its
   heading sat flush against the previous group's last request card, reading as
   a caption on the wrong group (Israel, 2026-09-10 screenshot). Headroom above,
   none needed below: the group's own cards follow immediately. */
/* The request that DID carry the opt-out signal is the most probative card in
   a mixed set -- the site passing the visitor's choice downstream. Green accent
   = compliance evidence, visible while collapsed via the chip. */
.cv-evidence-req--carried { border-left: 3px solid #2e7d32; background: #f4faf4; }
.cv-evidence-req.cv-withheld { background: var(--cv-withheld-bg); border-color: #f5b5b5; }
.cv-evidence-carried-chip {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  border-radius: 9px; font-size: 11px; font-weight: 600;
  background: #e2f2e2; color: #1e5b22; white-space: nowrap;
}
.cv-evidence-set { margin-top: 22px; }
.cv-evidence-set:first-child { margin-top: 8px; }
.cv-evidence-set-head { margin-bottom: 4px; }

/* WHERE ONE RECIPIENT ENDS AND THE NEXT BEGINS.
   Counsel's complaint about the detail page was navigational, not aesthetic:
   "when you're scrolling, there is no way I can figure out when the next
   finding begins… I need some space in between". The request cards below got
   their rule and their gap for that reason. On 2026-09-15 compound evidence was
   regrouped from hostname to ORGANISATION, which put a THIRD level into the
   same scroll — recipient, then host, then request — and shipped it with no
   styling at all, so a nine-recipient finding rendered as one undifferentiated
   column. That is the same defect made worse, on the same page, by the change
   meant to help.
   The three levels are deliberately not equal weight. A recipient is the thing
   the finding makes its claim about, so it carries the heaviest boundary; a
   host is where the claim was observed, so it is indented and lighter; a
   request is already a card. Read at speed the page should say party, then
   endpoint, then evidence, without anyone having to parse the text to find out
   which they are looking at. */
.cv-evidence-recipient-group { margin-top: 28px; padding-top: 16px;
  border-top: 2px solid #cbd5e1; }
.cv-evidence-recipient-group:first-child { margin-top: 10px; padding-top: 0;
  border-top: 0; }
.cv-evidence-recipient-group > .cv-evidence-set-head { font-size: 1rem;
  margin-bottom: 2px; }
.cv-evidence-feature-group { margin-top: 24px; padding-top: 14px;
  border-top: 2px solid #cbd5e1; }
.cv-evidence-feature-group:first-child { margin-top: 10px; padding-top: 0;
  border-top: 0; }
.cv-evidence-feature-group > .cv-evidence-set-head { font-size: 1rem;
  margin-bottom: 2px; }
/* The host list sits INSIDE its recipient, so it is indented against the rule
   above and gets a lighter one of its own. Without the indent the two headings
   read as siblings and the grouping argues with itself. */
.cv-evidence-host-block { margin-top: 14px; padding-left: 12px;
  border-left: 2px solid var(--cv-line); }
.cv-evidence-host-block:first-of-type { margin-top: 10px; }
.cv-evidence-set-subhead { margin-bottom: 6px; color: var(--cv-faint);
  font-size: 0.8125rem; }
/* The host NAME stays readable at full strength; only the label beside it is
   muted, or the thing a reader is scanning for is the faintest text on screen. */
.cv-evidence-set-subhead code { color: var(--cv-ink, inherit); }
.cv-evidence-hosts { display: flex; flex-wrap: wrap; gap: 4px 6px; margin: 6px 0; }
.cv-evidence-host { display: inline-flex; align-items: baseline; gap: 4px;
  padding: 1px 6px; border-radius: 4px; background: rgba(0,0,0,.05); font-size: 0.8125rem; }
.cv-evidence-host-n { font-variant-numeric: tabular-nums; font-weight: 700;
  color: var(--cv-faint); }
.cv-evidence-exact { margin-bottom: 10px; }
.cv-evidence-also { padding-top: 8px; border-top: 1px solid rgba(0,0,0,.08); }
.cv-evidence-k { display: block; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: #64748b; margin-bottom: 2px; }
mark.cv-hit { background: #fde047; color: inherit; padding: 0 1px; border-radius: 2px; font-weight: 700; }
.cv-kind-filter { margin-left: 4px; }
/* The opt-out modifier is a predicate over the categories, not one of them,
   so it wraps onto its own line instead of trailing the chip row. */
.cv-organize-break { flex: 0 0 100%; height: 0; margin: 0; }
/* Finding tier: the unit a client actually reads, headed by the finding's own
   headline rather than a bare recipient name (a collapsed finding can span
   several real recipients, and naming the tier after just one of them read as
   a claim about all of it — Israel, 2026-07-29). Collapsed by default — 68
   organisations over 206 hosts, all expanded, produced a 17,000px page in
   which the structure was invisible. The summary carries what happened, how
   much, and over how many hosts, which is enough to decide whether to open it. */
/* Detection-category tier. This had NO css at all, so it drew the browser's
   native disclosure triangle next to its own chevron — two arrows on every
   category. Invisible until the lens reached the client site. */
.cv-type-group > summary { display: flex; align-items: baseline; gap: 8px; cursor: pointer;
  padding: 6px 0; list-style: none; }
.cv-type-group > summary::-webkit-details-marker { display: none; }
.cv-type-group > summary::marker { content: ''; }
.cv-type-group[open] > summary .cv-group-chevron { transform: rotate(90deg); }
/* The category ("Opt-out signal ignored") is the heading its findings sit
   under, and had no weight of its own — it inherited, so it read as a sibling
   of the rows beneath it (Israel, 2026-08-05). Between the feature group above
   (750) and the finding headlines below (450), so the three levels step down
   rather than compete. */
.cv-type-name { flex: 1; min-width: 0; color: var(--cv-ink); font-size: 0.9375rem;
  font-weight: 700; line-height: 1.4; }

/* Findings sit INDENTED under their detection-category heading ("Personal
   data leaked to recipient"), so the category reads as their parent rather
   than as a sibling label. 16px puts a finding's chevron just past the
   category name's first character (Israel, 2026-07-29 — more indented, not
   less). The category itself keeps the group body's own 17px. */
.cv-type-body { padding-left: 16px; }
/* THE FINDING HEAD IS NOT A CONTROL (Israel, 2026-09-15: "we don't need an
   expander/closer on the inner level"). It was a <summary>: a pointer cursor, a
   chevron, and a click target that swallowed clicks aimed at the buttons in it.
   Now a plain row.

   `align-items: baseline` put every badge on the headline's text baseline, which
   reads well when they are all text and badly once chips, a severity dot and a
   host count sit in the same row at different heights. Centre them on each other
   and let the row wrap, so a long headline pushes its badges to the next line
   instead of stretching the row (Israel, 2026-09-15: "maybe line them up a
   little better"). `row-gap` is tighter than `column-gap` so a wrapped second
   line reads as continuation rather than as a new row. */
.cv-finding-tier > .cv-finding-tier-head { display: flex; align-items: center;
  flex-wrap: wrap; column-gap: 8px; row-gap: 3px; padding: 5px 0; }
/* The headline keeps the baseline behaviour it had, against its own line box,
   and takes the row's full width only when it would otherwise crowd the badges
   off the end. */
.cv-finding-tier > .cv-finding-tier-head > .cv-finding-tier-headline {
  align-self: baseline; }
/* The tier heading and the card beneath it name the SAME finding, so they read
   as one thing: same type size, same left edge. They used to differ on both —
   the heading inherited a larger size and sat ~19px in (chevron + gap) while
   the card title sat ~35px in (body padding 14 + border 2 + dot 8 + gap 11),
   which made the top-level card look like a caption for the indented "real"
   content rather than its heading (Israel, 2026-07-29). Heavier than the card
   title on purpose — it is the heading — but the same size. */
.cv-finding-tier-headline { font-size: 0.90625rem; font-weight: 450;
  color: var(--cv-ink); line-height: 1.45; }
/* WHAT was disclosed, on the row itself. Reads as data, not as a status:
   distinct from the severity label and the violation chip beside it. */
/* Counsel's own wording, shown beneath a rule-composed line while the rule is
   being evaluated (?headline=rule). Quiet, but present: the prototype must not
   be able to delete his text while being judged. */
/* Only ever rendered when the running build is provably out of date. */
.cv-release-notice { margin: 0; padding: 9px 14px; background: #fff8e1;
  border-bottom: 1px solid #f0dfa8; color: #6b4e00; font-size: 0.8125rem; }
.cv-release-notice .linklike { color: #6b4e00; font-weight: 700;
  text-decoration: underline; }
.cv-counsel-line { flex-basis: 100%; color: var(--cv-faint); font-size: 0.75rem;
  line-height: 1.4; font-style: italic; }
.cv-data-tag { flex: none; font-size: 0.6875rem; font-weight: 600; line-height: 1.4;
  padding: 1px 7px; border-radius: 9px; white-space: nowrap;
  color: #1d3f6b; background: rgba(37,99,235,.09);
  border: 1px solid rgba(37,99,235,.22); }
/* Data-type tags (Israel, 2026-09-24 20:01 EDT): one chip per data type, each a
   filter. A button keeps the span's look; pressed reads as the engaged filter. */
.cv-data-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
button.cv-data-tag.cv-chip-filter { font-family: inherit; font-size: 0.6875rem; font-weight: 600; line-height: 1.4;
  border: 1px solid rgba(37,99,235,.22); cursor: pointer; margin: 0; }
button.cv-data-tag:hover { background: rgba(37,99,235,.16); }
button.cv-data-tag.cv-chip-filter[aria-pressed="true"] { color: #fff; background: #1d3f6b; border-color: #1d3f6b; }
/* The feature label is a QUALIFIER of the headline, not a second headline.
   Unstyled it inherited the summary's base size and outweighed the 0.906rem
   headline beside it (Israel, 2026-07-31: "the feature labels here are too
   large relative to the other things"). Same voice as cv-org-count. */
.cv-finding-feature { color: var(--cv-faint); font-size: 0.75rem;
  line-height: 1.45; flex-shrink: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* it is a button (jumps to the feature's group), styled as a quiet link */
  background: none; border: 0; padding: 0; font-family: inherit;
  cursor: pointer; text-align: left; }
.cv-finding-feature:hover, .cv-finding-feature:focus-visible {
  color: var(--cv-ink); text-decoration: underline; }
/* EVERY journey a collapsed cross-visit finding was observed on. The chips are
   the same quiet qualifier as the single feature label above; the list of them
   is what tells two otherwise identical rows apart, so it wraps rather than
   truncating — a list that quietly ends here would hide the entry that
   distinguishes the set. A separator between chips, since they are names that
   can themselves contain commas. */
.cv-finding-journeys { display: inline-flex; flex-wrap: wrap; gap: 0 0.5rem;
  align-items: baseline; min-width: 0; }
.cv-finding-journeys .cv-finding-feature { white-space: normal; overflow: visible; }
.cv-finding-journeys .cv-finding-feature + .cv-finding-feature::before {
  content: "· "; color: var(--cv-faint); }
.cv-finding-journeys-rest { font-size: 0.75rem; line-height: 1.45; }
/* What was OBSERVED, beside what the journey was NAMED. Same quiet voice as the
   feature chip it qualifies — it is evidence about that label, not a claim of
   its own, and must not compete with the finding's headline. */
.cv-optout-observed { color: var(--cv-faint); font-size: 0.75rem;
  line-height: 1.45; white-space: nowrap; font-style: italic; }
.cv-org-count { margin-left: auto; color: var(--cv-faint); font-size: 0.8125rem; white-space: nowrap; }
/* The recipient hosts, named on the finding row rather than only inside the
   technical detail. Pushed right like the count it replaces, and allowed to
   shrink before the finding's own headline does — the headline is the claim,
   the hosts are who it is against. */
.cv-org-hosts {
  margin-left: auto; display: flex; gap: 0.375rem; align-items: baseline;
  min-width: 0; overflow: hidden; flex-wrap: wrap; justify-content: flex-end;
}
.cv-org-hosts code {
  color: var(--cv-faint); font-size: 0.8125rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 22ch;
}
.cv-org-hosts .cv-org-count { margin-left: 0; }
/* The copyable ", " between host chips (views/client.js): no size and one gap
   taken back, so the chips read as chips and a copy still reads as a list. */
.cv-org-hosts .cv-org-sep { font-size: 0; margin-left: -0.375rem; }
.cv-org-more {
  border: 0; padding: 0; background: none; cursor: pointer;
  color: var(--cv-faint); font-size: 0.8125rem; white-space: nowrap;
  font-family: inherit; text-decoration: underline dotted;
}
.cv-org-more:hover, .cv-org-more:focus-visible { color: var(--cv-ink); }
.cv-org-rest code { color: var(--cv-faint); font-size: 0.8125rem; }
/* No left padding/border: the dot + gap inside .cv-finding-line already carry
   the indent, and stacking both put the card 16px right of its own heading. */
.cv-org-body { padding-left: 0; margin: 2px 0 8px; }
/* Category "what it catches": what data left and who received it, mirroring the
   operator Recommendations card. Recipients are organisations — hostnames belong
   to the tier below. */
.cv-catches { margin: 2px 0 8px; font-size: 0.8125rem; color: var(--cv-faint); line-height: 1.7; }
.cv-catches-k { font-weight: 600; }
.cv-catches-chip { display: inline-block; padding: 1px 6px; margin: 0 1px; border-radius: 4px;
  background: rgba(0,0,0,.05); color: inherit; }
.cv-catches-more { font-style: italic; }
/* Type-level recommendation card: authored once per detectionType on the operator
   Recommendations page, so it is stated once here rather than on every finding. */
.cv-type-rec { margin: 4px 0 10px; padding: 9px 11px; border-radius: 6px;
  background: rgba(37,99,235,.05); border-left: 3px solid rgba(37,99,235,.35); }
.cv-type-rec-k { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-faint); margin-bottom: 2px; }
/* Counsel writes these with real structure — the Investopedia recommendation
   carries 13 newlines separating "(i) ... (ii) ..." clauses. Without pre-wrap
   the browser collapses every one of them and a carefully paragraphed legal
   recommendation renders as an unreadable monolith (Israel, 2026-07-29). The
   text is counsel's own and is never machine-edited, so preserving the breaks
   they typed is the whole job. */
.cv-type-rec-body { font-size: 0.875rem; line-height: 1.5; white-space: pre-wrap; }
/* Paragraphs and enumerated options, spaced (counsel, 2026-09-23). The breaks
   are markup, so the pre-wrap above must not add a second set. */
.cv-rec-formatted { white-space: normal; }
.cv-rec-p { margin: 0 0 6px; }
.cv-rec-p:last-child { margin-bottom: 0; }
.cv-rec-list { list-style: none; margin: 0 0 6px; padding-left: 14px; }
.cv-rec-list:last-child { margin-bottom: 0; }
.cv-rec-list li { margin: 0 0 3px; }
/* THE RULE BETWEEN THE RECOMMENDATION AND THE FINDINGS IT COVERS (Israel,
   2026-09-15, pointing at it on a screenshot: "between the proposed
   recommendation ... and above 'consent signal sent to openx did not carry the
   visitors opt out'").

   AN EMITTED ELEMENT, not a selector, and only when a recommendation exists.
   Two selector attempts failed: a border-bottom on .cv-type-rec underlines the
   CARD (tinted, rounded, blue left accent) instead of separating it from what
   follows; and `.cv-type-rec + .cv-type-body` never matches, because the
   recommendation block does not END with the card -- the multi-shape path
   returns the card followed by its per-shape "Edit recommendation" controls, so
   the element adjacent to the body is a button.

   It composes with the between-findings rule rather than doubling it: that one
   is `.cv-finding-tier + .cv-finding-tier`, so it skips the FIRST finding --
   exactly the one this rule sits above. No finding ever gets two lines. */
.cv-type-rec-divider { border-top: 1px solid rgba(0,0,0,.09);
  margin: 12px 0; }
/* A finding's own recommendation is the delta from the type default. */
.cv-finding-rec-specific { border-left: 2px solid rgba(0,0,0,.12); padding-left: 8px;
  white-space: pre-wrap; }
.cv-finding-rec-k { font-weight: 600; }
/* When a finding's detectionType has no authored default, its own recommendation
   IS the guidance, not a delta — same treatment as .cv-type-rec so it reads with
   equal weight, scoped to one finding instead of the whole category. */
.cv-finding-rec { margin: 4px 0 8px; padding: 9px 11px; border-radius: 6px;
  background: rgba(37,99,235,.05); border-left: 3px solid rgba(37,99,235,.35); }
/* Legacy-parity evidence sections: every part of the capture renders, with long
   bodies collapsed and opened bodies flowing in the page rather than trapping it. */
.cv-evidence-sec { margin: 5px 0; }
.cv-evidence-sec > summary { cursor: pointer; font-size: 0.75rem; font-weight: 600;
  color: #4a5563; list-style: revert; }
/* Darker than the surrounding muted chrome: this is the evidence a reader
   works through line by line, not a caption (Israel, 2026-08-05). */
.cv-evidence-sec > code { display: block; margin-top: 3px; padding: 7px 9px;
  background: #f6f7f9; border-radius: 5px; font-size: 0.75rem; line-height: 1.55;
  color: #16202c;
  white-space: pre-wrap; word-break: break-all; }
.cv-evidence-excerpt { margin: 6px 0; padding: 7px 9px; background: #fff8db;
  border: 1px solid #f0d778; border-radius: 5px; }
.cv-evidence-excerpt > code { display: block; margin-top: 4px; font-size: 0.75rem;
  line-height: 1.55; white-space: pre-wrap; word-break: break-all; color: #16202c; }
/* The detector's match must be unmissable inside a large body. */
mark.cv-hit { background: #ffe45e; color: inherit; padding: 0 2px; border-radius: 2px;
  outline: 1px solid rgba(180,140,0,.45); }
.cv-finding-tech-link { display: inline-block; margin: 6px 0 2px; font-size: 0.8125rem;
  color: var(--cv-blue, #2563eb); text-decoration: none; }
.cv-finding-tech-link:hover { text-decoration: underline; }
.cv-detail-back { margin: 2px 0 10px; font-size: 0.875rem; }
/* Detail page: the evidence is simply present — no button step ONCE IT HAS
   LOADED. The button used to be hidden unconditionally, so every line the
   deep-link auto-load did not reach (a second finding on the page, a failed
   or skipped load) showed its technical detail with no way to the requests
   (counsel 2026-08-17; Israel 2026-09-23 10:26 on the Wired
   identifiedSensitiveData row). It now hides only when its panel has content. */
.cv-detail-mode .cv-evidence:has(> .cv-evidence-out:not(:empty)) > .cv-evidence-btn { display: none; }
.cv-evidence-matched { margin: 4px 0; font-size: 0.8125rem; }
.cv-evidence-matched code { background: #fff7d6; padding: 0 4px; border-radius: 3px; }
/* THE PAIR IS THE POINT (counsel B1, 2026-09-14): each value sits beside the
   key that names it, so a plain address and its digest can never be read as two
   findings. One row per key, key left and fixed-width so the values line up and
   scan as a dictionary; a long digest wraps under its own key rather than
   pushing the next one out of line. The key is deliberately NOT the uppercase
   .cv-evidence-k treatment — that one heads the whole block, and two levels of
   small caps read as two headings rather than a heading and its entries. */
.cv-evidence-pair { display: flex; gap: 8px; align-items: baseline; margin-top: 2px; }
.cv-evidence-pair-k { flex: 0 0 auto; min-width: 13.5em; color: #64748b; font-weight: 600; }
.cv-evidence-pair code { word-break: break-all; }
.cv-surface-witness { margin: 8px 0; font-size: 0.8125rem; }
.cv-surface-witness dl { margin: 4px 0; }
.cv-surface-witness dt { font-weight: 600; color: #475569; }
.cv-surface-witness dd { margin: 1px 0 6px; }
.cv-surface-witness code { white-space: pre-wrap; overflow-wrap: anywhere; }
.cv-surface-kinds { margin: 0 0 4px; font-weight: 600; }
@media (max-width: 640px) {
  .cv-evidence-pair { display: block; }
  .cv-evidence-pair-k { display: block; min-width: 0; }
}

/* Opt-out evidence, on the request it was found on. Deliberately quiet beside
   the matched value: the finding is still the leak, and this answers "was the
   opt-out on THIS request" without competing for the eye. */
.cv-optout-evidence { margin: 6px 0; padding: 6px 8px; border-left: 2px solid #cbd5e1; background: #f8fafc; font-size: 0.8125rem; }
/* The consent state OF the request, above the signal the request carried. Same
   quiet treatment as its sibling for the same reason, and the same shape so the
   two read as one pair of facts about this card rather than two kinds of
   statement. */
.cv-request-consent { margin: 6px 0; padding: 6px 8px; border-left: 2px solid #cbd5e1; background: #f8fafc; font-size: 0.8125rem; }
.cv-request-consent-declared, .cv-request-consent-onset { color: #334155; margin-top: 2px; }
.cv-request-consent-where { margin-top: 2px; }
.cv-request-consent-journey { font-weight: 600; }
/* The per-request witness, dashed like its feature-group sibling so operator
   methodology is visibly a different KIND of block from the client's evidence
   around it. It carries data-review-control and never reaches a client build. */
.cv-request-witness { margin: 6px 0; padding: 6px 8px; border-radius: 7px;
  border: 1px dashed rgba(0,0,0,.18); font-size: 0.8125rem; line-height: 1.5; }
/* A journey name is not a link — nothing serves a leg — so it is set apart by
   weight rather than by an affordance that cannot resolve. */
.cv-tested-journey { font-weight: 600; }
.cv-optout-absent { font-weight: 600; color: #b45309; }
.cv-optout-signal { margin-top: 4px; }
.cv-optout-string { word-break: break-all; background: #eef2ff; padding: 0 4px; border-radius: 3px; }
.cv-optout-decoded { color: #334155; margin-top: 2px; }
/* An unread string must not read like an empty one — same weight as the claim
   it is refusing to make. */
.cv-optout-undecoded { color: #b45309; margin-top: 2px; }
/* The opt-out-violation marker is a CHIP, not a second headline: unstyled it
   inherited the row's text size and shouted over the finding name it
   qualifies (Israel, 2026-08-03). Small, red-tinted, no wrap. */
.cv-violation { display: inline-block; font-size: 0.6875rem; font-weight: 600;
  line-height: 1.4; padding: 1px 7px; border-radius: 9px; white-space: nowrap;
  color: #a02016; background: rgba(190,44,32,.08);
  border: 1px solid rgba(190,44,32,.25); vertical-align: baseline; }
/* Root cause pops as its own card — amber, so it cannot be read as advice
   (blue) or as counsel's per-finding text below (Israel, 2026-08-03). */
.cv-finding-cause-card { margin: 6px 0 8px; padding: 9px 11px; border-radius: 6px;
  background: rgba(217,119,6,.07); border-left: 3px solid rgba(217,119,6,.45); }
.cv-finding-reasoning-card { margin: 6px 0 8px; padding: 9px 11px; border-radius: 6px;
  background: rgba(100,116,139,.07); border-left: 3px solid rgba(100,116,139,.45); }
/* Why this grade + the grading grid page: staff only (grade-provenance.js). */
.cv-why-grade-card { margin: 6px 0 8px; padding: 7px 11px; border-radius: 6px;
  background: rgba(100,116,139,.05); border-left: 3px solid rgba(100,116,139,.35); }
.cv-why-grade-card > summary { cursor: pointer; }
.cv-why-grade-card .cv-finding-cause-heading { display: inline; }
.cv-why-lead { font-size: 0.8125rem; }
.cv-why-layers { margin: 6px 0 4px; padding-left: 18px; font-size: 0.8125rem; line-height: 1.5; }
.cv-why-layer.is-deciding { font-weight: 600; }
.cv-why-layer-k { display: inline-block; min-width: 11em; }
.cv-why-actions { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: baseline; font-size: 0.8125rem; }
.cv-grid-link { font-size: 0.8125rem; margin-left: 8px; }
.cv-grid-scroll { overflow-x: auto; max-width: 100%; }
.cv-grid-table { border-collapse: collapse; font-size: 0.75rem; }
.cv-grid-table th, .cv-grid-table td { border: 1px solid rgba(100,116,139,.25); padding: 3px 6px; vertical-align: top; }
.cv-grid-table tr.is-focus { outline: 2px solid #2563eb; }
.cv-grid-cell.is-live { background: rgba(37,99,235,.10); font-weight: 600; }
.cv-grid-count { display: inline-block; margin-left: 4px; padding: 0 5px; border-radius: 8px;
  background: rgba(37,99,235,.18); font-weight: 600; }
.cv-finding-cause-heading { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: #92600a; margin-bottom: 2px; }
.cv-finding-cause-body { font-size: 0.875rem; line-height: 1.5; white-space: pre-wrap; }
.cv-finding-rec-heading { font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-faint); margin-bottom: 2px; }
.cv-finding-rec-body { font-size: 0.875rem; line-height: 1.5; white-space: pre-wrap; }
/* Standing category-recommendation authoring: one trigger (+ card, once
   authored) per (detectionType, identifierType) shape, as flat siblings with no
   wrapper — see categoryRecommendationShapeHtml for why. Same visual language
   as the per-finding edit control so it reads as "the same kind of action". */
.cv-category-rec-edit, .cv-finding-rec-edit {
  display: inline-flex; margin-bottom: 8px; flex: none; align-items: center; gap: 4px;
  padding: 3px 7px; border: 1px solid #7b8495; border-radius: 6px; background: #fff;
  min-height: 24px; color: var(--cv-blue); font-size: 0.6875rem; font-weight: 650; line-height: 1.3;
}
.cv-category-rec-edit:hover, .cv-finding-rec-edit:hover { border-color: var(--cv-blue); background: #f7f8ff; }
.cv-category-editor {
  display: grid; gap: 10px; margin: 4px 0 10px; padding: 12px; border: 1px solid #cbd3f5;
  border-radius: 9px; background: #f7f8ff;
}
.cv-category-editor label {
  display: grid; gap: 4px; color: var(--cv-navy); font-size: 0.75rem; font-weight: 700;
}
.cv-category-editor textarea {
  box-sizing: border-box; width: 100%; min-height: 82px; padding: 9px 10px;
  resize: vertical; border: 1px solid #7b8495; border-radius: 7px; background: #fff;
  color: var(--cv-ink); font: inherit; font-size: 0.8125rem; line-height: 1.45;
}
.cv-category-editor textarea:focus { border-color: var(--cv-blue); }
.cv-category-rec-save { background: var(--cv-navy); color: #fff; }
.cv-category-rec-save:hover { background: #22375f; }
.cv-finding-editor-actions .cv-category-rec-cancel { border-color: #7b8495; background: #fff; color: var(--cv-muted); }
.cv-category-editor-error { min-height: 1.2em; margin: 0; color: #a93226; font-size: 0.75rem; }
.cv-category-editor-error:empty { display: none; }
/* A filter chip with nothing to filter must look inert. The opt-out violation
   toggle ships disabled when a report has zero violations, and with no :disabled
   styling it was pixel-identical to a live control — click, nothing happens. */
.cv-segmented button:disabled { opacity: .45; cursor: not-allowed; }
.cv-segmented button:disabled:hover { color: inherit; }
/* Chips in the "what it catches" line are filter toggles, so they must read as
   pressable and show their engaged state. */
.cv-chip-filter { border: 0; font: inherit; cursor: pointer; }
.cv-chip-filter:hover { background: rgba(37,99,235,.14); }
.cv-chip-filter.on { background: rgba(37,99,235,.9); color: #fff; }

/* "+N more" recipient hosts — a control, not a label. The revealed hosts are
   the same clickable chips as the first eight (see findingHostListHtml). */
.cv-host-more-btn { border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; color: #2563eb; text-decoration: underline; }
.cv-host-more-btn:hover, .cv-host-more-btn:focus-visible { color: #1d4ed8; }
.cv-host-rest { display: block; margin-top: 6px; }
.cv-domain-class {
  display: inline-flex; align-items: center; gap: 2px; max-width: 100%;
  margin-left: 5px; padding: 1px 6px; border-radius: 5px;
  font-size: 0.6875rem; font-weight: 700; line-height: 1.35;
  vertical-align: middle; white-space: normal;
}
.cv-domain-class-muted {
  background: #eef2f7; color: #4b5563; border: 1px solid #d7dee8;
}
.cv-domain-class-essential {
  background: #edf7ee; color: #217346; border: 1px solid #bfe2c8;
}
.cv-domain-class-finding {
  background: #fff4df; color: #8a5a08; border: 1px solid #f0d28f;
}
.cv-finding-summary .cv-domain-class { margin-left: 0; }
/* The class display rules above outrank the UA's [hidden]{display:none}, which
   made every collapsed "+N more" host list render expanded. The attribute must
   always win: hidden means hidden. */
.cv-host-rest[hidden], .cv-type-hostlist[hidden] { display: none !important; }


/* A repeated category recommendation, shown as a pointer rather than a wall of
   the same paragraph. Quieter than the first copy: it carries no new
   information, and it must not compete with the finding it sits under. */
.cv-type-rec-repeat .cv-type-rec-body { color: var(--cv-faint); font-style: italic; }



/* THE FACT LENS. The heading is now the finding itself — "Email address · sent
   to Amazon.com" — so the recipient has to read as part of the sentence rather
   than as a separate badge competing with it. Deliberately lighter than the
   group name: the data type is what a reader scans for, the recipient is what
   they stop on. */
.cv-group-recipient {
  margin-left: 0.4rem; font-weight: 400; color: var(--cv-faint);
}
/* Where the fact was seen. This is the context the by-feature lens used to
   spend a whole row on, per journey — kept, stated once, and placed above the
   findings rather than around them. */
.cv-fact-journeys {
  margin: 0 0 0.6rem; font-size: 0.8rem; color: var(--cv-faint);
  display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: baseline;
}
.cv-fact-journey {
  padding: 0.05rem 0.4rem; border-radius: 0.75rem;
  background: var(--cv-chip-bg, #eef1f5); color: var(--cv-faint);
  white-space: nowrap;
}
.cv-detail-observed {
  margin: 10px 0 8px; padding: 9px 12px; border-radius: 7px;
  background: var(--cv-info-bg); color: var(--cv-ink); font-size: 0.8125rem;
}
.cv-detail-observed-k {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--cv-faint); margin-bottom: 5px;
}
.cv-detail-observed-list {
  list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap;
  gap: 6px 14px;
}
.cv-detail-observed-list li { display: inline-flex; align-items: center; gap: 6px; }
.cv-detail-observed-feature { font-weight: 650; }
.cv-detail-observed-treatment {
  font-size: 0.75rem; font-weight: 600; color: var(--cv-faint);
}

/* How many of a fact's findings are opt-out violations. Warn-coloured because
   it is the one pill on the heading that states a legal claim rather than a
   count of rows. */
.cv-count-violation {
  background: var(--cv-warn-bg, #fdf1e3);
  color: var(--cv-warn-fg, #8a5300);
}
/* One visit a finding rests on, with the treatment observed in it. Listed
   inline in the technical panel — a reader scanning for "which of these was
   actually opted out" reads the pairs, not a table. */
.cv-visit { display: inline-block; margin-right: 0.9em; white-space: nowrap; }
/* The older-publication explanation is part of the evidence state. Keeping
   the old one-line layout clips its reason off the technical panel. */
.cv-visit-legacy { max-width: 100%; white-space: normal; }

/* Why the edit controls are absent. Operator-only: a reviewer whose view spans
   several evaluations gets no edit target, and used to get no explanation. */
.cv-review-scope-note {
  margin: .5rem 0 0;
  padding: .5rem .7rem;
  border-left: 3px solid #8a6d3b;
  background: rgba(138, 109, 59, .08);
  font-size: .86rem;
  line-height: 1.45;
}

/* Superseded-assets notice. Fixed to the bottom so it can appear while an
   operator is mid-form without moving the field under their cursor. */
.stale-console-notice {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 16px;
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid #b45309;
  background: #fffbeb;
  color: #7c2d12;
  font-size: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}
.stale-console-notice-reload {
  border: 1px solid #b45309;
  background: #fff;
  color: #7c2d12;
  border-radius: 6px;
  padding: 4px 12px;
  font: inherit;
  cursor: pointer;
}
.stale-console-notice-reload:hover { background: #fef3c7; }

/* A derived value the operator reads rather than sets. Matches the height and
   rhythm of the inputs beside it so the form does not look broken where a
   control used to be. */
.readonly-value {
  padding: 8px 10px;
  border: 1px dashed #d1d5db;
  border-radius: 6px;
  background: #f9fafb;
  color: #374151;
  font-size: 14px;
}

/* "Show all" on the evidence sample. Inline in the banner sentence, because it
   completes the sentence rather than sitting beside it. */
.cv-evidence-show-all {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: #2563eb;
  text-decoration: underline;
  cursor: pointer;
}
.cv-evidence-show-all:hover { color: #1d4ed8; }


/* Account-state sections over the feature list. A heading appears only when
   there is something to separate (see signedInSectionsHtml), so this never
   labels a list that is all one state. */
.cv-signedin-section {
  margin: 22px 0 8px; padding-bottom: 4px;
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: #475569;
  border-bottom: 1px solid #e2e8f0;
}
.cv-signedin-section:first-child { margin-top: 4px; }

/* C42 — the authored severity override surface, not a per-data-type matrix. */
.rec-sev-overrides { margin-top: 8px; }
.rec-sev-overrides > summary { cursor: pointer; font-size: 0.8125rem; color: var(--cv-link, #2557d6); }
.rec-sev-overrides table { border-collapse: collapse; margin-top: 8px; width: 100%; font-size: 0.78125rem; }
.rec-sev-overrides th, .rec-sev-overrides td { text-align: left; padding: 5px 10px 5px 0; border-bottom: 1px solid var(--cv-line, #e3e5ea); vertical-align: top; }
.rec-sev-overrides th { color: var(--cv-faint, #6b7280); font-weight: 600; }
.rec-sev-overrides-rule, .rec-sev-reason { max-width: 36ch; line-height: 1.35; }
.rec-sev-provenance, .rec-sev-observed-note { display: block; color: var(--cv-faint, #6b7280); font-size: 0.72rem; line-height: 1.35; }
/* The override keys this report actually produced. Marked, never filtered. */
.rec-sev-observed { background: var(--cv-info-bg, #f6f7f9); }
.rec-sev-observed td { font-weight: 600; }

/* C42 — the authored override grade is editable where its reason is shown. */
.rec-field-sev { font-size: 0.78125rem; padding: 2px 4px; }
.rec-field-sev-status { font-size: 0.72rem; margin-right: 6px; color: var(--cv-faint, #6b7280); }
.rec-field-sev-status.ok { color: #157347; }
.rec-field-sev-status.err { color: #b42318; }

/* Counsel's review is a decision about an exact text, distinct from authoring. */
.rec-review { max-width: 1000px; }
.rec-review .muted, #rec-progress { color: #606067; }
.rec-review > select { margin: 8px 0 20px 12px; }
.rec-review-card { border: 1px solid var(--border, #d8d5cf); border-left-width: 4px; padding: 20px; margin: 0 0 20px; border-radius: 4px; }
.rec-review-flagged { border-left-color: #946000; }
.rec-review-accepted { border-left-color: #287344; }
.rec-review-unreviewed { border-left-color: #777; }
.rec-review-heading { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.rec-review-heading h2 { font-size: 17px; margin: 0; }
.rec-review-card textarea { display: block; box-sizing: border-box; width: 100%; min-height: 100px; font: inherit; font-size: 14px; line-height: 1.6; padding: 12px; resize: vertical; }
.rec-review-card textarea[readonly] { background: var(--surface, #f7f6f3); }
.rec-review-quote { white-space: pre-wrap; overflow-wrap: anywhere; margin: 12px 0; padding-left: 16px; border-left: 2px solid #777; }
.rec-review-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.rec-review-actions [hidden] { display: none; }
.rec-review-card :is(button, textarea, summary):focus-visible { outline: 2px solid #245d88; outline-offset: 3px; }

/* ALSO CONSIDERED — the features we measured that produced no findings.

   Israel, 2026-09-16, reading the live Vogue report: these should appear as
   cards with the considered-feature badge, not a list. It was rendering as
   run-together text for the plainest possible reason:
   the markup shipped with NO RULE IN THIS FILE AT ALL, so every span sat inline
   against its neighbour. The renderer was tested and the stylesheet was never
   written, which is a shape worth naming: a unit test on markup cannot see that
   the markup is unreadable.

   THE BADGE CARRIES THE CLAIM, so its colours follow the same discipline as
   .cv-optout-badge above — a statement about OUR EVIDENCE is quieter than a
   statement about the site. `proven` is the only one that asserts something
   about the property and it is the only one given real colour; `partial` and
   `incomplete` describe what we could not do and stay grey, because a reader
   should not read our own capture trouble as a finding about them. */
.cv-cleared { margin-top: 26px; }
.cv-cleared-head { margin: 0 0 4px; font-size: 1rem; }
.cv-cleared-note { margin: 0 0 12px; color: var(--cv-muted, #5b6470); font-size: 0.85rem; }
.cv-cleared-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.cv-cleared-card {
  border: 1px solid var(--cv-rule, #e3e6ea); border-radius: 8px;
  background: var(--cv-card-bg, #fff); overflow: hidden;
}
.cv-cleared-badge {
  flex: none; display: inline-block; padding: 2px 8px; border-radius: 999px;
  border: 1px solid transparent; font-size: 0.75rem; font-weight: 650;
  white-space: nowrap;
}
/* ALL THREE ARE GREY. Israel, 2026-09-16: "all the no high priority findings at
   this time should be gray."

   `proven` was green on the reasoning that it was the only verdict asserting
   anything about the property. That reasoning died when the three sentences
   collapsed into one: every card now says the same thing, so colouring some of
   them differently would signal a distinction the words do not make, and green
   reads as a pass mark on a line that deliberately does not give one. */
.cv-cleared-badge-proven,
.cv-cleared-badge-partial,
.cv-cleared-badge-incomplete {
  color: var(--cv-info, #5b6470); background: var(--cv-info-bg, #f1f3f5); border-color: #d7dce2;
  font-weight: 600;
}

/* ALL CONTACTED HOSTS — the drawer restored 2026-09-16.
   Closed by default and visually quiet: it sits after the findings and must not
   compete with them. `cv-hosts-list` wraps rather than scrolls, because a
   recipient with 223 hosts (Google, measured on wired-california) is the case
   this has to stay readable in. */
.cv-hosts { margin: 28px 0 8px; border-top: 1px solid var(--cv-rule, #e3e6ea); padding-top: 14px; }
.cv-hosts > summary {
  cursor: pointer; color: var(--cv-muted, #5b6470); font-size: 0.9375rem;
  font-weight: 600; list-style-position: outside; padding: 2px 0;
}
.cv-hosts > summary:hover { color: var(--cv-ink, #1f2937); }
.cv-hosts-body { margin-top: 14px; display: grid; gap: 12px; }
.cv-hosts-controls { display: flex; gap: 8px; flex-wrap: wrap; }
.cv-hosts-controls button {
  border: 1px solid var(--cv-rule, #d7dce2); background: #fff; color: var(--cv-muted, #5b6470);
  border-radius: 6px; padding: 4px 9px; font-size: 0.8125rem; cursor: pointer;
}
.cv-hosts-controls button:hover { border-color: #aeb7c2; color: var(--cv-ink, #1f2937); }
.cv-hosts-companies { display: grid; gap: 8px; }
.cv-hosts-company {
  border: 1px solid var(--cv-rule, #e3e6ea); border-radius: 8px; padding: 8px 10px;
  background: #fff;
}
.cv-hosts-company > summary { cursor: pointer; list-style-position: outside; }
.cv-hosts-company[open] { background: #fcfcfd; }
.cv-hosts-name {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  color: var(--cv-ink, #1f2937); font-weight: 600; font-size: 0.9375rem;
}
.cv-hosts-count { color: var(--cv-muted, #5b6470); font-weight: 400; font-size: 0.8125rem; }
.cv-hosts-list { display: flex; flex-wrap: wrap; gap: 4px 8px; padding-top: 8px; }
.cv-hosts-host { display: inline-flex; align-items: baseline; gap: 4px; }
.cv-hosts-host-count { color: var(--cv-muted, #5b6470); font-size: 0.75rem; }
/* The host's classification ("Targeted advertising") had no rule of its own, so
   it inherited body size and read larger than the host it describes (Israel,
   2026-09-25 12:45: "too large compared to the other stuff"). Same scale as the
   transmission count beside it. */
.cv-hosts-host .cv-domain-class-text { color: var(--cv-muted, #5b6470); font-size: 0.75rem; }
/* A host's cookie NAMES sit on their own line under it, so the host stays the
   first thing read and the list still wraps rather than scrolls. A host that
   carries names takes the whole row: sharing it left the names of one host
   ragged under its neighbours (dogfooded on Wired/Vogue, 2026-09-25). */
.cv-hosts-host:has(.cv-hosts-host-cookies) { flex-wrap: wrap; flex-basis: 100%; }
.cv-hosts-host-cookies {
  flex-basis: 100%; color: var(--cv-muted, #5b6470); font-size: 0.75rem;
  overflow-wrap: anywhere;
}
.cv-hosts-host-cookies-more { display: inline; }
.cv-hosts-host-cookies-more > summary {
  display: inline; cursor: pointer; color: var(--cv-link, #2557d6); list-style: none;
}
.cv-hosts-host-cookies-more > summary::-webkit-details-marker { display: none; }
.cv-hosts-host-cookies-more[open] > summary { margin-right: 4px; }
.cv-hosts-list code {
  color: var(--cv-muted, #5b6470); font-size: 0.78rem; line-height: 1.5;
  overflow-wrap: anywhere;
}

/* THE CONSENT WITNESS, ADMIN RENDER ONLY (Israel, 2026-09-21).
   Deliberately quieter than the Process block above it and folded shut by
   default: it answers "how do we know this journey was opted out", which is a
   question an operator asks occasionally and counsel never. It carries
   data-review-control and never reaches a client build. */
.cv-feature-witness { margin: 8px 0 4px; padding: 8px 12px; border-radius: 7px;
  border: 1px dashed rgba(0,0,0,.18); font-size: 0.82rem; color: var(--cv-ink); }
.cv-feature-witness > summary { cursor: pointer; font-size: 0.6875rem;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--cv-faint); }
.cv-witness-list { list-style: none; margin: 8px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 10px; }
.cv-witness-head { font-weight: 600; margin-bottom: 3px; }
.cv-witness-facts { list-style: none; margin: 0; padding: 0; line-height: 1.5; }
.cv-witness-k { display: inline-block; min-width: 7.5em; color: var(--cv-muted);
  font-size: 0.6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; }
/* The screenshot path is a capture-box path with no serving route, so it is
   shown as a literal rather than styled to look clickable. */
.cv-witness-facts code { word-break: break-all; }
/* Console, direction C: the category editor and the slim Matrix page. */
.lce-category { margin: 14px 0; padding: 10px 12px; border: 1px solid rgba(100,116,139,.25); border-radius: 6px; }
.lce-name { margin: 0 0 4px; font-size: 1rem; }
.lce-subcase { margin: 10px 0 0 14px; padding-left: 10px; border-left: 2px solid rgba(100,116,139,.25); }
.lce-subcase-name { margin: 0 0 4px; font-size: 0.9rem; }
.lce-source { display: inline-block; font-size: 0.75rem; color: var(--cv-faint, #64748b); margin-bottom: 4px; }
.lce-source.is-edited { color: #1d4ed8; font-weight: 600; }
.lce-text { white-space: pre-wrap; font-size: 0.875rem; line-height: 1.5; margin: 4px 0 6px; max-width: 90ch; }
.lce-project select { margin-left: 6px; }
.mf-scroll { overflow-x: auto; max-width: 100%; }
.mf-table { border-collapse: collapse; font-size: 0.8125rem; }
.mf-table th, .mf-table td { border: 1px solid rgba(100,116,139,.25); padding: 4px 6px; vertical-align: top; }
.mf-table th[scope="row"] code { word-break: break-all; }
.mf-table td.num { text-align: right; }
.mf-table textarea { width: 36ch; }
