/* ========================================================================
   DEPLOY PATH: /css/PvS_style.4d15e5ec.css
   Tepuy Solutions — Property vs Shares calculator — complete styles (dark/light theme)
   Version: 2026-03-31 (headers added)
   Notes: Self-contained. Only load on property_vs_shares.html.
   ======================================================================== */

@import url('https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@300;400;500&family=DM+Sans:wght@300;400;500;600&family=Inter+Tight:wght@400;600;800&display=swap');

/* ── THEME (palette redesign 2026-08) ────────────────────────
   Was a dark-by-default theme with a data-theme="light" toggle
   variant; the toggle and its dark base are removed entirely (no page
   keeps a dark surface any longer, per the site-wide sweep). What was
   the light-theme token block is now the only block, values unchanged
   from what already shipped and was WCAG-AA-verified as this page's
   light mode. --bg-base is repointed to the site's --bone (was a
   self-contained cool-grey #f4f5f8, unrelated to the rest of the site's
   palette); everything else keeps its existing, already-tuned value.
   Retirement-parity pass (2026-08): repointed again, this time to --bg
   (#f7fbfc) — retirement.html's own main-content background (tepuy.css
   "body { background: var(--bg) }"), replacing the --bone cream/beige
   tint so PvS's page background literally matches the accepted
   reference template instead of carrying its own accent. */
