/* ========================================================================
   DEPLOY PATH: /css/offset-polish.513c581e.css
   Tepuy Solutions — Offset vs Shares Calculator sidebar polish
   Version: 2026-03-31 (refactored)
   
   Load AFTER tepuy.css.
   Token overrides are scoped to .calc-aside — they do NOT bleed globally.
   ======================================================================== */

/* ── Design tokens — base sidebar-surface/accordion/footer tokens now live
   in css/simulators.css (body.calc .calc-aside). --inp-focus stays here
   since it's used by this page's own form-row rules below (out of scope
   for the sidebar-chrome consolidation). ── */
.calc-aside {
  --inp-focus:  #1a6b4a;
}


/* ══════════════════════════════════════════════════════════════════════════
   1.  SIDEBAR SURFACE — base surface/background/scrollbar moved to
       css/simulators.css. Only the wide-tier flush-border block stays here.
       Used to be the odd one out on VALUES (border shorthand + --sb-border
       token vs. mortgage/lmi's four longhands + hardcoded #dce8e1 — same
       resolved color, different bytes) while lmi-polish.css was also the
       odd one out on MECHANISM (@media (min-width:1025px) instead of this
       @container calc-layout (min-width:800px)). The mechanism mismatch is
       fixed; the value-shorthand difference is left as-is (see
       mortgage-polish.css's own note).
   ══════════════════════════════════════════════════════════════════════════ */

/* Wide tier (>=800px) — same threshold as tepuy.css's shared calc-layout
   density tiers; measures .main-layout's own rendered width (the iframe's
   width when embedded) instead of the raw viewport. */
@container calc-layout (min-width: 800px) {
  body.calc .calc-aside .sidebar-panel {
    border-radius: 0 !important;
    border: none !important;
    border-right: 1px solid var(--sb-border) !important;
    padding: 0 !important;
  }
  body.calc .calc-aside .sidebar-scroll { padding: 0.5rem 0.6rem 0 !important; }
}


/* Tooltip escape from aside overflow */
aside .i::after { position: fixed !important; left: var(--tip-x, 50%) !important; top: var(--tip-y, -9999px) !important; bottom: auto !important; transform: none !important; z-index: 99999 !important; }
aside .i::before { position: fixed !important; left: var(--tip-arrow-x, 50%) !important; top: var(--tip-arrow-y, -9999px) !important; bottom: auto !important; transform: rotate(45deg) !important; z-index: 99998 !important; }

/* ══════════════════════════════════════════════════════════════════════════
   ACCORDION CARDS — this file deliberately declares NO padding for them.
   ══════════════════════════════════════════════════════════════════════════
   Recorded 2026-09-06 (R4) because "offset-polish has no accordion rule while
   the other two do" reads as an oversight and is not one. The absence IS the
   correct state, and adding an explicit rule here would break the thing it
   looks like it would fix.

   Where the values come from, in cascade order:

     css/simulators.css   the shared open padding, 0.65rem 0.9rem 0.85rem
     css/tepuy.css        the narrow tier, 0.45rem 0.9rem

   Measured in Chromium with the 0.3s transition allowed to settle, this page
   renders 10.4/14.4/13.6 at 1366 and 900 wide and 7.2/14.4/7.2 at 700 — the
   same as LMI and Property vs Shares at every width. It is already converged.

   An explicit `aside .card-content.open { … !important }` here would sit at
   DESKTOP level and therefore win at narrow widths too, pinning this page to
   desktop spacing exactly the way mortgage-polish.css's
   `:not([hidden]).open` selector used to pin Mortgage — the divergence R4
   deleted. So the rule that would make this file look consistent with its two
   siblings is the rule that would make the RENDERED page inconsistent with
   them.

   If a genuine offset-only accordion value is ever needed, put it inside the
   `@container calc-sidebar` block below rather than at desktop level.
   ══════════════════════════════════════════════════════════════════════════ */

/* Form rows */
aside .form-row { margin-bottom: 0.5rem !important; }
/* aside .form-row label now comes from css/tepuy.css, once, at 0.8125rem.
   This file's byte-identical override was one of four. */
aside .form-row input[type="text"],
aside .form-row input[type="number"],
aside .form-row select {
  width: 100% !important;
  /* padding, font-size, border: css/tepuy.css, "THE SIDEBAR INPUT" block. */
  background: #ffffff !important;
  color: #0f1c16 !important; font-family: inherit !important;
  transition: border-color 0.15s, box-shadow 0.15s !important; box-sizing: border-box !important;
}
aside .form-row input:focus, aside .form-row select:focus {
  border-color: var(--inp-focus) !important;
  box-shadow: 0 0 0 3px rgba(26,107,74,0.12) !important;
}
/* Select dropdown arrow.

   The selector carries `.form-row` deliberately. Until 2026-09-05 this rule
   was just `aside select` (specificity 0,1,1 -> 0,0,2), while the input
   styling above uses `aside .form-row select` (0,1,2) and sets a
   `background:` SHORTHAND — which resets background-image to none and, being
   more specific, won. Combined with `appearance: none` here, which the
   shorthand does NOT reset, the result was a select with no native arrow and
   no custom one.

   Measured across the four sidebar calculators: NINE of eleven selects
   rendered with no dropdown indicator at all. That is why the chevron's
   2.36:1 contrast never appeared in an axe scan — the chevron was not being
   painted. */
aside .form-row select,
aside select {
  appearance: none !important; -webkit-appearance: none !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2355685F'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important; background-position: right 0.6rem center !important;
  background-size: 8px 5px !important; padding-right: 1.8rem !important; cursor: pointer !important;
}
aside .grid-2 { display: grid !important; grid-template-columns: 1fr 1fr !important; gap: 0.5rem !important; }
/* Sidebar's own cramped width — 300px matches the Narrow-tier threshold
   used elsewhere; the sidebar's rendered width never reaches the old 440px
   viewport value verbatim. */
@container calc-sidebar (max-width: 300px) { aside .grid-2 { grid-template-columns: 1fr !important; } }

