/* styles.css -- Direction-B UI layer (Lucian, Phase 5+, frontend-contract build).
   Token set + shared components copied verbatim from the approved combined
   mockup (.../scratchpad/levels-planner-mockup.html), which itself copied
   them verbatim from oconnor-mortgage-planning-v2.html lines 13-95 (Design
   Spec token contract). App-specific component classes (login/setup/
   settings/forms/tables/banners) are new, built within the same palette --
   no ad-hoc colors. M8: externalized here -- no inline style attribute
   anywhere in index.html or app.js (CSP style-src 'self', no inline styles
   permitted); the handful of dynamic width/height values app.js sets at
   runtime (meter fills, SVG points) go through the element.style CSSOM
   API, which is unaffected by style-src since it never touches the HTML
   `style` attribute or a `<style>` element. */

/* ============================================================
   THEME TOKENS -- light (default) + dark via prefers-color-scheme,
   with manual :root[data-theme] override in both directions.
   ============================================================ */
:root{
  --bg:#f6f3ec; --paper:#fffdf9; --paper-alt:#efeadc;
  --ink:#1b1f23; --ink-2:#343b41; --muted:#5e6063;
  --line:#ddd5c1; --line-strong:#c8bd9f;
  --field-border:#857d6a; --mix-cash:#8a826f; /* ruled 2026-11-13 (Vesta) */
  --disabled-bg:var(--paper-alt); --disabled-fg:var(--muted); --disabled-border:var(--line-strong);

  --accent:#0d4a44; --accent-ink:#f8f6ee; --accent-bg:#e2efec; --accent-bg-strong:#c7e2db;

  --confirmed:#2a6a45; --confirmed-bg:#e5f1e8;
  --assume:#865b13;    --assume-bg:#faf0d8;
  --derived:#3c5b83;   --derived-bg:#e6edf6;
  --danger:#8a1f28;    --danger-bg:#f8e6e5;
  --ok:#2a6a45; --warn:#865b13;

  --shadow-sm:0 1px 2px rgba(24,20,10,.06);
  --shadow-md:0 4px 16px rgba(24,20,10,.07);

  --font-display:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
  --font-body:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --font-mono:ui-monospace,"SF Mono","Cascadia Code","Roboto Mono",Menlo,Consolas,monospace;

  color-scheme: light;

  /* UX pass 1 (2026-11-13): scales that alias GL-003 values (section 3.2 type, section 4 spacing,
     radius). Radius 4 / 8 / 24 (+ pill) and --text-meta 13px (muted metadata only, never below 13px)
     ruled 2026-11-13 (Vesta). Theme-independent, so declared once here. */
  --text-page:28px;      /* page title, display serif */
  --text-section:22px;   /* = GL-003 --text-h3 */
  --text-card:18px;      /* = GL-003 --text-h4 */
  --text-body:16px;      /* = GL-003 --text-body, prose */
  --text-dense:14px;     /* = GL-003 --text-small, rows, tables, buttons */
  --text-meta:13px;      /* metadata lines */
  --text-caption:12px;   /* = GL-003 --text-caption, eyebrows, field labels, chips */
  --text-figure:40px;    /* = GL-003 --text-h1 size, hero figures */
  --space-xs:4px; --space-sm:8px; --space-md:16px; --space-lg:24px; --space-xl:32px; --space-2xl:48px;
  /* Radius scale pinned 2026-11-13 (QA-1): 4 inputs and chips, 8 buttons and cards, 24 sheets. Vesta to rule on the Levels profile. */
  --radius-sm:4px; --radius-md:8px; --radius-lg:24px; --radius-pill:999px;
  --control-h:40px; --control-h-touch:44px; --control-h-sm:32px;
  --appbar-h:56px;
  /* Media token (Vesta Design Spec D3, 2026-11-14; pending Brendan ratification per GL-003): equals the pixel baked into
     intro-poster-phone.png and manifest theme_color; changes only when the poster is re-rendered. Theme-independent. */
  --media-poster-bg:#0d4a44;
}
@media (prefers-color-scheme: dark){
  :root{
    --bg:#14171a; --paper:#1a1e22; --paper-alt:#20252a;
    --ink:#e8e5db; --ink-2:#c7c3b8; --muted:#a0a5ab;
    --line:#2c3237; --line-strong:#3c444b;
    --field-border:#737b83; --mix-cash:#8b9096; /* ruled 2026-11-13 (Vesta) */
  --disabled-bg:var(--paper-alt); --disabled-fg:var(--muted); --disabled-border:var(--line-strong);
    --accent:#3fae9d; --accent-ink:#0a1310; --accent-bg:#173330; --accent-bg-strong:#1f463f;
    --confirmed:#54b47c; --confirmed-bg:#16311f;
    --assume:#dba845;    --assume-bg:#332a11;
    --derived:#86aad9;   --derived-bg:#1d2c3f;
    --danger:#e17178;    --danger-bg:#391a1c;
    --ok:#54b47c; --warn:#dba845;
    --shadow-sm:0 1px 2px rgba(0,0,0,.3); --shadow-md:0 6px 20px rgba(0,0,0,.35);
    color-scheme: dark;
  }
}
:root[data-theme="dark"]{
  --bg:#14171a; --paper:#1a1e22; --paper-alt:#20252a;
  --ink:#e8e5db; --ink-2:#c7c3b8; --muted:#a0a5ab;
  --line:#2c3237; --line-strong:#3c444b;
  --field-border:#737b83; --mix-cash:#8b9096; /* ruled 2026-11-13 (Vesta) */
  --disabled-bg:var(--paper-alt); --disabled-fg:var(--muted); --disabled-border:var(--line-strong);
  --accent:#3fae9d; --accent-ink:#0a1310; --accent-bg:#173330; --accent-bg-strong:#1f463f;
  --confirmed:#54b47c; --confirmed-bg:#16311f;
  --assume:#dba845;    --assume-bg:#332a11;
  --derived:#86aad9;   --derived-bg:#1d2c3f;
  --danger:#e17178;    --danger-bg:#391a1c;
  --ok:#54b47c; --warn:#dba845;
  color-scheme: dark;
}
:root[data-theme="light"]{
  --bg:#f6f3ec; --paper:#fffdf9; --paper-alt:#efeadc;
  --ink:#1b1f23; --ink-2:#343b41; --muted:#5e6063;
  --line:#ddd5c1; --line-strong:#c8bd9f;
  --field-border:#857d6a; --mix-cash:#8a826f; /* ruled 2026-11-13 (Vesta) */
  --disabled-bg:var(--paper-alt); --disabled-fg:var(--muted); --disabled-border:var(--line-strong);
  --accent:#0d4a44; --accent-ink:#f8f6ee; --accent-bg:#e2efec; --accent-bg-strong:#c7e2db;
  --confirmed:#2a6a45; --confirmed-bg:#e5f1e8;
  --assume:#865b13;    --assume-bg:#faf0d8;
  --derived:#3c5b83;   --derived-bg:#e6edf6;
  --danger:#8a1f28;    --danger-bg:#f8e6e5;
  --ok:#2a6a45; --warn:#865b13;
  color-scheme: light;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.55 var(--font-body);}
