/* ---------- Design tokens — Program Portal palette ----------
   Primitives come from the Program Portal integration spec (Section 3.2)
   and are theme-invariant. Semantic variables below map to these and do
   vary per theme. */

:root {
  /* Brand — Primary palette */
  --bl: #00A6DC;
  --bl-dk: #0082b0;
  --bl-lt: #e8f6fd;

  --or: #F7943E;
  --or-lt: #fff3e8;

  --pu: #614876;
  --pu-lt: #f0ecf5;

  /* Feedback */
  --gn: #1a9e6e;
  --gn-lt: #e8f8f2;

  --rd: #e04b4b;
  --rd-lt: #fdf0f0;

  --am: #c47d0e;
  --am-lt: #fef8ec;

  /* Neutrals */
  --gy: #414042;
  --gy-lt: #f4f5f7;
  --gy-bd: #e8eaed;
}

/* ---------- Theme variables ---------- */

:root[data-theme="light"] {
  /* Note: --border, --panel-2, and --text-dim are deliberately darker than
     the Program Portal primitives (--gy-bd / --gy-lt / --gy at 60%). Our
     three-pane density benefits from stronger dividers and higher-contrast
     secondary text; Program Portal is a lower-density dashboard where the
     lighter neutrals read fine. Primitives themselves are untouched, so
     badges/buttons still match the spec. */
  --bg: #ffffff;
  --panel: #e9ebef;
  --panel-2: #d8dce2;
  --border: #c4cad1;
  --text: var(--gy);
  --text-dim: #5f6266;            /* ~5.8:1 on white, well above AA */
  --accent: var(--bl);
  --accent-hover: var(--bl-dk);
  --warn: var(--am);
  --error: var(--rd);
  --ok: var(--gn);
  --selected-bg: var(--bl-lt);
}

:root[data-theme="dark"] {
  --bg: #0d1117;
  --panel: #161b22;
  --panel-2: #1f2631;
  --border: #30363d;
  --text: #e6edf3;
  --text-dim: #8b949e;
  --accent: var(--bl);
  --accent-hover: #33b8e5;         /* lighter than --bl so it reads as hover on dark */
  --warn: var(--am);
  --error: var(--rd);
  --ok: var(--gn);
  --selected-bg: #0e3747;
  /* S5: brighter purple so the QUEUED badge reads at a glance on dark
     backgrounds. The base #614876 is fine on light theme but blends
     into the dark panel; #a78bcf gives the badge ~3x luminance lift
     without losing its "purple = queued" identity. Applies anywhere
     --pu is read (badges, run-strip labels). */
  --pu: #a78bcf;
}

* { box-sizing: border-box; }

/* Ensure the HTML hidden attribute wins over display: flex etc. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  font-family: 'DM Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  height: 100vh;
  overflow: hidden;
}

body {
  display: flex;
  flex-direction: column;
}

/* ---------- Top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 24px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.2px;
}
.brand-logo {
  flex: 0 0 auto;
  border-radius: 5px;
  display: block;
}
.brand-text {
  white-space: nowrap;
}

.program-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.program-picker label {
  color: var(--text-dim);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.stats {
  font-size: 12px;
  color: var(--text-dim);
}

/* ---------- Inputs / buttons ---------- */

select, input[type="text"], input[type="number"], button {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 13px;
  font-family: inherit;
}

input[type="text"]:focus-visible,
input[type="number"]:focus-visible,
input[type="password"]:focus-visible,
textarea:focus-visible,
button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bl);
  border-color: var(--bl);
}

/* Selects deliberately don't get the brand-blue focus ring. The ring
   reads as a permanent accent on a control that's open often (program
   selector, range filters, model dropdowns), and Mark called it out
   as too loud across the app. Keep a quiet neutral state on focus so
   accessibility users still see a tab-stop signal. Hover darkens the
   border for the same affordance on mouse use. */
select:focus,
select:focus-visible {
  outline: none;
  box-shadow: none;
  border-color: var(--text-dim);
}
select:hover {
  border-color: var(--text-dim);
}

button {
  cursor: pointer;
  transition: background-color 0.1s ease;
}

button:hover:not(:disabled) {
  background: var(--panel-2);
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
}

button.primary:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* ---------- Three-pane layout ---------- */

.three-pane {
  display: grid;
  grid-template-columns: 260px 340px 1fr;
  flex: 1;
  overflow: hidden;
  min-height: 0;
}

.pane {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border);
  background: var(--panel);
  min-width: 0;
  overflow: hidden;
}

.pane:last-child {
  border-right: none;
  background: var(--bg);
}

.pane-header {
  padding: 0 14px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: 44px;
  flex: 0 0 auto;
  background: var(--panel);
}

/* Controls inside a pane header (e.g., the SnareScripted filter dropdown)
   must fit inside the 44px height so the bar doesn't grow taller than the
   tabs row in the adjacent pane. */
.pane-header select,
.pane-header input[type="text"],
.pane-header input[type="number"] {
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
}

.pane-header h2 {
  font-size: 11px;
  margin: 0;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--text-dim);
}

.count {
  color: var(--text-dim);
  font-weight: 400;
  margin-left: 4px;
}

.editor-meta {
  font-size: 11px;
  color: var(--text-dim);
}

/* ---------- File lists ---------- */

.file-list {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.file-list li {
  position: relative;          /* anchors absolute row-actions */
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  font-size: 13px;
  display: flex;
  flex-direction: column;       /* two-line layout — title on top, meta below */
  justify-content: center;
  gap: 3px;
  line-height: 1.3;
  min-height: 48px;             /* uniform row height across the panel —
                                   keeps badges, spinners, harvest counts
                                   from causing one row to be taller than
                                   another */
  box-sizing: border-box;
}

.file-list li:hover {
  background: var(--panel-2);
}

.file-list li.selected {
  background: var(--selected-bg);
}

.file-list-title {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.file-name {
  font-size: 12px;
  color: var(--text);
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.file-list-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  color: var(--text-dim);
}

.file-list-ts {
  margin-left: auto;
  white-space: nowrap;
}

/* Legacy single-line ".file-meta" still used in a couple of spots; keep
   the rule lightweight so it doesn't conflict with the two-line layout. */
.file-meta {
  font-size: 10px;
  color: var(--text-dim);
  white-space: nowrap;
  flex-shrink: 0;
}

.badge { flex-shrink: 0; }
.row-actions { flex-shrink: 0; }

/* Row-actions positioned in the top-right corner of the file row, mirroring
   the brief-list layout so the two queues feel identical. */
.file-list li .row-actions {
  position: absolute;
  top: 6px;
  right: 10px;
}

.file-kind-run_report .file-name,
.file-kind-errors_log .file-name,
.file-kind-file_state .file-name,
.file-kind-other .file-name {
  color: var(--text-dim);
  font-style: italic;
}

.badge {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--gy-lt);
  color: var(--gy);
  border: 1px solid transparent;
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 0.3px;
  white-space: nowrap;
}

.badge-draft { background: var(--gy-lt); color: var(--text-dim); }
.badge-in-review { background: var(--am-lt); color: var(--am); }
.badge-approved { background: var(--gn-lt); color: var(--gn); }
.badge-approval-stale {
  background: var(--am-lt);
  color: var(--am);
}
.badge-input-changed {
  background: var(--am-lt);
  color: var(--am);
}

/* ---------- Pane footers / drop zones ---------- */

.pane-footer {
  padding: 8px 14px;
  display: flex;
  gap: 8px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

/* ---------- Editor pane ---------- */

.editor-pane {
  display: flex;
  flex-direction: column;
}

.editor-placeholder {
  padding: 60px 40px;
  color: var(--text-dim);
  text-align: center;
  font-size: 14px;
}

.editor-placeholder .hint {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  opacity: 0.7;
}

.editor-view {
  flex: 1;
  overflow: auto;
  margin: 0;
  padding: 16px 20px;
  font-family: 'DM Mono', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
  background: var(--bg);
  color: var(--text);
}

/* ---------- Status bar ---------- */

.status-bar {
  padding: 6px 16px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-dim);
  display: flex;
  justify-content: space-between;
  flex-shrink: 0;
}

/* ---------- Dialog ---------- */

.dialog {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px 24px;
  min-width: 400px;
  max-width: 560px;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.dialog.dialog-wide { max-width: 760px; }
/* Dialog body paragraphs cap their line length for readability; long
   explanations don't stretch to the full 560px unless the dialog is wider. */
.dialog .dialog-body {
  max-width: 500px;
  margin: 0 0 10px;
  line-height: 1.5;
  color: var(--text);
}
.dialog .dialog-body-sub {
  color: var(--text-dim);
  margin-bottom: 6px;
}
/* Slice E5.5.1d — first-creation FAQ source-mode picker. */
.nb-faq-mode-picker {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 14px 12px;
  margin: 0 0 14px;
  background: var(--bg-secondary, #1f1f1f);
}
.nb-faq-mode-picker legend {
  padding: 0 6px;
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
}
.nb-faq-mode-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 0;
  cursor: pointer;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text);
}
.nb-faq-mode-option input[type="radio"] {
  margin-top: 4px;
  flex-shrink: 0;
}
.nb-faq-mode-option strong {
  color: var(--text);
  font-weight: 600;
}

.dialog .dialog-warning {
  background: rgba(220, 150, 50, 0.12);
  border: 1px solid rgba(220, 150, 50, 0.35);
  border-radius: 6px;
  padding: 10px 12px;
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
  max-width: 500px;
}
.dialog .dialog-list {
  margin: 0 0 14px;
  padding-left: 22px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.7;
}
.dialog .dialog-list li { margin: 0; }

.dialog::backdrop {
  background: rgba(0, 0, 0, 0.4);
}

.dialog h3 {
  margin: 0 0 16px 0;
  font-size: 16px;
}

.dialog label {
  display: block;
  margin-bottom: 12px;
  font-size: 12px;
  color: var(--text-dim);
}

.dialog label input {
  width: 100%;
  margin-top: 4px;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--text);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

/* Slice E5.7+ — New Brief footer. All buttons right-aligned for a
   clean grouped look. Start Over gets a slightly larger left gap
   (via margin-right on the right cluster) so it stays visually
   distinct from the Cancel / Save Configuration / Save & Generate
   trio without floating to the opposite edge of the dialog. */
.nb-dialog-actions {
  justify-content: flex-end;
  align-items: center;
}
.nb-dialog-actions-right {
  display: flex;
  gap: 8px;
  /* Pull the action group slightly away from Start Over with a
     pipe-like vertical separator so the two groups read as
     distinct kinds of actions, not just buttons in a row. */
  border-left: 1px solid var(--border);
  padding-left: 16px;
  margin-left: 16px;
}
.nb-start-over {
  background: transparent;
  color: var(--text-dim);
  border-color: var(--border);
}
.nb-start-over:hover {
  color: var(--text);
  border-color: var(--text-dim);
}

.error-note {
  margin-top: 10px;
  color: var(--error);
  font-size: 12px;
  min-height: 16px;
}

/* ---------- Small polish ---------- */

::selection {
  background: var(--accent);
  color: white;
}

#theme-toggle {
  font-size: 16px;
  padding: 4px 8px;
  line-height: 1;
}

.status-bar-right {
  color: var(--text-dim);
}

/* ---------- Phase 3: editor (editable) ---------- */

.editor-textarea {
  flex: 1;
  margin: 0;
  padding: 16px 20px;
  border: none;
  outline: none;
  resize: none;
  background: var(--bg);
  color: var(--text);
  font-family: 'DM Mono', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;     /* default: wrap long lines visually */
  word-wrap: break-word;
  overflow: auto;
  min-height: 0;
  tab-size: 2;
}

.editor-textarea.wrap-off {
  white-space: pre;          /* explicit opt-out for column-sensitive viewing */
  word-wrap: normal;
}

/* ---------- Phase 6: CodeMirror integration ---------- */

:root {
  --editor-font-size: 13px;
}

.CodeMirror {
  flex: 1;
  height: auto !important;
  font-family: 'DM Mono', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
  font-size: var(--editor-font-size);
  line-height: 1.5;
  background: var(--bg);
  color: var(--text);
}

/* Active line highlight */
.CodeMirror-activeline-background {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Gutter (line numbers) */
.CodeMirror-gutters {
  background: var(--panel);
  border-right: 1px solid var(--border);
}

.CodeMirror-linenumber {
  color: var(--text-dim);
  font-size: 11px;
}

/* Cursor */
.CodeMirror-cursor {
  border-left: 2px solid var(--accent);
}

/* Selection */
.CodeMirror-selected {
  background: color-mix(in srgb, var(--accent) 25%, transparent) !important;
}
.CodeMirror-focused .CodeMirror-selected {
  background: color-mix(in srgb, var(--accent) 35%, transparent) !important;
}

/* Match highlighter (auto-highlight other instances of selected word) */
.CodeMirror .cm-matchhighlight {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-bottom: 1px solid var(--accent);
}

/* Search match */
.CodeMirror-searching {
  background: color-mix(in srgb, var(--warn) 30%, transparent);
}

/* Bracket matching */
.CodeMirror-matchingbracket {
  color: var(--accent) !important;
  font-weight: 600;
}

/* ---------- Editor toolbar (Phase 6) ---------- */

.editor-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  flex-shrink: 0;
  font-size: 12px;
}

