/* styles.css — dense, functional, theme-aware. Density over decoration.
   Light + dark via prefers-color-scheme. Status badges are the only "color". */

:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --border: #d9dee5;
  --text: #16202b;
  --muted: #647082;
  --accent: #0d4f8b;
  --accent-text: #ffffff;
  --danger: #b3261e;
  --ok: #1b6e3c;
  --amber: #8a5a00;
  --amber-bg: #fff2d6;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  --radius: 6px;
  --gap: 12px;
  /* Subtle row-highlight / raised-cell tint. Light theme: a faint accent wash so
     it reads on white (previously this var was undefined and highlights fell back
     to a WHITE overlay — invisible on the light surface). */
  --surface-2: rgba(13, 79, 139, 0.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0d1b2a;
    --surface: #14212f;
    --border: #26384a;
    --text: #e6ecf3;
    --muted: #93a2b3;
    --accent: #4c9be8;
    --accent-text: #0a1622;
    --danger: #ff6b61;
    --ok: #5cd18a;
    --amber: #f0cf82;
    --amber-bg: #4a3a12;
    --shadow: none;
    --surface-2: rgba(255, 255, 255, 0.04);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
}

/* --- header --- */
.app-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.brand {
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.2px;
  color: var(--text);
  text-decoration: none;
}
.brand .dot { color: var(--accent); }
.header-actions { display: flex; gap: 8px; }

/* --- header nav (Review link + due badge) --- */
.header-nav { margin-right: auto; margin-left: 16px; display: flex; gap: 12px; }
.nav-link {
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  padding: 6px 8px;
  border-radius: var(--radius);
}
.nav-link:hover { color: var(--text); }
.nav-link.has-due { color: var(--accent); }

/* --- layout --- */
.view {
  max-width: 900px;
  margin: 0 auto;
  padding: 16px;
}
.view-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  margin-bottom: 12px;
}
h2 { font-size: 20px; margin: 0; }
h3 { font-size: 15px; margin: 20px 0 8px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.muted { color: var(--muted); }
.sub { margin-top: 4px; }

/* --- buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
  text-decoration: none;
}
.btn:hover { border-color: var(--accent); }
.btn-primary { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
.btn-ghost { background: transparent; }
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger:hover { border-color: var(--danger); filter: brightness(1.05); }

/* --- danger zone (destructive delete, kept away from Save) --- */
.danger-zone { margin-top: 32px; padding-top: 16px; border-top: 1px solid var(--danger); }
.danger-zone h3 { color: var(--danger); }

/* --- watchlist table --- */
table.watchlist {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.watchlist th, .watchlist td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
}
.watchlist th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.watchlist tbody tr:last-child td { border-bottom: none; }
.watchlist tbody tr.row { cursor: pointer; }
.watchlist tbody tr.row:hover { background: rgba(127, 127, 127, 0.08); }
.cell-ticker { font-weight: 600; font-variant-numeric: tabular-nums; }

/* --- watchlist glance dots (Increment 6D D3, display-only) --- */
.watchlist th.wl-price, .watchlist td.wl-price,
.watchlist th.wl-buy, .watchlist td.wl-buy { text-align: right; white-space: nowrap; }
.watchlist th.wl-buy, .watchlist td.wl-buy { text-align: center; }
.wl-price-val { font-variant-numeric: tabular-nums; }
.wl-dot { font-size: 10px; vertical-align: middle; margin-left: 6px; line-height: 1; }
.wl-buy .wl-dot { margin-left: 0; }
.wl-dot-fresh { color: var(--ok); }
.wl-dot-stale { color: var(--amber); }
.wl-dot-below { color: var(--ok); }
.wl-dot-above { color: var(--danger); }

/* --- watchlist micro price sparkline (Increment 8L, B6) --- */
.watchlist th.wl-trend, .watchlist td.wl-trend { text-align: center; white-space: nowrap; width: 72px; }
.watchlist td.wl-trend .trend-spark { display: inline-block; vertical-align: middle; }

/* --- watchlist per-row live-price refresh (row-refresh) --- */
/* Centred column; the "—" fallback reads muted like the other not-available cells. */
.watchlist th.wl-refresh, .watchlist td.wl-refresh { text-align: center; white-space: nowrap; }
/* Compact row button: reuses the .vc-refresh look (both themes via its tokens) but
   sized to sit inside a 43px row with a ~28px tap target. */
.wl-refresh-btn { padding: 2px 6px; font-size: 14px; min-width: 28px; min-height: 28px; }

/* --- watchlist filter / sort controls (Increment 8J) --- */
.wl-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
}
/* Override the global full-width input/select rule: these are inline controls. */
.wl-controls .wl-search { flex: 1 1 220px; width: auto; min-width: 160px; }
.wl-controls .wl-status,
.wl-controls .wl-sort { width: auto; flex: 0 0 auto; }
.wl-sort-wrap { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.wl-dir { flex: 0 0 auto; white-space: nowrap; }
.wl-chip {
  flex: 0 0 auto;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
}
.wl-chip:hover { border-color: var(--accent); }
.wl-chip.is-active {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
}
.wl-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--muted);
}