::selection{background:var(--accent-bg-strong);color:var(--ink)}
a{color:var(--accent)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
[hidden]{display:none !important}
button{font-family:inherit}

/* ---------- Masthead ---------- */

.theme-toggle,.icon-btn{border:1px solid var(--line-strong);background:var(--paper-alt);color:var(--ink-2);font-family:var(--font-body);font-size:var(--text-caption);letter-spacing:.06em;text-transform:uppercase;padding:7px 12px;border-radius:6px;cursor:pointer;flex:none}
.theme-toggle:hover,.icon-btn:hover{background:var(--accent-bg)}

/* ---------- Sync indicator ---------- */
.sync-indicator{display:inline-flex;align-items:center;gap:6px;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.sync-indicator .dot{width:8px;height:8px;border-radius:50%;background:var(--muted);flex:none}
.sync-indicator[data-state="saved"] .dot{background:var(--confirmed)}
.sync-indicator[data-state="saving"] .dot{background:var(--derived);animation:pulse 1s ease-in-out infinite}
.sync-indicator[data-state="conflict"] .dot{background:var(--danger)}
.sync-indicator[data-state="offline"] .dot{background:var(--assume)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}

/* ---------- Banners ---------- */
.banner{border-top:1px solid var(--line);border-bottom:2px solid var(--assume);background:var(--assume-bg)}
.banner-inner{max-width:1180px;margin:0 auto;padding:11px 24px;display:flex;gap:12px;align-items:flex-start}
.banner .glyph{flex:none;width:20px;height:20px;border-radius:50%;background:var(--assume);color:var(--paper);display:flex;align-items:center;justify-content:center;font-family:var(--font-body);font-weight:700;font-size:var(--text-caption)}
.banner p{margin:0;font-size:var(--text-meta);color:var(--ink-2)}
.banner strong{color:var(--assume)}
.banner.danger{border-bottom-color:var(--danger);background:var(--danger-bg)}
.banner.danger .glyph{background:var(--danger)}
.banner.danger strong{color:var(--danger)}
.banner.info{border-bottom-color:var(--derived);background:var(--derived-bg)}
.banner.info .glyph{background:var(--derived)}
.banner.info strong{color:var(--derived)}
.banner button.link-btn{margin-left:auto;flex:none}

/* ---------- Tab nav ---------- */
nav.tabnav{display:flex;gap:4px;max-width:1180px;margin:0 auto;padding:0 20px;border-bottom:1px solid var(--line);overflow-x:auto;background:var(--paper)}
nav.tabnav button,nav.tabnav a{appearance:none;background:none;border:none;border-bottom:3px solid transparent;padding:14px 18px 12px;font-family:var(--font-body);font-size:var(--text-dense);font-weight:700;color:var(--muted);cursor:pointer;white-space:nowrap;text-decoration:none}
nav.tabnav button[aria-selected="true"],nav.tabnav a[aria-current="page"]{color:var(--ink);border-bottom-color:var(--accent)}
nav.tabnav button:hover,nav.tabnav a:hover{color:var(--ink)}
/* Mobile scroll-affordance fade (Lector cold-read, 2026-08-11): at narrow
   widths the tab strip overflows (overflow-x:auto above) and the last tab
   clips mid-glyph at the viewport edge with no cue that more tabs exist
   off-screen -- reads as truncated, not scrollable. A right-edge fade
   signals "keep scrolling." Static (not scroll-position-aware -- doesn't
   remove itself once fully scrolled to the end); acceptable for a low-risk
   CSS-only affordance, matches this file's existing max-width:640px
   breakpoint convention (see .tx-scroll-hint above). */
@media (max-width:640px){
  nav.tabnav{-webkit-mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 0,#000 calc(100% - 28px),transparent 100%)}
}

/* ---------- Layout ---------- */
.wrap{max-width:1180px;margin:0 auto;padding:26px 20px 90px}
.section-head{margin-bottom:20px}
.section-head h2{font-family:var(--font-display);font-weight:600;font-size:var(--text-section);margin:0 0 6px;color:var(--ink)}
.section-head .sub{color:var(--muted);font-size:var(--text-dense);max-width:70ch;margin:0 0 16px}
.eyebrow{font-family:var(--font-body);font-size:var(--text-caption);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}

/* ---------- Cards ---------- */
.card{background:var(--paper);border:1px solid var(--line);border-radius:10px;padding:22px 24px;margin:18px 0;box-shadow:var(--shadow-sm)}
/* UX pass 3, finding 18: a left stripe is a signal, never decoration. accent = the one next step, danger = destructive, assume = warning. */
.card.stripe-accent{border-left:3px solid var(--accent)}
.card.stripe-assume{border-left:3px solid var(--assume)}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px}
.kpi{border:1px solid var(--line);border-radius:9px;padding:13px 15px;background:var(--paper-alt)}
.kpi .lab{font-family:var(--font-body);font-size:var(--text-caption);font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.kpi .val{font-family:var(--font-display);font-size:var(--text-section);font-weight:700;margin-top:3px;color:var(--ink);font-variant-numeric:tabular-nums}
.kpi .note{font-size:var(--text-caption);color:var(--muted);margin-top:4px;line-height:1.4}

/* ---------- Direction-B ladder ---------- */
.hero-rung-b{display:flex;align-items:center;gap:18px;background:var(--paper);border:1px solid var(--line);border-radius:14px;padding:18px 22px;margin-bottom:26px;box-shadow:var(--shadow-sm);flex-wrap:wrap}
.hero-rung-b .medallion{width:56px;height:56px;font-size:var(--text-section)}
.hero-rung-b .hero-text .eyebrow{margin-bottom:2px}
.hero-rung-b .hero-figure{font-family:var(--font-display);font-size:var(--text-page);color:var(--ink);font-variant-numeric:tabular-nums}
.hero-rung-b .relock-note{font-size:var(--text-caption);color:var(--warn);margin-top:3px}
.hero-rung-b .chip{margin-left:auto}

.tier-group{margin:30px 0}
/* QA-2 item 1: an empty tier is one 56px line; a closed assumptions card; slider value beside its label */
.tier-group.is-empty{margin:var(--space-sm) 0;padding:var(--space-sm) var(--space-md);border:1px solid var(--line);border-radius:10px;background:var(--paper)}
.tier-group.is-empty .tier-group-head{margin-bottom:0;min-height:40px}
.tier-group.is-empty .tier-goals{display:none}
.tier-group.is-empty .medallion{width:32px;height:32px;font-size:var(--text-meta)}
.tier-group.is-empty .tier-index{display:none}
.tier-group.is-empty .tier-copy .tier-name{font-size:var(--text-dense);margin:0}
.tier-group-head .tier-empty{font-size:var(--text-meta);color:var(--muted)}
.tier-group-head .add-goal-btn{margin-left:auto}
.assumptions > summary{cursor:pointer;font:600 14px/1.4 var(--font-body);color:var(--ink);list-style-position:inside}
.assumptions > summary:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.slider-label{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-sm)}
.slider-label .range-value{font-size:var(--text-meta)}
.chip.chip-plain{text-transform:none;letter-spacing:0}
.tier-group-head{display:flex;align-items:center;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.tier-group-head .tier-copy .tier-index{display:block;font-family:var(--font-body);font-size:var(--text-caption);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.tier-group-head .tier-copy .tier-name{font-family:var(--font-display);font-size:var(--text-card);color:var(--ink);font-weight:600}

.medallion{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-weight:700;font-size:var(--text-card);flex:none;border:2px solid}
.medallion.tier-0{background:var(--paper-alt);color:var(--ink-2);border-color:var(--line-strong)}
.medallion.tier-1{background:var(--derived-bg);color:var(--derived);border-color:var(--derived)}
.medallion.tier-2{background:var(--assume-bg);color:var(--assume);border-color:var(--assume)}
.medallion.tier-3{background:var(--accent-bg);color:var(--accent);border-color:var(--accent)}

.tier-goals{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}
.goal-card{background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:18px 20px;box-shadow:var(--shadow-sm)}
.goal-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:12px}
.goal-card h4{margin:0;font-family:var(--font-display);font-size:var(--text-body);color:var(--ink);font-weight:600}
.goal-card-actions{display:flex;gap:6px;margin-top:12px}
.goal-card-actions button{font-size:var(--text-caption);padding:5px 9px}

/* Bug A fix (Lucian, 2026-08-11): inline-on-card goal editing. The card
   being edited spans the full tier-goals grid row (instead of being
   squeezed into one grid cell) so the three form fields lay out
   comfortably, and it stays visually anchored right where "Edit" was
   clicked -- never off-screen. Composes the existing card/form tokens
   (.eyebrow, .form-grid, .auth-actions) rather than inventing new ones. */
.goal-card.editing{grid-column:1/-1;border-color:var(--accent)}
.goal-card.editing .eyebrow{margin-bottom:10px}

.chip{font-family:var(--font-body);font-size:var(--text-caption);font-weight:600;letter-spacing:.06em;text-transform:uppercase;padding:4px 10px;border-radius:999px;white-space:nowrap;flex:none;border:none}
.chip.unlocked{background:var(--confirmed-bg);color:var(--confirmed)}
.chip.locked{background:var(--paper-alt);color:var(--muted);border:1px solid var(--line-strong)}

.goal-costs{display:flex;gap:18px;margin-bottom:14px;flex-wrap:wrap}
.goal-costs div{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.goal-costs strong{display:block;color:var(--ink);font-size:var(--text-body);font-family:var(--font-display);text-transform:none;letter-spacing:0;font-variant-numeric:tabular-nums;margin-top:2px}

.meter{height:8px;border-radius:999px;background:var(--paper-alt);border:1px solid var(--line);overflow:hidden;margin-top:2px}
.meter > span{display:block;height:100%;background:var(--accent);border-radius:999px 0 0 999px}
.meter-label{display:flex;justify-content:space-between;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);margin-top:7px}

/* ---------- Projection chart ---------- */
/* Class B fix (2026-08-11, Lucian): the chart's axis-label text lives in
   SVG user-space units, so letting the svg shrink to 100% of a narrow
   mobile card (as small as ~280px) scaled every label down to ~4px --
   present in the DOM/aria-label but functionally unreadable, which fails
   the same "nothing can be read off this chart" bar the missing labels
   did. min-width holds the svg at a legible physical size; the wrap
   scrolls horizontally on viewports narrower than that (standard pattern
   for a dense 40-year trajectory) instead of shrinking text into noise.
   Unaffected on desktop, where the card is already wider than min-width. */
#projection-chart-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.chart-card svg{width:100%;min-width:680px;height:auto;display:block}
.chart-legend{display:flex;gap:18px;flex-wrap:wrap;font-size:var(--text-caption);color:var(--muted);margin-top:12px}
.chart-legend .item{display:flex;align-items:center}
.chart-legend .dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:6px;flex:none}

/* ---------- Tables (mortgage schedule) ---------- */
.table-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:8px;-webkit-overflow-scrolling:touch;max-height:520px}
table{border-collapse:collapse;width:100%;font-size:var(--text-dense);margin:0;min-width:640px}
th,td{text-align:left;padding:8px 11px;border-bottom:1px solid var(--line);white-space:nowrap}
th:first-child,td:first-child{white-space:normal}
/* QA-1 item 2: monospace only on numeric cells (.num), never on payee, category, account or symbol */
.num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;white-space:nowrap}
th.num,td.num{text-align:right}
thead th{position:sticky;top:0;background:var(--paper-alt);font-size:var(--text-caption);color:var(--muted);border-bottom:2px solid var(--line-strong);font-family:var(--font-body);text-transform:uppercase;letter-spacing:.06em;font-weight:700;z-index:1}
tbody tr:last-child td{border-bottom:none}
tr.row-locked-point td{background:var(--accent-bg)}