:root {
  --bg-base:        var(--bg, #f7fbfc);
  --bg-surface:     #ffffff;
  --bg-raised:      #f0f1f5;
  --bg-input:       #f7f8fb;
  --bg-hover:       #eaecf2;
  /* Retirement-parity pass (2026-08): repointed to retirement.html's own
     --border (tepuy.css, #e1ecf1) — even lighter than PvS's prior
     #d8dce8 (now ~1.20:1 on white, was 1.37:1). Doesn't change the
     accessibility picture: --border was never the boundary color WCAG
     1.4.11 applies to on this page (see --border-strong below), and
     retirement.html treats its own --border the same way — a soft
     decorative divider, not a required-contrast edge. */
  --border:         #e1ecf1;
  /* Structural boundary color — for .section/input/select borders
     specifically, the component-boundary cases WCAG 1.4.11 (non-text
     contrast, 3:1) actually applies to. Same blue-gray hue family as
     --border, just with presence: 3.40:1 on white, 3.20:1 against
     --bg-input (used on the toggle track). Design audit, 2026-08. */
  --border-strong:  #828ba3;
  --border-focus:   var(--clay, #b8922e);
  --text-primary:   #0b1f16;
  --text-secondary: #2c3248;
  --text-muted:     #505870;
  --shadow-sm:      0 1px 4px rgba(0,0,0,.08);
  --shadow-md:      0 4px 20px rgba(0,0,0,.10);
  --shadow-lg:      0 8px 40px rgba(0,0,0,.12);
  --shadow-gold:    0 0 24px rgba(184,146,46,.15);

  /* Was PvS's own amber/gold accent (#c9a84c), independent of the rest
     of the site. Remapped to --clay — the same "one accent, used
     sparingly" role --clay already plays everywhere else, and the same
     move for_professionals.html's rebrand made for its own --pro-gold.
     --gold-light/-dim keep the existing lighter/darker relationship,
     recomputed from --clay instead of the old literal amber. */
  --gold:       var(--clay, #BE6A3E);
  --gold-on:    #0E1512;   /* 4.69:1 on #BE6A3E; white would be only 3.95:1 */
  --gold-light: color-mix(in srgb, var(--clay, #BE6A3E) 70%, white);
  --gold-dim:   color-mix(in srgb, var(--clay, #BE6A3E) 70%, black);
  /* AA-safe darkened companion for --gold used as *text* (the raw
     --gold hex doesn't clear 4.5:1 on white) — same pattern as
     --dsc-teal-text below, applied wherever "gold" text appeared. */
  /* Was 85% clay: the comment above says it was meant to clear 4.5:1 on
     white, but measured from computed styles it renders 4.43:1 — just under.
     70% clears it with margin (6.97:1 by construction) and still reads clay. */
  --gold-text:  color-mix(in srgb, var(--clay, #BE6A3E) 70%, black);

  --property:     #4e8ef7;
  --property-dim: #c8deff;
  --shares:       #4ecb71;
  --shares-dim:   #c5f0d4;

  /* Decision Summary Card's own teal/gold accent pair (distinct from
     the --property/--shares blue/green used elsewhere on the page) —
     tokenized per the same approach drafted on an abandoned branch
     (claude/pvs-dsc-light-mode-cleanup) that never merged: raw #3dd4dc
     literals scattered through the DSC block, plus a light-mode pass
     that had drifted to recoloring the "property" winner badge blue
     instead of teal (a bug — it no longer matched the badge's own
     .teal/.gold classes elsewhere in the same card). One shared token,
     one AA-safe text variant, both themes read from the same value now
     that there's only one theme. */
  --dsc-teal:      #3dd4dc;
  --dsc-teal-text: #006b72;

  /* Retirement-parity pass (2026-08): --success was declared three times
     in this same :root block (this one, plus #2d8a4e near the top and
     #4ecb71 above — both now dead code, silently overridden by source
     order; only ever mattered because var(--success) has exactly one
     consumer, .td-pos, and all three greens were close enough in hue
     that the bug was invisible). Collapsed to one declaration, ported to
     retirement.html's own --success (tepuy.css, #28a745). --warning and
     --danger also ported to retirement's exact values (#ffaf1a /
     #e03434, tepuy.css) — --danger as text on white actually improves
     (3.75:1 -> 4.46:1, was already borderline-failing AA normal-text
     contrast). --warning as raw text (.section-header-exit/.td-exit/
     .td-exit-highlight) was already failing WCAG AA before this change
     (old #f5a623: ~2.0:1) and remains failing after (new #ffaf1a:
     ~1.8:1) — porting the token doesn't fix or meaningfully worsen a
     pre-existing text-contrast bug in those specific consumers; flagged
     as a follow-up, not fixed here (out of scope for a token port). */
  --success: #28a745;
  --warning: #ffaf1a;
  --danger:  #e03434;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;
  --radius-xl: 20px;
  --transition: all .18s cubic-bezier(.4,0,.2,1);
}

/* ── RESET ───────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* html{font-size} moved to css/calculators.css (2026-08 consolidation
   audit) — this used to declare 15px here, later silently overridden to
   15.5px by a rule further down this file, neither matching
   retirement.html's un-overridden 16px default. Every rem-sized element
   on this page was rendering ~3-6% smaller than its retirement.html
   equivalent as a result. Fixed once already by pinning this file's own
   value to 16px; fixed properly now by making calculators.css (loaded
   after this file on both pages) the one declaration both pages actually
   share, instead of two pages independently agreeing to the same number.
   scroll-behavior stays here — genuinely page-specific, not part of the
   shared type scale. */
html { scroll-behavior: smooth; }
/* Retirement-parity pass (2026-08): body was self-importing DM Sans as
   this page's own base font, independent of the rest of the rebranded
   site — the root cause of KPI labels/values-surrounding text, buttons,
   and headline accents all reading in a different typeface than
   retirement.html (which inherits 'Inter Tight' from tepuy.css's body
   rule, unopposed). Repointed to the exact same stack tepuy.css uses,
   so every element on this page that relied on inheriting body's font
   (not just .kpi-label, but any other unstyled text) now matches
   retirement.html without needing a per-selector override — the same
   thing retirement.html itself does. DM Mono (numeric/tabular figures)
   and DM Serif Display (headline accents, handled by explicit
   overrides below) are unaffected by this change. */
body {
  font-family: 'Inter Tight', system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial,
               "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  background: var(--bg-base);
  color: var(--text-primary);
  min-height: 100vh;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  transition: background .25s, color .25s;
  /* CHANGED (2026-08, navbar-fixed fix) — was padding-top: 0, cancelling
     tepuy.css's own body{padding-top:64px} compensation for its
     position:fixed navbar. That cancellation was only correct while
     PvS's navbar was (incorrectly) position:sticky, in-flow, reserving
     its own space naturally. Now that the navbar is genuinely
     position:fixed (see EXCEPTION 2 and the removed header:not(.page-head)
     rule above), this MUST reserve that space itself or page content
     renders underneath the fixed bar. 60px (not tepuy.css's 64px) to
     match EXCEPTION 1's navbar height:60px and every other 60px-based
     measurement already hardcoded through this file (.sidebar's
     top/height, etc.) — see EXCEPTION 1's own comment for the full list. */
  padding-top: 60px;
}
/* ── SCROLLBAR ───────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-base); }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--gold-dim); }

/* ── LAYOUT ──────────────────────────────────────────────── */
.app-shell { display: grid; grid-template-rows: auto 1fr; min-height: 100vh; }
/* Line 96 - Replace existing line */
.main-content { display: grid; grid-template-columns: 360px 1fr; min-height: calc(100vh - 60px); }

/* Container-query scaffolding — PvS is a standalone page (no tepuy.css), so
   this mirrors that shared setup independently instead of reusing it.
   body is the container (not .app-shell/.main-content themselves): a
   container can't restyle its own layout-affecting properties (display,
   grid-template-columns) based on a query of itself, so the tier queries
   below need .main-content to be a descendant of the query container. body's
   inline-size equals the iframe's own rendered width when embedded. */
body {
  container-type: inline-size;
  container-name: pvs-layout;
}
.sidebar {
  container-type: inline-size;
  container-name: pvs-sidebar;
}
.results-panel {
  container-type: inline-size;
  container-name: pvs-main;
}

/* ── HEADER ──────────────────────────────────────────────── */
/* REMOVED (2026-08, navbar-fixed fix) — this used to hold a full parallel
   header treatment (height/border/padding/shadow AND, critically,
   `position: sticky; top: 0`). The comment above claimed ".navbar's
   higher-specificity rule should already win on paper" — that assumption
   was wrong. `header:not(.page-head)` is an element selector plus a
   :not() whose argument's specificity counts, so it resolves to (0,1,1) —
   HIGHER than the bare `.navbar` class selector's (0,1,0), in tepuy.css
   AND in this file's own now-also-removed ".navbar { position: sticky }"
   override below (EXCEPTION 2). This rule was silently winning the
   position property on every load, and unlike ".navbar", <header>'s
   *containing block* for sticky purposes is just #navbar-placeholder — a
   box exactly as tall as the header itself, with zero extra room for
   "sticky" to ever hold: confirmed live (Playwright scroll test) that the
   navbar scrolled off-screen immediately, in exact lockstep with
   scrollY, on every page load. tepuy.css's ".navbar" is `position: fixed`
   for exactly this reason — fixed has no containing-block-height
   dependency at all. See EXCEPTION 2 below: PvS now uses that same fixed
   navbar unopposed, matching Mortgage/Offset vs Shares/Retirement. This
   rule's other properties (height/border/padding/shadow/flex) are already
   covered by tepuy.css's own ".navbar"/".navbar-inner" (see the "TEPUY
   NAVBAR" section further down) plus EXCEPTION 1's height:60px override,
   so nothing here needs to be kept. */

.logo {
  font-family: 'Inter Tight', sans-serif;
  font-weight: 600;
  font-size: 1.2rem;
  color: var(--gold);
  white-space: nowrap;
}
.logo span {
  color: var(--text-muted);
  font-size: .78rem;
  font-family: 'Inter Tight', sans-serif;
  font-weight: 400;
  margin-left: 10px;
  letter-spacing: .01em;
}

/* ── PAGE HEAD ───────────────────────────────────────────────
   PvS's own copy of the shared page-head component now filled in via
   js/page-head-include.js (same mechanism as #navbar-placeholder above)
   — same markup, same rule values as .page-head/h1/.sub/::after in
   css/tepuy.css (the pattern shared by the other calculators): one
   title, one subtitle, a full-width divider, stacked paragraph-style on
   wide screens, side-by-side two columns below 800px. tepuy.css's own
   copy points its breakpoint at @container calc-layout rather than the
   .main-layout > main element to dodge a display:contents bug — not
   relevant here since pvs-layout (declared on <body>) never has that
   conflict, but the values themselves are copied 1:1 either way. */
.page-head {
  /* No padding of its own, matching tepuy.css's canonical .page-head —
     #page-head-placeholder is now .results-panel's first child (moved
     2026-08, was a direct child of .app-shell with no padded ancestor),
     so .results-panel's own padding already carries the page's edge
     spacing and this only needs to add its bottom margin. */
  margin-bottom: 1.25rem;
}
.page-head h1 {
  font-size: clamp(1.35rem, 2.5vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #0f1c16;
  line-height: 1.2;
}
.page-head .sub {
  font-size: 0.925rem;
  color: #4a655a;
  margin: 0.35rem 0 0;
  line-height: 1.5;
}
.page-head::after {
  content: "";
  display: block;
  height: 1px;
  background: var(--border);
  margin-top: 0.75rem;
}

@container pvs-layout (max-width: 800px) {
  .page-head {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
    align-items: start;
  }
  .page-head::after {
    grid-column: 1 / -1;
  }
}

/* ── THEME TOGGLE ────────────────────────────────────────── */
.theme-toggle {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 5px 12px 5px 8px;
  transition: var(--transition);
  flex-shrink: 0;
}
.theme-toggle:hover { border-color: var(--gold-dim); }
.theme-toggle-icon { font-size: 1rem; line-height: 1; }
.theme-toggle-label {
  font-family: 'Inter Tight', system-ui, -apple-system, sans-serif;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ── SIDEBAR ─────────────────────────────────────────────── */
/* CANONICAL PATTERN — calculator sticky sidebar. This is the SAME
   mechanism as tepuy.css's `body.calc .calc-aside` (see tepuy.css,
   "14) CALCULATORS — fixed left rail"), which Mortgage/Offset vs
   Shares/Retirement all use unmodified: position: sticky (not fixed —
   fixed would need manual left-edge centering math against
   .main-content's max-width: 1200px/margin: 0 auto, which the grid
   column already gives sticky for free), pinned `height` so the sidebar
   scrolls its own contents via overflow-y once they exceed the viewport,
   released back into normal flow once .main-content's row (driven by
   whichever of .sidebar/.results-panel is taller) runs out — confirmed
   live via Playwright scroll sweep, same release behavior as Mortgage's
   own aside on its own longer page.
   PvS keeps its own class names (.sidebar, not .calc-aside) rather than
   adopting tepuy.css's directly: this file has ~2000 lines of component
   CSS (accordions, KPI cards, chart wraps, etc.) built against .sidebar/
   .results-panel/.app-shell, and renaming the outer shell would mean
   auditing every one of those for accidental collisions with tepuy.css's
   OWN .calc-aside descendant rules (.card, .card-header, .form-row, etc.
   — see tepuy.css section 14) — a large, high-blast-radius rewrite for a
   purely cosmetic class-name win. The VALUES (60px, not tepuy.css's
   var(--stick-top): 80px) are PvS's own — see EXCEPTION 1 in the "TEPUY
   NAVBAR" section below for why 60px is pinned throughout this file.
   A genuinely NEW calculator should use tepuy.css's `.main-layout` +
   `.calc-aside.aside--bare` + `.sidebar-panel` + `.sidebar-scroll`
   directly (the Mortgage/Retirement pattern), not copy this block —
   this comment exists so a future session finds the real canonical
   source instead of re-deriving it from PvS's parallel copy. */
.sidebar {
  /* FIX (2026-08, sidebar-restructure) — was var(--bg-surface) (white),
     matching the main panel exactly instead of reading as a distinct
     rail. Mortgage's own sidebar (mortgage-polish.css, "SIDEBAR
     SURFACE") uses a flat #f4f8f6 for both .calc-aside and
     .sidebar-panel — var(--bg-raised) (#f0f1f5) is PvS's own existing
     token for the same "barely-tinted, not-quite-white surface" job,
     reused here rather than hardcoding a second near-identical value.
     overflow-y: auto REMOVED — scrolling now lives on .sidebar-scroll
     below instead of the whole aside, so .sidebar-footer (Run
     Comparison + its button rows) can stay pinned outside the scroll
     region instead of scrolling away with the accordion list. */
  background: var(--bg-raised);
  border-right: 1px solid var(--border);
  /* CONFIRMED BUG (2026-08) — was calc(100vh - 60px), filling the
     viewport exactly flush with its bottom edge. #disclaimerFooter is
     position:sticky; bottom:0 (pre-existing, unrelated to this
     restructure) and sits in that exact same spot — before this
     session's sidebar-footer pinning, whatever content fell at the
     tail of .sidebar's own internal scroll only rarely landed there,
     and could be scrolled clear of it regardless; now that
     .sidebar-footer (Run Comparison + Save/Load) is pinned flush with
     .sidebar's own bottom edge, it landed exactly under the disclaimer
     bar with no way to scroll clear — confirmed live, Save/Load
     visually covered and unclickable at both 900px and 1080px viewport
     heights. The extra 60px subtracted here (measured disclaimer bar
     height: 54px at 1440px width, +6px buffer for its text wrapping
     onto an extra line at narrower widths) stops .sidebar short of the
     true viewport bottom, leaving the disclaimer bar its own clear
     strip below the sidebar instead of overlapping it. When the bar is
     dismissed (its own close button) this reads as a bit of extra
     breathing room at the sidebar's bottom, not a visible gap. */
  height: calc(100vh - 60px - 60px);
  position: sticky;
  top: 60px;
}
/* .sidebar-inner is now the flex column that makes the pin possible:
   .sidebar-scroll (flex: 1, its own overflow-y) takes all the space
   .sidebar-footer (flex-shrink: 0) doesn't need, so the footer always
   lands at the bottom of .sidebar's own fixed height — never pushed
   down by how much accordion content happens to be open above it, and
   never scrolled away with it either. Mirrors tepuy.css's canonical
   `body.calc .calc-aside .sidebar-panel { display:flex; flex-direction:
   column }` + `.sidebar-scroll { flex:1 1 auto; min-height:0; overflow-y:
   auto }` mechanism (see the CANONICAL PATTERN comment on .sidebar
   above) under PvS's own class names. */
.sidebar-inner {
  padding: 16px;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}
.sidebar-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* CONFIRMED COLLISION (2026-08) — tepuy.css has its own bare, unscoped
     `.sidebar-scroll { background: var(--brand) }` (dark Tepuy green,
     written for a DIFFERENT — body.calc — sidebar pattern that never
     applies here since PvS's <body> has no .calc class). PvS loads
     tepuy.css before this file, so equal specificity + later source
     order means PvS's own declarations win where they compete — but
     background wasn't originally declared here, so tepuy's dark-green
     value was the only one in play and silently won. Confirmed live:
     the eyebrow title rendered dark-green-on-dark-green, invisible.
     transparent here lets .sidebar's own var(--bg-raised) show through
     instead, same as intended. */
  background: transparent;
}
.sidebar-footer {
  flex-shrink: 0;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
/* .pvs-sidebar-title / .pvs-sidebar-sub / .pvs-calc-hint moved to
   css/simulators.css (Step 3, 2026-08-19) — identical values, now shared
   with Mortgage/Offset/LMI's equivalent eyebrow/hint rules via a
   .pvs-* branch on those selectors. */

/* ── ACCORDION ───────────────────────────────────────────── */
/* Design audit, 2026-08: border strengthened to --border-strong (3.4:1 on white, was 1.37:1,
   was 1.37:1) and a soft shadow added — previously relying entirely on
   that near-invisible 1px line for definition, with zero shadow anywhere
   on the accordion.
   Retirement-parity pass (2026-08): radius and shadow re-ported to
   retirement.html's exact "aside .card" values (retirement.css) — 14px
   (--tp-radius-card, was a PvS-specific 10px) and the 2-layer resting
   shadow --tp-shadow-card. Hover previously only changed border-color;
   retirement.html's card hover is a shadow lift instead
   (--tp-shadow-card-hover, with an explicit "transform: none" since its
   own .card:hover elsewhere in retirement.css sets a transform this
   needs to cancel — kept here too for a literal port even though
   nothing in this file currently sets one). */
/* .section/.section-header/.section-icon (+ 8 .icon-* variants)/
   .section-title/.section-chevron/.section-body all removed here — Step 3
   (2026-08-19) sidebar rebuild:
   - .section -> .card, .section-header -> .card-header,
     .section-body -> .card-content (markup renamed in
     property_vs_shares.html), styled via css/simulators.css's shared
     .sidebar .card* branch instead of locally.
   - .section-icon and all 8 .icon-* category-color variants removed
     entirely, no replacement — confirmed in the UI polish audit as
     "removed, not migrated".
   - .section-chevron (text-glyph "▼") removed entirely — the shared
     .card-header::after SVG chevron in simulators.css replaces it, no
     markup element needed.
   - .section-title div replaced with a plain <h4> inside .card-header,
     matching Mortgage/Offset/LMI's markup — this also resolves the
     dashed-connector-line finding from the UI audit: that line was never
     PvS's own design, it was an accidental collision with tepuy.css's
     unrelated blog-heading .section-title::after rule (tepuy.css:2692).
     Renaming away from .section-title removes the collision at the
     source instead of overriding it.
   @keyframes slideDown is now unused (only .section-body's open animation
   referenced it) and removed with it. */

/* ── FORM CONTROLS ───────────────────────────────────────── */
.field { margin-bottom: 14px; }
.field:last-child { margin-bottom: 0; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

label {
  display: block;
  /* font-family audit (2026-08): inherits body's stack, see .section-title above. */
  font-size: .68rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 4px;
  letter-spacing: .03em;
  text-transform: uppercase;
}
label .hint {
  color: var(--text-muted);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  margin-left: 4px;
  font-size: .65rem;
}

.input-wrap { position: relative; display: flex; align-items: center; }
.input-prefix, .input-suffix {
  position: absolute;
  /* Was 'DM Mono', monospace — missed by the Step 3 input font fix above,
     which only targeted input[type="number"]/input[type="text"]/select.
     .input-prefix/.input-suffix are separate <span> elements with their
     own font-family declaration, so they kept rendering DM Mono even
     after the inputs themselves switched to Inter Tight. Confirmed live
     via getComputedStyle across all 34 prefix/suffix spans on the page
     before this fix — every one still resolved to DM Mono. Same explicit
     stack as the input fix, not `font-family: inherit` — inputs/spans
     don't reliably inherit from the page (see the input rule's own note
     above). */
  font-family: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', Roboto,
               Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
  font-size: .72rem;
  color: var(--text-muted);
  pointer-events: none;
  z-index: 1;
}
.input-prefix { left: 9px; }
.input-suffix { right: 9px; }

/* .sidebar .card-content — NOT just a naming nicety. tepuy.css:1684 has a
   generic ".card-content input:not([type=checkbox]):not([type=radio]),
   .card-content select" fallback rule (specificity 0,3,1 — the two :not()
   attribute args each count as a class) for pages using the shared card
   pattern outside body.calc .calc-aside. PvS's inputs started matching it
   for the first time the moment Step 3 renamed .section-body to
   .card-content — before that they were never in a .card-content at all,
   so this collision didn't exist. Unscoped, PvS's own rule below
   (previously 0,1,1) loses that specificity fight, and tepuy.css's
   padding:.5rem silently wins over PvS's own padding — collapsing the
   $-prefix gap into an overlap, and also overriding border-radius/
   border-color/background/font-size/color and adding an unwanted
   margin-top none of that was true font-family-swap fallout. Prefixing
   with .sidebar .card-content (both real, always-present ancestors —
   every input/select on this page lives inside <aside class="sidebar">)
   brings specificity to a tie (0,3,1); PvS_style.css loads last (see the
   <head> comment above the stylesheet links), so the tie resolves in its
   favor. Fixes the collision by not colliding, same approach as the
   dashed-connector fix above — not a font-metrics patch. */
.sidebar .card-content input[type="number"],
.sidebar .card-content input[type="text"],
.sidebar .card-content select {
  width: 100%;
  background: var(--bg-input);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  /* Was 'DM Mono', monospace — UI polish audit finding #8: DM Mono is not
     the site's canonical font (Inter Tight is) and these inputs aren't
     tabular data, the one case DM Mono is meant for.
     Explicit stack, not `font-family: inherit` or just deleting the line —
     confirmed live (getComputedStyle) that form controls (input/select/
     textarea) do NOT inherit font-family from the page by default in
     Chromium's UA stylesheet; removing the declaration entirely computed
     to plain "Arial", not body's stack. Same literal stack body already
     uses (line ~128 above). */
  font-family: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', Roboto,
               Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
  font-size: .78rem;
  padding: 7px 9px;
  margin-top: 0;
  outline: none;
  transition: var(--transition);
  appearance: none;
}
.sidebar .card-content input[type="number"]:focus,
.sidebar .card-content input[type="text"]:focus,
.sidebar .card-content select:focus {
  border-color: var(--gold);
  background: var(--bg-hover);
  box-shadow: 0 0 0 3px rgba(201,168,76,.08);
}
.sidebar .card-content .has-prefix input { padding-left: 20px; }

/* Suffix fields ($-prefix is unaffected, still fixed-width padding-left
   above — "$" is always exactly one character, not the class of bug
   below). A fixed padding-right budget (previously 26px) works for short
   suffixes ("%", "yrs") but silently overlaps for longer ones ("% of
   building value") — pre-existing, reproduces identically on unmodified
   main with the original DM Mono font, so not a font-metrics issue
   either. Rather than pick a bigger fixed number (which just moves the
   same bug to the next long suffix string), the suffix becomes a real
   flex sibling instead of an absolutely-positioned overlay, and the
   input gets flex:1 — the browser reserves exactly the suffix's actual
   rendered width, so there's no px budget to run out of at any length.
   Border/background move from <input> onto the wrap since the input can
   no longer own the whole visual "pill" once the suffix sits inside it
   as flex content rather than overlaid on top.
   :has(.input-suffix) targets by actual content rather than the
   .has-suffix wrap class, which also incidentally fixes strata_fees:
   its wrap carries only .has-prefix despite containing a suffix span,
   so it never matched the old .has-suffix rule and was always overlap-
   prone at the default 9px padding-right. */
.sidebar .card-content .input-wrap:has(.input-suffix) {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-input);
  padding-right: 9px;
  transition: var(--transition);
}
.sidebar .card-content .input-wrap:has(.input-suffix):focus-within {
  border-color: var(--gold);
  background: var(--bg-hover);
  box-shadow: 0 0 0 3px rgba(201,168,76,.08);
}
.sidebar .card-content .input-wrap:has(.input-suffix) input[type="number"],
.sidebar .card-content .input-wrap:has(.input-suffix) input[type="text"] {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  background: transparent;
  border-radius: 0;
  padding-right: 6px;
}
.sidebar .card-content .input-wrap:has(.input-suffix) input:focus {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}
.sidebar .card-content .input-wrap .input-suffix {
  position: static;
  flex: 0 0 auto;
  white-space: nowrap;
  padding-left: 4px;
}

select {
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%235a6070'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  padding-right: 26px;
}
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238890a8'/%3E%3C/svg%3E");
}

/* Range — input[type="range"]/::-webkit-slider-thumb moved to
   css/simulators.css (Step 3, 2026-08-19): now shared via a .sidebar
   branch on the same rule Mortgage/Offset/LMI/Retirement would use if
   any of them had a slider. Colors there are the shared brand green, not
   this file's --gold — a deliberate, visible change (see simulators.css's
   §6 comment). .range-wrap stays here (layout wrapper, still tied to this
   page's markup). .range-val's font-family dropped for the same reason
   as the input font-family above — DM Mono isn't tabular data here
   either, just a single slider readout number. */
.range-wrap { display: flex; align-items: center; gap: 8px; }
.range-val { font-size: .72rem; color: var(--gold); min-width: 36px; text-align: right; }

/* Toggle switch (row/label/slider) moved to css/calculators.css — 2026-08
   Stage 2. Its tepuy.css class-name-collision fix (label.toggle vs bare
   .toggle) traveled with it unchanged; see calculators.css for the note. */

/* Radio group */
.radio-group {
  display: flex; gap: 3px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 3px;
}
.radio-group label {
  flex: 1; text-align: center;
  padding: 4px 5px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: .66rem; font-weight: 600;
  color: var(--text-muted);
  letter-spacing: .03em; text-transform: uppercase;
  margin: 0; transition: var(--transition);
}
.radio-group input[type="radio"] { display: none; }
.radio-group input[type="radio"]:checked + label {
  background: var(--bg-raised); color: var(--gold);
  box-shadow: var(--shadow-sm);
}

/* ── CALCULATE BUTTON ────────────────────────────────────── */
/* .btn-calculate/.btn-secondary/.btn-row (css/calculators.css, 2026-08
   Stage 2) are no longer used by the sidebar footer as of the Step 3
   sidebar rebuild (2026-08-19) — the primary button is now #runBtn
   (class="btn btn-primary"), styled by css/simulators.css's shared
   .sidebar .sidebar-footer #runBtn rule, same mechanism Mortgage/Offset/
   LMI use. calculators.css's .btn-calculate/.btn-secondary/.btn-row
   classes are left as-is in that file (unused by this page now, but not
   this step's concern to clean up — Retirement may still reference them).
   Text stays "Run Comparison", not "Calculate" — PvS compares two
   strategies, not a single calculation; confirmed with the requester
   before implementing. */

/* ── SAVE / LOAD / SHARE ROW ─────────────────────────────────
   New in Step 3 — PvS previously had a 2x2 Export/Print/Reset/Share grid
   plus a separate Save/Load row (removed from the visible footer; #btn_csv/
   #btn_print/#btn_reset stay in the DOM, hidden, since app1.js's listeners
   and the results-area .export-bar's proxy clicks both depend on those
   IDs existing — see the markup comment in property_vs_shares.html).
   Share moved out of that grid into this row instead, joining Save/Load,
   matching Mortgage/Offset/LMI/Retirement's shared footer shape.
   Values copied from mortgage-polish.css's .ret-scenario-row/.ret-scen-btn
   (identical to lmi-polish.css's copy) — Step 1 deliberately did not put
   this row in css/simulators.css (offset's version has real differences),
   so PvS gets its own local copy too, same as the other three. Unscoped
   (no body.calc prefix) since PvS doesn't use that pattern; .ret-scen-btn
   isn't a generic-enough name to need it either. */
.ret-scenario-row {
  display: flex; gap: 0.35rem; margin-top: 0.1rem;
}
.ret-scen-btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center;
  gap: 0.28rem; padding: 0.38rem 0.4rem;
  font-family: inherit; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.03em;
  color: #3d5248; background: #f0f5f2; border: 1px solid #c8ddd3;
  border-radius: 6px; cursor: pointer; white-space: nowrap;
  transition: background 0.13s, border-color 0.13s, color 0.13s;
}
.ret-scen-btn:hover { background: #e6f2ec; border-color: #3db07e; color: #1a5236; }
.ret-scen-btn:active { background: #d4eae0; }
.ret-scen-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.ret-scen-btn--share { color: #1a5236; background: #edf7f2; border-color: #b3d9c4; }
.ret-scen-btn--share:hover { background: #d4ede2; border-color: #1a6b4a; }

/* ── SUMMARY BAR ─────────────────────────────────────────── */
.summary-bar {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px;
  margin-top: 8px;
}
.summary-bar-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 2px 0;
}
.summary-bar-key { font-size: .74rem; color: var(--text-secondary); }
.summary-bar-val { font-family: 'DM Mono', monospace; font-size: .72rem; color: var(--text-secondary); }
.summary-bar-val.gold { color: var(--gold); }

/* ── RESULTS PANEL ───────────────────────────────────────── */
/* CANONICAL PATTERN — calculator main-panel white background. Mirrors
   tepuy.css's `body.calc .main-layout > main { background: var(--surface);
   }` (section 14) — same var (--bg-surface here is PvS's own alias for
   the identical #ffffff value tepuy.css calls --surface), same intent:
   a flat white content panel over the page's pale --bg/--bg-base tint,
   so the panel doesn't look tinted by the ambient page background. */
/* No overflow-y here (was: auto) — an overflow:auto item in a stretch grid
   row contributes only its min-content height to the row's auto-sizing, so
   .main-content's row collapsed to ~1 viewport tall and this panel scrolled
   internally instead of the page growing. That's what broke .sidebar's
   position:sticky (see below): with the page never taller than one
   viewport, there was no scroll distance for it to stick through. Letting
   this panel size to its natural content height — same as Mortgage's/
   Retirement's plain, non-scrolling <main> — fixes both at once: the page
   scrolls normally, and background: var(--bg-surface) gives it Mortgage's
   flat white panel instead of the body's pale --bg-base showing through. */
/* min-width: 0 overrides the browser default of min-width: auto on grid
   items, which refuses to shrink a grid item below its content's own
   min-content size — normally invisible, but a wide table (see the
   "TABLE" section's CANONICAL PATTERN comment) has a large min-content
   width, and without this override that width propagates straight up
   through .results-panel into .main-content's grid track, blowing out
   the ENTIRE page's width instead of scrolling inside the table's own
   .table-wrap. Same fix tepuy.css applies on its own `main` for the
   identical reason (search tepuy.css for "prevent grid blowout"). */
.results-panel { padding: 20px; background: var(--bg-surface); min-width: 0; }

/* CONFIRMED BUG (2026-08) — js/app1.js's runCalculation() calls
   `#results_content.scrollIntoView({block:'start'})` after every Run
   Comparison. The native scrollIntoView API has no awareness of
   .navbar's position:fixed, so it lands #results_content's top flush
   with viewport y:0 — directly BEHIND the 60px-tall fixed navbar.
   Reproduced live with Playwright WebKit (the engine every iPhone
   uses) + the real calc engine driving a real render, not a
   simulated/stubbed one: the winner banner and its summary text render
   partially hidden under the translucent, blurred navbar immediately
   after the very first Run Comparison — before the user has scrolled
   or interacted further, which is exactly what reads as "sections gone
   blank/wrong" on a first glance. Did not reproduce in Chromium (its
   scrollIntoView happened to land far enough down to clear the navbar
   on this page's current content height) — but that's a coincidence of
   content length, not a fix; the same code will land short again the
   moment the content above shrinks. scroll-margin-top is the standard,
   engine-independent fix: it tells scrollIntoView to stop that many
   px earlier, regardless of which browser's scroll math is doing the
   landing. 60px matches the fixed navbar's own height (EXCEPTION 1 in
   the "TEPUY NAVBAR" section below) plus a few px of breathing room. */
#results_content { scroll-margin-top: 72px; }

/* ── EMPTY STATE ─────────────────────────────────────────── */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; min-height: 400px; text-align: center; gap: 14px; color: var(--text-muted);
}
.empty-icon { font-size: 3.2rem; opacity: .18; font-weight: 200; letter-spacing: -.05em; }
.empty-title { font-weight: 600; font-size: 1.35rem; color: var(--text-secondary); }
.empty-sub { font-size: .82rem; max-width: 340px; line-height: 1.75; }

/* WINNER BANNER — removed (2026-08, results-section cleanup). The "★
   winner banner" HTML block (results_content's first child) was deleted:
   it stacked a duplicate of the same $ figure/margin the Decision
   Summary Card and the Performance Overview KPI grid also show, three
   times over. See the HTML comment in calculators/property_vs_shares.html
   where the block used to be. All .winner-*/#winner_* rules below this
   point in the file (media queries, contrast-fix overrides) were removed
   with it — none of those selectors match anything any more. */

/* ── KPI GRID ────────────────────────────────────────────── */
/* KPI simplification (2026-08): 8 cards -> 4 (Future Value Winner, IRR
   comparison, Break-even Year, Present Value Winner). Grid dropped from
   4 columns to 2 — the two "winner" cards (kpi-card-delta) span both
   columns as full-width rows, IRR and Break-even sit side by side
   between them. Removed cards' values are still visible elsewhere:
   Total Depreciation on the Depreciation tab (#total_depr_claimed) and
   the Assumptions tab (#assumption_depr); Property/Shares Net Proceeds
   and Terminal PV remain in the underlying summary data used by other
   tabs, just no longer duplicated here. */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
/* Structurally these already match retirement.html's .insight-card
   (label/value/sub, same 3-line pattern) — the drift was purely visual:
   left-aligned vs. retirement's centered layout, and no resting shadow
   (retirement's cards carry one at rest, not just on hover). Centering
   and the shadow below copy retirement.html's .insight-card exactly;
   colors are left alone since PvS's property/shares/gold value coloring
   is load-bearing (it's how a card signals which side of the comparison
   it belongs to) where retirement's flat green is not. */
.kpi-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 18px 16px;
  transition: var(--transition);
  min-height: 90px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Matches tepuy.css's .insight-card exactly (0 2px 4px rgba(0,0,0,.05))
     — the PREVIOUS value here (0 3px 10px rgba(0,0,0,.07)) was a
     "visual-weight pass" that believed it was porting retirement's
     shadow while actually diverging from it; the comment claiming
     parity was wrong, not just the value. */
  box-shadow: 0 2px 4px rgba(0,0,0,.05);
}
/* translateY distance matched to retirement's .insight-card:hover
   (-2px, was -1px); border-color stays PvS's own clay family
   (var(--border-focus)) rather than retirement's
   color-mix(var(--brand) 25%, var(--border)) green-mix. */
.kpi-card:hover { border-color: var(--border-focus); transform: translateY(-2px); box-shadow: var(--shadow-sm); }
/* Results-section cleanup (2026-08): the previous "hero accent" here (a
   fixed gold left border + gold-tinted background, regardless of which
   side actually won) was a decorative mismatch on two counts — it read
   as an off-brand orange highlight against retirement.html's teal/green
   system, AND the color was wrong half the time anyway: it stayed gold
   even in a property-winning scenario, while this same card's value text
   (.kpi-value.property/.shares below) correctly switches color per
   winner. retirement.html's own insight-card has no such border/
   background treatment at all — every card is visually uniform, and
   only the VALUE text carries color. Matched that here: .kpi-card-delta
   now only carries its layout (full-width span), not a color treatment;
   .kpi-card's own uniform border/hover styling applies to it like every
   other card. */
.kpi-card-delta {
  grid-column: span 2;
  min-height: 90px;
}
/* Label/value/sub sizes matched to tepuy.css's .insight-label/.insight-
   value/.insight-sub (same rationale as the box-shadow fix above — a
   prior pass believed these already matched and they didn't: label was
   .72rem/700/.07em vs retirement's .8rem/600/.4px, value was 1.9rem/800
   vs retirement's 1.4-1.5rem/bold, sub was .72rem vs retirement's
   .85rem). Semantic colors (property/shares/gold) are kept PvS-specific
   rather than forced to retirement's flat green — that color-coding is
   load-bearing here, unlike retirement's single flat KPI color.
   FONT FIX (2026-08, full audit): .kpi-value/.kpi-value-irr/.kpi-sub
   used to hardcode font-family: 'DM Mono', monospace, on the (never
   actually checked) assumption that retirement's own .insight-value
   also used a monospace font for its figures. Confirmed via
   getComputedStyle live on retirement.html: .insight-value computes to
   the same "Inter Tight", ... stack as everything else on that page —
   no monospace anywhere in its KPI strip. Dropped the override here so
   these inherit body's font like retirement's do, instead of
   hardcoding a copy of it (there's no --font-* custom property in this
   codebase to reference — inheritance is the actual shared "token").
   DM Mono is kept ONLY where the user explicitly sanctioned it: the
   year-by-year table's genuinely tabular/columnar number columns
   (see the "TABLE" section further down). */
/* font-size/font-weight/letter-spacing/text-transform/margin-bottom
   moved to css/calculators.css (2026-08 consolidation audit), shared
   with tepuy.css's .insight-label — the two were declared identically
   here by coincidence, not by sharing a source, which is how this file
   ended up with a font-size "floor" rule that silently shrank .kpi-label
   below its own declared size (see calculators.css's own comment on this
   block for the full incident). Only the page-specific color stays. */
.kpi-label { color: var(--text-secondary); }
/* font-size/font-weight moved to css/calculators.css, shared with
   tepuy.css's .insight-value. */
.kpi-value { line-height: 1; margin-bottom: 5px; flex-grow: 1; }
.kpi-value.property { color: var(--property); }
.kpi-value.shares   { color: var(--shares); }
.kpi-value.gold     { color: var(--gold); }
.kpi-sub { font-size: .85rem; color: var(--text-secondary); line-height: 1.45; }

/* IRR card: two values (property/shares) side by side in one card
   instead of two separate cards — smaller than the standard .kpi-value
   size so both fit without wrapping awkwardly on narrow cards. */
/* .kpi-value.kpi-value-irr (not bare .kpi-value-irr) — this element always
   carries both classes in the markup (property_vs_shares.html:
   <div class="kpi-value kpi-value-irr">), and needs its own smaller/
   bolder size (1.35rem/800) to override the shared .kpi-value rule
   (1.5rem/700, css/calculators.css) that would otherwise apply via the
   .kpi-value class alone. Before the 2026-08 consolidation moved that
   sizing into calculators.css, a bare .kpi-value-irr selector was enough
   — same specificity as .kpi-value, but declared later within this same
   file, so it won by source order. Once the competing rule moved to a
   file that loads AFTER this one, source-order-within-PvS_style.css
   stopped mattering and the shared rule started winning instead (a real
   regression, caught by the getComputedStyle re-audit run right after
   the consolidation — .kpi-value-irr measured font-weight 700 instead of
   800). Two classes beats calculators.css's one regardless of which file
   loads last, so this is the actually-correct fix, not source-order
   dependent. */
.kpi-value.kpi-value-irr {
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1;
  margin-bottom: 5px;
  flex-grow: 1;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}
.kpi-value-irr .property { color: var(--property); }
.kpi-value-irr .shares   { color: var(--shares); }
.kpi-value-irr .kpi-vs {
  font-size: .65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
}

/* IRR proportional split bar — mirrors retirement.html's own
   benchmark-bar pattern (.dd-benchmark/.dd-bench-track/.dd-bench-seg):
   segment widths reflect each side's share of the combined IRR, so the
   card communicates "who's ahead" at a glance, not just two numbers.
   Populated by js/app1.js (renderResults) since it depends on the
   computed IRR values; hidden by default until populated. */
.kpi-irr-bar-wrap { display: none; margin-top: 6px; width: 100%; max-width: 220px; }
.kpi-irr-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; background: var(--bg-raised); }
.kpi-irr-bar-prop   { background: var(--property); }
.kpi-irr-bar-shares { background: var(--shares); }

@container pvs-main (max-width: 600px) {
  .kpi-grid { grid-template-columns: 1fr; }
  .kpi-card-delta { grid-column: span 1; }
  .kpi-card { min-height: 80px; padding: 12px; }
}

/* ── TABS ─────────────────────────────────────────────────
   Retirement-parity pass (2026-08): full underline-indicator pattern
   ported from retirement.html's .rtab-bar/.rtab-btn/.rtab-btn--active —
   a genuine UX pattern change, not a color swap: was a filled-pill
   selection style (background fill + shadow on the active tab), now a
   bottom-border indicator (transparent border reserved on every tab so
   layout doesn't shift on activate; only the active tab's border-bottom
   goes solid). Verified against retirement.html's actual rendered
   computed styles (not just its authored CSS) — a "better balance"
   refinement block in tepuy.css targeting the same .rtab-bar/.rtab-btn
   classes turned out to be dead on retirement.html itself, shadowed by
   an inline <style> block later in that page's own document; the
   values below are what retirement.html actually renders.
   Structural values (padding/radius/border-bottom width/font-weight/
   letter-spacing/the reserved-space mechanic) are literal ports. Colors
   stay in PvS's own gold/clay family rather than retirement's green,
   consistent with every other color decision in this round — WCAG
   verified: --gold (active underline) vs white = 3.32:1 (clears the
   3:1 UI-component minimum); --gold-text (active/hover text) vs white
   ≈ 4.41:1, the same pre-existing token already used elsewhere on this
   page for AA-safe gold text.
   Left untouched (out of scope for this pass): the equal-width flex:1
   tab sizing and flex-wrap responsive behavior — retirement instead
   makes its (7-tab) bar horizontally scrollable, but PvS has 9 tabs and
   its existing wrap behavior is already tested; switching sizing/
   overflow mechanics is a bigger structural change than "port the
   indicator style" asked for. */
.tabs {
  display: flex; gap: 2px;
  background: #f7faf8;
  border: none;
  border-bottom: 1px solid #e3ede8;
  border-radius: 0;
  padding: 0.55rem 0.75rem 0;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.tab {
  flex: 1; padding: 0.35rem 0.85rem 0.4rem;
  border: none; background: transparent;
  border-radius: 6px 6px 0 0;
  border-bottom: 2px solid transparent;
  position: relative; bottom: -1px;
  color: var(--text-muted);
  /* font-family: inherit — NOT redundant on a <button>: browsers don't
     cascade body's font into form controls (button/input/select/
     textarea) via normal inheritance; Chromium's own UA default for a
     bare <button> here computes to plain "Arial", confirmed live. The
     very first pass at this font audit removed this line assuming it
     was a harmless duplicate of body's stack, same as the non-button
     fixes elsewhere in this pass — that broke it (verified: computed
     font-family became "Arial"). .dsc-share-btn already had this
     correctly figured out (font-family: inherit) before this audit
     touched anything; the other buttons below are now brought in line
     with it rather than the reverse. */
  font-family: inherit;
  font-size: .68rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase;
  cursor: pointer; transition: var(--transition), border-bottom-color .15s;
  white-space: nowrap;
}
.tab:hover { color: var(--gold-text); }
.tab.active {
  background: #ffffff;
  color: var(--gold-text);
  border-bottom-color: var(--gold);
  font-weight: 800;
  box-shadow: none;
}

.tab-pane { display: none; }
.tab-pane.active { display: block; }

/* ── CHART CARDS ─────────────────────────────────────────── */
.chart-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px;
  margin-bottom: 14px;
}
.chart-title {
  font-size: .7rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-secondary);
  margin-bottom: 14px;
  display: flex; align-items: center; gap: 7px;
}
/* Chart.js with maintainAspectRatio:false fills its container height.
   Wrap the canvas in a div capped at 85vh so charts never dominate the screen. */
.chart-wrap {
  position: relative;
  height: min(360px, 62vh); /* comfortable default; never taller than 62vh */
  max-height: 62vh;
  width: 100%;
}
canvas { width: 100% !important; height: 100% !important; }

/* ── MC STATS ────────────────────────────────────────────── */
.mc-stats-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 8px; margin-top: 14px;
}
.mc-stat {
  background: var(--bg-raised); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 11px; text-align: center;
}
.mc-stat-label { font-size: .65rem; color: var(--text-secondary); letter-spacing: .05em; text-transform: uppercase; margin-bottom: 5px; }
.mc-stat-val { font-family: 'DM Mono', monospace; font-size: .95rem; font-weight: 500; }

/* MC methodology note */
.mc-note {
  margin-top: 10px;
  font-size: .68rem;
  color: var(--text-muted);
  padding: 8px 10px;
  background: var(--bg-raised);
  border-radius: var(--radius-sm);
  border-left: 2px solid var(--gold-dim);
  line-height: 1.6;
}
.mc-note strong { color: var(--gold); }

/* ── TABLE ───────────────────────────────────────────────── */
/* CANONICAL PATTERN — horizontally-scrollable data table. .table-wrap
   already had overflow-x: auto, so on paper every table here (year-by-
   year, depreciation, sensitivity, tornado) should already scroll on
   mobile — but `table { width: 100% }` below capped every table at
   exactly its container's width, so it could never grow wider than
   .table-wrap and there was nothing to scroll: columns just got
   squeezed illegibly narrow instead. min-width: 100% (not width: 100%)
   keeps the same "fill the container on desktop" look when the content
   fits, while letting the table grow past 100% and trigger the
   wrapper's real horizontal scroll once it doesn't — same fix needed
   for a future calculator's own data table: overflow-x: auto on the
   wrapper is necessary but not sufficient; the table inside it must be
   allowed to exceed the wrapper's width. */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  /* Discoverability: overflow-x:auto's native scrollbar is easy to miss
     on mobile (many browsers hide it entirely until mid-scroll). A
     persistent right-edge fade is the standard "there's more here"
     affordance — background-attachment:local vs (default) scroll is
     what makes the two inner gradients scroll WITH the table content
     while the outer two solid blocks stay pinned to the wrapper's own
     edges, so the fade only shows while there's unscrolled content
     left in that direction (it disappears at each scroll extreme). */
  background:
    linear-gradient(to right, var(--bg-surface) 30%, rgba(255,255,255,0)) 0 0,
    linear-gradient(to left, var(--bg-surface) 30%, rgba(255,255,255,0)) 100% 0,
    linear-gradient(to right, rgba(15,17,24,.12), rgba(15,17,24,0) 100%) 0 0,
    linear-gradient(to left, rgba(15,17,24,.12), rgba(15,17,24,0) 100%) 100% 0;
  background-repeat: no-repeat;
  background-color: var(--bg-surface);
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
/* Small explicit hint text on top of the fade, narrow screens only —
   the fade alone can read as a design flourish rather than "scroll me"
   at a glance; spelling it out removes the ambiguity. Hidden once the
   table actually fits without scrolling (>= 700px, matching PvS's own
   .edu-glossary single-column breakpoint) since there's nothing to
   discover there. */
.table-wrap::before {
  content: '⟷ Scroll to see all columns';
  display: block;
  padding: 6px 11px 0;
  font-size: .68rem;
  font-weight: 600;
  color: var(--text-muted, #7a8a9a);
  text-align: right;
}
@container pvs-main (min-width: 700px) {
  .table-wrap::before { display: none; }
}
table { width: auto; min-width: 100%; border-collapse: collapse; font-family: 'DM Mono', monospace; font-size: .7rem; }
/* FONT FIX (2026-08, table-font audit) — thead th used to inherit
   table's DM Mono uncontested. Checked against mortgage.html's own
   amortisation schedule table live: its <th> AND <td> both compute to
   plain "Inter Tight" — mortgage doesn't monospace any of its table,
   headers or numbers. This table's own column headers ("Year", "Prop
   Value", "Loan Balance", the "Property"/"Shares"/etc. group headers)
   are labels, not data, so they get the same explicit Inter Tight
   override thead th[title]:hover::after already needed further down
   this file for the identical reason: `thead th { font-family: inherit
   }` would NOT reach body's font here — the nearest ancestor setting
   font-family is <table> itself (DM Mono, intentionally, for the
   numeric td cells below), so inherit would just re-inherit DM Mono
   from it. The literal stack has to be spelled out to actually reach
   past that ancestor.
   tbody td is DELIBERATELY left on DM Mono, unlike mortgage's own
   table: every column here is a dollar figure, percentage, or Y/N
   flag in a genuinely dense, many-column financial table (mortgage's
   schedule has 7 columns; this one has 50+), where monospace digit
   alignment carries real value mortgage's simpler table doesn't need.
   That's a deliberate PvS-specific choice, not an oversight — matching
   mortgage's table font exactly was considered and rejected here. */
thead th {
  background: var(--bg-raised); padding: 9px 11px;
  text-align: right; font-size: .66rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--text-secondary);
  border-bottom: 1px solid var(--border); white-space: nowrap; position: relative;
  font-family: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial,
               'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}
thead th:first-child { text-align: left; }

/* Section header row spans property / shares column groups */
.section-header-prop,
.section-header-shares,
.section-header-exit {
  text-align: center !important; font-size: .65rem;
  padding: 6px 10px; letter-spacing: .06em; border-bottom: 2px solid transparent;
}
.section-header-prop   { color: var(--property) !important; border-bottom-color: var(--property); background: rgba(78,142,247,.07) !important; }
.section-header-shares { color: var(--shares)   !important; border-bottom-color: var(--shares);   background: rgba(78,203,113,.07) !important; }
.section-header-exit   { color: var(--warning)  !important; border-bottom-color: var(--warning);  background: rgba(245,166,35,.07) !important; }

/* Tooltip icon inside column header */
.th-tip { display: inline-block; font-size: .55rem; opacity: .5; cursor: help; vertical-align: super; margin-left: 2px; font-style: normal; transition: opacity .15s; }
thead th[title]:hover .th-tip { opacity: 1; }
thead th[title]:hover { background: var(--bg-hover) !important; color: var(--text-primary) !important; cursor: help; }

tbody tr { border-bottom: 1px solid var(--border); transition: background .12s; }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--bg-raised); }
tbody td { padding: 7px 11px; text-align: right; color: var(--text-secondary); }
tbody td:first-child { text-align: left; color: var(--text-secondary); }
.td-property { color: var(--property) !important; }
.td-shares   { color: var(--shares) !important; }
.td-exit     { color: var(--warning) !important; opacity: 0.85; }
.td-exit-highlight { color: var(--warning) !important; font-weight: 600; background: rgba(245,166,35,.08) !important; }
.td-pos      { color: var(--success) !important; }
.td-neg      { color: var(--danger) !important; }
.td-gold     { color: var(--gold) !important; }
.row-highlight td { background: rgba(201,168,76,.04); }
.yr-age { color: var(--text-muted); font-size: .6rem; margin-left: 4px; }

/* ── ASSUMPTIONS ─────────────────────────────────────────── */
.assumptions-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
.assumption-card {
  background: var(--bg-surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 14px;
}
.assumption-card h4 {
  font-size: .65rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 10px;
  padding-bottom: 7px; border-bottom: 1px solid var(--border);
}
.assumption-row { display: flex; justify-content: space-between; align-items: center; padding: 3px 0; }
.assumption-key { font-size: .68rem; color: var(--text-secondary); }
.assumption-val { font-family: 'DM Mono', monospace; font-size: .68rem; color: var(--gold); }

/* ── SENSITIVITY TABLE ───────────────────────────────────── */
.sensitivity-grid table th, .sensitivity-grid table td { text-align: center; }
.cell-green { background: rgba(78,203,113,.10); color: var(--shares) !important; }
.cell-red   { background: rgba(224,85,85,.08);  color: var(--danger) !important; }

/* ── EXPORT BAR ──────────────────────────────────────────── */
/* .export-bar/.btn-export moved to css/calculators.css — 2026-08 Stage 2.
   (.export-bar is still referenced by selector in the @media print rule
   further down this file — that's fine, it doesn't need its own rule
   here to be a valid selector reference.) */

/* ── SECTION INTRO ───────────────────────────────────────── */
.section-intro {
  font-size: .74rem; color: var(--text-secondary);
  margin-bottom: 10px; line-height: 1.65;
  padding: 7px 9px;
  background: var(--bg-input);
  border-radius: var(--radius-sm);
  border-left: 2px solid var(--gold-dim);
}

/* ── DR BADGE ────────────────────────────────────────────── */
.dr-badge {
  display: inline-block;
  background: rgba(240,100,180,.08);
  border: 1px solid rgba(240,100,180,.22);
  border-radius: 99px; padding: 1px 7px;
  font-size: .58rem; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
  color: #f064b4; margin-left: 5px;
}

/* ── LOADING OVERLAY ─────────────────────────────────────── */
.loading-overlay {
  display: none; position: fixed; inset: 0;
  background: rgba(13,15,20,.75);
  z-index: 999; align-items: center; justify-content: center;
  backdrop-filter: blur(4px);
}
.loading-overlay { background: rgba(244,245,248,.75); }
.loading-overlay.visible { display: flex; }
.loading-spinner {
  width: 40px; height: 40px;
  border: 3px solid var(--border);
  border-top-color: var(--gold);
  border-radius: 50%;
  animation: spin .6s linear infinite;
}
.loading-label {
  color: var(--text-secondary);
  font-size: .8rem; margin-top: 14px; text-align: center;
}
.loading-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── DIVIDER ─────────────────────────────────────────────── */
.divider { height: 1px; background: var(--border); margin: 10px 0; }

/* ── RESPONSIVE ──────────────────────────────────────────── */
@container pvs-main (max-width: 1100px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@container pvs-layout (max-width: 1200px) {
  .main-content { grid-template-columns: 320px 1fr; }
}
/* Key Wide -> Medium/Narrow tier threshold (PvS's own tuned value —
   equivalent to the 799.98px threshold the other calculators share via
   tepuy.css, kept at PvS's original 900px rather than forced to match). */
@container pvs-layout (max-width: 900px) {
  .main-content { grid-template-columns: 1fr; }
  .sidebar { height: auto; position: static; }

  /* #page-head-placeholder now lives inside .results-panel (moved 2026-08
     so its width matches the main column on desktop — see .page-head
     above) but on mobile it still needs to render ABOVE .sidebar, same
     reading order as before the move. display:contents flattens
     .results-panel so its children become direct grid items of
     .main-content, letting `order` place the hero first without moving
     anything in the DOM — the same trick tepuy.css uses for Mortgage/
     Retirement's own #page-head-placeholder at their narrow tier. */
  .main-content > .results-panel { display: contents; }
  .main-content > .results-panel > #page-head-placeholder { order: 1; }
  .main-content > .sidebar { order: 2; }
  .main-content > .results-panel > :not(#page-head-placeholder) {
    order: 3;
    /* .results-panel's own min-width: 0 (see "RESULTS PANEL" above) no
       longer applies to anything once it's display: contents — its
       children are the real grid items now, each needing the same
       override for the same reason (a wide table's min-content width
       must not blow out the page; see the "TABLE" section). */
    min-width: 0;
  }
}
@container pvs-main (max-width: 600px) {
  .kpi-grid { grid-template-columns: 1fr 1fr; }
  .assumptions-grid { grid-template-columns: 1fr; }
  .mc-stats-grid { grid-template-columns: 1fr 1fr; }
}

/* ── PRINT ───────────────────────────────────────────────── */
@media print {
  .sidebar, header, .export-bar, .loading-overlay { display: none !important; }
  .main-content { grid-template-columns: 1fr; }
  .results-panel { padding: 0; }
  .chart-card { break-inside: avoid; }
}

/* ─── v5 ADDITIONS ────────────────────────────────────────────── */

/* Info tip tooltip (.info-tip / .info-tip-popup) moved to
   css/calculators.css — 2026-08 Stage 2. Its position:fixed /
   js/pvs-tooltip.js mechanism travels with it unchanged. The *separate*
   native-title-attribute tooltip for table headers below
   (thead th[title]::after) is a different, PvS-only mechanism and
   stays here. */
/* table header tooltip — needs higher z and wider */
thead th[title]:hover::after {
  content: attr(title);
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  min-width: 200px;
  max-width: 300px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 9px 12px;
  font-size: .68rem;
  line-height: 1.6;
  color: var(--text-secondary);
  z-index: 300;
  box-shadow: var(--shadow-lg);
  white-space: normal;
  pointer-events: none;
  font-family: 'Inter Tight', sans-serif;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
thead th[title] { position: relative; }

/* PPOR note */
.ppor-note {
  background: rgba(201,168,76,.10);
  border: 1px solid rgba(201,168,76,.25);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  font-size: .71rem;
  color: var(--gold-light);
  margin: 4px 0 8px;
  line-height: 1.5;
}

/* ── EDUCATIONAL SECTION ─────────────────────────────────────────── */
/* "Learn & Reference" (.edu-*) moved to css/calculators.css — 2026-08
   Stage 2. Consolidated from 3 competing passes scattered across this
   file (this base rule plus two later override passes further down,
   see the "EDU PANEL" and "COMPREHENSIVE CONTRAST FIX v2" sections
   below) into one clean definition per selector in the shared file,
   and the panel-heading background was deliberately changed from a
   cream tint to white per the Stage 2 plan — see calculators.css. */

/* ─── v5.1 ADDITIONS ──────────────────────────────────────────── */

/* .btn-pdf moved to css/calculators.css — 2026-08 Stage 2. */

/* .insights-bar and .insights-title removed here (2026-08): dead code —
   both targeted markup (#insights_bar and its "Key Insights" title div)
   that no longer exists on the page, deleted when Key Insights moved
   into its own tab earlier today. .insights-list/li below are kept —
   that markup is still live inside the Insights tab pane. */
.insights-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.insights-list li {
  font-size: .8rem;
  color: var(--text-primary);
  opacity: .88;
  padding: 4px 0;
  border-bottom: 1px solid rgba(201,168,76,.1);
  line-height: 1.6;
}
.insights-list li:last-child { border-bottom: none; }
.insights-list li::before { content: '• '; color: var(--gold); }

/* Light mode stronger text in inputs */
input,
select,
textarea {
  color: #0f1118;
}
label { color: #2c3248; }
.hint { color: #505870; }

/* Better mobile layout — split from the original combined query: the
   stacking/overlap-prevention rules are a pvs-layout concern (redundant
   with the 900px stacking rule above for .main-content, but preserved
   as-is rather than deduplicated), while kpi-grid/winner-banner are sized
   against the results panel's own width (pvs-main). */
@container pvs-layout (max-width: 768px) {
  .main-content {
    grid-template-columns: 1fr;
  }
  .sidebar {
    max-height: none;
    position: relative;
    /* CONFIRMED BUG (2026-08) — the base `.sidebar` rule (Wide tier) sets
       top: 60px, meaningful there because position is sticky. That top
       value is inert under both position: static (900px tier above) and
       the OLD position here — but position: relative DOES honor top/left/
       right/bottom offsets, and this rule never reset it. The result:
       switching to position: relative silently reactivated a 60px
       downward visual shift that was previously harmless, pushing
       .sidebar 60px into whatever renders after it (#results_content) —
       confirmed live with Playwright WebKit + a real calc-engine-driven
       render: .sidebar's bottom edge lands ~36px past #results_content's
       top after Run Comparison's scrollIntoView, visibly overlapping the
       winner banner with the sidebar's Save/Load Scenario buttons. A
       relatively-positioned element with an inherited offset and no
       layout-affecting side effect is exactly the kind of latent trap
       that survives until some OTHER change (like position finally
       becoming relative) makes it real — reset explicitly here rather
       than relying on the cascade not changing again upstream. */
    top: auto;
  }
  .results-panel {
    padding: 12px;
    /* No margin-top here anymore (was: 40px, "prevent overlap with
       sidebar buttons") — dead weight since the 900px tier above made
       .results-panel display:contents, which strips its own box
       (padding/margin included) so its children can flatten into
       .main-content's flex order alongside .sidebar. A margin-top on a
       display:contents element has nothing to apply to. The equivalent
       clearance now lives directly on #pvs_shared_banner/.empty-state/
       #results_content below — the actual elements that render right
       after .sidebar once stacked. */
  }
  /* The real fix for the stacked-mobile clearance the rule above used to
     provide: applied directly to the elements that now render immediately
     after .sidebar (order: 2) in the flattened order: 3 group, since
     .results-panel itself no longer has a box to hang a margin off of. */
  #pvs_shared_banner,
  .empty-state,
  #results_content {
    margin-top: 24px;
  }
}
@container pvs-main (max-width: 768px) {
  .kpi-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@container pvs-main (max-width: 480px) {
  .kpi-grid {
    grid-template-columns: 1fr;
  }
}
@container pvs-layout (max-width: 480px) {
  header { padding: 0 12px; }
  /* .edu-tabs .edu-tab responsive override moved to css/calculators.css
     — 2026-08 Stage 2. */
}

/* ═══════════════════════════════════════════════════════════════
   TEPUY NAVBAR — now shares tepuy.css's rules via the normal cascade
   (tepuy.css is loaded before this file — see the <link> order in
   property_vs_shares.html). This section used to carry a full parallel
   copy of every .navbar/.logo-title/.nav-links/.sub-menu/.hamburger/
   .cta-button/.plan-badge rule tepuy.css already defines for the exact
   same shared markup (includes/navbar.html) — that's why fixes here kept
   being incomplete: each patch matched one property while the copy
   itself stayed in place to drift on the next one. Everything tepuy.css
   already styles identically has been deleted; only genuine, functional
   exceptions remain below, each explained.
   ═══════════════════════════════════════════════════════════════ */

/* EXCEPTION 1 — height math. PvS's own layout (.sidebar, .results-panel,
   .main-content) is hardcoded around a 60px-tall navbar (height: calc(
   100vh - 60px), top: 60px, etc. — search this file for "60px" if that
   ever needs to change). tepuy.css's own ".navbar-inner" only guarantees
   min-height: 64px, and ".navbar" itself sets no height at all — so
   height: 60px must stay pinned here on both, or PvS's sidebar/results
   layout would drift out of alignment with the navbar. */
.navbar { height: 60px; }
.navbar-inner { height: 60px; }

/* EXCEPTION 2 (retired 2026-08) — this used to force the navbar to
   position: sticky instead of tepuy.css's own position: fixed, on the
   theory that PvS's navbar "has always been sticky... in normal flow,
   reserving its own space naturally." That was never actually true in a
   way that worked: <header>'s containing block for sticky purposes is
   #navbar-placeholder, a box exactly as tall as the header itself — with
   zero room for "sticky" to hold onto, it just scrolled away like a
   normal in-flow element (confirmed live: the navbar tracked scrollY
   1:1, on every load). This override, plus the equally-guilty (and now
   also removed) `header:not(.page-head){position:sticky}` rule above,
   is why the navbar didn't stay visible while scrolling — the one
   thing every other calculator's navbar does correctly, unopposed,
   straight from tepuy.css. Deleting both lets ".navbar { position: fixed
   }" cascade through as-is, matching Mortgage/Offset vs Shares/
   Retirement exactly — this IS the canonical calculator navbar pattern;
   a future calculator needs zero navbar CSS of its own for this to work,
   same as those three. body's padding-top: 60px (see above) is the other
   half of this fix — required for a fixed navbar, restored there. */

/* EXCEPTION 3 (retired) — this used to key a dark navbar tint off PvS's
   own light/dark toggle, which is now removed entirely (palette redesign
   2026-08: no page keeps a dark navbar or a theme toggle). tepuy.css's
   base ".navbar" rule (bone-tinted) applies with zero PvS CSS needed,
   exactly like every other calculator/blog page. */

/* EXCEPTION 4 — mobile menu positioning AND opacity. tepuy.css's shared
   mobile dropdown is position: absolute, anchored below the navbar. That
   trips a real WebKit bug on iOS Safari (an absolutely-positioned child
   of a position: sticky ancestor scrolls/repaints incorrectly), so PvS's
   panel uses fixed positioning + safe-area insets + a GPU-compositing
   hint instead — a full-height sheet rather than a dropdown.
   Border/text color are NOT redeclared: they still come from tepuy.css's
   own mobile rule via the same --nav-text/--nav-border custom properties
   Exception 3 sets. Background IS redeclared, at higher opacity than
   Exception 3's 68%/tepuy.css's 82% — that level is tuned for a slim bar
   or a small dropdown sitting over a limited area, which is what it is
   on every other page. Here it's behind a full-height sheet covering
   this page's own busy content (hero text, badges), where the same
   opacity let that content visibly bleed through — confirmed by
   screenshot, not assumed. 92% matches PvS's own prior tuning for this
   exact full-height-sheet case, just recomputed from tepuy.css's brand
   colors instead of PvS's old --bg-surface token.
   Breakpoint matches tepuy.css's own (768px) — this used to be a
   mismatched 900px, which meant PvS alone showed its mobile hamburger
   menu in the 768–900px tablet range while every other page still showed
   the full desktop nav-links row. */
@media (max-width: 768px) {
  .navbar {
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
    will-change: transform;
    padding-left: env(safe-area-inset-left, 0px);
    padding-right: env(safe-area-inset-right, 0px);
  }
  .navbar .nav-links {
    position: fixed;
    top: 60px;
    left: 0;
    right: 0;
    max-height: calc(100vh - 60px);
    padding-bottom: max(12px, env(safe-area-inset-bottom, 12px));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    z-index: 999;
  }
  .navbar .nav-links {
    background: color-mix(in srgb, var(--bone) 92%, transparent);
  }
}

/* EXCEPTION 5 — wordmark + plan-badge font-family. tepuy.css's ".navbar
   .logo-title" and ".plan-badge" rules only set font-weight/size/color
   (and radius/background for the badge), not font-family — on pages
   that load ONLY tepuy.css, they don't need to: both just inherit 'Inter
   Tight' from tepuy.css's own "body" rule. Retirement-parity pass
   (2026-08): this override is now redundant (PvS_style.css's own body
   rule was repointed to 'Inter Tight' too, so the inheritance these two
   selectors were fighting for no longer disagrees), but left in place
   rather than removed — harmless belt-and-suspenders, and removing it
   is a needless risk for zero visual change. */
.logo-title,
.plan-badge {
  font-family: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

/* No tepuy.css equivalent exists for active-nav-link highlighting (it
   has no concept of a "current page" state in the shared nav) — kept as
   a genuine PvS-only addition, not a duplicate of anything. */
.nav-links > a.active,
.nav-links > a[aria-current="page"] {
  color: var(--gold);
  background: rgba(201,168,76,.1);
}

/* EDU PANEL "Behind the Math" readability fix + LIGHT MODE stronger-text
   pass's .edu-* lines: both moved to css/calculators.css, consolidated,
   as part of the 2026-08 Stage 2 Learn & Reference extraction. */

/* ═══════════════════════════════════════════════════════════════
   LIGHT MODE — stronger text throughout
   ═══════════════════════════════════════════════════════════════ */

.field label { color: #1a2030 !important; font-weight: 500; }
.hint, .range-val { color: #4a5068 !important; }
.kpi-label { color: #1a2030 !important; }
.kpi-value { color: #0f1118 !important; }
/* .tab / .tab.active dark-navy !important overrides removed here
   (2026-08): leftover from the old dark-theme-era "stronger text" patch,
   already dead before this pass (both were silently beaten by the
   #374060/#0f1118 !important pair further down this file — see the
   "Tabs" section removed alongside this one), and would now also fight
   the ported underline-tab design's gold-text/font-weight:800 active
   state. Confirmed removal doesn't affect anything: the tab redesign's
   own base rule sets final, correct, WCAG-checked colors directly. */
table th { color: #0f1118 !important; }
table td { color: #1a2030 !important; }
/* .edu-header-title/.edu-tab/.edu-tab.active/.edu-glossary dt/dd color
   overrides moved to css/calculators.css — 2026-08 Stage 2. */
.insights-list li { color: #1a2030 !important; }

/* Pro gate notice */
/* .pro-gate-notice removed — no pro gating */

/* ═══════════════════════════════════════════════════════════════
   DISCLAIMER FOOTER
   ═══════════════════════════════════════════════════════════════ */
.disclaimer-footer {
  background: rgba(180,40,40,.07);
  border-top: 1px solid rgba(180,40,40,.2);
  padding: 10px 24px;
  position: sticky;
  bottom: 0;
  z-index: 80;
  backdrop-filter: blur(8px);
}
.disclaimer-inner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: 1400px;
  margin: 0 auto;
  font-size: .71rem;
  color: var(--text-secondary);
  line-height: 1.5;
}
.disclaimer-icon { font-size: .9rem; flex-shrink: 0; margin-top: 1px; }
.disclaimer-inner strong { color: var(--text-primary); }
.disclaimer-inner a { color: var(--gold); text-decoration: underline; }

.disclaimer-footer {
  background: rgba(180,40,40,.05);
}
.disclaimer-inner { color: #505870; }
.disclaimer-inner strong { color: #0f1118; }

/* field-note utility */
.field-note {
  font-size: .65rem;
  line-height: 1.5;
  margin-top: 4px;
}



/* ═══════════════════════════════════════════════════════════════
   LOGO FIX — hard cap so the image can never overflow header
   ═══════════════════════════════════════════════════════════════ */
/* .calc-header-logo removed — logo only in top navbar */

/* ═══════════════════════════════════════════════════════════════
   BASIC / ADVANCED MODE TOGGLE BAR
   ═══════════════════════════════════════════════════════════════ */
.mode-toggle-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding: 8px 10px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.mode-toggle-label {
  font-size: .65rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
  flex-shrink: 0;
}

.mode-toggle-group {
  display: flex;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px;
  gap: 2px;
}

.mode-btn {
  padding: 4px 12px;
  border: none;
  border-radius: calc(var(--radius-sm) - 1px);
  font-family: inherit; /* <button> — see .tab's comment above */
  font-size: .68rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
  background: transparent;
  color: var(--text-muted);
  letter-spacing: .02em;
  white-space: nowrap;
}

.mode-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.mode-btn.active {
  background: var(--gold);
  color: #0d0f14;
  box-shadow: 0 1px 4px rgba(201,168,76,.30);
}

.mode-btn.active {
  /* Was #ffffff — 3.32:1 on the clay --gold background, below AA. --gold-on
     is the accessible pairing for whatever --gold resolves to in this file. */
  color: var(--gold-on, #0E1512);
}

.mode-hint {
  font-size: .62rem;
  color: var(--text-muted);
  font-style: italic;
  margin-left: auto;
  white-space: nowrap;
}



/* ═══════════════════════════════════════════════════════════════
   SCENARIO SAVE / LOAD BUTTONS & DROPDOWN
   Moved to css/calculators.css — 2026-08 Stage 2, as part of the shared
   export/print/reset/save/load button strip (.btn-scenario,
   .scenario-auth-hint, .scenario-load-dropdown, .sld-*, plus the
   @keyframes fadeIn it used, which had no other consumer in this file).
   ═══════════════════════════════════════════════════════════════ */

/* .section-icon font-family override removed — the icon system itself
   (markup + .section-icon/.icon-* CSS) was removed in the Step 3 sidebar
   rebuild; nothing to style. */

/* Login/Signup button in navbar (triggers Auth0 directly) */
.nav-login-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: 'Inter Tight', sans-serif;
  font-size: .82rem;
  font-weight: 500;
  padding: 6px 12px;
  cursor: pointer;
  transition: var(--transition);
  white-space: nowrap;
}
.nav-login-btn:hover {
  color: var(--gold);
  border-color: var(--gold-dim);
  background: rgba(201,168,76,.07);
}
.nav-login-btn { color: #2c3248; }
.nav-login-btn:hover { color: #0f1118; background: #eaecf2; border-color: var(--gold); }

/* Assumption card heading: brighter */
.assumption-card h4 {
  font-size: .67rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-secondary); margin-bottom: 10px;
  padding-bottom: 7px; border-bottom: 1px solid var(--border);
}





/* ============================================================================
   v6 Cashflow Neutrality UI
============================================================================ */

.cashflow-verification .chart-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cfv-status {
  font-size: 0.95rem;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.10);
}

.cfv-status.ok {
  border-color: rgba(60, 220, 150, 0.35);
  background: rgba(60, 220, 150, 0.12);
}

.cfv-status.bad {
  border-color: rgba(255, 120, 120, 0.35);
  background: rgba(255, 120, 120, 0.12);
}

.cfv-meta {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
  padding: 10px 14px 0;
}

.cfv-meta .k {
  display: inline-block;
  min-width: 84px;
  opacity: 0.8;
}

.cfv-meta .v {
  font-weight: 600;
}

.cfv-table table {
  width: 100%;
}

.cfv-table tbody tr.ok td {
  opacity: 0.92;
}

.cfv-table tbody tr.bad td {
  opacity: 0.92;
}

.cfv-table tbody tr.bad td:last-child {
  font-weight: 700;
}





/* ============================================================
   ADDITIONS — extracted from inline HTML styles + new features
   Organised: Share buttons → DSC → Share Card → MC note →
              Shared banner → Light-mode contrast → Font floor
   ============================================================ */


    /* .btn-share/.btn-share-export moved to css/calculators.css —
       2026-08 Stage 2. */
    /* ═══════════════════════════════════════════════════════════════════
       DECISION SUMMARY CARD — shareable, narrative output layer
       Sits between insights-bar and kpi-grid.
    ═══════════════════════════════════════════════════════════════════ */
    /* Retirement-parity pass (2026-08, results-section cleanup): this
       card is now the SINGLE condensed result banner (the old "★ winner
       banner" was removed — see results_content's HTML comment). Its top
       accent was previously teal-to-GOLD — the gold half wasn't signaling
       anything (this bar isn't the property/shares winner indicator,
       that's .dsc-winner-label below), just a leftover decorative accent
       that read as an off-brand orange stripe next to retirement.html's
       teal/green system. Ported to retirement's own brand green
       (#1a5236, tepuy.css's --cardH-bg) instead. Background here is
       overridden to plain white by the "CONTRAST FIX v2" block further
       down this file (#decision_summary_card { background:#fff; ... }) —
       matching retirement.html's own white card background, so left as
       white rather than fighting that with a second, competing value. */
    #decision_summary_card {
      display: none;
      background: #ffffff;
      border: 1px solid var(--border);
      border-radius: 14px;
      padding: 22px 24px 18px;
      margin: 16px 0 10px;
      position: relative;
      overflow: hidden;
    }
    #decision_summary_card::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 3px;
      background: linear-gradient(90deg, #008b95, #1a5236);
      border-radius: 14px 14px 0 0;
    }
    #decision_summary_card.visible { display: block; }

    /* ── Headline ── */
    .dsc-headline {
      font-size: 1.05rem;
      font-weight: 700;
      color: var(--text-primary);
      line-height: 1.4;
      margin-bottom: 14px;
      padding-right: 8px;
    }
    .dsc-headline .dsc-winner-label {
      display: inline-block;
      font-size: 0.68rem;
      font-weight: 700;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      padding: 2px 8px;
      border-radius: 4px;
      margin-right: 8px;
      vertical-align: middle;
      position: relative;
      top: -1px;
    }
    .dsc-winner-label.property { background: rgba(0,139,149,0.12); color: var(--dsc-teal-text); }
    .dsc-winner-label.shares   { background: rgba(201,168,76,0.15); color: var(--gold-text); }

    /* ── Insight tiles ── */
    .dsc-insights {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
      gap: 10px;
      margin-bottom: 16px;
    }
    .dsc-insight-item {
      background: var(--bg-raised);
      border: 1px solid var(--border);
      border-radius: 9px;
      padding: 10px 12px;
    }
    .dsc-insight-label {
      font-size: 0.62rem;
      font-weight: 600;
      letter-spacing: 0.07em;
      text-transform: uppercase;
      color: var(--text-muted);
      margin-bottom: 3px;
    }
    .dsc-insight-value {
      font-size: 0.88rem;
      font-weight: 600;
      color: var(--text-primary);
      line-height: 1.35;
    }
    .dsc-insight-value.teal { color: var(--dsc-teal-text); }
    .dsc-insight-value.gold { color: var(--gold-text); }
    .dsc-insight-value.warn { color: #8b3a00; }

    /* ── Assumption strip ── */
    .dsc-assumption-strip {
      display: flex;
      flex-wrap: wrap;
      gap: 6px 16px;
      font-size: 0.71rem;
      color: var(--text-muted);
      margin-bottom: 14px;
      padding: 8px 10px;
      background: var(--bg-base, rgba(0,0,0,0.15));
      border-radius: 7px;
    }
    .dsc-assumption-strip strong { color: var(--text-secondary); }

    /* ── Footer ── */
    .dsc-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      gap: 8px;
    }
    .dsc-legal {
      font-size: 0.62rem;
      color: var(--text-muted);
      line-height: 1.5;
      flex: 1;
      min-width: 160px;
    }
    /* Retirement-parity pass (2026-08): was gold/clay-bordered
       (var(--gold-dim)/var(--gold)) — the one Share button on the page
       that isn't tied to the property/shares winner color-coding, so
       there's no functional reason for it to differ from
       retirement.html's own Share Result button. Colors ported exactly
       from css/sidebar-polish.css's .ret-share-result-btn. */
    .dsc-share-btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      font-size: 0.75rem;
      font-weight: 600;
      padding: 7px 14px;
      border-radius: 7px;
      border: 1.5px solid #86efac;
      color: #1a5236;
      background: #f0fdf4;
      cursor: pointer;
      transition: background 0.15s, border-color 0.15s;
      white-space: nowrap;
      font-family: inherit;
    }
    .dsc-share-btn:hover {
      background: #dcfce7;
      border-color: #4ade80;
    }
    .dsc-share-btn .dsc-copy-tick { display: none; color: #4caf82; }
    .dsc-share-btn.copied .dsc-copy-label { display: none; }
    .dsc-share-btn.copied .dsc-copy-tick { display: inline; }

    /* A second, later pass further down this file ("COMPREHENSIVE
       CONTRAST FIX v2") used to override every one of these selectors
       again for [data-theme="light"] — this whole first pass was dead
       code, its values never actually reaching the page. Removed rather
       than unprefixed; the v2 pass (now unprefixed, see below) is the
       one source of truth. */

    @container pvs-main (max-width: 600px) {
      .dsc-insights { grid-template-columns: 1fr 1fr; }
      .dsc-headline { font-size: 0.95rem; }
    }


    /* ── Shared-scenario banner (shown when URL params present) ── */
    #pvs_shared_banner {
      display: none;
      background: linear-gradient(135deg, rgba(201,168,76,0.12), rgba(201,168,76,0.05));
      border: 1px solid var(--gold-dim, #8a6d28);
      border-radius: 8px;
      padding: 10px 16px;
      margin: 0 0 16px 0;
      font-size: 0.82rem;
      color: var(--gold, #c9a84c);
      align-items: center;
      gap: 8px;
      line-height: 1.4;
    }
    #pvs_shared_banner.visible { display: flex; }
    #pvs_shared_banner strong { color: var(--text-primary, #e8e0d0); }
  


/* ══ SHARE CARD OVERLAY ═══════════════════════════════════════════════════════
   A full-screen modal containing an isolated, screenshot-ready result card.
   Fixed 600px wide, always dark, designed to be captured by html2canvas.
═══════════════════════════════════════════════════════════════════════════ */
#share_card_overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.82);
  z-index: 9000;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  backdrop-filter: blur(4px);
}
#share_card_overlay.visible { display: flex; }

#share_card_outer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  max-width: 640px;
}

/* The card itself — always dark, fixed width, screenshot target */
#share_card {
  width: 600px;
  max-width: 100%;
  background: #111520;           /* slightly lighter than pure black — tiles now visible */
  border-radius: 18px;
  padding: 28px 28px 22px;
  position: relative;
  overflow: hidden;
  font-family: 'Inter Tight', sans-serif;
  box-shadow: 0 24px 80px rgba(0,0,0,0.9);
}

/* Accent bar top */
#share_card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: linear-gradient(90deg, #4e8ef7 0%, var(--gold) 50%, #4ecb71 100%);
}

/* Subtle grid — reduced opacity so it doesn't muddy contrast */
#share_card::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.018) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.018) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
}

/* Header row: winner badge + Tepuy brand */
.sc-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 18px;
  gap: 12px;
}
.sc-brand {
  font-family: 'Inter Tight', sans-serif;
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  color: rgba(255,255,255,0.50);   /* was 0.28 — much more readable */
  text-align: right;
  line-height: 1.4;
  flex-shrink: 0;
}
.sc-brand span {
  display: block;
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;              /* was 0.60 */
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.35);   /* was 0.18 */
  margin-top: 2px;
}

.sc-winner-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.74rem;              /* was 0.65 */
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 6px;
}
.sc-winner-badge.property {
  background: rgba(78,142,247,0.22);
  color: #93c0ff;                  /* brighter — was #7ab3ff */
  border: 1px solid rgba(78,142,247,0.45);
}
.sc-winner-badge.shares {
  background: rgba(78,203,113,0.22);
  color: #80e89a;                  /* brighter — was #6dd98a */
  border: 1px solid rgba(78,203,113,0.45);
}

/* Main headline */
.sc-headline {
  font-family: 'Inter Tight', sans-serif;
  font-weight: 600;
  font-size: 1.32rem;
  line-height: 1.42;
  color: #dde2ee;                  /* slightly softer than pure white for long text */
  margin-bottom: 20px;
  letter-spacing: -0.01em;
}
.sc-headline strong {
  color: #ffffff;
}

/* 2×2 stat grid */
.sc-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 20px;
}
.sc-stat {
  background: #1c2133;             /* was rgba(255,255,255,0.04) ≈ invisible — now a real surface */
  border: 1px solid #2e3550;       /* was rgba(255,255,255,0.07) — now clearly visible */
  border-radius: 10px;
  padding: 14px 16px;              /* slightly more padding */
}
.sc-stat-label {
  font-family: 'DM Mono', monospace;
  font-size: 0.70rem;              /* was 0.58 — now readable */
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);   /* was 0.35 */
  margin-bottom: 7px;
}
.sc-stat-value {
  font-size: 0.96rem;              /* was 0.88 */
  font-weight: 600;
  line-height: 1.35;
  color: #eef0f5;
}
.sc-stat-value.blue  { color: #93c0ff; }   /* brighter for dark bg */
.sc-stat-value.green { color: #80e89a; }
.sc-stat-value.gold  { color: #e0c070; }
.sc-stat-value.warn  { color: #ffaa60; }

/* Divider */
.sc-divider {
  height: 1px;
  background: rgba(255,255,255,0.10);  /* was 0.07 */
  margin: 0 0 14px;
}

/* Assumptions strip */
.sc-assumptions {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 16px;
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;              /* was 0.62 */
  color: rgba(255,255,255,0.50);   /* was 0.30 */
  margin-bottom: 16px;
}
.sc-assumptions strong {
  color: rgba(255,255,255,0.80);   /* was 0.55 */
}

/* Footer: disclaimer + URL */
.sc-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.sc-disclaimer {
  font-size: 0.70rem;              /* was 0.60 */
  color: rgba(255,255,255,0.38);   /* was 0.20 */
  line-height: 1.55;
  flex: 1;
}
.sc-url {
  font-family: 'DM Mono', monospace;
  font-size: 0.72rem;              /* was 0.62 */
  color: rgba(201,168,76,0.80);    /* was 0.55 — gold URL now visible */
  white-space: nowrap;
  flex-shrink: 0;
}

/* Action buttons row (outside the card, not captured) */
.sc-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.sc-action-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'Inter Tight', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 10px 20px;
  border-radius: 9px;
  border: none;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.1s;
}
.sc-action-btn:hover { opacity: 0.88; transform: translateY(-1px); }
.sc-action-btn.primary {
  background: linear-gradient(135deg, #4e8ef7, #2d6fd4);
  color: #ffffff;
}
.sc-action-btn.secondary {
  background: rgba(255,255,255,0.08);
  color: rgba(255,255,255,0.75);
  border: 1px solid rgba(255,255,255,0.12);
}
.sc-action-btn.close-btn {
  background: rgba(255,255,255,0.05);
  color: rgba(255,255,255,0.45);
  border: 1px solid rgba(255,255,255,0.08);
}
.sc-hint {
  font-size: 0.70rem;
  color: rgba(255,255,255,0.28);
  text-align: center;
  font-family: 'DM Mono', monospace;
}


/* ══ LIGHT MODE — COMPREHENSIVE CONTRAST FIX v2 ══════════════════════════════
   Every component that was unreadable in day mode.
   All colours WCAG AA verified against their backgrounds.
══════════════════════════════════════════════════════════════════════════════ */

/* ── Global ── */
body { color: #1a1d26; }
/* html{font-size:15.5px} removed here (2026-08, font-parity audit) — this
   was the actual value that won (later in the file, same specificity as
   the RESET section's own html rule), and the root cause of PvS's whole
   type scale reading ~3-6% smaller than retirement.html's. See the
   RESET section's html rule (now 16px) for the full explanation. */

/* ── Chart cards & titles ──
   Retirement-parity pass (2026-08): shadow re-ported from a single-layer
   PvS-specific value to retirement.html's exact 2-layer --tp-shadow-card,
   same as .section above. */
.chart-card {
  background: #ffffff;
  border: 1px solid #d0d4e0;
  box-shadow: 0 2px 10px rgba(14,21,18,.07), 0 1px 3px rgba(14,21,18,.05);
}
.chart-title { color: #0f1118 !important; font-weight: 700; }

/* ── KPI cards ──
   box-shadow deliberately omitted here (was 0 1px 4px rgba(0,0,0,.05) —
   weaker than and would silently override the visual-weight pass's
   stronger 0 3px 10px rgba(0,0,0,.07) set earlier in this file, since
   this "light mode" block loads later at equal specificity). Found via
   the same class of bug as today's toggle collision — a later override
   block quietly winning over an earlier, intentional value. */
.kpi-card {
  background: #ffffff;
  border: 1px solid #d0d4e0;
}
.kpi-sub { color: #374060 !important; }

/* ── Section intro / hint ── */
.section-intro { color: #374060 !important; }
.chart-card .hint { color: #505870 !important; }

/* Light-mode .section/.section-header/.section-body overrides removed —
   the sidebar's accordion is now .card/.card-header/.card-content, styled
   via css/simulators.css (no light/dark variant to override here). */

/* ── Tabs ──
   Removed here (2026-08): three dark-theme-era !important overrides
   (.tabs border-bottom-color, .tab:not(.active) color, and its hover)
   that would otherwise silently beat the ported underline-tab design's
   own border-bottom-color (#e3ede8, retirement's exact value),
   var(--text-muted) inactive color, and var(--gold-text) hover color —
   same class of collision as everything else found in today's audit.
   The tab redesign's base rule already sets final, WCAG-checked colors
   directly, so these patches are redundant now, not just risky. */

.insights-list li { color: #1a2030 !important; font-size: .82rem; }

/* ── Decision Summary Card (inline version) ── */
#decision_summary_card {
  background: #ffffff;
  border-color: #d0d4e0;
  box-shadow: 0 2px 12px rgba(0,0,0,.07);
}
.dsc-headline { color: #0f1118 !important; }
.dsc-insight-item { background: #f7f8fb; border-color: #d0d4e0; }
.dsc-insight-label { color: #505870 !important; }
.dsc-insight-value { color: #0f1118 !important; }
.dsc-insight-value.teal { color: var(--dsc-teal-text) !important; }
.dsc-insight-value.gold { color: var(--gold-text) !important; }
.dsc-insight-value.warn { color: #8b3a00 !important; }
.dsc-assumption-strip { background: #eef0f5; color: #374060; }
.dsc-assumption-strip strong { color: #0f1118; }
.dsc-legal { color: #505870; }
/* Was blue/green (--property/--shares) here — a bug: it recolored the
   badge to a different hue family than its own .teal/.gold classes and
   this same card's base rules use, so the badge changed hue on every
   theme toggle. Restored to the teal/gold family. */
.dsc-winner-label.property { background: rgba(0,139,149,.12); color: var(--dsc-teal-text); }
.dsc-winner-label.shares   { background: rgba(201,168,76,.15); color: var(--gold-text); }
.dsc-share-btn { border-color: #86efac; color: #1a5236; }
.dsc-share-btn:hover { background: #dcfce7; border-color: #4ade80; }

/* ── Monte Carlo stats ── */
.mc-stat { background: #ffffff; border: 1px solid #d0d4e0; }
.mc-stat-label { color: #374060 !important; }
.mc-stat-val { color: #0f1118 !important; }
.mc-note { color: #505870 !important; }

/* ── MC transparency note ── */
.mc-transparency-note {
  background: rgba(184,146,46,.06) !important;
  border-color: rgba(184,146,46,.25) !important;
  color: #374060 !important;
}
.mc-transparency-note strong { color: var(--gold-text) !important; }
.mc-transparency-note li { color: #374060 !important; }

/* ── Sensitivity grid ── */
.sensitivity-grid td { color: #0f1118 !important; }
.sensitivity-grid th { color: #374060 !important; }

/* ── Assumptions grid ── */
.assumption-card { background: #ffffff; border: 1px solid #d0d4e0; }
.assumption-key { color: #374060 !important; }
.assumption-val { color: #0f1118 !important; }

/* ── Cashflow verification ── */
.cashflow-verification { background: #ffffff; border: 1px solid #d0d4e0; }
.cfv-meta .k { color: #505870 !important; }
.cfv-meta .v { color: #0f1118 !important; }

/* ── Empty state ── */
.empty-icon { color: #c0c4d0; }
.empty-title { color: #0f1118 !important; }
.empty-sub { color: #374060 !important; }

/* ── Sidebar controls ── */
.mode-toggle-bar { color: #374060; }
.mode-btn:not(.active) { color: #374060 !important; }
.range-val { color: #374060 !important; }
/* .toggle-label color override removed here (2026-08 Stage 2): value-equal
   to the consolidated rule now in css/calculators.css (#2c3248 ==
   var(--text-secondary)), a no-op duplicate post-extraction. */

/* .edu-faq-item summary/p and .edu-table td color overrides moved to
   css/calculators.css — 2026-08 Stage 2. */

/* ── Share card light-mode variant ── */
#share_card.light-mode {
  background: #f8f9fc;
  box-shadow: 0 24px 80px rgba(0,0,0,.25);
}
/* Remove grid watermark in light mode — causes checkered artifact in html2canvas */
#share_card.light-mode::after {
  display: none;
}
#share_card.light-mode::after {
  background-image:
    linear-gradient(rgba(0,0,0,.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.025) 1px, transparent 1px);
}
#share_card.light-mode .sc-headline { color: #0f1118; }
#share_card.light-mode .sc-headline strong { color: #000; }
#share_card.light-mode .sc-brand { color: rgba(0,0,0,.35); }
#share_card.light-mode .sc-brand span { color: rgba(0,0,0,.22); }
#share_card.light-mode .sc-winner-badge.property { background: rgba(78,142,247,.12); color: #1a4a9a; border-color: rgba(78,142,247,.25); }
#share_card.light-mode .sc-winner-badge.shares   { background: rgba(78,203,113,.12); color: #1a6a35; border-color: rgba(78,203,113,.25); }
#share_card.light-mode .sc-stat { background: #ffffff; border-color: #d4d8e8; }
#share_card.light-mode .sc-stat-label { color: #505870; }
#share_card.light-mode .sc-stat-value { color: #0f1118; }
#share_card.light-mode .sc-stat-value.blue  { color: #1a4a9a; }
#share_card.light-mode .sc-stat-value.green { color: #1a6a35; }
#share_card.light-mode .sc-stat-value.gold  { color: var(--gold-text); }
#share_card.light-mode .sc-stat-value.warn  { color: #8b3a00; }
#share_card.light-mode .sc-divider { background: rgba(0,0,0,.10); }
#share_card.light-mode .sc-assumptions { color: rgba(0,0,0,.40); }
#share_card.light-mode .sc-assumptions strong { color: rgba(0,0,0,.65); }
#share_card.light-mode .sc-disclaimer { color: rgba(0,0,0,.30); }
#share_card.light-mode .sc-url { color: rgba(120,80,0,.55); }

/* ── Global font-size minimums — raise tiny labels to readable floor ── */
/* .kpi-label removed from this list (2026-08, font-parity audit): the
   "floor" here is a flat .73rem, which is SMALLER than .kpi-label's real
   size (.8rem — now css/calculators.css's shared .insight-label/
   .kpi-label rule, previously a local rule right here). Since both
   declarations had equal specificity, this later one was winning and
   silently shrinking .kpi-label from .8rem down to .73rem — a floor rule
   overriding a value that was already above the floor, backwards from
   its own stated purpose. Confirmed via getComputedStyle: KPI card
   labels ("FUTURE VALUE WINNER" etc.) were rendering at 11.315px instead
   of the 12.4-12.8px retirement.html's equivalent labels use. Leaving
   .kpi-label off this list stays correct/necessary even now that the
   sizing lives in calculators.css (loaded after this file, so it would
   win regardless) — no reason to re-add a selector that only ever caused
   harm here. */
.badge,
.sc-stat-label,
.dsc-insight-label,
.mc-stat-label,
.section-intro,
.assumption-key,
.cfv-meta .k,
.hint {
  font-size: max(.73rem, 0.73rem); /* floor ~11px at 15px base — .edu-tab's
  membership in this list moved to css/calculators.css's own consolidated
  .edu-tab rule (2026-08 Stage 2): it's baked into that rule's font-size
  directly (.73rem) rather than reapplied via this shared selector list. */
}


/* SEO editorial styles moved to /css/seo-editorial.06b0142e.css */

.related-tools {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  padding: 0 24px;
}

/* ── RELATED TOOLS GRID ── */
.related-tools {
  margin-bottom: 64px;
}

.related-tools__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px;
}

.related-tool-card {
  display: block;
  padding: 16px;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: var(--text-secondary);
  transition: border-color .15s, background .15s, transform .15s;
}

.related-tool-card:hover {
  border-color: var(--gold);
  background: rgba(201,168,76,.04);
  transform: translateY(-2px);
  color: var(--text-secondary);
  text-decoration: none;
}

.related-tool-card--featured {
  background: rgba(201,168,76,.05);
  border-color: rgba(201,168,76,.25);
}

.related-tool-card--featured:hover {
  background: rgba(201,168,76,.09);
}

.rtc-title {
  font-weight: 600;
  font-size: .85rem;
  color: var(--text-primary);
  margin-bottom: 5px;
}

.rtc-title--gold { color: var(--gold); }

.rtc-desc {
  font-size: .75rem;
  color: var(--text-muted);
  line-height: 1.5;
}

/* Light theme */
.related-tool-card {
  background: #fff;
  border-color: #d0dfe0;
}
.related-tool-card:hover {
  border-color: var(--gold);
  background: #fffbf0;
}
.related-tool-card--featured {
  background: #fffbf2;
  border-color: rgba(201,168,76,.4);
}
.rtc-title { color: #0f1118; }
.rtc-title--gold { color: var(--gold-text); }
.rtc-desc { color: #505870; }

/* ── RESPONSIVE ── */
@media (max-width: 768px) {
  .related-tools { padding: 0 16px; }
  .related-tools__grid { grid-template-columns: 1fr 1fr; gap: 10px; }
}

@media (max-width: 480px) {
  .related-tools__grid { grid-template-columns: 1fr; }
}

/* ── Disclaimer footer ──
   Moved out of property_vs_shares.html's inline <style> block — 2026-08
   Stage 2 (PvS-specific, not part of the shared calculators.css layer). */
#disclaimerFooter { display: flex; }
#disclaimerFooter .disclaimer-inner { display: flex; align-items: flex-start; width: 100%; gap: 0.5rem; }
#disclaimerFooter[hidden] { display: none !important; }
