:root {
  --bg: #fbfbfa;
  --surface: #ffffff;
  --line: #e7e5df;
  --line-strong: #d6d3ca;
  --text: #1f1e1b;
  --muted: #6b6862;
  --faint: #9a968d;
  --accent: #1d6e56;
  --accent-bg: #e1f5ee;
  --accent-text: #0f6e56;
  --warn-bg: #faeeda;
  --warn-text: #854f0b;
  /* benchmark-relative columns: neutral slate — informational, NOT "good" (green would imply valence) */
  --rel-bg: #eef1f6;
  --rel-tint: #f5f7fa;
  --rel-text: #3c4a5c;
  --rel-line: #d5dce6;
  --hover: #f3f2ee;
  --shadow: rgba(0, 0, 0, 0.10);

  /* Spacing. The file already lives on a 2px ramp; these name the values that
     carry a rule, so a new component cannot invent a fifth card padding by
     copying an older one. */
  --pad-card: 14px 16px;   /* every bordered content card */
  /* 18, not 14: at 14 the gap between cards equalled the padding inside them,
     which makes the grouping ambiguous — you cannot tell where one card ends. */
  --gap-block: 18px;       /* between stacked cards and page blocks */
  --pad-row: 12px 16px;    /* a card inside a list of cards */
  --pad-tile: 10px 12px;   /* a small filled box inside a card */
  --gap-sm: 8px;           /* grid gutters and control rows */

  /* Fixed chrome, measured once. The topbar's height was emergent (padding +
     content + border) and six offsets were computed against a guess at it, so
     the sticky section nav tucked UNDER the bar it is meant to sit below. The
     mobile tab bar had five different clearance constants and only one of them
     accounted for the device's safe-area inset. */
  --topbar-h: 57px;
  --tabbar: 0px;           /* no tab bar above 720px */

  /* Control heights. Nine values were in use and three of them collided inside
     a single row, so a select, an input and a button side by side did not sit
     on one baseline. */
  --ctl-h: 34px;           /* the default control */
  --ctl-h-sm: 30px;        /* inside a card, a menu or a toolbar */
  color-scheme: light;
}

/* ---- Dark theme: override the token layer + the few accent tints that are
   light-on-light. Structural surfaces already use var(--surface)/var(--line). ---- */