/* ---------- Transactions table (Budgeting tab) -- scoped via .tx-table so
   the mortgage-schedule table above (same generic .table-scroll/table
   classes, unrelated columns) is unaffected. Fixes three linked defects
   found via computed-style probe against the real dry-run feed:
   BUG#1 (AMOUNT column clipped mid-glyph at 1280px -- PAYEE/CATEGORY/
   ACCOUNT were unconstrained-nowrap and grew to their longest real value,
   e.g. ACCOUNT hit 379px on "TreasuryDirect -- Savings Bonds", pushing the
   table 14px past its .table-scroll box so AMOUNT's right edge sat past
   the visible/clipped boundary) and the DATE-column item (10-char dates
   wrapped onto 3 lines at 1280 because DATE was the one column still
   carrying the generic first-child white-space:normal rule, so the
   browser's auto table-layout treated it as the "compressible" column
   and starved it below its own single-line content width while
   PAYEE/CATEGORY/ACCOUNT held large excess whitespace). */
.tx-table th:first-child,.tx-table td:first-child{white-space:nowrap;min-width:96px}
.tx-table th:nth-child(2),.tx-table td:nth-child(2){max-width:190px;overflow:hidden;text-overflow:ellipsis}
.tx-table th:nth-child(3),.tx-table td:nth-child(3){max-width:150px;overflow:hidden;text-overflow:ellipsis}
.tx-table th:nth-child(4),.tx-table td:nth-child(4){max-width:170px;overflow:hidden;text-overflow:ellipsis}
.tx-table th:nth-child(5),.tx-table td:nth-child(5){min-width:96px}

/* BUG#2 follow-through: even after the column caps above, five real
   columns still won't all fit at a 375px viewport -- .table-scroll's
   overflow-x:auto already scrolls correctly (verified: it does NOT force
   page-level overflow, the real 375px overflow culprit was the filter
   <select> elements above, fixed separately), it just had no visible
   affordance telling a household reader that more columns exist off-
   screen. Shown only at narrow widths -- at desktop the column caps above
   already make the table fit without scrolling, so the hint would be
   noise there. */
.tx-scroll-hint{display:none}
@media (max-width:640px){
  .tx-scroll-hint{display:block}
}

/* ---------- Forms ---------- */
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}
.field{display:flex;flex-direction:column;gap:5px}
.field label{font-family:var(--font-body);font-size:var(--text-caption);font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.field .hint{font-size:var(--text-caption);color:var(--muted);line-height:1.4}
.field input[type="text"],.field input[type="number"],.field input[type="date"],.field input[type="password"],.field select{
  border:1px solid var(--field-border);border-radius:6px;padding:9px 10px;background:var(--paper);color:var(--ink);font:14px var(--font-body)}
.field input:focus-visible,.field select:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* click-through #8: Chromium does not always match :focus-visible on a date input (focus sits in its inner fields) */
.field input[type="date"]:focus,.field input[type="date"]:focus-within{outline:2px solid var(--accent);outline-offset:1px}
.field input[type="range"]{width:100%;accent-color:var(--accent)}
.field .range-value{font-family:var(--font-mono);font-size:var(--text-meta);color:var(--ink);font-variant-numeric:tabular-nums}
fieldset{border:1px solid var(--line);border-radius:10px;padding:16px 18px;margin:0}
legend{font-family:var(--font-body);font-size:var(--text-caption);text-transform:uppercase;letter-spacing:.06em;color:var(--muted);padding:0 6px}

/* One button system (UX pass 1, finding 11 in the report, #10 in the brief): three variants, one height rule.
   Secondary is the default .btn; .primary fills with the accent; .ghost and .link-btn are the tertiary text button.
   Anchors use the same classes. Disabled is 40% opacity of the same hue, never a different colour. */
.btn,button.link-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-sm);min-height:var(--control-h);padding:0 var(--space-md);border-radius:var(--radius-md);font:600 14px/1.2 var(--font-body);letter-spacing:0;text-transform:none;text-decoration:none;cursor:pointer;border:1px solid var(--line-strong);background:transparent;color:var(--ink);white-space:nowrap;transition:background-color .12s ease,border-color .12s ease,filter .12s ease}
@media (hover:hover){.btn:hover{background:var(--paper-alt);border-color:var(--muted)}}
.btn.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
@media (hover:hover){.btn.primary:hover{background:var(--accent);filter:brightness(1.12)}}
.btn.danger{background:var(--danger);color:var(--paper);border-color:var(--danger)}
@media (hover:hover){.btn.danger:hover{background:var(--danger);filter:brightness(1.1)}}
.btn.ghost,button.link-btn{background:transparent;border-color:transparent;color:var(--accent);padding:0 var(--space-sm)}
@media (hover:hover){.btn.ghost:hover,button.link-btn:hover{background:var(--accent-bg);border-color:transparent}}
/* a11y L3, Vesta ruling 3: disabled is a neutral fill at AA, never 40% opacity; primary and danger look the same when off. */
.btn:disabled,.btn.is-off,.btn[aria-disabled="true"],.btn.primary:disabled,.btn.primary.is-off,.btn.primary[aria-disabled="true"],.btn.danger:disabled,.btn.danger.is-off{background:var(--disabled-bg);color:var(--disabled-fg);border-color:var(--disabled-border);cursor:not-allowed;filter:none;opacity:1}
.btn:disabled:hover,.btn.is-off:hover{background:transparent;border-color:var(--line-strong)}
.btn.primary:disabled:hover,.btn.primary.is-off:hover,.btn.danger:disabled:hover,.btn.danger.is-off:hover{background:var(--disabled-bg);border-color:var(--disabled-border)}
.btn:focus-visible,button.link-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (max-width:600px){.btn,button.link-btn{min-height:var(--control-h-touch)}}

.error-msg{color:var(--danger);font-size:var(--text-meta);margin-top:4px}
.hint-warn{color:var(--warn);font-size:var(--text-meta);margin-top:8px;background:var(--assume-bg);border:1px solid var(--assume);border-radius:8px;padding:10px 12px}
.field.has-error input{border-color:var(--danger)}

/* ---------- Login / setup screens ---------- */
.centered-screen{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--bg)}
.auth-card{max-width:440px;width:100%;background:var(--paper);border:1px solid var(--line);border-radius:14px;padding:32px 30px;box-shadow:var(--shadow-md)}
.auth-card h1{font-family:var(--font-display);font-size:var(--text-section);margin:0 0 4px;color:var(--ink)}
.auth-card .sub{font-size:var(--text-meta);color:var(--muted);margin:0 0 22px}
.auth-card .field{margin-bottom:16px}
.auth-actions{display:flex;flex-direction:column;gap:10px;margin-top:18px}
.auth-divider{display:flex;align-items:center;gap:10px;margin:18px 0;color:var(--muted);font-size:var(--text-caption);text-transform:uppercase;letter-spacing:.06em}
.auth-divider::before,.auth-divider::after{content:"";flex:1;height:1px;background:var(--line)}

.setup-steps{display:flex;gap:6px;margin-bottom:22px}
.setup-steps .step-dot{flex:1;height:4px;border-radius:2px;background:var(--line)}
.setup-steps .step-dot.done{background:var(--confirmed)}
.setup-steps .step-dot.active{background:var(--accent)}

.passphrase-display{font-family:var(--font-mono);font-size:var(--text-card);font-weight:600;letter-spacing:.01em;background:var(--paper-alt);border:1px solid var(--line-strong);border-radius:8px;padding:14px 16px;word-break:break-all;color:var(--ink);margin:10px 0}

.entropy-meter{height:6px;border-radius:999px;background:var(--paper-alt);border:1px solid var(--line);overflow:hidden;margin-top:8px}
.entropy-meter > span{display:block;height:100%;border-radius:999px 0 0 999px}
.entropy-meter[data-ok="true"] > span{background:var(--confirmed)}
.entropy-meter[data-ok="false"] > span{background:var(--danger)}
.entropy-note{font-size:var(--text-caption);color:var(--muted);margin-top:5px}
.entropy-note.bad{color:var(--danger)}

.kit-warning{background:var(--danger-bg);border:1px solid var(--danger);border-radius:10px;padding:16px 18px;margin:14px 0}
.kit-warning strong{color:var(--danger);display:block;margin-bottom:4px}
.kit-warning p{margin:0;font-size:var(--text-meta);color:var(--ink-2);line-height:1.5}

.dev-only-box{border:2px dashed var(--assume);border-radius:10px;padding:16px 18px;margin-top:24px;background:var(--assume-bg)}
.dev-only-box .eyebrow{color:var(--assume)}
.dev-only-box p{font-size:var(--text-meta);color:var(--ink-2);margin:6px 0 12px}

/* ---------- Settings overlay ---------- */
.overlay-screen{position:fixed;inset:0;background:var(--bg);z-index:50;overflow-y:auto}
.overlay-header{display:flex;justify-content:space-between;align-items:center;max-width:900px;margin:0 auto;padding:20px 20px 0}
.overlay-header h2{font-family:var(--font-display);margin:0}