.editor-toolbar button {
  font-size: 11px;
  padding: 3px 9px;
}

.editor-toolbar button:disabled {
  opacity: 0.4;
}

.editor-toolbar .tb-sep {
  width: 1px;
  height: 16px;
  background: var(--border);
  margin: 0 4px;
}

.tb-font-size {
  display: inline-block;
  min-width: 22px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--text-dim);
}

.tb-options {
  position: relative;
  margin-left: auto;
}

.tb-options summary {
  cursor: pointer;
  list-style: none;
  font-size: 11px;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  background: var(--bg);
  user-select: none;
}

.tb-options summary::-webkit-details-marker { display: none; }
.tb-options summary::marker { content: ""; }

.tb-options summary:hover {
  background: var(--panel-2);
}

.tb-options[open] summary {
  background: var(--panel-2);
  border-color: var(--accent);
}

.tb-popover {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  min-width: 240px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tb-popover-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  cursor: pointer;
  color: var(--text);
  margin: 0;
}

.tb-popover-item input {
  margin: 0;
  width: auto;
  cursor: pointer;
}

/* Search/replace dialog (CodeMirror's built-in) */
.CodeMirror-dialog {
  background: var(--panel);
  color: var(--text);
  border-bottom: 1px solid var(--border);
  padding: 6px 10px;
  font-size: 12px;
  font-family: inherit;
}
.CodeMirror-dialog input {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 4px 8px;
  font-family: inherit;
  margin: 0 4px;
  border-radius: 3px;
}
.CodeMirror-dialog button {
  font-size: 11px;
  padding: 2px 6px;
}

.editor-textarea:focus {
  box-shadow: inset 0 0 0 1px var(--accent);
}

.editor-footer {
  padding: 8px 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
  background: var(--panel);
  flex-shrink: 0;
  gap: 12px;
}

.editor-footer-right {
  display: flex;
  gap: 8px;
}

.editor-status {
  font-size: 12px;
  color: var(--text-dim);
}

.editor-status.dirty {
  color: var(--warn);
  font-weight: 500;
}

.editor-status.saved {
  color: var(--ok);
}

.editor-wordcount {
  font-size: 12px;
  color: var(--text-dim);
  margin-left: auto;   /* pushes count to the right, just before the buttons */
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#editor-title.dirty::before {
  content: "● ";
  color: var(--warn);
}

/* ---------- Phase 3: file list checkboxes ---------- */

.file-list li .file-check {
  margin: 0;
  width: 14px;
  height: 14px;
  cursor: pointer;
  accent-color: var(--accent);
}

.select-all-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
}

.select-all-toggle input {
  margin: 0;
  accent-color: var(--accent);
}

