/*
 * Phase 6a baseline styles for the Synesis P_success frontend.
 *
 * Card-based layout with progressive disclosure. Sections start hidden
 * (via the `hidden` HTML attribute) and main.js reveals them as the user
 * advances through the flow: setup → research → parameters / scenarios /
 * benchmarks / Monte Carlo. The full theme port from
 * `../SynesisLabs Platform/psuccess-platform.html` is still deferred —
 * this pass is the structural rework, with the visual upgrade staying
 * intentionally light so the markup is what we're committing to, not
 * the colours.
 */

/* === Tokens =============================================================== */
/*  Single source of truth for the colour palette. Tweak here, not at        */
/*  per-component sites. The hex values stay close to the legacy brand       */
/*  so a future dark-theme port stays a colour swap, not a layout fight.    */

:root,
[data-theme="light"] {
  --bg: #f5f7fa;
  --surface: #ffffff;
  --surface-muted: #f7fafc;
  --border: #e2e8f0;
  --border-strong: #cbd5e0;
  --text: #1a202c;
  --text-muted: #4a5568;
  --text-subtle: #718096;
  --accent: #2b6cb0;
  --accent-strong: #1e3a5f;
  --accent-soft: rgba(43, 108, 176, 0.08);
  --good: #2f855a;
  --good-soft: #d1fae5;
  --warn: #b7791f;
  --warn-soft: #fef3c7;
  --bad: #c53030;
  --bad-soft: #fee2e2;
  --orange: #f97316;
  --modal-backdrop: rgba(15, 23, 42, 0.45);
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08);
}

/*  Dark-theme token overrides. Same variable names, different values —
 *  every component reads via `var(--*)` so swapping the attribute on
 *  `<html>` swaps the whole UI without touching any per-component CSS.
 *  Soft variants use rgba alpha so coloured backgrounds blend onto the
 *  dark surfaces correctly; light mode's pastel solids would look
 *  garish on a dark card.
 */
[data-theme="dark"] {
  --bg: #0b1120;
  --surface: #131c30;
  --surface-muted: #1c2740;
  --border: #2a3656;
  --border-strong: #475569;
  --text: #e7ecf3;
  --text-muted: #cbd5e0;
  --text-subtle: #8c9ab2;
  --accent: #38bdf8;
  --accent-strong: #7dd3fc;
  --accent-soft: rgba(56, 189, 248, 0.14);
  --good: #34d399;
  --good-soft: rgba(52, 211, 153, 0.18);
  --warn: #fbbf24;
  --warn-soft: rgba(251, 191, 36, 0.18);
  --bad: #f87171;
  --bad-soft: rgba(248, 113, 113, 0.18);
  --orange: #fb923c;
  --modal-backdrop: rgba(0, 0, 0, 0.6);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.5);
}

/*  Smooth-but-not-distracting transition when the user toggles. Picks
 *  the properties that actually change so the page doesn't animate
 *  unrelated layout shifts.
 */
html {
  transition: background-color 0.15s linear;
}

body {
  transition: background-color 0.15s linear, color 0.15s linear;
}

/* === Page-level ========================================================== */
/*  Constrained reading column, neutral background, consistent type ramp.    */

* {
  box-sizing: border-box;
}

/* The `hidden` attribute must always win over a component's own `display`
   rule. Several shell elements set `display` (`.login-wrap` → flex, `.app-body`
   → grid, `.app-menu` / `.menu-item` → flex) which would otherwise override the
   UA `[hidden] { display: none }` and leave "hidden" elements rendered. This
   guard (the HTML5-boilerplate idiom) keeps `el.hidden = true` authoritative
   everywhere it's used. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
}

main {
  max-width: 880px;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 4rem;
}

/* === App header ========================================================== */
/*  Sticks to the top of the page (no scroll detach). Title on the left,    */
/*  account chip on the right; the chip is hidden when no session exists.   */

.app-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.85rem 1.5rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.app-title {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}

.app-title .title-accent {
  color: var(--accent);
}

.app-header-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* NOTE: `.app-header`, `.app-title`, `.app-header-actions` and `.title-accent`
 * above are retained because the admin SPA (`admin.html`) still uses that
 * header layout. The main app's header was replaced by the shell top bar in
 * UI-overhaul phase U0 (see the "Shell" sections near the end of this file). */

.theme-icon {
  display: block;
  pointer-events: none;
}

/*  Default (light theme): show moon glyph, hide sun. Dark theme flips. */
.theme-icon-sun { display: none; }
[data-theme="dark"] .theme-icon-moon { display: none; }
[data-theme="dark"] .theme-icon-sun  { display: block; }

/* === Card system ========================================================= */
/*  Every major section sits inside a .card. The visible heading is in
    .card-header > .card-title, with optional .card-subtitle copy. Actions
    live in .card-footer at the bottom. Cards stack vertically with
    consistent spacing so the page reads as a top-down checklist. */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
}

.card-header {
  margin-bottom: 1rem;
}

.card-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--accent-strong);
}

.card-subtitle {
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  color: var(--text-muted);
  line-height: 1.45;
}

.card-footer {
  margin-top: 1rem;
}

.section-subtitle {
  margin: 1rem 0 0.5rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-subtle);
  font-weight: 700;
}

.prose {
  line-height: 1.55;
  color: var(--text);
}

.prose strong {
  color: var(--accent-strong);
}

/* === Form controls ======================================================= */
/*  Inputs span the card width by default. Labels stack above inputs.       */

label {
  display: block;
  margin: 0.85rem 0 0.3rem;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text);
}

label .label-hint {
  font-weight: 400;
  color: var(--text-subtle);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
select,
textarea {
  width: 100%;
  padding: 0.55rem 0.7rem;
  font-size: 0.95rem;
  font-family: inherit;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  box-sizing: border-box;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: var(--accent);
}

textarea {
  resize: vertical;
  min-height: 5rem;
  font-family: inherit;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.6rem;
  font-weight: 500;
  font-size: 0.9rem;
}

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

.settings-grid label {
  margin-top: 0.7rem;
}

/* === Buttons ============================================================= */
/*  Three visual roles: primary (the headline action — RUN MODEL, Log in),  */
/*  secondary (RUN scenarios / RUN benchmarks / Run MC), ghost (Log out,    */
/*  modal close, anything that shouldn't compete for attention).            */

button {
  font-family: inherit;
  cursor: pointer;
  border: 0;
  border-radius: 6px;
  font-weight: 600;
  padding: 0.5rem 1rem;
  font-size: 0.95rem;
  transition: filter 0.12s, background-color 0.12s;
}

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

.btn-primary {
  background: var(--accent);
  color: #fff;
}

.btn-primary:hover:not(:disabled) {
  background: var(--accent-strong);
}

.btn-secondary {
  background: var(--surface-muted);
  color: var(--text);
  border: 1px solid var(--border-strong);
}

.btn-secondary:hover:not(:disabled) {
  background: #edf2f7;
  border-color: var(--accent);
  color: var(--accent);
}

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
  padding: 0.35rem 0.65rem;
  font-weight: 500;
}

.btn-ghost:hover:not(:disabled) {
  color: var(--text);
  background: var(--surface-muted);
}

.btn-large {
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
}

.btn-small {
  padding: 0.3rem 0.55rem;
  font-size: 0.85rem;
}

/* Horizontal group of buttons inside a card-footer (e.g. Export + Generate
   report). Wraps on narrow screens; the gap keeps them from touching. */
.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* === Status + error lines ================================================ */
/*  Status line uses the spinner cycle from app/status-cycle.js — monospace */
/*  keeps the leading braille glyph at fixed width.                          */

.status-line {
  margin: 0.6rem 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92rem;
  color: var(--accent);
}