/* ---------- Auto-lock overlay ---------- */
.autolock-overlay{position:fixed;inset:0;background:rgba(20,17,10,.72);z-index:100;display:flex;align-items:center;justify-content:center;padding:20px}
.autolock-box{background:var(--paper);border-radius:14px;padding:28px 26px;max-width:380px;text-align:center;box-shadow:var(--shadow-md)}
.autolock-box h3{font-family:var(--font-display);margin:0 0 8px}
.autolock-box p{font-size:var(--text-meta);color:var(--muted);margin:0 0 18px}

/* ---------- Dialog (recast lock confirm) ---------- */
.dialog-backdrop{position:fixed;inset:0;background:rgba(20,17,10,.55);z-index:80;display:flex;align-items:center;justify-content:center;padding:20px}
.dialog-box{background:var(--paper);border-radius:14px;padding:24px 26px;max-width:520px;width:100%;box-shadow:var(--shadow-md);max-height:85vh;overflow-y:auto}
.dialog-box h3{font-family:var(--font-display);margin:0 0 10px}
.dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}

/* ---------- Recast dual framing ---------- */
.recast-compare{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;margin:14px 0}
.recast-option{border:1px solid var(--line);border-radius:10px;padding:16px 18px;background:var(--paper-alt)}
.recast-option.selected{border-color:var(--accent);background:var(--accent-bg)}
.recast-option h4{margin:0 0 8px;font-family:var(--font-display);font-size:var(--text-body)}
.recast-option .warn-line{font-size:var(--text-caption);color:var(--warn);margin-top:8px;line-height:1.4}
.recast-option .figure{font-family:var(--font-display);font-size:var(--text-card);color:var(--ink);font-variant-numeric:tabular-nums}

/* ---------- Self-check badge ---------- */
.selfcheck-badge{display:inline-flex;align-items:center;gap:8px;border-radius:999px;padding:8px 14px;font-family:var(--font-body);font-size:var(--text-caption);font-weight:700}
.selfcheck-badge[data-pass="true"]{background:var(--confirmed-bg);color:var(--confirmed)}
.selfcheck-badge[data-pass="false"]{background:var(--danger-bg);color:var(--danger)}
.selfcheck-details{margin-top:12px;font-size:var(--text-caption);font-family:var(--font-mono);color:var(--muted);max-height:220px;overflow-y:auto;border:1px solid var(--line);border-radius:8px;padding:10px 12px}
.selfcheck-details .row{display:flex;justify-content:space-between;gap:10px;padding:3px 0}
.selfcheck-details .row.fail{color:var(--danger)}

/* ---------- Master history ---------- */
.master-list{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:8px}
.master-list li{display:flex;justify-content:space-between;align-items:center;gap:12px;border:1px solid var(--line);border-radius:8px;padding:10px 14px;background:var(--paper-alt);flex-wrap:wrap}
.master-list li.active{border-color:var(--accent);background:var(--accent-bg)}
.master-list .m-label{font-weight:700;font-size:var(--text-meta)}
.master-list .m-meta{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted)}

.backups-list{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:6px;max-height:260px;overflow-y:auto}
.backups-list li{display:flex;justify-content:space-between;align-items:center;gap:10px;border:1px solid var(--line);border-radius:6px;padding:8px 12px;font-family:var(--font-mono);font-size:var(--text-caption)}

.foot{max-width:1180px;margin:0 auto;font-size:var(--text-caption);color:var(--muted);padding:16px 20px 40px;border-top:1px solid var(--line);line-height:1.6}

/* ---------- Utility classes (replace one-off inline styles, M8) ---------- */
.mt-8{margin-top:8px} .mt-10{margin-top:10px} .mt-12{margin-top:12px} .mt-14{margin-top:14px} .mt-16{margin-top:16px}
.mb-8{margin-bottom:8px} .mb-10{margin-bottom:10px}
.h2-compact{font-size:var(--text-card)}
.row-flex{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
.my-12{margin:12px 0}
.text-tight{margin:0 0 12px}
.btn-sm,.btn.btn-sm{min-height:var(--control-h-sm);padding:0 12px;font-size:var(--text-meta)}
@media (max-width:600px){.btn.btn-sm{min-height:var(--control-h-sm)}}
.auth-card-wide{max-width:560px}
.wrap-narrow{max-width:900px;margin-left:auto;margin-right:auto}
.dot-confirmed{background:var(--confirmed)}
.dot-accent{background:var(--accent)}
.checkbox-field{flex-direction:row;align-items:center;display:flex;gap:8px;text-transform:none;font-family:var(--font-body);font-size:var(--text-meta);color:var(--ink-2)}
.checkbox-input{width:auto}
.banner-compact{margin:0 0 16px;border-radius:8px}
.banner-inner-compact{padding:10px 14px}
.entropy-meter > span{width:0}

@media (max-width:600px){
  .auth-card{padding:24px 20px}
  }

@media (prefers-reduced-motion: no-preference){
  .theme-toggle,.card,.goal-card{transition:background-color .15s ease,border-color .15s ease}
}
@media (prefers-reduced-motion: reduce){ *{scroll-behavior:auto !important} }

.import-textarea{width:100%;box-sizing:border-box;border:1px solid var(--field-border);border-radius:6px;padding:10px;background:var(--paper);color:var(--ink);font:13px var(--font-mono);resize:vertical;margin:8px 0}
.import-error{color:var(--assume);margin:0 0 10px}

/* ============================================================
   MASTER-APP MERGE COMPONENTS (Phase 5, Lucian) -- folded verbatim
   from design/mockup-extensions.css per Brendan's mockup approval
   (household-finance-master-app-merge-mockup-approved.md, 2026-08-09).
   Zero new hex beyond the two PROPOSED categorical hues below (plum/
   stone for illiquid-equity/home-equity dataviz categories -- flagged
   to Vesta/Brendan for ratification per the source file's own note;
   everything else reuses existing Direction-B custom properties.
   ============================================================ */

/* ---------- Freshness / sync chip (Overview + Settings) ---------- */
.freshness-chip{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);background:var(--paper-alt);border:1px solid var(--line);border-radius:999px;padding:7px 14px}
.freshness-chip .dot{width:8px;height:8px;border-radius:50%;background:var(--confirmed);flex:none}
.freshness-chip[data-state="stale"] .dot{background:var(--assume)}
.freshness-chip[data-state="failed"] .dot{background:var(--danger)}
.freshness-chip strong{color:var(--ink);font-weight:700}

/* ---------- Account groups (Overview accounts drill-down) ---------- */
.account-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin-top:16px}
.account-group{background:var(--paper);border:1px solid var(--line);border-radius:10px;padding:16px 18px;box-shadow:var(--shadow-sm)}
.account-group h3{margin:0 0 10px;font-family:var(--font-display);font-size:var(--text-body);font-weight:600;color:var(--ink)}
.account-group .group-total{font-family:var(--font-mono);font-size:var(--text-caption);color:var(--muted);margin-left:6px}
.account-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:7px 0;border-bottom:1px solid var(--line)}
.account-row:last-child{border-bottom:none}
.account-row .a-name{font-size:var(--text-dense);color:var(--ink-2)}
.account-row .a-org{display:block;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.account-row .a-bal{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:var(--text-dense);color:var(--ink);white-space:nowrap}
.account-row .a-bal.negative{color:var(--danger)}

/* ---------- Filter / toolbar chips (Budgeting transaction browser) ---------- */
.table-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:14px 0}
.table-toolbar input[type="search"]{flex:1;min-width:180px;border:1px solid var(--field-border);border-radius:6px;padding:9px 12px;background:var(--paper);color:var(--ink);font:14px var(--font-body)}
.filter-chip{font-family:var(--font-body);font-size:var(--text-meta);font-weight:600;letter-spacing:0;text-transform:none;padding:6px 12px;border-radius:999px;border:1px solid var(--line-strong);background:var(--paper-alt);color:var(--ink-2);cursor:pointer;white-space:nowrap;max-width:100%;min-width:0}
/* select elements (month/account/category filters) auto-size to their
   WIDEST option's intrinsic content in Chromium, not just the currently
   selected/displayed option -- with real long account/category names this
   forces the control past a narrow viewport (BUG#2, 375px page overflow:
   399px rendered vs 375px viewport, isolated via computed-style probe to
   these three <select class="filter-chip"> elements, NOT the transactions
   table itself, which was already properly contained by .table-scroll).
   max-width:100% is the actual fix; the browser truncates the displayed
   selected-option text to fit, the full option list is unaffected. */
select.filter-chip{text-overflow:ellipsis;overflow:hidden}
.filter-chip[aria-pressed="true"]{background:var(--accent-bg);border-color:var(--accent);color:var(--accent)}
.filter-chip:hover{background:var(--accent-bg)}