.sa-label {
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* ---------- Phase 3b: per-step bottom strip ---------- */

/* Container that wraps the existing run-strip / batch-view surfaces and
   adds a collapsible header. Phase 3b in the multi-submission UX plan.
   See index.html for the operator-facing rationale (hidden / collapsed
   / expanded states + per-step localStorage memory). */
.step-strip {
  background: var(--panel);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

/* The thin collapsed header. Always rendered when the strip is
   visible — the operator clicks the chevron to expand. */
.step-strip-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 16px;
  font-size: 12px;
  min-height: 32px;
}

.step-strip-summary-label {
  color: var(--text);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.step-strip-summary-label.is-paused {
  color: var(--warn, #e6a83c);
  font-weight: 600;
}

.step-strip-summary-label.has-failures {
  color: var(--err, #e6685f);
  font-weight: 600;
}

.step-strip-toggle {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 2px 10px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 11px;
  line-height: 1;
}

.step-strip-toggle:hover {
  color: var(--text);
  background: var(--panel-2);
}

/* The detail body — wraps the existing strip surfaces. When the strip
   is collapsed this is ``hidden`` and only the summary header shows. */
.step-strip-body {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--border);
}

/* The existing surfaces inside the new container should not double up
   on the panel background + top border (the container already provides
   them). Tighten the inner ``.active-run-strip`` padding-top so the
   transition from header to detail flows. */
.step-strip-body > .active-run-strip {
  background: transparent;
  border-top: none;
  padding-top: 10px;
}

.step-strip-body > .batch-view {
  background: transparent;
  border-top: none;
}

/* Multi-row in-flight list (Phase 3b+). One row per running BG entry —
   fixes the legacy single-line strip's tendency to overwrite the
   previous submission's display when a second brief lands concurrently. */
.step-strip-runs {
  display: flex;
  flex-direction: column;
  padding: 10px 16px;
  gap: 6px;
}

.step-strip-run-row {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
}

.step-strip-run-row .run-label {
  color: var(--accent);
  font-weight: 600;
}

.step-strip-run-row .run-file {
  font-weight: 500;
  color: var(--text);
  min-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Phase 16 Slice 3g — "User · [Program ·] " prefix on strip rows.
   Muted + slightly smaller so it provides context without competing
   with the brief label. */
.step-strip-run-row .strip-row-prefix {
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.step-strip-run-row .run-meta {
  color: var(--text-dim);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-left: auto;
}

/* Dedicated elapsed-time span; pushed to the right edge so the live
   clock reads at the same horizontal position across all rows. Tabular
   numerics avoid the digits jiggling as seconds tick. */
.step-strip-run-row .run-elapsed {
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}

/* S5: per-stat segments between filename and elapsed. Each one is a
   discrete data point (sentence progress, accept counters, cost, cache)
   pulled from the run snapshot. Dim text + small font keeps the row
   visually compact even at full width. */
.step-strip-run-row .run-stat {
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* S5: per-row cancel — small × that doesn't compete with the data
   points but stays one-click reachable. Hover-darken for affordance. */
.step-strip-run-row .strip-row-cancel {
  margin-left: 8px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
}
.step-strip-run-row .strip-row-cancel:hover:not(:disabled) {
  color: var(--danger, #f85149);
  border-color: var(--danger, #f85149);
}
.step-strip-run-row .strip-row-cancel:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* S5: badge-mounted × for cancelling queued entries from file/brief
   lists. Sits inside the QUEUED badge so it's contextual to the state
   it cancels. */
.badge-cancel {
  background: transparent;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  padding: 0 2px;
  margin-left: 2px;
  opacity: 0.7;
}
.badge-cancel:hover:not(:disabled) {
  opacity: 1;
}
.badge-cancel:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.step-strip-run-row.queued .run-label {
  color: var(--text-dim);
}

/* ---------- legacy: standalone run strip styles (kept for migration) ---------- */

.active-run-strip {
  background: var(--panel);
  border-top: 1px solid var(--border);
  padding: 10px 16px 0 16px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.run-header {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
}

.run-label {
  color: var(--accent);
  font-weight: 600;
}

.run-file {
  font-weight: 500;
  color: var(--text);
  min-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.run-meta {
  color: var(--text-dim);
  font-size: 12px;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.run-actions {
  display: flex;
  gap: 6px;
}

.run-actions button {
  padding: 3px 10px;
  font-size: 12px;
}

.progress-bar {
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 6px;
}

.progress-fill {
  height: 100%;
  background: var(--accent);
  width: 0%;
  transition: width 0.2s ease-out;
}

.progress-fill.completed {
  background: var(--ok);
}

.progress-fill.cancelled {
  background: var(--warn);
}

.progress-fill.failed {
  background: var(--error);
}

/* ---------- Phase 3: approval dialog ---------- */

.dialog-body {
  margin: 0 0 12px 0;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}

.approval-list {
  margin: 0 0 16px 0;
  padding: 8px 0 8px 20px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: 'DM Mono', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
  font-size: 12px;
  color: var(--warn);
  max-height: 200px;
  overflow-y: auto;
}

.approval-list li {
  margin: 2px 0;
}

/* ---------- Phase 4: row actions ---------- */

.row-actions {
  display: none;         /* take zero layout width when hidden — let badges sit flush right */
  gap: 4px;
}

.file-list li:hover .row-actions,
.file-list li.selected .row-actions,
.brief-list li:hover .row-actions,
.brief-list li.selected .row-actions {
  display: flex;
}

/* Brief-list row actions float to the top-right so the title + metadata
   still fill the row naturally. */
.brief-list li {
  position: relative;
}
.brief-list li .row-actions {
  position: absolute;
  top: 6px;
  right: 10px;
}

.row-action {
  font-size: 10px;
  padding: 2px 6px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  font-weight: 500;
}

.row-action:hover {
  background: var(--panel-2);
  border-color: var(--accent);
}

.row-action.primary {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}

.row-action.danger {
  color: var(--warn);
  border-color: var(--warn);
}

.file-list li.selected .row-action {
  color: var(--text);
  background: var(--bg);
}
.file-list li.selected .row-action.primary {
  background: var(--accent);
  color: white;
}

/* Harvest badge on review files */
.badge-harvest-never {
  background: var(--gy-lt);
  color: var(--text-dim);
}
.badge-harvest-fresh {
  background: var(--gn-lt);
  color: var(--gn);
}
.badge-harvest-stale {
  background: var(--am-lt);
  color: var(--am);
}

/* ---------- Phase 4: toasts ---------- */

.toast-container {
  position: fixed;
  bottom: 48px;
  right: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 9999;
  pointer-events: none;
}

.toast {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 10px 14px;
  font-size: 13px;
  max-width: 360px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
  animation: toast-in 0.2s ease-out;
  pointer-events: auto;
  cursor: pointer;
}

.toast.toast-success { border-left-color: var(--ok); }
.toast.toast-warn { border-left-color: var(--warn); }
.toast.toast-error { border-left-color: var(--error); }

.toast.fading { animation: toast-out 0.3s ease-in forwards; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes toast-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(8px); }
}

/* ---------- Phase 4: batch view ---------- */

.batch-view {
  background: var(--panel);
  border-top: 1px solid var(--border);
  padding: 10px 16px 0 16px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  max-height: 35vh;
  overflow: hidden;
}

.batch-header {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  margin-bottom: 6px;
  flex-shrink: 0;
}

.batch-summary {
  color: var(--text-dim);
  font-size: 12px;
  flex: 1;
}

.batch-table-wrap {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.batch-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.batch-table thead th {
  position: sticky;
  top: 0;
  background: var(--panel);
  text-align: left;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  color: var(--text-dim);
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.5px;
  font-weight: 600;
}

.batch-table tbody td {
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
}

.batch-table .col-state { width: 20px; text-align: center; }
.batch-table .col-file { min-width: 160px; }
.batch-table .col-num { text-align: right; width: 70px; font-variant-numeric: tabular-nums; }
.batch-table .col-counts { text-align: right; width: 100px; font-variant-numeric: tabular-nums; }

.batch-row-state { font-size: 13px; }
.batch-row-queued { color: var(--text-dim); }
.batch-row-running { color: var(--accent); }
.batch-row-done { color: var(--ok); }
.batch-row-cancelled { color: var(--warn); }

.batch-row-running .state-icon {
  display: inline-block;
  animation: batch-spin 1.5s linear infinite;
}

@keyframes batch-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.progress-bar-bottom { margin-top: 6px; }

/* ---------- Phase 4: history dialog ---------- */

.dialog-wide { min-width: 640px; max-width: 90vw; }

.history-scroll {
  max-height: 60vh;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 4px;
  margin-bottom: 12px;
}

.history-row {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 16px;
  align-items: center;
}

.history-row:last-child { border-bottom: none; }

.history-row:hover { background: var(--bg); }

.history-row-title {
  font-size: 13px;
  font-weight: 500;
}

.history-row-meta {
  font-size: 11px;
  color: var(--text-dim);
}

.history-row-stats {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  text-align: right;
  white-space: nowrap;
}

.history-row.cancelled .history-row-title::before {
  content: "⚠ ";
  color: var(--warn);
}

/* ----- Run History one-line table (Phase B 2026-05-15) --------------------
   Each entry renders as a single grid row with fixed columns:
   time | step pill | identifier (flex) | status badge | duration | cost | cache.
   Identifier truncates with ellipsis when the row is narrow; everything else
   is tabular-numeric and right-aligned for fast scanning. */
.runs-toolbar {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin: 8px 0 12px;
}

.runs-filter-group {
  display: flex;
  align-items: center;
  gap: 6px;
}

.runs-filter-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-dim);
  margin-right: 2px;
}

.runs-table-wrap {
  border: 1px solid var(--border);
  border-radius: 4px;
  margin-bottom: 12px;
  overflow: hidden;
}

/* Header lives in the wrap, OUTSIDE the scroll container, so it stays
   pinned while data rows scroll under it. Reserve scrollbar-width on
   the right so columns line up with their data below. */
.runs-table-wrap > .runs-row--header {
  border-bottom: 1px solid var(--border);
  padding-right: calc(14px + var(--scrollbar-width, 12px));
}

/* The scroll container loses its own border/radius — the wrap owns them
   now — so the header sits flush above the data. */
.runs-table {
  max-height: 70vh;
  border: none;
  border-radius: 0;
  margin-bottom: 0;
}

.runs-row {
  display: grid;
  grid-template-columns: 170px 36px minmax(0, 1fr) 110px 80px 64px 56px;
  gap: 12px;
  align-items: center;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.runs-row:last-child { border-bottom: none; }
.runs-row:hover { background: var(--bg); }

.runs-cell {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.runs-cell--time { color: var(--text-dim); font-size: 12px; }
.runs-cell--id   { color: var(--text); }
.runs-cell--duration,
.runs-cell--cost,
.runs-cell--cache {
  text-align: right;
  color: var(--text-dim);
  font-size: 12px;
}

/* Small left-aligned pill identifying the producing pipeline. */
.runs-step {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--gy-lt);
  color: var(--text-dim);
  text-transform: uppercase;
}
.runs-step--snarescripting { background: #ecf2fb; color: #2a5ec9; }
.runs-step--baseline       { background: #f1ecfb; color: #6c47c4; }
.runs-step--brief          { background: #f1ecfb; color: #6c47c4; }

/* Status badges. Solid vivid backgrounds with white text so the
   outcome is unambiguous at a glance — pastel-on-light reads as
   "decoration" rather than "this run failed". */
.badge-completed {
  background: var(--gn);
  color: #ffffff;
  border-color: var(--gn);
}
.badge-cancelled {
  background: var(--am);
  color: #ffffff;
  border-color: var(--am);
}
.badge-failed {
  background: var(--rd);
  color: #ffffff;
  border-color: var(--rd);
}
.badge-permanently_failed {
  background: #8b1a1a;
  color: #ffffff;
  border-color: #8b1a1a;
}

/* Column headers above the run rows. Same grid template as .runs-row so
   the headers align with their columns exactly. Header text is dim and
   uppercase so the rows themselves stay visually dominant. */
.runs-row--header {
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  font-size: 10px;
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: default;
}

.runs-row--header:hover {
  background: var(--panel-2);
}

.runs-row--header .runs-cell--duration,
.runs-row--header .runs-cell--cost,
.runs-row--header .runs-cell--cache {
  color: var(--text-dim);
}

.topbar-action {
  font-size: 12px;
  padding: 4px 10px;
}

/* Settings is an <a> (full-page route, browser-back works) while Run history /
   Lifecycle Report / Configure are <button>s. Anchor doesn't inherit the
   generic <button> chrome, so re-declare the same look here for any
   topbar-action regardless of element type. */
a.topbar-action {
  display: inline-block;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.1s ease;
}
a.topbar-action:hover {
  background: var(--panel-2);
  color: var(--text);
}
a.topbar-action:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bl);
  border-color: var(--bl);
}

/* ---------- Phase 5: Settings modal ---------- */

.settings-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
  padding-bottom: 0;
}

.settings-tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 14px;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13px;
  border-radius: 0;
}

.settings-tab:hover { color: var(--text); background: transparent; }
.settings-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 500;
}

.settings-body {
  min-height: 340px;
  max-height: 55vh;
  overflow-y: auto;
  padding-right: 4px;
}

.settings-panel { display: none; }
.settings-panel.active { display: block; }

.settings-panel h4 {
  margin: 0 0 12px 0;
  font-size: 14px;
  color: var(--text);
  font-weight: 600;
}

.settings-panel h5 {
  margin: 0 0 8px 0;
  font-size: 13px;
  color: var(--text);
  font-weight: 600;
}

.ai-models-block { margin-bottom: 24px; }
.ai-models-block + .ai-steps-block {
  border-top: 1px solid var(--border);
  padding-top: 18px;
}

.ai-models-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}
.ai-models-header h5 { margin: 0; }

.ai-models-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  margin-top: 8px;
}
.ai-models-table th,
.ai-models-table td {
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.ai-models-table th {
  font-weight: 600;
  color: var(--text-dim);
  background: var(--bg-soft, transparent);
}
.ai-models-table code {
  font-size: 11px;
  color: var(--text);
}
.ai-models-actions {
  text-align: right;
  white-space: nowrap;
}
.ai-models-actions button {
  margin-left: 6px;
  padding: 3px 8px;
  font-size: 11px;
}

.settings-panel label {
  display: block;
  margin-bottom: 12px;
  font-size: 12px;
  color: var(--text-dim);
}

.settings-panel label.checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-size: 13px;
}

.settings-panel label.checkbox input {
  margin: 0;
  width: auto;
}

.settings-panel input[type="text"],
.settings-panel input[type="password"],
.settings-panel input[type="number"],
.settings-panel select {
  width: 100%;
  margin-top: 4px;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-sizing: border-box;
  font-family: inherit;
}

.settings-panel .hint {
  font-size: 12px;
  color: var(--text-dim);
  margin: 4px 0 12px 0;
  font-style: italic;
}

.settings-panel .hint code,
.settings-panel label code {
  font-family: 'DM Mono', 'Cascadia Code', Menlo, Monaco, Consolas, monospace;
  font-size: 11px;
  background: var(--bg);
  padding: 1px 5px;
  border-radius: 3px;
  border: 1px solid var(--border);
  font-style: normal;
}

.inline-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 8px;
}

.inline-status {
  font-size: 12px;
  color: var(--text-dim);
  margin-left: 8px;
}

.inline-status.success { color: var(--ok); }
.inline-status.error { color: var(--error); }

.st-programs-list {
  border: 1px solid var(--border);
  border-radius: 4px;
  margin-bottom: 12px;
  max-height: 380px;
  overflow-y: auto;
}

.st-program-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.st-program-row:last-child { border-bottom: none; }

.st-program-row.archived {
  opacity: 0.55;
}

.st-program-row .st-program-info { flex: 1; min-width: 0; }

.st-program-row .st-program-name {
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.st-program-row .st-program-stats {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 2px;
}

.st-program-row .st-program-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

.st-program-row .row-action {
  font-size: 10px;
  padding: 3px 8px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  border-radius: 3px;
}

.st-program-active-badge {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--bl-lt);
  color: var(--bl-dk);
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 0.3px;
  margin-right: 6px;
}

/* Spell check overlay — red wavy underline on words the dictionary doesn't
   know. SnareScript tokens are skipped by the overlay tokenizer, so this
   class is only applied to real prose words. */
.cm-misspelled {
  text-decoration: underline wavy var(--rd);
  text-decoration-skip-ink: none;
  text-underline-offset: 2px;
}

/* SnareScript syntax error — stray `[[`, `]]`, or `]N]` that doesn't belong
   to a valid variable or group. Same overlay; different class so the editor
   can distinguish prose typos from markup mistakes. */
.cm-snare-error {
  background: color-mix(in srgb, var(--rd) 22%, transparent);
  border-bottom: 2px solid var(--rd);
  border-radius: 2px;
}

/* Baseline run strip — same shape as the SnareScripting active-run-strip but
   with a different accent color so the operator can distinguish the two at a
   glance when both are visible (rare, but possible). */
.baseline-run-strip .run-label { color: var(--pu); }
.baseline-run-strip {
  border-top-color: var(--pu);
}

/* Spell-check right-click menu — appears on right-click of a misspelled word.
   Suggestions on top, "Add to dictionary" / "Ignore once" actions below. */
.spellcheck-menu {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
  font-size: 13px;
  min-width: 180px;
  max-width: 280px;
  z-index: 2000;
  padding: 4px 0;
  user-select: none;
}
.spellcheck-menu-item {
  padding: 6px 14px;
  cursor: pointer;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spellcheck-menu-item:hover { background: var(--accent); color: #fff; }
.spellcheck-menu-suggestion { font-weight: 500; }
.spellcheck-menu-action     { font-size: 12px; color: var(--text-dim); }
.spellcheck-menu-action:hover { color: #fff; }
.spellcheck-menu-empty {
  color: var(--text-dim);
  font-style: italic;
  cursor: default;
}
.spellcheck-menu-empty:hover { background: transparent; color: var(--text-dim); }
.spellcheck-menu-separator {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

/* ============================================================
   Program Configuration page  (/program/<id>/config)
   Full-page UI for the per-program baseline content creation
   settings. Not part of the three-pane portal; it takes over
   the viewport.
   ============================================================ */

.pc-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
}

.pc-header {
  flex: 0 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.pc-header-left   { display: flex; align-items: baseline; gap: 14px; }
.pc-header-right  { display: flex; align-items: center; gap: 10px; }

.pc-back {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 13px;
}
.pc-back:hover { color: var(--text); }

.pc-header h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}
.pc-program-name {
  color: var(--text-dim);
  font-size: 13px;
}

.pc-dirty-indicator {
  color: var(--warn);
  font-size: 12px;
  font-weight: 500;
  margin-right: 8px;
}

.pc-btn {
  padding: 6px 14px;
  font-size: 13px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s;
}
.pc-btn:hover:not(:disabled) { background: var(--border); }
.pc-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.pc-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.pc-btn-primary:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.pc-btn-secondary { background: var(--panel-2); }

.pc-btn-ghost {
  background: transparent;
  border: 1px solid transparent;
  padding: 2px 8px;
  font-size: 14px;
}
.pc-btn-ghost:hover:not(:disabled) { background: var(--panel-2); border-color: var(--border); }

/* Tabs ------------------------------------------------------- */
.pc-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 2px;
  padding: 0 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.pc-tab {
  border: none;
  background: transparent;
  color: var(--text-dim);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.pc-tab:hover { color: var(--text); }
.pc-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Body / scroll region --------------------------------------- */
.pc-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 24px 20px 40px;
  background: var(--bg);
}

.pc-tab-panel { display: none; max-width: 900px; margin: 0 auto; }
.pc-tab-panel.active { display: block; }

.pc-tab-panel h2 {
  margin: 0 0 6px;
  font-size: 20px;
  font-weight: 600;
}
.pc-tab-desc {
  margin: 0 0 24px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.5;
}

/* Sub-section heading inside a tab — used to break the Brand tab into
   "brand voice" and "writing profile" without making them feel like
   separate tabs. Smaller than the tab's main h2, with a top border so
   the sub-section reads as a divider. */
.pc-subhead {
  margin: 28px 0 6px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 16px;
  font-weight: 600;
}

/* Field layout ---------------------------------------------- */
.pc-field { margin-bottom: 20px; }
.pc-field label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 6px;
  color: var(--text);
}
.pc-field label.pc-inline-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 400;
}
.pc-field-hint {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-dim);
}

.pc-field textarea,
.pc-field input[type="text"],
.pc-field input[type="number"],
.pc-field select {
  width: 100%;
  padding: 8px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}
.pc-field textarea:focus,
.pc-field input:focus,
.pc-field select:focus {
  outline: none;
  border-color: var(--accent);
}

.pc-field input[type="number"] { width: 120px; }
.pc-field input[type="checkbox"] {
  width: 14px;
  height: 14px;
  margin: 0;
}

/* AI Configuration tab — registry-driven step cards. Sizing + chrome
   match the rest of the program config tabs (.pc-field, .pc-tab-desc)
   so this surface doesn't feel like a different page. Number inputs are
   widened past the .pc-field default of 120px so the inheritance
   placeholder ("(inherit 2048)") fits without clipping. */
.pc-ai-steps { margin-top: 24px; }
.pc-ai-step {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 18px 20px;
  margin-bottom: 18px;
}
.pc-ai-step-title {
  font-size: 16px;
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--text);
}
.pc-ai-step .pc-tab-desc {
  margin: 0 0 8px;
}
.pc-ai-resolved {
  font-size: 12px;
  color: var(--accent);
  margin: 0 0 18px;
  font-family: var(--mono, 'DM Mono', Menlo, Consolas, monospace);
}
.pc-ai-step .pc-field { margin-bottom: 14px; }
.pc-ai-step .pc-field:last-child { margin-bottom: 0; }
.pc-ai-num-field input[type="number"] { width: 220px; }

/* Candidate FAQ entries (slice E2) — list-of-candidates UI inside the
   AI Suggestions panel for append-type briefs. Each candidate is a
   clickable row showing question + answer outline; selection state
   indicated by the .selected class. */
.nb-suggest-candidates {
  list-style: none;
  margin: 8px 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nb-suggest-candidate {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  background: var(--bg-secondary, #1f1f1f);
  transition: background 0.1s, border-color 0.1s;
}
.nb-suggest-candidate:hover {
  border-color: var(--accent);
}
.nb-suggest-candidate.selected {
  background: var(--accent-bg, rgba(0, 120, 215, 0.15));
  border-color: var(--accent);
}
/* Slice E5.7+ — bumped from 14px/1.5px border to 18px/2px so the
   checkbox stays visually distinct against tinted row backgrounds
   (especially the amber-tinted .is-duplicate rows on the
   rewrite-dedup picker, where a 1.5px gray border was hard to see). */
.nb-candidate-check {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--text-dim);
  border-radius: 3px;
  background: var(--bg);
  margin-top: 1px;
  flex-shrink: 0;
}
.nb-suggest-candidate.selected .nb-candidate-check {
  background: var(--accent);
  border-color: var(--accent);
}
.nb-candidate-body { flex: 1; }
.nb-candidate-question {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}
.nb-candidate-outline {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.4;
}
/* 2026-05-05 — keyword chips inside a FAQ candidate row. Small + tight so
   the candidate's question + outline stay the dominant content. Colors
   and origin-stripe rules come from the shared .nb-kw-chip declarations
   above (program = purple, suggested = accent). */
.nb-candidate-chips {
  margin-top: 6px;
  gap: 4px;
}
.nb-candidate-chips .nb-kw-chip {
  font-size: 11px;
  padding: 2px 6px;
}
.nb-candidates-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 6px;
}

/* Brainstorm topic candidates (2026-05-03) — blog-only single-pick
   picker, distinct from the FAQ multi-select candidates above. Each
   row is a card with title + rationale + a clear "Use this topic"
   affordance so it reads as a selection control, not a static
   bulleted list. Click anywhere on the row → fill Topic field. */
.nb-suggest-topic-candidates {
  list-style: none;
  margin: 8px 0 4px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.nb-suggest-topic-candidate {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  background: var(--bg-secondary, #1f1f1f);
  transition: background 0.1s, border-color 0.1s, transform 0.05s;
}
.nb-suggest-topic-candidate:hover {
  border-color: var(--accent);
  background: var(--accent-bg, rgba(0, 120, 215, 0.08));
}
.nb-suggest-topic-candidate:active {
  transform: translateY(1px);
}
.nb-topic-candidate-title {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
  line-height: 1.3;
}
.nb-topic-candidate-rationale {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.45;
}

/* 2026-05-04 — expected_keywords chip row on each brainstorm candidate.
   Renders only when the AI tagged the topic with one or more program
   SEO keywords. Helps the operator pick based on SEO alignment, not
   just topic fit. Compact chips, accent-tinted so they read as data
   tags rather than interactive buttons. */
.nb-topic-candidate-keywords {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.nb-topic-candidate-keywords-label {
  font-size: 12px;
  color: var(--text-muted);
  margin-right: 2px;
}
.nb-topic-candidate-keyword-chip {
  display: inline-block;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text);
  background: var(--accent-bg, rgba(0, 120, 215, 0.18));
  border: 1px solid var(--accent, #2a8cff);
  border-radius: 10px;
  white-space: nowrap;
}

/* Slice E5.7+ — rewrite-path dedup picker. Reuses the candidate-row
   chrome (.nb-suggest-candidate styling) so the visual language is
   consistent: checkbox + question + answer-as-outline + optional
   warning badge. The .is-duplicate variant tints the row amber to
   signal the AI flagged it.

   Container override: the parent .nb-suggest-block defaults to a
   flex row with center alignment + wrap, which causes the picker's
   label / summary / list / count / hint to land on different visual
   rows with inconsistent left edges. Switching to column layout +
   stretch alignment lines everything up cleanly down the left edge. */
#nb-suggest-rewrite-dedup-block {
  flex-direction: column;
  align-items: stretch;
}
.nb-suggest-rewrite-dedup-list {
  list-style: none;
  margin: 8px 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nb-suggest-rewrite-dedup-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  background: var(--bg-secondary, #1f1f1f);
  transition: background 0.1s, border-color 0.1s;
}
.nb-suggest-rewrite-dedup-row:hover {
  border-color: var(--accent);
}
.nb-suggest-rewrite-dedup-row.selected {
  background: var(--accent-bg, rgba(0, 120, 215, 0.15));
  border-color: var(--accent);
}
.nb-suggest-rewrite-dedup-row.selected .nb-candidate-check {
  background: var(--accent);
  border-color: var(--accent);
}
.nb-suggest-rewrite-dedup-row.is-duplicate {
  border-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 6%, transparent);
}
.nb-suggest-rewrite-dedup-row.is-duplicate:hover {
  border-color: var(--warn);
}
.nb-rewrite-dedup-badge {
  margin-top: 6px;
  font-size: 11px;
  color: var(--warn);
  font-weight: 500;
}
.nb-suggest-rewrite-dedup-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 6px;
}

/* Content Types tab — Layer 2 override panels (slice C). Mirrors the
   AI step card chrome so the surface feels coherent with neighboring
   tabs. The panel header lays the title and Reset button on the same
   row. */
#pc-content-type-panels { margin-top: 16px; }
.pc-content-type-panel {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 16px 20px;
  margin-bottom: 14px;
}
.pc-content-type-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  gap: 12px;
}
.pc-content-type-panel-header h3 {
  font-size: 15px;
  font-weight: 600;
  margin: 0;
  color: var(--text);
}
.pc-content-type-panel .pc-tab-desc {
  margin: 0 0 14px;
  font-size: 13px;
}
.pc-content-type-panel .pc-field { margin-bottom: 12px; }
.pc-content-type-panel .pc-field:last-child { margin-bottom: 0; }

/* Help tooltips --------------------------------------------- */
.pc-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--panel-2);
  color: var(--text-dim);
  font-size: 10px;
  font-weight: 600;
  cursor: help;
  margin-left: 4px;
  user-select: none;
  border: 1px solid var(--border);
}
.pc-help:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

.pc-tooltip {
  position: fixed;
  max-width: 320px;
  padding: 8px 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text);
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  z-index: 1000;
  pointer-events: none;
}

/* Personas repeater ----------------------------------------- */
.pc-persona {
  margin-bottom: 16px;
  padding: 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.pc-persona-head {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
  align-items: center;
}
.pc-persona-name {
  flex: 1;
  padding: 6px 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
}
.pc-persona-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.pc-persona-grid .pc-field { margin-bottom: 0; }
@media (max-width: 720px) { .pc-persona-grid { grid-template-columns: 1fr; } }

/* ============================================================
   Brief pane (Phase 10) — tabbed Input pane with Files + Briefs
   ============================================================ */

/* Tabbed pane top bar. Same overall height (44px) as `.pane-header` so the
   Baselines/Briefs tab row aligns with the SnareScripted and Editor headers
   across the three-pane layout. */
.pane-tabs {
  display: flex;
  align-items: stretch;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  padding: 0 10px;
  flex: 0 0 auto;
  height: 44px;
}
.pane-tab {
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  padding: 0 14px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
  display: inline-flex;
  align-items: center;
}
.pane-tab:hover { color: var(--text); }
.pane-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Trailing element on the tab bar (e.g., the "ALL" select-all checkbox). */
.pane-tabs-trailing {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding: 0 4px 0 8px;
}
.pane-tabs-trailing input[type="checkbox"] {
  margin: 0;
}

/* Each tab body fills the remaining pane space. Display set by JS / hidden
   attribute, but when visible it must layout as a flex column. */
.pane-tab-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

/* Brief list -- same chrome as file-list, different item shape. */
.brief-list {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

/* Bulk-import drop overlay over the Briefs queue. Hidden by default; the
   JS sets `dragging` while a drag-with-files is over the queue, which
   lights up the overlay. Pointer-events stay enabled only while visible
   so a stale overlay can never block clicks on the brief rows. */
#briefs-step-queue { position: relative; }
.briefs-drop-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
  border: 2px dashed var(--accent);
  border-radius: 6px;
  z-index: 5;
  pointer-events: none;
}
.briefs-drop-overlay-msg {
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.brief-list li {
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.brief-list li:hover { background: var(--panel-2); }
.brief-list li.selected { background: var(--selected-bg); }

.brief-list-title {
  font-size: 12px;
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brief-list-meta {
  font-size: 10px;
  color: var(--text-dim);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

/* Status badges — plain-text, not glyph. */
.brief-badge {
  font-size: 9px;
  padding: 1px 6px;
  border-radius: 3px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.brief-badge-draft        { color: var(--text-dim); border-color: var(--border); }
.brief-badge-generating   { color: var(--accent);   border-color: var(--accent); background: rgba(47, 129, 247, 0.10); }
.brief-badge-awaiting     { color: var(--warn);     border-color: var(--warn); }
.brief-badge-approved     { color: var(--ok);       border-color: var(--ok); }
.brief-badge-rejected     { color: var(--error);    border-color: var(--error); }
/* Phase O7: permanently_failed terminal state — the system gave up on
   this entry (cost ceiling, max recovery attempts, or stuck-file
   timeout). Same visual weight as rejected so it draws operator
   attention without looking identical (lets the eye distinguish at
   a glance). */
.brief-badge-permfail     { color: var(--error);    border-color: var(--error); background: rgba(224, 75, 75, 0.12); }
.brief-badge-review       { color: var(--text-dim); border-color: var(--text-dim); }
/* Pre-generation lifecycle: needs_configuration = orange (warn family,
   matches AWAITING SnareScripting on the baseline side); configured =
   accent blue (actionable next step, ready for Generate). */
.brief-badge-needs-config { color: var(--warn);     border-color: var(--warn); }
.brief-badge-configured   { color: var(--pu);       border-color: var(--pu);     background: rgba(97, 72, 118, 0.10); }

/* Row action: destructive variant (e.g., trash icon for delete). */
.row-action.danger {
  color: var(--error);
}
.row-action.danger:hover {
  background: var(--error);
  color: #fff;
}

/* Rename dialog — checkbox row gets a bit of vertical breathing room. */
#rename-dialog .rn-cascade {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-dim);
  margin: 4px 0 8px;
}

/* Delete dialog — danger button styling. */
#delete-dialog .danger,
#del-submit.danger {
  background: var(--error);
  color: #fff;
  border-color: var(--error);
}
#delete-dialog .danger:hover {
  background: color-mix(in srgb, var(--error) 80%, black);
}

/* Empty state — shared across the file lists and brief list. */
.brief-list-empty,
.file-list-empty {
  padding: 24px 14px;
  color: var(--text-dim);
  font-size: 12px;
  text-align: center;
  line-height: 1.5;
  cursor: default;
  list-style: none;
}
.file-list-empty:hover { background: transparent; }

/* Review toolbar above editor when a brief is open ---------------------- */
.brief-review-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 14px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  gap: 10px;
}
.brief-review-status,
.output-review-status,
.baseline-review-status,
.approved-review-status {
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 500;
}

/* Output / baseline / approved review toolbars — same chrome as
   brief-review-toolbar so the editor pane has a consistent "what am I
   looking at + what can I do" strip regardless of pipeline step. */
.output-review-toolbar,
.baseline-review-toolbar,
.approved-review-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 14px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  gap: 10px;
}
.output-review-actions,
.baseline-review-actions {
  display: flex;
  gap: 8px;
}

/* Compact status pills used in queue rows — replaces the older full-width
   "DRAFT" / "APPROVED" / "STALE" badges. Single letter with a tooltip
   surfacing the full status + approver + timestamp on hover. Same idea
   for harvest indicators on .review.md rows. */
.status-pill,
.harvest-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  border-radius: 4px;
  flex: 0 0 auto;
  user-select: none;
}
.status-pill-draft { background: var(--panel-2); color: var(--text-dim); border: 1px solid var(--border); }
.status-pill-approved { background: #2c8a4f; color: #ffffff; }
.status-pill-stale { background: #c47526; color: #ffffff; }
.status-pill-review { background: var(--accent); color: #ffffff; }
.status-pill-input-changed {
  background: transparent;
  color: #c47526;
  border: 1px solid #c47526;
}
.harvest-pill-fresh { background: #2c8a4f; color: #ffffff; }
.harvest-pill-stale { background: #c47526; color: #ffffff; }

/* SEO score badge — lives in the brief-review-toolbar alongside the
   Request Revision / Approve buttons. Color band signals score
   (green/yellow/red); click opens the breakdown panel with per-check
   detail + Improve Further / Try Again Fresh actions. */
.seo-score-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  margin-left: 10px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 12px;
  border: 1px solid transparent;
  cursor: pointer;
  user-select: none;
  background: transparent;
  color: #ffffff;
  transition: filter 0.12s ease;
}
.seo-score-badge:hover { filter: brightness(1.1); }
.seo-score-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.seo-score-badge[hidden] { display: none; }
.seo-score-badge-icon { font-weight: 700; opacity: 0.9; }
.seo-score-badge.band-green  { background: #2c8a4f; }
.seo-score-badge.band-yellow { background: #c47526; }
.seo-score-badge.band-red    { background: #b04444; }

/* SEO breakdown panel — opens when the operator clicks the score badge.
   Absolute-positioned popover anchored to the editor-pane (which is
   position: relative). Floats over the textarea rather than fighting
   the flex column layout — that keeps it visible regardless of how
   the editor's CodeMirror overlay sizes itself. */
.editor-pane { position: relative; }
.seo-panel {
  position: absolute;
  top: 56px;
  left: 16px;
  right: 16px;
  z-index: 50;
  padding: 12px 16px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.28);
  font-size: 12px;
  color: var(--text);
  max-height: 60vh;
  overflow-y: auto;
}
.seo-panel[hidden] { display: none; }
.seo-panel-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.seo-panel-title {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}
.seo-panel-score {
  font-size: 22px;
  font-weight: 700;
}
.seo-panel-band {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding: 2px 8px;
  border-radius: 4px;
  background: var(--panel-3, var(--panel));
  color: var(--text-dim);
}
.seo-panel-band.band-green  { background: #2c8a4f; color: #ffffff; }
.seo-panel-band.band-yellow { background: #c47526; color: #ffffff; }
.seo-panel-band.band-red    { background: #b04444; color: #ffffff; }
.seo-panel-close {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 18px;
  cursor: pointer;
  padding: 0 6px;
  line-height: 1;
}
.seo-panel-close:hover { color: var(--text); }
.seo-panel-bar {
  height: 6px;
  background: var(--panel-3, var(--border));
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 10px;
}
.seo-panel-bar-fill {
  height: 100%;
  background: var(--text-dim);
  transition: width 0.25s ease, background-color 0.18s ease;
}
.seo-panel-bar-fill.band-green  { background: #2c8a4f; }
.seo-panel-bar-fill.band-yellow { background: #c47526; }
.seo-panel-bar-fill.band-red    { background: #b04444; }
.seo-panel-meta {
  color: var(--text-dim);
  font-size: 11px;
  margin-bottom: 10px;
}
.seo-panel-meta:empty { display: none; }
.seo-panel-localize-note {
  background: rgba(196, 117, 38, 0.10);
  border: 1px solid rgba(196, 117, 38, 0.35);
  border-left: 3px solid #c47526;
  padding: 8px 10px;
  border-radius: 4px;
  margin-bottom: 10px;
  font-size: 11px;
  line-height: 1.5;
}
.seo-panel-checks {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  gap: 4px 10px;
  margin-bottom: 12px;
}
.seo-panel-check {
  display: contents;
}
.seo-panel-check-icon {
  font-weight: 700;
  text-align: center;
}
.seo-panel-check.passed .seo-panel-check-icon { color: #4caf50; }
.seo-panel-check.failed .seo-panel-check-icon { color: #e57373; }
.seo-panel-check.not-applicable .seo-panel-check-icon { color: var(--text-dim); }
.seo-panel-check-body {
  display: flex;
  flex-direction: column;
}
.seo-panel-check-label {
  font-weight: 500;
}
.seo-panel-check-detail {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 1px;
}
.seo-panel-check-weight {
  font-size: 11px;
  color: var(--text-dim);
  white-space: nowrap;
  align-self: baseline;
}
.seo-panel-actions {
  display: flex;
  gap: 12px;
  align-items: center;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}
.seo-panel-actions .brief-btn { font-size: 12px; }
.seo-panel-actions .brief-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.seo-panel-actions-note {
  font-size: 11px;
  color: var(--text-dim);
}

/* In-flight spinner overlay — covers the panel content during the
   Improve Further round-trip. The dim background prevents accidental
   clicks on the breakdown rows / Close button while the LLM call is
   running; the centered spinner + label is unmissable. */
.seo-panel-spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 8px;
  z-index: 60;
  font-size: 13px;
  font-weight: 500;
  color: #ffffff;
}
.seo-panel-spinner[hidden] { display: none; }
.seo-panel-spinner-dot {
  width: 20px;
  height: 20px;
  border: 2px solid rgba(255, 255, 255, 0.25);
  border-top-color: #2c8a4f;
  border-radius: 50%;
  animation: seo-spin 0.85s linear infinite;
}
@keyframes seo-spin {
  to { transform: rotate(360deg); }
}

/* Row-action buttons (✎ rename, 🗑 delete) stay hidden by default and
   reveal on row hover or focus. Keeps the queue visually quiet during
   scanning; the badges + topic + timestamp are the primary content.
   Applies uniformly across briefs, baselines, and SnareScripted lists. */
.row-actions {
  opacity: 0;
  transition: opacity 0.12s ease;
}
li:hover .row-actions,
li:focus-within .row-actions,
li.selected .row-actions {
  opacity: 1;
}

/* Row-level activity feedback: a spinner + accent border surface on the
   row whose file/brief is currently being processed by a run. Pairs with
   the corner run strip (which holds cost/cancel/etc.) so the user sees
   *where* the work is happening without having to look at chrome. */
.row-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 6px;
  flex: 0 0 auto;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: row-spinner-rot 0.8s linear infinite;
  vertical-align: middle;
}

/* Meta-line variant — smaller, tighter, paired with the 9px badge so the
   spinner and the GENERATING label read as one visual unit. */
.row-spinner-meta {
  width: 9px;
  height: 9px;
  border-width: 1.5px;
  margin-right: 4px;
}

@keyframes row-spinner-rot {
  to { transform: rotate(360deg); }
}

.row-active {
  border-left: 3px solid var(--accent);
  background: rgba(0, 166, 220, 0.06);
}

/* Timestamp pill on brief rows — same visual weight as the file-meta
   timestamp on file rows so editors get a consistent "last touched" cue. */
.brief-list-ts {
  font-size: 10px;
  color: var(--text-dim);
  margin-left: auto;
  flex: 0 0 auto;
  white-space: nowrap;
}

/* Phase 16 Slice 3i — "last event by User" subtitle pill on brief rows.
   Sits between the status badge and the timestamp; same muted style
   as the timestamp so the row still reads as a single metadata line. */
.brief-list-user {
  font-size: 10px;
  color: var(--text-dim);
  margin-left: 8px;
  flex: 0 0 auto;
  white-space: nowrap;
}
.brief-list-user + .brief-list-ts {
  margin-left: 6px;
}
.brief-list-user + .brief-list-ts::before {
  content: "· ";
  color: var(--text-dim);
  opacity: 0.6;
}

/* Phase 16 Slice 3i — Activity audit block in the editor pane.
   Renders the 4 lifecycle events (created / baseline_approved /
   snarescripted / final_approved) with US Eastern timestamps. Subtle
   bordered metadata strip — clearly distinct from the action toolbar
   above it but not visually loud. */
.brief-activity {
  border-top: 1px solid var(--border);
  padding: 8px 16px;
  background: var(--panel);
  font-size: 12px;
  color: var(--text-dim);
}
.brief-activity-heading {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.brief-activity-row {
  line-height: 1.6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brief-activity-label {
  color: var(--text-dim);
}
.brief-activity-user {
  color: var(--text);
  font-weight: 500;
}
.brief-activity-ts {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.brief-review-actions { display: flex; gap: 8px; }
.brief-btn {
  padding: 5px 12px;
  font-size: 12px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}
.brief-btn:hover:not(:disabled) { background: var(--border); }
.brief-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.brief-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.brief-btn-primary:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* New Brief form layout ------------------------------------------------ */
.nb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: 10px 12px;
  margin-bottom: 12px;
}
.nb-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--text);
  margin-bottom: 12px;
}
/* Required-field highlight — orange left-bar on inputs / selects whose
   value is still empty so the editor sees at a glance which fields are
   blocking Save. Same warn color as the AWAITING SnareScripting badge so
   the visual language stays consistent. JS toggles ``.nb-required-empty``
   on the wrapping label as the value changes. */
.nb-field.nb-required-empty input,
.nb-field.nb-required-empty select,
.nb-field.nb-required-empty textarea {
  border-left: 3px solid var(--warn);
}

.nb-field input,
.nb-field select,
.nb-field textarea {
  width: 100%;
  padding: 6px 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-family: inherit;
  font-size: 12px;
}
.nb-field textarea { resize: vertical; }

/* Content tier picker — operator-readable description rendered under
   the dropdown so the rationale for the chosen tier is visible while
   filling out the form. Same for the below-recommended word-count
   warning. Both are dim/secondary text by default; the warning gets
   an amber accent to draw attention without alarming. Description
   reads as italic hint copy (visually subordinate to the select +
   inputs around it) and is constrained to the field column width so
   it wraps cleanly. */
.nb-row-full { grid-column: 1 / -1; }
.nb-content-tier-description {
  display: block;
  font-size: 11px;
  color: var(--text-dim);
  margin-top: -4px;
  padding: 6px 10px;
  border-left: 2px solid var(--border);
  background: var(--bg-soft, transparent);
  border-radius: 0 3px 3px 0;
  line-height: 1.5;
  font-style: italic;
}
.nb-content-tier-description:empty { display: none; }
.nb-word-count-warning {
  display: block;
  font-size: 11px;
  color: #c47526;
  margin-top: 6px;
  padding-left: 8px;
  border-left: 2px solid #c47526;
  line-height: 1.45;
}
.nb-word-count-warning[hidden] { display: none; }
.nb-hint { color: var(--text-dim); font-size: 10px; }
.nb-col-1 { grid-column: span 2; }

/* Slice E5.4 follow-up — context-aware instructions panel at the top of the
   New Brief dialog. JS renders different copy per content type, with rich
   structure (bold, lists). Sized so it sits comfortably above the form
   fields without dominating the dialog. */
.nb-instructions {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-left: 3px solid var(--accent, #4080ff);
  background: var(--panel-2, rgba(64, 128, 255, 0.05));
  border-radius: 4px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
}
.nb-instructions p {
  margin: 0 0 8px;
}
.nb-instructions p:last-child {
  margin-bottom: 0;
}
.nb-instructions ul,
.nb-instructions ol {
  margin: 6px 0 8px;
  padding-left: 22px;
}
.nb-instructions li {
  margin-bottom: 4px;
}
.nb-instructions strong {
  color: var(--text);
}
.nb-instructions em {
  font-style: italic;
  color: var(--text);
}

/* Slice E5.4e — live mode-detection chip above the Source Content textarea
   for FAQ briefs. Two visual modes: PROD_IMPORT (Q:/A: detected → blue) and
   GROUND (prose detected → green). Subtle pill so it's noticed without
   competing with the form. Hidden via the ``hidden`` attribute when the
   chip doesn't apply. */
.nb-source-mode-chip {
  display: inline-block;
  margin: 4px 0 6px;
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 500;
  border: 1px solid transparent;
}
.nb-source-mode-chip.is-prod-import {
  background: rgba(64, 128, 255, 0.10);
  border-color: rgba(64, 128, 255, 0.35);
  color: var(--accent, #4080ff);
}
.nb-source-mode-chip.is-ground {
  background: rgba(64, 192, 96, 0.10);
  border-color: rgba(64, 192, 96, 0.35);
  color: rgb(64, 160, 80);
}

/* Slice E5.7+ — REWRITE_SOURCE decision block. FAQ-only, shown below
   the Source field when Q:/A: format is detected. Visually framed as a
   single decision unit (border + padding) so the two-radio choice
   reads as one question with two answers, not two stray inputs.
   2026-05-19: shared with .nb-source-mode-block (Localize-only L1) — same
   two-radio decision pattern, same visual frame. */
.nb-rewrite-source-block,
.nb-source-mode-block {
  margin: 8px 0 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.nb-rewrite-source-legend,
.nb-source-mode-legend {
  padding: 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
.nb-rewrite-source-option,
.nb-source-mode-option {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 10px;
  row-gap: 2px;
  padding: 6px 4px;
  cursor: pointer;
  user-select: none;
  border-radius: 4px;
}
.nb-rewrite-source-option:hover,
.nb-source-mode-option:hover {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.nb-rewrite-source-option input[type="radio"],
.nb-source-mode-option input[type="radio"] {
  /* Override .nb-field input { width: 100% } — without this the radio's
     click area stretches across the grid column and the dot visually
     centers inside that wide area instead of sitting flush-left next to
     the label. Same fix applies to the FAQ rewrite-source radio. */
  width: auto;
  /* Match the intrinsic radio size; padding from .nb-field input would
     otherwise pad the click area. */
  padding: 0;
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  justify-self: start;
  margin: 3px 0 0;
  cursor: pointer;
}
.nb-rewrite-source-option-label,
.nb-source-mode-option-label {
  grid-column: 2;
  grid-row: 1;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.nb-rewrite-source-option-hint,
.nb-source-mode-option-hint {
  grid-column: 2;
  grid-row: 2;
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.35;
}

/* AI-Suggest button row + suggestion panel inside the New Brief dialog.
   Panel only renders after a successful Suggest call; visual treatment
   is intentionally subtle so it doesn't dominate the dialog when present
   and disappears entirely otherwise. */
.nb-suggest-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
}
.nb-suggest-row button {
  padding: 4px 12px;
  font-size: 12px;
}
.nb-suggest-status {
  font-size: 11px;
  color: var(--text-dim);
}
.nb-suggest-panel {
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel-2);
}
.nb-suggest-header {
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.nb-suggest-meta {
  font-size: 10px;
  font-weight: 400;
  color: var(--text-dim);
  text-transform: none;
  letter-spacing: 0;
  margin-left: 6px;
}
.nb-suggest-block {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
}
.nb-suggest-block:first-of-type { border-top: 0; }
.nb-suggest-label {
  font-size: 11px;
  color: var(--text-dim);
  min-width: 160px;
}
.nb-suggest-value {
  font-size: 12px;
  color: var(--text);
  flex: 1;
}
.nb-suggest-use {
  padding: 2px 10px;
  font-size: 11px;
}
.nb-suggest-keywords-block {
  flex-direction: column;
  align-items: stretch;
}

/* Slice E5.7 — dedup signal block. Pinned at the top of the Suggest panel
   so a duplicate-warning is the first thing the operator sees. Two
   variants share this container: warning card (amber, decision UI) and
   quiet confirmation (green check, single line). The block hides
   entirely when the AI returned no signal. */
.nb-dedup-block {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 8px 0;
}
.nb-dedup-warning {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--warn);
  border-radius: 6px;
  background: color-mix(in srgb, var(--warn) 10%, transparent);
}
.nb-dedup-warning-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.nb-dedup-warning-icon {
  color: var(--warn);
  font-size: 16px;
  line-height: 1;
}
.nb-dedup-warning-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.nb-dedup-warning-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nb-dedup-matched-row,
.nb-dedup-alternate-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px;
}
.nb-dedup-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-dim);
  min-width: 130px;
}
.nb-dedup-matched,
.nb-dedup-alternate {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
}
.nb-dedup-explanation {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.4;
}
.nb-dedup-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}
.nb-dedup-btn {
  padding: 4px 12px;
  font-size: 12px;
}
.nb-dedup-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.nb-dedup-btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
.nb-dedup-btn-quiet {
  background: transparent;
  color: var(--text-dim);
}
/* Quiet-confirmation variant — single row, green check, low-weight copy.
   No buttons; pure reassurance signal. */
.nb-dedup-novel {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
  font-size: 11px;
  color: var(--text-dim);
}
.nb-dedup-novel-icon {
  color: var(--ok);
  font-weight: 600;
}

/* Suggested-topic inline edit input. Same chrome as the .nb-field inputs
   so the user perceives it as "you can edit me before pressing Use" not
   as a static label. The word-count hint sits to its right. */
.nb-suggest-topic-input {
  flex: 1;
  padding: 4px 8px;
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
}
.nb-suggest-topic-count {
  font-size: 10px;
  color: var(--text-dim);
  min-width: 50px;
  text-align: right;
}
.nb-suggest-topic-count.over { color: var(--warn); font-weight: 600; }

/* Per-row Add all + Clear buttons live inside the row to the right of
   the chip strip. Smaller and quieter than the primary Apply action. */
.nb-kw-add-all,
.nb-kw-clear {
  font-size: 11px;
  padding: 2px 10px;
  align-self: flex-start;
  margin-top: 2px;
}

/* One row per source: extracted, suggested, selected. Each row leads with
   a small label so the editor sees the origin at a glance. */
.nb-kw-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 4px 0;
}
.nb-kw-row-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--text-dim);
  min-width: 150px;
  padding-top: 4px;
}
.nb-kw-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1;
}
.nb-kw-empty {
  font-size: 11px;
  color: var(--text-dim);
  font-style: italic;
  padding: 4px 0;
}

/* Click-toggle chips. Default state = unselected, faint border; ``.selected``
   highlights when the chip is in the working set. Visual difference between
   extracted / suggested origins kept subtle (left-bar color) so the focus
   stays on selected vs. not-selected. */
.nb-kw-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  font-size: 11px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  user-select: none;
  transition: background 0.1s, border-color 0.1s;
}
.nb-kw-chip:hover { border-color: var(--accent); }
.nb-kw-chip.selected {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: var(--accent);
  color: var(--text);
}
.nb-kw-chip[data-origin="extracted"] { border-left: 3px solid #2c8a4f; }
.nb-kw-chip[data-origin="suggested"] { border-left: 3px solid var(--accent); }
.nb-kw-chip[data-origin="custom"]    { border-left: 3px solid #c47526; }
/* Program keywords (2026-05-04) — sourced from program.baseline.seo_keywords
   via the picked brainstorm candidate's expected_keywords. Distinct purple
   left-bar to read as program-strategy data, not AI-generated, so the
   operator can tell at a glance which chips trace back to the configured
   SEO list. */
.nb-kw-chip[data-origin="program"] { border-left: 3px solid #8b5cf6; }

/* ===== New Brief: SEO Keywords chip view (live preview of the
   comma-separated input). First chip carries the PRIMARY badge so the
   operator can see + change which keyword drives the SEO score. Click
   any non-primary chip to promote it to position 0. ============== */
#nb-keywords-chips {
  margin-top: 6px;
  min-height: 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
#nb-keywords-chips .nb-kw-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px 3px 10px;
  font-size: 11px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  user-select: none;
  transition: background 0.1s, border-color 0.1s;
}
#nb-keywords-chips .nb-kw-pill:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
#nb-keywords-chips .nb-kw-pill.is-primary {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-color: var(--accent);
  cursor: default;
  font-weight: 600;
  padding-left: 8px;
}
#nb-keywords-chips .nb-kw-pill.is-primary:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
#nb-keywords-chips .nb-kw-pill-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--accent);
  text-transform: uppercase;
}
#nb-keywords-chips .nb-kw-pill-remove {
  color: var(--text-dim);
  font-weight: 700;
  font-size: 13px;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
}
#nb-keywords-chips .nb-kw-pill-remove:hover { color: var(--error, #ff5555); }
#nb-keywords-chips .nb-kw-empty-hint {
  font-size: 11px;
  color: var(--text-dim);
  font-style: italic;
}
/* Order-of-selection hint at the bottom of the Suggest + Localize
   keyword pickers. Tells the operator the first keyword in their
   selection becomes the primary SEO target — taught at the moment
   they're picking, not on every glance at the SEO Keywords field. */
.nb-kw-order-hint {
  margin: 10px 0 6px 0;
  padding: 8px 10px;
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-radius: 0 4px 4px 0;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text);
}
.nb-kw-order-hint strong {
  color: var(--text);
  font-weight: 600;
}

/* 2026-05-19 — Localize-only L3 chip-review panel. Reuses .nb-suggest-panel
   styles for the outer frame + .nb-kw-chip styles for the keyword picker.
   These rules style the variable-substitution + protected-phrase lists. */
.nb-localize-varlist,
.nb-localize-protlist {
  list-style: none;
  padding: 0;
  margin: 4px 0 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.nb-localize-varrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}
.nb-localize-varlabel {
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  color: var(--text);
}
.nb-localize-protlist li {
  font-size: 12px;
  color: var(--text);
  padding: 2px 0;
}

/* Chips inside the Selected row use an X-button to remove. */
.nb-kw-chips-selected .nb-kw-chip-remove {
  cursor: pointer;
  color: var(--text-dim);
  font-weight: 700;
  margin-left: 2px;
}
.nb-kw-chips-selected .nb-kw-chip-remove:hover { color: var(--error, #ff5555); }

.nb-kw-add {
  display: flex;
  gap: 6px;
  margin: 8px 0 4px 160px;
}
.nb-kw-add input {
  flex: 1;
  padding: 4px 8px;
  font-size: 12px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
}
.nb-kw-add button {
  padding: 4px 12px;
  font-size: 11px;
}
.nb-kw-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 6px;
}
.nb-suggest-specifics {
  margin: 0;
  padding-left: 180px;
  font-size: 12px;
  list-style: none;
}
.nb-suggest-specifics li {
  padding: 2px 0;
  color: var(--text);
}
.nb-suggest-specifics .specific-text {
  font-weight: 600;
}
.nb-suggest-specifics .specific-arrow {
  color: var(--text-dim);
  margin: 0 6px;
}
.nb-suggest-specifics .specific-suggest {
  color: var(--accent);
  font-family: var(--mono, monospace);
}
.nb-grid .nb-field { margin-bottom: 0; }
@media (max-width: 780px) {
  .nb-grid { grid-template-columns: 1fr 1fr; }
  .nb-col-1 { grid-column: span 2; }
}

/* Type-specific field groups inside the New Brief form. Each fieldset is
   shown/hidden based on the selected Content Type. */
.nb-typefields {
  margin: 0 0 14px;
  padding: 10px 14px 4px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel);
}
.nb-typefields legend {
  padding: 0 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--accent);
}
.nb-typefields .nb-grid { margin-bottom: 10px; }

/* Revise dialog — feedback textarea fills the dialog width and is tall enough
   to be usable without having to drag the corner to resize. */
#revise-dialog .rv-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: var(--text);
  margin-bottom: 12px;
  min-width: 520px;
  max-width: 720px;
}
#revise-dialog .rv-field textarea {
  width: 100%;
  min-height: 180px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.55;
  resize: vertical;
}
#revise-dialog .rv-field textarea:focus {
  outline: none;
  border-color: var(--accent);
}
#revise-dialog .dialog-body {
  max-width: 640px;
  color: var(--text-dim);
}

