/* ========================================================================
   DEPLOY PATH: /css/simulators.40bf4328.css
   Tepuy Solutions — shared calculator sidebar shell
   Version: 2026-08-18

   Single source of truth for the sidebar chrome shared by Mortgage,
   Offset vs Shares and LMI: sidebar surface, eyebrow/subtitle block,
   accordion header, and the Calculate-button footer. Extracted from
   mortgage-polish.css / offset-polish.css / lmi-polish.css §1/§2/§3/§5
   per the 2026-08 sidebar chrome audit.

   Step 1.5 (2026-08-18) adds Retirement's Advanced-mode sidebar surface
   and eyebrow/subtitle (#advModePanel .sidebar-title/.sidebar-sub) — see
   §2 below. Retirement's accordion header/card and Calculate-button
   footer are NOT included here: they use a structurally different
   treatment (bordered white card with box-shadow vs the other three's
   borderless card, a 14px/10px radius scale vs 8px, a translucent-circle
   chevron badge the others don't have, and — critically — a non-important
   `display` on .sidebar-footer that js/sidebar-mode.js relies on to toggle
   the footer between Simple and Advanced mode; this file's shared footer
   rule is `!important` and would break that toggle if it applied to
   Retirement). Left fully local to css/sidebar-polish.css. Simple mode
   (Retirement's default view, no accordion at all) uses none of these
   selectors and is unaffected either way.

   Step 3 (2026-08-19, PvS sidebar rebuild) added PvS's accordion/eyebrow/
   footer/slider via a PARALLEL `.sidebar ...` selector branch alongside
   every `body.calc .calc-aside ...` one, because PvS's <body> and <aside>
   were not on the body.calc/.calc-aside pattern. THOSE BRANCHES ARE GONE
   (2026-09, stream P): PvS is on the shared shell, its <aside> IS
   `.calc-aside`, and no page in the repo has an element with class
   `sidebar` any more — every remaining match is a hyphenated name
   (`sidebar-panel`, `sidebar-scroll`, `sidebar-title`, `sidebar-sub`,
   `sidebar-footer`), which `.sidebar` does not select. Seventeen rules
   were reduced to their `body.calc .calc-aside` half; every rule where
   `.sidebar` was the only selector was deleted outright, its explanatory
   comment kept. The declarations were byte-identical across the two
   branches, which is why removing one changes nothing — verified by
   re-driving all five calculators before and after.

   The hazard that made the parallel branch necessary is real and is now
   handled at the other end. PvS's sticky/height/disclaimer-bar-clearance
   math is tuned against values (60px navbar, a measured 54px disclaimer
   height) that do NOT match tepuy.css's own body.calc .calc-aside rule
   (var(--stick-top): 80px), and adopting .calc-aside would otherwise hand
   that rule the sticky/top/height properties and silently reintroduce the
   exact disclaimer-bar-overlap bug PR #83 fixed. css/PvS_style.css now
   restates both at `body.calc .calc-aside` — equal specificity, and it
   loads after this file and after tepuy.css, so it wins on source order.
   test/pvs_on_shared_calc_shell.test.js pins that.

   Load AFTER tepuy.css and BEFORE the page's own -polish.css file, same
   relative order tepuy.css already used for the pre-existing (unused,
   non-!important) "SHARED CALCULATOR SIDEBAR SURFACE" block at
   tepuy.css:4122 — that block never actually applied because these three
   polish files' !important rules always won; this file supersedes it.

   All selectors are scoped under body.calc .calc-aside (or body.calc
   .calc-aside .card* for the bare `aside .card*` rules the three source
   files used) so nothing here can land on a non-calculator page — see
   the audit's "tepuy.css collision risks" section (.section-title,
   .sidebar-scroll, .sidebar-title/.sidebar-sub already bit once in
   PR #83; this file avoids repeating that class of bug).

   Scope of this file, deliberately: ONLY declarations verified
   byte-identical (or provably no-op-different, e.g. padding shorthand
   variants of the same value) across all three source files. Every
   place the three files actually diverge in rendered output is called
   out below and left as a small, commented override in the page's own
   -polish.css file instead of being forced into agreement here.
   Retirement is partially in scope as of Step 1.5 (see above); PvS is
   still fully untouched — out of scope for this pass.
   ======================================================================== */