.error {
  color: var(--bad);
  margin: 0.5rem 0 0;
}

.meta-status {
  text-align: center;
  color: var(--text-muted);
  font-style: italic;
  margin: 1rem 0;
}

/* === Sign-in (Clerk) ===================================================== */

/*
 * The sign-in screen is just a centering wrapper around Clerk's own card — we
 * intentionally don't wrap it in our .card (that produced a redundant outer box
 * the Clerk card overflowed). Clerk is themed to our palette via clerkAppearance()
 * in app/clerk.js.
 */
.login-wrap {
  display: flex;
  /* Column so the admin-only notice (when revealed) stacks above the Clerk
     card rather than sitting beside it; align-items keeps the card centred
     exactly as the old row layout did. */
  flex-direction: column;
  align-items: center;
  margin: 3rem auto;
  padding: 0 1rem;
}

/* Warning banner shown on admin-only deployments (branch trial stacks) after
   a non-admin's sign-in is refused server-side — see auth:admin-only in
   app/main.js. Uses the theme's "bad" colour at low opacity so it reads as a
   warning in both light and dark. */
.login-notice {
  max-width: 25rem;
  margin: 0 0 1.25rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--bad);
  border-radius: 6px;
  color: var(--bad);
  background: color-mix(in srgb, var(--bad) 8%, transparent);
  font-size: 0.92rem;
}

.card-title {
  margin: 0;
}

/* === Upload zone ========================================================= */

.upload-zone {
  border: 1.5px dashed var(--border-strong);
  border-radius: 6px;
  padding: 1rem 0.75rem;
  text-align: center;
  font-size: 0.9rem;
  color: var(--text-muted);
  cursor: pointer;
  background: var(--surface-muted);
  transition: border-color 0.12s, color 0.12s, background-color 0.12s;
}

.upload-zone:hover,
.upload-zone:focus {
  border-color: var(--accent);
  color: var(--accent);
  outline: none;
}

.upload-zone.dragging {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}

.upload-hint {
  margin-top: 0.25rem;
  font-size: 0.75rem;
  color: var(--text-subtle);
}

.file-list {
  margin-top: 0.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.file-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.55rem;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.85rem;
}

.file-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-badge {
  font-size: 0.75rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--border);
  color: var(--text-muted);
}

.file-badge-parsing { background: var(--border); color: var(--text-muted); }
.file-badge-ok      { background: var(--good-soft); color: var(--good); }
.file-badge-unsupported { background: var(--warn-soft); color: var(--warn); }
.file-badge-error   { background: var(--bad-soft); color: var(--bad); }

.file-remove {
  background: transparent;
  color: var(--text-subtle);
  border: 0;
  padding: 0 0.4rem;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  font-weight: 700;
}

.file-remove:hover {
  color: var(--bad);
}

/* === Parameter group headings ============================================ */
/*  Group headings ("INTERNAL FACTORS (PROJECT STRENGTHS)", "ELASTICITIES     */
/*  (PROJECT RISKS)", "CALIBRATION CONSTANTS") are injected by sliders.js      */
/*  between the three groups of the Parameters tab.                           */

#slidersSection h2 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 1.5rem 0 0.4rem;
  color: var(--text-subtle);
  font-weight: 700;
}
/* First group heading sits directly under the tab-head; trim its top gap. */
#slidersSection h2:first-child {
  margin-top: 0.25rem;
}

/* The old six-cell diagnostic result strip (.result-strip / .result-cell /
   .result-label / .result-value) was replaced by the headline metrics strip in
   UI-overhaul phase U0 — see the "Shell: headline strip" section below. */

/* ========================================================================= *
 *  UI-overhaul phase U2 — Parameters tab rows
 *
 *  Each row (internal factor, elasticity, or calibration delta) is a three-
 *  column grid: label + arrow + ⓘ | track | numeric readout. The track carries
 *  a slim line, two muted endpoint captions, and a value BUBBLE positioned at
 *  the value's spot along the track and colour-coded by favourability. The real
 *  control is a transparent `<input type="range">` (`.param-input`) laid over
 *  the whole track — see the sliders.js header for the accessibility rationale.
 *  All colours use existing tokens so both themes work unchanged.
 * ========================================================================= */

.param-row {
  display: grid;
  grid-template-columns: 11rem 1fr 4rem;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 0;
}

/* Left cell: label text + optional direction arrow + ⓘ info trigger. */
.param-label {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text);
}
.param-arrow {
  color: var(--text-subtle);
  font-weight: 700;
}

/* Middle cell: the track. Tall enough for the bubble (above the line) and the
   endpoint captions (below it). `position: relative` anchors all the absolutely
   positioned children. */
.param-track {
  position: relative;
  height: 1.9rem;
}
.param-track-line {
  position: absolute;
  left: 0;
  right: 0;
  top: 0.5rem;
  height: 2px;
  background: var(--border-strong);
  border-radius: 1px;
}
.param-cap {
  position: absolute;
  top: 0.95rem;
  font-size: 0.6rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-subtle);
  pointer-events: none;
  white-space: nowrap;
}
.param-cap-lo { left: 0; }
.param-cap-hi { right: 0; text-align: right; }

/* The value bubble. Positioned by JS (`left: NN%`) and centred on the line; it
   never intercepts pointer events so a drag over it still reaches the input. */
.param-bubble {
  position: absolute;
  top: 0.5rem;
  transform: translate(-50%, -50%);
  padding: 1px 6px;
  border-radius: 5px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  font: 700 0.68rem ui-monospace, SFMono-Regular, monospace;
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}
/* Favourability variants — soft fill + strong text, mirroring the file-badge
   pattern so contrast holds in both light and dark themes. */
.param-bubble.fav-good { background: var(--good-soft); color: var(--good); border-color: var(--good); }
.param-bubble.fav-bad { background: var(--bad-soft); color: var(--bad); border-color: var(--bad); }
.param-bubble.fav-warn { background: var(--warn-soft); color: var(--warn); border-color: var(--warn); }
.param-bubble.fav-neutral { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }

/* The real range control: transparent but fully interactive, laid over the
   whole track (above the bubble so a drag anywhere reaches it). Its thumb is
   invisible; the bubble is the visible handle. */
.param-input {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 3;
}
/* Keyboard focus indicator: since the input itself is invisible, draw the ring
   on the track's line + bubble when anything inside the track is focused. */