/* ============================================================
   Pipeline navigation — primitive for the step-driven dashboard.
   Replaces the old .three-pane layout. The pipeline strip lists
   every step in process order; selecting one shows that step's
   queue (left) + the editor (right). Adding a step = appending
   another `.pipeline-step` button + a `.step-queue` div.
   ============================================================ */

.pipeline-shell {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
  min-height: 0;
}

.pipeline-strip {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  padding: 0 16px;
  height: 48px;
  flex: 0 0 auto;
  overflow-x: auto;
  white-space: nowrap;
}

.pipeline-step {
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  padding: 6px 14px;
  cursor: pointer;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.pipeline-step:hover {
  background: var(--panel-2);
  color: var(--text);
}

.pipeline-step.active {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

/* Count badge — explicit color (not inherited) so it stays legible across
   active/inactive tab states + light/dark themes. On the active tab the
   accent fill swallowed the count when it inherited white at low opacity;
   the pill background gives the number its own contrast surface. */
.pipeline-step .count {
  font-weight: 600;
  font-size: 11px;
  color: var(--text);
  background: var(--panel-2);
  padding: 1px 7px;
  border-radius: 999px;
  min-width: 20px;
  text-align: center;
  line-height: 1.4;
}

.pipeline-step:hover .count {
  background: var(--panel);
}

.pipeline-step.active .count {
  color: #ffffff;
  background: rgba(255, 255, 255, 0.22);
}

/* Activity badge — ambient indicator of in-flight work for this step.
   Hidden when idle (empty content). Two visible states:

   * .running — green dot + count; the step has N runs in flight.
   * .paused  — amber dot + "paused"; the shared circuit breaker is
     paused so dispatch is blocked across all steps.

   Sits inside the step button so glancing at the strip from any
   pipeline view answers "is anything happening over there?" without
   the operator switching steps. See renderPipelineActivity in
   portal.js. */
.pipeline-step .activity {
  font-weight: 600;
  font-size: 11px;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  line-height: 1.4;
  background: transparent;
  color: transparent;
  display: none;
}
.pipeline-step .activity.running,
.pipeline-step .activity.paused {
  display: inline-block;
}
.pipeline-step .activity.running {
  background: rgba(80, 200, 120, 0.18);
  color: #5fc88a;
}
/* Active step is filled with --accent (solid blue). The previous
   translucent-white treatment blended into the blue and was hard to
   read — surfaced 2026-05-14. Inverted stamp (solid white pill +
   accent text) pops cleanly against the filled step background. */
.pipeline-step.active .activity.running {
  background: #ffffff;
  color: var(--accent);
}
.pipeline-step .activity.paused {
  background: rgba(230, 168, 60, 0.20);
  color: #e6a83c;
}
/* Same inversion for paused — keep amber semantics by using a saturated
   amber pill on the active step instead of washed-out translucent. */
.pipeline-step.active .activity.paused {
  background: #ffd070;
  color: #5a3d00;
}

.pipeline-arrow {
  color: var(--text-dim);
  font-size: 14px;
  user-select: none;
  opacity: 0.55;
}

/* Item filter — segmented switch on the right side of the pipeline strip.
   ``margin-left: auto`` pushes it past the last tab + arrow without
   needing a flex spacer element. */
.pipeline-strip-actions {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel-2);
  overflow: hidden;
}

.pipeline-toggle {
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  padding: 5px 12px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.pipeline-toggle:hover:not(.active) {
  background: var(--panel);
  color: var(--text);
}

.pipeline-toggle.active {
  background: var(--accent);
  color: #ffffff;
}

/* Step content — 2-column grid: queue (left) + editor (right). */
.step-content {
  display: grid;
  grid-template-columns: 380px 1fr;
  flex: 1;
  overflow: hidden;
  min-height: 0;
}

.queue-pane {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border);
  background: var(--panel);
  min-width: 0;
  overflow: hidden;
}

/* One queue per step. Hidden until its step is active. */
.step-queue {
  flex: 1 1 auto;
  display: none;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.step-queue.active {
  display: flex;
}

.queue-title {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

/* Trailing controls inside the queue's pane-header (select-all checkbox on
   Baselines, view-mode dropdown on SnareScripted). Sized to fit the 44px
   header. ``data-only-step`` gates per-step visibility. */
.queue-header-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

.queue-header-controls select {
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
}

.queue-header-controls .select-all-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.queue-header-controls .select-all-toggle input[type="checkbox"] {
  margin: 0;
}

/* Chip filter row inside a queue. Height locked to 44px so it aligns
   horizontally with .pane-header (the editor-pane title bar). Generic
   container — every queue gets one; the chip set is rendered dynamically
   from /api/content-types so adding a content type updates all chips. */
.filter-chips {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 12px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  flex: 0 0 auto;
  height: 44px;
}

.filter-chips-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
}

.filter-chips-trailing {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

/* Trailing controls inside a filter-chips row sized to fit the 44px height. */
.filter-chips-trailing select {
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
}

.filter-chips-trailing .select-all-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}

.filter-chips-trailing .select-all-toggle input[type="checkbox"] {
  margin: 0;
}

.chip {
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.chip:hover {
  color: var(--text);
  border-color: var(--text-dim);
}

.chip.active {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

/* Small text marker placed on .review.md rows in the file list — replaces
   the visible ".review.md" extension which was noisy for editors. The
   row's existing kind-based background remains as a secondary cue. */
.file-review-tag {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 3px;
  flex: 0 0 auto;
}


/* ----- Lifecycle Report dialog -------------------------------------------
   Per-program time/cost/quality breakdown by pipeline step. Opens from the
   Lifecycle Report button in the topbar. Active program preselected; range
   defaults to last 30 days. Quality section + reset button land in S2/S3.
*/
.lifecycle-dialog {
  width: min(960px, 90vw);
  max-height: 86vh;
  overflow: hidden;
}

/* Browsers default <dialog> to display: none until opened. The flex layout
   only applies when the dialog is actually open — otherwise the rule below
   would force the dialog visible at page load (the bug we just fixed). */
.lifecycle-dialog[open] {
  display: flex;
  flex-direction: column;
}

.lifecycle-dialog[open] form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
  min-height: 0;
}

/* Program name as a subtitle next to the page title. Reads as
   "Lifecycle Report — sheridan" with the program name dimmed so it's
   clear context, not headline. Same shape as Configure's
   .pc-program-name + the leading em-dash separator. */
.lifecycle-program-subtitle {
  font-size: 13px;
  color: var(--text-dim);
}

.lifecycle-program-subtitle:not(:empty)::before {
  content: "—";
  margin-right: 8px;
}

/* View-controls row at the top of the body — Range filter on the left,
   Reset (destructive) far right. Sits inside .pc-body so the header
   stays a single-row identity bar that matches Configure / Settings /
   Run History exactly. */
.lifecycle-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}

.lifecycle-range-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
}

.lifecycle-range-label select {
  font-size: 12px;
}

.lifecycle-tracking {
  font-size: 12px;
  color: var(--text-dim);
}

.lifecycle-reset-btn {
  font-size: 12px;
  padding: 4px 10px;
  background: transparent;
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 3px;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background-color 0.12s ease;
}

.lifecycle-reset-btn:hover {
  color: var(--text);
  border-color: var(--text-dim);
}

.lifecycle-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* Constrain the Lifecycle body content to the same max-width Configure
   and Settings use for their .pc-tab-panel surfaces. Keeps the page
   from sprawling edge-to-edge on wide monitors and gives the four
   full-page surfaces a uniform reading-width so the chrome feels
   consistent. The .pc-body padding still applies; this just centers
   each section inside the available width. */
.lifecycle-body > * {
  max-width: 900px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.lifecycle-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-dim);
}