/* ── Design tokens — same values mortgage/offset/lmi already render today ── */
body.calc .calc-aside {
  --sb-bg:      #f4f8f6;
  --sb-border:  #dce8e1;
  /* Was #9aada6. Its eight text consumers across the five calculators — the
     .*-sidebar-sub and .*-calc-hint pairs — every one of them failed AA. */
  --sb-muted:   var(--text-muted);
  --cardH-bg:   #1a5236;
  --cardH-open: #21673f;
  --cardH-text: #ffffff;
  --inp-border: #c8ddd3;
  --inp-focus:  #1a6b4a;
  --transition: all .18s cubic-bezier(.4,0,.2,1);
}
/* ══════════════════════════════════════════════════════════════════════════
   SHARED CALCULATOR TOKEN BRIDGE  (added 2026-09)

   css/calculators.css — the shared mechanics layer that owns .rtab-*,
   .insight-* / .kpi-* typography, .edu-*, .info-tip and the button strip —
   references generic token names (--gold, --text-secondary, --bg-raised,
   --radius-md, --shadow-md …) because css/PvS_style.css was its first
   consumer and PvS's own :root already defined them. Every other page that
   loads calculators.css has had to define the same names itself:
   css/retirement.css carried a hand-written "Bridge tokens" :root block for
   exactly this, and lmi/offset_vs_shares/mortgage — which did not load
   calculators.css at all until this change — defined NONE of them.

   Measured before moving them here: of the 27 distinct tokens the two shared
   stylesheets consume, 16 resolved to a DIFFERENT value on PvS than on
   Retirement, and 12 resolved to nothing at all on LMI / Offset vs Shares /
   Mortgage. That is why the same byte-identical shared rule rendered
   differently per page — e.g. .info-tip-popup computed rgb(240,241,245) on
   PvS against rgb(247,250,248) on Retirement, from --bg-raised alone.

   This file is the only shared stylesheet ALL FIVE calculators load, so a
   definition placed here reaches all five; one in calculators.css reaches
   two. Values are Retirement's — it is the page whose palette matches the
   rest of the site (green/white/black), and its own block said so.

   var(--tp-shadow-*) aliases are resolved to their literal values here:
   --tp-shadow-card and friends are declared only in css/retirement.css, so
   carrying the alias into a shared file would leave the other four pages
   with an unresolvable custom property.

   ── Cascade position, which is load-bearing ──
   PvS loads tepuy -> simulators -> PvS_style -> calculators, so a :root here
   LOSES to PvS_style.css. Retirement loads tepuy -> retirement.css ->
   simulators -> …, so a :root here WINS over retirement.css. That asymmetry
   is why PvS's overrides had to be deleted for this to take effect on PvS,
   and why retirement.css's now-redundant bridge block was deleted rather
   than left as a silent duplicate.

   ── What is deliberately NOT unified here ──
   PvS keeps its own --gold / --gold-on / --gold-dim / --gold-light /
   --gold-text / --border-focus. Those are the accent hue, not the neutral
   ramp: PvS maps them to the site's marketing --clay (#C97A3A) and
   Retirement maps them to brand green (#1a5236), and BOTH decisions are
   documented and deliberate in their own files. Flipping PvS would restyle
   61 call sites in PvS_style.css (42 for --gold alone) — sliders, range
   values, links, table cells, the disclaimer bar, a chart gradient — which
   is a product decision about the accent, not the token-plumbing fix this
   block is. Recorded in docs/OPEN-ITEMS.md instead.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  /* Neutral text ramp — sage-green family, matching the rest of the site.
     PvS previously rendered these as a cool slate-blue ramp (#0b1f16 /
     #2c3248 / #505870), which is what made its results area read as a
     different product. */
  --text-primary:   #0f1c16;
  --text-secondary: #3d5248;

  /* --text-muted IS now shared, at a value that clears AA. This closes the
     deferral the previous version of this comment recorded.

     THE OLD VALUE. #9aada6 does not clear WCAG AA on any background this site
     paints it on: 2.36:1 on #ffffff, 2.24:1 on #f7faf8, 2.20:1 on #f4f8f6,
     2.03:1 on #e6f0ec, 2.12:1 on #f4f3eb, 2.24:1 on #faf9f4 — against 4.5:1
     for normal text. Measured across the five product calculators, 53
     elements rendered their own text in it and every one of them failed.

     WHERE IT CAME FROM, measured rather than assumed. Only 8 of those 53 got
     it from a token (--sb-muted, below). ZERO got it from --text-muted. The
     other 45 were the same hex pasted as a literal into six stylesheets. So
     retiring the token alone would have fixed 8 of 53 and left the same
     failing value in 45 call sites for the next element to inherit.

     THE NEW VALUE, #55685F, is the one addition this pass makes to the
     palette, and it is an addition rather than a pick from it: clay, moss,
     ink, stone and bone cannot produce a muted tone that is both lighter
     than --text-secondary (#3d5248) and above 4.5:1. It is the same sage
     family as the value it replaces, sits between --text-secondary and the
     old #9aada6 in lightness so the primary / secondary / muted hierarchy
     survives, and measures 5.95:1 on #ffffff, 5.66:1 on #f7faf8, 5.55:1 on
     #f4f8f6, 5.11:1 on #e6f0ec, 5.34:1 on #f4f3eb and 5.64:1 on #faf9f4 —
     worst case 5.11:1, against a 4.5:1 requirement.

     Kept as a plain hex, not a color-mix of existing tokens: #206 measured
     that getComputedStyle returns a custom property with var() substituted
     but color-mix() NOT evaluated, so a derived value cannot be read back by
     the JS that paints canvas labels. */
  --text-muted:     #55685F;

  /* Surfaces */
  --bg-surface: #ffffff;
  --bg-raised:  #f7faf8;
  --bg-hover:   #eef5f1;
  --border:     #e3ede8;

  /* Structural — not brand-specific, so there is no reason for one
     calculator's toggle or tooltip to render a different shape or timing
     than another's. */
  --radius-sm:  4px;
  --radius-md:  8px;
  --transition: all .18s cubic-bezier(.4,0,.2,1);
  --shadow-sm:  0 1px 2px rgba(14, 21, 18, 0.06);
  --shadow-md:  0 2px 10px rgba(14, 21, 18, 0.07), 0 1px 3px rgba(14, 21, 18, 0.05);
  --shadow-lg:  0 6px 20px rgba(14, 21, 18, 0.10);

  /* Accent. PvS overrides all six of these in PvS_style.css (loaded after
     this file); Retirement and the other three take them from here. */
  --gold:       #1a5236;
  --gold-on:    #ffffff;   /* 9.11:1 on #1a5236 */
  --gold-dim:   #3db07e;
  --gold-light: #247857;
  --gold-text:  #1a5236;
  --border-focus: #c8ddd3;
  --shadow-gold:  0 2px 8px rgba(26,82,54,.35);

  --danger: #c0392b;
}

/* NOTE: deliberately NOT reusing tepuy.css's --brand/--cardH-bg tokens —
   --brand resolves to #1f4c3b there (tepuy.css:39), a different green
   than the #1a5236 these three calculators actually render. Reusing it
   would be a silent visual change.

   --transition is the same value PvS_style.css:109 and retirement.css:67
   already use — a deliberate port from the UI polish audit. Applying it
   below to the accordion header/chevron/Calculate-button transitions IS
   an intentional visible change for Mortgage/Offset/LMI (smoother easing,
   not a neutral refactor) — see the audit's finding #5. */


/* ══════════════════════════════════════════════════════════════════════════
   1.  SIDEBAR SURFACE
   ══════════════════════════════════════════════════════════════════════════ */
body.calc .calc-aside,
body.calc .calc-aside .sidebar-panel {
  background: var(--sb-bg) !important;
}

body.calc .calc-aside .sidebar-scroll {
  background: transparent !important;
  scrollbar-width: thin;
  scrollbar-color: #c8ddd3 transparent;
}
body.calc .calc-aside .sidebar-scroll::-webkit-scrollbar { width: 5px; }
body.calc .calc-aside .sidebar-scroll::-webkit-scrollbar-thumb {
  background: #c8ddd3;
  border-radius: 4px;
}

/* Wide-tier flush-right-edge border treatment (border-radius:0, border-right
   only) is INTENTIONALLY NOT included here. All three pages (mortgage,
   offset, lmi) now gate it behind the same @container calc-layout
   (min-width:800px) — lmi-polish.css used to use @media (min-width:1025px)
   instead, a real behaviour mismatch that's now fixed (see the
   breakpoint-mismatch audit, finding #1). Still left duplicated in each
   page's own -polish.css file rather than folded in here: offset's block
   uses a `border` shorthand + --sb-border token where mortgage/lmi use four
   longhands + a hardcoded #dce8e1 (same resolved color, different bytes),
   and consolidating that is a separate cleanup from fixing the threshold. */