/* ---------- Preset chip row (scenario planner) ---------- */
.preset-row{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0}
.preset-chip{font-family:var(--font-body);font-size:var(--text-meta);font-weight:700;padding:8px 14px;border-radius:8px;border:1px solid var(--line-strong);background:var(--paper);color:var(--ink-2);cursor:pointer}
.preset-chip[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.preset-chip:hover:not([aria-pressed="true"]){background:var(--accent-bg)}

/* ---------- Slider rows (scenario planner) ---------- */
.slider-row{margin:16px 0}
.slider-row .slider-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px}
.slider-row label{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.slider-row .range-value{font-family:var(--font-mono);font-size:var(--text-meta);color:var(--ink);font-variant-numeric:tabular-nums;font-weight:700}
.slider-row input[type="range"]{width:100%;accent-color:var(--accent)}

/* ---------- Cut chip (scenario planner discretionary trims) ---------- */
.cut-chips{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0}
.cut-chip{display:flex;align-items:center;gap:8px;border:1px solid var(--line-strong);border-radius:8px;padding:8px 12px;background:var(--paper);cursor:pointer;font-size:var(--text-meta)}
.cut-chip input{width:auto;margin:0}
.cut-chip .cc-name{font-weight:600;color:var(--ink-2)}
.cut-chip .cc-detail{display:block;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted)}
.cut-chip .cc-save{font-family:var(--font-mono);font-size:var(--text-caption);color:var(--confirmed);font-weight:700;margin-left:auto}
.cut-chip:has(input:checked){background:var(--accent-bg);border-color:var(--accent)}
.toggle-row{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid var(--line);border-radius:8px;padding:10px 14px;margin:10px 0}
.toggle-row .tr-label{font-size:var(--text-meta);color:var(--ink-2)}
.toggle-switch{position:relative;width:40px;height:22px;border-radius:999px;border:1px solid var(--line-strong);background:var(--paper-alt);cursor:pointer;flex:none;padding:0}
.toggle-switch::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--muted);transition:transform .15s ease}
.toggle-switch[aria-pressed="true"]{background:var(--accent);border-color:var(--accent)}
.toggle-switch[aria-pressed="true"]::after{background:var(--accent-ink);transform:translateX(18px)}

/* ---------- Provenance marker (live vs estimate) ---------- */
.prov-marker{font-family:var(--font-body);font-size:var(--text-caption);font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:3px 8px;border-radius:999px}
.prov-marker.live{background:var(--confirmed-bg);color:var(--confirmed)}
.prov-marker.estimate{background:var(--assume-bg);color:var(--assume)}

/* ---------- Allocation bar (Holdings) ---------- */
.alloc-bar{display:flex;height:14px;border-radius:999px;overflow:hidden;border:1px solid var(--field-border);margin:12px 0 8px}
.alloc-bar span + span{border-left:2px solid var(--paper)} /* a11y M3: segments separate by more than hue */
.alloc-bar span{display:block;height:100%}
.table-scroll:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.alloc-legend{display:flex;gap:18px;flex-wrap:wrap;font-size:var(--text-caption);color:var(--muted)}
.alloc-legend .item{display:flex;align-items:center;gap:6px}
.alloc-legend .dot{width:9px;height:9px;border-radius:50%;display:inline-block}

/* ---------- Empty state block (honest empty variants) ---------- */
.empty-state{text-align:center;padding:48px 24px;border:1px dashed var(--line-strong);border-radius:12px;background:var(--paper-alt)}
.empty-state .glyph{width:44px;height:44px;border-radius:50%;background:var(--paper);border:1px solid var(--line-strong);display:flex;align-items:center;justify-content:center;margin:0 auto 14px;font-family:var(--font-display);font-size:var(--text-card);color:var(--muted)}
.empty-state p{margin:0 0 14px;font-size:var(--text-dense);color:var(--ink-2);max-width:44ch;margin-left:auto;margin-right:auto}
.mockup-divider{display:flex;align-items:center;gap:12px;margin:34px 0 20px;color:var(--muted);font-family:var(--font-body);font-size:var(--text-caption);text-transform:uppercase;letter-spacing:.06em}
.mockup-divider::before,.mockup-divider::after{content:"";flex:1;height:1px;background:var(--line-strong)}

/* ---------- Auto / manual-override toggle pill (Levels rewire) ---------- */
.auto-toggle{display:inline-flex;border:1px solid var(--line-strong);border-radius:999px;overflow:hidden;font-family:var(--font-body);font-size:var(--text-caption);font-weight:700;text-transform:uppercase;letter-spacing:.06em}
.auto-toggle button{border:none;background:var(--paper-alt);color:var(--muted);padding:6px 12px;cursor:pointer}
.auto-toggle button[aria-pressed="true"]{background:var(--accent);color:var(--accent-ink)}
.field-with-toggle{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.field-note{font-size:var(--text-caption);color:var(--muted);margin-top:4px}

/* ---------- Manual-asset row (Settings) ---------- */
.manual-asset-row{display:flex;justify-content:space-between;align-items:center;gap:12px;border:1px solid var(--line);border-radius:8px;padding:10px 14px;background:var(--paper-alt);flex-wrap:wrap;margin-bottom:8px}
.manual-asset-row .ma-label{font-weight:700;font-size:var(--text-meta);color:var(--ink)}
.manual-asset-row .ma-meta{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted)}
.manual-asset-row .ma-val{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:var(--text-dense);color:var(--ink)}
.manual-asset-row .ma-val.liability{color:var(--danger)}

@media (max-width:480px){
  .account-groups{grid-template-columns:1fr}
  .table-toolbar{flex-direction:column;align-items:stretch}
  .table-toolbar input[type="search"]{width:100%}
}

/* ============================================================
   COCKPIT ELEVATION + insight/action-card primitives -- Vesta
   design-direction (2026-08-09-12-45_vesta_levels-overview-cockpit-
   design-direction.md). Two PROPOSED categorical hexes below (plum,
   stone) pending explicit Vesta/Brendan ratification -- flagged in
   the return handoff; every other value is an existing token alias.
   ============================================================ */

:root{
  --shadow-lg:0 8px 32px rgba(24,20,10,.10);
  --surface-hero:linear-gradient(180deg, var(--paper) 0%, var(--accent-bg) 130%);
  --surface-insight-critical:var(--danger-bg);
  --surface-insight-attention:var(--assume-bg);
  --surface-insight-positive:var(--confirmed-bg);
  --surface-insight-info:var(--derived-bg);
  --category-investable:var(--accent);
  --category-cash:var(--derived);
  --category-illiquid-equity:#6d4576;   /* plum-600 -- PROPOSED, pending approval */
  --category-home-equity:#6e675c;       /* stone-600 -- PROPOSED, pending approval */
  --motion-fast:120ms;
  --motion-base:220ms;
  --motion-slow:420ms;
}
@media (prefers-color-scheme: dark){
  :root{
    --shadow-lg:0 10px 36px rgba(0,0,0,.40);
    --surface-hero:linear-gradient(180deg, var(--paper) 0%, var(--accent-bg) 160%);
    --category-illiquid-equity:#b48bbd;
    --category-home-equity:#a39a8c;
  }
}
:root[data-theme="dark"]{
  --shadow-lg:0 10px 36px rgba(0,0,0,.40);
  --surface-hero:linear-gradient(180deg, var(--paper) 0%, var(--accent-bg) 160%);
  --category-illiquid-equity:#b48bbd;
  --category-home-equity:#a39a8c;
}
:root[data-theme="light"]{
  --shadow-lg:0 8px 32px rgba(24,20,10,.10);
  --surface-hero:linear-gradient(180deg, var(--paper) 0%, var(--accent-bg) 130%);
  --category-illiquid-equity:#6d4576;
  --category-home-equity:#6e675c;
}

.hero-cockpit{position:relative;background:var(--surface-hero);border:1px solid var(--line);border-radius:16px;padding:24px 26px 22px;margin:18px 0 20px;box-shadow:var(--shadow-lg)}
.hero-cockpit-head{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:2px}
.hero-figure-lg{display:block;font-family:var(--font-display);font-size:var(--text-figure);line-height:1.05;color:var(--ink);font-variant-numeric:tabular-nums;margin:6px 0 4px}
@media (max-width:600px){ .hero-figure-lg{font-size:var(--text-figure)} }

/* Sub2 (2026-08-11, Lucian) -- honest cash-flow surface. Supersedes the
   removed .hero-delta/.since ("$X ahead of plan · Plan target $Y") --
   grep-confirmed unused elsewhere before deletion. */
.cf-safe-to-spend{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap;padding:10px 14px;border-radius:10px;background:var(--accent-bg)}
.cf-safe-to-spend.negative{background:var(--danger-bg)}
.cf-safe-to-spend .cf-safe-figure{font-family:var(--font-display);font-size:var(--text-card);font-variant-numeric:tabular-nums;color:var(--accent)}
.cf-safe-to-spend.negative .cf-safe-figure{color:var(--danger)}
.cf-commitments-list{display:flex;flex-direction:column;gap:2px}
.cf-commitment-row{display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:var(--text-meta);padding:8px 0;border-bottom:1px solid var(--line)}
.cf-commitment-row:last-child{border-bottom:none}
.cf-commitment-name{color:var(--ink-2);font-weight:600;flex:1;min-width:120px}
.cf-commitment-amt{font-family:var(--font-mono);font-variant-numeric:tabular-nums;color:var(--ink)}
.cf-commitment-due{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}
.cf-sparkline-wrap{margin-bottom:12px}
.cf-sparkline{width:100%;height:56px;display:block}