.param-track:focus-within .param-track-line {
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.param-track:focus-within .param-bubble {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Right cell: the monospace numeric readout (absolute value for params, signed
   delta for calibration rows). */
.param-readout {
  font-variant-numeric: tabular-nums;
  text-align: right;
  font-size: 0.82rem;
  color: var(--text-muted);
  font-family: ui-monospace, SFMono-Regular, monospace;
}

/* === Source badges ======================================================= */
/*  Inline chips above the research summary: "web research used" /          */
/*  "N documents".                                                          */

.source-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

.source-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.78rem;
  background: var(--border);
  color: var(--text-muted);
}

.source-badge.active {
  background: var(--good-soft);
  color: var(--good);
}

.source-badge.inactive {
  background: var(--surface-muted);
  color: var(--text-subtle);
}

/* === Scenario cards (U3) ================================================= */
/*  Collapsible ScenarioCards: header row (id chip, direction arrow, title,
    Δpp badge, ✎/× icon buttons) + an expandable drawer (description, the
    shifted-params table, outcome line, Adopt, FOLD UP). Rendered by
    app/scenarios.js. All colours come from the existing tokens so both themes
    work unchanged.                                                            */

.scenarios-list {
  margin-top: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* Toolbar above the scenario list: Summary heading left, Reset right. */
.scenarios-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.scenarios-toolbar .section-subtitle {
  margin: 1rem 0 0.5rem;
}

.scenarios-hint {
  margin: 0 0 0.25rem;
  font-size: 0.8rem;
  color: var(--text-subtle);
  font-style: italic;
}

.scenario-card {
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: 6px;
  overflow: hidden;
}
.scenario-card.scenario-up   { border-left-color: var(--good); }
.scenario-card.scenario-down { border-left-color: var(--bad); }

/* Adopted card: accent-tinted ring so the user can see which entry currently
   drives the sliders (shared visual language with .benchmark-card.adopted). */
.scenario-card.adopted {
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

/* Header row — the expand/collapse affordance. */
.scenario-card-head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 0.85rem;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
}
.scenario-card-head:hover {
  background: var(--surface);
}
.scenario-card-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.scenario-id-chip {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
}

.scenario-up .scenario-arrow   { color: var(--good); }
.scenario-down .scenario-arrow { color: var(--bad); }

/* Title takes the slack so the Δpp badge + icons sit flush right. */
.scenario-card-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Projected Δpp vs baseline (filled async from /score/batch). */
.scenario-pp {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text-muted);
  white-space: nowrap;
}
.scenario-pp.pos { color: var(--good); }
.scenario-pp.neg { color: var(--bad); }

/* ✎ / × icon buttons (shared style with the benchmark cards). */
.scenario-card-actions,
.benchmark-card-actions {
  display: inline-flex;
  gap: 0.15rem;
}
.scenario-icon-btn,
.benchmark-icon-btn {
  background: none;
  border: 0;
  padding: 0.1rem 0.3rem;
  font-size: 0.9rem;
  line-height: 1;
  color: var(--text-subtle);
  cursor: pointer;
  border-radius: 4px;
}
.scenario-icon-btn:hover,
.benchmark-icon-btn:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

/* --- Drawer ------------------------------------------------------------- */

.scenario-drawer,
.benchmark-drawer {
  padding: 0.75rem 0.85rem 0.85rem;
  border-top: 1px solid var(--border);
  cursor: auto;
}

.scenario-desc,
.benchmark-desc {
  font-size: 0.88rem;
  color: var(--text-muted);
  line-height: 1.5;
}
.scenario-desc p,
.benchmark-desc p {
  margin: 0 0 0.4rem;
}

/* Shared shifted-params / comparison table pattern. Column widths are fixed
   for the numeric cells; the wrapper scrolls horizontally on narrow screens
   (min-width on the rows) so the cards never overflow the panel. */
.scenario-table,
.benchmark-table {
  margin-top: 0.75rem;
  overflow-x: auto;
}
.scenario-table-head,
.scenario-tr,
.benchmark-table-head,
.benchmark-tr {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 30rem; /* horizontal scroll instead of squashing at ~900px */
  border-bottom: 1px solid var(--border);
  padding: 0.3rem 0;
}
.scenario-table-head,
.benchmark-table-head {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
}
.scenario-th.col-name, .scenario-td.col-name,
.benchmark-th.col-name, .benchmark-td.col-name {
  flex: 1;
  min-width: 0;
}
.scenario-th.col-num, .scenario-td.col-num {
  width: 6.5rem;
  flex: none;
}
.benchmark-th.col-num, .benchmark-td.col-num {
  width: 6.5rem;
  flex: none;
}
.scenario-tr, .benchmark-tr {
  font-size: 0.85rem;
}
.scenario-td-code, .benchmark-td-code {
  color: var(--text-subtle);
  font-size: 0.72rem;
}
.scenario-td.mono, .benchmark-td.mono {
  font-family: ui-monospace, SFMono-Regular, monospace;
}
.scenario-td.strong, .benchmark-td.strong { font-weight: 700; }
.scenario-td.muted, .benchmark-td.muted { color: var(--text-muted); }
/* Favourability colouring: pos = favourable move, neg = unfavourable (an
   elasticity DECREASE is favourable — computed in JS per param direction). */
.scenario-td.pos, .benchmark-td.pos { color: var(--good); }
.scenario-td.neg, .benchmark-td.neg { color: var(--bad); }

/* Outcome line: Baseline P_success X% → Scenario P_success Y%. */
.scenario-outcome {
  margin-top: 0.75rem;
  font-size: 0.88rem;
}
.scenario-outcome strong {
  font-family: ui-monospace, SFMono-Regular, monospace;
}
.scenario-outcome strong.pos { color: var(--good); }
.scenario-outcome strong.neg { color: var(--bad); }

/* Adopt button row + FOLD UP footer (shared with benchmark cards). */
.scenario-adopt-row,
.benchmark-adopt-row {
  margin-top: 0.6rem;
  display: flex;
  justify-content: flex-end;
}
.scenario-adopt-btn,
.benchmark-adopt-btn {
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.45rem 1.1rem;
  border-radius: 6px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.scenario-adopt-btn:hover,
.benchmark-adopt-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
/* Adopted state: filled accent + revert affordance in the label. */
.scenario-adopt-btn.active,
.benchmark-adopt-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.scenario-foldup,
.benchmark-foldup {
  margin-top: 0.75rem;
  width: 100%;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: none;
  padding: 0.45rem;
  text-align: center;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  cursor: pointer;
}
.scenario-foldup:hover,
.benchmark-foldup:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* === Benchmark cards (U4) ================================================ */
/*  Collapsible BenchmarkCards: #rank / title / p_success% header + drawer
    (rationale, Sources line, comparison line, Adopt, full 14-param table).
    Rendered by app/peers.js; most drawer styles are shared with the scenario
    selectors above.                                                          */

.peers-list {
  margin-top: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.benchmark-card {
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.benchmark-card.adopted {
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.benchmark-card-head {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 0.85rem;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
}
.benchmark-card-head:hover {
  background: var(--surface);
}
.benchmark-card-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.benchmark-rank {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 0.78rem;
  color: var(--text-subtle);
}

.benchmark-card-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.benchmark-prob {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}

/* Muted "Sources: …" line under the description; only http(s) entries are
   links (escaping + URL vetting happens in peers.js#buildSourcesLine). */
.benchmark-sources {
  margin-top: 0.4rem;
  font-size: 0.78rem;
  color: var(--text-subtle);
  overflow-wrap: anywhere; /* long URLs must not overflow the card */
}
.benchmark-sources a {
  color: var(--text-subtle);
  text-decoration: underline;
}
.benchmark-sources a:hover {
  color: var(--accent);
}

/* "<Name> X% vs Your baseline Y% (you trail/lead by N pp)" line. */
.benchmark-compare {
  margin-top: 0.75rem;
  font-size: 0.88rem;
}
.benchmark-compare .cmp-name { font-weight: 700; }
.benchmark-compare strong {
  font-family: ui-monospace, SFMono-Regular, monospace;
}
.benchmark-compare .cmp-pos { color: var(--good); }
.benchmark-compare .cmp-neg { color: var(--bad); }
.benchmark-compare .cmp-neutral { color: var(--text-muted); }

/* === Monte Carlo trigger + modal ========================================= */
/*  Trigger button gets the brand-accent treatment to read as the lone      */
/*  flagship action inside the Parameters card.                              */

.mc-trigger {
  background: linear-gradient(135deg, #f97316, #dc2626) !important;
  color: #fff !important;
  border: 0 !important;
  font-weight: 700;
}

.mc-trigger:hover:not(:disabled) {
  filter: brightness(1.05);
}

#monteCarloModal {
  max-width: 760px;
  width: 92%;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  background: var(--surface);
  color: var(--text);
  margin: auto;
}

#monteCarloModal::backdrop {
  background: var(--modal-backdrop);
}

#monteCarloModal h3 {
  margin: 0 0 0.25rem;
  font-size: 1.15rem;
  color: var(--accent-strong);
}

.modal-subtitle {
  margin: 0 0 1rem;
  font-size: 0.9rem;
  color: var(--text-muted);
}

#monteCarloModal label span {
  font-family: ui-monospace, SFMono-Regular, monospace;
  color: var(--accent);
  font-weight: 700;
  margin-left: 0.25rem;
}

#monteCarloModal input[type="range"] {
  width: 100%;
}

.mc-status {
  margin: 0.6rem 0 0;
  font-style: italic;
  color: var(--accent);
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1rem;
}

.mc-results {
  margin-top: 1rem;
}

.mc-chart {
  width: 100%;
  max-height: 220px;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: 6px;
}

/* SVG marker styling — extracted from inline SVG attributes into CSS
 * classes so the chart adapts to the theme. Bars keep their semantic
 * red/amber/green inline-fills (those convey meaning, not theming);
 * markers and axis labels follow the theme's text colour.
 */
.mc-marker {
  stroke: var(--text);
  stroke-width: 1.2;
  stroke-dasharray: 3 3;
}

.mc-marker-label {
  fill: var(--text);
  font-size: 10px;
  font-family: ui-monospace, SFMono-Regular, monospace;
}

.mc-axis-label {
  fill: var(--text-muted);
  font-size: 10px;
  font-family: ui-monospace, SFMono-Regular, monospace;
}

.mc-stats {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.75rem;
  margin: 0.85rem 0 0.5rem;
}

.mc-stat-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-subtle);
  font-weight: 700;
}