.lifecycle-section h4 {
  margin: 0 0 8px 0;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}

.lifecycle-table-wrap {
  overflow-x: auto;
}

.lifecycle-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.lifecycle-table th,
.lifecycle-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

.lifecycle-table th {
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: 0.4px;
  background: var(--panel-2);
}

.lifecycle-table .col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.lifecycle-section-hint {
  margin: 0 0 10px 0;
  font-size: 11.5px;
  color: var(--text-dim);
  line-height: 1.4;
}

/* Cost & time totals — uniform 2-row table that visually matches the
   by-step table above it (same row backgrounds, header treatment, and
   border style). The only structural difference: the row-head column
   carries a label like "Last 30 days" / "Lifetime" instead of a step
   name. Keeping the styling identical is intentional — both tables
   present the same shape of data, just rolled up differently. */
.lifecycle-totals-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.lifecycle-totals-table th,
.lifecycle-totals-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: middle;
}

.lifecycle-totals-table thead th {
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: 0.4px;
  background: var(--panel-2);
}

.lifecycle-totals-table .col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.lifecycle-cost-totals-rowhead {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

/* Action-needed chart: five vertical bars, equal-width columns, fixed
   chart height. Each column has count above, bar in the middle, label
   below. Bar height is computed in JS as a percentage of the tallest
   non-zero bar, so the visual scales to "where the work is piling up". */
.lifecycle-action-chart {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  height: 180px;
  padding: 6px 4px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
}

.lifecycle-action-chart-msg {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-style: italic;
  color: var(--text-dim);
}

.lifecycle-bar-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.lifecycle-bar-count {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  height: 18px;
  line-height: 18px;
}

.lifecycle-bar-track {
  flex: 1 1 auto;
  width: 60%;
  min-width: 28px;
  max-width: 64px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.lifecycle-bar {
  width: 100%;
  background: var(--accent);
  border-radius: 3px 3px 0 0;
  transition: height 0.15s ease;
}

.lifecycle-bar.terminal {
  /* Terminal "Approved (complete)" bar — a distinct success-oriented hue
     so the visual makes "this is the done pile" obvious. Greenish tone so
     the eye reads it as success rather than a fifth flavor of action. */
  background: #2ea061;
}

.lifecycle-bar-label {
  font-size: 10.5px;
  text-align: center;
  color: var(--text-dim);
  line-height: 1.2;
  height: 26px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

.lifecycle-action-totals {
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--text-dim);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.lifecycle-quality {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.lifecycle-quality-headline {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.lifecycle-quality-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
  min-width: 0;  /* lets the grid track shrink uniformly */
}

.lifecycle-quality-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.lifecycle-quality-label {
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.lifecycle-quality-trend {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.lifecycle-quality-trend-title {
  margin: 0;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}

.lifecycle-quality-svg-wrap {
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
  padding: 8px;
}

.lifecycle-quality-svg {
  width: 100%;
  height: auto;
  display: block;
}

.lifecycle-quality-empty {
  margin: 0;
  padding: 14px;
  font-size: 12px;
  font-style: italic;
  color: var(--text-dim);
  text-align: center;
}

/* ============================================================
   AI Assist dialog (Slice 1) — overlays the Program Configuration
   page. Native <dialog> element. Multi-step wizard: scenario →
   inputs → running → review → done.
   ============================================================ */

.ai-assist-dialog {
  width: min(900px, 95vw);
  max-height: 90vh;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  color: var(--text);
}

.ai-assist-dialog::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

.aia-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--panel-2);
}

.aia-header h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}

.aia-close {
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-size: 22px;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 4px;
}

.aia-close:hover { background: var(--panel); color: var(--text); }

.aia-body {
  padding: 18px;
  overflow-y: auto;
  max-height: calc(90vh - 60px);
}

.aia-step h3 {
  margin: 0 0 8px 0;
  font-size: 14px;
  font-weight: 600;
}

.aia-help {
  margin: 0 0 16px 0;
  font-size: 13px;
  color: var(--text-dim);
  line-height: 1.4;
}

.aia-step-actions {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.aia-step-actions > :only-child {
  margin-left: auto;
}

/* Step 1 — scenario picker */

.aia-scenario-options {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.aia-scenario-option {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  gap: 4px 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: border-color 0.12s, background-color 0.12s;
}

.aia-scenario-option:hover { background: var(--panel-2); }

.aia-scenario-option input[type="radio"] {
  grid-row: 1 / 3;
  align-self: center;
  margin: 0;
}

.aia-scenario-option strong {
  font-size: 13px;
  font-weight: 600;
}

.aia-scenario-option span {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.4;
}

.aia-scenario-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--panel-2);
}

/* Mode picker (Slice B4) — vertical list of action cards for
   programs that already have scenario + premise + populated fields. */
.aia-mode-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
}

.aia-mode-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.12s, background-color 0.12s;
}

.aia-mode-card:hover { background: var(--panel-2); border-color: var(--accent); }

.aia-mode-title {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 4px;
}

.aia-mode-desc {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.4;
}

.aia-mode-card-danger:hover { border-color: var(--danger, #c44); }

/* Step 2 — inputs */

.aia-input-group {
  margin-bottom: 14px;
}

.aia-label {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  font-weight: 600;
}

.aia-optional {
  font-weight: 400;
  color: var(--text-dim);
}

.aia-input-group input[type="url"],
.aia-input-group textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
}

.aia-input-group textarea {
  resize: vertical;
  min-height: 60px;
}

.aia-field-hint {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-dim);
}

.aia-materials-list {
  list-style: none;
  margin: 0 0 8px 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  min-height: 32px;
  max-height: 200px;
  overflow-y: auto;
}

.aia-materials-empty {
  padding: 10px 12px;
  font-size: 12px;
  color: var(--text-dim);
  font-style: italic;
}

.aia-material-item {
  display: flex;
  align-items: center;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
}

.aia-material-item:last-child { border-bottom: 0; }

.aia-mat-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.aia-mat-size {
  margin-left: 8px;
  color: var(--text-dim);
  font-size: 11px;
}

.aia-mat-delete {
  margin-left: 8px;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-size: 16px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
  border-radius: 3px;
}

.aia-mat-delete:hover { background: var(--panel-2); color: var(--text); }

.aia-materials-actions {
  display: flex;
  gap: 8px;
}

/* Multi-URL repeater rows. Each row = url input + delete button. */
.aia-url-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}