.insight-cards{display:flex;gap:14px;flex-wrap:wrap;margin:16px 0}
.insight-card{flex:1 1 260px;min-width:240px;border-radius:12px;border:1px solid var(--line);padding:16px 18px;box-shadow:var(--shadow-lg);display:flex;flex-direction:column;gap:8px}
.insight-card[data-severity="critical"]{background:var(--surface-insight-critical);border-color:var(--danger)}
.insight-card[data-severity="attention"]{background:var(--surface-insight-attention);border-color:var(--assume)}
.insight-card[data-severity="positive"]{background:var(--surface-insight-positive);border-color:var(--confirmed)}
.insight-card[data-severity="info"]{background:var(--surface-insight-info);border-color:var(--derived)}
.insight-card-head{display:flex;align-items:center;gap:8px}
.insight-card-head .sev-dot{width:9px;height:9px;border-radius:50%;flex:none}
.insight-card[data-severity="critical"] .sev-dot{background:var(--danger)}
.insight-card[data-severity="attention"] .sev-dot{background:var(--assume)}
.insight-card[data-severity="positive"] .sev-dot{background:var(--confirmed)}
.insight-card[data-severity="info"] .sev-dot{background:var(--derived)}
.insight-card-head .sev-label{font-family:var(--font-body);font-size:var(--text-caption);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.insight-card h4{margin:0;font-family:var(--font-body);font-size:var(--text-body);font-weight:600;color:var(--ink);line-height:1.35}
.insight-card p{margin:0;font-size:var(--text-meta);line-height:1.5;color:var(--ink-2)}
.insight-card-actions{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:auto;padding-top:6px;flex-wrap:wrap}

.action-cards{display:flex;flex-direction:column;gap:12px;margin:16px 0}
.action-card{display:flex;align-items:center;gap:16px;border:1px solid var(--line);border-radius:12px;padding:14px 18px;background:var(--paper);box-shadow:var(--shadow-lg);flex-wrap:wrap}
.action-card .a-rank{flex:none;width:30px;height:30px;border-radius:50%;background:var(--accent-bg);color:var(--accent);display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-weight:700;font-size:var(--text-dense)}
.action-card .a-body{flex:1;min-width:200px}
.action-card .a-title{font-size:var(--text-dense);font-weight:600;color:var(--ink);margin:0 0 4px}
.action-card .a-meta{display:flex;gap:14px;flex-wrap:wrap;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted)}
.action-card .a-impact.positive{color:var(--confirmed);font-weight:700}
.action-card .a-impact.risk{color:var(--derived);font-weight:700}
.action-card .a-cta{flex:none}

/* Action Tracker / Open Items (CBI-1663) -- extends the .action-card shell
   above with a check-off control + domain/due/metric meta. Layout-only
   additions, zero new tokens (existing --accent/--danger/--muted/
   --derived-bg/--derived reused throughout). */
.action-card .a-check-wrap{flex:none;width:30px;height:30px;display:flex;align-items:center;justify-content:center}
.action-card .a-check-wrap input[type="checkbox"]{width:19px;height:19px;accent-color:var(--accent);cursor:pointer}
.action-card .a-check-dot{color:var(--muted);font-size:var(--text-body);line-height:1}
.action-card .a-detail{margin:4px 0 0;font-size:var(--text-meta);color:var(--ink-2)}
.action-card .a-due{color:var(--muted)}
.action-card .a-due.overdue{color:var(--danger);font-weight:700}
.action-card .a-condition-note{font-style:italic;color:var(--muted)}
.action-card .a-dismiss{flex:none;margin-left:auto}
.action-card.is-done{color:var(--muted)} /* a11y L4: no opacity drop; the line-through on the title carries 'done' */
.action-card.is-done .a-title{text-decoration:line-through}
.chip.domain{background:var(--derived-bg);color:var(--derived)}

/* Sub3 (2026-08-11, Lucian) -- open-item detail. .a-body-tappable is a
   <details>/<summary> in place of .a-body's plain <div> (native keyboard
   activation, no custom role/keydown handling -- matches
   .accounts-disclosure's idiom). */
.action-card .a-body-tappable{flex:1;min-width:200px;cursor:pointer}
.action-card .a-body-tappable > summary{list-style:none;cursor:pointer}
.action-card .a-body-tappable > summary::-webkit-details-marker{display:none}
.action-card .a-body-tappable > summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}
.a-details-chevron{display:inline-block;margin-left:8px;font-family:var(--font-body);font-size:var(--text-caption);font-weight:700;color:var(--accent);text-transform:uppercase;letter-spacing:.06em}
.a-details-chevron::before{content:"\25B8 ";}
.action-card .a-body-tappable[open] .a-details-chevron::before{content:"\25BE ";}
.a-detail-sheet{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line)}
.a-detail-sheet-title{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-weight:600;color:var(--ink);margin:0 0 8px;font-size:var(--text-dense)}
.a-detail-sheet p{font-size:var(--text-meta);color:var(--ink-2);line-height:1.55;margin:0 0 10px}
.doc-pointer{display:inline-flex;align-items:center;gap:6px;font-size:var(--text-meta);color:var(--accent);text-decoration:underline}
.doc-pointer.repo{display:flex;flex-wrap:wrap;align-items:center;gap:8px;color:var(--ink-2);text-decoration:none;margin-top:6px}
.doc-pointer-ref{font-family:var(--font-mono);font-size:var(--text-caption);color:var(--muted);background:var(--paper-alt);padding:2px 7px;border-radius:5px;word-break:break-all}

/* Sub4 (2026-08-11, Lucian) -- budget customization surface. */
.commitment-row{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 12px;padding:10px 0;border-bottom:1px solid var(--line);font-size:var(--text-meta)}
.commitment-row:last-child{border-bottom:none}
.commitment-row .commitment-name{color:var(--ink-2);font-weight:600;flex:1;min-width:120px}
.commitment-row .commitment-target{font-family:var(--font-mono);font-variant-numeric:tabular-nums;color:var(--ink)}
.commitment-row .commitment-state{font-family:var(--font-body);font-size:var(--text-meta);color:var(--muted);white-space:normal}
@media (max-width:600px){.commitment-row .commitment-state{flex-basis:100%;text-align:right}}
.commitment-row.is-paid .commitment-state{color:var(--confirmed)}
.commitment-row.is-partial .commitment-state{color:var(--assume)}
.budget-cat-block{margin-bottom:16px}
.budget-cat-block:last-child{margin-bottom:0}
.accrual-meter,.savings-meter{margin-bottom:2px}
.cat-customizer{border-top:1px dashed var(--line);padding-top:10px;margin-top:8px}
.cat-customizer-toggle{margin-top:6px}
.type-segmented{display:flex;flex-wrap:wrap;gap:6px}
.seg-btn{font-family:var(--font-body);font-size:var(--text-caption);font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:6px 11px;border-radius:7px;border:1px solid var(--line-strong);background:var(--paper-alt);color:var(--ink-2);cursor:pointer}
.seg-btn.active{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.seg-btn:hover:not(.active){background:var(--accent-bg)}

.accounts-disclosure{margin-top:24px}
.accounts-disclosure > summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:8px;font-family:var(--font-body);font-size:var(--text-dense);font-weight:600;color:var(--accent);text-transform:none;letter-spacing:0}
.accounts-disclosure > summary::-webkit-details-marker{display:none}
.accounts-disclosure > summary::before{content:"\25B8";display:inline-block}
.accounts-disclosure[open] > summary::before{content:"\25BE"}
.accounts-disclosure .account-groups{margin-top:14px}

/* BUG#9 root-cause fix (2026-08-11): the reported symptom was "second
   (faded) open-item row drops to near-invisible contrast in dark theme."
   Direct computed-style probe against the real feed found the actual
   cause was NOT a color-contrast deficiency (dark --muted vs --paper
   measures ~5.2:1, above AA) -- it was .action-card's staggered
   cockpit-in entrance animation below: nth-child(2)/(3) start at
   opacity:0 and don't reach opacity:1 until 220ms/440ms of animation-
   delay plus 420ms duration have elapsed (~640ms/860ms total). A probe
   taken shortly after render (any screenshot/verification tool, or a
   real user glancing at the screen on load) catches rows 2-3 mid-fade or
   still at their pre-animation opacity:0 -- reproduced directly: card 2
   measured opacity:0, card 3 measured opacity:0, card 1 measured
   opacity:0.75, all "visibility:visible" (i.e. genuinely invisible, not
   a CSS bug report false positive). This happens in BOTH themes; dark
   theme just made it easier to notice against a busy background. Removed
   entirely for .action-card (kept for .hero-cockpit/.insight-card,
   which weren't reported and load once, not per-row in a list where
   staggered invisibility reads as a real defect). */
@keyframes cockpit-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
@media (prefers-reduced-motion: no-preference){
  .hero-cockpit,.insight-card{animation:cockpit-in var(--motion-slow,420ms) ease both}
  .insight-card:nth-child(2){animation-delay:var(--motion-base,220ms)}
  .insight-card:nth-child(3){animation-delay:calc(var(--motion-base,220ms) * 2)}
}
@media (prefers-reduced-motion: reduce){
  .hero-cockpit,.insight-card{animation:none}
}