.mc-stat-value {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}

.mc-stat-value.mc-stat-low  { color: var(--bad); }
.mc-stat-value.mc-stat-high { color: var(--good); }
.mc-stat-value.mc-stat-mean { color: var(--accent); }

.mc-band {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  color: var(--text-muted);
}

.mc-verdict {
  margin-top: 0.85rem;
  padding: 0.75rem 0.9rem;
  background: rgba(249, 115, 22, 0.08);
  border-left: 3px solid var(--orange);
  border-radius: 4px;
}

.mc-verdict-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #c2410c;
  font-weight: 700;
}

.mc-verdict-text {
  margin-top: 0.25rem;
  font-size: 0.95rem;
  color: var(--text);
  line-height: 1.45;
}

/* === Model clarification modal ========================================== */

#modelClarificationModal {
  max-width: 560px;
  width: 90%;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  color: var(--text);
  background: var(--surface);
  margin: auto;
}

#modelClarificationModal::backdrop {
  background: var(--modal-backdrop);
}

#modelClarificationModal h3 {
  margin: 0 0 0.25rem;
  font-size: 1.1rem;
  color: var(--accent-strong);
}

#modelClarificationModal .modal-body {
  white-space: pre-wrap;
  line-height: 1.5;
  font-size: 0.95rem;
  color: var(--text);
  max-height: 60vh;
  overflow-y: auto;
  padding: 0.75rem 0.85rem;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  border-radius: 4px;
}

/* === Responsive tweaks =================================================== */

@media (max-width: 600px) {
  .param-row {
    grid-template-columns: 8rem 1fr 3.5rem;
  }
  .mc-stats {
    grid-template-columns: repeat(2, 1fr);
  }
  main {
    padding: 1rem 0.85rem 3rem;
  }
}

/* === Phase 6d: API-settings + Terms modals ============================== */

/* Prompt-template selector (now a labelled row inside the hamburger menu).
   The run-mode radio group and web-search checkbox that used to sit alongside
   it in the Setup card were replaced in UI-overhaul phase U0 by the sidebar
   WEB SEARCH ON/OFF toggle chip. */
.prompt-template-select {
  margin-bottom: 0.25rem;
}

/* Shared form layout used inside the API-settings modal: stacked
   label/control pairs with comfortable spacing. */
.settings-grid {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
}
.settings-grid label:not(.checkbox-label) {
  font-weight: 600;
  font-size: 0.9rem;
}
.settings-grid input[type="password"],
.settings-grid select {
  width: 100%;
}
.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.25rem;
  font-weight: 500;
  cursor: pointer;
}

/* Status line tones for the "Test connection" result. Base `.status-line`
   already sets layout/colour; these override the colour by outcome. */
.status-ok {
  color: var(--good);
}
.status-bad {
  color: var(--bad);
}

#apiSettingsModal {
  max-width: 520px;
  width: 92%;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  background: var(--surface);
  color: var(--text);
  margin: auto;
}
#apiSettingsModal::backdrop {
  background: var(--modal-backdrop);
}
#apiSettingsModal h3 {
  margin: 0 0 0.25rem;
  font-size: 1.15rem;
  color: var(--accent-strong);
}

/* Terms modal: tall, scrollable body with a pinned header banner + footer.
   Flex layout is scoped to [open] so the dialog's closed (display:none)
   state from the UA stylesheet still applies. */
#termsModal {
  max-width: 760px;
  width: 92%;
  max-height: 85vh;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  background: var(--surface);
  color: var(--text);
  margin: auto;
}
#termsModal[open] {
  display: flex;
  flex-direction: column;
}
#termsModal::backdrop {
  background: var(--modal-backdrop);
}
#termsModal h3 {
  margin: 0 0 0.5rem;
  font-size: 1.2rem;
  font-weight: 800;
  letter-spacing: -0.4px;
}
.terms-tag {
  font-size: 0.75rem;
  color: var(--text-muted);
  font-weight: 500;
  margin-left: 0.6rem;
  padding-left: 0.6rem;
  border-left: 1px solid var(--border-strong);
}

/* Amber "out of date" notice — pinned above the scrollable body. */
.terms-stale-banner {
  background: var(--warn-soft);
  border-left: 3px solid var(--warn);
  border-radius: 5px;
  padding: 0.7rem 0.85rem;
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
  line-height: 1.5;
}
.terms-stale-banner strong {
  color: var(--warn);
}

/* Blue consent banner — shown only in gate mode. */
.terms-consent-banner {
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 5px;
  padding: 0.7rem 0.85rem;
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
  line-height: 1.5;
}

/* The scrollable legal text. flex:1 lets it take the remaining height
   between the banners and the footer; overflow-y makes it scroll. */
.terms-body {
  flex: 1;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  font-size: 0.82rem;
  line-height: 1.55;
}
.terms-body h4 {
  color: var(--accent-strong);
  font-size: 0.9rem;
  margin: 1rem 0 0.35rem;
}
.terms-body h4:first-of-type {
  margin-top: 0.25rem;
}
.terms-body ul {
  padding-left: 1.3rem;
  margin: 0.35rem 0;
}
.terms-body a {
  color: var(--accent);
}
.terms-effective,
.terms-footnote {
  color: var(--text-muted);
  font-size: 0.75rem;
}
.terms-footnote {
  margin-top: 1.2rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--border);
}

/* === Per-parameter ⓘ rationale popover (slider rows) =================== */

/* The ⓘ trigger sits inline after each slider's label text. position:relative
   makes it the anchor for the absolutely-positioned popover. */
.slider-info {
  position: relative;
  display: inline-block;
  margin-left: 0.35rem;
  color: var(--accent);
  cursor: help;
  font-size: 0.85rem;
  line-height: 1;
  font-weight: 700;
}
.slider-info:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* The popover. Hidden until the trigger is hovered or focused. Wider than the
   label column, so it overlays the slider area (high z-index). Scrolls
   internally if a rationale + long source list overflow the max height. */