/* --- cross-company compare table (Increment 8R) --- */
.cmp-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 4px 0 10px; }
.cmp-controls label { font-size: 13px; color: var(--muted); }
.cmp-controls .wl-status { width: auto; flex: 0 0 auto; }
.cmp-meta { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
table.compare-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.compare-table th, .compare-table td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.compare-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.compare-table tbody tr:last-child td { border-bottom: none; }
.compare-table tbody tr.row { cursor: pointer; }
.compare-table tbody tr.row:hover { background: rgba(127, 127, 127, 0.08); }
.compare-table td.cell-ticker { font-weight: 600; font-variant-numeric: tabular-nums; }
.compare-table th.cmp-num, .compare-table td.cmp-num { text-align: right; font-variant-numeric: tabular-nums; }
.cmp-th-sortable { cursor: pointer; user-select: none; }
.cmp-th-sortable:hover, .compare-table th.is-active { color: var(--text); }
.cmp-buy-below { color: var(--v-pass-fg); font-weight: 600; }
.cmp-buy-above { color: var(--v-fail-fg); font-weight: 600; }
.compare-table td.cmp-score { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cmp-pass { color: var(--v-pass-fg); font-weight: 600; }
.cmp-fail { color: var(--v-fail-fg); font-weight: 600; margin-left: 6px; }
.cmp-forensic {
  display: inline-block; font-size: 12px; font-weight: 700;
  padding: 2px 7px; border-radius: 999px;
  background: var(--v-fail-bg); color: var(--v-fail-fg);
}
.cmp-forensic-lolla { background: var(--danger); color: #fff; }
.btn-link {
  border: none;
  background: none;
  padding: 0;
  color: var(--accent);
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
}
.wl-empty { margin: 0; }
@media (max-width: 420px) {
  .wl-controls .wl-search { flex: 1 1 100%; width: 100%; }
}

/* --- "Needs you today" action inbox (Increment 8D) --- */
.action-inbox { margin: 0 0 20px; }
/* P3: one quiet Sovrenn-shortlist pointer above the watchlist (not a nag). */
.wl-sovrenn-pointer {
  display: inline-flex; align-items: center; gap: 4px; margin: 0 0 16px;
  font-size: 13px; text-decoration: none;
  /* Now a button (opens the filtered queue) — strip the native chrome so it reads
     as the same quiet muted line as before. */
  background: none; border: 0; padding: 0; cursor: pointer;
  color: inherit; font: inherit; text-align: left;
}
.wl-sovrenn-pointer:hover { color: var(--accent); text-decoration: underline; }
.wl-sovrenn-arrow { font-weight: 700; }
/* Triage caveat above the Sovrenn queue (F3) — muted, wraps on small screens. */
.wl-sovrenn-caveat:empty { display: none; }
.wl-sovrenn-caveat { margin: 0 0 12px; max-width: 60ch; }
.wl-sovrenn-triage { font-size: 12px; line-height: 1.5; margin: 0; }
.inbox-head-title { display: flex; align-items: center; gap: 6px; }
.inbox-title { margin: 0 0 8px; }
.inbox-empty { margin: 0; font-size: 14px; }
.inbox-list {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
.inbox-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.inbox-list .inbox-row:last-child { border-bottom: none; }
.inbox-row:hover { background: rgba(127, 127, 127, 0.08); }
.inbox-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.inbox-dot { font-size: 10px; line-height: 1; flex: 0 0 auto; }
.inbox-dot-danger { color: var(--danger); }
.inbox-dot-good { color: var(--ok); }
.inbox-dot-warn { color: var(--amber); }
.inbox-dot-neutral { color: var(--muted); }
.inbox-ticker { font-weight: 600; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.inbox-name { font-size: 13px; flex: 0 0 auto; }
.inbox-label { font-size: 13px; flex: 1 1 100%; }
/* F4 (8S): a price that JUST crossed into the buy zone — elevate the label so the
   most actionable moment reads louder than the ongoing buy-zone reminder. Weight
   only, no new colour, so both themes are unaffected. */
.inbox-row-just .inbox-label { font-weight: 600; }

/* --- empty state --- */
.empty {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 32px;
  text-align: center;
  background: var(--surface);
}

/* --- status badges --- */
.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid transparent;
  white-space: nowrap;
}
.badge-watching       { background: #e7edf5; color: #33506f; }
.badge-researching    { background: #fff2d6; color: #7a5600; }
.badge-thesis-formed  { background: #dcf0e3; color: #1b6e3c; }
.badge-holding        { background: #dde7f7; color: #1a3f7a; }
.badge-exited         { background: #eceef1; color: #55606e; }
@media (prefers-color-scheme: dark) {
  .badge-watching      { background: #21354a; color: #9fc0e6; }
  .badge-researching   { background: #4a3a12; color: #f0cf82; }
  .badge-thesis-formed { background: #163a26; color: #6fd89a; }
  .badge-holding       { background: #1a2f4d; color: #8fb6ef; }
  .badge-exited        { background: #2a333d; color: #a5b1bf; }
}

/* --- forms --- */
.record-form, .detail { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow); }
.field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.field-label { font-size: 13px; color: var(--muted); font-weight: 600; }
.field-hint { font-size: 12px; color: var(--muted); }

/* --- data-staleness "as of" chips + amber nudge (Increment 6C) --- */
.asof-chip {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--muted);
  vertical-align: middle;
}
.asof-chip.asof-stale { background: var(--amber-bg); color: var(--amber); border-color: var(--amber); }
.pf-asof { margin: 0 0 10px; }
.pf-asof-stale { color: var(--amber); }

/* --- Screener deep-links + results-date quick-setters (Increment 6C) --- */
.deep-link {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
}
.deep-link:hover { border-color: var(--accent); }
.quick-set { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px; }
.quick-set .field-hint { margin-left: 4px; }
input, textarea, select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font: inherit;
}
textarea { resize: vertical; }
/* Textareas GROW to fit their content instead of squishing long text into a
   few fixed rows behind a scrollbar. This bit hard once the draft loop landed:
   an AI-drafted thesis paragraph rendered into a rows="4" slot, and after a
   save/re-render every filled field came back as a letterbox. field-sizing is
   CSS-only (Chromium 123+; older browsers simply keep the rows attribute —
   graceful). min keeps empty fields inviting; max stops a wall of text from
   swallowing the page — beyond that it scrolls as before. */
textarea {
  field-sizing: content;
  min-height: 4.5em;
  max-height: 60vh;
}
input:focus, textarea:focus, select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.field-invalid { border-color: var(--danger); outline-color: var(--danger); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
@media (max-width: 560px) { .grid-2 { grid-template-columns: 1fr; } }
.form-actions { margin-top: 8px; }
/* --- new-from-file (Screener prefill) block on #/new --- */
.prefill-block { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--border); }
.prefill-block h3 { margin: 0 0 4px; font-size: 15px; }
.prefill-block .muted { margin: 0 0 10px; }
.prefill-actions { margin-bottom: 8px; }
.prefill-status:empty { display: none; }
.prefill-status { font-size: 13px; }
.form-errors:empty { display: none; }
.form-errors { margin-bottom: 12px; }
.err { color: var(--danger); font-size: 13px; padding: 6px 10px; border: 1px solid var(--danger); border-radius: var(--radius); margin-bottom: 6px; }

/* --- journal --- */
.journal-add { display: grid; grid-template-columns: 130px 1fr auto; gap: 8px; align-items: start; margin-bottom: 12px; }
@media (max-width: 560px) { .journal-add { grid-template-columns: 1fr; } }
.journal-list { list-style: none; margin: 0; padding: 0; }
.journal-entry { border-left: 2px solid var(--border); padding: 4px 0 10px 12px; margin-bottom: 4px; }
.journal-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.journal-date { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.journal-text { white-space: pre-wrap; }

/* --- toast --- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%) translateY(20px);
  max-width: 90vw;
  padding: 10px 16px;
  border-radius: var(--radius);
  background: var(--text);
  color: var(--bg);
  font-size: 14px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast-ok { background: var(--ok); color: #fff; }
.toast-error { background: var(--danger); color: #fff; }

/* --- backup nag banner (above the watchlist) --- */
.nag-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--danger);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.nag-text { font-size: 14px; }
.nag-actions { display: flex; gap: 8px; flex-shrink: 0; }
/* The "choose a backup folder" upsell line inside the export nag (increment 5A). */
.nag-suggest { display: block; margin-top: 4px; font-size: 13px; color: var(--muted); }

/* --- persistent update banner (bottom-pinned, never auto-hides) --- */
.update-banner {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 92vw;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: var(--radius);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.update-banner-text { font-size: 14px; }
.update-banner .btn { flex-shrink: 0; }
/* Merge warnings variant: a warning-toned persistent banner (increment 5C). It
   reuses .update-banner's layout but signals "needs your attention", not "reload". */
.update-banner.is-warning { background: var(--danger); color: #fff; }

/* --- import-mode chooser modal (increment 5C, two-device merge) --- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0.45);
}
.modal {
  width: 100%;
  max-width: 420px;
  padding: 20px;
  background: var(--surface, #fff);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  /* EVERY modal must fit the viewport and scroll internally. Without this, any
     modal with a long list (the Sovrenn report listed ~54 stale entries) grew
     taller than the screen and its ACTION BUTTONS fell below the edge with no
     way to reach them — the dialog was effectively stuck. The backdrop's 16px
     padding is inside the 100dvh, so 85vh leaves comfortable margin even with
     mobile browser chrome (dvh-aware browsers treat vh generously here). */
  max-height: min(85vh, calc(100dvh - 32px));
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal h3 { margin: 0 0 8px; font-size: 17px; }
.modal p { margin: 0 0 16px; font-size: 14px; color: var(--muted); }
.modal-actions { display: flex; flex-direction: column; gap: 8px; }
.modal-actions .btn { width: 100%; }

/* --- Calamity review (crash-day) — a CALM, read-only review. Deliberately not a
   wall of red: steady tone, reusing existing tokens. --- */
.cal-modal { max-width: 460px; display: flex; flex-direction: column; max-height: 85vh; overflow-y: auto; }
.cal-title { color: var(--text); text-transform: none; letter-spacing: 0; }
.cal-lead { color: var(--text); margin: 0 0 16px; }
.cal-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
  padding: 12px;
  margin: 0 0 12px;
}
.cal-card-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.cal-ticker { font-weight: 700; font-size: 14px; color: var(--text); }
.cal-drop { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cal-chip {
  display: inline-block;
  margin: 8px 0 4px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1.5;
  border: 1px solid var(--border);
  color: var(--muted);
}
.cal-chip-structural { color: var(--amber); background: var(--amber-bg); border-color: var(--amber); }
.cal-chip-opportunity { color: var(--ok); border-color: var(--ok); }
.cal-plan { margin: 8px 0 4px; }
.cal-plan-field { margin: 0 0 8px; }
.cal-plan-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.cal-plan-text { margin: 2px 0 0; font-size: 13px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cal-plan-text.muted { color: var(--muted); }
.cal-open { display: inline-block; margin-top: 4px; font-size: 13px; color: var(--accent); }
.cal-opps-head { color: var(--text); margin: 4px 0 6px; }
.cal-opps { margin: 0 0 14px; padding-left: 18px; }
.cal-opps li { font-size: 13px; margin: 0 0 4px; }
.cal-opps a { color: var(--accent); }
.cal-reminder { font-size: 13px; font-style: italic; margin: 0 0 16px; }

/* --- bulk "Update prices" panel (Increment 8F) --- */
.view-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.pu-modal { max-width: 460px; display: flex; flex-direction: column; max-height: 85vh; }
.pu-list { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; margin: 4px 0 14px; padding-right: 2px; }
.pu-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.pu-row-info { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; flex: 1 1 55%; min-width: 0; }
.pu-ticker { font-weight: 700; font-size: 13px; }
.pu-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.pu-asof { font-size: 11px; color: var(--muted); white-space: nowrap; }
.pu-asof-stale { color: var(--amber); }
.pu-row-input { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.pu-cur { font-size: 13px; }
.pu-input { width: 108px; }
.pu-row-err { flex: 1 1 100%; color: var(--danger); font-size: 12px; }
/* Paste-prices box (P2): prefills the rows above; nothing here writes a price. */
.pu-paste-area { border: 1px solid var(--border); border-radius: 8px; margin: 0 0 12px; background: var(--bg); }
.pu-paste-toggle { cursor: pointer; padding: 8px 12px; font-size: 13px; font-weight: 600; }
.pu-paste-body { display: flex; flex-direction: column; gap: 8px; padding: 0 12px 12px; }
.pu-paste-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 13px; resize: vertical; min-height: 68px; }
.pu-paste-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.pu-paste-summary { font-size: 12px; display: flex; flex-direction: column; gap: 4px; }
.pu-paste-count { font-weight: 600; }
.pu-paste-details summary { cursor: pointer; }
.pu-paste-list { margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 2px; }
/* A row prefilled from the paste box — a quiet tint + a "from paste" tag. */
.pu-row-pasted { background: var(--surface-2); border-radius: 6px; }
.pu-paste-tag { font-size: 10px; font-weight: 600; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 1px 6px; white-space: nowrap; }

/* --- settings data-safety lines --- */
.settings-storage { font-size: 13px; }
.settings-check { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; margin: 6px 0; cursor: pointer; }
.settings-check input { margin-top: 2px; }
.settings-storage.is-protected { color: var(--ok); }
.settings-storage.is-atrisk { color: var(--danger); }

/* --- auto-backup block in Settings → Data safety (increment 5A) --- */
.settings-autobackup { margin-top: 12px; }
.settings-autobackup h4 { margin: 0 0 6px; font-size: 14px; }
.settings-autobackup .form-actions { margin-top: 8px; flex-wrap: wrap; gap: 8px; }

/* --- manual-import helper card (shown only when folder auto-backup is
   unavailable — phones/most mobile). Prominent but calm: accent-tinted panel. --- */
.settings-manualimport {
  margin-top: 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.settings-manualimport h4 { margin: 0 0 6px; font-size: 14px; }
.settings-manualimport p { margin: 6px 0 0; }
.settings-manualimport .form-actions { margin-top: 10px; flex-wrap: wrap; gap: 8px; }

/* --- manual inputs 3-up --- */
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 16px; }
@media (max-width: 640px) { .grid-3 { grid-template-columns: 1fr; } }

/* --- forensic scorecard --- */
.scorecard { margin-top: 4px; }
.sc-empty { margin-top: 4px; }

/* verdict palette — theme-aware, one accent per verdict, review stays neutral */
:root {
  --v-pass-bg: #dcf0e3; --v-pass-fg: #1b6e3c;
  --v-warn-bg: #fff2d6; --v-warn-fg: #7a5600;
  --v-fail-bg: #fbdcd9; --v-fail-fg: #b3261e;
  --v-review-bg: #e7edf5; --v-review-fg: #33506f;
  --v-na-bg: #eceef1; --v-na-fg: #55606e;
}
@media (prefers-color-scheme: dark) {
  :root {
    --v-pass-bg: #163a26; --v-pass-fg: #6fd89a;
    --v-warn-bg: #4a3a12; --v-warn-fg: #f0cf82;
    --v-fail-bg: #4a1c18; --v-fail-fg: #ff8a80;
    --v-review-bg: #21354a; --v-review-fg: #9fc0e6;
    --v-na-bg: #2a333d; --v-na-fg: #a5b1bf;
  }
}

.sc-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 4px 0 12px; }
.sc-chip { font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 999px; }
.sc-chip.sc-pass { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.sc-chip.sc-warn { background: var(--v-warn-bg); color: var(--v-warn-fg); }
.sc-chip.sc-fail { background: var(--v-fail-bg); color: var(--v-fail-fg); }
.sc-chip.sc-review { background: var(--v-review-bg); color: var(--v-review-fg); }
.sc-chip.sc-na { background: var(--v-na-bg); color: var(--v-na-fg); }
.sc-years { margin-left: auto; font-size: 12px; }

.scorecard-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 13px;
}
.scorecard-table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px;
  color: var(--muted); padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.scorecard-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.scorecard-table tr:last-child td { border-bottom: none; }
.sc-group td {
  background: var(--bg); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.5px; color: var(--muted); padding: 6px 10px;
}
.sc-label { font-weight: 600; white-space: nowrap; }
.sc-value { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text); }
.sc-detail { font-size: 12px; line-height: 1.4; }

.sc-badge { font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.3px; }
.sc-badge.sc-pass { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.sc-badge.sc-warn { background: var(--v-warn-bg); color: var(--v-warn-fg); }
.sc-badge.sc-fail { background: var(--v-fail-bg); color: var(--v-fail-fg); }
.sc-badge.sc-review { background: var(--v-review-bg); color: var(--v-review-fg); }
.sc-badge.sc-na { background: var(--v-na-bg); color: var(--v-na-fg); }

.sc-type { font-size: 12px; font-weight: 700; padding: 2px 8px; border-radius: 999px; background: var(--v-review-bg); color: var(--v-review-fg); }
.sc-type-franchise { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.sc-type-commodity { background: var(--v-warn-bg); color: var(--v-warn-fg); }

@media (max-width: 640px) {
  .sc-detail { white-space: normal; }
  .scorecard-table { font-size: 12px; }
}

/* --- Trends: small-multiple line charts + annual series (increment 8E) --- */
/* Charts are hand-rolled SVG (js/charts.js); all colour is CSS-var driven there,
   so the cards only own layout. `min-width:0` on cards keeps a full-width SVG from
   blowing out the grid; auto-fit + the 640px query drop to one column on mobile. */
.trends { margin-top: 8px; }
.trend-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}
.trend-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  min-width: 0;
}
.trend-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.trend-card-title { font-size: 13px; font-weight: 600; color: var(--text); }
.trend-card-latest {
  font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text);
  font-size: 13px; white-space: nowrap;
}
.trend-delta {
  display: inline-block; margin-top: 2px; font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.trend-delta-good { color: var(--v-pass-fg); }
.trend-delta-warn { color: var(--v-warn-fg); }
.trend-delta-flat { color: var(--muted); }
.trend-chart-holder { margin-top: 6px; }
.trend-chart-holder .trend-chart { width: 100%; height: auto; display: block; }

.annual-series-wrap { margin-top: 12px; }
.annual-series-wrap > summary {
  cursor: pointer; font-size: 12px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.4px; padding: 6px 0;
}
.annual-series {
  width: 100%; border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
  font-size: 13px;
}
.annual-series th {
  text-align: right; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px;
  color: var(--muted); padding: 8px 10px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.annual-series th:first-child { text-align: left; }
.annual-series td {
  padding: 6px 10px; border-bottom: 1px solid var(--border);
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.annual-series td:first-child { text-align: left; }
.annual-series tr:last-child td { border-bottom: none; }
.as-year { font-weight: 600; }

@media (max-width: 640px) {
  .trend-grid { grid-template-columns: 1fr; }
}

/* --- valuation visuals (increment 8K): the range band + P/E & drawdown cards.
   The band is a hand-rolled SVG (js/charts.js rangeBandSVG) whose colour is all
   CSS-var driven; these rules own only layout, and width:100% keeps the SVG from
   ever forcing a page h-scroll. The P/E/drawdown cards reuse .trend-card/.trend-grid. */
.val-visuals { margin-top: 12px; display: grid; gap: 12px; }
.val-band {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px 12px; min-width: 0;
}
.val-band-holder { width: 100%; }
.val-band-holder .range-band { width: 100%; height: auto; display: block; }
.val-band-legend {
  display: flex; flex-wrap: wrap; gap: 12px; margin-top: 6px;
  font-size: 11px; color: var(--muted);
}
.val-band-legend .vbl-methods { color: var(--accent); font-weight: 600; }
.val-band-legend .vbl-price { color: var(--text); font-weight: 600; }
.val-band-legend .vbl-buy { color: var(--muted); font-weight: 600; }

/* --- valuation verdict (increment 6A) --- */
.valuation-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 13px;
}
.valuation-table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px;
  color: var(--muted); padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.valuation-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.valuation-table tr:last-child td { border-bottom: none; }
.val-pick { width: 28px; text-align: center; }
.val-label { font-weight: 600; }
.val-result { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text); font-weight: 600; }
.val-basis { font-size: 12px; line-height: 1.4; }
.val-row-na { opacity: 0.55; }
.val-row-na .val-result { font-weight: 400; }
.val-row-manual { background: var(--bg); }
.val-manual { width: 130px; }
.val-anchor-controls { margin-top: 12px; }
.val-mos { width: 110px; }

/* Buy-below line: the point of the increment. Green when the last price is at/below
   the buy price, red when above, neutral when there is no price to compare. */
.buy-below { margin-top: 14px; padding: 12px 14px; border-radius: var(--radius); border: 1px solid var(--border); }
.buy-below-main { font-weight: 600; font-size: 14px; }
.buy-below-foot { font-size: 12px; margin-top: 4px; }
.buy-below-ok { background: var(--v-pass-bg); border-color: var(--ok); }
.buy-below-ok .buy-below-main { color: var(--v-pass-fg); }
.buy-below-bad { background: var(--v-fail-bg); border-color: var(--danger); }
.buy-below-bad .buy-below-main { color: var(--v-fail-fg); }
.buy-below-neutral { background: var(--bg); }
.val-nobuy { margin-top: 14px; }

/* Header pill mirroring the buy-below verdict. */
.val-pill { font-size: 12px; font-weight: 700; padding: 2px 9px; border-radius: 999px; }
.val-pill-below { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.val-pill-above { background: var(--v-fail-bg); color: var(--v-fail-fg); }
.val-pill-neutral { background: var(--v-na-bg); color: var(--v-na-fg); }

/* One-line synthesised verdict (Increment 8C): four descriptive segments on a
   flex-wrap row — reads on one line on desktop, wraps cleanly on mobile. Each
   segment reuses the verdict colour tokens (good/warn/danger/neutral). */
.verdict-synthesis { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 2px; }
.verdict-synthesis .vseg {
  font-size: 12.5px; font-weight: 600; line-height: 1.35;
  padding: 3px 9px; border-radius: 8px;
}
.vseg-good { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.vseg-warn { background: var(--v-warn-bg); color: var(--v-warn-fg); }
.vseg-danger { background: var(--v-fail-bg); color: var(--v-fail-fg); }
.vseg-neutral { background: var(--v-na-bg); color: var(--v-na-fg); }

/* --- review cadence (Module 6) --- */
.rv-reminder {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 14px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
}
.rv-reminder summary { cursor: pointer; font-weight: 600; padding: 8px 0; }
.rv-reminder-body { padding-bottom: 8px; }
.rv-reasons { margin: 6px 0; padding-left: 20px; }
.rv-reasons li { margin-bottom: 6px; }
.rv-never { font-weight: 600; margin: 8px 0 4px; }
.rv-source { font-size: 12px; }

.rv-group { margin-bottom: 22px; }
.rv-group-title { display: flex; align-items: baseline; gap: 2px; }
.rv-count { font-size: 13px; text-transform: none; letter-spacing: 0; }
.rv-group-note { margin: 0 0 10px; font-size: 13px; }
.rv-list { display: flex; flex-direction: column; gap: 12px; }

.rv-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  box-shadow: var(--shadow);
}
/* Due cards carry the accent edge — these are the ones that need action. */
.rv-due { border-left: 4px solid var(--accent); }
.rv-reviewed { opacity: 0.62; padding: 10px 14px; }
.rv-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.rv-title { text-decoration: none; color: var(--text); font-weight: 600; }
.rv-title:hover .rv-name { text-decoration: underline; }
.rv-name { font-weight: 400; }
.rv-meta { display: flex; align-items: center; gap: 10px; }
.rv-date { font-size: 13px; font-variant-numeric: tabular-nums; }

/* Kill-criteria — the point of the module. Emphasised, full text, never
   truncated (wraps freely, preserves the writer's line breaks). */
.kc-block {
  margin: 12px 0 4px;
  padding: 10px 12px;
  border-left: 3px solid var(--danger);
  background: var(--v-fail-bg);
  border-radius: var(--radius);
}
.kc-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--danger);
  margin-bottom: 4px;
}
.kc-text { white-space: pre-wrap; overflow-wrap: anywhere; font-weight: 600; color: var(--text); }
.kc-missing { font-weight: 400; }

/* --- Kill-criteria tripwires + breach surfacing (Increment 4B) --- */
/* The RED breach banner at the top of the company detail. Reuses danger tokens. */
.kill-breach {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 2px solid var(--danger);
  border-left-width: 6px;
  border-radius: var(--radius);
  background: var(--v-fail-bg);
}
.kill-breach-head {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--danger);
  margin-bottom: 6px;
}
.kill-breach-list { margin: 0 0 6px; padding-left: 20px; }
.kill-breach-list li { color: var(--text); font-weight: 600; margin: 2px 0; }
.kill-breach-foot { font-size: 12px; }

/* Cluster synthesis callout (Increment 8B) — sits above the scorecard table.
   Same breach-banner family: left-accent bar + verdict-toned tint. Only rendered
   when a sourced pattern fires. Descriptive synthesis, no buy/sell language. */
.cluster-synthesis { margin: 0 0 12px; display: flex; flex-direction: column; gap: 8px; }
.cluster-callout {
  padding: 10px 12px;
  border: 1px solid transparent;
  border-left-width: 6px;
  border-radius: var(--radius);
}
.cluster-lolla {
  background: var(--v-fail-bg);
  border-color: var(--danger);
}
.cluster-accrual {
  background: var(--v-warn-bg);
  border-color: var(--v-warn-fg);
}
.cluster-head { font-weight: 800; margin-bottom: 4px; }
.cluster-lolla .cluster-head { color: var(--danger); text-transform: uppercase; letter-spacing: 0.5px; }
.cluster-accrual .cluster-head { color: var(--v-warn-fg); }
.cluster-body { color: var(--text); font-size: 13px; line-height: 1.45; }
.cluster-flags { font-weight: 600; }
.cluster-src { font-size: 11px; margin-top: 5px; }

/* The tripwire-management subsection under the freetext kill-criteria field. */
.kt-block { margin: 8px 0 4px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius); }
.kt-title { margin: 0 0 4px; font-size: 14px; }
.kt-hint { font-size: 12px; margin: 0 0 10px; }
.kt-empty { margin: 0 0 10px; }
.kt-list { list-style: none; margin: 0 0 10px; padding: 0; }
.kt-item {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 8px; border-radius: var(--radius); margin-bottom: 4px;
  background: transparent;
}
.kt-item.kt-fired { background: var(--v-fail-bg); }
.kt-detail { flex: 1; min-width: 200px; }
.kt-note-txt { font-size: 12px; }
.kt-badge {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px;
  padding: 1px 7px; border-radius: 999px; color: #fff;
}
.kt-badge-fired { background: var(--danger); }
.kt-badge-ok { background: var(--ok); }
.kt-badge-na { background: var(--muted); }
.kt-add { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.kt-add .field { margin: 0; }
.kt-threshold, .kt-years { width: 90px; }
.kt-add-action { display: flex; align-items: flex-end; }

/* --- ownership & incentives dossier (Increment 8H) --- */
.own-block { margin: 8px 0 4px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius); }
.own-title { margin: 0 0 4px; font-size: 14px; }
.own-hint { font-size: 12px; margin: 0 0 10px; }
.own-empty { margin: 0 0 10px; }
.own-body { margin: 0 0 10px; }
/* Latest-reading stat chips — the calm chip treatment, not a scorecard badge. */
.own-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 10px; }
.own-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.own-chip-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.own-chip-val { font-size: 14px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.own-asof { font-size: 12px; }
.own-charts { margin-bottom: 10px; }
/* Quiet REVIEW note — the calm surface-2 + accent-left-border family (help banner /
   temperament nudge), deliberately NOT the red/danger scorecard treatment: pledging
   levels have no sourced cutoff, so this reviews, it never alarms. */
.own-review {
  margin: 0 0 10px; padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.own-review-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--muted);
}
.own-review-body { margin: 6px 0 0; font-size: 13px; }

/* Increment 8M — pre-mortem nudge (A3) + base-rate note (A4). Both are quiet REVIEW
   surfaces in the same calm surface-2 + accent-left-border family (help banner /
   temperament nudge / own-review), deliberately NOT the red/danger scorecard
   treatment: neither is a gate, so they review, they never alarm. */
.premortem-nudge,
.base-rate-note {
  margin: 0 0 12px; padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.base-rate-note { margin: 10px 0; }
.pmn-label,
.brn-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--muted);
}
.pmn-body,
.brn-body { margin: 6px 0 0; font-size: 13px; }
.own-list { list-style: none; margin: 0 0 10px; padding: 0; }
.own-item {
  display: flex; align-items: baseline; gap: 8px 12px; flex-wrap: wrap;
  padding: 6px 8px; border-radius: var(--radius); margin-bottom: 4px;
}
.own-item-date { font-weight: 600; min-width: 96px; }
.own-item-vals { flex: 1; min-width: 160px; font-variant-numeric: tabular-nums; color: var(--muted); }
.own-add { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; }
.own-add .field { margin: 0; }
.own-pct { width: 110px; }
.own-add-action { display: flex; align-items: flex-end; }
@media (max-width: 560px) {
  /* Vertical stack at narrow widths — no wide tables, no horizontal scroll. */
  .own-add { flex-direction: column; align-items: stretch; }
  .own-add .field, .own-add-action { width: 100%; }
  .own-pct { width: 100%; }
  .own-item { flex-direction: column; align-items: stretch; gap: 2px; }
}

/* Increment 11G — scuttlebutt ledger. Reuses the journal list treatment (accent
   left border, dated head, remove control) + the calm chip family for the source
   type. Add-form is a labelled grid that collapses to a single column on narrow
   screens (no horizontal scroll). Both themes via vars. */
.scu-gloss { font-size: 12px; margin: 0 0 10px; }
.scu-block { margin: 4px 0; }
.scu-empty { margin: 0 0 12px; }
.scu-list { list-style: none; margin: 0 0 12px; padding: 0; }
.scu-item { border-left: 2px solid var(--accent); padding: 4px 0 10px 12px; margin-bottom: 6px; }
.scu-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.scu-item-date { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.scu-chip {
  display: inline-flex; align-items: center;
  padding: 2px 9px; border-radius: 999px;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--muted);
}
.scu-item-source { font-size: 13px; color: var(--muted); }
.scu-del { margin-left: auto; }
.scu-item-note { white-space: pre-wrap; margin-top: 6px; }
.scu-add { display: grid; grid-template-columns: 130px 160px 1fr auto; gap: 8px; align-items: start; }
.scu-add .field { margin: 0; }
.scu-add .scu-note { min-height: 40px; }
.scu-add-action { display: flex; align-items: flex-end; align-self: end; }
@media (max-width: 560px) {
  .scu-add { grid-template-columns: 1fr; }
  .scu-add-action { width: 100%; }
  .scu-del { margin-left: 0; }
}

/* Watchlist row marker + review-queue badge. */
.wl-breach { color: var(--danger); font-weight: 800; }
.rv-breach {
  font-size: 11px; font-weight: 700; color: #fff; background: var(--danger);
  padding: 1px 8px; border-radius: 999px;
}
.rv-card.rv-breached { border-left: 4px solid var(--danger); }

/* Forensic scorecard markers (Increment 8N) — ADDITIVE, separate from the
   kill-trigger breach markers above. Reuse the verdict fail tokens so they read
   consistently with the scorecard chips; the lollapalooza variant is stronger
   (solid danger) since it is the blow-up pattern. */
.wl-forensic {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  background: var(--v-fail-bg);
  color: var(--v-fail-fg);
  border: 1px solid var(--danger);
  white-space: nowrap;
  vertical-align: middle;
}
.wl-forensic-lolla { background: var(--danger); color: #fff; border-color: var(--danger); }
.rv-forensic {
  font-size: 11px;
  font-weight: 700;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--v-fail-bg);
  color: var(--v-fail-fg);
  border: 1px solid var(--danger);
  white-space: nowrap;
}
.rv-forensic-lolla { background: var(--danger); color: #fff; border-color: var(--danger); }

/* A5 (Increment 8N): the browsable "known blow-up signatures" reference under the
   scorecard. Quiet reference styling — a learning aid, never an alarm. */
.fraud-library {
  margin-top: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: 8px 12px;
}
.fraud-summary { cursor: pointer; font-weight: 600; font-size: 13px; color: var(--text); }
.fraud-summary:hover { color: var(--accent); }
.fraud-intro { font-size: 12px; margin: 8px 0; line-height: 1.45; }
.fraud-list { margin: 8px 0 4px; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.fraud-case { font-size: 12.5px; line-height: 1.4; overflow-wrap: anywhere; }
.fraud-name { font-weight: 700; }
.fraud-src { font-size: 11px; margin-top: 6px; }

.cc-block { margin: 10px 0 4px; }
.cc-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
.cc-text { white-space: pre-wrap; overflow-wrap: anywhere; }

.rv-actions { display: flex; gap: 8px; margin-top: 12px; align-items: center; }
/* "Set next results date?" prompt after Mark reviewed (Increment 4B item 2). */
.rv-nextprompt { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; width: 100%; }
.rv-nextprompt-label { font-weight: 600; }
.rv-nextdate { width: 140px; }
.rv-nextprompt-actions { display: flex; gap: 8px; }
.rv-note { flex: 1; }
.rv-hint { margin-top: 8px; font-size: 13px; }

/* Results-season cockpit (Increment 11C): the one-line "what changed this quarter"
   summary + the "Copy results-pack" button on a Due card. Wraps the button below
   the summary on narrow screens (≤375px handled by flex-wrap). Both themes via vars. */
.rv-results-row {
  display: flex;
  gap: 8px 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  margin: 10px 0 4px;
}
.rv-whatchanged { margin: 0; font-size: 13px; flex: 1 1 60%; min-width: 0; overflow-wrap: anywhere; }
.rv-wc-label { font-weight: 600; }
.rv-pack-btn { flex: 0 0 auto; white-space: nowrap; }
.rv-pack-fallback { margin-top: 8px; }
.rv-pack-fallback .fl-ctx-text { width: 100%; }

@media (max-width: 560px) {
  .rv-actions { flex-direction: column; align-items: stretch; }
  .rv-pack-btn { flex: 1 1 100%; }
}

/* --- position & per-lot P&L (Module 5) --- */
.btn-small { padding: 3px 8px; font-size: 12px; }
.pnl-up { color: var(--ok); }
.pnl-down { color: var(--danger); }
.pnl-flat { color: var(--muted); }

.pos-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 12px;
  margin: 4px 0 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.pos-stat { display: flex; flex-direction: column; gap: 2px; }
.pos-stat-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; }
.pos-stat-value { font-size: 15px; font-weight: 600; }
.pos-stat-value.pos-hint { font-size: 12px; font-weight: 400; color: var(--muted); font-style: italic; }

.pos-note-copy { font-size: 12px; margin: 0 0 10px; }

.pos-add {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 14px;
}
.pos-add .pos-type { width: auto; }
.pos-add .pos-date { width: 120px; }
.pos-add .pos-qty, .pos-add .pos-price { width: 100px; }
.pos-add .pos-note { flex: 1; min-width: 140px; }

.pos-tx-list { list-style: none; margin: 0 0 14px; padding: 0; }
.pos-tx {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.pos-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  letter-spacing: 0.4px;
}
.pos-badge-buy { background: #dde7f7; color: #1a3f7a; }
.pos-badge-sell { background: #f6e0d6; color: #8a3b13; }
.pos-badge-dividend { background: #dcf0e3; color: #1b6e3c; }
@media (prefers-color-scheme: dark) {
  .pos-badge-buy { background: #1a2f4d; color: #8fb6ef; }
  .pos-badge-sell { background: #4a2a17; color: #f0a878; }
  .pos-badge-dividend { background: #163a26; color: #6fd89a; }
}
.pos-add .pos-amount { width: 120px; }
.pos-tx-date { font-variant-numeric: tabular-nums; }
.pos-tx-qp { font-weight: 600; }
.pos-tx-note { flex: 1; }
.pos-del { margin-left: auto; }

.pos-lots-title { font-size: 13px; margin: 8px 0 6px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.pos-lots {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
}
.pos-lots th, .pos-lots td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}
.pos-lots th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.pos-lots tr:last-child td { border-bottom: none; }
.pos-lot-dim td { opacity: 0.55; }

@media (max-width: 560px) {
  .pos-add { flex-direction: column; align-items: stretch; }
  .pos-add .pos-type, .pos-add .pos-date, .pos-add .pos-qty, .pos-add .pos-price, .pos-add .pos-amount, .pos-add .pos-note { width: 100%; }
}

/* --- recent quarters (increment 4C) --- */
.quarters { margin-top: 4px; }
.quarters-note { margin: 0 0 8px; font-size: 13px; }
.quarters-empty { margin: 4px 0; }
.quarters-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
}
.quarters-table th, .quarters-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}
.quarters-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.quarters-table th:not(:first-child), .quarters-table td.q-num { text-align: right; }
.quarters-table tr:last-child td { border-bottom: none; }
.q-period { font-weight: 600; white-space: nowrap; }
.q-num { font-variant-numeric: tabular-nums; }
.q-row-latest td { background: var(--surface-2); font-weight: 600; }

/* --- portfolio aggregate view (increment 4C) --- */
.portfolio { max-width: 100%; }
/* Totals strip = the same stat-card treatment as the per-company position
   summary (.pos-summary), so Portfolio and a company's Money block read alike. */
.pf-totals {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 12px;
  margin: 12px 0;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
/* Annualized-return (XIRR) card (increment 8I) — same stat-card treatment as the
   totals strip, but stacked with a caption + compare lines. Wraps cleanly at 375px. */
.pf-xirr {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px;
  margin: 0 0 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.pf-xirr .pos-stat-value { font-size: 22px; }
.pf-xirr-cap { margin: 0; font-size: 12px; }
.pf-xirr-cmp { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.pf-xirr-cmp b { color: var(--text); font-weight: 600; }
/* Inflation-adjusted (real) return line (increment 8O) — a quiet fact under the
   caption; the real % keeps its pnl tone, the rest is muted. */
.pf-xirr-real { margin: 1px 0 0; font-size: 13px; color: var(--muted); }
.pf-xirr-real b { font-weight: 700; }

/* --- Goal / target-corpus card (increment 8O) --- */
/* Same stat-card treatment as the XIRR card + totals strip; a progress bar plus a
   few computed lines. Honest scope caption always shown. Wraps cleanly at 375px. */
.pf-goal {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px;
  margin: 0 0 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.pf-goal-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--text); }
.pf-goal-bar {
  width: 100%;
  height: 10px;
  margin: 4px 0 2px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
}
.pf-goal-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.3s ease;
}
.pf-goal-fill.is-reached { background: var(--ok); }
.pf-goal-line { margin: 0; font-size: 14px; color: var(--muted); }
.pf-goal-line b { color: var(--text); font-weight: 700; }
.pf-goal-detail { margin: 0; font-size: 13px; color: var(--muted); }
.pf-goal-detail b { color: var(--text); font-weight: 700; }
.pf-goal-track { margin: 0; font-size: 13px; font-weight: 600; }
.pf-goal-scope { margin: 2px 0 0; font-size: 12px; font-style: italic; }

.pf-partial { margin: 0 0 10px; }
.pf-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
}
.pf-table th, .pf-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
}
.pf-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.pf-table th:not(:first-child), .pf-table td.pf-num { text-align: right; }
.pf-table tr:last-child td { border-bottom: none; }
.pf-num { font-variant-numeric: tabular-nums; }
.pf-weight { font-weight: 600; }
.pf-name a { text-decoration: none; }
.pf-name-full { font-weight: 400; }
.pf-hint { color: var(--muted); font-style: italic; }
.pf-row-exited td { opacity: 0.55; }
.pf-note { margin-top: 10px; }

/* --- portfolio allocation & concentration (Increment 8L, B3 + F2) --- */
/* A calm, review-toned block: the stacked allocation bar, a sector mini-list, and
   the concentrationRead reflections. Same bg-card treatment as the totals strip. */
.pf-alloc {
  margin: 0 0 12px;
  padding: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.pf-alloc-title { margin: 0 0 8px; font-size: 14px; font-weight: 700; color: var(--text); }
.pf-alloc-bar { width: 100%; }
.pf-alloc-bar .weight-bars { width: 100%; height: auto; display: block; }
.pf-alloc-sectors { margin: 8px 0 0; font-size: 13px; }
.pf-alloc-notes { margin: 8px 0 0; padding-left: 18px; list-style: disc; }
.pf-alloc-notes li { margin: 2px 0; font-size: 13px; color: var(--muted); line-height: 1.4; }

/* --- net worth & allocation (Increment 8V, Theme D — D6) --- */
/* The whole-wealth lens: an equity + non-equity allocation bar, a net-worth
   headline, the equity-share line + honest caveat, and the asset manager. Same
   bordered surface-card family as the goal/alloc blocks so it reads consistently. */
.pf-nw {
  margin: 0 0 12px;
  padding: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.pf-nw-title { margin: 0 0 8px; font-size: 14px; font-weight: 700; color: var(--text); }
.pf-nw-headline { margin: 0 0 8px; font-size: 15px; color: var(--muted); }
.pf-nw-headline b { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }
.pf-nw-bar { width: 100%; }
.pf-nw-bar .weight-bars { width: 100%; height: auto; display: block; }
.pf-nw-equity { margin: 8px 0 0; font-size: 14px; color: var(--muted); }
.pf-nw-equity b { color: var(--text); font-weight: 700; }
.pf-nw-caveat { margin: 6px 0 0; font-size: 12px; line-height: 1.4; }
.pf-nw-empty { margin: 10px 0 0; font-size: 13px; line-height: 1.4; }

/* Asset list: kind · label ......... value  [Delete] */
.pf-nw-list { margin: 10px 0 0; padding: 0; list-style: none; }
.pf-nw-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
}
.pf-nw-item:last-child { border-bottom: none; }
.pf-nw-item-kind { font-weight: 600; color: var(--text); font-size: 14px; }
.pf-nw-item-label { font-size: 13px; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-nw-item-val { font-variant-numeric: tabular-nums; font-size: 14px; color: var(--text); margin-left: auto; }
.pf-nw-del { flex: 0 0 auto; }

/* Add form: type / label / value / button — wraps on narrow screens. */
.pf-nw-add {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.pf-nw-add .field { margin: 0; }
.pf-nw-kind, .pf-nw-value { min-width: 120px; }
.pf-nw-label { min-width: 160px; }
.pf-nw-add-action { display: flex; align-items: flex-end; }
@media (max-width: 375px) {
  .pf-nw-add { gap: 8px; }
  .pf-nw-add .field { flex: 1 1 100%; }
  .pf-nw-add-action { flex: 1 1 100%; }
  .pf-nw-add-action .btn { width: 100%; }
}

/* --- FY realized-gains report (Increment 6C) --- */
/* Styled like the company-page group <details> (Increment 6D D3): a bordered
   surface card with a clickable summary, so collapsibles read consistently. */
.fy-report {
  margin-top: 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.fy-summary { font-size: 15px; font-weight: 700; color: var(--text); cursor: pointer; padding: 13px 16px; list-style: none; display: flex; align-items: center; gap: 8px; }
.fy-summary::-webkit-details-marker { display: none; }
.fy-summary::before { content: '\25B8'; color: var(--muted); font-size: 12px; }
.fy-report[open] > .fy-summary::before { content: '\25BE'; }
.fy-report > .table-scroll { margin: 0 16px; }
.fy-report > .fy-foot { margin: 8px 16px 14px; }
.fy-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
  margin-top: 6px;
}
.fy-table th, .fy-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
}
.fy-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.fy-table th:not(:first-child), .fy-table td.fy-num { text-align: right; }
.fy-num { font-variant-numeric: tabular-nums; }
.fy-label { font-weight: 600; white-space: nowrap; }
.fy-total td { border-top: 2px solid var(--border); font-weight: 700; border-bottom: none; }
.fy-foot { margin-top: 8px; font-size: 12px; }
/* Download-CSV action row (Increment 8Q, E3). Left-aligned under the FY table. */
.fy-actions { margin: 10px 16px 0; display: flex; flex-wrap: wrap; gap: 8px; }

/* --- first-run onboarding welcome card (Increment 8Q, E4) --- */
/* Quiet card family (surface-2 + accent left border), matching help/temperament. */
.welcome-card {
  margin: 4px 0 14px;
  padding: 14px 16px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.welcome-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.welcome-title { font-size: 15px; font-weight: 700; color: var(--text); }
.welcome-dismiss {
  font-size: 13px;
  padding: 5px 12px;
  min-height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.welcome-intro { margin: 6px 0 12px; font-size: 13px; }
.welcome-steps { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 12px; }
.welcome-step { display: flex; gap: 12px; align-items: flex-start; }
.welcome-step-n {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.welcome-step-body { display: flex; flex-direction: column; gap: 4px; }
.welcome-step-title { font-weight: 600; color: var(--text); font-size: 14px; }
.welcome-step-body p { margin: 0; font-size: 13px; }
.welcome-step-line { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13px; }
.welcome-btn { min-height: 34px; }

/* --- filings & chat-with-filing (Modules 3 & 4) --- */
.filings { margin-top: 4px; }
/* Section head: title on the left, the "Copy context" button on the right.
   Wraps onto two lines on narrow screens so the button never overflows. */
.fl-section-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.fl-add {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 10px 0 14px;
}
.fl-add .fl-in-date { width: 120px; }
.fl-add .fl-in-title { flex: 1 1 180px; }
.fl-add .fl-in-url { flex: 1 1 160px; }
.fl-add .fl-in-takeaway { flex: 2 1 220px; }

.fl-list { display: flex; flex-direction: column; gap: 12px; }
.fl-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
}
.fl-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.fl-title-wrap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.fl-date { font-variant-numeric: tabular-nums; font-size: 13px; }
.fl-title { font-weight: 600; }
.fl-del { margin-left: auto; }
.fl-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 6px;
  font-size: 13px;
}
.fl-src { color: var(--accent); text-decoration: none; }
.fl-src:hover { text-decoration: underline; }
.fl-takeaway { flex: 1; }

.fl-analysis {
  margin-top: 10px;
  border-top: 1px solid var(--border);
  padding-top: 10px;
}
.fl-analysis-cap {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-bottom: 6px;
}
.fl-analysis-body {
  white-space: pre-wrap;
  word-wrap: break-word;
  font-size: 14px;
  line-height: 1.5;
  max-height: 420px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px;
}
/* Analysis -> journal takeaway control (Increment 4B item 3). */
.fl-analysis-actions { margin-top: 8px; }
.fl-take-panel { margin-top: 8px; }
.fl-take-text { width: 100%; }
.fl-take-actions { margin-top: 6px; }

.fl-analyze-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
/* "Paste analysis" sits beside "Analyze with Claude" as an equally-visible route. */
.fl-paste-toggle { margin-left: 0; }
.fl-offline { font-size: 13px; }
.fl-panel { margin-top: 10px; }
.fl-paste { width: 100%; resize: vertical; }
.fl-panel-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.fl-panel-hint { flex: 1; font-size: 12px; }
/* Busy spinner while an analysis is running. */
.fl-panel.is-busy { position: relative; opacity: 0.85; }
.fl-run:disabled { cursor: progress; }
.fl-run:disabled::before {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 6px;
  vertical-align: -1px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: fl-spin 0.7s linear infinite;
}
@keyframes fl-spin { to { transform: rotate(360deg); } }

@media (max-width: 560px) {
  .fl-add { flex-direction: column; align-items: stretch; }
  .fl-add .fl-in-date, .fl-add .fl-in-title, .fl-add .fl-in-url, .fl-add .fl-in-takeaway { width: 100%; }
}

/* --- settings (#/settings) --- */
.settings { max-width: 640px; }
.settings-key-row { display: flex; gap: 8px; align-items: center; }
.settings-key-row #s-key { flex: 1; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.settings-note { font-size: 13px; }

/* --- research-stage tracker (increment 6B) --- */
.stage-tracker { margin: 8px 0 4px; }
.stage-strip { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.stage-seg {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--surface);
  white-space: nowrap;
}
.stage-seg.stage-done {
  color: var(--accent-text);
  background: var(--ok);
  border-color: var(--ok);
}
.stage-hint { margin-top: 6px; font-size: 13px; }
.cell-stages { letter-spacing: 2px; color: var(--accent); white-space: nowrap; }

/* --- research checklists (increment 6B) --- */
.checklists { margin-top: 8px; }
.cl-intro { font-size: 13px; margin: 2px 0 10px; }
.cl-block {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: 8px;
}
.cl-summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
.cl-summary::-webkit-details-marker { display: none; }
.cl-summary::before { content: '▸'; margin-right: 6px; color: var(--muted); }
.cl-block[open] .cl-summary::before { content: '▾'; }
.cl-head-count { font-weight: 400; font-size: 13px; }
.cl-items { padding: 4px 8px 10px; display: flex; flex-direction: column; gap: 4px; }
.cl-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  font: inherit;
  line-height: 1.35;
}
.cl-item:hover { border-color: var(--accent); }
.cl-mark {
  flex: 0 0 auto;
  width: 18px;
  text-align: center;
  font-weight: 700;
}
.cl-item.cl-yes { border-color: var(--ok); }
.cl-item.cl-yes .cl-mark { color: var(--ok); }
.cl-item.cl-no { border-color: var(--danger); }
.cl-item.cl-no .cl-mark, .cl-item.cl-no .cl-text { color: var(--danger); }
.cl-item.cl-unset .cl-mark { color: var(--muted); }
.cl-red-note {
  color: var(--danger);
  font-size: 13px;
  margin: 4px 0 0;
}

/* --- Thesis-Formed pre-flight modal (increment 6B) --- */
.pf-list { list-style: none; margin: 10px 0; padding: 0; }
.pf-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.pf-row:last-child { border-bottom: none; }
.pf-label { color: var(--text); }
.pf-yes { color: var(--ok); font-weight: 700; }
.pf-no { color: var(--muted); font-weight: 700; }
.pf-count { font-weight: 600; }
.pf-count-red { color: var(--danger); }

/* --- Coffee-Can suggested tripwires (increment 6B) --- */
.kt-suggest {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 12px;
  margin: 8px 0;
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  background: var(--bg);
}
.kt-suggest-txt { font-size: 13px; }

/* KB-standard tripwire chips (increment prefill/B) — a quiet one-tap offer row under
   the add-form. Theme-driven colours only (both themes inherit via the vars). */
.kt-kb {
  margin: 8px 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kt-kb-txt { font-size: 12px; }
.kt-kb-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.kt-kb-chip { font-size: 12px; }

/* Sovrenn FACTS ownership prefill offer (increment prefill/A) — one quiet line above
   the manual add-form. Mirrors .kt-suggest's dashed-accent quiet-offer look. */
.own-prefill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 12px;
  margin: 8px 0;
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  background: var(--bg);
}
.own-prefill-txt { font-size: 13px; }

/* =============================================================================
   Company page: verdict header card + grouped collapsible sections + sticky nav
   (Increment 6D — structure/style only). The outer .detail becomes a transparent
   container so the header card and each group read as their own surface.
   ============================================================================= */
.detail {
  background: transparent;
  border: none;
  padding: 0;
  box-shadow: none;
}

/* --- verdict header card --- */
.verdict-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 12px;
  box-shadow: var(--shadow);
}
.vc-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.vc-titlerow { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.vc-title { font-size: 20px; margin: 0; line-height: 1.3; }
/* One-company live price refresh (⟳). Only rendered when a proxy URL is configured
   and the company resolves to a quote symbol, so it is absent by default. */
.vc-refresh { flex-shrink: 0; line-height: 1; padding: 4px 9px; font-size: 15px; }
.vc-refresh[disabled] { opacity: 0.6; cursor: default; }
.vc-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.vc-back { flex-shrink: 0; }
.vc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 10px; }
.vc-price { display: inline-flex; align-items: baseline; gap: 8px; }
.vc-price-val { font-weight: 700; font-variant-numeric: tabular-nums; font-size: 16px; }
/* Inside the card the stage tracker sits flush under the badges. */
.verdict-card .stage-tracker { margin: 10px 0 0; }

/* --- sticky in-page pill nav --- */
.pg-nav {
  position: sticky;
  top: 48px; /* clears the sticky app-header */
  z-index: 5;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 8px 0;
  margin-bottom: 12px;
  background: var(--bg);
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.pg-nav-pill {
  flex: 0 0 auto;
  width: auto;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.pg-nav-pill:hover { border-color: var(--accent); color: var(--accent); }

/* --- collapsible group --- */
.pg-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 12px;
  box-shadow: var(--shadow);
  scroll-margin-top: 96px; /* so a nav jump doesn't hide under header + nav */
}
.pg-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 16px;
  cursor: pointer;
  list-style: none;
  font-weight: 700;
}
.pg-summary::-webkit-details-marker { display: none; }
.pg-summary::before { content: '\25B8'; color: var(--muted); font-size: 12px; }
.pg-group[open] > .pg-summary::before { content: '\25BE'; }
.pg-summary:hover { color: var(--accent); }
.pg-summary-title { font-size: 15px; }
.pg-body { padding: 4px 16px 16px; border-top: 1px solid var(--border); }
.pg-body > h3:first-child { margin-top: 12px; }

/* --- wide-table overflow container (Increment 6D D2/D4) ----------------------
   Every wide table (watchlist, scorecard, quarters, valuation, portfolio, FY,
   open lots) is wrapped so it scrolls horizontally on narrow screens instead of
   forcing the whole page wider. min-width kicks in only below ~560px viewport. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll > table { min-width: 540px; }

/* --- subtle zebra on plain data tables (skip the semantically-coloured
   scorecard/valuation and the latest-quarter-highlighted quarters table). A
   neutral overlay so it reads the same in light and dark. --- */
.watchlist tbody tr:nth-child(even) td,
.pf-table tbody tr:nth-child(even) td,
.fy-table tbody tr:nth-child(even) td,
.pos-lots tbody tr:nth-child(even) td { background: rgba(127, 127, 127, 0.045); }

/* --- narrow-screen header wrap --------------------------------------------
   The app header is a single flex row: brand + nav (Portfolio/Review/Settings)
   + action buttons (Export/Import/?). Its content needs ~558px; below that the
   row can't fit and the action buttons were overflowing the right edge, forcing
   the WHOLE page to scroll sideways (~183px at 375px). Let the header wrap so
   brand + actions stay on row one (justify-content:space-between keeps them at
   opposite ends) and the nav drops to a full-width second row. This block must
   come AFTER the base .app-header and .pg-nav rules so its overrides win the
   equal-specificity tie. Placed here (≤560, matching the grid breakpoints)
   because that is the width at which the header stops fitting — well before the
   ≤480 phone-ergonomics tweaks below. */
@media (max-width: 560px) {
  .app-header { flex-wrap: wrap; }
  .header-nav { order: 3; flex-basis: 100%; margin: 2px 0 0 0; }
  /* The wrapped header is ~107px tall (vs ~61px on one row), so the sticky
     in-page pill nav must stick lower to clear it (base rule is top:48px for the
     one-row header). 100px leaves the same small seamless tuck under the header
     border that the one-row layout has. */
  .pg-nav { top: 100px; }
}

/* =============================================================================
   Phone ergonomics (Increment 6D D4) — ≤480px. Header card wraps, the sticky
   pill nav scrolls horizontally (already overflow-x:auto), wide tables keep their
   scroll, and every tap target (buttons, nav pills, checklist three-way toggles,
   collapsible summaries) is at least 40px tall. Inputs are already full-width.
   ============================================================================= */
@media (max-width: 480px) {
  /* Header card: title/badges wrap, the back button drops to its own line. */
  .vc-top { flex-wrap: wrap; }
  .vc-title { font-size: 18px; }
  .vc-back { margin-top: 6px; }

  /* Comfortable touch targets. inline-flex + align-items:center already centre
     the label, so a min-height just grows the hit area. */
  .btn { min-height: 40px; }
  .pg-nav-pill { min-height: 40px; }
  .cl-item { min-height: 40px; align-items: center; }
  .pg-summary, .fy-summary { padding-top: 15px; padding-bottom: 15px; }

  /* Give the horizontal nav a touch more breathing room while it scrolls. */
  .pg-nav { gap: 6px; }
  .pg-nav-pill { padding: 9px 14px; }

  /* Full-width primary actions so Save/Add are easy to hit. */
  .form-actions .btn { width: 100%; justify-content: center; }
}

/* ---- Guided walkthroughs (Increment 7A) ------------------------------------
   Coach-mark overlay + popover, the auto-offer toast, and the header "?" menu.
   All colours use the existing theme tokens so light + dark both work; the tour
   layer sits above every other z-index in the app (header 10, banners 20-30). */
.tour-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 2000;
}
body.tour-lock { overflow: hidden; }

/* The anchored element pokes above the dim (both live in the root stacking
   context — .view creates none) and gets a bright ring. pointer-events off so a
   click lands on the blocking overlay, never on the live control mid-tour. */
.tour-highlight {
  position: relative;
  z-index: 2001;
  pointer-events: none;
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius);
  box-shadow: 0 0 0 6px rgba(76, 155, 232, 0.3);
}

.tour-popover {
  position: fixed;
  z-index: 2002;
  width: 340px;
  max-width: 92vw;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
  padding: 14px 16px;
}
.tour-popover-center {
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
}
.tour-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.tour-title { font-weight: 700; font-size: 15px; }
.tour-skip { flex-shrink: 0; }
.tour-body { margin: 10px 0 14px; font-size: 14px; line-height: 1.5; }
.tour-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tour-count { font-size: 12px; }
.tour-btns { display: flex; gap: 8px; }
.tour-btns .btn { min-height: 40px; }

/* Auto-offer toast — bottom-centre, non-blocking (never the full overlay). */
.tour-offer {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  z-index: 2003;
  max-width: 92vw;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
}
.tour-offer-text { font-size: 14px; }
.tour-offer-btns { display: flex; gap: 8px; flex-shrink: 0; }

/* Header "?" relaunch menu. */
.btn-help { font-weight: 700; }
.tour-menu {
  position: fixed;
  z-index: 2003;
  width: 300px;
  max-width: 92vw;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.tour-menu-head { font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); }
.tour-menu-item { justify-content: center; min-height: 40px; }
.tour-menu-note { font-size: 13px; line-height: 1.45; margin: 0; }

@media (max-width: 480px) {
  .tour-offer { flex-direction: column; align-items: stretch; }
  .tour-offer-btns { justify-content: flex-end; }
}

/* ---- Inline section help (Increment 7B) -----------------------------------
   A small round "?" flexed into a section header, and a quiet collapsible
   banner beneath it. No transform/z-index here: the tour highlight relies on
   data-tour ancestors creating NO stacking context (7A watch item). */

/* Header line carrying a trailing "?". The header text keeps its own styling;
   the "?" is pushed to the end and the row stays baseline-aligned. */
.help-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.help-head-text { flex: 0 1 auto; }

/* The "?" toggle. Round, quiet, ≥40px touch target via padding even though the
   glyph is small. Sits at the end of the header line (margin-left:auto). */
.help-toggle {
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 9px; /* extends the hit area past the 22px glyph toward 40px */
  box-sizing: content-box;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
}
.help-toggle:hover { border-color: var(--accent); color: var(--accent); }
.help-toggle[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent-text);
  background: var(--accent);
}

/* The banner: hidden until opened. Muted background, thin left accent border,
   small text — deliberately quiet so it never shouts over the content. */
.help-banner {
  display: none;
  margin: 4px 0 10px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  transition: background 0.12s ease;
}
.help-banner-open { display: block; }
.help-banner-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.help-banner-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}
.help-banner-body {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}
.help-dismiss {
  flex: 0 0 auto;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  min-width: 40px;
  min-height: 24px;
  cursor: pointer;
}
.help-dismiss:hover { color: var(--accent); }

/* Temperament nudge (Increment 8G) — a quiet, dismissible reflection surfaced above
   the transaction list after a buy/sell. Reflection, NOT a warning: it reuses the
   calm surface-2 + accent-left-border family (like the help banner), never the
   red/danger scorecard treatment. Session-only; blocks nothing. */
.temperament-nudge {
  margin: 4px 0 12px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.tn-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.tn-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
}
.tn-dismiss {
  flex: 0 0 auto;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  min-width: 40px;
  min-height: 24px;
  cursor: pointer;
}
.tn-dismiss:hover { color: var(--accent); }
.tn-quote {
  margin: 6px 0 0;
  padding: 0;
  border: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}
.tn-quote-text { font-style: italic; font-size: 14px; color: var(--text); }
.tn-attr { font-size: 12px; color: var(--muted); white-space: nowrap; }
.tn-note {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}

/* Position-sizing preview (Increment 8P) — a live, pre-commit concentration
   projection under the buy inputs. Quiet REVIEW tone (calm surface-2 + accent
   left border, like the temperament nudge), NEVER an alarm or a block. The
   reflection sits beneath the factual line, muted. Both themes via vars; wraps
   at 375px. */
.sizing-preview {
  margin: 6px 0 4px;
  padding: 9px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.sizing-line {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
}
.sizing-line strong { font-weight: 700; }
.sizing-reflection {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
}

@media (max-width: 375px) {
  .sizing-preview { padding: 8px 10px; }
  .sizing-line, .sizing-reflection { font-size: 12.5px; }
}

/* ---- Increment 8T: discipline reflections (surface-not-enforce) --------------
   All reuse the QUIET review family (calm surface-2 + accent left border), NEVER
   an alarm. Both themes via vars; wrap at 375px. */

/* Three-Year-Rule reflection after selling a young holding (F5). Reuses .tn-head /
   .tn-label / .tn-dismiss from the temperament nudge. */
.three-year-note {
  margin: 4px 0 12px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.tyn-body {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}

/* Circle-of-competence note on the company page (F3): the company's sector sits
   outside your defined circle. A reflection, not a warning. */
.circle-note {
  margin: 8px 0 4px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.cn-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
}
.cn-body {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
}
.cn-body strong { font-weight: 700; }

/* Portfolio do-nothing / zero-churn line (F5) — a calm muted sentence. */
.pf-churn {
  margin: 8px 0 0;
  padding: 9px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  line-height: 1.5;
}

/* Opportunity-cost line inside the pre-flight modal (F3). */
.pf-oppcost {
  margin: 10px 0 0;
  padding: 9px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 13px;
  line-height: 1.5;
}
.pf-oppcost strong { font-weight: 700; color: var(--text); }

@media (max-width: 375px) {
  .three-year-note, .circle-note, .pf-churn, .pf-oppcost { padding: 8px 10px; }
  .tyn-body, .cn-body, .pf-oppcost { font-size: 12.5px; }
}

/* Route headers (Watchlist / Portfolio / Review): group the h2 + "?" so the
   "?" hugs the title while the action button stays right-aligned. */
.view-head-title { display: flex; align-items: center; gap: 8px; }
.view-head-title .help-toggle { margin-left: 0; }

@media (max-width: 480px) {
  .help-toggle { padding: 10px; }
}

/* --- Decisions journal (Increment 8U) --- */
/* Calibration strip: a neutral, factual scorecard line. Quiet surface card,
   segments separated by a middot; reuses the app's win/loss tones only in the
   table below (the strip itself stays neutral — no green/red on the summary). */
.dj-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  padding: 12px 14px;
  margin: 4px 0 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--text);
}
.dj-seg { position: relative; }
.dj-seg + .dj-seg::before {
  content: "·";
  color: var(--muted);
  margin-right: 12px;
}
.dj-seg-lead { font-weight: 600; }

.dj-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: 14px;
}
.dj-table th, .dj-table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.dj-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted); white-space: nowrap; }
.dj-table th.dj-num, .dj-table td.dj-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dj-table th.dj-kill, .dj-table td.dj-kill { text-align: center; }
.dj-table tbody tr:last-child td { border-bottom: none; }
.dj-row { cursor: pointer; }
.dj-row:hover, .dj-row:focus-visible { background: rgba(127, 127, 127, 0.08); outline: none; }
.dj-tk { display: flex; flex-direction: column; gap: 1px; }
.dj-ticker { font-weight: 600; font-variant-numeric: tabular-nums; }
.dj-name { font-size: 12px; }
.dj-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid currentColor;
}
.dj-thesis, .dj-lesson { display: inline-block; max-width: 260px; }
.dj-note { margin-top: 10px; font-size: 12px; }

/* ---- Sovrenn shortlist ingestion (Increment 9A) ------------------------------
   A read-only provenance panel from the separate company.sovrenn namespace. Reuses
   the calm surface-2 + accent-border family (like .own-block / help banner). Verdict
   tones reuse the valuation-verdict pass/warn tokens; nulls render muted ("unknown").
*/
.sov-block {
  margin: 8px 0 4px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
}
.sov-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-bottom: 6px; }
.sov-title { margin: 0; font-size: 14px; }
.sov-provenance {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--muted);
}
.sov-score { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.sov-subhead {
  margin: 12px 0 6px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--muted);
}
/* Verdict badge — pill, verdict-toned. shortlist = pass, watch = warn, unknown = muted. */
.sov-verdict {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 700; text-transform: capitalize;
}
.sov-verdict-shortlist { background: var(--v-pass-bg); color: var(--v-pass-fg); }
.sov-verdict-watch { background: var(--v-warn-bg); color: var(--v-warn-fg); }
.sov-verdict-unknown { background: var(--surface-2); color: var(--muted); border: 1px solid var(--border); }
/* Criteria checklist — one row per criterion; the value glyph is tone-classed. */
.sov-criteria { display: grid; grid-template-columns: 1fr auto; gap: 2px 12px; }
.sov-crit-row { display: contents; }
.sov-crit-label { font-size: 13px; padding: 3px 0; }
.sov-crit-yes, .sov-crit-no, .sov-crit-unknown, .sov-crit-enum {
  font-size: 13px; padding: 3px 0; text-align: right; font-weight: 600;
}
.sov-crit-yes { color: var(--v-pass-fg); }
.sov-crit-no { color: var(--v-fail-fg); }
.sov-crit-unknown { color: var(--muted); }
.sov-crit-enum { color: var(--text); font-weight: 500; }
/* Snapshot metrics — label over value; null values render "unknown" in muted. */
.sov-metrics { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.sov-metric { display: flex; flex-direction: column; min-width: 84px; }
.sov-metric-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; color: var(--muted); }
.sov-metric-val { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.sov-metric-val.sov-unknown { font-weight: 500; color: var(--muted); font-style: italic; }
.sov-asof { font-size: 12px; margin: 6px 0 0; }
/* Pipeline timeline — date · type · summary, one row each. */
.sov-timeline { list-style: none; margin: 0; padding: 0; }
.sov-tl-item {
  display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline;
  padding: 5px 0; border-bottom: 1px solid var(--border);
}
.sov-tl-item:last-child { border-bottom: none; }
.sov-tl-date { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; min-width: 84px; }
.sov-tl-type {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px;
  color: var(--accent); font-weight: 700;
}
.sov-tl-summary { font-size: 13px; flex: 1 1 160px; }
.sov-coverage { font-size: 12px; margin: 8px 0 0; }
.sov-notes { font-size: 13px; margin: 8px 0 0; }
.sov-disclaimer { font-size: 11px; margin: 8px 0 0; font-style: italic; }
/* Watchlist "Sovrenn" tag — a quiet accent pill next to the company name. */
.sov-tag {
  display: inline-block; padding: 1px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px;
  background: var(--surface-2); color: var(--accent); border: 1px solid var(--border);
  vertical-align: middle;
}
/* Import-report modal list of failed records. */
.sov-report-summary { font-weight: 600; margin: 4px 0 8px; }
.sov-report-failed { margin: 4px 0 8px; padding-left: 18px; font-size: 13px; }
.sov-report-failed li { margin: 2px 0; }
/* Bulk Screener-import report modal (increment 11J). Inherits .modal for the
   container, theme vars, and 375px width; these just size the summary + lists. */
.bulk-report-summary { font-weight: 600; margin: 4px 0 8px; }
.bulk-report-imported,
.bulk-report-unmatched,
.bulk-report-ambiguous,
.bulk-report-errors { margin: 4px 0 8px; padding-left: 18px; font-size: 13px; }
.bulk-report-imported li,
.bulk-report-unmatched li,
.bulk-report-ambiguous li,
.bulk-report-errors li { margin: 2px 0; word-break: break-word; }

/* =============================================================================
   DESIGN PASS (branch fable/design-pass) — D1..D6
   ---------------------------------------------------------------------------
   CSS ONLY. No markup changed, no behaviour changed. This block is appended LAST
   so it wins equal-specificity ties with the rules above; every colour comes from
   the existing theme custom properties, so light and dark both hold.

   Measured causes this fixes (1280px viewport, watchlist view):
     - .view was max-width:900px -> 380px of a 1280px screen sat empty while the
       9-column table was crammed into 868px.                            (D1)
     - The status cell (94px) could not fit badge + tripwire ⚠ + forensic chip
       side by side, so they stacked — the "mushed icons".               (D2)
     - td / .cell-ticker / .muted / .wl-price were ALL 15px: no hierarchy. (D3)
     - Company 179px wrapped long legal names to 2-3 lines (63px rows);
       "Next key date" (66px) was narrower than its own header.          (D4)
   ============================================================================= */

/* --- shared scale tokens (theme-independent; no colour here) ----------------
   --space-* names the 4/8/12/20/32 rhythm this stylesheet already uses by hand,
   so future spacing has one scale to pick from instead of a new one-off value. */
:root {
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;   /* == --gap */
  --space-4: 20px;
  --space-5: 32px;
  /* Data-dense views (tables). Scales with the screen instead of stopping dead at a
     fixed width: on a ~2000px monitor a hard 1360px cap left ~320px of empty gutter
     on each side while the table itself was still crowded. The 1760px ceiling keeps
     an ultrawide from stretching rows into unreadable tracking. */
  --shell-wide: min(96vw, 1760px);
  --measure: 72ch;       /* comfortable reading measure for body copy */
  --chip-h: 20px;        /* one chip height for every pill in the app */
}

/* --- D1: let wide screens breathe -----------------------------------------
   The shell keeps its 900px reading width by default (prose surfaces: company
   detail, review, decisions, settings). Only the DATA-DENSE views opt into the
   wide shell, matched on what they actually contain — no new markup. If :has()
   is unsupported the rule is simply dropped and the old 900px shell stands.
   Gutters scale with the viewport instead of being a flat 16px, so the table
   never touches the screen edge on a large monitor. */
.view { padding: 16px clamp(16px, 2vw, 32px); }
.view:has(table.watchlist),
.view:has(table.compare-table),
.view:has(.portfolio) { max-width: var(--shell-wide); }

/* Prose must NOT stretch with the shell. Cap the body-copy blocks at a
   65-80 character measure wherever they appear (they also sit inside the
   900px views, where 900px still ran ~100 characters per line). */
.help-banner { max-width: min(100%, 78ch); }
.help-banner-body,
.journal-text,
.cc-text,
.sov-notes,
.scu-item-note,
.fraud-intro,
.inbox-label,
.field-hint,
.rv-whatchanged { max-width: var(--measure); }
/* (.wl-sovrenn-caveat keeps its own, deliberately tighter, 60ch cap above.) */

/* --- D2: un-mush the chips -------------------------------------------------
   One consistent pill: same height, same padding, same radius, optically
   centred against the text beside it. */
.badge,
.wl-forensic,
.sov-tag,
.asof-chip,
.rv-breach,
.rv-forensic,
.cmp-forensic,
.deep-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--chip-h);
  padding: 0 8px;
  border-radius: 999px;
  white-space: nowrap;
  vertical-align: middle;
}

/* The watchlist status cell (column 4 — it carries no class in the markup):
   status badge + tripwire ⚠ + forensic chip sit on ONE baseline with a real gap
   instead of a stacked pile. The `nowrap` that FORCES one line is applied only in
   the >=1200px block below: measured, it costs the auto-layout table ~69px of
   min-content width, and between 560px and 1200px that width has to come out of
   the company column (which then wraps to 3 lines — a worse trade). Below 1200px
   the cell keeps main's wrapping behaviour, so nothing regresses there. */
.watchlist td:nth-child(4) { line-height: 1.2; }
.watchlist td:nth-child(4) > * { vertical-align: middle; }
.wl-breach {
  display: inline-flex;
  align-items: center;
  min-height: var(--chip-h);
  margin-left: 6px;
  line-height: 1;
  vertical-align: middle;
}
.watchlist td:nth-child(2) .sov-tag { margin-left: 2px; }
/* Same treatment for the compare table's status cell (column 2). */
.compare-table td:nth-child(2) > * { vertical-align: middle; }

/* --- D3: type hierarchy in the tables --------------------------------------
   Was: everything 15px. Now: ticker is the loud identifier, company name is the
   label, sector / next-date are quiet secondary data, and every number is
   tabular so the columns line up. */
.watchlist th,
.compare-table th {
  font-size: 11px;
  letter-spacing: 0.6px;
}
.watchlist td { font-size: 14px; }
.watchlist .cell-ticker,
.compare-table .cell-ticker {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.3px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  /* A company the pipeline could not resolve to an NSE symbol carries its key as the
     ticker ("ace-construction-equipment" = 207px in a 122px column). With nowrap and
     the default overflow:visible that text SPILLED OUT of the cell and collided with
     the company name beside it. Clip it here; app.js puts the full value in title=. */
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 0; /* lets the fixed-layout percentage govern, so ellipsis actually fires */
}
/* Company name: the row's label — normal weight, full 15px. */
.watchlist td:nth-child(2) { font-size: 15px; }
/* Sector + next key date: secondary, smaller (they already carry .muted). */
.watchlist td:nth-child(3),
.watchlist td:nth-child(8) { font-size: 13px; }

/* Money, percentages and dates: tabular figures + right alignment so digits
   stack. Misaligned digits are the single biggest "cheap" tell in a financial
   tool. (tabular-nums is a no-op on non-numeric text, so mixed columns are
   safe.) */
.watchlist td.wl-price,
.watchlist td.wl-buy,
.watchlist td:nth-child(8),
.pf-table td,
.fy-table td,
.pos-lots td,
.compare-table td { font-variant-numeric: tabular-nums; }
.watchlist th:nth-child(8),
.watchlist td:nth-child(8) { text-align: right; }

/* Page titles: a little more presence than the 20px flat scale. */
h2 { font-size: 22px; letter-spacing: -0.2px; }

/* --- D4: column proportions (desktop only) ---------------------------------
   Below 1200px the table keeps its auto layout (and .table-scroll keeps
   scrolling it on a phone). At >=1200px the shell is wide enough to hand every
   column a deliberate share. Percentages are chosen against the narrowest case
   the query allows — a 1200px viewport, i.e. a 1152px table:
     ticker 10% =115px | company 24% =277px | sector 14% =161px
     status 15% =173px | price   9% =104px | buy     4% = 46px
     stages  7% = 81px | next   10% =115px | trend   7% = 81px
   Each of those clears its own worst-case content ("Thesis formed" + ⚠ + "⚠ 2"
   is ~164px; the "NEXT KEY DATE" header is ~124px; the sparkline is 64px). */
@media (min-width: 1200px) {
  table.watchlist { table-layout: fixed; }
  /* No header wraps its own text, and the status chips are forced onto one line. */
  .watchlist th { white-space: nowrap; }
  .watchlist td:nth-child(4) { white-space: nowrap; }
  /* Ticker gets 13%, not 10%: real books carry unresolved slug tickers that are far
     longer than a 6-letter symbol. The 3% comes from Sector and Next-key-date, which
     are "—" for most rows in practice. */
  /* 10 columns now (a per-row ⟳ refresh joined the tail, row-refresh): the 3% it
     needs came out of Company (24→23), Sector (12→11) and Price (9→8). Sum = 100:
     13 + 23 + 11 + 15 + 9 + 4 + 7 + 8 + 7 + 3. */
  .watchlist th:nth-child(1) { width: 13%; }
  .watchlist th:nth-child(2) { width: 23%; }
  .watchlist th:nth-child(3) { width: 11%; }
  .watchlist th:nth-child(4) { width: 15%; }
  .watchlist th:nth-child(5) { width: 9%; }
  .watchlist th:nth-child(6) { width: 4%; }
  .watchlist th:nth-child(7) { width: 7%; }
  .watchlist th:nth-child(8) { width: 8%; }
  .watchlist th:nth-child(9) { width: 7%; }
  .watchlist th:nth-child(10) { width: 3%; }
  /* The narrowest columns get tighter side padding so their content fits. */
  .watchlist th.wl-buy, .watchlist td.wl-buy,
  .watchlist th.wl-trend, .watchlist td.wl-trend,
  .watchlist th.wl-refresh, .watchlist td.wl-refresh { padding-left: 6px; padding-right: 6px; }
  /* Company + sector truncate with an ellipsis instead of wrapping to 3 lines,
     which is what pushed rows to 63px tall. */
  .watchlist td:nth-child(2),
  .watchlist td:nth-child(3) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Rows settle to a single-line height. */
  .watchlist td { padding-top: 10px; padding-bottom: 10px; }
}

/* --- D5: the phone --------------------------------------------------------- */
/* The page itself must never scroll sideways: the tables scroll INSIDE
   .table-scroll, and nothing may push a wider box out of the shell. */
.table-scroll { max-width: 100%; }
.wl-table-host { min-width: 0; }

@media (max-width: 480px) {
  /* Comfortable side padding without eating the narrow screen. */
  .view { padding-left: 14px; padding-right: 14px; }
  /* Tap targets: the watchlist filter row is the densest control cluster in the
     app and its selects/chips were below the 40px the buttons already use. */
  .wl-controls .wl-search,
  .wl-controls .wl-status,
  .wl-controls .wl-sort,
  .wl-controls .wl-chip,
  .wl-sort-wrap > select { min-height: 40px; }
  .wl-controls { gap: 8px; row-gap: 8px; }
  /* Consistent vertical rhythm between the stacked sections of a detail page. */
  .action-inbox { margin-bottom: var(--space-4); }
}

/* --- D6: consistent edges + both themes -------------------------------------
   Audited rather than rewritten: every card, table and modal in this file
   already uses `1px solid var(--border)` + `border-radius: var(--radius)`
   (.record-form, .detail, .empty, .inbox-list, .pos-summary, .fraud-library,
   .modal, table.watchlist, table.compare-table), so there was nothing to
   normalise and adding duplicate rules would have been dead CSS. The one real
   inconsistency was the chips — four different heights, paddings and radii —
   which D2 above now unifies through --chip-h.

   Every declaration in this block is either a length or a var() from the
   existing token set; no colour is hardcoded, so the dark-theme :root override
   at the top of the file continues to drive both themes unchanged. */

/* --- Draft loop (draft-loop) ------------------------------------------------
   The "Draft with AI" / "Paste draft" buttons, the DOM-only fill banner, and the
   subtle .draft-filled field marker. All colours are existing tokens, so both
   themes are driven by the :root override at the top of the file. The banner
   reuses the calm surface-2 + accent-left treatment (like .premortem-nudge),
   never the red/danger family — a draft is a helper, not an alarm. */
.thesis-draft-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 10px; }
.thesis-draft-fallback { margin: 0 0 10px; }
.thesis-draft-fallback .fl-ctx-text { width: 100%; }
.thesis-draft-banner {
  margin: 0 0 12px; padding: 10px 12px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.tdb-body { font-size: 13px; }
/* Subtle accent border on a field the AI draft filled; clears on the user's first edit. */
.draft-filled { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.draft-paste-input {
  width: 100%; resize: vertical;
  border: 1px solid var(--border); border-radius: var(--radius);
}
/* draft-plus: the review step listing tap-to-accept tripwire/checklist proposals. */
.draft-review-group { margin: 0 0 16px; }
.draft-review-head { margin: 0 0 2px; font-size: 14px; }
.draft-review-hint { margin: 0 0 8px; font-size: 12px; }
.draft-review-list { display: flex; flex-direction: column; gap: 8px; }
.draft-review-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  padding: 8px 10px;
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.draft-review-txt { font-size: 13px; line-height: 1.35; }
.draft-review-row .btn { flex: 0 0 auto; }
.draft-review-allrow { margin-top: 8px; }
.draft-review-dropped {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12px;
  padding: 2px 0;
  overflow-wrap: anywhere;
}