/* ══════════════════════════════════════════════════════════════════════════
   2.  SIDEBAR EYEBROW / SUBTITLE

   `.calc-sidebar-title` / `.calc-sidebar-sub` are what js/sidebar-header.js
   renders, and Property vs Shares and retirement both mount it. The three
   page-prefixed pairs below are Mortgage, Offset vs Shares and LMI, which
   still carry hand-written markup; they render identically because this one
   rule serves all of them. Adopting the component there is a one-line mount
   each and is deliberately not done here.

   `.pvs-sidebar-title` / `.pvs-sidebar-sub` are gone from the list too, for
   the plain reason that Property vs Shares mounts the component now and no
   markup anywhere carries those classes. A selector kept after its last
   consumer is how a stylesheet stops describing the page.

   `#advModePanel .sidebar-title` USED TO BE IN THIS LIST and is gone on
   purpose. Retirement's header lived inside the Advanced-mode tabpanel, so
   it needed that ID ancestor to escape `body.calc .calc-aside .sidebar-title`
   in css/tepuy.css — a 1rem, non-caps, border-bottomed heading. Being in
   that panel is also what put the header below the toggle and the Country
   gate, and what hid it entirely in Simple mode. The component renders a
   class name nothing else in the repo targets, so the scoping trick is no
   longer needed and no longer works: leaving the old selector here would
   style an element that no longer exists.
   ══════════════════════════════════════════════════════════════════════════ */