.rationale-tip {
  display: none;
  position: absolute;
  top: 1.5em;
  left: 0;
  z-index: 50;
  width: 300px;
  max-width: 78vw;
  max-height: 320px;
  overflow-y: auto;
  padding: 0.7rem 0.85rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.5;
  text-align: left;
  white-space: normal;
  cursor: auto;
}
.slider-info:hover .rationale-tip,
.slider-info:focus .rationale-tip,
.slider-info:focus-within .rationale-tip {
  display: block;
}
.rationale-tip > strong {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--accent-strong);
}
.rationale-tip .rt-info {
  color: var(--text-muted);
}
.rationale-tip .rt-model {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}
.rationale-tip .rt-proposed {
  margin-bottom: 0.25rem;
}
.rationale-tip .rt-text {
  margin-bottom: 0.4rem;
}
.rationale-tip .src {
  font-size: 0.74rem;
  color: var(--text-muted);
}
.rationale-tip .src-heading {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.2rem;
}
.rationale-tip .src ul {
  margin: 0;
  padding-left: 1.1rem;
}
.rationale-tip .src li {
  margin: 0.15rem 0;
  word-break: break-word;
}
.rationale-tip .src a {
  color: var(--accent);
}

/* ========================================================================= *
 *  UI-overhaul phase U0 — app-shell layout
 *
 *  The main app moved from a single centred column of progressively-revealed
 *  cards to an app shell: a fixed top bar, a left sidebar (~380px), and a right
 *  content panel with a four-tab bar. Everything below is expressed in the
 *  existing token palette (`--surface`, `--border`, `--accent`, `--good`, …) so
 *  both the light and dark themes work without any new colour values.
 * ========================================================================= */

/* === Shell: grid ========================================================= */
/*  The shell is a vertical stack: the top bar, then a body that fills the rest
    of the viewport. The body is a two-column grid (sidebar + content), each
    column scrolling independently so the headline strip / tab bar stay put
    while long content scrolls. Below ~900px the grid collapses to a single
    column and the whole page scrolls normally (a fuller responsive pass is
    deferred to U5). */

.app-shell {
  display: flex;
  flex-direction: column;
  /* Exactly viewport height — NOT min-height. With min-height the shell
     grows past the viewport when sidebar/content get tall, the page itself
     scrolls, and the sidebar's pinned RUN PROJECT footer scrolls away with
     it. A fixed height forces all overflow into the sidebar's and content
     panel's own scroll containers (2026-08-03). */
  height: 100vh;
}

.shell-main {
  /* Override the global `main` rule (max-width 880px, centred, padded) — the
     shell body must span the full width so the sidebar/content grid fills it. */
  max-width: none;
  margin: 0;
  padding: 0;
  width: 100%;
  flex: 1;
  min-height: 0;
  display: flex;
}

/* The signed-in shell body: sidebar | content. `hidden` (display:none from the
   UA stylesheet) still wins when #appSection is hidden pre-login. */
.app-body {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
}

/* Flex column: the scrollable body (.sidebar-scroll) takes the free height
   and the RUN PROJECT footer (.sidebar-run, styled with the other sidebar
   pieces further down) stays pinned at the bottom, always on screen. */
.sidebar {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* Grid items refuse to shrink below their content by default
     (min-height:auto); without this the tall sidebar stretches the grid row
     past the viewport and the pinned footer overflows off screen. */
  min-height: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
}

.sidebar-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 1rem 1.1rem 1.25rem;
}

.content {
  overflow-y: auto;
  min-width: 0;
  /* Same grid-item shrink allowance as .sidebar: tall tab content must
     scroll in here, not stretch the shared grid row past the viewport. */
  min-height: 0;
  padding: 1.25rem 1.5rem 3rem;
}

/* The login view fills the shell body and centres Clerk's card.
   .login-wrap is a COLUMN flex (so the admin-only notice stacks above the
   Clerk card — see the base rule), which rotates the axes here: top-pinning
   the card is justify-content, not align-items. An align-items override
   would instead LEFT-shift the card (that exact bug shipped once —
   left-justified sign-in form). Horizontal centring comes from the base
   rule's align-items: center. */
.shell-main > .login-wrap {
  flex: 1;
  justify-content: flex-start;
  /* The shell is hard-capped at 100vh now (see .app-shell); on a short
     window the Clerk card must scroll within the login view rather than
     clip. Vertical only — horizontal centring still comes from the base
     rule's align-items and is not affected. */
  overflow-y: auto;
}

/* === Shell: top bar ====================================================== */
/*  Two clusters — brand (left), API chip + hamburger (right; New Project
    lives in the hamburger menu). Fixed height, own surface, bottom border. */

.topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 1rem;
  height: 60px;
  padding: 0 1.25rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.topbar-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: none;
}

.brand-wordmark {
  font-weight: 800;
  font-size: 1.56rem;
  letter-spacing: -0.01em;
  color: var(--text);
  white-space: nowrap;
}

/* The Synesis ⓘ tooltip trigger. position:relative anchors the popover. */
.brand-info {
  position: relative;
  display: inline-block;
  margin-left: 0.3rem;
  color: var(--accent);
  cursor: help;
  font-size: 0.8rem;
  font-weight: 700;
}
.brand-info:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* The Synesis blurb popover — two paragraphs, revealed on hover/focus. */
.brand-tip {
  display: none;
  position: absolute;
  top: 1.6em;
  left: 0;
  z-index: 300;
  width: 320px;
  max-width: 80vw;
  padding: 0.85rem 1rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: var(--shadow-md);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.55;
  text-align: left;
  white-space: normal;
  cursor: auto;
}
.brand-info:hover .brand-tip,
.brand-info:focus .brand-tip,
.brand-info:focus-within .brand-tip {
  display: block;
}
.brand-tip-p {
  display: block;
}
.brand-tip-p + .brand-tip-p {
  margin-top: 0.6rem;
}

/* Thin vertical divider between the wordmark and the product name. */
.brand-divider {
  width: 1px;
  height: 31px;
  background: var(--border-strong);
}

.brand-product {
  font-weight: 700;
  /* Match the wordmark's enlarged size (was the inherited 1rem body default). */
  font-size: 1.56rem;
  color: var(--accent);
  white-space: nowrap;
}

/* Small "BETA" chip. */
.brand-beta {
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
}

/* Right cluster: API chip + hamburger. margin-left:auto pushes it to the far
   edge now that the centre cluster is gone (New Project moved into the
   hamburger menu, 2026-08-03 styling pass). */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: none;
  margin-left: auto;
}

/* API chip: a pill button with a status dot. */
.api-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  background: var(--surface-muted);
  border: 1px solid var(--border-strong);
  color: var(--text);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.api-chip:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Status dot: green when a key is stored, red when not (set by main.js). The
   neutral default covers the brief moment before the first paint. */
.api-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-subtle);
  flex: none;
}
.api-dot-good { background: var(--good); }
.api-dot-bad { background: var(--bad); }

/* === Shell: hamburger menu =============================================== */

.menu-wrap {
  position: relative;
}

.menu-toggle {
  background: transparent;
  border: 0;
  padding: 0.3rem 0.55rem;
  border-radius: 6px;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
}
.menu-toggle:hover {
  background: var(--surface-muted);
  color: var(--text);
}

/* Dropdown panel, anchored to the toggle. `hidden` closes it (main.js). */
.app-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 200;
  min-width: 250px;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: var(--shadow-md);
}

/* One menu row — used for links, buttons, and the theme toggle. Applies to both
   <button> and <a> so they read as one list. */
.menu-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.menu-item:hover {
  background: var(--surface-muted);
}

/* The signed-in email chip: quieter, and allowed to wrap a long address. */
.menu-email {
  color: var(--text-muted);
  font-size: 0.82rem;
  word-break: break-all;
}

/* The prompt-template selector row inside the menu: a small label above the
   full-width select. */
.menu-row {
  padding: 0.4rem 0.6rem 0.5rem;
}
.menu-row label {
  display: block;
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-subtle);
}