.aia-url-row {
  display: flex;
  gap: 6px;
  align-items: center;
}

.aia-url-row input[type="url"] {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
}

.aia-url-delete {
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1;
  padding: 6px 10px;
  border-radius: 4px;
  cursor: pointer;
}

.aia-url-delete:hover {
  background: var(--panel);
  color: var(--text);
}

/* Inline help marker on labels (matches the existing pc-help pattern). */
.aia-help-hover {
  display: inline-block;
  width: 14px;
  height: 14px;
  text-align: center;
  line-height: 14px;
  font-size: 10px;
  font-weight: 700;
  color: var(--text-dim);
  background: var(--panel-2);
  border-radius: 50%;
  cursor: help;
  margin-left: 4px;
}

/* Per-field "✦ AI" refine button (Slice 2). Sits inside the field's
   <label> alongside the help icon. Subtle by default; pops on hover.
   Operator clicks → mini-dialog opens for refining that one field. */
.pc-ai-refine {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--accent);
  border-radius: 3px;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
  transition: background-color 0.12s, color 0.12s, border-color 0.12s;
}

.pc-ai-refine:hover {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

/* AI confidence badge — sits next to the ✦ button on each Tier A
   field's label. Set by JS from the program's stored confidence
   map; cleared on manual edit. Same color scheme as the in-dialog
   confidence badges so the visual language is consistent. */
.pc-ai-conf-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  vertical-align: middle;
  text-transform: uppercase;
  line-height: 1.6;
}