/* ============================================================
   OVERVIEW LEADING-INDICATORS (v3) -- approved surface per
   household-finance-master-app-merge-mockup-approved.md. Net worth
   demoted to a compact honest strip; cash flow / attainment / runway
   lead. Zero new hex -- reuses Direction-B + cockpit tokens above.
   ============================================================ */

.text-confirmed{color:var(--confirmed)}
.text-assume{color:var(--assume)}
.text-derived{color:var(--derived)}
.text-danger{color:var(--danger)}
.meter > span.fill-confirmed,.bullet-fill.fill-confirmed{background:var(--confirmed)}
.meter > span.fill-assume,.bullet-fill.fill-assume{background:var(--assume)}
.meter > span.fill-derived,.bullet-fill.fill-derived{background:var(--derived)}
.meter > span.fill-danger,.bullet-fill.fill-danger{background:var(--danger)}

.bullet-rows{display:flex;flex-direction:column;gap:14px}
.bullet-row-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:6px;flex-wrap:wrap}
.bullet-label{font-family:var(--font-body);font-size:var(--text-dense);font-weight:600;color:var(--ink-2);text-transform:none;letter-spacing:0}
.bullet-value{font-family:var(--font-body);font-size:var(--text-meta);color:var(--ink)}
.bullet-target{color:var(--muted);font-weight:400;margin-left:4px}
.bullet-bar{position:relative;height:10px;border-radius:999px;background:var(--paper-alt);border:1px solid var(--line);overflow:visible}
.bullet-fill{display:block;height:100%;border-radius:999px;background:var(--accent)}
.bullet-target-mark{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--ink-2)}
.bullet-target-mark::after{content:"";position:absolute;top:-4px;left:50%;transform:translateX(-50%);width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid var(--ink-2)}

.cf-month-label{display:block;font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-top:2px}
.hero-figure-unit{font-family:var(--font-body);font-size:var(--text-body);font-weight:600;color:var(--ink-2);vertical-align:middle;margin-left:8px}
.cashflow-hero .bullet-bar{background:var(--paper)}

.attainment-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:16px;margin:16px 0}
.goal-attain-rows{display:flex;flex-direction:column;gap:16px}
.goal-attain-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px}
.ga-name{font-size:var(--text-dense);color:var(--ink-2);font-weight:600}
.ga-pct{font-family:var(--font-mono);font-size:var(--text-meta);font-weight:700;font-variant-numeric:tabular-nums}

.runway-card .runway-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.runway-figure{font-family:var(--font-display);font-size:var(--text-page);font-weight:700;font-variant-numeric:tabular-nums}
.runway-sub{font-size:var(--text-meta);color:var(--muted)}
.runway-bar{height:14px}
/* BUG#7 fix: was display:flex;justify-content:space-between -- three
   labels at fixed 0/50/100% positions regardless of what they described,
   which put "Floor — 6 mo" at a visual midpoint that never matched the
   floor tick-mark's real position on the bar above (often near the right
   edge once floor > current cash). Now a relative-positioned row with
   each label absolutely placed at the SAME percentage as the thing it
   labels (0 = left edge, floor = mark.style.left set in app.js to match
   the bar's own floor tick exactly, max = right edge), so the axis is
   internally consistent and readable at a glance. */
.runway-scale{position:relative;height:14px;font-family:var(--font-mono);font-size:var(--text-caption);color:var(--muted);margin-top:6px}
.runway-scale .rs-mark{position:absolute;top:0;white-space:nowrap}
.runway-scale .rs-mark-0{left:0}
.runway-scale .rs-mark-floor{transform:translateX(-50%)}

.networth-strip{display:grid;grid-template-columns:auto 1fr;gap:14px 26px;border:1px solid var(--line);border-radius:12px;padding:16px 20px;background:var(--paper);box-shadow:var(--shadow-sm);align-items:start}
.ns-left{display:flex;flex-direction:column;gap:8px;min-width:140px}
.strip-sparkline{width:140px;height:34px;display:block}
.strip-sparkline .spark-area{fill:var(--accent-bg-strong);opacity:.4}
.strip-sparkline .spark-line{fill:none;stroke:var(--accent);stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
.ns-figures{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px}
.ns-figure{display:flex;flex-direction:column;gap:3px}
.ns-label{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
.ns-value{font-family:var(--font-display);font-size:var(--text-card);font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.ns-caveat{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);font-weight:400;margin-left:4px;text-transform:uppercase}
.ns-note{font-size:var(--text-caption);line-height:1.4}
.ns-figure-flag .ns-value{color:var(--assume)}
.ns-total{grid-column:1 / -1;margin-top:2px;color:var(--muted)}
.rl-flag{color:var(--assume);margin-left:3px;cursor:help}
@media (max-width:640px){
  .networth-strip{grid-template-columns:1fr}
}

/* ---------- Budget-bars-first IA (B4): spending-by-category donut ---------- */
.donut-row{display:flex;gap:28px;align-items:center;flex-wrap:wrap;margin:14px 0 4px}
.cat-donut-wrap{position:relative;flex:none;width:140px;height:140px}
.cat-donut{width:140px;height:140px;border-radius:50%;border:1px solid var(--line)}
.cat-donut-hole{position:absolute;top:18px;left:18px;right:18px;bottom:18px;border-radius:50%;background:var(--paper);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;box-shadow:var(--shadow-sm)}
.cat-donut-hole .cd-total{font-family:var(--font-display);font-size:var(--text-card);font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.cat-donut-hole .cd-label{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-top:2px}
.cat-legend{flex:1 1 220px;display:flex;flex-direction:column;gap:9px;min-width:200px}
.cat-legend-row{display:flex;align-items:center;gap:9px;font-size:var(--text-meta)}
.cat-legend-row .dot{width:10px;height:10px;border-radius:50%;flex:none}
.cat-legend-name{flex:1;color:var(--ink-2);font-weight:600}
.cat-legend-val{font-family:var(--font-body);font-size:var(--text-meta);color:var(--muted);font-variant-numeric:tabular-nums}

/* ---------- Inline section head (label + action button on one row) ---------- */
.section-head-inline{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}

/* ---------- Levels: starter-goals suggestion panel (D6/B6) ---------- */
.starter-goal-list{display:flex;flex-direction:column;gap:2px}
.starter-goal-row{display:flex;align-items:center;gap:12px;padding:9px 0;border-top:1px solid var(--line)}
.starter-goal-row:first-child{border-top:none}
.sg-name{flex:1;font-size:var(--text-dense);font-weight:600;color:var(--ink-2)}
.sg-detail{font-family:var(--font-body);font-size:var(--text-caption);color:var(--muted)}

/* ---- Protection tab (Estate & Protection module) ---- */
.pr-headline{font-family:var(--font-display);font-size:var(--text-card);font-weight:700;margin:4px 0 10px;color:var(--ink)}
.pr-person,.pr-doc,.pr-bene-row,.pr-dime{border-top:1px solid var(--line);padding:14px 0;display:flex;flex-direction:column;gap:10px}
.pr-doc-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}
.pr-chip[data-tone="ok"]{background:var(--confirmed-bg);color:var(--confirmed)}
.pr-chip[data-tone="warn"]{background:var(--paper-alt);color:var(--warn);border:1px solid var(--warn)}
.pr-chip[data-tone="bad"]{background:var(--danger-bg);color:var(--danger)}
/* UX pass 3, finding 12: no red stripes; one summary row, one account open at a time, three selects on one line */
.pr-bene-summary{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm) 0}
.pr-bene-summary p{margin:0;font-size:var(--text-dense);color:var(--ink)}
.pr-bene-line{display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) auto;gap:var(--space-sm) var(--space-md);align-items:end}
.pr-bene-line .pr-chip{align-self:center;margin-top:18px}
@media (max-width:600px){.pr-bene-line{grid-template-columns:1fr}.pr-bene-line .pr-chip{justify-self:start;margin-top:0}}
.pr-review-menu{list-style:none;margin:var(--space-sm) 0 0;padding:var(--space-sm);border:1px solid var(--line);border-radius:var(--radius-md);background:var(--paper);display:flex;flex-direction:column;gap:2px;max-width:420px}
.pr-review-menu li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-sm)}
.pr-review-menu .field-note{margin:0}
.pr-locked{margin:var(--space-sm) 0 0;color:var(--muted)}
#panel-protection .auth-actions{flex-direction:row;flex-wrap:wrap;align-items:center}
.pr-dime .pr-chip,.pr-person > .btn{align-self:flex-start}
.pr-line{margin:10px 0;font-size:var(--text-dense);line-height:1.5}
.pr-policy-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 0;border-top:1px solid var(--line)}
.pr-policy-row .a-org{display:block}
.pr-advisory{margin:12px 0 0;padding-left:18px;font-size:var(--text-dense);line-height:1.55;color:var(--ink)}
.pr-advisory li{margin-bottom:8px}
.grid-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
/* ---------- Allocation panel (allocation-ui.js) ---------- */
.row-between{display:flex;justify-content:space-between;align-items:center;gap:12px;margin:8px 0}
.grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:12px;margin:12px 0}
/* ============================================================
   ASK (A2) -- floating button + bottom sheet. Tokens only.
   ============================================================ */