/* Theme toggle as a menu item: the icon stack sits before the "Theme" label. */
.theme-toggle-icons {
  display: inline-flex;
  align-items: center;
  color: var(--text-muted);
}

/* === Shell: sidebar ====================================================== */

/* (The "PROJECT MENU" heading and its .sidebar-title rule were dropped on
   2026-07-28 — the sidebar's contents are self-describing and the label was
   just consuming vertical space at the top of the column.) */

.sidebar-block {
  margin-bottom: 1rem;
}

/* ======================================================================== */
/* Question panel (U1) — the clarify-chat authoring surface.                */
/*                                                                          */
/* Rendered by `app/clarify-chat.js`. Two states share the bordered panel:  */
/* the chat (message log + input row) and the collapsed ACCEPTED QUESTION   */
/* card. All colours come from the existing theme tokens (no new palette),  */
/* so both light and dark themes work unchanged. The accepted brief lands   */
/* in the hidden #projectDescription field; these rules only style the UI.  */
/* ======================================================================== */

.question-panel {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  overflow: hidden;
  margin-bottom: 1rem;
}

/* Panel header row ("Question"). */
.question-head {
  display: flex;
  align-items: center;
  padding: 0.65rem 0.8rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-muted);
}

.question-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text);
}

/* --- Chat state --------------------------------------------------------- */

.clarify-chat-log {
  /* min-height gives the panel presence on first load: the welcome bubble sits
     at the top with breathing room below it, instead of the panel collapsing
     to a cramped strip (user feedback, 2026-07-22). max-height still caps the
     log once a conversation grows; between the two it scrolls. */
  min-height: 200px;
  max-height: 320px;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* One message bubble. Bot/system align left; the user's own turns align
   right. Bot/user carry one square corner to match the wireframe's shape. */
.clarify-msg {
  max-width: 88%;
  padding: 0.5rem 0.7rem;
  border-radius: 10px;
  font-size: 0.9rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.clarify-msg-bot {
  align-self: flex-start;
  background: var(--surface-muted);
  border: 1px solid var(--border);
  color: var(--text);
  border-bottom-left-radius: 2px;
}

/* User bubble: accent fill. `color: var(--surface)` is the theme-safe inverse
   of the accent (accent-on-surface is used for links, so surface-on-accent is
   equally legible) — readable in both light and dark modes. */
.clarify-msg-user {
  align-self: flex-end;
  background: var(--accent);
  color: var(--surface);
  border-bottom-right-radius: 2px;
}

.clarify-msg-system {
  align-self: center;
  background: transparent;
  color: var(--text-muted);
  font-style: italic;
  font-size: 0.83rem;
  max-width: 100%;
  text-align: center;
}

.clarify-msg-thinking {
  align-self: flex-start;
  color: var(--text-muted);
  letter-spacing: 0.15em;
}

/* The closed brief, shown inside the bot's "ready" message as a quoted block. */
.clarify-brief-block {
  margin-top: 0.4rem;
  padding: 0.5rem 0.6rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  font-size: 0.88rem;
  color: var(--text);
}

/* Accept button, inside the "ready" bubble (extends .btn-primary). */
.clarify-accept-btn {
  display: block;
  width: 100%;
  margin-top: 0.6rem;
}

.clarify-chat-input-row {
  display: flex;
  gap: 0.5rem;
  padding: 0.5rem;
  border-top: 1px solid var(--border);
}

.clarify-chat-input {
  flex: 1;
  resize: vertical;
  /* Roomy default: fits the wrapped placeholder without a native scrollbar and
     gives the user space to type a real description (user feedback). */
  min-height: 5.75rem;
}

/* Send stretches to match the input's height so the row reads as one control
   (align-self: stretch, not flex-end — the button previously sat short at the
   bottom of the row). */
.clarify-chat-input-row .btn-primary {
  align-self: stretch;
  white-space: nowrap;
}

/* --- Accepted state ----------------------------------------------------- */

.clarify-accepted {
  padding: 0.8rem;
}

/* The ACCEPTED QUESTION content. Deliberately *unstyled* as a card: the
   surrounding .question-panel already provides the border, radius and
   background, so giving this a second border/fill nested it inside its own
   well (user feedback, 2026-07-28). It keeps only `position: relative`, which
   anchors the ✎ edit button to the content area's top-right corner. */
.clarify-accepted-card {
  position: relative;
}

.clarify-accepted-label {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--text-subtle);
  margin-bottom: 0.5rem;
  padding-right: 1.8rem; /* clear the edit button */
}

.clarify-accepted-brief {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ✎ Edit affordance, top-right of the accepted content. Zero offsets align it
   with the content box (which is already inset by .clarify-accepted's padding)
   so it sits flush with the label's baseline row rather than floating inward. */
.clarify-edit-btn {
  position: absolute;
  top: 0;
  right: 0;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 0.9rem;
  color: var(--text-subtle);
  background: transparent;
  border: 0;
  border-radius: 4px;
  cursor: pointer;
}

.clarify-edit-btn:hover {
  background: var(--accent-soft);
  color: var(--text);
}

/* Accordion: a bordered group with a clickable header (a real <button> for
   keyboard access) and a body toggled via the `hidden` attribute. */
.accordion {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.6rem;
  background: var(--surface);
  overflow: hidden;
}

.accordion-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  padding: 0.65rem 0.8rem;
  background: var(--surface-muted);
  border: 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

/* Chevron indicator: a rotated corner that points down when collapsed and up
   when the accordion is expanded (`aria-expanded="true"`). */
.chev {
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--text-subtle);
  border-bottom: 2px solid var(--text-subtle);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
  flex: none;
}
.accordion-head[aria-expanded="true"] .chev {
  transform: rotate(-135deg);
}

.accordion-body {
  padding: 0.75rem 0.8rem 1rem;
}

.accordion-desc {
  margin: 0 0 0.6rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  line-height: 1.45;
}

/* Stacked, full-width action buttons inside an accordion. */
.sidebar-actions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.sidebar-actions button {
  width: 100%;
}

/* Small uppercase sub-labels inside the Information Source accordion
   ("Online Information", "Private Documents"). */
.sub-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-subtle);
  font-weight: 700;
  margin: 0.85rem 0 0.4rem;
}
.sub-label:first-child {
  margin-top: 0;
}

/* Info tooltip anchor + popover for a sub-label (same idiom as .brand-info). */
.sub-info {
  position: relative;
  display: inline-block;
  margin-left: 0.25rem;
  color: var(--accent);
  cursor: help;
  font-size: 0.75rem;
}
.sub-info:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}
.sub-tip {
  display: none;
  position: absolute;
  top: 1.5em;
  left: 0;
  z-index: 50;
  width: 260px;
  max-width: 70vw;
  padding: 0.6rem 0.75rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  box-shadow: var(--shadow-md);
  font-size: 0.78rem;
  font-weight: 400;
  line-height: 1.5;
  text-transform: none;
  letter-spacing: normal;
  text-align: left;
}
.sub-info:hover .sub-tip,
.sub-info:focus .sub-tip,
.sub-info:focus-within .sub-tip {
  display: block;
}

/* WEB SEARCH ON/OFF toggle chip: a labelled switch. The track + thumb move on
   the `aria-checked` state that main.js maintains. */
.toggle-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  background: transparent;
  border: 0;
  padding: 0.2rem 0;
  cursor: pointer;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text);
}
.toggle-track {
  position: relative;
  width: 34px;
  height: 18px;
  border-radius: 999px;
  background: var(--border-strong);
  transition: background-color 0.15s ease;
  flex: none;
}
.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease;
}
.toggle-chip[aria-checked="true"] .toggle-track {
  background: var(--good);
}
.toggle-chip[aria-checked="true"] .toggle-thumb {
  transform: translateX(16px);
}