.check-row {
  display: flex !important; align-items: flex-start !important;
  gap: 0.45rem !important; font-size: 0.8rem !important; color: #3d5248 !important;
  cursor: pointer !important; margin-top: 0.2rem !important;
}
.check-row input[type="checkbox"] { width: auto !important; margin: 2px 0 0 !important; flex-shrink: 0 !important; accent-color: #1a5236 !important; }

/* Scenario B sub-label */
.ovs-scen-b-label {
  font-size: 0.67rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 0.5rem;
  padding-top: 0.35rem; border-top: 1px solid #e8f0eb; margin-top: 0.35rem;
}

/* Sidebar footer's base surface and Calculate button live in
   css/simulators.css — no local override here. Unlike mortgage/lmi, this
   page's #runBtn/.ovs-calc-hint never set letter-spacing/line-height, and
   simulators.css's shared rule deliberately excludes both properties for
   that reason (referenced from mortgage-polish.css and lmi-polish.css —
   keep this note if removing that exclusion). */

/* Scenario buttons (reuse retirement pattern) */
.ret-scenario-row { display: flex; gap: 0.35rem; }
.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; color: #3d5248;
  background: #f4f8f6; 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; }
/* Load-button busy state (fix-scenario-save-load-followup-bugs, 2026-08-30)
   — :disabled alone gave no visible cue a fetch was in flight, so a click
   right after Save/page-load (before the list request resolves) looked
   like a no-op; reuses tepuy.css's shared @keyframes spin. */
.ret-scen-btn.is-busy { opacity: 0.75; cursor: wait; }
.ret-scen-btn.is-busy::before {
  content: "";
  width: 0.85em; height: 0.85em;
  border-radius: 50%;
  border: 2px solid rgba(61,82,72,0.25);
  border-top-color: currentColor;
  animation: spin 0.8s linear infinite;
}
.ret-scen-btn--share { color: #1a5236; background: #edf7f2; border-color: #b3d9c4; }
.ret-scen-btn--share:hover { background: #d4ede2; border-color: #1a6b4a; }
.ret-scen-hint { display: none; font-size: 0.7rem; font-weight: 500; padding: 0.15rem 0; text-align: center; }

/* Pro badge hidden */
.pro-badge, #footerBadge, .pro-cta, #unlockPro, .pro-emoji { display: none !important; }


/* ══════════════════════════════════════════════════════════════════════════
   4.  SHARED BANNER + SHARE RESULT BAR
   ══════════════════════════════════════════════════════════════════════════ */


.ret-share-result-bar { display: flex; justify-content: flex-end; margin: 0.5rem 0 0.75rem; }
.ret-share-result-bar[hidden] { display: none !important; }
/* .ret-share-result-btn used to be declared here too, with different (and
   undocumented — unlike the .ret-sc-badge divergence below, which has a
   reasoned comment) padding/font-size/background/border/border-radius
   values, and NO letter-spacing or hover box-shadow. Since this second
   declaration further down the cascade (same specificity) always won,
   THIS block was dead CSS, and the one that rendered had silently drifted
   from Mortgage's/LMI's identical shared value. Removed; see that
   declaration below for the fix. */


/* ══════════════════════════════════════════════════════════════════════════
   6.  RESULTS TAB SYSTEM
   ══════════════════════════════════════════════════════════════════════════ */
.results-tabs-wrap {
  background: #ffffff; border: 1px solid #dce8e1; border-radius: 14px;
  overflow: hidden; margin-bottom: 1.25rem; box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
/* .rtab-bar / .rtab-btn / .rtab-btn--active / .rtab-panel / .rtab-panel--hidden
   / .rtab-actions were verbatim copies of css/calculators.css's rules and are
   deleted here. This page did not load calculators.css when they were written;
   it has since #204, so the copies were pure duplication — except that
   .rtab-panel--hidden's copy carried `!important` and the shared rule does
   not, so the copy WON and the shared rule was dead on every page that had
   one. Measured after deletion: every panel still hides — calculators.css
   declares .rtab-panel--hidden AFTER .rtab-panel at equal specificity, so it
   wins without needing !important — and .rtab-btn--active still computes
   `2px solid rgb(26, 82, 54)` with font-weight 800, unchanged.
   (No line numbers quoted on purpose: docs/OPEN-ITEMS.md records a previous
   entry whose cited line had drifted by 41 before anyone checked.)
   One deliberate behaviour change: the copy's hover was `.rtab-btn:hover`,
   the shared rule's is `.rtab-btn:hover:not(:disabled)` — a disabled
   ("coming soon") tab no longer takes hover paint, which is what the shared
   rule always intended. */

.btn-ghost-sm {
  display: inline-flex; align-items: center; gap: 0.35rem; font-family: inherit;
  font-size: 0.775rem; font-weight: 500; color: #4a655a; background: transparent;
  border: 1px solid #c8ddd3; border-radius: 4px; padding: 0.3rem 0.7rem;
  cursor: pointer; transition: color 0.15s, border-color 0.15s, background 0.15s; white-space: nowrap;
}
.btn-ghost-sm:hover { color: #0f1c16; border-color: #3db07e; background: #f8faf9; }
.btn-ghost-sm svg { flex-shrink: 0; }

.btn-action {
  display: inline-flex; align-items: center; gap: 0.4rem; font-family: inherit;
  font-size: 0.8rem; font-weight: 600; color: #ffffff; background: #1a5236;
  border: none; border-radius: 8px; padding: 0.45rem 0.95rem; cursor: pointer;
  transition: background 0.15s, box-shadow 0.15s, transform 0.1s; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0,0,0,0.12);
}
.btn-action:hover { background: #247857; box-shadow: 0 3px 8px rgba(26,82,54,0.25); transform: translateY(-1px); }
.btn-action--ghost { color: #3d5248; background: #f1f7f4; box-shadow: none; border: 1px solid #e3ede8; }
.btn-action--ghost:hover { background: #e6f0eb; border-color: #c8ddd3; box-shadow: none; color: #0f1c16; }

/* Chart container */
body.calc {
  --chart-height-desktop: 400px;
}
.rtab-chart { position: relative; width: 100%; height: var(--chart-height-desktop); min-height: 220px; overflow: hidden; }
.rtab-chart canvas { display: block !important; width: 100% !important; height: 100% !important; }

/* calc-layout, not calc-main — same defect as .ovs-kpi-strip above (the
   calc-main container this queried is display:contents-broken in the
   exact stacked tier this needs to fire in).

   That said: this specific pair is currently DEAD CODE either way, and
   was before this change too. css/tepuy.css declares its own .rtab-chart
   height at every tier via raw @media queries with !important, which
   always wins over a non-!important rule regardless of specificity or
   source order. Confirmed by deleting this pair entirely and measuring
   getComputedStyle('.rtab-chart').height at 375px before and after:
   identical (260px) either way. So this does NOT explain the separately-
   reported "charts too small on mobile" suspicion — tepuy.css's own rule
   already governs this chart's height, unaffected by the calc-main bug.
   Left as a mechanical swap anyway for consistency with the rest of this
   file and in case tepuy.css's rule is ever weakened or removed — but
   it is inert today (same finding, independently confirmed, as
   mortgage-polish.css's identical .rtab-chart pair). */
@container calc-layout (max-width: 960px) { .rtab-chart { height: 300px; } }
@container calc-layout (max-width: 640px) { .rtab-chart { height: 260px; } }


/* Tab intro text */
.ovs-tab-intro {
  font-size: 0.85rem; color: #4a655a; line-height: 1.55;
  margin: 0 0 1rem; padding: 0.65rem 0.85rem;
  background: #f7faf8; border-radius: 8px; border-left: 3px solid #c8ddd3;
}

/* Table */
.ovs-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: 8px; border: 1px solid #e3ede8; }
.ovs-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.ovs-table thead th {
  padding: 0.5rem 0.75rem; background: #f7faf8; color: #4a655a;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  border-bottom: 1.5px solid #dce8e1; white-space: nowrap; text-align: right;
}
.ovs-table thead th:first-child { text-align: left; }
.ovs-table tbody td {
  padding: 0.4rem 0.75rem; border-bottom: 1px solid #f0f5f2;
  color: #1a3326; text-align: right; font-variant-numeric: tabular-nums;
}
.ovs-table tbody td:first-child { text-align: left; color: #4a655a; font-weight: 600; }
.ovs-table tbody tr:last-child td { border-bottom: none; }
.ovs-table tbody tr:hover td { background: #f7faf8; }


/* ── Table — three-scenario headers ── */
.td-yr { width: 30px; text-align: center !important; color: #4a655a !important; font-weight: 600 !important; }


/* ── Sensitivity table ── */
.ovs-sens-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.ovs-sens-note { font-size: 0.72rem; color: var(--text-muted); margin: 0.5rem 0 0; line-height: 1.45; }


/* ── Explainer framing box ── */
.ovs-explainer-framing {
  background: #f0f9ff;
  border: 1px solid #bae6fd;
  border-left: 3px solid #38bdf8;
  border-radius: 8px;
  padding: 0.75rem 0.95rem;
  margin-bottom: 1rem;
  font-size: 0.85rem;
  color: #0c4a6e;
  line-height: 1.55;
}


/* ══════════════════════════════════════════════════════════════════════════
   LOAD SCENARIO DROPDOWN  (ret-load-dropdown / rld-*)
   Mirrors lmi-polish.css exactly so Save/Load/Share work on this page.
   ══════════════════════════════════════════════════════════════════════════ */
.ret-load-dropdown {
  background: #ffffff;
  border: 1px solid #c8ddd3;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0,0,0,0.13);
  overflow: hidden;
  margin: 0 0 0.5rem;
  z-index: 200;
  animation: rld-fadein 0.15s ease;
}
@keyframes rld-fadein { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:translateY(0); } }

/* The rest of .rld-* (header/list/item/name/date + most hover states)
   moved to css/simulators.css — confirmed byte-identical across this file,
   mortgage-polish.css and lmi-polish.css, via a direct diff, before the
   move. .rld-close itself stays here: this file (and lmi's) set
   `line-height: 1` on it, mortgage-polish.css doesn't — a real, if tiny,
   difference the move must not erase. */
.rld-close { background: none; border: none; font-size: 0.8rem; color: var(--text-muted); cursor: pointer; padding: 0; line-height: 1; }


/* ══════════════════════════════════════════════════════════════════════════
   SHARE CARD MODAL  (ret-sc-overlay / ret-sc-*)
   Mirrors lmi-polish.css exactly so the share result card works on this page.
   ══════════════════════════════════════════════════════════════════════════ */

/* Most of .ret-sc-* moved to css/simulators.css — confirmed byte-identical
   across this file, mortgage-polish.css and lmi-polish.css, via a direct
   diff, before the move. What's left below is page-local ON PURPOSE, not
   an oversight:

   - .ret-sc-badge / .ret-sc-badge-good / .ret-sc-badge-warn: this file's
     bare .ret-sc-badge defaults background/color/border to the "good"
     look, and the -good/-warn variants only override `border-color`.
     mortgage-polish.css's bare .ret-sc-badge sets none of that, so its
     variants each supply the FULL `border` shorthand instead. Same
     rendered result for -good/-warn either way, but a DIFFERENT result
     for an unmodified .ret-sc-badge — moving this would be a behaviour
     change, not a move.
   - .ret-sc-action-primary: `color: #ffffff` here vs `#fff` in
     mortgage-polish.css — identical rendered color, different bytes; left
     alone rather than picking a winner un-asked.

   The .ret-sc-stats/-headline/-action-btn tweak a little further down has
   the same values in all three files but stays local for a different
   reason: lmi-polish.css gates the identical declarations with
   `@media (max-width: 500px)` where this file (and mortgage's) use
   `@container calc-layout (max-width: 500px)` — the same LMI/mortgage
   container-vs-media divergence already flagged elsewhere in this repo,
   not something to paper over here by picking one mechanism. */
.ret-sc-badge {
  display: inline-block; font-size: 0.68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.09em;
  padding: 0.28rem 0.75rem; border-radius: 20px;
  background: rgba(26,107,74,0.25); color: #4ade80; border: 1px solid rgba(74,222,128,0.3);
}
.ret-sc-badge.ret-sc-badge-good { background: rgba(26,107,74,0.25); color: #4ade80; border-color: rgba(74,222,128,0.3); }
.ret-sc-badge.ret-sc-badge-warn { background: rgba(251,191,36,0.15); color: #fbbf24; border-color: rgba(251,191,36,0.3); }

.ret-sc-action-primary { background: #1a5236; color: white; }

/* Share result bar (above the chart tabs) */
.ret-share-result-bar {
  display: flex; justify-content: flex-end;
  margin-bottom: 0.5rem;
}
/* Converged onto Mortgage's/LMI's identical value (2026-09) — see the
   comment where the second, drifted declaration used to sit above this
   one, before it was removed. */
.ret-share-result-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.45rem 1rem; font-family: inherit; font-size: 0.82rem; font-weight: 600;
  color: #1a5236; background: #f0fdf4; border: 1.5px solid #86efac;
  border-radius: 8px; cursor: pointer; letter-spacing: 0.01em;
  transition: background 0.14s, border-color 0.14s, box-shadow 0.14s;
}
.ret-share-result-btn:hover {
  background: #dcfce7; border-color: #4ade80;
  box-shadow: 0 2px 8px rgba(26,107,74,0.15);
}

@container calc-layout (max-width: 500px) {
  .ret-sc-stats { grid-template-columns: 1fr; }
  .ret-sc-headline { font-size: 0.95rem; }
  .ret-sc-action-btn { padding: 0.5rem 0.75rem; font-size: 0.76rem; }
}


/* ── IP property type toggle pill row ── */
#propertyPurpose {
  font-weight: 600;
}

/* ── Out-of-pocket column ── */
.th-oop { background: rgba(0,0,0,0.04) !important; font-style: italic; }
.td-oop { color: #4a655a; font-size: 0.78rem; font-variant-numeric: tabular-nums; }


/* Partial final year row */
.tr-partial-year {
  background: rgba(26, 82, 54, 0.08) !important;
}
.tr-partial-year td {
  font-style: italic;
}


/* ══════════════════════════════════════════════════════════════════════════
   UX-4-OVS — the results area in the UX-3 PvS pattern (decision 745; Luis
   approved the mockups 8 Nov 2026). docs/design/ux-4-ovs/README.md.
   PALETTE ONLY (485, 510, and Luis's note of 8 Nov): every colour in this
   section is a Tepuy token from css/tepuy.css (var(--…)), a tint of one
   (color-mix with white or transparent), or white. No literal hex, rgb() or
   named colour: test/ovs_ux4_palette.test.js reads this section and fails on
   one. It replaces the off-palette rules this file used to give the KPI
   strip, the scenario chips, the idle-money box, the summary line, the
   plain-English panel, the Insights and Sensitivity tabs and the CGT notice.
   ══════════════════════════════════════════════════════════════════════════ */

/* Path colours by family (OVS-VISUAL-1b, Luis 10 Nov 2026; js/ovs-labels.js):
   the Offset family in three clay shades, the Shares family in moss. Shades of
   tokens only (color-mix toward black), each at least 3:1 on white as a chart
   line: O1 clay 3.32, O2 clay 70% 6.06, O3 clay 50% 9.4, S1 moss 4.95. The
   three clay lines keep their dash patterns (O1 6/3, O2 3/3, O3 5/4) so they
   stay apart without colour. Chips keep AA text: ink on clay (5.58:1), white on
   the darker clays and on moss. Engine keys stay A-D: --scen-a is O3. */
:root {
  --scen-a: color-mix(in srgb, var(--clay) 50%, black);   /* O3  Interest-only + invest (what-if) */
  --scen-b: var(--clay);                                    /* O1  All in Offset */
  --scen-c: var(--moss);                                    /* S1  All in Shares */
  --scen-d: color-mix(in srgb, var(--clay) 70%, black);   /* O2  Offset + invest the difference */
  --ovs-fam-offset: var(--clay);
  --ovs-fam-shares: var(--moss);
}
.scen-pill, .scen-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 18px; padding: 0 5px; border-radius: 9px; flex-shrink: 0;
  font-size: 0.65rem; font-weight: 800; line-height: 1; letter-spacing: .02em;
}
.scen-badge { min-width: 26px; height: 20px; font-size: 0.7rem; }
.scen-a { background: var(--scen-a); color: white; }
.scen-b { background: var(--scen-b); color: var(--ink); }
.scen-c { background: var(--scen-c); color: white; }
.scen-d { background: var(--scen-d); color: white; }

/* Shared-link banner, above the result. */
.ret-shared-banner {
  display: flex; align-items: center; gap: 0.65rem; padding: 0.7rem 1rem; margin-bottom: 1rem;
  background: var(--ovs-wash); border: 1px solid var(--ovs-line); border-radius: 10px;
  font-size: 0.85rem; color: var(--text); line-height: 1.45;
}
.ret-shared-banner[hidden] { display: none !important; }
.ret-shared-banner__close { margin-left: auto; background: none; border: none; font-size: 0.85rem; color: var(--brand); cursor: pointer; padding: 0.1rem 0.2rem; }

/* 1. The verdict line: the PvS #pvs_verdict treatment from 600px up (a --brand bar, white text, in the flow).
   The (1,3,2) selector outranks css/tepuy.css's stacked-layout padding reset on <main>'s children, which is
   (1,2,2) because its :not() lists an id, so the shared stylesheet is not touched. */
.ovs-verdict { position: relative; margin: 0 0 6px; border-radius: var(--radius, 12px); background: var(--brand); color: var(--text-inverse); }
body.calc .main-layout > main > #ovsVerdict.ovs-verdict { padding: 14px 18px; }

/* The phone action bar's copy: in the layout (js/mobile-action-bar.js copies a source only while it has a box)
   but not seen, and aria-hidden in the markup, so the sentence is read once. */


@media (max-width: 599.98px) {
  body.calc .main-layout > main > #ovsVerdict.ovs-verdict { padding: 12px 14px; }
  
}

/* 2. The four scenario cards: one grid, 4 across, 2x2 from the 640px container tier (calc-layout, not calc-main:
   kpi_grid_calc_layout.test.js), every row the same height (grid-auto-rows: 1fr), so no orphan row. */
.ovs-kpi-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 10px; margin: 0 0 12px; }
@container calc-layout (max-width: 640px) { .ovs-kpi-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.ovs-kpi-card.is-top { border-top-color: var(--brand); }
.ovs-kpi-label { display: flex; align-items: center; gap: 6px; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text); }

.ovs-kpi-exact { font-size: 0.75rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.ovs-kpi-tag { align-self: flex-start; padding: 1px 7px; border-radius: 999px; font-size: 0.66rem; font-weight: 700; color: var(--brand); background: var(--ovs-line-soft); }
.ovs-kpi-second { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px; margin-top: auto; padding-top: 6px; border-top: 1px solid var(--ovs-line-soft); font-size: 0.78rem; color: var(--text); }
.ovs-kpi-second strong { font-variant-numeric: tabular-nums; }

/* "Why this result" (under the cards) and "How tax is modelled" (under the results tabs): closed by default. */


.ovs-cgt-notice a { color: var(--brand); }

/* Results before first paint (UI-2, 26 Oct). The column from the verdict down is laid out but not painted until
   js/offset_vs_shares_calc.js's first calculate() has filled it (its finally block clears the class; the inline
   <head> script sets it and clears it after 5 s at the latest), so the verdict, the cards and the tabs do not move
   when the load-time run fills them. Hidden boxes changing size are not layout shifts; the page head and the
   sidebar paint at once. */
html.ovs-first-run main > #ovsVerdict,
html.ovs-first-run main > #ovsVerdict ~ * {
  visibility: hidden;
}

/* 4. The chart's one legend: the scenario chips. */


/* The watermark is drawn on the canvas, in the band under the x-axis labels, right-aligned (the ovsWatermark
   plugin in js/offset_vs_shares_calc.js), so it is outside the plot and goes into the PNG and the PDF. The old
   CSS ::after sat over the plot lines and the x-axis (Luis, 8 Nov), and an export never had it. */
.rtab-chart::after { content: none; }

/* Share Result joins the PNG / PDF row (pushed to its end). */
#ovsShareResultBar.ret-share-result-bar { margin: 0 0 0 auto; }

/* 6. Phone: all five result tabs readable without sideways scrolling (two rows). A page-owned modifier on the tab
   strip, not a fork of css/calculators.css's .rtab-* rules (test/shared_stylesheet_ownership.test.js); the id keeps
   it above calculators.css, which loads later. A wrapped strip does not scroll, so js/rtab-scroll-affordance.js
   shows neither edge fade. */
@container calc-layout (max-width: 640px) {
  #ovsResultsTabs .ovs-tabs-wrap { flex-wrap: wrap; overflow: visible; row-gap: 2px; }
}

/* Insights tab. */
.ovs-insight-headline { margin-bottom: 1rem; padding: 0.85rem 1rem; font-size: 1rem; font-weight: 600; line-height: 1.55; color: var(--text); background: var(--ovs-wash); border: 1px solid var(--ovs-line); border-radius: 10px; }
.ovs-insight-headline strong { color: var(--brand); }
.ovs-ins-warn { background: color-mix(in srgb, var(--clay) 8%, white); border-color: color-mix(in srgb, var(--clay) 40%, white); }
.ovs-ins-warn strong { color: var(--ink) !important; }
.ovs-ins-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.75rem; margin-bottom: 1rem; }
@container calc-layout (max-width: 640px) { .ovs-ins-grid { grid-template-columns: 1fr 1fr; } }
.ovs-ins-kpi { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.75rem 0.85rem; background: var(--ovs-wash); border: 1px solid var(--ovs-line-soft); border-radius: 10px; }
.ovs-ins-kpi-label { font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); }
.ovs-ins-kpi-value { font-size: 1.1rem; font-weight: 700; line-height: 1.2; color: var(--text); font-variant-numeric: tabular-nums; }
.ovs-ins-kpi-value--green { color: var(--brand); }
.ovs-ins-kpi-value--warn { color: var(--ink); }
.ovs-ins-kpi-value--blue { color: var(--denim); }
.ovs-ins-kpi-sub { font-size: 0.67rem; line-height: 1.3; color: var(--text-muted); }
.ovs-ins-explain { padding: 1rem; background: var(--ovs-wash); border: 1px solid var(--ovs-line-soft); border-radius: 10px; }
.ovs-ins-exp-title { margin-bottom: 0.6rem; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); }
.ovs-ins-explain p { margin: 0; font-size: 0.9rem; line-height: 1.65; color: var(--text); }
.ovs-strat-top td { font-weight: 600 !important; }
.ovs-mc-summary { margin-top: 0.85rem; padding: 0.7rem 0.85rem; font-size: 0.82rem; line-height: 1.55; color: var(--text); background: white; border-radius: 8px; }
.ovs-hurdle-box { margin-top: 0.85rem; padding: 0.8rem 0.95rem; font-size: 0.85rem; line-height: 1.6; color: var(--text); background: color-mix(in srgb, var(--clay) 8%, white); border: 1px solid color-mix(in srgb, var(--clay) 35%, white); border-radius: 8px; }
.ovs-above, .ovs-pro { color: var(--brand); font-weight: 600; }
.ovs-below, .ovs-con { color: var(--ink); font-weight: 600; }
.ovs-pro, .ovs-con { font-size: 0.8rem; font-weight: 500; }
.ovs-equity-note { margin-top: 0.85rem; padding: 0.75rem 0.95rem; font-size: 0.82rem; line-height: 1.55; color: var(--text); background: color-mix(in srgb, var(--denim) 6%, white); border: 1px solid color-mix(in srgb, var(--denim) 25%, white); border-left: 3px solid var(--denim); border-radius: 8px; }
.ovs-equity-note strong { color: var(--denim); }
.ovs-wealth-defs { display: block; margin-top: 0.4rem; font-size: 0.75rem; font-style: italic; color: var(--text); }
.ovs-notice { margin-bottom: 0.75rem; padding: 0.75rem 1rem; font-size: 0.88rem; line-height: 1.55; color: var(--text); border-radius: 8px; }
.ovs-notice--warn { background: color-mix(in srgb, var(--clay) 9%, white); border-left: 4px solid var(--clay); }
.ovs-notice--info { background: color-mix(in srgb, var(--denim) 7%, white); border-left: 4px solid var(--denim); }
.ovs-notice strong { font-weight: 700; }
.ovs-ref-only { margin-left: 6px; padding: 1px 6px; font-size: 0.65rem; font-weight: 500; color: var(--text-muted); background: var(--ovs-line-soft); border-radius: 9999px; }

/* Year-by-Year table: scenario headers, the leading cell, the leader column, row states. */
.th-scen { text-align: center !important; font-size: 0.72rem !important; padding: 0.35rem !important; }
.th-scen-a { background: color-mix(in srgb, var(--scen-a) 15%, white) !important; color: var(--text) !important; }
.th-scen-b { background: color-mix(in srgb, var(--scen-b) 18%, white) !important; color: var(--text) !important; }
.th-scen-c { background: color-mix(in srgb, var(--scen-c) 18%, white) !important; color: var(--text) !important; }
.th-scen-d { background: color-mix(in srgb, var(--scen-d) 12%, white) !important; color: var(--text) !important; }
.td-lead { font-weight: 700 !important; color: var(--text) !important; background: color-mix(in srgb, var(--brand) 7%, white) !important; }
.td-ldr { font-weight: 700 !important; text-align: center !important; color: var(--text); }
.td-ldr.scen-a { background: color-mix(in srgb, var(--scen-a) 15%, white); }
.td-ldr.scen-b { background: color-mix(in srgb, var(--scen-b) 18%, white); }
.td-ldr.scen-c { background: color-mix(in srgb, var(--scen-c) 18%, white); }
.td-ldr.scen-d { background: color-mix(in srgb, var(--scen-d) 12%, white); }
.td-ldr.scen-a, .td-ldr.scen-b, .td-ldr.scen-c, .td-ldr.scen-d { color: var(--text); }
.td-oop .td-io { display: inline-block; margin-left: 0.25rem; padding: 0.05rem 0.3rem; font-size: 0.6rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; vertical-align: middle; color: var(--ink); background: color-mix(in srgb, var(--clay) 15%, white); border: 1px solid color-mix(in srgb, var(--clay) 45%, white); border-radius: 3px; }
.ovs-table tbody .tr-io-phase { background: color-mix(in srgb, var(--scen-a) 4%, white); }
.ovs-table tbody .tr-postpayoff { background: var(--ovs-wash); }
.ovs-table tbody .tr-postpayoff td { color: var(--brand); font-style: italic; }
.ovs-table tbody .tr-postpayoff .td-yr::after { content: ' ★'; font-size: 0.6rem; font-style: normal; color: var(--brand-light); }
.td-partial-badge { display: inline-block; margin-left: 4px; padding: 1px 4px; font-size: 0.6rem; font-weight: 700; vertical-align: middle; color: var(--text-inverse); background: var(--brand-light); border-radius: 3px; }

/* Sensitivity grid: each cell tinted with the scenario that ends highest of B, C and D there. */
.ovs-sens-table { border-collapse: collapse; font-size: 0.8rem; min-width: 360px; }
.ovs-sens-table th { padding: 0.45rem 0.6rem; text-align: center; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); background: var(--ovs-wash); border-bottom: 1.5px solid var(--ovs-line); }
.ovs-sens-table td { padding: 0.45rem 0.6rem; text-align: center; cursor: default; border-bottom: 1px solid var(--ovs-line-soft); }
.ovs-sens-table td.sens-a { background: color-mix(in srgb, var(--scen-a) 15%, white); }
.ovs-sens-table td.sens-b { background: color-mix(in srgb, var(--scen-b) 18%, white); }
.ovs-sens-table td.sens-c { background: color-mix(in srgb, var(--scen-c) 18%, white); }
.ovs-sens-table td.sens-d { background: color-mix(in srgb, var(--scen-d) 12%, white); }
.sens-top { display: block; font-size: 1rem; font-weight: 800; line-height: 1; color: var(--text); }
.sens-delta { display: block; margin-top: 1px; font-size: 0.62rem; color: var(--text-muted); }
.sens-corner { font-size: 0.72rem; }
.sens-corner-sub { font-size: 0.65rem; opacity: 0.7; }
.sens-col-actual { background: var(--ovs-line-soft) !important; font-weight: 700; }
.sens-row-actual th, .sens-row-actual-th { background: var(--ovs-line-soft) !important; font-weight: 700; }
.sens-cell-actual { outline: 2px solid var(--ink); outline-offset: -2px; }
.sens-actual-dot { margin-left: 2px; font-size: 0.55rem; vertical-align: middle; color: var(--ink); }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════
   OVS-VISUAL-1 — directions A and B combined (Luis, 9 Nov 2026; design record docs/design/ovs-visual-1/). Page-scoped:
   every selector is this page's own (#ovs…, .ovs-…) or a shared class under one of them, so no other calculator
   changes. Palette tokens, tints of them and white only (test/ovs_ux4_palette.test.js reads this section too).
   UX-4A (11 Nov 2026): the shared results pattern this section built (the Quick panel, the answer, the bars card, the
   key-figure tiles, the disclosures and the chip legend) moved, verbatim and in order, to css/calc-results.css, which
   this page links immediately before this file; Mortgage reuses it. What stays here is this page's own.
   ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.scen-bg-a { background: var(--scen-a); } .scen-bg-b { background: var(--scen-b); }
.scen-bg-c { background: var(--scen-c); } .scen-bg-d { background: var(--scen-d); }

/* Sidebar: Quick / Full (the toggle's own chrome is css/simulators.css, shared). */


/* The sliders take the shared sidebar range style (css/simulators.css, css/mobile-polish.css: Property vs Shares'
   sliders), so the two Quick panels look and behave alike; only the width and the focus ring are this page's. */


/* The answer and the four paths */


/* Families (OVS-VISUAL-1b): a band with the family's name and idea, its paths under it; the Offset family's what-if
   (O3) under a dashed rule inside it. */
.ovs-fam { display: flex; flex-direction: column; border-left: 3px solid var(--ovs-fam-accent, var(--ovs-fam-offset)); padding-left: .7rem; margin: .35rem 0 .15rem; }
.ovs-fam--offset { --ovs-fam-accent: var(--ovs-fam-offset); }
.ovs-fam--shares { --ovs-fam-accent: var(--ovs-fam-shares); }
.ovs-fam__band { display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap; padding: .3rem .55rem; border-radius: 8px;
  background: color-mix(in srgb, var(--ovs-fam-accent) 12%, white); }
.ovs-fam__name { font-size: .72rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--ovs-fam-accent) 70%, black); }
.ovs-fam__idea { font-size: .8rem; font-weight: 600; color: var(--text); }
.ovs-fam__rule { border-top: 1px dashed color-mix(in srgb, var(--ink) 22%, transparent); margin: .25rem 0 0; }
.ovs-lane__owed { grid-column: 1 / -1; font-size: .76rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ovs-leg-fam { align-self: center; font-size: .7rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.ovs-leg-fam--offset { color: color-mix(in srgb, var(--clay) 70%, black); }
.ovs-leg-fam--shares { color: color-mix(in srgb, var(--moss) 85%, black); }
.ovs-leg-fam--shares { margin-left: .5rem; }
.th-fam { font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; color: var(--text) !important; text-align: left !important; padding-left: .8rem !important; }
.th-fam-offset { background: color-mix(in srgb, var(--clay) 24%, white) !important; }
.th-fam-shares { background: color-mix(in srgb, var(--moss) 24%, white) !important; }
.ovs-sens-key { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .8rem; margin: .5rem 0 0; font-size: .78rem; color: var(--text-muted); }
.ovs-sens-key__fam { font-size: .7rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }
.ovs-sens-key__fam--offset { color: color-mix(in srgb, var(--clay) 70%, black); }
.ovs-sens-key__fam--shares { color: color-mix(in srgb, var(--moss) 85%, black); }
.ovs-sens-key__i { display: inline-flex; align-items: center; gap: .3rem; }
.ovs-sens-key__i i { display: inline-block; width: 14px; height: 10px; border-radius: 2px; }
.ovs-sens-key__i i.sens-b { background: var(--scen-b); } .ovs-sens-key__i i.sens-c { background: var(--scen-c); } .ovs-sens-key__i i.sens-d { background: var(--scen-d); }
.ovs-mc__row.is-whatif { border-top: 1px dashed color-mix(in srgb, var(--ink) 18%, transparent); }

#ovsKpiStrip .ovs-lane .ovs-kpi-tag { grid-column: 1; justify-self: start; margin: -.1rem 0 0; }

#ovsKpiStrip .ovs-lane.is-top .ovs-lane__name::after { content: 'ends highest'; font-size: .7rem; font-weight: 700; color: var(--brand);
  background: color-mix(in srgb, var(--brand) 9%, white); border-radius: 999px; padding: .12rem .5rem; }


.ovs-lane[data-scen="A"] .ovs-lane__bar { background-color: var(--scen-a); opacity: .6;
  background-image: repeating-linear-gradient(135deg, color-mix(in srgb, white 24%, transparent) 0 6px, transparent 6px 12px); }
.ovs-lane[data-scen="B"] .ovs-lane__bar { background-color: var(--scen-b); }
.ovs-lane[data-scen="C"] .ovs-lane__bar { background-color: var(--scen-c); }
.ovs-lane[data-scen="D"] .ovs-lane__bar { background-color: var(--scen-d); }
.ovs-lane__lump { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: color-mix(in srgb, white 56%, transparent); border-right: 2px solid white; }
.ovs-lane__gaplabel { position: absolute; right: 100%; top: 50%; transform: translateY(-50%); padding-right: .4rem; white-space: nowrap;
  font-size: .72rem; font-weight: 800; color: white; }
.ovs-lane[data-scen="B"] .ovs-lane__gaplabel { color: var(--ink); }


#ovsKpiStrip .ovs-lane .ovs-kpi-exact { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ovs-lanes__key { order: 10; display: flex; align-items: center; gap: .45rem; margin: .5rem 0 0; font-size: .78rem; color: var(--text-muted); }
.ovs-lanes__key i { flex: none; width: 22px; height: 10px; border-radius: 3px; background: color-mix(in srgb, var(--moss) 42%, white); }

/* Key-figure tiles */

/* OVS-BREAKEVEN-1: six tiles, three a row; the level point's words (no crossing in range) set smaller than a figure. */

.ovs-tile--level .scen-pill + .scen-pill { margin-left: -.15rem; }



.ovs-ring__fill { stroke: var(--scen-c); }
.ovs-ring__fill[data-scen="B"] { stroke: var(--scen-b); } .ovs-ring__fill[data-scen="D"] { stroke: var(--scen-d); }

/* Lead timeline */
.ovs-lead { background: white; border: 1px solid color-mix(in srgb, var(--ink) 10%, transparent); border-radius: 18px; padding: .9rem 1.1rem; margin: 0 0 1rem; }
.ovs-lead__h { margin: 0; font-size: .98rem; font-weight: 800; color: var(--text); }
.ovs-lead__cap { margin: .15rem 0 .55rem; font-size: .8rem; color: var(--text-muted); }
.ovs-lead__strip { display: grid; gap: 3px; }
.ovs-lead__cell { height: 30px; border-radius: 6px; display: grid; place-items: center; font-size: .74rem; font-weight: 800; color: white; }
.ovs-lead__cell.scen-bg-b { color: var(--ink); }
.ovs-lead__axis { display: flex; justify-content: space-between; margin-top: .3rem; font-size: .74rem; color: var(--text-muted); }
.ovs-lead__txt { margin: .45rem 0 0; font-size: .86rem; color: var(--text); }

/* Wealth paths: race controls and the toggle chips (the one legend) */
.ovs-race { display: flex; align-items: center; gap: .7rem; margin: .1rem 0 .4rem; }
.ovs-race__play { width: 40px; height: 40px; flex: none; border-radius: 50%; border: 0; background: var(--brand); color: white; display: grid; place-items: center; cursor: pointer; }
.ovs-race__play svg { width: 14px; height: 14px; }
.ovs-race__play:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.ovs-race__year { flex: 1; accent-color: var(--brand); min-width: 0; }
.ovs-race__lab { min-width: 4.6rem; font-weight: 800; font-size: .95rem; color: var(--text); }


.ovs-race__at { display: flex; flex-wrap: wrap; gap: .35rem .9rem; align-items: center; margin-top: .45rem; font-size: .84rem; color: var(--text); min-height: 1.6rem; }
.ovs-race__y { font-weight: 800; }
.ovs-race__v { display: inline-flex; align-items: center; gap: .3rem; font-variant-numeric: tabular-nums; }
.ovs-race__v.is-lead { font-weight: 800; }
.ovs-race__v small { color: var(--text-muted); }

/* Monte Carlo strips */
.ovs-mc { margin-top: .4rem; }
.ovs-mc__axis { display: flex; justify-content: space-between; margin: 0 92px 0 172px; font-size: .74rem; color: var(--text-muted); }
.ovs-mc__row { display: grid; grid-template-columns: 160px minmax(0, 1fr) 80px; gap: .25rem .75rem; align-items: center; padding: .6rem 0; border-top: 1px solid color-mix(in srgb, var(--ink) 8%, transparent); }
.ovs-mc__row:first-of-type { border-top: 0; }
.ovs-mc__name { display: flex; align-items: center; gap: .45rem; font-weight: 700; font-size: .9rem; color: var(--text); }
.ovs-mc__name small, .ovs-mc__val small { display: block; font-size: .7rem; font-weight: 600; color: var(--text-muted); }
.ovs-mc__name small { display: inline; }
.ovs-mc__strip { position: relative; height: 22px; }
.ovs-mc__b90, .ovs-mc__b50 { position: absolute; top: 50%; height: 10px; transform: translateY(-50%); border-radius: 999px; }
.ovs-mc__b90 { opacity: .28; } .ovs-mc__b50 { opacity: .72; }
.ovs-mc__med { position: absolute; top: 50%; width: 4px; height: 22px; border-radius: 2px; transform: translate(-50%, -50%); background: var(--ink); }
.ovs-mc__val { text-align: right; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.ovs-mc__line { margin: .8rem 0 0; font-size: .95rem; font-weight: 600; color: var(--text); }

/* Sensitivity: each cell tinted in the top scenario's colour, more for a larger margin (sens-heat-0..5, set per cell
   by renderSensitivity: $12K steps); dark text throughout. */
#ovsSensPanel .ovs-sens-table td { color: var(--text); }
#ovsSensPanel .ovs-sens-table td.sens-b { --ovs-heat: var(--scen-b); } #ovsSensPanel .ovs-sens-table td.sens-c { --ovs-heat: var(--scen-c); }
#ovsSensPanel .ovs-sens-table td.sens-d { --ovs-heat: var(--scen-d); }
#ovsSensPanel .ovs-sens-table td.sens-heat-0 { background: color-mix(in srgb, var(--ovs-heat) 12%, white); }
#ovsSensPanel .ovs-sens-table td.sens-heat-1 { background: color-mix(in srgb, var(--ovs-heat) 19%, white); }
#ovsSensPanel .ovs-sens-table td.sens-heat-2 { background: color-mix(in srgb, var(--ovs-heat) 26%, white); }
#ovsSensPanel .ovs-sens-table td.sens-heat-3 { background: color-mix(in srgb, var(--ovs-heat) 33%, white); }
#ovsSensPanel .ovs-sens-table td.sens-heat-4 { background: color-mix(in srgb, var(--ovs-heat) 40%, white); }
#ovsSensPanel .ovs-sens-table td.sens-heat-5 { background: color-mix(in srgb, var(--ovs-heat) 47%, white); }
#ovsSensPanel .ovs-sens-table td.sens-cell-actual { outline: 2.5px solid var(--ink); outline-offset: -2px; }

/* Your result: the share card */
.ovs-share { margin: 1.2rem 0; }
.ovs-share__h { margin: 0 0 .6rem; font-size: 1.15rem; font-weight: 800; color: var(--text); }
.ovs-share__card { background: var(--stone); color: var(--bone); border-radius: 20px; padding: 1.2rem 1.3rem; max-width: 640px; }
.ovs-share__brand { font-size: .74rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; opacity: .78; }
.ovs-share__head { margin: .5rem 0 .9rem; font-size: 1.3rem; font-weight: 800; line-height: 1.2; color: var(--bone); }
.ovs-share__rows { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; }
.ovs-share__rows > div { background: color-mix(in srgb, var(--bone) 8%, transparent); border-radius: 12px; padding: .55rem .7rem; font-size: .8rem; }
.ovs-share__rows b { display: block; font-size: 1.1rem; margin-top: .1rem; }
.ovs-share__rows .scen-d { background: var(--bone); color: var(--ink); }
.ovs-share__ass { margin: .9rem 0 0; font-size: .76rem; line-height: 1.5; opacity: .78; }
.ovs-share__actions { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin-top: .8rem; }

/* Tiers (the page's container, body.calc: calc-layout) */
@container calc-layout (max-width: 1239.98px) {
  
  
  .ovs-tile--mc, .ovs-tile--level { grid-column: 1 / -1; }
}
@container calc-layout (max-width: 799.98px) {
  /* Stacked: the inputs come before the answer (UX-RUN-FIRST, Luis 10 Nov 2026; until then the answer, the paths, the
     tiles and the lead were ordered 1, above the inputs). css/tepuy.css orders the page head 1, the aside 2 and the rest
     of main 3 (main is display: contents here). */
  .ovs-mc__axis { margin: 0; }
  .ovs-mc__row { grid-template-columns: minmax(0, 1fr) auto; }
  .ovs-mc__strip { grid-column: 1 / -1; grid-row: 2; }
}
@media (max-width: 599.98px) {
  /* The page head (shared partial) on this page only: one column, compact, so the answer is on the first screen. */
  
  
  
  
  
  
  
  
  
  
  
  .ovs-share__rows { grid-template-columns: minmax(0, 1fr); }
}

.ovs-share__actions { max-width: 640px; justify-content: flex-start; }
.ovs-share__actions .ret-share-result-bar { margin: 0; }
/* axe (OVS-VISUAL-1): the grid's small text reads at full text colour on every tint, and the corner sub-label in the
   page's muted text token (5.25:1 on its ground); the scroll regions are focusable (tabindex in the markup). */
#ovsSensPanel .ovs-sens-table .sens-delta, #ovsSensPanel .ovs-sens-table .sens-top { color: var(--text); opacity: 1; }
#ovsSensPanel .ovs-sens-table .sens-corner-sub { color: var(--text-muted); opacity: 1; }
.ovs-table-wrap:focus-visible, #ovsSensPanel .ovs-sens-wrap:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ═══ OVS-VISUAL-1b — polish (Leo, 9 Nov 2026; words and layout only, no figure changes) ═══ */
/* (2) The hero: the answer and the key-figure tiles in the left column, the bars card in the right, so no empty band
   opens under the answer at 1440. Stacked (one column), the tiles follow the bars. */


/* The bars card runs the height of both rows, its four bars spread evenly, so the two columns end together. */


/* (4) Tile sub-lines at the body minimum (14px) in the muted body colour (5.95:1 on white); the label a step up. */


/* (3) In Quick the run button is secondary: outlined, the brand colour on white (9.74:1). */
/* The selector mirrors css/simulators.css's shared #runBtn rule (id + :not(:has()), !important) with one class more. */
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer #runBtn.ovs-run--quiet { background: white !important; color: var(--brand) !important;
  border: 1.5px solid var(--brand) !important; box-shadow: none !important; }
body.calc .calc-aside:not(:has(#advModePanel)) .sidebar-footer #runBtn.ovs-run--quiet:hover { background: color-mix(in srgb, var(--brand) 6%, white) !important; }
/* (5) "Also assumed" as a disclosure with a count. */


.ovs-mc__name small, .ovs-race__v small { white-space: nowrap; }
/* OVS-VISUAL-1b: the worked example's row headers name a path with its chip ("O3 — Interest-only + invest"); on a
   phone they wrap instead of pushing the table wider than the page (the shared rule keeps them on one line). */
@media (max-width: 600px) { .calc-explainer .worked-example tbody th { white-space: normal; } }