.ask-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.ask-fab{position:fixed;right:16px;bottom:calc(20px + env(safe-area-inset-bottom,0px));z-index:40;min-height:52px;padding:0 22px;border-radius:999px;border:none;background:var(--accent);color:var(--accent-ink);font:700 16px var(--font-body);box-shadow:var(--shadow-md);cursor:pointer;display:flex;align-items:center;gap:8px}
.ask-fab[hidden]{display:none}
.ask-fab-mark{width:22px;height:22px;border-radius:50%;background:var(--accent-ink);color:var(--accent);display:grid;place-items:center;font-size:var(--text-dense)}
.ask-fab:focus-visible,.ask-root button:focus-visible,.ask-root input:focus-visible,.ask-root summary:focus-visible{outline:3px solid var(--derived);outline-offset:2px}
.ask-scrim{position:fixed;inset:0;z-index:50;background:rgba(20,18,10,.4)}
.ask-scrim[hidden],.ask-sheet[hidden],.ask-stale[hidden]{display:none}
.ask-sheet{position:fixed;left:0;right:0;bottom:0;top:44px;z-index:51;background:var(--paper);color:var(--ink);border-radius:18px 18px 0 0;display:flex;flex-direction:column;box-shadow:0 -6px 24px rgba(0,0,0,.18);max-width:640px;margin:0 auto}
.ask-sheet:before{content:"";width:40px;height:4px;border-radius:9px;background:var(--line-strong);margin:8px auto 0;flex:none}
.ask-head{display:flex;justify-content:space-between;align-items:flex-start;padding:8px 18px 10px;border-bottom:1px solid var(--line);flex:none}
.ask-head h2{margin:0;font:700 22px var(--font-display)}
.ask-sub{margin:2px 0 0;font-size:var(--text-meta);color:var(--muted)}
.ask-x{width:44px;height:44px;border:none;background:none;font-size:var(--text-page);color:var(--ink-2);cursor:pointer;border-radius:50%}
.ask-body{flex:1;overflow:auto;padding:14px 16px;display:flex;flex-direction:column;gap:12px}
.ask-hello h3{font:700 18px var(--font-display);margin:6px 0 2px}
.ask-hello p{margin:0;color:var(--ink-2)}
.ask-sugs{display:flex;flex-direction:column;gap:8px}
.ask-sug{text-align:left;min-height:44px;padding:10px 14px;border:1px solid var(--line-strong);background:var(--paper);color:var(--ink);border-radius:12px;font:600 14px var(--font-body);cursor:pointer}
.ask-sug:hover{background:var(--accent-bg)}
.ask-note{font-size:var(--text-meta);color:var(--muted);margin:4px 0 0}
.ask-msg{max-width:92%;border-radius:14px;padding:11px 14px}
.ask-msg p{margin:0 0 8px;overflow-wrap:anywhere}
.ask-msg p:last-child{margin:0}
.ask-user{align-self:flex-end;background:var(--accent);color:var(--accent-ink)}
.ask-bot{align-self:flex-start;background:var(--paper-alt);border:1px solid var(--line);max-width:100%;width:100%}
.ask-err{background:var(--danger-bg);border-color:var(--danger)}
.ask-err b{color:var(--danger)}
.ask-alt{display:flex;flex-direction:column;gap:6px;margin:8px 0}
.ask-retry{min-height:44px;padding:0 18px;border:none;border-radius:10px;background:var(--danger);color:var(--paper);font:700 14px var(--font-body);cursor:pointer;width:fit-content}
.ask-figs{margin:8px 0;background:var(--paper);border:1px solid var(--line);border-radius:10px;padding:2px 12px}
.ask-figs summary{cursor:pointer;font:700 12px var(--font-body);letter-spacing:.06em;text-transform:uppercase;color:var(--muted);padding:9px 0;min-height:36px}
.ask-figs ul{list-style:none;margin:0;padding:0 0 6px}
.ask-figs li{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-top:1px solid var(--line);font-size:var(--text-dense)}
.ask-figs b{font-family:var(--font-mono);white-space:nowrap}
.ask-fnote{font-size:var(--text-meta);color:var(--ink-2)}
.ask-asof{display:flex;align-items:center;gap:7px;font:12px var(--font-body);color:var(--confirmed);margin:6px 0 0}
.ask-dot{width:8px;height:8px;border-radius:50%;background:var(--confirmed);flex:none}
.ask-asof.old{color:var(--assume)}
.ask-asof.old .ask-dot{background:var(--assume)}
.ask-stale{display:flex;gap:10px;padding:10px 16px;background:var(--assume-bg);border-bottom:2px solid var(--assume);flex:none}
.ask-stale p{margin:0;font-size:var(--text-meta);color:var(--ink-2)}
.ask-stale strong{color:var(--assume)}
.ask-glyph{flex:none;width:20px;height:20px;border-radius:50%;background:var(--assume);color:var(--paper);display:grid;place-items:center;font:700 12px var(--font-body)}
.ask-typing{display:flex;gap:6px;padding:4px 0 8px}
.ask-typing i{width:9px;height:9px;border-radius:50%;background:var(--accent);opacity:.35;animation:ask-b 1.2s infinite}
.ask-typing i:nth-child(2){animation-delay:.2s}
.ask-typing i:nth-child(3){animation-delay:.4s}
@keyframes ask-b{50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.ask-typing i{animation:none;opacity:.7}}
.ask-composer{display:flex;gap:8px;padding:10px 14px calc(16px + env(safe-area-inset-bottom,0px));border-top:1px solid var(--line);background:var(--paper);flex:none}
.ask-composer input{flex:1;min-width:0;min-height:48px;border:1px solid var(--field-border);border-radius:12px;padding:0 14px;background:var(--bg);color:var(--ink);font:16px var(--font-body)}
.ask-send{min-height:48px;padding:0 18px;border:none;border-radius:12px;background:var(--accent);color:var(--accent-ink);font:700 16px var(--font-body);cursor:pointer}
.ask-root button:disabled,.ask-root input:disabled{opacity:.5;cursor:not-allowed}
body.ask-open{overflow:hidden}
body.ask-mounted{padding-bottom:88px}
.chip.stale{background:var(--paper-alt);color:var(--warn);border:1px solid var(--warn);margin-left:8px}

/* ---------- UX pass 2: currency input with a "$" prefix (finding 3) ---------- */
.money-input{position:relative;display:flex;align-items:center}
.money-input .adorn{position:absolute;left:10px;color:var(--muted);font-size:var(--text-dense);pointer-events:none}
.field .money-input input[type="text"]{width:100%;padding-left:22px;font-variant-numeric:tabular-nums}
/* UX pass 3, finding 14: "%" sits after the number */
.money-input.is-suffix .adorn{left:auto;right:12px}
.field .money-input.is-suffix input[type="text"]{padding-left:10px;padding-right:28px}
.form-actions{display:flex;justify-content:flex-end;gap:var(--space-sm)}
/* Suggested goals: a collapsed helper under the ladder (finding 3) */
details.starter-goals > summary{cursor:pointer;font-weight:600;font-size:var(--text-dense);color:var(--ink)}
details.starter-goals[open] > summary{margin-bottom:12px}

/* ---------- QA-1 fold (2026-11-13) ---------- */
/* Buttons size to their label inside cards; auth screens keep full-width actions. Replaces .btn-fit. */
.auth-actions{align-items:flex-start}
.auth-card .auth-actions{align-items:stretch}
/* Item 5: an empty Overview module is one muted line with a tertiary link */
.module-empty{margin:0;font-size:var(--text-dense);color:var(--muted);padding:var(--space-sm) 0;display:flex;align-items:center;flex-wrap:wrap;gap:4px}
.grid > .module-empty,.attainment-grid > .module-empty{align-self:start}
.attainment-grid.goals-empty > *{grid-column:1 / -1}
#profile-form[data-setup="true"] .in-setup-card{display:none}
.budget-edit-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px 12px;margin-top:6px}
.budget-edit-row .budget-amount{flex:0 1 160px;margin:0}
.budget-edit-row .budget-amount .money-input input[type="text"]{min-height:var(--control-h-sm)}
.budget-edit-row > :not(.budget-amount):not(.cat-customizer-toggle){flex-basis:100%}
/* ---------- UX pass 2, finding 10: Holdings ---------- */
.alloc-bar-wrap{position:relative;margin:16px 0 12px}
.alloc-bar-wrap .alloc-bar{margin:0}
.alloc-target{position:absolute;top:-5px;bottom:-5px;width:3px;margin-left:-1.5px;background:var(--ink);border-radius:2px;box-shadow:0 0 0 2px var(--paper)}
.tick-key{display:inline-block;width:2px;height:12px;background:var(--ink);margin-right:6px;vertical-align:-1px}
.target-row .target-edit{width:100%}
.disclaimer p{margin:0 0 8px}

/* axe heading-order fix: an eyebrow that is a real heading keeps the eyebrow look */
h3.eyebrow-heading{margin:0}

/* Design polish 10: a field marked invalid shows it on the field, not only in the sentence under it. */
input[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:var(--danger)}

/* Strict walk fix 21 (2026-11-14): "Alerts & advice" reads as an eyebrow like every other one (never the serif h3 face);
   an empty Overview section is a card, like its neighbours. */
h3.eyebrow-heading{font-family:var(--font-body);font-size:var(--text-caption);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.ov-empty-card .module-empty{padding:0}
.ov-empty-card .eyebrow{margin:0 0 6px}