/* Document caps note under the file list. */
.docs-caps {
  margin: 0.55rem 0 0;
  font-size: 0.72rem;
  color: var(--text-subtle);
  line-height: 1.4;
}

/* === Shell: headline strip =============================================== */
/*  Three large metrics (P_success / P_failure / Δ vs baseline). Metrics-only
    since the RUN PROJECT button moved to the sidebar (2026-07-22 feedback). */

.headline {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding: 0.25rem 0 1rem;
}

.headline-metrics {
  display: flex;
  gap: 2.5rem;
  flex-wrap: wrap;
  align-items: flex-start;
}
.headline-metrics.calculating {
  opacity: 0.55;
}

.headline-metric {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.headline-label {
  display: flex;
  align-items: center;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-subtle);
}

.headline-value {
  font-size: 2.4rem;
  font-weight: 800;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  line-height: 1.1;
}

/* Semantic tones for the headline figures (styling spec 2026-08-03):
   P_success is always --good, P_failure always --bad, and Δ vs baseline is
   toned by its magnitude with a ±0.05 pp dead-band (> +0.05 pp → good,
   < −0.05 pp → bad, otherwise the neutral --text inherited from
   .headline-value above — so a displayed "0.0 pp" is never coloured).
   Applied by result-strip.js via buildMetric's `tone` argument. --accent is
   reserved for a raw-score figure should one return to the strip. */
.headline-value.tone-good   { color: var(--good); }
.headline-value.tone-bad    { color: var(--bad); }
.headline-value.tone-accent { color: var(--accent); }

/* Inline error rendered into the headline strip when a /score call fails. */
.headline-error {
  color: var(--bad);
  font-size: 0.95rem;
}

/* P_success / P_failure ⓘ tooltip (same idiom as .brand-info). */
.headline-info {
  position: relative;
  display: inline-block;
  margin-left: 0.3rem;
  color: var(--accent);
  cursor: help;
  font-size: 0.75rem;
  font-weight: 700;
}
.headline-info:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}
.headline-tip {
  display: none;
  position: absolute;
  top: 1.5em;
  left: 0;
  z-index: 300;
  width: 300px;
  max-width: 80vw;
  padding: 0.75rem 0.9rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: var(--shadow-md);
  font-size: 0.78rem;
  font-weight: 400;
  line-height: 1.55;
  text-align: left;
  white-space: normal;
  cursor: auto;
}
.headline-info:hover .headline-tip,
.headline-info:focus .headline-tip,
.headline-info:focus-within .headline-tip {
  display: block;
}

/* The primary RUN PROJECT button — the flagship action of the panel. */
.btn-run {
  background: var(--accent);
  color: #fff;
  font-weight: 800;
  letter-spacing: 0.5px;
  padding: 0.85rem 2.5rem;
  border-radius: 8px;
  font-size: 1rem;
}
.btn-run:hover:not(:disabled) {
  background: var(--accent-strong);
}

/* === Shell: tab bar + panels ============================================= */

.tab-bar {
  display: flex;
  border: 1.5px solid var(--border-strong);
  border-radius: 6px;
  overflow: hidden;
}

.tab-btn {
  flex: 1;
  text-align: center;
  padding: 0.7rem 0.5rem;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--surface-muted);
  border: none;
  border-right: 1px solid var(--border);
  border-radius: 0;
  cursor: pointer;
}
.tab-btn:last-child {
  border-right: 0;
}
.tab-btn:not(.active):hover {
  background: var(--surface);
  color: var(--text);
}
.tab-btn.active {
  background: var(--accent);
  color: #fff;
}

.tab-panels {
  margin-top: 1rem;
}

/* Pre-run empty-state line shown before a research run. The RUN PROJECT
   reference inside is bolded but not italic. */
.tab-empty {
  margin: 0.5rem 0;
  font-size: 0.9rem;
  font-style: italic;
  color: var(--text-muted);
}
.tab-empty strong {
  font-style: normal;
}

/* Scenarios / Benchmarks tab header row: a title, a RUN button, and a
   (currently disabled) + add button. */
.tab-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.tab-head-title {
  flex: 1;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle);
}
.tab-run-btn {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 0.35rem 0.9rem;
  border-radius: 6px;
  background: var(--surface-muted);
  border: 1px solid var(--border-strong);
  color: var(--text);
  cursor: pointer;
}
.tab-run-btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.tab-add-btn {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
  padding: 0.2rem 0.65rem;
  border-radius: 6px;
  background: var(--surface-muted);
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
  cursor: pointer;
}

/* === Shell: responsive =================================================== */
/*  Below ~900px the two-pane grid collapses: the sidebar stacks above the
    content and the whole page scrolls as one document (a fuller polish pass is
    deferred to U5). */

@media (max-width: 900px) {
  .shell-main {
    display: block;
    overflow-y: auto;
  }
  .app-body {
    display: block;
  }
  .sidebar {
    display: block;
    overflow: visible;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .sidebar-scroll {
    /* Single-column mode: the page scrolls as one, so the inner scroll
       container (and the RUN footer pin) stand down. */
    overflow: visible;
  }
  .content {
    overflow: visible;
  }
}

/* === Add/Edit entry modal (U3/U4) ======================================== */
/*  Shared native <dialog> for adding/editing custom scenarios + benchmarks
    (app/modals/entry-modal.js — the markup is built in JS from /meta). Sticky
    footer per the wireframe so Cancel/Save stay reachable while the 14 rows
    scroll.                                                                   */

#entryModal {
  max-width: 640px;
  width: 92%;
  max-height: 85vh;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem 0;
  background: var(--surface);
  color: var(--text);
  margin: auto;
}
#entryModal::backdrop {
  background: var(--modal-backdrop);
}
#entryModal .entry-modal-title {
  margin: 0 0 0.25rem;
  font-size: 1.15rem;
  color: var(--accent-strong);
}

.entry-field-label {
  margin-top: 0.9rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
}

.entry-input {
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  box-sizing: border-box;
}
.entry-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
.entry-textarea {
  resize: vertical;
}

.entry-param-rows {
  margin-top: 0.4rem;
}
.entry-param-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.25rem 0;
}
.entry-param-label {
  flex: 1;
  font-size: 0.88rem;
}
.entry-param-code {
  color: var(--text-subtle);
  font-size: 0.72rem;
}
.entry-num {
  width: 7.5rem;
  flex: none;
  margin-top: 0;
  font-family: ui-monospace, SFMono-Regular, monospace;
}

/* Sticky footer: stays pinned while the param rows scroll. */
.entry-modal-footer {
  position: sticky;
  bottom: 0;
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 0.9rem 0;
  margin-top: 1rem;
}

/* === API-settings signup hint (U5) ======================================= */

.api-signup-hint {
  margin: 0.15rem 0 0.4rem;
  font-size: 0.78rem;
  color: var(--text-subtle);
}
.api-signup-hint a {
  color: var(--text-subtle);
  text-decoration: underline;
}
.api-signup-hint a:hover {
  color: var(--accent);
}

/* ======================================================================== */
/* Define Project modal + sidebar RUN (2026-07-22 feedback)                 */
/*                                                                          */
/* The clarification chat and the project-name input live in the            */
/* #projectDefineModal (auto-opened on first load / New Project); the       */
/* sidebar Question panel shows either the pre-accept placeholder or the    */
/* ACCEPTED QUESTION card. RUN PROJECT moved from the headline strip into   */
/* the sidebar, above the (pre-run greyed) Generate Reports accordion.      */
/* ======================================================================== */