.pc-ai-conf-badge.pc-ai-conf-high   { background: rgba(40, 180, 100, 0.15); color: #28a; }
.pc-ai-conf-badge.pc-ai-conf-medium { background: var(--panel-2); color: var(--text-dim); }
.pc-ai-conf-badge.pc-ai-conf-low    { background: rgba(204, 170, 0, 0.18); color: #b80; }

/* Slice 2.9 — calibrated rule field state badges + Restore-default
   link + Rules-tab calibration note. The five rule fields
   (protected_definition, market_type_rules, output_formatting_rules,
   seo_rules, content_creation_rules) display a SYSTEM DEFAULT or
   CUSTOMIZED badge so the operator knows which fields are at the
   calibration baseline vs operator-overridden. */

.pc-rule-state-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  vertical-align: middle;
  text-transform: uppercase;
  line-height: 1.6;
}

.pc-rule-state-badge.pc-rule-state-default {
  background: var(--panel-2);
  color: var(--text-dim);
}

.pc-rule-state-badge.pc-rule-state-customized {
  background: rgba(204, 170, 0, 0.18);
  color: #b80;
}

.pc-rule-restore {
  margin-left: 6px;
  padding: 1px 7px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text-dim);
  border-radius: 3px;
  font-size: 11px;
  line-height: 1.4;
  cursor: pointer;
  vertical-align: middle;
}

.pc-rule-restore:hover {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

.pc-rules-calibration-note {
  padding: 12px 14px;
  margin: 0 0 14px 0;
  background: var(--panel-2);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-dim);
}

.pc-rules-calibration-note strong {
  color: var(--text);
}

/* Admin button on the topbar (Slice 2.8). Visually de-emphasized vs
   primary nav so an operator's eye doesn't land on a destructive
   action by default. Will be admin-role-gated when the security layer
   lands; for now relies on the endpoint's blocklist + typed-confirm. */
.topbar-action-admin {
  color: var(--text-dim);
  font-style: italic;
}

.topbar-action-admin:hover {
  color: var(--text);
}

/* Admin reset dialog. Shares .dialog base from the rest of the portal.
   Adds destructive-action styling and the typed-confirmation gate. */
.admin-program-summary {
  margin: 12px 0;
  padding: 10px 12px;
  background: var(--panel-2);
  border-radius: 4px;
  font-size: 13px;
}

.admin-program-name {
  margin-left: 8px;
  color: var(--text-dim);
}

.admin-cleared-summary {
  margin: 12px 0;
  font-size: 12px;
}

.admin-cleared-summary ul {
  margin: 6px 0 0 0;
  padding-left: 18px;
  color: var(--text-dim);
  max-height: 220px;
  overflow-y: auto;
}