:root[data-theme="dark"] {
  --bg: #14171a;
  --surface: #1c2024;
  --line: #2c3238;
  --line-strong: #3a424a;
  --text: #e8e6e1;
  --muted: #9aa1a8;
  --faint: #71787f;
  --accent: #3fa985;
  --accent-bg: #16352b;
  --accent-text: #6fd0ac;
  --warn-bg: #3a2c14;
  --warn-text: #e0b070;
  --rel-bg: #232a33;
  --rel-tint: #1f242b;
  --rel-text: #a9b6c6;
  --rel-line: #333d49;
  --hover: #262b30;
  --shadow: rgba(0, 0, 0, 0.55);
  color-scheme: dark;
}
:root[data-theme="dark"] .outlook.t5 { background: #16352b; color: #6fd0ac; }
:root[data-theme="dark"] .outlook.t4 { background: #26310f; color: #a7c96f; }
:root[data-theme="dark"] .outlook.t3 { background: #2a2925; color: #b3b0a8; }
:root[data-theme="dark"] .outlook.t2 { background: #3a2c14; color: #e0b070; }
:root[data-theme="dark"] .outlook.t1 { background: #3a1f1f; color: #e58585; }
:root[data-theme="dark"] .twin-callout,
:root[data-theme="dark"] .xray-overlap td,
:root[data-theme="dark"] .stat.attr-good { background: #16352b; border-color: #2c5a48; }
:root[data-theme="dark"] .stat.attr-good .v { color: #6fd0ac; }
:root[data-theme="dark"] .stat.attr-bad { background: #3a1f1f; border-color: #5a2c2c; }
:root[data-theme="dark"] .stat.attr-bad .v { color: #e58585; }
:root[data-theme="dark"] tbody tr:hover td.rel { background: #2b323c; }
:root[data-theme="dark"] .cmp-tbl td.cmp-best { background: #17362b; color: #6fd0ac; }
:root[data-theme="dark"] .neg,
:root[data-theme="dark"] tbody td.neg { color: #e58585; }
:root[data-theme="dark"] .star b { color: #d6a94a; }
:root[data-theme="dark"] a.pcard:hover { border-color: #3fa985; box-shadow: 0 2px 10px rgba(63,169,133,0.18); }
:root[data-theme="dark"] .menu-panel,
:root[data-theme="dark"] .acct-menu,
:root[data-theme="dark"] .fs-results,
:root[data-theme="dark"] .colmenu { box-shadow: 0 8px 30px var(--shadow); }
@media print { :root[data-theme="dark"] { --bg: #fff; --surface: #fff; --text: #000; } }
* { box-sizing: border-box; }

/* Square corners, everywhere.
   This was 95 border-radius declarations across 16 different values (6px, 10px,
   8px, 5px, 12px, 50%, 999px, 4px 0 0 4px …) — the kind of drift a hand-written
   stylesheet accumulates when each component picks its own. Declared once here
   instead, so a new component cannot reintroduce a curve by copying an older
   rule, and tests/test_squared_ui.py fails if one comes back. */
*, *::before, *::after { border-radius: 0; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px; line-height: 1.5;
  /* Sticky footer. A short page — an empty dashboard, a 404, a fresh account —
     used to leave the footer floating mid-screen above a band of dead space.
     The page now always fills the viewport and the footer sits on the bottom.
     dvh (with a vh fallback) so a mobile browser's collapsing URL bar does not
     leave a gap or force a scroll. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
/* the main content column takes the slack, pushing the footer down */
.wrap { flex: 1 0 auto; }
.auth-wrap { flex: 1 0 auto; }
html { scroll-behavior: smooth; }
.topbar {
  display: flex; align-items: center; gap: 10px; height: var(--topbar-h);
  /* Match .wrap's centred gutter so the topbar's content sits on the same left
     edge as the page content below it — it was a flat 20px against .wrap's
     centred max-width, so on a wide screen the header was 32px out. The footer
     already aligns because .footer-inner repeats .wrap's box. */
  padding: 12px max(20px, calc((100% - min(1600px, 95vw)) / 2 + 20px));
  border-bottom: 1px solid var(--line); background: var(--surface);
  position: sticky; top: 0; z-index: 50;
}
#screenerTop, #correlation, #portfolio { scroll-margin-top: calc(var(--topbar-h) + 12px); }
a.brand { text-decoration: none; color: inherit; }
.brand { font-weight: 600; font-size: 15px; letter-spacing: -0.01em; display: inline-flex; align-items: center; gap: 8px; }
/* The wordmark's dot belongs to the mark, not to one particular container. It was
   scoped to `.brand` only, so on the six signed-out templates (which use
   `.auth-brand`) it rendered as a detached grey full stop — the first thing every
   visitor saw. Style it wherever the wordmark appears. */
.brand .dot, .auth-brand .dot { color: var(--accent); }
.brand-mark { flex-shrink: 0;}
.brand-word { line-height: 1; }
/* gap separates the mark from the wordmark — never the word from its own dot */
.brand, .auth-brand { gap: 0; }
.brand .brand-word { margin-left: 8px; }
.auth-brand .brand-word { margin-left: 9px; }
.auth-brand { display: inline-flex; align-items: center; }
.mode-pill {
  font-size: 11px; color: var(--muted); background: var(--bg);
  border: 1px solid var(--line); padding: 4px 9px;
}
.wrap { max-width: min(1600px, 95vw); margin: 0 auto; padding: 18px 20px 60px; }

.controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.controls .spacer { flex: 1; }
select, input, button {
  font: inherit; color: var(--text); background: var(--surface);
  border: 1px solid var(--line-strong);
  padding: 7px 10px; height: var(--ctl-h);
}
select { cursor: pointer; }
button { cursor: pointer; background: var(--surface); }
button:hover { background: var(--hover); }
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
button.primary:hover { background: #18604b; }
label.fld { font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
label.fld.chk { cursor: pointer; border: 1px solid var(--line-strong); height: 34px; padding: 0 10px; }
.controls input[type="checkbox"] { height: auto; width: auto; padding: 0; margin: 0; vertical-align: -1px; }

.chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; font-size: 12px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px;
  background: var(--surface); border: 1px solid var(--line); color: var(--muted);
}
.chip.rel { background: var(--rel-bg); color: var(--rel-text); border-color: var(--rel-line); }
.chip input { height: 24px; width: 64px; padding: 2px 6px; }
.chip-x { cursor: pointer; color: var(--faint); }

.tablecard { background: var(--surface); border: 1px solid var(--line); overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
thead th {
  text-align: right; font-weight: 500; color: var(--muted); padding: 9px 10px;
  border-bottom: 1px solid var(--line-strong); white-space: nowrap; cursor: pointer; user-select: none;
}
thead th.left { text-align: left; }
thead th.rel { background: var(--rel-bg); color: var(--rel-text); }
thead th .arrow { opacity: 0.5; font-size: 10px; }
thead th.sorted .arrow { opacity: 1; }
tbody td { text-align: right; padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap; }
tbody td.left { text-align: left; }
tbody td.center { text-align: center; }
thead th.center { text-align: center; }
tbody td.rel { background: var(--rel-tint); }
tbody tr:hover td { background: var(--hover); }
tbody tr:hover td.rel { background: #e9edf3; }
.fund-id { font-weight: 600; color: var(--text); text-decoration: none; }
a.fund-id:hover { color: var(--accent-text); text-decoration: underline; }
.fund-name { font-size: 11px; color: var(--faint); }
/* Screener fund column: a viewport-relative cap so it shrinks fast on narrower
   desktops instead of hogging whitespace and pushing numeric columns off. The
   name truncates with an ellipsis; the <720px sticky-column rules are untouched. */
@media (min-width: 721px) {
  #grid th.left, #grid td.left { width: clamp(140px, 17vw, 300px); max-width: clamp(140px, 17vw, 300px); }
  #grid td.left .fund-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #grid td.left .fund-id { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
}
.lowcorr { font-weight: 600; color: var(--accent-text); }
.neg { color: #a32d2d; }
.star { display: inline-flex; align-items: center; gap: 2px; background: var(--bg);
  border: 1px solid var(--line); padding: 2px 8px; font-size: 11px; color: var(--muted); }
.star b { color: #b07a12; }
.outlook { display: inline-block; padding: 2px 8px; font-size: 11px; font-weight: 600; white-space: nowrap; }
.outlook.t5 { background: #e1f5ee; color: #0f6e56; }
.outlook.t4 { background: #eaf3de; color: #3b6d11; }
.outlook.t3 { background: #f1efe8; color: #5f5e5a; }
.outlook.t2 { background: #faeeda; color: #854f0b; }
.outlook.t1 { background: #fcebeb; color: #a32d2d; }
.outlook.t0 { color: #9a968d; }
.colpick { position: relative; }
.colmenu { position: absolute; right: 0; top: 40px; z-index: 20; background: var(--surface);
  border: 1px solid var(--line-strong); padding: 8px; width: 150px; }
.colopt { display: block; font-size: 13px; padding: 4px 6px; cursor: pointer; color: var(--text); }
.colopt input { margin-right: 6px; vertical-align: -1px; }

/* Toolbar dropdown menus (worklist / benchmark / filters / view) */
.menu { position: relative; }
.menu-btn { height: 34px; padding: 0 12px; font-size: 13px; display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.menu-btn.icon-btn { padding: 0 11px; font-size: 15px; line-height: 1; }
.menu-panel { position: absolute; left: 0; top: 40px; z-index: 45; background: var(--surface);
  border: 1px solid var(--line-strong); padding: 8px; min-width: 210px; max-width: 92vw;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.10); }
.menu.right .menu-panel { left: auto; right: 0; }
.menu-panel.wide { min-width: 250px; }
.menu-item { display: block; width: 100%; text-align: left; height: auto; padding: 8px 10px; border: none; background: none; font-size: 13px; color: var(--text); }
.menu-item:hover { background: var(--bg); }
.menu-item.danger { color: #a32d2d; }
.menu-label { font-size: 10px; color: var(--faint); text-transform: uppercase; letter-spacing: 0.04em; padding: 8px 8px 3px; }
.menu-row { display: flex; gap: 6px; padding: 2px 4px 6px; }
.menu-row input { flex: 1; }
.menu-check { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 7px 8px; cursor: pointer; }
.menu-filter { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 5px 8px; font-size: 13px; }
.menu-filter span { color: var(--muted); }
.menu-filter.rel span { color: var(--rel-text); }
.menu-filter input { width: 88px; height: 30px; }
.menu-actions { display: flex; gap: 8px; padding: 8px 4px 2px; }
.menu-actions .mini { flex: 1; }
.menu-dot { display: inline-block; width: 7px; height: 7px; background: var(--accent); margin: 0 1px 0 3px; }
.menu-panel > select { width: 100%; margin: 2px 0 4px; }
.colmenu-inline { max-height: 240px; overflow-y: auto; padding: 2px 0; }

/* Saved screens list (inside the Screens ▾ menu) */
.screens-list { max-height: 240px; overflow-y: auto; padding: 2px 0; }
.screen-row { display: flex; align-items: center; gap: 4px; }
.screen-apply { flex: 1; text-align: left; height: auto; padding: 7px 8px; border: none; background: none;
font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.screen-apply:hover { background: var(--bg); }
.screen-del { border: none; background: none; color: var(--faint); height: auto; padding: 4px 7px;}
.screen-del:hover { color: #a32d2d; background: var(--bg); }

/* Alerts bell (topbar) */
.bell { position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; color: var(--muted); text-decoration: none; border: 1px solid transparent; }
.bell:hover { background: var(--bg); color: var(--text); }
.bell.has-alerts { color: var(--warn-text); }
.bell-badge { position: absolute; top: 1px; right: 1px; min-width: 15px; height: 15px; padding: 0 4px;
background: #a32d2d; color: #fff; font-size: 10px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; }

/* Alerts page */
.alert-form h4 { margin: 0 0 10px; }
.alert-form-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: end; }
.alert-list { display: flex; flex-direction: column; gap: 8px; }
.alert-card { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--line); padding: var(--pad-row); }
.alert-card.is-trig { border-color: #e2b48a; background: var(--warn-bg); }
.al-main { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.al-rule { font-size: 13px; color: var(--text); }
.al-rule b { color: var(--accent-text); font-weight: 600; }
.al-name { font-size: 12px; color: var(--faint); }
.al-right { display: flex; align-items: center; gap: 10px; }
.al-now { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.al-badge { font-size: 11px; font-weight: 600; padding: 4px 9px; white-space: nowrap; }
.al-badge.trig { background: #fcebeb; color: #a32d2d; }
.al-badge.ok { background: var(--accent-bg); color: var(--accent-text); }
.al-badge.na { background: var(--bg); color: var(--faint); }
:root[data-theme="dark"] .al-badge.trig { background: #3a1f1f; color: #e58585; }

/* Density toggle: compact rows on the screener table */
#grid.dense thead th { padding: 6px 10px; }
#grid.dense tbody td { padding: 4px 10px; font-size: 12.5px; }
#grid.dense .fund-name { font-size: 10.5px; }

/* CSV / paste import modal (portfolio builder) */
.import-modal { position: fixed; inset: 0; z-index: 120; background: rgba(0,0,0,0.4);
  display: none; align-items: center; justify-content: center; padding: 20px; }
.import-modal.show { display: flex; }
.import-card { background: var(--surface); border: 1px solid var(--line-strong);
  padding: 18px 20px; width: min(520px, 96vw); box-shadow: 0 12px 40px var(--shadow); }
.import-card h3 { margin: 0 0 4px; font-size: 16px; }
.import-card .muted-sm { margin-bottom: 10px; }
.import-card textarea { width: 100%; min-height: 150px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; resize: vertical; border: 1px solid var(--line-strong); padding: 8px 10px; }
.import-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }
.import-note { font-size: 12px; margin-top: 8px; min-height: 16px; }
.import-note.err { color: #a32d2d; }
.import-note.ok { color: var(--accent-text); }

/* Searchable benchmark picker */
.bench-cap { color: var(--muted); font-size: 11px; margin-right: 6px; }
.bench-val { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px; }
.menu-caret { color: var(--faint); margin-left: 4px; }
.bench-panel { min-width: 320px; }
.bench-panel #benchSearch { width: 100%; margin-bottom: 6px; }
.bench-results { max-height: 340px; overflow-y: auto; }
.bench-group { font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--faint); padding: 8px 8px 3px; }
.bench-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; text-align: left;
  border: none; background: none; height: auto; padding: 7px 9px; font-size: 13px; color: var(--text); }
.bench-item:hover { background: var(--bg); }
.bench-item-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bench-tag { font-size: 9px; text-transform: uppercase; letter-spacing: 0.03em; padding: 2px 8px; flex: none;
  background: var(--bg); color: var(--faint); border: 1px solid var(--line); }
.bench-tag.index { background: var(--accent-bg); color: var(--accent-text); border-color: #bfe6d7; }
.bench-tag.blend { background: #eef1f7; color: #3b5a86; border-color: #cdd8ea; }
.bench-empty { padding: 12px; color: var(--faint); font-size: 12px; text-align: center; }
.bench-blend { border-top: 1px solid var(--line); margin-top: 4px; color: var(--accent-text); }

/* Custom date-range inputs */
.range-inputs { display: inline-flex; align-items: center; gap: 6px; }
.range-inputs[hidden] { display: none; }   /* honor the hidden attribute */
.range-inputs input[type="date"] { width: 150px; }
.range-dash { color: var(--muted); }

/* Header fund search */
.fundsearch { position: relative; margin-left: 12px; }
.fundsearch > input { height: 32px; width: 220px; font-size: 13px; }
.fs-results { position: absolute; left: 0; top: 38px; z-index: 60; width: 340px; max-width: 80vw; background: var(--surface);
  border: 1px solid var(--line-strong); padding: 6px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.10);
  max-height: 360px; overflow-y: auto; }
.fs-item { display: flex; align-items: baseline; gap: 10px; padding: 7px 9px; text-decoration: none; color: var(--text); }
.fs-item:hover { background: var(--bg); }
.fs-id { font-weight: 600; min-width: 54px; }
.fs-name { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-empty { padding: 10px; color: var(--faint); font-size: 12px; }

/* Worklist management + custom benchmark */
.mini { height: var(--ctl-h-sm); padding: 2px 10px; font-size: 12px; }
.bench-custom { width: 132px; }
#benchClear { height: var(--ctl-h-sm); padding: 2px 9px; font-size: 12px; }
.wl-panel { background: var(--surface); border: 1px solid var(--line); padding: var(--pad-card); margin-bottom: var(--gap-block); }
.wl-add { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.wl-add input { width: 210px; }
.wl-members { display: flex; flex-wrap: wrap; gap: 6px; }
.wl-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg); border: 1px solid var(--line); padding: 4px 9px; font-size: 12px; }
.wl-chip .x { cursor: pointer; color: var(--faint); font-size: 13px; }
.wl-chip .x:hover { color: #a32d2d; }

/* Blended benchmarks */
.cb-row { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.cb-name { font-weight: 600; min-width: 90px; }
.cb-summary { color: var(--muted); flex: 1; }
.cb-editor { border-top: 1px solid var(--line); padding-top: 10px; }
.cb-editor-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.cb-comp { display: flex; align-items: center; gap: 8px; margin: 5px 0; font-size: 13px; }
.cb-comp input.cb-cid { width: 190px; }
.cb-comp input.cb-cw { width: 70px; }
.cb-comp .x { cursor: pointer; color: var(--faint); }
.cb-comp .x:hover { color: #a32d2d; }
.cb-editor-actions { display: flex; gap: 8px; margin-top: 8px; }

/* Save/load portfolios */
.pf-saveload { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.pf-saveload select { width: auto; min-width: 160px; height: 30px; }
.addbtn { border: none; background: none; height: auto; padding: 2px 6px; color: var(--accent); cursor: pointer; }
.addbtn:hover { background: none; color: #18604b; }
.added { color: var(--faint); }
.add-label { display: none; }
.muted-sm { font-size: 11px; color: var(--faint); margin: 8px 2px 0; }

.builder { margin-top: var(--gap-block); background: var(--surface); border: 1px solid var(--line); padding: var(--pad-card); }
.builder h3 { margin: 0; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.builder .tag { font-size: 11px; color: var(--muted); background: var(--bg); border: 1px solid var(--line); padding: 2px 8px; font-weight: 400; }
.hold { display: flex; align-items: center; gap: 10px; margin: 8px 0; }
.hold .tk { width: 70px; font-weight: 600; }
.hold .bar { flex: 1; height: 8px; background: var(--bg); overflow: hidden; }
.hold .bar > div { height: 100%; background: var(--accent); }
.hold input { width: 70px; height: var(--ctl-h-sm); }
.hold .rm { cursor: pointer; color: var(--faint); }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 14px; }
/* .stat was --bg on a --bg page with no border: twelve invisible boxes on the
   fund page. It needs an edge of its own now that nothing is rounded to imply
   one. */
.stat { background: var(--bg); border: 1px solid var(--line); padding: var(--pad-tile); }
.stat.rel { background: var(--rel-tint); border-color: var(--rel-line); }
.stat .k { font-size: 12px; color: var(--muted); }
.stat.rel .k { color: var(--rel-text); }
.stat .v { font-size: 20px; font-weight: 600; }
.stat.rel .v { color: var(--text); }
.disclaimer { font-size: 11px; color: var(--faint); margin-top: 12px; }
.empty { background: var(--surface); border: 1px solid var(--line); padding: 28px 20px; text-align: center; padding: 28px; text-align: center; color: var(--faint); }

/* Auth pages */
.auth-wrap { display: flex; align-items: center; justify-content: center; padding: 24px; }
.auth-logo { display: block; margin: 0 auto 10px;}
.auth-card { width: 100%; max-width: 380px; background: var(--surface); border: 1px solid var(--line); padding: 28px 26px; }
.auth-brand { font-size: 20px; font-weight: 600; margin: 0 0 2px; letter-spacing: -0.01em; }
.auth-sub { color: var(--muted); margin: 0 0 18px; font-size: 14px; }
.auth-card label { display: block; font-size: 12px; color: var(--muted); margin: 12px 0 4px; }
.auth-hint { color: var(--faint); }
.auth-card input { width: 100%; }
.auth-submit { width: 100%; margin-top: 18px; height: 38px; }
.auth-alt { font-size: 13px; color: var(--muted); margin: 16px 0 0; text-align: center; }
.auth-alt a { color: var(--accent-text); text-decoration: none; }
.auth-flash { font-size: 13px; padding: 8px 10px; margin-bottom: 8px; }
.auth-flash.error { background: #fcebeb; color: #a32d2d; }
.auth-flash.success { background: var(--accent-bg); color: var(--accent-text); }

/* Correlation heatmap */
.corrcard { margin-top: 16px; }
.corr-toggle { font-size: 13px; }
.corr-grid { overflow-x: auto; margin-top: 8px; border: 1px solid var(--line);}
.corr-table { border-collapse: collapse; font-size: 11px; }
.corr-table th { background: var(--surface); font-weight: 500; color: var(--muted); padding: 5px 7px; text-align: center; white-space: nowrap; }
.corr-table thead th { position: sticky; top: 0; z-index: 2; }
.corr-table tbody th { position: sticky; left: 0; z-index: 1; text-align: right; }
.corr-table td { padding: 5px 7px; text-align: center; min-width: 42px; border: 1px solid var(--surface); color: var(--text); }
.corr-table td.corr-na { color: var(--faint); background: repeating-linear-gradient(45deg, transparent, transparent 3px, #f1efe8 3px, #f1efe8 4px); }

/* Optimizer */
.opt { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 14px; }
.opt-controls { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.frontier { width: 360px; max-width: 100%; height: auto; margin-top: 10px; }
.frontier .ax { stroke: var(--line-strong); stroke-width: 1; }
.frontier .axl { fill: var(--faint); font-size: 9px; }
.frontier .fline { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0.7; }
.flegend { display: flex; gap: 14px; font-size: 11px; color: var(--muted); margin-top: 4px; }
.flegend i { display: inline-block; width: 9px; height: 9px; margin-right: 4px; vertical-align: -1px; }
.optsets { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; }
.optset { flex: 1; min-width: 200px; background: var(--bg); border: 1px solid var(--line); padding: var(--pad-tile); }
.optset-h { display: flex; justify-content: space-between; align-items: center; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.applyw { height: 26px; padding: 2px 8px; font-size: 12px; }
.optw { width: 100%; font-size: 12px; margin-bottom: 6px; }
.optw td { padding: 2px 0; }
.optw td:last-child { text-align: right; }

/* ---- Fund profile page ---- */
.brand { text-decoration: none; color: inherit; }
.back-link { font-size: 13px; color: var(--accent-text); text-decoration: none; }
.back-link:hover { text-decoration: underline; }
.prof-head { background: var(--surface); border: 1px solid var(--line); padding: var(--pad-card); margin-bottom: var(--gap-block); }
.ph-top { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.ph-ticker { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; display: flex; align-items: center; gap: 10px; }
.ph-name { color: var(--muted); font-size: 15px; margin-top: 2px; }
.ph-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; align-items: center; }
.ph-chip { font-size: 11px; color: var(--muted); background: var(--bg); border: 1px solid var(--line); padding: 4px 9px; }
.ph-chip.inferred { border-style: dashed; font-style: italic; cursor: help; }
.ph-facts { display: grid; grid-template-columns: repeat(2, auto); gap: 8px 22px; align-content: start; }
.ph-facts > div { display: flex; flex-direction: column; }
.ph-facts span { font-size: 11px; color: var(--faint); }
.ph-facts b { font-size: 16px; font-weight: 600; }
.ph-subfact { font-size: 10.5px; color: var(--muted); font-weight: 500; margin-top: 1px; }
.ph-blurb { margin: 10px 2px 0; color: var(--muted); font-size: 13.5px; line-height: 1.55; max-width: 640px; }

/* Blend composition: donut pie + legend beside an allocation / data-range table */
.blend-alloc { display: grid; grid-template-columns: 190px 1fr; gap: 20px; align-items: center;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.alloc-pie { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.pie { width: 128px; height: 128px; }
.pie-legend { flex-wrap: wrap; justify-content: center; row-gap: 4px; }
.mini-tbl.alloc { width: 100%; }
.mini-tbl.alloc td, .mini-tbl.alloc th { text-align: right; }
.mini-tbl.alloc td.left, .mini-tbl.alloc th.left { text-align: left; }
.mini-tbl.alloc td.left .fund-name { display: inline-block; max-width: 260px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.cdot { display: inline-block; width: 9px; height: 9px; margin-right: 6px; vertical-align: -1px; }
.constraint-tag { font-size: 10px; background: #faeeda; color: #854f0b; padding: 2px 8px; margin-left: 6px; }
.mini-tbl.alloc td.cons { color: #854f0b; font-weight: 600; }
.mini-tbl.alloc tr.unavail { opacity: 0.55; }
.alloc-note { font-size: 11px; color: var(--muted); margin-top: 8px; }
@media (max-width: 720px) {
  .blend-alloc { grid-template-columns: 1fr; }
  .mini-tbl.alloc td.left .fund-name { max-width: 46vw; }
}

/* 0, not 2px: this heading sits above the stat grid and its 2px indent put it
   on a different left edge from the card headings above and below it. */
.prof-stats-h { font-size: 13px; font-weight: 600; margin: 4px 0 8px; }
.prof-stats-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--gap-sm); margin-bottom: var(--gap-block); }
.prof-stats-grid .stat { padding: 8px 10px; }
.prof-stats-grid .stat .v { font-size: 17px; font-variant-numeric: tabular-nums; }
@media (max-width: 820px) { .prof-stats-grid { grid-template-columns: repeat(3, 1fr); } }

.chartcard, .panelcard { background: var(--surface); border: 1px solid var(--line); padding: var(--pad-card); margin-bottom: var(--gap-block); }
.chartcard h4, .panelcard h4 { margin: 0 0 8px; font-size: 14px; font-weight: 600; display: flex; align-items: baseline; gap: 3px 8px; flex-wrap: wrap; }
/* The inline note in a card heading inherits .muted-sm's top margin, which in a
   flex row pushes the whole heading down — so 11 of 16 card headings sat ~5px
   lower than the rest. */
.chartcard h4 .muted-sm, .panelcard h4 .muted-sm { margin: 0; }
/* panel header with an inline control (e.g. the top-funds card's own range picker) */
.panel-h { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.panel-h h4 { margin-bottom: 8px; }
.panel-ctl { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.panel-ctl select { height: 30px; }

/* segmented toggle (allocation by asset class / by fund) */
.seg { display: inline-flex; border: 1px solid var(--line-strong); overflow: hidden; }
.seg-btn { height: 30px; padding: 0 12px; font-size: 12px; background: var(--surface); color: var(--muted); border: none; cursor: pointer; }
.seg-btn.active { background: var(--accent-bg); color: var(--accent-text); font-weight: 600; }
.seg-btn + .seg-btn { border-left: 1px solid var(--line); }

/* rebalance markers on the allocation-over-time chart */
.reb-marker { stroke: #33475b; stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.5; }

/* risk/reward scatter point labels */
.scat-lbl { font-size: 9px; fill: var(--faint); }
.scat-lbl.strong { fill: #1d6e56; font-weight: 700; font-size: 10px; }
.scat-lbl.bench { fill: #185fa5; font-weight: 600; }

/* ===== Category context: percentile-rank hero + quartile bar ===== */
.peer-grid { display: grid; grid-template-columns: 250px 1fr; gap: 22px; align-items: center; }
@media (max-width: 720px) { .peer-grid { grid-template-columns: 1fr; } }
.rank-big { font-size: 34px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
.rank-big.muted { color: var(--faint); font-size: 22px; }
.rank-unit { font-size: 13px; font-weight: 500; color: var(--muted); margin-left: 7px; }
.quartbar { position: relative; display: flex; gap: 3px; height: 14px; margin: 10px 0 8px; }
.qseg { flex: 1; background: var(--bg); border: 1px solid var(--line); }
.qseg:nth-child(1).active { background: #cdeee1; border-color: #0f6e56; }
.qseg:nth-child(2).active { background: #dfeec9; border-color: #3b6d11; }
.qseg:nth-child(3).active { background: #f7e3c0; border-color: #854f0b; }
.qseg:nth-child(4).active { background: #f7cfcf; border-color: #a32d2d; }
.qmark { position: absolute; top: -4px; bottom: -4px; width: 3px;
  background: var(--text); box-shadow: 0 0 0 2px var(--surface); }
.rank-chip { display: inline-block; min-width: 26px; text-align: center; padding: 2px 8px;
font-size: 11px; font-weight: 700; }
.rank-chip.q1 { background: #e1f5ee; color: #0f6e56; }
.rank-chip.q2 { background: #eaf3de; color: #3b6d11; }
.rank-chip.q3 { background: #faeeda; color: #854f0b; }
.rank-chip.q4 { background: #fcebeb; color: #a32d2d; }

/* ===== Risk & capture bars ===== */
.cap-row { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
.cap-l { width: 96px; font-size: 12px; color: var(--muted); }
.cap-track { position: relative; flex: 1; height: 16px; background: var(--bg);
  border: 1px solid var(--line); overflow: hidden; }
.cap-fill { height: 100%;}
.cap-fill.up { background: #7fc7ab; }
.cap-fill.dn { background: #e0a1a1; }
.cap-100 { position: absolute; top: -2px; bottom: -2px; left: 71.4%; width: 2px; background: var(--text); opacity: 0.55; }
.cap-v { width: 48px; text-align: right; font-weight: 600; font-size: 13px; }

/* ===== Drawdown episodes ===== */
.ep-h { font-size: 12px; font-weight: 600; color: var(--muted); margin: 12px 2px 6px; }
.ep-wrap { position: relative; min-width: 120px; padding: 1px 4px; }
.ep-depth { position: absolute; left: 0; top: 0; bottom: 0; background: rgba(163,45,45,0.14);}
.ep-wrap span { position: relative; font-weight: 600; }
.ep-open { color: #a32d2d; font-size: 11px; font-weight: 600; background: #fcebeb; padding: 2px 8px; white-space: nowrap; }

/* ===== Crisis replay rows ===== */
.cr-row { display: grid; grid-template-columns: 175px 1fr 110px 150px; gap: 12px; align-items: center;
  padding: 7px 0; border-bottom: 1px solid var(--line); }
.cr-row:last-of-type { border-bottom: none; }
.cr-label b { display: block; font-size: 12.5px; }
.cr-label .muted-sm { font-size: 10.5px; }
.cr-track { position: relative; height: 22px; background: var(--bg); border: 1px solid var(--line);}
.cr-zero { position: absolute; top: 0; bottom: 0; width: 1.5px; background: var(--text); opacity: 0.4; }
.cr-bar { position: absolute;}
.cr-bar.fund { top: 3px; height: 7px; background: #1d6e56; }
.cr-bar.bench { bottom: 3px; height: 7px; background: #8db6dd; }
.cr-vals { text-align: right; font-size: 12.5px; font-weight: 600; display: flex; flex-direction: column; }
.cr-vals .cr-b { color: #185fa5; font-weight: 500; font-size: 11.5px; }
.cr-rec { font-size: 11.5px; color: var(--muted); }
@media (max-width: 720px) {
  .cr-row { grid-template-columns: 105px 1fr 76px; }
  .cr-rec { grid-column: 2 / 4; margin-top: -4px; }
}

/* ===== Behavioral style box (RBSA) ===== */
.style-grid { display: grid; grid-template-columns: auto 1fr; gap: 20px; align-items: start; }
@media (max-width: 720px) { .style-grid { grid-template-columns: 1fr; } }
.sb-wrap { display: flex; gap: 6px; }
.sb-ylabels { display: flex; flex-direction: column; justify-content: space-around; font-size: 10px; color: var(--faint); text-align: right; }
.sb-xlabels { display: flex; justify-content: space-around; font-size: 10px; color: var(--faint); margin-top: 4px; }
.stylebox { position: relative; display: grid; grid-template-columns: repeat(3, 44px); grid-template-rows: repeat(3, 44px); gap: 3px; }
.sb-cell { background: var(--bg); border: 1px solid var(--line);}
.sb-cell.active { background: var(--accent-bg); border-color: #0f6e56; }
.sb-dot { position: absolute; width: 13px; height: 13px; background: #1d6e56;
  border: 2.5px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.35); transform: translate(-50%, -50%); }
.mix-h { font-weight: 600; margin-bottom: 5px; }
.mixbar { display: flex; height: 20px; overflow: hidden; border: 1px solid var(--line); }
.mix-seg { height: 100%; }

/* ===== Similar funds / cheaper twin ===== */
.twin-callout { display: flex; gap: 12px; align-items: center; background: #eefaf4;
  border: 1px solid #bfe6d7; padding: var(--pad-row); margin-bottom: 12px; }
.twin-flag { flex-shrink: 0; background: #0f6e56; color: #fff; font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; padding: 4px 9px; }
.twin-main { font-size: 13px; }
.corrbar { display: inline-block; vertical-align: -2px; width: 52px; height: 7px; margin-left: 6px;
  background: var(--bg); border: 1px solid var(--line); overflow: hidden; }
.corrbar > div { height: 100%; background: #7fc7ab; }
.corr-cell { white-space: nowrap; }
.pos { color: #0f6e56; font-weight: 600; }

/* ===== Section chips (sticky in-page nav) ===== */
.sec-chips { position: sticky; top: var(--topbar-h); z-index: 35; display: flex; gap: 6px; overflow-x: auto;
  background: var(--bg); padding: 8px 2px; margin: 0 0 8px; scrollbar-width: none; }
.sec-chips::-webkit-scrollbar { display: none; }
.sec-chips a { flex-shrink: 0; font-size: 12px; color: var(--muted); text-decoration: none;
  border: 1px solid var(--line); padding: 5px 12px; background: var(--surface); }
.sec-chips a.active { background: var(--accent-bg); color: var(--accent-text); border-color: #bfe6d7; font-weight: 600; }

/* ===== UX popover (inline prompt replacement) + armed delete buttons ===== */
.ux-pop-row { display: flex; gap: 6px; padding: 6px; }
.ux-pop-row input { flex: 1; height: 30px; min-width: 150px; }
button.armed { background: #fcebeb !important; border-color: #a32d2d !important; color: #a32d2d !important; }
.gloss, .stat .k[title], .mini-tbl td.left[title] { cursor: help; text-decoration: underline dotted var(--faint); text-underline-offset: 3px; }

/* ===== Compare funds ===== */
.cmp-add { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.cmp-add input { height: 34px; min-width: 260px; flex: 0 1 340px; }
.cmp-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.cmp-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
  border: 1.5px solid var(--line-strong); padding: 3px 6px 3px 9px; background: var(--surface); }
.cmp-chip i { width: 9px; height: 9px;}
.cmp-chip b { cursor: pointer; color: var(--faint); font-weight: 400; }
.cmp-chip b:hover { color: #a32d2d; }
.cmp-tbl th, .cmp-tbl td { text-align: right; padding: 8px 12px; white-space: nowrap; }
.cmp-tbl th.left, .cmp-tbl td.left { text-align: left; }
.cmp-tbl thead th { border-bottom: 1px solid var(--line-strong); vertical-align: bottom; }
.cmp-tbl td.cmp-best { background: #e1f5ee; font-weight: 700; color: #0f6e56; }
/* compare bar + row checkboxes on the screener */
.cmp-bar { position: sticky; bottom: 0; z-index: 40; display: none; align-items: center; gap: 12px;
  background: #1d2723; color: #f2f1ec; padding: 10px 16px; margin: 10px 0;
  box-shadow: 0 6px 20px rgba(0,0,0,0.2); }
.cmp-bar.show { display: flex; }
.cmp-bar .cmp-bar-ids { flex: 1; font-size: 13px; }
.cmp-bar button { height: 32px; }
/* clear the fixed bottom tab bar on mobile so Clear/Compare aren't hidden behind it */
@media (max-width: 720px) { .cmp-bar { bottom: calc(var(--tabbar) + 12px); } }
td.cmp-cell, th.cmp-cell { width: 28px; text-align: center !important; padding: 0 !important; }
.cmp-check { width: auto; height: auto; margin: 0; cursor: pointer; }

/* ===== Account settings ===== */
.acct-sec { max-width: 520px; margin-bottom: var(--gap-block); }
/* `.acct-sec h2` used to restate what `.info-page h2` already provides, at a
   different size — and lost, because .info-page h2 is the more specific
   selector on these pages. Deleted rather than fought; the one thing it did
   uniquely was the red rule on the Delete-account section, which is restored
   below as a longhand so it beats .info-page h2's border shorthand. */
.acct-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.verify-badge { font-size: 11px; font-weight: 600; padding: 4px 9px; margin-left: 8px; }
.verify-badge.ok { background: #e1f5ee; color: #0f6e56; }
.verify-badge.no { background: #faeeda; color: #854f0b; }
.acct-form { display: flex; flex-direction: column; }
.acct-form label { font-size: 12px; color: var(--muted); margin: 10px 0 4px; }
.acct-form input { height: 36px; }
.danger-zone h2 { color: #a32d2d; border-bottom-color: #efc7c7; }
.danger-btn { background: #a32d2d; color: #fff; border-color: #a32d2d; }
.danger-btn:hover { background: #8a2626; }
.acct-menu .menu-item { display: block; padding: 7px 10px; font-size: 13px; color: var(--text); text-decoration: none;}
.acct-menu .menu-item:hover { background: var(--bg); }
.mini.primary { background: var(--accent); color: #fff; border-color: var(--accent); text-decoration: none;
  display: inline-flex; align-items: center; }
.mini.primary:hover { filter: brightness(1.06); }
/* 2FA enrollment */
.twofa-steps { padding-left: 20px; margin: 6px 0 16px; }
.twofa-steps li { line-height: 1.6; font-size: 13.5px; margin: 4px 0; color: var(--text); }
.twofa-qr { display: inline-block; padding: 10px; background: #fff; border: 1px solid var(--line);
line-height: 0; }
.twofa-qr svg { width: 190px; height: 190px; }
.twofa-key { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.twofa-key code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
  letter-spacing: 1px; background: var(--bg); border: 1px solid var(--line);
  padding: 5px 9px; user-select: all; word-break: break-all; }
.backup-codes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px;
  margin: 14px 0; padding: 14px; background: var(--bg); border: 1px solid var(--line);}
.backup-codes code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px;
  letter-spacing: 1px; user-select: all; }

/* ===== Info pages (methodology / terms / privacy) + footer ===== */
.info-page { max-width: 860px; }
/* One page-title treatment. First ink landed at 77, 81, 83 or 85px depending
   which page you were on, because each title carried its own top margin on top
   of .wrap's. .wrap's 18px is now the only top offset, and every title is 26px
   — matching .dash-hi, which was already right. */
.info-h1 { font-size: 26px; letter-spacing: -0.02em; margin: 0 0 6px; }
.info-lead { font-size: 16px; color: var(--muted); line-height: 1.6; margin-bottom: 20px; }
.info-toc { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 26px; }
.info-toc a { font-size: 12px; color: var(--accent-text); text-decoration: none; border: 1px solid #bfe6d7;
  background: var(--accent-bg); padding: 4px 11px; }
.info-page section { margin: 0 0 26px; }
.info-page h2 { font-size: 18px; margin: 0 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--line); scroll-margin-top: calc(var(--topbar-h) + 12px); }
.info-page p, .info-page li { line-height: 1.65; }
.info-page ul { padding-left: 20px; }
.info-page li { margin: 4px 0; }
/* table-layout:fixed + width:100% => the table can never exceed its container,
   and the long description column wraps instead of forcing horizontal overflow. */
.info-tbl { width: 100%; table-layout: fixed; border-collapse: collapse; margin: 4px 0; }
/* white-space:normal is required — the global `tbody td { white-space: nowrap }`
   (screener table) otherwise matches these cells and forces horizontal overflow. */
.info-tbl td { padding: 9px 12px; border-bottom: 1px solid var(--line); vertical-align: top;
  line-height: 1.55; white-space: normal; overflow-wrap: break-word; word-break: break-word; }
.info-tbl td:first-child { font-weight: 600; width: 30%; }
@media (max-width: 620px) { .info-tbl td:first-child { width: auto; } .info-tbl, .info-tbl tbody, .info-tbl tr, .info-tbl td { display: block; } .info-tbl td { border: none; padding: 2px 0; } .info-tbl tr { border-bottom: 1px solid var(--line); padding: 8px 0; } }

.site-footer { border-top: 1px solid var(--line); background: var(--surface); margin-top: 40px; }
.footer-inner { max-width: min(1600px, 95vw); margin: 0 auto; padding: 16px 20px 24px; display: flex;
  align-items: center; gap: 16px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
.footer-brand { font-weight: 600; color: var(--text); }
.footer-links { display: flex; gap: 16px; }
.footer-links a { color: var(--accent-text); text-decoration: none; }
.footer-links a:hover { text-decoration: underline; }
.footer-note { color: var(--faint); flex: 1; min-width: 220px; }
.footer-asof { color: var(--muted); white-space: nowrap; cursor: help; }
.gloss-dl { display: grid; grid-template-columns: max-content 1fr; gap: 8px 20px; margin: 6px 0; }
.gloss-dl dt { font-weight: 600; color: var(--text); white-space: nowrap; }
.gloss-dl dd { margin: 0; color: var(--muted); line-height: 1.6; }
@media (max-width: 640px) { .gloss-dl { grid-template-columns: 1fr; gap: 2px 0; } .gloss-dl dd { margin: 0 0 10px; } }
@media (max-width: 720px) { .site-footer { margin-bottom: var(--tabbar); } }

/* ===== Holdings look-through / X-Ray ===== */
.hold-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin-bottom: 4px; }
.hold-facts > div { display: flex; flex-direction: column; background: var(--bg); border: 1px solid var(--line); padding: 7px 10px; }
.hold-facts span { font-size: 10.5px; color: var(--faint); }
.hold-facts b { font-size: 16px; font-variant-numeric: tabular-nums; }
.hbar-wrap { position: relative; min-width: 130px; }
.hbar { position: absolute; left: 0; top: 0; bottom: 0; background: var(--accent-bg);}
.hbar-wrap span { position: relative; font-variant-numeric: tabular-nums; }
.xray-overlap td { background: #eefaf4; }
.xray-src { font-size: 10.5px; color: var(--muted); }
/* sector-exposure bars (fund holdings + portfolio X-Ray) */
.sec-list { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.sec-row { display: grid; grid-template-columns: minmax(90px, 34%) 1fr auto; align-items: center; gap: 8px; font-size: 12px; }
.sec-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sec-bar-wrap { background: var(--bg); border: 1px solid var(--line); height: 12px; overflow: hidden; }
.sec-bar { height: 100%;}
.sec-pct { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 42px; text-align: right; }
:root[data-theme="dark"] .xray-overlap td { background: #16352b; }

/* ===== Chart hover layer (charts.js) ===== */
.ch-tip { position: absolute; z-index: 40; pointer-events: none; background: #1d2723; color: #f2f1ec;
padding: 7px 10px; font-size: 11.5px; line-height: 1.45;
  box-shadow: 0 4px 16px rgba(0,0,0,0.28); min-width: 120px; max-width: 240px; }
.ch-tip .ch-m { font-weight: 700; margin-bottom: 3px; color: #cfe8dd; }
.ch-tip .ch-row { display: flex; align-items: center; gap: 6px; }
.ch-tip .ch-row i { width: 8px; height: 8px; flex-shrink: 0; }
.ch-tip .ch-row span { color: #b9c4be; flex: 1; margin-right: 8px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 130px; }
.ch-tip .ch-row b { font-variant-numeric: tabular-nums; }
.ch-xhair { stroke: #6b7671; stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.8; }
.ch-dot { stroke: #fff; stroke-width: 1.4; }

/* ===== Dashboard home ===== */
.dash-hero { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px;
  flex-wrap: wrap; margin: 0 0 20px; }
.dash-hi { margin: 0 0 4px; font-size: 26px; letter-spacing: -0.02em; }
.dash-hi .dot { color: #1d6e56; }
.dash-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.dash-h { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin: 18px 2px 10px; }
.popular-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.pop-chip { display: inline-flex; align-items: baseline; gap: 6px; text-decoration: none;
  border: 1px solid var(--line); background: var(--surface); padding: 6px 11px;
  font-size: 12.5px; color: var(--text); max-width: 240px; }
.pop-chip b { color: var(--accent-text); } .pop-chip span { color: var(--muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.pop-chip:hover { border-color: var(--accent); }
.pop-chip.pop-more { color: var(--accent-text); font-weight: 600; }
/* minmax(0, 1fr) lets the tracks shrink below their min-content, preventing a
   long ticker line from blowing the grid past the viewport (horizontal overflow). */
.tile-row { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 980px) { .tile-row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 720px) { .tile-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tile { background: var(--surface); border: 1px solid var(--line); padding: var(--pad-tile); min-width: 0; }
.tile-h { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 4px; gap: 6px; min-width: 0; }
.tile-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tile-sub { font-size: 10.5px; color: var(--faint); }
.spark { width: 100%; height: 34px; display: block; margin: 2px 0 4px; }
.tile-row2 { display: flex; gap: 12px; }
.tile-kv { display: inline-flex; flex-direction: column; }
.tile-kv i { font-style: normal; font-size: 10px; color: var(--faint); }
.tile-kv b { font-size: 12.5px; }
.up { color: #0f6e56; }
.down { color: #a32d2d; }
.dash-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: 20px; align-items: start; }
@media (max-width: 900px) { .dash-grid { grid-template-columns: 1fr; } }
.pcard { display: block; background: var(--surface); border: 1px solid var(--line);
  padding: var(--pad-row); margin-bottom: 10px; color: var(--text); text-decoration: none; }
a.pcard:hover { border-color: #0f6e56; box-shadow: 0 2px 10px rgba(15,110,86,0.10); }
.pcard-h { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.pcard-h b { font-size: 15px; }
.pcard-body { display: flex; align-items: center; gap: 16px; }
.pcard-body .spark { width: 160px; height: 40px; flex-shrink: 0; }
.pcard-kvs { display: flex; gap: 14px; flex-wrap: wrap; }
.wl-movers { display: flex; gap: 16px; flex-wrap: wrap; margin: 4px 0; font-size: 12.5px; }
.pcard-links { margin-top: 6px; font-size: 12px; }
.pcard-links a { color: var(--accent-text); text-decoration: none; }
.empty-cta { text-align: center; padding: 22px 16px; }
.empty-cta .fund-act { display: inline-flex; align-items: center; }

/* skeleton shimmer for loading states */
.stat.skel { min-height: 58px; border: 1px solid var(--line);}
.skel {
  position: relative; overflow: hidden; min-height: 84px; border-color: var(--line);
  /* NOT var(--bg): that is the page background, so the block was invisible
     wherever it sat on the page and the only thing that read as loading was the
     sweep — the animation carrying visibility on its own, which is the failure
     this codebase already fixed once for .sk-bar. A tint of --text is visible
     against both --bg and --surface, in both themes. Plain rgba first so an
     engine without color-mix still shows a block rather than nothing. */
  background: rgba(128, 128, 128, 0.14);
  background: color-mix(in srgb, var(--text) 12%, transparent);
}
.skel::after { content: ""; position: absolute; inset: 0;
  /* 0.55, not 0.65: 65% white over the dark theme's #14171a is a near-white
     flash. Same value .sk-bar settled on. */
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.55), transparent);
  animation: shimmer 1.2s infinite; }
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* ===== Screener loading state =====
   Screening the full 26k universe takes ~1.8s, and the table body was simply
   empty for all of it — the page looked frozen rather than working. A skeleton
   that matches the real column layout keeps the layout stable (no reflow jump
   when data lands) and reads as progress rather than a hang. */
.scan-bar {
  position: relative; height: 2px; overflow: hidden;
  background: rgba(128, 128, 128, 0.16);
  background: color-mix(in srgb, var(--accent) 14%, transparent); margin: 0 0 -2px;
}
.scan-bar::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 38%;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  animation: scan 1.15s cubic-bezier(.45,.05,.35,1) infinite;
}
@keyframes scan { from { left: -40%; } to { left: 102%; } }

.sk-cell { padding: 11px 10px; }
.sk-bar {
  display: block; height: 9px; position: relative; overflow: hidden;
  /* 9% was invisible against the table's own background — the rows read as
     blank, which is the problem this is meant to solve. */
  background: rgba(128, 128, 128, 0.18);
  background: color-mix(in srgb, var(--text) 15%, transparent);
}
.sk-bar::after {
  content: ""; position: absolute; inset: 0;
  /* a LIGHT sweep over the grey bar. The first version swept a darker tone over
     an already-dark bar, so nothing moved. White works in both themes: it
     lightens the grey in light mode and the near-black in dark mode. */
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  animation: shimmer 1.25s infinite;
}
.sk-bar.sm { height: 7px; margin-top: 5px; opacity: .6; }
/* Stagger the shimmer so the table reads as filling in rather than flashing as a
   block. This is DECORATION ONLY: the rows are fully visible without it. An
   earlier version faded each row in from opacity 0, which meant that whenever the
   animation did not run — a throttled background tab, reduced motion, an old
   engine — the entire loading state was invisible and the page looked frozen,
   which is the exact problem this is here to solve. Never hide the content behind
   the animation. */
.sk-row .sk-bar { animation-delay: calc(var(--i, 0) * 55ms); }

@media (prefers-reduced-motion: reduce) {
  .scan-bar::after, .sk-bar::after, .skel::after { animation: none; }
  /* `animation: none` alone freezes the sweep wherever it happens to sit, which
     leaves a permanent bright band washing out one end of every block. The
     sweep is decoration over a placeholder that is now visible on its own, so
     under reduced motion drop it entirely and show a flat, even block.
     .scan-bar::after is NOT dropped: there it is the bar itself, not a sweep. */
  .sk-bar::after, .skel::after { display: none; }
}

/* ===== Trade attribution & Monte Carlo verdict cards ===== */
.attr-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 10px; }
.attr-unit { font-size: 12px; font-weight: 500; color: var(--muted); margin-left: 2px; }
.stat.attr-good { background: #eefaf4; border-color: #bfe6d7; }
.stat.attr-good .v { color: #0f6e56; }
.stat.attr-bad { background: #fdf1f1; border-color: #efc7c7; }
.stat.attr-bad .v { color: #a32d2d; }

/* rebalance timeline editor */
.reb-edit { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 12px; }
.reb-block { border: 1px solid var(--line); padding: 10px 12px; margin: 8px 0; background: var(--bg); }
.reb-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.reb-holds { display: flex; flex-direction: column; gap: 4px; margin-bottom: 6px; }

/* print: drop the chrome, expand to full width, keep cards intact */
@media print {
  .noprint, .topbar, .site-footer, .bottom-tabs, .botnav, .fb-fab, .fb-panel,
  .fund-actions, .sec-chips,
  #secChips, .toast, .ch-tip,
  /* The Tearsheet button prints the page as it stands. Without this a tearsheet
     printed while the fund was still loading came out full of grey bars — and
     print engines drop backgrounds by default, so they would have printed as
     blank boxes carrying no hint that anything was missing. */
  .skel-block, .sk-bar, .scan-bar { display: none !important; }
  :root { --bg: #fff; --surface: #fff; --text: #111; }
  body { background: #fff; color: #111; }
  .wrap { max-width: 100%; padding: 0; }
  .chartcard, .panelcard, .prof-head, .tablecard, .card, .prof-stats-grid { break-inside: avoid; box-shadow: none !important; }
  a[href]::after { content: ""; }   /* don't append raw URLs */
  @page { margin: 14mm; }
}
/* margin-bottom on the grid itself, not a `+ .panelcard` patch. That patch
   matched only a .panelcard that FOLLOWED, and on the fund page two .prof-grid2
   blocks are direct siblings (#returnsSec then #riskSec) — so nothing matched
   and the two card rows butted together with a 0px gap where every other card
   boundary has 14px. Square corners fused them into one 2x2 block. */
.prof-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-block);
  margin-bottom: var(--gap-block); }
.prof-grid2 .panelcard { margin-bottom: 0; }
@media (max-width: 820px) { .prof-grid2 { grid-template-columns: 1fr; } }

.period-note { background: var(--warn-bg); color: var(--warn-text); border: 1px solid #f0dcc0;
padding: var(--pad-row); font-size: 12.5px; line-height: 1.55; margin-bottom: 14px; }
.period-note em { font-style: normal; font-weight: 600; }
/* Data-integrity notice: shown in place of a stat block we would otherwise have
   to fill with a figure we know is false (a stable-NAV fund's flat 0.00%). Same
   warm palette as the period note so it reads as "about the data", not an error. */
.data-notice { background: var(--warn-bg); color: var(--warn-text); border: 1px solid #f0dcc0; padding: var(--pad-card); margin-bottom: var(--gap-block); line-height: 1.5; max-width: 84ch; }
.data-notice .muted-sm { margin-top: 10px; }

.chart-ctrls { display: flex; gap: 12px; margin: 0 0 8px; flex-wrap: wrap; }
.seg { display: inline-flex; border: 1px solid var(--line-strong); overflow: hidden; }
.seg button { height: 26px; padding: 0 11px; font-size: 12px; border: none; background: var(--surface); color: var(--muted); }
.corr-seg { margin-top: 10px; }
.seg button + button { border-left: 1px solid var(--line); }
.seg button:hover { background: var(--hover); }
.seg button.on, .seg .on { background: var(--accent-bg); color: var(--accent-text); font-weight: 600; }
.seg button.on, .seg .on:hover { background: var(--accent-bg); }

.tschart { width: 100%; height: auto; display: block; }
.tschart .grid { stroke: var(--line); stroke-width: 1; }
.tschart .axl { fill: var(--faint); font-size: 9px; }

.mini-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.mini-tbl th { text-align: right; font-weight: 500; color: var(--muted); padding: 6px 8px; border-bottom: 1px solid var(--line-strong); white-space: nowrap; }
.mini-tbl th.left, .mini-tbl td.left { text-align: left; }
.mini-tbl th.rel { background: var(--rel-bg); color: var(--rel-text); }
.mini-tbl td { text-align: right; padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
/* Run the outer columns flush with the card heading above. Every panel table
   started 8px right of its own heading, which is the left-edge ladder you see
   down the fund page. .heat is excluded: its cells draw their own border and
   are centred, so they need symmetric padding. */
.mini-tbl:not(.heat) th:first-child, .mini-tbl:not(.heat) td:first-child { padding-left: 0; }
.mini-tbl:not(.heat) th:last-child, .mini-tbl:not(.heat) td:last-child { padding-right: 0; }
.mini-tbl tr.rel td, .mini-tbl td.rel { background: var(--rel-tint); }
.mini-tbl .negc { color: #a32d2d; }
.mini-tbl.heat td { text-align: center; font-size: 11px; min-width: 38px; border: 1px solid var(--surface); color: var(--text); }
.mini-tbl.heat .yeartot { font-weight: 600; background: var(--bg); }
.mini-tbl.heat td.left { text-align: left; font-weight: 600; }

.fac { display: flex; align-items: center; gap: 10px; margin: 7px 0; font-size: 13px; }
.fac-l { width: 210px; color: var(--muted); }
.fac-bar { flex: 1; height: 9px; background: var(--bg); border: 1px solid var(--line); overflow: hidden; }
.fac-bar > div { height: 100%; background: var(--accent); }
.fac-v { width: 56px; text-align: right; font-weight: 600; }
.fac-v .pctlbl { font-size: 10px; color: var(--faint); font-weight: 400; margin-left: 2px; }

/* ---- Navigation: top bar links + account menu + mobile bottom tab bar ---- */
.topnav { display: flex; gap: 2px; margin-left: 14px; }
.navlink { font-size: 13px; color: var(--muted); text-decoration: none; padding: 6px 12px; white-space: nowrap; }
.navlink:hover { background: var(--bg); color: var(--text); }
.navlink.active { color: var(--accent-text); background: var(--accent-bg); font-weight: 600; }
.acct { position: relative; }
.acct-btn { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; font-size: 13px; }
.acct-ico { width: 17px; height: 17px; }
.acct-menu { position: absolute; right: 0; top: 42px; z-index: 60; background: var(--surface);
  border: 1px solid var(--line-strong); padding: 8px; min-width: 200px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.10); }
.acct-email { font-size: 12px; color: var(--muted); padding: 4px 8px 8px; border-bottom: 1px solid var(--line); margin-bottom: 6px; word-break: break-all; }
.acct-logout { width: 100%; height: 34px; }
.botnav { display: none; }
.bico { width: 22px; height: 22px; }
.mobile-only { display: none; }

@media (max-width: 720px) {
  /* One definition of the tab bar's footprint, inset included. */
  /* 59, not 58: the bar is a 58px item plus its own 1px top border, so
     reserving 58 tucked the footer's bottom edge exactly under that border.
     Measured: nav renders 59px. */
  :root { --tabbar: calc(59px + env(safe-area-inset-bottom, 0px)); --topbar-h: 53px; }
  /* The footer kept .wrap's DESKTOP box on mobile, so its content sat 17-26px
     further in than the page content above it — header, body and footer on
     three different left edges. */
  .footer-inner { max-width: 100%; padding: 16px 12px 24px; }
  .topnav { display: none; }
  .acct-btn { display: none; }        /* account lives in the bottom bar on mobile */
  .mode-pill { display: none; }
  .topbar { padding: 10px 12px; gap: 8px; }

  /* The wordmark ate 136px of a 375px bar and squeezed search down to 90px —
     too narrow to read a fund name in. The logo mark alone still identifies the
     app, and the page title is right below it. */
  .brand .brand-word, .brand .dot { display: none; }
  .fundsearch { flex: 1 1 auto; min-width: 0; }
  .fundsearch input { width: 100%; }
  .wrap { max-width: 100%; padding: 12px 12px calc(var(--tabbar) + 24px); }

  .botnav { display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 100;
    background: var(--surface); border-top: 1px solid var(--line-strong);
    padding-bottom: env(safe-area-inset-bottom, 0px); }
  .botnav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; height: 58px; font-size: 10px; color: var(--muted); background: none; border: none; text-decoration: none; }
  .botnav-item.active { color: var(--accent-text); }
  .botnav-item:hover { background: none; }
  .acct-menu { position: fixed; right: 12px; left: auto; top: auto; bottom: 66px; }
  /* toolbar menus open as a full-width sheet under the sticky header */
  .menu-panel, .menu.right .menu-panel { position: fixed; left: 10px; right: 10px; top: 62px;
    min-width: 0; max-width: none; max-height: 74vh; overflow-y: auto; }

  /* touch targets + compact controls */
  select, input, button { height: 38px; }
  .mini { height: 34px; }
  .mobile-only { display: inline-block; }
  #mSort { flex: 1; min-width: 130px; }

  /* fund list: keep TABLE ROWS, densely compressed; swipe sideways for more
     columns with the fund pinned on the left. Rows do NOT wrap into cards. */
  .tablecard { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #grid { font-size: 11px; }
  thead th { padding: 7px 6px; font-size: 10px; }
  tbody td { padding: 5px 6px; }
  /* pin the fund column while metrics scroll horizontally */
  thead th.left, tbody td.left { position: sticky; left: 0; z-index: 2;
    background: var(--surface); border-right: 1px solid var(--line-strong); max-width: 130px; }
  tbody tr:hover td.left { background: var(--hover); }
  .fund-id { font-size: 12px; }
  .fund-name { font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; }
  .add-label { display: none; }         /* compact '+' button, no label in table rows */
  .addbtn { padding: 2px 6px; }

  /* profile page compaction */
  .prof-stats-grid { grid-template-columns: repeat(2, 1fr); }
  .prof-grid2 { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .ph-ticker { font-size: 20px; }
  .optsets { flex-direction: column; }
  .fac-l { width: 128px; }
  #windowTbl, #monthlyTbl, #trailingTbl { overflow-x: auto; }   /* wide tables scroll in-card */
  #ddEpisodes, #similarBody, .peer-tbl, #rebHistory, #holdings, .alloc-tbl { overflow-x: auto; }
  .panelcard, .chartcard { overflow-x: auto; }   /* any remaining wide content scrolls in-card */
  .fld select { max-width: 58vw; }               /* long benchmark names can't push the page wide */
  .cb-editor-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
  .bench-cap { display: none; }
  .bench-val { max-width: 150px; }
  .bench-panel { min-width: 0; }
  .fundsearch { flex: 1; margin-left: 8px; min-width: 90px; }
  .fundsearch > input { width: 100%; }
  .fs-results { width: auto; left: 0; right: 0; }
  .range-inputs input[type="date"] { width: 132px; }
}

/* ---- Add to worklist / portfolio ---- */
.card-add { white-space: nowrap; }
.card-add .wl-trigger { color: var(--faint); font-size: 13px; }
.card-add .wl-trigger:hover { color: #b07a12; }
.fund-actions { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
/* Self-contained rather than leaning on the `select, input, button` base: one of
   these four is an <a> (it navigates to /alerts), and that base does not match
   anchors — so the alert action had no border, background or height and sat in
   the row as bare link text. */
.fund-act {
  display: inline-flex; align-items: center; gap: 7px;
  height: 36px; padding: 0 14px; font-size: 13px; line-height: 1;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line-strong);
  cursor: pointer; text-decoration: none; white-space: nowrap;
}
.fund-act:hover { background: var(--hover); }
.fund-act .fa-ico { flex: none; opacity: .75; }
/* Any control carrying an icon lays it out the same way, wherever it lives —
   .menu-item in a dropdown, .mini in a toolbar, .fund-act in an action row. One
   rule so a new iconed button does not have to reinvent the alignment. */
.menu-item:has(> .fa-ico), button:has(> .fa-ico), a:has(> .fa-ico) {
  display: inline-flex; align-items: center; gap: 7px;
}
.menu-item > .fa-ico { flex: none; opacity: .7; }
.fa-ico { vertical-align: -2px; }
.fund-act:hover .fa-ico { opacity: 1; }
.fund-act.wl-trigger { color: var(--accent-text); border-color: #bfe6d7; }
.fund-act.wl-trigger .fa-ico { opacity: .9; }
.wl-pop { position: absolute; z-index: 200; background: var(--surface); border: 1px solid var(--line-strong);
padding: 6px; min-width: 190px; max-width: 80vw; max-height: 300px; overflow-y: auto;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); }
.wl-pop-h { font-size: 11px; color: var(--muted); padding: 4px 8px 6px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.wl-pop-item { display: block; width: 100%; text-align: left; border: none; background: none; padding: 8px 10px; font-size: 13px; color: var(--text); height: auto; }
.wl-pop-item:hover { background: var(--bg); }
.wl-pop-new { color: var(--accent-text); border-top: 1px solid var(--line); margin-top: 4px; }
.wl-pop-empty { font-size: 12px; color: var(--faint); padding: 6px 10px; }
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%) translateY(20px);
  background: #1f1e1b; color: #fff; padding: 10px 16px; font-size: 13px; z-index: 300;
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25); }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* AFTER the base rule, not before it. The mobile clearance used to live higher
   up the file, so `.toast { bottom: 24px }` overrode it right back and the
   toast rendered behind the tab bar on every phone. */
@media (max-width: 720px) { .toast { bottom: calc(var(--tabbar) + 16px); } }

/* Blends list page */
.page-h { font-size: 26px; font-weight: 600; margin: 0 0 6px; letter-spacing: -0.02em; }
/* The one-line description under a page title. It was inline `class="muted-sm"
   style="margin-bottom:14px"` on four pages — 11px faint text — while the policy
   pages used .info-lead at 16px muted, for the same role. One class, sized
   between the two. */
.page-lead { font-size: 13px; color: var(--muted); line-height: 1.55;
  margin: 0 0 var(--gap-block); max-width: 760px; }
.blend-list { display: flex; flex-direction: column; gap: 8px; }
.blend-card { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--line);
padding: var(--pad-row); flex-wrap: wrap; }
.blend-name { font-weight: 600; font-size: 15px; color: var(--accent-text); text-decoration: none; min-width: 120px; }
.blend-name:hover { text-decoration: underline; }
.blend-summary { color: var(--muted); font-size: 13px; flex: 1; min-width: 160px; }

/* Monte Carlo caveats — a projection handed to a client must carry the reasons
   it should be read with suspicion, next to the number, not in a tooltip. */
.mc-caveat {
  margin: 12px 0 0; padding: 12px 14px; font-size: 13.5px; line-height: 1.55;
  border-left: 3px solid var(--muted); background: var(--panel, transparent);
}
.mc-caveat.warn { border-left-color: #b0641a; }
.mc-caveat strong { display: block; margin-bottom: 5px; font-size: 12px;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.mc-caveat ul { margin: 0; padding-left: 18px; }
.mc-caveat li { margin-bottom: 4px; }
.mc-caveat li:last-child { margin-bottom: 0; }

/* A row backed by very little history. The number is not wrong, but it is not
   comparable to a ten-year one sitting beside it under the same heading. */
.hist-thin { color: #b0641a; font-weight: 600; }

/* Marks a row whose history has had corrupted months removed. The gap is the
   honest state, but it costs the fund its category rank, so say why. */
.scrub-mark { color: #b0641a; font-weight: 700; margin-left: 1px; }

/* Comparison of funds with materially different histories. Every metric in the
   table is computed over each fund own months, so this is not cosmetic. */
.cmp-warn {
  margin: 10px 0 0; padding: 10px 13px; font-size: 13px; line-height: 1.5;
  border-left: 3px solid #b0641a; background: var(--panel, transparent);
}
.cmp-warn strong { color: #b0641a; }

/* ===== Fund page loading state =====
   As shipped the fund page is 1,573px tall and 5,643px once data lands — a
   4,070px jump, 4.5 viewport-heights, with ten chart cards sitting as empty
   titled boxes for the whole of it. On mobile the same jump is 5.9 screens.

   The charts are reserved by ASPECT RATIO, from the same viewBox the SVG is
   drawn at (measured: rendered ratio == viewBox ratio, exactly, and every W/H
   in fund.js is a literal constant). Fixed pixel heights would be wrong — the
   growth chart is 361px at 1280 and 100px at 375.

   .chart-slot is deliberately NOT a loading-only rule. It applies while
   loading, once the chart is drawn, and when a chart has no data and renders
   "Not enough history" instead. All three states occupy the same box, so the
   page cannot jump when data lands or collapse when it turns out to be absent.

   Nothing is reserved for #peerCard or #crisisSec. Both hide themselves
   entirely (fund.js:173, fund.js:257), and #crisisChart's height is one row per
   episode, so it is not knowable in advance. Reserving space for a card that
   then vanishes collapses the page under the reader after they have started
   reading — a worse failure than the growth it would prevent. Under-reserve.

   Under-reserving is not only about cards that vanish. #styleCard shipped
   reserving 316px against a branch that renders 79.5px, and it was invisible on
   a desktop because .prof-grid2 is two-column above 820px and #riskCard's own
   316px held the row. Below 820px the two stack, each card stands on its own,
   and the page collapsed 236px. Check a panel reservation at the width where
   its grid stops covering for it, not just at 1280. */
.chart-slot { aspect-ratio: var(--ar); display: flex; flex-direction: column; justify-content: center; }
.chart-slot > .tschart { width: 100%; }
#growthChart   { --ar: 760 / 240; }
#ddChart       { --ar: 760 / 150; }
#rollChart     { --ar: 760 / 160; }
#rollCorrChart { --ar: 760 / 180; }
#calChart      { --ar: 480 / 200; }
.chart-slot > .skel-block { flex: 1; min-height: 0;}

/* Line skeletons for the tables and panels, in the screener's visual language
   (.sk-bar) so the two loading states read as one product. The 26px margin puts
   the pitch at 35px, which is the real row pitch of these tables — that is what
   makes the reserved height land on the real height instead of near it. */
.sk-lines .sk-bar { margin: 0 0 26px; }
.sk-lines .sk-bar:last-child { margin-bottom: 0; }
.sk-lines .sk-bar:nth-child(3n)   { width: 82%; }
.sk-lines .sk-bar:nth-child(3n+1) { width: 95%; }
.sk-lines .sk-bar:nth-child(3n+2) { width: 88%; }
/* riskCard and styleCard ship with no heading — their render writes the <h4>
   too — so their skeleton has to stand in for the title as well. */
/* Two selectors, and it must come after the nth-child rules above. The bare
   .sk-title is for #statCards, whose heading bar is not inside a .sk-lines. The
   qualified one is for riskCard/styleCard, where the heading bar IS the first
   child of a .sk-lines and so is also matched by :nth-child(3n+1) at equal
   specificity — without this it inherited that rule's 95% and read as a rule
   across the panel rather than a heading. */
.sk-title,
.sk-lines .sk-bar.sk-title { width: 42%; height: 12px; margin-bottom: 20px; }

/* ===== Feedback widget =====
   A floating report button, present on every app and policy page via _footer.
   Sits clear of the mobile tab bar (.botnav is 58px tall plus the safe-area
   inset below 720px) so it never covers a nav target, and is .noprint so it
   cannot appear on a printed tearsheet. */
.fb-fab {
  position: fixed; right: 18px; bottom: 18px; z-index: 300;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 14px; cursor: pointer;
  background: var(--accent); color: #fff; border: 1px solid transparent;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
  font-size: 13px; font-weight: 600; line-height: 1;
}
.fb-fab:hover { filter: brightness(1.06); }
.fb-fab:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.fb-panel {
  position: fixed; right: 18px; bottom: 74px; z-index: 300;
  width: min(360px, calc(100vw - 36px));
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
  padding: 14px; display: flex; flex-direction: column; gap: 9px;
}
/* `display: flex` on a class beats the [hidden] attribute's `display: none`,
   which is a bare attribute selector — so without this the panel renders open
   on every page load. */
.fb-panel[hidden] { display: none; }
.fb-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fb-head strong { font-size: 14px; }
.fb-x { background: none; border: none; font-size: 20px; line-height: 1; cursor: pointer;
        color: var(--muted); padding: 0 4px; }
.fb-x:hover { color: var(--text); }
.fb-seg { align-self: stretch; }
.fb-seg button { flex: 1; }
.fb-label { font-size: 12px; color: var(--muted); }
.fb-panel textarea {
  width: 100%; resize: vertical; min-height: 92px; padding: 8px 10px;
  border: 1px solid var(--line);
  background: var(--bg); color: var(--text); font: inherit; font-size: 13px;
}
.fb-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fb-foot .muted-sm { flex: 1; }
.fb-ok { color: var(--accent); }
.fb-err { color: #a32d2d; }
:root[data-theme="dark"] .fb-err { color: #ef9a9a; }

@media (max-width: 720px) {
  /* clear the tab bar: 58px + the device's own inset */
  .fb-fab { bottom: calc(var(--tabbar) + 14px); right: 14px; }
  .fb-panel { bottom: calc(var(--tabbar) + 70px); right: 14px; }
  .fb-fab-label { display: none; }          /* icon only where width is scarce */
  .fb-fab { padding: 12px; }
}

/* The fund page's free-text benchmark box, when what was typed could not be
   resolved. The server falls back to the default benchmark rather than failing,
   which is right for rendering but reads as the app ignoring you. */
.bench-warn { color: #a32d2d; font-size: 12px; align-self: center; max-width: 34ch; line-height: 1.25; }
:root[data-theme="dark"] .bench-warn { color: #ef9a9a; }
.bench-custom.is-bad { border-color: #a32d2d; }

/* ===== Landing page =====
   Deliberately built from the product's own primitives — .panelcard, .stat,
   .mini-tbl, .fund-act — rather than a separate marketing style sheet. A visitor
   who signs up should recognise the thing they just read about. Square corners,
   one accent, system fonts, dense tables: the same language as the app. */
.lp-navspace { flex: 1; }
.lp-wrap { max-width: min(1180px, 92vw); }

.lp-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 40px; align-items: center; padding: 34px 0 40px;
}
.lp-eyebrow { font-size: 12px; color: var(--muted); letter-spacing: .02em; margin: 0 0 12px;
  text-transform: uppercase; }
.lp-h1 { font-size: 42px; line-height: 1.12; letter-spacing: -0.03em; margin: 0 0 16px; font-weight: 700; }
.lp-lead { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0 0 22px; max-width: 56ch; }
.lp-lead b { color: var(--text); font-weight: 600; }
.lp-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.lp-cta { background: var(--accent); color: #fff; border-color: var(--accent); }
.lp-cta:hover { background: #18604b; }
.lp-cta-lg { height: 42px; padding: 0 18px; font-size: 14px; }
.lp-fineprint { font-size: 12px; color: var(--faint); margin: 14px 0 0; }

/* a framed slab of real product chrome */
.lp-shot { margin: 0; border: 1px solid var(--line-strong); background: var(--surface); }
.lp-shot-cap { font-size: 12px; font-weight: 600; color: var(--muted);
  padding: 9px 14px; border-bottom: 1px solid var(--line); background: var(--bg); }
/* The mock table is 7 nowrap columns. Real cards get `overflow-x: auto` at the
   mobile breakpoint; this frame is not a card, so without its own it pushed the
   whole page 103px wide on a phone. Scroll inside the frame, as the app does. */
.lp-shot-body { padding: 14px 16px; overflow-x: auto; }
.lp-tbl { width: 100%; font-size: 12.5px; }
.lp-illus { font-size: 11px; color: var(--faint); margin: 10px 0 0; }
.lp-count { font-size: 13px; margin: 0; line-height: 1.7; }

.lp-stats { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--gap-sm);
  margin: 0 0 44px; }
.lp-stats .stat .k { font-size: 11px; }
.lp-stats .stat .v { font-size: 19px; font-variant-numeric: tabular-nums; }

.lp-sec { padding: 0 0 44px; }
.lp-h2 { font-size: 26px; letter-spacing: -0.02em; margin: 0 0 8px; font-weight: 700; }
.lp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: var(--gap-block); margin-top: 20px; }
.lp-card p { color: var(--muted); font-size: 13.5px; line-height: 1.6; margin: 0; }

.lp-honest { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 40px; align-items: start; }
.lp-list { margin: 18px 0 0; padding: 0; list-style: none; }
.lp-list li { position: relative; padding: 0 0 12px 20px; font-size: 13.5px;
  line-height: 1.6; color: var(--muted); }
.lp-list li::before { content: ""; position: absolute; left: 0; top: 8px;
  width: 7px; height: 7px; background: var(--accent); }
.lp-list b { color: var(--text); font-weight: 600; }

.lp-close { border-top: 1px solid var(--line); padding: 36px 0 8px; text-align: center; }
.lp-close .lp-lead { margin-left: auto; margin-right: auto; }
.lp-close .lp-actions { justify-content: center; }

@media (max-width: 900px) {
  .lp-hero, .lp-honest { grid-template-columns: 1fr; gap: 26px; }
  .lp-h1 { font-size: 32px; }
  .lp-stats { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 560px) {
  .lp-stats { grid-template-columns: repeat(2, 1fr); }
  .lp-h1 { font-size: 27px; }
  /* the marketing nav has more links than fit a phone; keep the two that matter */
  .lp .topnav, .lp .navlink[href="/methodology"], .lp .navlink[href="/security"] { display: none; }
}

/* ===== White paper (methodology) =====
   A reference document, not a marketing page: a measured column, a serif body
   for sustained reading, sans for anything a reader scans rather than reads
   (headings, labels, tables), and section and table numbers generated by CSS
   counters so they can never drift out of sequence when a section is added. */
.wp { counter-reset: wpsec wptbl; max-width: 74ch; }
.wp p, .wp li {
  font-family: Georgia, "Iowan Old Style", "Times New Roman", Times, serif;
  font-size: 15.5px; line-height: 1.68; color: var(--text);
}
.wp b { font-weight: 700; }

.wp-head { border-bottom: 2px solid var(--text); padding-bottom: 16px; margin-bottom: 22px; }
.wp-kicker { font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 6px; font-family: inherit; }
.wp-title { font-size: 30px; letter-spacing: -0.02em; margin: 0 0 6px; font-weight: 700; }
.wp-sub { font-size: 15px; color: var(--muted); margin: 0 0 16px; max-width: 60ch; }
.wp-meta { display: flex; flex-wrap: wrap; gap: 0 28px; margin: 0; }
.wp-meta div { display: flex; gap: 7px; align-items: baseline; }
.wp-meta dt { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.wp-meta dd { margin: 0; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }

.wp-abstract { border-left: 3px solid var(--accent); padding: 2px 0 2px 16px; margin: 0 0 26px; }
.wp-abstract p { margin: 0; }

.wp-toc { border: 1px solid var(--line); background: var(--bg); padding: 14px 18px; margin: 0 0 30px; }
.wp-toc-h { font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 8px; font-family: inherit; }
.wp-toc ol { margin: 0; padding-left: 22px; }
.wp-toc li { font-size: 14px; line-height: 1.9; font-family: inherit; }
.wp-toc a { color: var(--text); text-decoration: none; }
.wp-toc a:hover { color: var(--accent-text); text-decoration: underline; }

/* Numbered sections. The number is generated, so inserting a section renumbers
   the document rather than leaving a stale hand-typed digit behind. */
.wp-sec { counter-increment: wpsec; margin: 0 0 30px; scroll-margin-top: calc(var(--topbar-h) + 16px); }
.wp-sec > h3 {
  font-size: 19px; font-weight: 700; letter-spacing: -0.01em;
  margin: 0 0 12px; padding-bottom: 7px; border-bottom: 1px solid var(--line);
}
.wp-sec > h3::before { content: counter(wpsec) ".  "; color: var(--muted); font-variant-numeric: tabular-nums; }
.wp-sec p { margin: 0 0 12px; }

.wp-points { margin: 0 0 12px; padding-left: 24px; }
.wp-points li { margin-bottom: 9px; }

/* Numbered table captions, above the table as in a printed paper. */
.wp-cap { counter-increment: wptbl; font-family: inherit !important; font-size: 12px !important;
  color: var(--muted); margin: 18px 0 7px !important; }
.wp-tbl { font-size: 13px; }
.wp-tbl td { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
.wp-tbl tr > td:first-child { font-weight: 600; white-space: normal; }
.wp-note { font-size: 13px !important; color: var(--muted); border-top: 1px solid var(--line);
  padding-top: 12px; margin-top: 18px !important; }

@media (max-width: 720px) {
  .wp p, .wp li { font-size: 15px; }
  .wp-title { font-size: 24px; }
  .wp-meta { gap: 0 18px; }
}
@media print {
  .wp { max-width: 100%; }
  .wp-toc { break-inside: avoid; }
  .wp-sec { break-inside: avoid-page; }
}