/* Both dialogs are themed explicitly (like every other dialog in this file):
   a <dialog> with no background/colour of its own falls back to the UA's
   white card, which reads as broken in dark mode. */
#projectDefineModal,
#confirmReacceptModal {
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  background: var(--surface);
  color: var(--text);
  margin: auto;
}
#projectDefineModal::backdrop,
#confirmReacceptModal::backdrop {
  background: var(--modal-backdrop);
}
#projectDefineModal h3,
#confirmReacceptModal h3 {
  margin: 0 0 0.25rem;
  font-size: 1.15rem;
  color: var(--accent-strong);
}

/* The define modal is wider than the settings dialogs so the chat has room.
   Scaled up 25% on 2026-07-28 (was 680px) — this is the app's main authoring
   surface and the chat wants the space. The 92vw cap keeps it from overflowing
   narrow viewports. */
#projectDefineModal {
  width: min(850px, 92vw);
}

/* ---- Shared corner ✕ dismiss button ------------------------------------ */
/*
   Every dialog dismisses from a ✕ in its top-right corner rather than a
   "Close"/"Cancel" button in the footer (user feedback, 2026-07-28). Footer
   buttons that only dismissed were removed; footers now carry actions only.
   The one exception is #confirmReacceptModal, a destructive confirmation
   where an explicitly labelled Cancel beside "Clear and continue" is worth
   keeping — there the ✕ is a second route to the same cancel.

   No `position: relative` on the dialogs: the UA stylesheet already gives
   `dialog:modal` `position: fixed` (and a plain open dialog `position:
   absolute`), either of which makes it the containing block for this
   absolutely positioned child. Overriding to `relative` would defeat the
   `inset: 0` + `margin: auto` centering these dialogs rely on.

   Positioned inside each dialog's existing padding, so it costs no extra
   height or padding — it just occupies corner whitespace that was already
   there. Visual weight matches the ✎ affordance on the sidebar's accepted
   card.
*/
.dialog-close-btn {
  position: absolute;
  top: 0.55rem;
  right: 0.6rem;
  width: 1.9rem;
  height: 1.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 0.95rem;
  line-height: 1;
  color: var(--text-subtle);
  background: transparent;
  border: 0;
  border-radius: 4px;
  cursor: pointer;
}
.dialog-close-btn:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

/* Focus handling. `app/modals/dialog-focus.js` is what actually keeps the ✕
   from being the target when a dialog opens; these two rules are the backstop,
   so a stray programmatic focus can never draw a ring around the close button
   (user feedback, 2026-07-28 — "should not be highlighted, ever"). Keyboard
   users still get a clear indicator: :focus-visible only matches genuine
   keyboard navigation. */
.dialog-close-btn:focus {
  outline: none;
}
.dialog-close-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The dialog shell receives initial focus (see dialog-focus.js) and is never
   tab-reachable, so it should never render a ring of its own. */
dialog:focus {
  outline: none;
}

/* Reserve the corner so a long title can never run under the ✕. Applies to
   every dialog carrying one. */
#projectDefineModal h3,
#monteCarloModal h3,
#modelClarificationModal h3,
#confirmReacceptModal h3,
#apiSettingsModal h3,
#termsModal h3,
.entry-modal .entry-modal-title {
  padding-right: 2rem;
}
#confirmReacceptModal {
  width: min(460px, 92vw);
}

/* Name field: label on its own line above the input (feedback 2026-07-22).
   The name is mandatory — the chat can't be used until it's filled. */
.define-name-row {
  margin: 1rem 0;
}
.define-name-row label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
}
.define-name-row input {
  width: 100%;
}
/* Required marker + the hint shown while the field is empty. */
.define-name-req {
  color: var(--bad);
  margin-left: 0.15rem;
}
.define-name-hint {
  margin: 0.35rem 0 0;
  font-size: 0.75rem;
  color: var(--text-subtle);
}
.define-name-hint.is-required {
  color: var(--bad);
}

/* The chat inside the modal: give the log real presence (the modal IS the
   authoring surface now) while keeping it scrollable on short viewports. */
.define-chat {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
}
/* Scaled up 25% alongside the modal width (was 260px / 45vh, 2026-07-28) so the
   dialog grows in both dimensions rather than just getting wider. The vh cap
   still bounds it on short viewports; past that the log scrolls as before. */
.define-chat .clarify-chat-log {
  min-height: 325px;
  max-height: 56vh;
}

/* Sidebar pre-accept placeholder: hint + full-width "Define project". */
.question-placeholder {
  padding: 0.85rem;
}
.question-placeholder-hint {
  margin: 0 0 0.75rem;
  font-size: 0.83rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.question-placeholder .btn-primary {
  display: block;
  width: 100%;
}

/* Project name on the ACCEPTED QUESTION card (above the brief). */
.clarify-accepted-name {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.35rem;
  padding-right: 1.8rem; /* clear the ✎ button */
  overflow-wrap: anywhere;
}

/* Sidebar RUN PROJECT block: pinned footer of the sidebar flex column
   (2026-08-03) — the flagship action goes full-width and never scrolls
   off screen. */
.sidebar-run {
  flex: none;
  margin: 0;
  padding: 0.85rem 1.1rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--surface);
}
.sidebar-run .btn-run {
  display: block;
  width: 100%;
}
.sidebar-run .error {
  margin: 0.5rem 0 0;
}

/* In-flight state (run-indicator.js): the label carries the verb spinner.
   Full opacity despite `disabled` — this is "working", not the greyed-out
   gated state — with a progress cursor signalling the interaction block. */
.btn-run.running:disabled {
  opacity: 1;
  cursor: progress;
}

/* Global input lock while a run is in flight (run-indicator.js puts
   `run-locked` on <body> and makes the input regions inert). The sidebar
   body dims to signal its controls are locked; the tab panels stay at full
   opacity so in-flight results remain readable — their controls are dead
   via `inert`, not visually greyed. */
body.run-locked .sidebar-scroll {
  opacity: 0.55;
}

/* A disabled accordion head (Generate Reports pre-run): visibly muted and
   inert — sidebar.js's toggle never fires on a disabled button. */
.accordion-head:disabled {
  color: var(--text-subtle);
  cursor: not-allowed;
}
.accordion-head:disabled .chev {
  opacity: 0.4;
}

/* ===========================================================================
   Report preview overlay (app/report.js)
   ===========================================================================

   The generated report used to open as a same-origin `blob:` tab, which gave
   anything inside it read access to the BYOK key in localStorage
   (F-D3-REPORT-XSS). It now renders into a sandboxed iframe inside this
   near-fullscreen dialog: scripting off, opaque origin, no way back into the
   app. The dialog is built in JS on demand, so these rules are keyed off the
   `.report-preview` class rather than an id in index.html.
*/
.report-preview {
  width: min(1180px, 96vw);
  height: 92vh;
  max-width: none;
  max-height: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Toolbar: the controls that used to be inline `onclick` buttons inside the
   report document itself. They live out here, in the trusted parent, so the
   report can be rendered with scripting disabled entirely. */
.report-preview-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.65rem 3rem 0.65rem 1rem; /* right padding clears the ✕ */
  border-bottom: 1px solid var(--border);
  background: var(--surface-2, var(--surface));
}
.report-preview-title {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-right: 0.3rem;
}
.report-preview-hint {
  font-size: 0.75rem;
  color: var(--text-subtle);
}
/* The shared corner-✕ rules position against the dialog box; nudge it to sit
   centred in the toolbar strip rather than over the report content. */
.report-preview-close {
  top: 0.5rem;
  right: 0.5rem;
}

/* The isolated frame fills whatever the toolbar leaves. White background
   because the report is a print artefact with hardcoded light colours and is
   deliberately not themed. */
.report-preview-frame {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
  background: #fff;
}