.admin-cleared-summary li {
  margin: 2px 0;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 11px;
}

.dialog-field {
  margin: 14px 0 10px 0;
}

.dialog-field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
}

.dialog-field code {
  background: var(--panel-2);
  padding: 1px 6px;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 12px;
  color: var(--accent);
}

.dialog-field input[type="text"] {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
}

.admin-blocked-msg {
  margin: 8px 0;
  padding: 8px 12px;
  background: rgba(220, 60, 60, 0.08);
  border: 1px solid #d44;
  border-radius: 4px;
  font-size: 12px;
  color: #d44;
}

/* ----- Users tab (Phase 16 Slice 3d1) ----------------------------------- */

.users-create-block {
  margin: 16px 0 28px 0;
  padding: 16px 18px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  max-width: 720px;
}

.users-create-block h5 {
  margin: 0 0 14px 0;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.users-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 16px;
}

.users-form-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}

.users-form-field > span {
  font-weight: 600;
  color: var(--text);
}

.users-form-field > span small {
  font-weight: 400;
  color: var(--text-dim);
  margin-left: 4px;
  font-size: 11px;
}

.users-form-field input,
.users-form-field select {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
}

.users-form-field input:focus,
.users-form-field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(0, 166, 220, 0.18);
}

.users-form-actions {
  margin-top: 14px;
  display: flex;
  justify-content: flex-end;
}

.users-create-error {
  margin: 12px 0 0 0;
  padding: 8px 12px;
  background: rgba(220, 60, 60, 0.08);
  border: 1px solid #d44;
  border-radius: 4px;
  font-size: 12px;
  color: #d44;
}

.users-list-block h5 {
  margin: 0 0 10px 0;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.users-table {
  width: 100%;
  max-width: 960px;
  border-collapse: collapse;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  font-size: 13px;
}

.users-table thead {
  background: var(--panel);
}

.users-table th {
  text-align: left;
  padding: 10px 14px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}

.users-table td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.users-table tbody tr:last-child td {
  border-bottom: none;
}

.users-table tbody tr:hover {
  background: rgba(0, 166, 220, 0.04);
}

.users-table td code {
  background: var(--panel);
  padding: 2px 8px;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 12px;
  color: var(--accent);
}

.users-table .pc-btn-small {
  padding: 4px 10px;
  font-size: 12px;
}

.users-expand-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--text-dim);
  font-size: 12px;
  padding: 0 4px;
}
.users-expand-btn:hover { color: var(--accent); }

.users-row-detail > td {
  background: rgba(0, 166, 220, 0.03);
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
}

.users-detail-grid {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 24px;
}

.users-detail-edit h6,
.users-detail-roles h6 {
  margin: 0 0 10px 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
}

.users-edit-form,
.users-grant-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.users-form-field-inline {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.users-form-field-inline > span { font-weight: 400; }

.users-roles-list { margin-bottom: 14px; }

.users-roles-empty {
  margin: 4px 0 14px 0;
  font-style: italic;
}

.users-roles-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
}

.users-roles-table th {
  text-align: left;
  padding: 6px 10px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}

.users-roles-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
}
.users-roles-table tbody tr:last-child td { border-bottom: none; }

.users-can-approve-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
}

/* Password reset modal */
.users-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.users-modal[hidden] { display: none; }

.users-modal-card {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px 22px;
  width: 360px;
  max-width: 90vw;
}

.users-modal-card h4 {
  margin: 0 0 8px 0;
  font-size: 15px;
  font-weight: 600;
}

.users-modal-target { margin: 0 0 14px 0; font-size: 12px; }

.users-modal-actions {
  margin-top: 14px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.admin-danger {
  background: #c44 !important;
  color: #ffffff !important;
}

.admin-danger:hover:not(:disabled) {
  background: #a33 !important;
}

.admin-danger:disabled {
  background: var(--panel-2) !important;
  color: var(--text-dim) !important;
  cursor: not-allowed;
}

.admin-result {
  margin-top: 14px;
  padding: 12px;
  background: rgba(40, 180, 100, 0.08);
  border: 1px solid #2a8;
  border-radius: 4px;
  font-size: 12px;
}

.admin-result h4 {
  margin: 0 0 6px 0;
  color: #2a8;
}

.admin-result ul {
  margin: 4px 0;
  padding-left: 18px;
}

.admin-result-hint {
  margin: 8px 0 0 0;
  color: var(--text-dim);
  font-style: italic;
}

/* Refine mini-dialog. Shares ai-assist-dialog base styles; mostly
   sized smaller and uses the current-value preformatted block. */
.aia-refine-dialog {
  width: min(720px, 95vw);
}

.aia-refine-current {
  margin: 0;
  padding: 10px 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: inherit;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 280px;
  overflow: auto;
  color: var(--text-dim);
}

/* Step 3 — running spinner (kept for any callers that still use it) */

.aia-spinner {
  margin: 30px auto;
  width: 36px;
  height: 36px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: aia-spin 0.9s linear infinite;
}

@keyframes aia-spin {
  to { transform: rotate(360deg); }
}

/* Progress UI for running steps. Indeterminate bar (we can't show
   true streaming token progress for a synchronous create() call) plus
   live elapsed-time counter so the operator can see the run is alive
   and gauge whether it's running long. Threshold reassurance text
   lives in the help paragraph above; JS updates that copy at
   intervals. */
.aia-progress-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 20px 0 8px 0;
}

.aia-progress-bar {
  flex: 1;
  height: 6px;
  background: var(--panel-2);
  border-radius: 3px;
  overflow: hidden;
  position: relative;
}

/* Indeterminate sliding fill (used by refine dialog and any single-call
   path where we can't show real progress). */
.aia-progress-bar:not(.aia-progress-determinate) .aia-progress-bar-fill {
  position: absolute;
  top: 0;
  left: -30%;
  width: 30%;
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  animation: aia-bar-slide 1.6s ease-in-out infinite;
}

@keyframes aia-bar-slide {
  0%   { left: -30%; }
  100% { left: 100%; }
}

/* Determinate fill driven by JS — width: percentage. Used by the
   per-field initial-populate path where each completed field
   advances the bar. */
.aia-progress-bar.aia-progress-determinate .aia-progress-bar-fill {
  width: 0%;
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.3s ease;
}

.aia-progress-stats {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 8px 0;
  font-size: 12px;
  color: var(--text-dim);
  font-family: ui-monospace, SFMono-Regular, monospace;
}

.aia-progress-sep {
  opacity: 0.5;
}

.aia-elapsed {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  min-width: 50px;
  text-align: right;
}

.aia-running-hint {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
  font-style: italic;
}

/* Step 4 — review */

.aia-summary {
  margin-bottom: 12px;
  padding: 8px 12px;
  background: var(--panel-2);
  border-radius: 4px;
  font-size: 12px;
  color: var(--text-dim);
}

.aia-validation-errors {
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1px solid #d44;
  border-radius: 4px;
  background: rgba(220, 60, 60, 0.08);
  font-size: 12px;
}

.aia-validation-errors h4 {
  margin: 0 0 6px 0;
  font-size: 13px;
  color: #d44;
}

.aia-validation-errors ul { margin: 0; padding-left: 18px; }

.aia-clarifying {
  margin-bottom: 14px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-left: 3px solid #ca0;
  border-radius: 4px;
  background: var(--panel-2);
  font-size: 13px;
}

.aia-clarifying h4 { margin: 0 0 6px 0; font-size: 13px; }
.aia-clarifying ul { margin: 0; padding-left: 18px; }

.aia-proposals {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.aia-proposals-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-dim);
  font-style: italic;
}

.aia-proposal-card {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}

.aia-proposal-invalid {
  border-color: #d44;
  background: rgba(220, 60, 60, 0.04);
}

.aia-proposal-low-conf {
  border-left: 3px solid #ca0;
}

.aia-prop-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}

.aia-prop-check {
  margin: 0;
}

.aia-prop-path {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 12px;
  font-weight: 600;
  word-break: break-all;
}

.aia-prop-conf {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: 3px;
  white-space: nowrap;
}

.aia-conf-high   { background: rgba(40, 180, 100, 0.15); color: #28a; }
.aia-conf-medium { background: var(--panel-2); color: var(--text-dim); }
.aia-conf-low    { background: rgba(204, 170, 0, 0.18); color: #b80; }

.aia-prop-rationale {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.4;
  margin-bottom: 8px;
  font-style: italic;
}

.aia-prop-edit {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  resize: vertical;
}

.aia-prop-hint {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-dim);
}

.aia-prop-errmsg {
  margin-top: 6px;
  font-size: 11px;
  color: #d44;
}

/* ============================================ SEO Best-Practices tab ===
 * Admin → SEO Configuration: tier table per content type + ✦ Refresh
 * from AI button + diff modal. Lives on its own Apply/Revert pair so
 * editing doesn't trigger the page-global Save action.
 * ====================================================================== */

.pc-caveat {
  margin: 8px 0 12px;
  padding: 8px 12px;
  border-left: 3px solid var(--warn);
  background: var(--bg-soft, transparent);
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.5;
}

.seo-bp-provenance {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  font-size: 12px;
  color: var(--text-dim);
  margin: 10px 0;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-soft, transparent);
}
.seo-bp-provenance strong { color: var(--text); font-weight: 600; }
.seo-bp-provenance code {
  background: transparent;
  color: var(--text);
  font-size: 11px;
}
.seo-bp-prov-sep { color: var(--border); }

.seo-bp-actions {
  margin-top: 6px;
  margin-bottom: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.seo-bp-ct-card {
  margin: 16px 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-soft, transparent);
}

.seo-bp-ct-title {
  margin: 0 0 8px;
  font-size: 14px;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.seo-bp-ct-id {
  font-size: 11px;
  color: var(--text-dim);
  background: transparent;
}

.seo-bp-tier-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  table-layout: fixed;
}
.seo-bp-tier-table th,
.seo-bp-tier-table td {
  padding: 6px 8px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.seo-bp-tier-table th {
  font-weight: 600;
  color: var(--text-dim);
}
.seo-bp-tier-table tbody tr:last-child td { border-bottom: none; }
.seo-bp-tier-table code {
  font-size: 11px;
  color: var(--text);
  background: transparent;
}

.seo-bp-col-tier-id { width: 90px; }
.seo-bp-col-label   { width: 36%; }
.seo-bp-col-target  { width: 90px; }
.seo-bp-col-desc    { width: auto; }

.seo-bp-input {
  width: 100%;
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--panel, var(--bg, transparent));
  color: var(--text);
  font-family: inherit;
  box-sizing: border-box;
}
.seo-bp-target { max-width: 90px; }
.seo-bp-desc { min-height: 60px; resize: vertical; }

/* ---- Diff modal ---- */
.seo-bp-diff-dialog {
  width: min(720px, 92vw);
  max-width: 720px;
}
.seo-bp-diff-summary {
  margin: 0 0 10px;
  padding: 6px 10px;
  border-left: 3px solid var(--accent);
  background: var(--bg-soft, transparent);
  font-size: 12px;
  color: var(--text);
}
.seo-bp-diff-scroll {
  max-height: 50vh;
  overflow-y: auto;
  padding-right: 4px;
}

.seo-bp-diff-ct {
  margin: 12px 0;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
}
.seo-bp-diff-ct h4 {
  margin: 0 0 6px;
  font-size: 13px;
  color: var(--text);
}
.seo-bp-diff-tier {
  margin: 8px 0 12px;
  padding-left: 8px;
  border-left: 2px solid var(--border);
}
.seo-bp-diff-tier-label {
  font-size: 11px;
  color: var(--text-dim);
  margin-bottom: 4px;
  display: flex;
  gap: 6px;
  align-items: baseline;
}
.seo-bp-diff-tier-label-name { color: var(--text); }

.seo-bp-diff-field {
  font-size: 12px;
  line-height: 1.5;
  margin: 4px 0;
  color: var(--text);
}
.seo-bp-diff-field-label {
  color: var(--text-dim);
  margin-right: 6px;
}
.seo-bp-diff-from {
  text-decoration: line-through;
  color: var(--text-dim);
}
.seo-bp-diff-arrow {
  color: var(--text-dim);
  margin: 0 6px;
}
.seo-bp-diff-to {
  color: var(--text);
  font-weight: 600;
  background: rgba(var(--accent-rgb, 33, 175, 213), 0.15);
  padding: 0 4px;
  border-radius: 2px;
}
.seo-bp-diff-field-block {
  display: block;
}
.seo-bp-diff-from-multi,
.seo-bp-diff-to-multi {
  margin: 4px 0;
  padding: 6px 8px;
  border-radius: 3px;
  white-space: pre-wrap;
  font-size: 12px;
  line-height: 1.5;
}
.seo-bp-diff-from-multi {
  background: var(--bg-soft, transparent);
  color: var(--text-dim);
  text-decoration: line-through;
}
.seo-bp-diff-arrow-block {
  color: var(--text-dim);
  font-size: 11px;
  margin: 2px 0;
}
.seo-bp-diff-to-multi {
  background: rgba(var(--accent-rgb, 33, 175, 213), 0.12);
  color: var(--text);
  font-weight: 500;
}