.calc-sidebar-title,
.mort-sidebar-title,
.ovs-sidebar-title,
.lmi-sidebar-title {
  font-size: 0.7rem !important;
  font-weight: 700 !important;
  text-transform: uppercase !important;
  letter-spacing: 0.1em !important;
  color: var(--cardH-bg, #1a5236) !important;
  /* The subtitle rule below has always set its own line-height; this one did
     not, so the eyebrow inherited whatever each page's body used and the
     "shared" component rendered at two different leadings. Measured: 17.92px
     on Property vs Shares (css/PvS_style.css:203 sets 1.6 on an ancestor)
     against 16.24px on Mortgage, Offset vs Shares, LMI and retirement. Same
     class of bug as the toggle reading --gold and --bg-input — a per-page
     value leaking into a component that is supposed to look the same
     everywhere. 1.45 is the value four of the five already rendered, so only
     Property vs Shares moves, by 1.68px on one line. */
  line-height: 1.45 !important;
  padding: 0.35rem 0.9rem 0 !important;
  margin: 0 0 0.1rem !important;
  border-bottom: none !important;
}
.calc-sidebar-sub,
.mort-sidebar-sub,
.ovs-sidebar-sub,
.lmi-sidebar-sub {
  font-size: 0.72rem !important;
  color: var(--sb-muted, var(--text-muted)) !important;
  padding: 0 0.9rem !important;
  margin: 0 0 0.5rem !important;
  line-height: 1.4 !important;
}


/* ══════════════════════════════════════════════════════════════════════════
   3.  ACCORDION HEADER — card, header, chevron, content open/close
   Form-row/input styling (mortgage/lmi's own "§4 FORM ROWS") is out of
   scope for this pass — not part of the audit's Step 1 ask.
   ══════════════════════════════════════════════════════════════════════════ */
body.calc .calc-aside .card,
body.calc .calc-aside .tp-card{
  border: none !important;
  border-radius: 8px !important;
  margin-bottom: 0.35rem !important;
  padding: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  overflow: visible !important;
  transition: none !important;
}
body.calc .calc-aside .card:hover{
  box-shadow: none !important;
  border-color: transparent !important;
}
/* LMI's .card uses overflow:hidden, not visible — real difference, kept as
   a targeted override in lmi-polish.css rather than forced here. */

body.calc .calc-aside .card-header{
  height: 40px !important;
  padding: 0 2.4rem 0 0.9rem !important;
  font-size: 0.775rem !important;
  font-weight: 700 !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  color: var(--cardH-text, #ffffff) !important;
  background: var(--cardH-bg, #1a5236) !important;
  border-radius: 8px !important;
  display: flex !important;
  align-items: center !important;
  cursor: pointer !important;
  user-select: none !important;
  position: relative !important;
  transition: var(--transition, all .18s cubic-bezier(.4,0,.2,1)) !important;
}
body.calc .calc-aside .card-header:hover{ background: var(--cardH-open, #21673f) !important; }
body.calc .calc-aside .card-header[aria-expanded="true"]{ border-radius: 8px 8px 0 0 !important; }

body.calc .calc-aside .card-header h4{
  font: inherit !important;
  color: inherit !important;
  margin: 0 !important;
  line-height: 1 !important;
}

/* SVG chevron */
body.calc .calc-aside .card-header::after{
  content: '' !important;
  position: absolute !important;
  right: 11px !important;
  top: 50% !important;
  transform: translateY(-50%) !important;
  width: 16px !important; height: 16px !important;
  border-radius: 50% !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%23ffffff' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
  background-size: 12px 12px !important;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-color: transparent !important;
  border: none !important; box-shadow: none !important; font-size: 0 !important;
  transition: var(--transition, all .18s cubic-bezier(.4,0,.2,1)) !important;
}
body.calc .calc-aside .card-header[aria-expanded="true"]::after{
  transform: translateY(-50%) rotate(180deg) !important;
}

/* Card content: CSS-driven open/close.
   padding is deliberately declared via the bare `aside .card-content`
   selector, NOT body.calc .calc-aside — tepuy.css:3721 has its own narrow-
   width rule (body.calc .calc-aside .card-content { padding: 0.45rem 0.9rem
   !important }, inside @container calc-layout max-width:799.98px) that
   already out-specifies bare selectors at mobile widths in the original
   site (all three source files used bare `aside .card-content` for
   padding). Matching that here, rather than out-specifying it, keeps
   mobile spacing exactly as it was — see the sidebar audit's tepuy.css
   collision notes. Every other .card-content property is safely scoped. */
body.calc .calc-aside .card-content {
  display: block !important;
  max-height: 0 !important;
  overflow: hidden !important;
  opacity: 0 !important;
  background: #ffffff !important;
  transition: max-height 0.3s ease, opacity 0.22s ease, padding 0.3s ease !important;
}
aside .card-content { padding: 0 !important; }

body.calc .calc-aside .card-content.open,
body.calc .calc-aside .card-content:not([hidden]).open {
  max-height: 3600px !important;
  overflow: visible !important;
  opacity: 1 !important;
}
aside .card-content.open { padding: 0.65rem 0.9rem 0.85rem !important; }
/* NOT including the aside .card-content:not([hidden]).open variant here:
   :not([hidden]) contributes attribute-selector specificity, so that form
   ties with (and, by source order, wins against) tepuy.css's narrow-tier
   rule above — mortgage-polish.css originally had that extra selector and
   so already won this tie; offset/lmi didn't and lost it, ending up with
   tepuy's 0.45rem/0.9rem at mobile widths instead. Keeping the shared rule
   at offset/lmi's original (losing) specificity and restoring mortgage's
   extra selector locally in mortgage-polish.css preserves both outcomes. */

body.calc .calc-aside .card-content[hidden] {
  display: block !important;
  max-height: 0 !important;
  opacity: 0 !important;
  overflow: hidden !important;
}

/* PvS's .sidebar .card-content — a plain, self-contained block rather than
   folded into the bare `aside .card-content` lines above: those exist only
   to lose a specificity tie against tepuy.css's body.calc .calc-aside
   narrow-width rule (see the comment above).

   CORRECTION, 2026-09-06: the sentence that used to end this note —
   "which doesn't exist for PvS at all (PvS isn't under
   body.calc .calc-aside)" — is FALSE, and has been for as long as the file
   has looked like this. calculators/property_vs_shares.html:303 is
   `<body class="calc">` and :327 is `<aside class="calc-aside aside--bare">`,
   exactly like the other four. Verified by rendering, not by reading: PvS
   measures 10.4/14.4/13.6 on open accordion content at 1366 and 900 wide and
   7.2/14.4/7.2 at 700 — i.e. it picks up both the shared rule AND tepuy's
   narrow tier, which it could not do if the premise here were true.

   Corrected as a COMMENT only. The rules below are not changed and no markup
   moved: the code has always behaved correctly, and this note is the one
   thing that was wrong. CLAUDE.md's "verify against execution, not against
   code comments" exists because of exactly this shape — a confident,
   plausible sentence that a reader would otherwise have taken as a
   constraint on where PvS rules may live. */

/* Suppress transitions during init (identical in all three source files) */
body.calc .calc-aside.no-transitions .card-content,
body.calc .calc-aside.no-transitions .card-header { transition: none !important; }


/* ══════════════════════════════════════════════════════════════════════════
   5.  SIDEBAR FOOTER — Calculate button + hint text only.
   The Save/Load/Share scenario row (.ret-scenario-row/.ret-scen-btn) is
   NOT included: offset's version has real differences from mortgage/lmi
   (different button background color #f4f8f6 vs #f0f5f2, missing
   :active/:disabled states, missing letter-spacing) — merging it safely
   needs its own visual-diff pass, left duplicated for now.

   Every selector here is guarded with :not(:has(#advModePanel)) — found
   during Step 1.5's verification, not assumed. Retirement's .sidebar-footer
   has the same class name and DOM shape as mortgage/offset/lmi's, so simply
   linking this file on retirement.html (to pick up §1/§2 below) also
   exposed retirement's footer to this section's !important rules —
   permanently showing the Advanced-mode footer in Simple mode too (an
   !important stylesheet rule always beats an inline style, so
   js/sidebar-mode.js's style.display = 'none' toggle stopped working), and
   silently flipping retirement's Calculate button from its 10px
   (--tp-radius-control) radius to this file's hardcoded 8px. The guard
   keeps this section exactly as Step 1 shipped it for mortgage/offset/lmi
   (none of them have #advModePanel) while leaving retirement's footer
   fully local to sidebar-polish.css, as intended.
   ══════════════════════════════════════════════════════════════════════════ */
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer{
  display: flex !important;
  flex-direction: column !important;
  gap: 0.35rem !important;
  padding: 0.6rem !important;
  flex-shrink: 0 !important;
  border-top: 1px solid var(--sb-border, #dce8e1) !important;
  background: var(--sb-bg, #f4f8f6) !important;
}
/* PvS's .sidebar never contains #advModePanel, so the guard above is
   unnecessary for it (kept only on the body.calc branch, for the reason
   documented in the comment above this section). */

body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer #runBtn,
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer .btn.btn-primary{
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: 100% !important;
  height: 42px !important;
  font-size: 0.88rem !important;
  font-weight: 700 !important;
  color: #ffffff !important;
  background: linear-gradient(135deg, #1a5236 0%, #247857 100%) !important;
  border: none !important;
  border-radius: 8px !important;
  cursor: pointer !important;
  box-shadow: 0 2px 8px rgba(26,82,54,0.22) !important;
  transition: var(--transition, all .18s cubic-bezier(.4,0,.2,1)) !important;
  box-sizing: border-box !important;
}
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer #runBtn:hover,
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer .btn.btn-primary:hover{
  transform: translateY(-1px) !important;
  box-shadow: 0 4px 14px rgba(26,82,54,0.3) !important;
}
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer #runBtn:active,
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer .btn.btn-primary:active{
  transform: translateY(0) !important;
}
/* letter-spacing on #runBtn is NOT shared: mortgage/lmi explicitly set
   0.03em, offset sets nothing (inherits 0.2px from elsewhere in tepuy.css
   — an inherited value, not a knowable "default" to restore by keyword).
   Each page's own -polish.css re-declares what it needs; see mortgage-
   polish.css / lmi-polish.css. */

.mort-calc-hint,
.ovs-calc-hint,
.lmi-calc-hint,
.pvs-calc-hint {
  font-size: 0.68rem !important;
  color: var(--sb-muted, var(--text-muted)) !important;
  text-align: center !important;
  margin: 0 !important;
}
/* line-height is NOT shared for the same reason: mortgage/lmi explicitly
   set 1.35, offset sets nothing (inherits 1.45 from body in tepuy.css).
   Restored per-page below rather than guessed here. */


/* ══════════════════════════════════════════════════════════════════════════
   6.  RANGE SLIDERS — ported from css/PvS_style.css:666-676 (UI polish
   audit finding #3). Pure element-selector CSS, no PvS markup dependency
   (PvS's own .range-wrap/.range-val wrapper classes are NOT included —
   those are layout/label classes tied to PvS's markup, out of scope here).
   Colors swapped from PvS's --gold accent to this file's --cardH-bg green
   token and --inp-border, so a slider styled from here matches the
   existing accordion/input palette instead of PvS's gold.

   No calculator currently has <input type="range"> outside PvS — confirmed
   via grep across calculators/*.html before and after this change — so
   this is a pure addition with zero rendered effect today. Scoped under
   body.calc .calc-aside (PvS's own version is an unscoped bare selector)
   to match this file's collision-avoidance convention.
   ══════════════════════════════════════════════════════════════════════════ */
body.calc .calc-aside input[type="range"]{
  flex: 1 !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  height: 3px !important;
  background: var(--inp-border, #c8ddd3) !important;
  border-radius: 99px !important;
  outline: none !important;
}
body.calc .calc-aside input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance: none !important;
  width: 14px !important;
  height: 14px !important;
  background: var(--cardH-bg, #1a5236) !important;
  border-radius: 50% !important;
  cursor: pointer !important;
  box-shadow: 0 0 6px rgba(26,82,54,.35) !important;
}
/* PvS is now the consumer this section's header comment mentioned as
   "zero rendered effect today" — Step 3 (2026-08-19) points PvS's own
   sliders at this shared rule and removes its local gold-accent copy
   from PvS_style.css. --inp-border/--cardH-bg are defined only on
   body.calc .calc-aside (see the token block near the top of this file)
   — PvS's .sidebar is a different subtree and doesn't inherit them, so
   both var() calls above needed an explicit fallback added (#c8ddd3 /
   #1a5236, the same literal values the token block itself uses) or
   PvS's slider background/thumb would resolve to nothing. Confirmed
   this fallback path is what actually renders for PvS — see the
   verification screenshots/report for this step.

/* ─── Load-scenario dropdown: keep it from collapsing ──────────────────────
   .ret-load-dropdown is inserted as a flex item of the sidebar's flex column
   (.sidebar-panel > .sidebar-scroll / dropdown / .sidebar-footer) by
   js/calc-scenario.js, js/ovs-scenario.js, js/mortgage-scenario.js and
   js/lmi-scenario.js.

   It sets overflow:hidden, and per the flexbox spec a flex item whose overflow
   is not `visible` gets an automatic minimum main size of 0 rather than its
   content size. So under space pressure from .sidebar-scroll (long sidebar,
   several accordions open, or a short viewport) it shrinks below its content
   and clips its own list — the dropdown opens showing a header and one or two
   rows, which reads as "I have fewer saved scenarios than I do".

   Measured before this rule, 1440x900, 8 saved scenarios, accordions open:
     property_vs_shares  box 236px / content 234px   7 of 8 rows   (correct)
     retirement          box 146px / content 254px   4 of 8 rows
     mortgage            box 162px / content 254px   4 of 8 rows
     lmi                 box 130px / content 254px   3 of 8 rows
     offset_vs_shares    box 127px / content 254px   3 of 8 rows

   property_vs_shares was already correct because css/calculators.css gives its
   .scenario-load-dropdown the identical protection (added 2026-08-30 for this
   same collapse). This is that fix applied to the other four, in the one
   stylesheet all five calculators load, rather than four more copies.

   Declared here and not in the four *-polish.css files on purpose: those load
   AFTER this file but none of them declares flex-shrink, so this value stands
   and there is a single place to change it. */
.ret-load-dropdown { flex-shrink: 0; }

/* ─── Sidebar repeating groups: wrap the fields instead of squeezing them ──
   A repeating row with more than about four fields cannot fit a sidebar
   column. The investment-property repeater added in #182 put SEVEN columns
   (value, growth, loan, repayment, net rent, sell age, remove) into a single
   `grid-template-columns` track list. Measured at 1440x900 with two
   properties entered, every input was narrower than its own content:

     ip-value      $750,000   box 51px / content 82px   -> "$750,"
     ip-loan       $420,000   box 46px / content 82px   -> "$420("
     ip-rent       $26,000    box 42px / content 73px   -> "$26"
     ip-growth     4.5        box 32px / content 39px   -> "4.!"
     ip-sellage    68         box 30px / content 48px

   10 of 12 inputs truncated at 1440x900, and 10 of 12 again at 390x844.

   The fix is to stop treating one property as one ROW and treat it as a
   small CARD whose fields wrap. `repeat(auto-fit, minmax(...))` is the
   deliberate choice: the column count follows whatever width the component
   is given, with no media query and no reference to the sidebar's own
   structure. That matters because Retirement and Property vs Shares have
   had the deep CSS styling pass and offset_vs_shares / lmi / mortgage have
   not — this rule does not care which kind of sidebar it lands in, so the
   pattern can be reused on the un-upgraded three unchanged.

   Each field carries its own label, which also removes the separate
   uppercase header row. That header duplicated the row builder's
   `grid-template-columns` in js/calc-init.js and had to be kept in sync with
   it by hand — the exact consolidation seam this repo keeps reopening.

   CANONICAL REPEATING-ROW GRID. This is the ONE declaration of the pattern.
   Three groups render through it, all built in js/calc-init.js:
       .investment-property-row   Investment Properties   (6 fields)  #185
       .big-ticket-row            One-off Events          (4 fields)
       .career-change-row         Career Changes          (2 fields)
   Adding a fourth means adding `repeater-card` to that row's className — NOT
   copying this block or re-declaring grid-template-columns anywhere else. A
   second copy is the seam defect this repo keeps producing, so
   test/repeater_grid_canonical.test.js fails the build if one appears, or if
   a row using the pattern stops referencing this class.

   Flat field groups (Australian Rules, Fees & Tax, the partner block, and
   every PvS .field-row) deliberately do NOT use this: they are not repeating
   rows, they have no Add button, and forcing a wrap-to-fit card onto them
   would be worse than the inconsistency it removed. */
.repeater-card {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.25rem, 1fr));
  gap: 0.45rem 0.5rem;
  align-items: end;
  padding: 0.55rem 0.6rem 0.5rem;
  margin-bottom: 0.5rem;
  border: 1px solid #dce8e2;
  border-radius: 8px;
  background: #fbfdfc;
}
.repeater-field {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;            /* lets the field shrink inside its grid track */
}
/* #4a655a, not the #7a948a the old uppercase header row used: at 0.62rem on
   the card's #fbfdfc ground that colour measures 3.19:1, below the 4.5:1
   WCAG AA minimum for small text. axe reported 14 new contrast nodes on the
   first cut of this layout for exactly that reason. #4a655a measures
   6.23:1 on the same ground and stays in the same green-grey family. */
/* :first-child, not a bare `> span`: One-off Events wraps its <select> in a
   .bt-kind-wrap span (css/retirement.css draws the chevron on it), which is
   also a direct child of .repeater-field. Without this the wrapper would pick
   up the uppercase label styling. */
.repeater-field > span:first-child {
  font-size: 0.62rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.04em; color: #4a655a; line-height: 1.2;
}
/* `select` alongside `input`: One-off Events' Type field is a <select>, and it
   needs the same min-width:0 that lets a field shrink inside its grid track.
   Its visual skin stays in css/retirement.css (higher specificity, and the
   chevron is Retirement-only markup) — only the box model is shared here. */
.repeater-card input,
.repeater-card select {
  width: 100%; min-width: 0; box-sizing: border-box;
  padding: 4px 6px; font-size: 0.8rem;
}
.repeater-card .repeater-remove {
  grid-column: 1 / -1; justify-self: end;
  background: none; border: 1px solid #c8ddd3; border-radius: 4px;
  padding: 2px 9px; cursor: pointer; color: #4a655a;   /* 6.23:1 on #fbfdfc */
  font-size: 0.75rem; line-height: 1.5;
}
.repeater-card .repeater-remove:hover { background: #f0f6f3; color: #3d5248; }

/* ─── Per-property summary (Retirement Planner, Wealth results area) ───────
   Renders projectScenario().ipPerProperty. Deliberately a compact block
   inside the EXISTING results area rather than a tab of its own: a separate
   property surface was considered and decided against, because every new
   surface is one that can drift from the engine.

   Colours are taken from the same family the repeater's labels use, at
   contrast measured against this panel's ground rather than assumed —
   #4a655a is 6.23:1 on #fbfdfc and 6.36:1 on #ffffff, both above the 4.5:1
   WCAG AA minimum for small text. */
.ip-sum-head {
  font-size: 0.95rem; font-weight: 700; margin: 0 0 0.6rem; color: #24382f;
}
.ip-sum-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.7rem;
}
.ip-sum-card {
  border: 1px solid #dce8e2; border-radius: 8px;
  background: #fbfdfc; padding: 0.7rem 0.8rem;
}
.ip-sum-title {
  font-size: 0.82rem; font-weight: 700; margin: 0 0 0.5rem; color: #24382f;
  display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: baseline;
}
.ip-sum-sub { font-size: 0.68rem; font-weight: 500; color: #4a655a; }
.ip-sum-line {
  display: flex; justify-content: space-between; gap: 0.75rem;
  font-size: 0.78rem; line-height: 1.7; color: #24382f;
}
.ip-sum-line b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ip-sum-line--muted { color: #4a655a; font-size: 0.72rem; line-height: 1.5; }
.ip-sum-line--total {
  border-top: 1px solid #dce8e2; margin-top: 0.35rem; padding-top: 0.35rem;
  font-weight: 700;
}
.ip-sum-note, .ip-sum-foot {
  font-size: 0.7rem; line-height: 1.5; color: #4a655a; margin: 0.4rem 0 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   SHARED BASIC/ADVANCED MODE TOGGLE
   Consumed by calculators/property_vs_shares.html and
   calculators/retirement.html. Those are the only two pages with a mode
   toggle at all — mortgage, offset_vs_shares, lmi and macroeconomics have no
   `.mode-btn` markup — so declaring it in this file, which all five load,
   restyles nothing else. That is what makes this a safe home rather than a
   sixth copy.

   Before this, the two were separate implementations: PvS drew a gold pill
   with an icon typed into the markup ("● Basic" / "⚙ Advanced"), retirement
   drew a plain two-tone segmented control in green with no icons and its own
   `--active` class. They looked different, and nothing stopped them drifting
   further.

   THE MARKUP IS SHARED TOO, from js/mode-toggle.js. Sharing only the
   stylesheet was not enough and this file is where that shows: the rules
   below for .mode-toggle-label and .mode-toggle-group had nothing to match on
   retirement, which had neither element, and on PvS they lost to equal-
   specificity copies in css/PvS_style.css that loaded later. Both are gone
   now; this file is the only place the component is styled.

   WHAT EACH PAGE KEEPS: its own label text (retirement "Simple/Advanced",
   PvS "Basic/Advanced"), its own hint copy, and its own JS. Only the pill
   chrome — shape, colours, icons — is shared.

   TWO ACTIVE-STATE HOOKS, on purpose. PvS's JS sets `.active` and reads it
   back (js/app1.js:1855 does `.mode-btn.active` -> dataset.mode); retirement's
   sets `.mode-btn--active` and also maintains `aria-selected` for its
   role="tablist". Matching all three means neither page's behaviour had to be
   rewritten for a presentation-only change, and `aria-selected` means the
   styling follows the accessibility state rather than sitting beside it.
   ══════════════════════════════════════════════════════════════════════════ */

body.calc .calc-aside .mode-toggle-bar,
.mode-toggle-bar {
  display: flex;
  align-items: center;
  /* Wraps rather than overflowing. The caption is white-space:nowrap and the
     track is a fixed pair of pills, so a narrow sidebar has nothing to shrink:
     measured at 390px, the section overflowed its own box by 33px once
     retirement gained the label and the track (before that, retirement fitted
     only because it was missing both). Property vs Shares already overflowed
     the same way at 320px, so this fixes a pre-existing narrow-width bug on
     that page too. The caption keeps margin-left:auto and lands right-aligned
     on its own line. Neither page's document ever overflowed — this is inside
     the bar, not a 1.4.10 reflow failure. */
  flex-wrap: wrap;
  gap: 6px 8px;
  margin-bottom: 12px;
  padding: 8px 10px;
  background: var(--bg-raised, #f7faf8);
  border: 1px solid var(--border, #d6e4dc);
  border-radius: 10px;
}

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

/* The inset track. Both pages have one now — the markup for the whole
   section comes from js/mode-toggle.js, so there is a single skeleton.
   Before that, PvS wrapped its buttons in this and retirement put them
   straight in the bar, which is why the two bars measured 45px and 39px. */
.mode-toggle-group {
  display: flex;
  /* --mode-track-bg, not --bg-input. Same trap as --gold below: --bg-input is
     a PER-PAGE token and resolved differently on each consumer — measured
     #F7F8FB on Property vs Shares against plain white on retirement, so the
     "shared" track still drew two different colours. Its own token, like the
     active pill's. */
  background: var(--mode-track-bg, #ffffff);
  border: 1px solid var(--border, #d6e4dc);
  border-radius: 8px;
  padding: 2px;
  gap: 2px;
}

body.calc .calc-aside .mode-btn,
.mode-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 12px;
  border: none;
  border-radius: 7px;
  font-family: inherit;
  font-size: .68rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
  background: transparent;
  color: var(--text-muted, #55685F);
  letter-spacing: .02em;
  white-space: nowrap;
}

body.calc .calc-aside .mode-btn:hover,
.mode-btn:hover {
  color: var(--text-primary, #1c2b2a);
  background: var(--bg-hover, #eef4f1);
}

/* ── The icons ────────────────────────────────────────────────────────────
   Drawn by CSS, not typed into the markup, for two reasons: the spec shows
   them on the INACTIVE option only, which markup cannot express on its own;
   and it keeps the glyphs out of each page's label text, so the accessible
   name stays "Basic" / "Simple" / "Advanced" rather than "● Basic" (WCAG
   2.5.3 Label in Name). PvS's markup previously carried "● " and "⚙ "
   inline; those are removed there.

   aria-hidden is not needed — a CSS ::before is not exposed as content to
   assistive technology in any engine that matters here.

   Keyed on data-mode, which PvS already had and retirement has been given,
   so one selector serves both pages. */
.mode-btn[data-mode]::before {
  font-size: .78em;
  line-height: 1;
  color: var(--accent-icon, #1a6b4a);
}
.mode-btn[data-mode="basic"]::before   { content: '\25CF'; }  /* ● dot     */
.mode-btn[data-mode="advanced"]::before { content: '\2726'; } /* ✦ sparkle */

/* ── Active state ─────────────────────────────────────────────────────────
   Orange fill, and the icon is dropped: the spec reserves orange for the
   active option and shows the accent icon only on the inactive one.

   TEXT COLOUR IS NOT WHITE, DELIBERATELY — and this needs Luis's call.
   The reference screenshots show white on the orange fill. At this size
   (.68rem ≈ 11px) that is small text and needs 4.5:1. Measured on the clay
   #C97A3A this component fills with:

       white   on #C97A3A = 3.32:1   FAILS AA
       #0E1512 on #C97A3A = 5.58:1   passes

   css/PvS_style.css:84 already carries the same finding in its own words
   ("white would be only 3.95:1" against the darker #BE6A3E it resolves for),
   so shipping white here would knowingly undo a fix.

   If white text is wanted, the FILL has to darken to carry it — #A85A28
   gives white 5.05:1. That is a brand decision, not a CSS one, so it is
   flagged rather than taken. Override --mode-active-bg/--mode-active-fg
   together to change it. */
body.calc .calc-aside .mode-btn.active,
body.calc .calc-aside .mode-btn--active,
body.calc .calc-aside .mode-btn[aria-selected="true"],
.mode-btn.active,
.mode-btn--active,
.mode-btn[aria-selected="true"] {
  /* Its OWN tokens, not var(--gold). --gold is a PER-PAGE brand token and
     resolves differently on each consumer — measured: #C97A3A (clay) on
     Property vs Shares, #1a5236 (green) on retirement. Reading it made the
     "shared" component adopt each page's accent and render green on one page
     and orange on the other, which is precisely the split this change exists
     to end. The active pill is orange on both, from here. */
  background: var(--mode-active-bg, #C97A3A);
  color: var(--mode-active-fg, #0E1512);
  box-shadow: 0 1px 4px rgba(201, 122, 58, .30);
}
.mode-btn.active::before,
.mode-btn--active::before,
.mode-btn[aria-selected="true"]::before { content: none; }

/* The caption to the right of the pill. Retirement swaps its text with the
   mode ("5 key inputs" / "Full control") and PvS states an audience ("For
   beginners"); both keep their own wording. */
body.calc .calc-aside .mode-hint,
.mode-hint {
  font-size: .62rem;
  color: var(--text-muted, #55685F);
  font-style: italic;
  line-height: 1.4;
  margin-left: auto;
  white-space: nowrap;
}


/* ══════════════════════════════════════════════════════════════════════════
   7.  LOAD SCENARIO DROPDOWN + SHARE CARD MODAL
   Moved from mortgage-polish.css, lmi-polish.css and offset-polish.css,
   where these two components were tripled verbatim. Extraction only — no
   selector or declaration was changed. Verified byte-identical across all
   three source files with a direct, order-preserving diff (not just a
   normalized comparison) before moving a single rule.

   NOT everything in these two components made the move — some of it is
   page-local on purpose and stays that way in the three polish files:

   - .rld-close sets `line-height: 1` in lmi-polish.css and offset-polish.css
     but not in mortgage-polish.css — a real difference.
   - .ret-sc-badge / .ret-sc-badge-good / .ret-sc-badge-warn: mortgage's
     bare .ret-sc-badge sets no background/color/border, so its -good/-warn
     variants each supply the full `border` shorthand; lmi/offset's bare
     .ret-sc-badge instead defaults to the "good" look, and their variants
     only override `border-color`. Same rendered -good/-warn result either
     way, but a different result for an UNMODIFIED .ret-sc-badge — a
     behaviour difference, not formatting.
   - .ret-sc-action-primary: `color: #fff` (mortgage) vs `#ffffff`
     (lmi/offset) — cosmetic byte difference, left alone rather than
     picking a winner un-asked.
   - The .ret-sc-stats/-headline/-action-btn tweak at 500px: identical
     values in all three files, but lmi-polish.css gates it with
     `@media (max-width: 500px)` while mortgage/offset use
     `@container calc-layout (max-width: 500px)` — the same LMI/mortgage
     container-vs-media divergence already flagged elsewhere in this repo.
     Consolidating the mechanism, not just the values, is a separate,
     larger change and not part of this move.

   See each polish file's own "SHARE CARD MODAL" / "LOAD DROPDOWN" section
   for the specific rules that stayed, with the same reasoning inline.
   ══════════════════════════════════════════════════════════════════════════ */
.rld-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.5rem 0.75rem; background: #f4f8f6; border-bottom: 1px solid #e3ede8;
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: #3d5248;
}

.rld-close:hover { color: #1a5236; }

.rld-list { list-style: none; margin: 0; padding: 0.3rem 0; max-height: 220px; overflow-y: auto; }

.rld-item {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.5rem; width: 100%; padding: 0.45rem 0.75rem;
  font-family: inherit; font-size: 0.8rem; color: #0f1c16;
  background: none; border: none; cursor: pointer; text-align: left; transition: background 0.1s;
}

.rld-item:hover { background: #f0f7f4; color: #1a5236; }

.rld-name { flex: 1; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.rld-date { font-size: 0.64rem; color: var(--text-muted); flex-shrink: 0; white-space: nowrap; }

.ret-sc-overlay {
  display: none; position: fixed; inset: 0;
  background: rgba(0,0,0,0.72); z-index: 99990;
  align-items: center; justify-content: center;
  padding: 1rem; backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}

.ret-sc-overlay.ret-sc-visible { display: flex; }

.ret-sc-outer {
  display: flex; flex-direction: column; align-items: center;
  gap: 0.85rem; width: 100%; max-width: 640px; max-height: 92vh; overflow-y: auto;
}

.ret-sc-card {
  width: 100%; border-radius: 14px; overflow: hidden;
  font-family: 'Inter', system-ui, sans-serif;
  background: #0d1117; color: #e8f0eb;
  border: 1px solid #1e2a22; box-shadow: 0 8px 40px rgba(0,0,0,0.5);
}

.ret-sc-card.ret-sc-light {
  background: #ffffff; color: #0f1c16;
  border: 1px solid #e3ede8; box-shadow: 0 4px 24px rgba(0,0,0,0.1);
}

.ret-sc-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 1.25rem 0.75rem;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.ret-sc-card.ret-sc-light .ret-sc-header { border-bottom-color: #e3ede8; }

.ret-sc-card.ret-sc-light .ret-sc-badge.ret-sc-badge-good { background: #dcfce7; color: #15803d; border-color: #86efac; }

.ret-sc-card.ret-sc-light .ret-sc-badge.ret-sc-badge-warn { background: #fef9c3; color: #a16207; border-color: #fde047; }

.ret-sc-brand {
  display: flex; flex-direction: column; align-items: flex-end;
  font-size: 0.72rem; font-weight: 700; color: rgba(255,255,255,0.45); line-height: 1.4;
}

.ret-sc-card.ret-sc-light .ret-sc-brand { color: var(--text-muted); }

.ret-sc-brand span { font-size: 0.62rem; font-weight: 400; opacity: 0.7; }

.ret-sc-headline {
  padding: 1rem 1.25rem 0.75rem;
  font-size: 1.1rem; font-weight: 600; line-height: 1.45; color: #e8f0eb;
}

.ret-sc-card.ret-sc-light .ret-sc-headline { color: #0f1c16; }

.ret-sc-headline strong { color: #4ade80; }

.ret-sc-card.ret-sc-light .ret-sc-headline strong { color: #15803d; }

.ret-sc-stats {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: rgba(255,255,255,0.06); margin: 0 1.25rem 0.75rem;
  border-radius: 10px; overflow: hidden; border: 1px solid rgba(255,255,255,0.06);
}

.ret-sc-card.ret-sc-light .ret-sc-stats { background: #e3ede8; border-color: #e3ede8; }

.ret-sc-stat { background: #131a1f; padding: 0.7rem 0.85rem; display: flex; flex-direction: column; gap: 0.3rem; }

.ret-sc-card.ret-sc-light .ret-sc-stat { background: #f7faf8; }

.ret-sc-stat-label { font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: rgba(255,255,255,0.4); }

.ret-sc-card.ret-sc-light .ret-sc-stat-label { color: var(--text-muted); }

.ret-sc-stat-value { font-size: 0.875rem; font-weight: 500; line-height: 1.4; color: #c8ddd3; }

.ret-sc-card.ret-sc-light .ret-sc-stat-value { color: #3d5248; }

.ret-sc-stat-value.green { color: #4ade80; }

.ret-sc-stat-value.blue  { color: #60a5fa; }

.ret-sc-stat-value.warn  { color: #fbbf24; }

.ret-sc-stat-value.red   { color: #f87171; }

.ret-sc-card.ret-sc-light .ret-sc-stat-value.green { color: #15803d; }

.ret-sc-card.ret-sc-light .ret-sc-stat-value.blue  { color: #1d4ed8; }

.ret-sc-card.ret-sc-light .ret-sc-stat-value.warn  { color: #92400e; }

.ret-sc-card.ret-sc-light .ret-sc-stat-value.red   { color: #b91c1c; }

.ret-sc-divider { height: 1px; background: rgba(255,255,255,0.06); margin: 0 1.25rem; }

.ret-sc-card.ret-sc-light .ret-sc-divider { background: #e3ede8; }

.ret-sc-assumptions {
  padding: 0.65rem 1.25rem; font-size: 0.72rem;
  color: rgba(255,255,255,0.45); line-height: 1.7;
}

.ret-sc-card.ret-sc-light .ret-sc-assumptions { color: #4a655a; }

.ret-sc-assumptions strong { color: rgba(255,255,255,0.75); font-weight: 600; }

.ret-sc-card.ret-sc-light .ret-sc-assumptions strong { color: #1f3d2d; }

.ret-sc-footer {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1rem; padding: 0.65rem 1.25rem 1rem;
  border-top: 1px solid rgba(255,255,255,0.06);
}

.ret-sc-card.ret-sc-light .ret-sc-footer { border-top-color: #e3ede8; }

.ret-sc-disclaimer { font-size: 0.62rem; color: rgba(255,255,255,0.25); line-height: 1.5; margin: 0; }

.ret-sc-card.ret-sc-light .ret-sc-disclaimer { color: #b0bfba; }

.ret-sc-url { font-size: 0.62rem; font-weight: 600; color: rgba(255,255,255,0.2); white-space: nowrap; flex-shrink: 0; }

.ret-sc-card.ret-sc-light .ret-sc-url { color: #c8ddd3; }

.ret-sc-actions {
  display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: center; width: 100%;
}

.ret-sc-action-btn {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.55rem 1.1rem; font-family: inherit; font-size: 0.82rem; font-weight: 600;
  border-radius: 8px; cursor: pointer; border: none;
  transition: background 0.14s, transform 0.1s; white-space: nowrap;
}

.ret-sc-action-btn:active { transform: translateY(1px); }

.ret-sc-action-primary:hover { background: #247857; }

.ret-sc-action-secondary { background: rgba(255,255,255,0.1); color: #e8f0eb; border: 1px solid rgba(255,255,255,0.15); }

.ret-sc-action-secondary:hover { background: rgba(255,255,255,0.18); }

.ret-sc-action-close { background: rgba(255,255,255,0.07); color: rgba(255,255,255,0.55); border: 1px solid rgba(255,255,255,0.1); }

.ret-sc-action-close:hover { background: rgba(255,255,255,0.14); color: #fff; }

.ret-sc-hint { font-size: 0.72rem; color: rgba(255,255,255,0.3); text-align: center; margin: 0; }
