/* Take-Home Pay Simulator — EMS-aligned, single-page, graph-first.
   Deep-navy primary, teal secondary, light background, scientific-figure graph. */

:root {
  /* The app is a single, always-light design (no theme switching): it never follows the OS into dark,
     and `color-scheme: light` keeps native controls (dropdowns, checkboxes, scrollbars) light too so
     nothing renders dark-on-light on a dark-mode Mac. */
  color-scheme: light;
  --navy: #10233f;
  --teal: #0f9f7a;
  --teal-deep: #0a6b52; /* WCAG-AA: light text meets 4.5:1 on this deep emerald (plain --teal is too light) */
  --bg: #f5f7f6;
  --surface: #ffffff;
  --text: #21303b;
  --muted: #5b6670; /* WCAG-AA: ≥4.5:1 on white AND on the light-emerald current-band chip */
  --line: #e3e8ec;
  --grid: #eef2f4;
  --crosshair: #0b7a5c;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(16, 35, 63, 0.06), 0 6px 20px rgba(16, 35, 63, 0.05);
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Themed surfaces/tracks (pptx S3 dark-mode fix): every light hard-coded colour now flows through a
     variable so a single dark override recolours the whole app — no more light boxes with light text. */
  --surface-alt: #fafbfb;         /* zebra rows, sub-panels, pills */
  --surface-alt-hover: #eef2f4;
  --track: #e7edf0;               /* read-only bars / zoom rails */
  --track-2: #dfe6ea;             /* range inputs */
  --soft-bg: #f4f8fb;             /* explainer callouts */
  --svg-label-bg: #ffffff;        /* crosshair/band label backing */
  --warn-bg: #fff6ea; --warn-border: #f0c98a; --warn-text: #7a3c00;
  --info-bg: #fff7e9; --info-border: #f0e0c0; --info-text: #6b5320;
  --danger-bg: #fdecea; --danger-border: #f3c6c0; --danger-text: #a3271b;
  --band-current-bg: #d8f2e8;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body { font-family: var(--sans); color: var(--text); background: var(--bg); line-height: 1.45; -webkit-font-smoothing: antialiased; }

/* Desktop remains a single, non-scrolling workspace. Conditional content uses reserved geometry,
   while the chart flexes within the remaining viewport rather than growing the page. */
#simulator-root { height: 100vh; overflow: hidden; padding: 20px clamp(16px, 2.5vw, 44px); display: flex; flex-direction: column; }

.layout {
  display: grid;
  grid-template-columns: minmax(340px, 1fr) minmax(0, 1.9fr);
  grid-template-rows: minmax(0, 1fr);
  gap: clamp(20px, 2.4vw, 36px);
  flex: 1;
  min-height: 0;
  align-items: stretch;
}
/* minmax(0, 1fr) — NOT bare 1fr — so the single column can shrink below the chart's intrinsic min-content
   width (the desktop columns already use minmax(0,…)). Bare 1fr keeps a min-content floor = the 840-wide
   SVG, which forced a horizontal page scroll on narrow viewports (CUB-TOK-05). */
@media (max-width: 900px) {
  #simulator-root { height: auto; overflow: visible; }
  .layout { grid-template-columns: minmax(0, 1fr); min-height: 0; }
}
/* CUB-TOK-03 mobile first-screen rules live at the END of this file (after the base rules they override),
   so equal-specificity media-query rules win by source order. See the @media (max-width: 640px) block. */

/* ── Graph panel ────────────────────────────────────────────────────── */
.graph-panel {
  order: 2;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 20px 24px 22px;
  display: flex; flex-direction: column; min-height: 0;
}

/* ── Welcome / progressive-disclosure state ──────────────────────────────────────────────────────────
   The welcome panel and the three calculator sections toggle via the real `hidden` attribute (set in JS).
   Their base classes set display:grid/flex, which would beat the UA [hidden] rule, so restore display:none
   here at higher specificity — a hidden section is then truly out of layout, the a11y tree AND focus order. */
.graph-panel .welcome-panel[hidden],
.graph-panel .graph-topbar[hidden],
.graph-panel .bands-and-view-toggle[hidden],
.graph-panel .chart-grid[hidden] { display: none; }

.welcome-panel { display: flex; flex-direction: column; gap: 14px; max-width: 640px; margin: clamp(8px, 4vh, 48px) auto; padding: 4px 8px; }
.welcome-heading { margin: 0; color: var(--navy); font-size: clamp(1.5rem, 3vw, 2.1rem); line-height: 1.1; letter-spacing: -0.02em; }
.welcome-sub { margin: 0; color: var(--muted); font-size: clamp(1rem, 1.5vw, 1.15rem); }
.welcome-uses-title { margin: -2px 0 0; color: var(--teal-deep); font-size: 0.9rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; }
.welcome-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.welcome-list li { position: relative; padding-left: 30px; color: var(--text); font-size: 1rem; line-height: 1.4; }
.welcome-list li::before { content: ""; position: absolute; left: 4px; top: 0.42em; width: 9px; height: 9px; border-radius: 3px; background: var(--teal); }
.welcome-cta { align-self: flex-start; margin-top: 8px; min-height: 48px; padding: 10px 22px; color: #fff; background: var(--teal-deep); border: 2px solid var(--teal-deep); border-radius: 10px; box-shadow: 0 5px 15px rgba(10,107,82,.25); font: inherit; font-size: 1rem; font-weight: 800; cursor: pointer; }
.welcome-cta:hover { transform: translateY(-1px); box-shadow: 0 9px 22px rgba(10,107,82,.3); }
.welcome-step-hint { min-height: 1.55em; margin: -4px 0 0; color: var(--muted); font-size: 0.82rem; line-height: 1.55; opacity: 0; visibility: hidden; }
.welcome-step-hint.is-visible { opacity: 1; visibility: visible; }
.welcome-disclaimer { margin: 8px 0 2px; padding-top: 16px; border-top: 1px solid var(--line); color: var(--muted); font-size: 0.82rem; line-height: 1.55; }
.welcome-disclaimer strong { color: var(--navy); }

/* Subtle one-shot reveal when the calculator first appears (data-engaged flips true once per session). */
@media (prefers-reduced-motion: no-preference) {
  .graph-panel[data-engaged="true"] .graph-topbar,
  .graph-panel[data-engaged="true"] .bands-and-view-toggle,
  .graph-panel[data-engaged="true"] .chart-grid { animation: welcome-reveal .28s ease both; }
}
@keyframes welcome-reveal { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.graph-topbar { display: grid; grid-template-columns: minmax(230px, 1fr) auto; align-items: center; gap: 10px 14px; margin-bottom: 12px; }
.graph-title { font-size: clamp(1.05rem, 1.6vw, 1.35rem); margin: 0; color: var(--navy); text-align: center; letter-spacing: -0.01em; }
.graph-actions { display: flex; align-items: center; justify-content: center; gap: 7px; flex-wrap: wrap; }
.step-title { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.step-badge { display: inline-grid; place-items: center; flex: 0 0 auto; padding: 2px 9px; min-height: 22px; border: 2px solid currentColor; border-radius: 999px; font-size: .72rem; font-weight: 900; line-height: 1; white-space: nowrap; }
.scenario-tools { display: inline-flex; align-items: center; gap: 7px; margin-left: 3px; padding-left: 10px; border-left: 1px solid var(--line); }
.graph-utilities { grid-column: 1 / -1; justify-self: stretch; display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-width: 0; }
.compact-result { display: block; color: #fff; font-size: 0.92rem; font-weight: 800; line-height: 1.15; white-space: nowrap; }
.results-summary-cta { display: inline-flex; min-height: 50px; min-width: 185px; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; padding: 7px 12px; border: 2px solid var(--teal-deep); border-radius: 10px; background: var(--teal-deep); color: #fff; box-shadow: 0 5px 15px rgba(10,107,82,.25); font: inherit; text-align: left; cursor: pointer; }
.results-step { font-size: .84rem; font-weight: 800; white-space: nowrap; }
.results-summary-hint { font-size: .69rem; font-weight: 650; opacity: .82; }
.results-summary-cta:hover { transform: translateY(-1px); background: #086047; box-shadow: 0 8px 19px rgba(10,107,82,.32); }
.results-summary-cta:focus-visible { outline: 3px solid rgba(15,159,122,.3); outline-offset: 2px; }
.btn-primary, .btn-secondary { min-height: 32px; padding: 6px 11px; border-radius: 8px; font: inherit; font-size: 0.76rem; font-weight: 700; cursor: pointer; }
.btn-primary { min-height: 38px; padding-inline: 15px; color: #fff; background: var(--navy); border: 2px solid var(--navy); box-shadow: 0 3px 10px rgba(16,35,63,.2); font-size: .84rem; }
.results-cta { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 42px; color: var(--navy); background: #fff; border-color: var(--navy); box-shadow: 0 4px 12px rgba(16,35,63,.14); }
.results-cta:hover { transform: translateY(-1px); color: #fff; background: var(--navy); box-shadow: 0 8px 19px rgba(16,35,63,.25); }
.results-cta:focus-visible { outline: 3px solid rgba(16,35,63,.24); outline-offset: 2px; }
.results-icon { width: 18px; height: 18px; flex: none; background: currentColor; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4 4h16v16H4zM7 15h2v2H7zm0-4h2v2H7zm0-4h2v2H7zm4 8h6v2h-6zm0-4h6v2h-6zm0-4h6v2h-6z'/%3E%3C/svg%3E") center / contain no-repeat; }
.btn-secondary { color: var(--navy); background: var(--surface); border: 1px solid var(--line); }
.btn-primary:hover, .btn-secondary:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.btn-secondary:disabled { cursor: not-allowed; opacity: 0.48; transform: none; box-shadow: none; }
.save-scenario-wrap, .compare-scenario-wrap { display: inline-flex; border-radius: 8px; }
.compare-scenario-wrap[hidden] { display: inline-flex; visibility: hidden; pointer-events: none; }
.save-scenario-wrap:focus-visible, .compare-scenario-wrap:focus-visible { outline: 3px solid rgba(15,159,122,.3); outline-offset: 2px; }
.scenario-chips { display: flex; flex: 1; justify-content: flex-end; gap: 5px; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
.scenario-chip { flex: none; max-width: 105px; padding: 4px 7px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border: 1px solid var(--line); border-radius: 999px; background: var(--surface-alt); color: var(--navy); font-size: 0.69rem; cursor: pointer; }
.scenario-chip[aria-current="true"] { color: #fff; background: var(--teal-deep); border-color: var(--teal-deep); }
.export-cta { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 42px; padding: 8px 15px; border: 2px solid var(--teal-deep); border-radius: 9px; background: var(--teal-deep); color: #fff; box-shadow: 0 5px 15px rgba(10,107,82,.25); font: inherit; font-size: .84rem; font-weight: 800; cursor: pointer; }
.graph-actions > .export-cta { min-height: 50px; padding-inline: 14px; border-radius: 10px; font-size: .82rem; white-space: nowrap; }
.graph-actions > .export-cta .export-icon { width: 17px; height: 17px; }
.export-cta:hover { transform: translateY(-1px); box-shadow: 0 8px 19px rgba(10,107,82,.32); }
.export-cta:focus-visible { outline: 3px solid rgba(15,159,122,.3); outline-offset: 2px; }
.export-icon { width: 19px; height: 19px; flex: none; background: currentColor; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12M7 8l5-5 5 5M5 13v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6'/%3E%3C/svg%3E") center / contain no-repeat; }

@media (max-width: 1100px) and (min-width: 901px) {
  .graph-topbar { grid-template-columns: 1fr; }
  .graph-actions { justify-content: flex-start; }
}

.graph-controls-left { display: flex; flex-direction: column; gap: 9px; justify-self: stretch; align-items: flex-start; min-width: 0; }
.metric-view-row { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; }
.y-metric-label { display: flex; align-items: center; gap: 7px; width: 100%; min-width: 0; font-size: 0.82rem; color: var(--muted); }
.y-metric { flex: 1 1 280px; width: 100%; min-width: 0; max-width: 480px; font-size: 0.95rem; padding: 7px 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--navy); font-weight: 600; cursor: pointer; }
.period-toggle { display: flex; align-items: center; gap: 3px; }
.period-caption { font-size: 0.8rem; color: var(--muted); margin-right: 4px; }
.period-toggle label { font-size: 0.84rem; padding: 5px 11px; border: 1px solid var(--line); border-radius: 999px; cursor: pointer; background: var(--surface-alt); position: relative; }
.period-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.period-toggle label:has(input:checked) { background: var(--navy); color: #fff; border-color: var(--navy); }
.period-toggle label:focus-within { outline: 2px solid var(--teal); outline-offset: 1px; }
.btn-ghost { justify-self: end; font-size: 0.74rem; color: var(--navy); background: var(--surface-alt); border: 1px solid var(--line); border-radius: 8px; padding: 4px 10px; cursor: pointer; }
.btn-ghost:hover { background: var(--surface-alt-hover); }
.graph-utilities [data-testid="y-auto"][hidden] { display: inline-block; visibility: hidden; pointer-events: none; }
.bands-and-view-toggle { position: relative; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.bands-and-view-toggle .bands-section { flex: 1 1 auto; min-width: 0; }
/* Absolutely positioned in the plot's right-hand margin, OUT of layout flow: it adds no row to the graph
   column (so the aspect-locked SVG keeps its full height/width) and cannot shift the graph or any future
   sibling when its text wraps to 1, 2 or 3 lines. Narrow + wrapping so it stays clear of the plotted curve. */
.chart-view-toggle { position: absolute; top: 50%; right: 8px; transform: translateY(-50%); z-index: 4; box-sizing: border-box; width: 132px; height: 106px; display: grid; grid-template-rows: 1fr 1fr; gap: 2px; padding: 7px; white-space: normal; text-align: center; color: var(--teal-deep); background: #effaf6; border: 2px solid var(--teal-deep); border-radius: 10px; font-size: .7rem; line-height: 1.15; font-weight: 750; box-shadow: 0 5px 16px rgba(10,107,82,.16); }
/* FIXED width AND height: both label states ("…pie chart instead" / "…graph instead") wrap inside the same
   box, so clicking never reshapes the button. Out of flow + fixed size ⇒ zero layout drift on toggle. */
.chart-view-option { position: relative; display: grid; place-items: center; min-height: 44px; padding: 4px 5px; border: 1px solid transparent; border-radius: 7px; cursor: pointer; }
.chart-view-option input { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; pointer-events: none; }
.chart-view-option span { display: block; }
.chart-view-option:has(input:checked) { color: #fff; background: var(--teal-deep); border-color: var(--teal-deep); box-shadow: 0 2px 7px rgba(10,107,82,.22); }
.chart-view-option:has(input:focus-visible) { outline: 3px solid rgba(15,159,122,.35); outline-offset: 2px; }
.chart-view-option:hover:not(:has(input:checked)) { background: var(--band-current-bg); border-color: var(--teal); }
.chart-view-toggle[hidden] { display: none; }
/* Re-assert the centering transform on hover so it overrides `.btn-secondary:hover`'s translateY(-1px)
   (equal specificity, so this later rule wins). Hover feedback is colour/border/shadow only — no movement. */
.chart-view-toggle:hover { transform: translateY(-50%); box-shadow: 0 8px 20px rgba(10,107,82,.2); }

/* chart grid: [y-zoom][svg] / [corner][x-zoom] */
.chart-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto 24px; gap: 6px; flex: 1; min-height: 0; }
.chart-wrap { grid-column: 1; grid-row: 1; min-width: 0; min-height: 0; position: relative; display: grid; }
.chart-view { grid-area: 1 / 1; min-width: 0; min-height: 0; position: relative; }
.chart-line-view, .pie-chart-view { width: 100%; height: 100%; }
/* Responsive SVG: fill the (now shrinkable) cell rather than imposing the viewBox's 840px intrinsic width,
   which would force horizontal overflow on narrow viewports (CUB-TOK-05). */
#chart { display: block; width: 100%; height: 100%; max-width: 100%; }
#chart { width: 100%; height: 100%; display: block; }
#pie-chart { display: block; width: 100%; height: 100%; max-width: 100%; }
.pie-slice-hit { fill: #fff; fill-opacity: .001; stroke: none; pointer-events: fill; cursor: pointer; }
.pie-slice { pointer-events: none; stroke: var(--surface); stroke-width: 2.5; vector-effect: non-scaling-stroke; transform-box: fill-box; transform-origin: center; transition: transform 160ms ease-out, filter 160ms ease-out; }
.pie-slice[data-active="true"] { transform: translate(var(--pie-pop-x), var(--pie-pop-y)) scale(1.015); filter: drop-shadow(0 5px 5px rgba(16,35,63,.2)); }
.pie-slice[data-key="takeHome"] { fill: var(--teal-deep); }
.pie-slice[data-key="incomeTax"] { fill: #c22a20; }
.pie-slice[data-key="employeeNi"] { fill: #c77f1a; }
.pie-slice[data-key="studentLoan"] { fill: #7556a8; }
.pie-slice[data-key="pensionFromPay"] { fill: #167da3; }
.pie-empty-state { position: absolute; inset: 0; display: grid; place-items: center; margin: 0; color: var(--muted); font-size: 1rem; text-align: center; }
.pie-empty-state[hidden] { display: none; }
.pie-legend { grid-column: 1; grid-row: 2; margin: 0 8px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--navy); }
.pie-legend-head { margin: 0 0 5px; font-size: .75rem; font-weight: 750; color: var(--muted); }
.pie-legend-rows { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px 10px; }
.pie-legend-row { min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto auto; align-items: center; column-gap: 6px; padding: 6px 8px; border-radius: 8px; transition: transform 160ms ease-out, background 160ms ease-out, box-shadow 160ms ease-out; }
.pie-legend-row[data-active="true"] { transform: translateY(-2px); background: var(--band-current-bg); box-shadow: inset 0 0 0 1.5px var(--teal), 0 4px 12px rgba(10,107,82,.12); }
.pie-legend-row:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.pie-legend-swatch { grid-row: 1 / span 2; width: 10px; height: 10px; border-radius: 3px; }
.pie-legend-swatch[data-key="takeHome"] { background: var(--teal-deep); }
.pie-legend-swatch[data-key="incomeTax"] { background: #c22a20; }
.pie-legend-swatch[data-key="employeeNi"] { background: #c77f1a; }
.pie-legend-swatch[data-key="studentLoan"] { background: #7556a8; }
.pie-legend-swatch[data-key="pensionFromPay"] { background: #167da3; }
.pie-legend-label { font-size: .7rem; line-height: 1.25; }
.pie-legend-value { font-size: .72rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pie-legend-percent { margin-left: 5px; color: var(--muted); font-weight: 400; }
.pie-legend-row[data-zero="true"] { opacity: .52; }
@media (max-width: 1200px) {
  .pie-legend-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Pie view keeps chart-wrap at its exact line-view size, so the plot cell NEVER resizes and the toggle NEVER
   moves when you switch views (both were drift). The legend — same labels, £ and % — is OVERLAID in the empty
   area to the LEFT of the centred circle instead of taking a row below it (which used to shrink the plot); the
   toggle sits in the empty area to the RIGHT, and the circle sits clear between them. */
/* Legend placement is chosen at RUNTIME by syncPieLayout() via chart-wrap[data-pie-fit], NOT a static
   breakpoint that can rot as labels/fonts/zoom change: it goes BESIDE the circle only where measured geometry
   proves the legend clears the circle's left edge AND the toggle clears its right edge AND the legend height
   fits; otherwise BENEATH (compact two columns). "mobile" is the coarse layout-mode fallback. Floats over
   empty white space, so it drops the card border/background. */
.chart-grid[data-view="pie"] .pie-legend { margin: 0; padding: 0; border: 0; background: none; box-shadow: none; }
/* grid-area: 1 / 1 gives this absolutely-positioned grid child a containing block = the plot cell (the base
   .pie-legend has grid-row: 2, an implicit ~zero-height track, which made top:50% resolve to 0 and clip). With
   the plot cell as the containing block, top:50% centres correctly. (grid-area:1/1, not grid-row:1/-1: chart-
   wrap uses implicit tracks, so -1 is unreliable.) */
.chart-wrap[data-pie-fit="beside"] .pie-legend { position: absolute; grid-area: 1 / 1; left: 8px; top: 50%; transform: translateY(-50%); z-index: 3; max-width: min(31%, 250px); }
.chart-wrap[data-pie-fit="beside"] .pie-legend-rows { grid-template-columns: minmax(0, 1fr); gap: 9px 0; }
.chart-wrap[data-pie-fit="beneath"] .pie-legend,
.chart-wrap[data-pie-fit="mobile"] .pie-legend { position: static; transform: none; margin: 10px auto 2px; max-width: 640px; }
.chart-wrap[data-pie-fit="beneath"] .pie-legend-rows,
.chart-wrap[data-pie-fit="mobile"] .pie-legend-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 18px; }
.chart-grid[data-view="pie"] .xzoom-wrap,
.chart-grid[data-view="pie"] .overlay-legend { visibility: hidden; }
@keyframes committed-frame-in { from { opacity: .72; } to { opacity: 1; } }
.graph-panel.committed-frame-in { animation: committed-frame-in 150ms ease-out; }
/* UI-REQ-1 off-scale indicator — a small badge over the top-right of the chart. */
.off-scale-indicator { position: absolute; top: 6px; right: 8px; max-width: 62%; margin: 0; padding: 5px 9px; font-size: 0.74rem; line-height: 1.3; color: var(--warn-text); background: var(--warn-bg); border: 1px solid var(--warn-border); border-radius: 8px; box-shadow: var(--shadow); }
.off-scale-indicator[hidden] { display: none; }
/* S2: Marginal-rates colour key + selected-salary breakdown. Reserved space below the SVG keeps the
   axes visible at every viewport size; items may wrap instead of overflowing or covering the plot. */
.overlay-legend { grid-column: 1; grid-row: 2; min-width: 0; max-width: none; margin: 0 8px; padding: 7px 12px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 14px; font-size: 0.75rem; color: var(--navy); background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow); }
.overlay-legend[hidden] { display: none; }
.overlay-legend-head { flex-basis: 100%; margin: 0 0 2px; font-size: 0.72rem; font-weight: 700; color: var(--muted); }
.overlay-policy-note { flex-basis: 100%; margin: 0 0 3px; font-size: 0.72rem; line-height: 1.35; color: var(--navy); }
.overlay-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.overlay-legend-item[data-zero="true"] { opacity: 0.45; }
.overlay-legend-item .overlay-val { margin-left: 1px; font-variant-numeric: tabular-nums; }
.overlay-swatch { width: 13px; height: 3px; border-radius: 2px; display: inline-block; }
.overlay-swatch.ov-incometax { background: #2563eb; }
.overlay-swatch.ov-ni { background: #0d9488; }
.overlay-swatch.ov-studentloan { background: #d97706; }
.overlay-swatch.ov-pension { background: #9333ea; }
.overlay-swatch.ov-total { background: var(--navy); height: 4px; }
.overlay-total { padding-left: 10px; border-left: 1px solid var(--line); font-weight: 700; }
.corner, .yzoom-wrap { display: none; }
.xzoom-wrap { grid-column: 1; grid-row: 3; display: flex; align-items: center; }
.zoom-x { width: 100%; }
.zoom-y { writing-mode: vertical-lr; direction: rtl; height: 100%; width: 18px; }

/* SVG chart primitives */
.axis-line { stroke: var(--navy); stroke-width: 1.2; }
.grid-line { stroke: var(--grid); stroke-width: 1; }
.tick-label { fill: var(--muted); font-size: 12px; font-family: var(--sans); }
.axis-title { fill: var(--navy); font-size: 13px; font-weight: 600; font-family: var(--sans); }
.curve { fill: none; stroke: var(--teal); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.scenario-curve { stroke-width: 3; opacity: .9; }
.scenario-curve-0 { stroke: #2563eb; }
.scenario-curve-1 { stroke: #d97706; stroke-dasharray: 8 4; }
.scenario-curve-2 { stroke: #9333ea; stroke-dasharray: 3 4; }
.scenario-chip-wrap { position: relative; display: inline-flex; padding-top: 4px; }
.scenario-chip-wrap .scenario-chip { padding-right: 22px; }
.scenario-chip-delete { position: absolute; top: 0; right: 1px; display: grid; place-items: center; width: 19px; height: 19px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--muted); font: 700 15px/1 sans-serif; cursor: pointer; opacity: 1; transform: scale(1); transition: transform .15s ease, color .15s ease, border-color .15s ease, background .15s ease, box-shadow .15s ease; }
.scenario-chip-delete:hover,.scenario-chip-delete:focus-visible { border-color: #b42318; background: #fff1f0; color: #b42318; box-shadow: 0 2px 7px rgba(180,35,24,.18); outline: none; transform: scale(1.14) rotate(8deg); }
[data-testid="toggle-scenario-curves"] { transition: color .16s ease, background .16s ease, border-color .16s ease, box-shadow .16s ease, transform .12s ease; }
[data-testid="toggle-scenario-curves"][aria-pressed="true"] { border-color: var(--teal-deep); background: var(--teal-deep); color: #fff; box-shadow: 0 5px 14px rgba(10,107,82,.2); }
[data-testid="toggle-scenario-curves"][aria-pressed="true"]:hover { background: var(--teal); box-shadow: 0 7px 18px rgba(10,107,82,.26); transform: translateY(-1px); }
[data-testid="toggle-scenario-curves"]:active { transform: translateY(1px); box-shadow: none; }
.overlay-swatch.scenario-curve-0 { background: #2563eb; }
.overlay-swatch.scenario-curve-1 { background: repeating-linear-gradient(90deg, #d97706 0 8px, transparent 8px 12px); }
.scenario-marker { stroke: #fff; stroke-width: 2; }
.scenario-marker-0 { fill: #2563eb; }
.scenario-marker-1 { fill: #d97706; }
.scenario-marker-2 { fill: #9333ea; }
/* Combined marginal-DEDUCTION curve (navy) drawn alongside the frozen marginal-income-tax staircase
   (muted, dashed) — two visually distinct, non-conflated series (INV-D2). */
.curve-combined { stroke: var(--navy); stroke-width: 3.2; }
.curve-frozen-marginal { stroke: var(--muted); stroke-width: 1.8; stroke-dasharray: 6 4; opacity: 0.8; }
/* S2: Marginal-rates overlay — the Total (navy, thick) with its components drawn beneath it in
   distinct colours; each is a TRUE staircase and they visibly add up to the Total. */
/* pptx S2: the component lines were too faint to see — thicker + full opacity, distinct hues. */
.curve-component { stroke-width: 2.6; opacity: 1; }
.curve-component.ov-incometax { stroke: #2563eb; }
.curve-component.ov-ni { stroke: #0d9488; }
.curve-component.ov-studentloan { stroke: #ea580c; }
.curve-component.ov-pension { stroke: #9333ea; stroke-dasharray: 6 3; }
.crosshair-dot.off-scale { fill: #d97706; }
.crosshair { stroke: var(--crosshair); stroke-width: 1.4; stroke-dasharray: 5 4; }
.crosshair-dot { fill: var(--crosshair); stroke: #fff; stroke-width: 2; cursor: ew-resize; filter: drop-shadow(0 2px 2px rgba(15, 23, 42, 0.3)); }
.marker-hit { fill: transparent; cursor: ew-resize; touch-action: none; }
.marker-halo { fill: #d8f3eb; stroke: var(--crosshair); stroke-width: 1.5; cursor: ew-resize; transition: r 120ms ease, fill 120ms ease; }
.marker-grip { stroke: #fff; stroke-width: 1.35; stroke-linecap: round; pointer-events: none; }
.marker-halo:hover, .marker-dragging .marker-halo { r: 13px; fill: #bce9dc; }
.marker-dragging, .marker-dragging [data-marker-handle] { cursor: ew-resize; }
.crosshair-label { fill: var(--navy); font-size: 12.5px; font-weight: 700; font-family: var(--sans); }
.crosshair-label-bg { fill: var(--svg-label-bg); opacity: 0.88; }
/* band boundary emphasis points on the curve */
.band-guide { stroke: #cdd6dd; stroke-width: 1; stroke-dasharray: 2 3; }
.band-point { stroke: #ffffff; stroke-width: 2; }
.band-point[data-rate="0"] { fill: #9aa7b2; }
.band-point[data-rate="20"] { fill: #0f9f7a; }
.band-point[data-rate="40"] { fill: #b7791f; }
.band-point[data-rate="45"] { fill: #b42318; }
.band-point[data-rate="60"] { fill: #6b4fa0; }
.band-point-label { font-size: 11px; font-weight: 700; font-family: var(--sans); fill: var(--navy); }
.band-point-label-bg { fill: var(--svg-label-bg); opacity: 0.85; }

/* Inline help affordance — a small "?" node; concise explanation shown on hover or click. */
.help {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 4px; flex: none;
  border-radius: 50%; border: 1px solid var(--line); background: var(--surface-alt);
  color: var(--muted); font-size: 0.66rem; font-weight: 700; line-height: 1;
  cursor: pointer; vertical-align: middle; user-select: none;
}
.help:hover, .help:focus-visible { background: var(--navy); color: #fff; border-color: var(--navy); outline: none; }

/* Tax-free allowance row: keep the "?" beside its label, value stays pushed to the right. */
.pa-gauge-name { display: inline-flex; align-items: center; }

/* Shared tooltip — rendered on <body> (JS-positioned) so no scroll container clips it.
   Wide + short text = a horizontal box, not a narrow vertical column. */
.tip {
  position: fixed; z-index: 100; max-width: 320px; width: max-content;
  background: var(--navy); color: #fff;
  font-size: 0.8rem; font-weight: 500; line-height: 1.4;
  padding: 8px 12px; border-radius: 8px;
  box-shadow: 0 6px 20px rgba(16, 35, 63, 0.28);
  pointer-events: none;
}
.tip[hidden] { display: none; }
/* Shared "lead line + bullets" copy — used in the "?" tooltips AND the pension / student-loan explainer
   boxes. A short plain-English lead, then tight scannable bullets. */
.rich-lead { margin: 0; }
.rich-list { margin: 5px 0 0; padding-left: 1.15em; }
.rich-list li { margin: 2px 0; }
.tip .rich-list { padding-left: 1.05em; }

/* ── Control panel ──────────────────────────────────────────────────── */
.control-panel { order: 1; display: flex; flex-direction: column; gap: 12px; min-height: 0; overflow-y: auto; padding-right: 2px; }
.control-panel > section, .control-panel > aside { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 10px 16px; }

.card-header-row { display: flex; align-items: stretch; gap: 6px; }
.card-header-row .card-collapse-toggle { flex: 1 1 auto; width: auto; min-width: 0; }
.card-collapse-toggle { width: 100%; min-height: 36px; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0; border: 0; background: transparent; color: var(--navy); font: inherit; font-weight: 700; text-align: left; cursor: pointer; }
.card-reset { flex: none; min-width: 54px; padding: 5px 8px; border: 1px solid var(--teal-deep); border-radius: 9px; background: #fff; color: var(--teal-deep); font: inherit; font-size: .7rem; font-weight: 800; cursor: pointer; }
.card-reset:hover { background: var(--soft-bg); }
.card-reset:focus-visible { outline: 3px solid rgba(15,159,122,.25); outline-offset: 2px; }
.collapse-chevron { position: relative; flex: none; width: 30px; height: 30px; border: 1px solid var(--line); border-radius: 50%; background: var(--surface-alt); box-shadow: 0 1px 3px rgba(16,35,63,.08); transition: transform .2s ease, border-color .2s ease, background .2s ease, box-shadow .2s ease; }
.collapse-chevron::before { content: ""; position: absolute; left: 50%; top: 47%; width: 7px; height: 7px; border-right: 2px solid var(--navy); border-bottom: 2px solid var(--navy); transform: translate(-50%, -65%) rotate(45deg); }
.card-collapse-toggle:hover .collapse-chevron { border-color: var(--teal); background: var(--soft-bg); box-shadow: 0 3px 8px rgba(10,107,82,.16); }
.card-collapse-toggle:focus-visible { outline: 3px solid rgba(15,159,122,.25); outline-offset: 3px; border-radius: 6px; }
.card-collapse-toggle[aria-expanded="false"] .collapse-chevron { transform: rotate(-90deg); }
.card-heading { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.start-here { display: inline-flex; align-items: center; padding: 2px 7px; border-radius: 999px; background: var(--teal-deep); color: #fff; font-size: .65rem; font-weight: 800; white-space: nowrap; transition: opacity .18s ease, transform .18s ease; }
.salary-control:not([data-start="true"]) .start-here { opacity: 0; transform: scale(.85); pointer-events: none; }
.control-panel .card-collapse-toggle { min-height: 38px; padding: 5px 9px; border-radius: 9px; background: var(--teal-deep); color: #fff; box-shadow: 0 4px 12px rgba(10,107,82,.18); transition: transform .18s ease, background .18s ease, box-shadow .18s ease; }
.control-panel .card-collapse-toggle:hover { transform: translateY(-1px); background: #086047; box-shadow: 0 6px 15px rgba(10,107,82,.26); }
.control-panel .card-collapse-toggle .collapse-chevron { border-color: rgba(255,255,255,.55); background: rgba(255,255,255,.12); box-shadow: none; }
.control-panel .card-collapse-toggle .collapse-chevron::before { border-color: #fff; }
.control-panel .card-collapse-toggle:hover .collapse-chevron { border-color: #fff; background: rgba(255,255,255,.18); box-shadow: none; }
.control-panel .start-here { background: #fff; color: var(--teal-deep); }
.collapsible-card-content { margin-top: 6px; }
.collapsible-card-content[hidden] { display: none; }
.salary-card-content { display: block; }
.deductions-card-content, .results-card-content { display: flex; flex-direction: column; gap: 7px; }
.salary-number-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.salary-number-row .prefix { font-size: 1.6rem; color: var(--muted); }
.salary-number-row .suffix { color: var(--muted); font-size: 0.95rem; }
.salary-number-row input {
  font-size: 1.7rem; font-variant-numeric: tabular-nums; width: 100%; max-width: 220px;
  padding: 8px 12px; border: 1px solid var(--line); border-radius: 10px; color: var(--navy); font-weight: 700; background: var(--surface);
}
.salary-control input#income-range { width: 100%; }
.field-error { flex-basis: 100%; margin: 4px 0 8px; color: var(--danger-text); font-size: 0.8rem; font-weight: 650; }
.field-error[hidden] { display: none; }
input[aria-invalid="true"] { border-color: var(--danger-border) !important; box-shadow: 0 0 0 1px var(--danger-border); }

/* Tax-free allowance gauge — a read-only indicator that tracks the salary slider */
.pa-gauge { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line); }
.pa-gauge-label { display: flex; justify-content: space-between; align-items: baseline; font-size: 0.82rem; color: var(--muted); margin-bottom: 4px; }
.pa-gauge-label output { font-variant-numeric: tabular-nums; color: var(--navy); font-weight: 700; font-size: 0.95rem; }
.pa-slider { width: 100%; pointer-events: none; background: var(--track); }
.pa-slider::-webkit-slider-thumb { background: #6b4fa0; border: 3px solid #fff; cursor: default; }
.pa-slider::-moz-range-thumb { background: #6b4fa0; border: 3px solid #fff; cursor: default; }
.allowance-option { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; padding: 7px 9px; border: 1px solid var(--line); border-radius: 9px; }
.allowance-explainer { flex-basis: 100%; }
.tax-region-option { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 10px; margin-top: 8px; padding: 7px 9px; border: 1px solid var(--line); border-radius: 9px; color: var(--muted); font-size: 0.82rem; }
.tax-region-option select { min-width: 0; flex: 1 1 210px; padding: 5px 9px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--navy); font: inherit; font-weight: 600; }
.region-explainer { flex-basis: 100%; }
/* S3: read-only derived indicators (NI-free band, taxable salary after pension). A filled bar — not a
   slider — so it can't be mistaken for a control. */
.derived-gauge { margin-top: 8px; }
.derived-gauge[hidden] { display: none; }
.derived-gauge.derived-gauge-wide { flex-basis: 100%; }
.derived-gauge-label { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; font-size: 0.8rem; color: var(--muted); margin-bottom: 4px; }
.derived-gauge-value { font-variant-numeric: tabular-nums; color: var(--navy); font-weight: 700; font-size: 0.92rem; }
.derived-bar { height: 8px; border-radius: 999px; background: var(--track); overflow: hidden; }
.derived-bar-fill { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, #0d9488, #14b8a6); transition: width 0.15s ease; }
.taxable-salary-gauge .derived-bar-fill, [data-testid="taxable-salary-gauge"] .derived-bar-fill { background: linear-gradient(90deg, #2563eb, #4f83f0); }
.derived-gauge-note { display: block; margin-top: 4px; font-size: 0.72rem; color: var(--muted); }

/* Range sliders (teal thumb) */
input[type="range"] { -webkit-appearance: none; appearance: none; height: 6px; border-radius: 999px; background: var(--track-2); outline-offset: 3px; }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; border-radius: 50%; background: var(--teal); border: 3px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.25); cursor: pointer; }
input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--teal); border: 3px solid #fff; cursor: pointer; }
.zoom-x, .zoom-y { background: var(--track); height: 5px; }
.zoom-x::-webkit-slider-thumb, .zoom-y::-webkit-slider-thumb { width: 15px; height: 15px; background: var(--navy); }
input[type="range"]:focus-visible { outline: 2px solid var(--navy); }

/* Readouts */
.readouts { display: flex; flex-direction: column; gap: 10px; }

/* Results move into an explicit, roomy layer so the right control column stays short. */
.results-dialog { width: min(860px, calc(100vw - 32px)); max-height: min(88vh, 900px); padding: 0; border: 0; border-radius: 14px; color: var(--text); background: var(--surface); box-shadow: 0 24px 80px rgba(16,35,63,.28); }
.results-dialog::backdrop { background: rgba(16,35,63,.42); backdrop-filter: blur(2px); }
.results-dialog-shell { padding: 20px; overflow-y: auto; max-height: min(88vh, 900px); }
.results-dialog [hidden] { display: none !important; }
.results-dialog-header { position: sticky; top: -20px; z-index: 3; display: flex; justify-content: space-between; align-items: center; margin: -20px -20px 14px; padding: 16px 20px 12px; border-bottom: 1px solid var(--line); background: var(--surface); }
.results-dialog-header h2 { margin: 0; color: var(--navy); font-size: 1.35rem; }
.dialog-header-actions { display: flex; align-items: center; gap: 10px; }
.results-dialog-header .export-cta { min-height: 38px; padding: 6px 13px; }
.dialog-close { width: 38px; height: 38px; border: 1px solid var(--line); border-radius: 50%; background: var(--surface-alt); color: var(--navy); font-size: 1.55rem; line-height: 1; cursor: pointer; }
.gross-pay-result { display: grid; margin: 10px 4px 4px; border-bottom: 1px solid var(--line); color: var(--text); font-size: .85rem; }
.gross-pay-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 7px 4px; border-bottom: 1px solid var(--line); }
.gross-pay-row:last-child { border-bottom: 0; }
.gross-pay-result output { color: var(--navy); font-weight: 700; font-variant-numeric: tabular-nums; }

.export-dialog { width: min(620px, calc(100vw - 28px)); max-height: min(760px, 90vh); padding: 0; border: 0; border-radius: 16px; color: var(--text); box-shadow: 0 22px 70px rgba(9, 30, 56, .25); }
.export-dialog::backdrop { background: rgba(9, 30, 56, .42); }
.export-dialog-shell { max-height: min(760px, 90vh); padding: 22px; overflow: auto; }
.export-dialog-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.export-dialog-header h2 { margin: 0; color: var(--navy); font-size: 1.35rem; }
.export-dialog-header p { margin: 4px 0 0; color: var(--muted); }
.export-choice { display: flex; align-items: center; gap: 10px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 10px; font-weight: 650; cursor: pointer; }
.export-choice input { width: 18px; height: 18px; accent-color: var(--teal-deep); }

/* Audience simplification: retain the line-graph machinery, but offer the
   results summary and pay-allocation pie as the only ordinary user paths. */
.chart-view-toggle,
.export-choice-graph { display: none !important; }
.export-primary-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 18px 0; }
.export-primary-choices > .export-choice,
.export-primary-choices .export-choice-pie { min-height: 70px; }
.export-graph-choices { min-width: 0; margin: 0; padding: 0; border: 0; }
.export-primary-choices .export-option-grid { grid-template-columns: 1fr; }
.export-graph-choices legend { margin-bottom: 9px; color: var(--navy); font-weight: 750; }
.export-graph-choices [data-testid="export-graph-options"] { display: grid; gap: 18px; }
.export-option-group h3 { margin: 0; color: var(--navy); font-size: 1rem; }
.export-option-note { margin: 4px 0 9px; color: var(--muted); font-size: .82rem; line-height: 1.45; }
.export-option-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.export-option-group-extra { padding-top: 16px; border-top: 1px solid var(--line); }
/* Export dialog: drop the "Main illustrations" / "Extra" tiering; extras hidden into the DOM (2026-07-27, owner-directed) */
#export-main-heading,
.export-option-group-main .export-option-note { display: none; }
.export-option-group-extra { display: none; }
@media (max-width: 560px) {
  .export-primary-choices { grid-template-columns: 1fr; }
}

/* Experimental custom-tax droplet. Violet is deliberately outside the normal
   teal/navy action palette, while retaining the established card geometry. */
.custom-tax-entry-card { display: flex; align-items: center; gap: 7px; align-self: flex-end; width: min(360px, 100%); margin-top: auto; padding: 7px; border: 1px solid #d8c9f2; border-radius: 11px; background: #faf7ff; box-shadow: var(--shadow-sm); }
.custom-tax-entry { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; min-height: 46px; padding: 8px 10px; border: 0; border-radius: 9px; background: #6d3cc3; color: #fff; font: inherit; font-size: .82rem; font-weight: 800; white-space: nowrap; cursor: pointer; box-shadow: 0 5px 14px rgba(109,60,195,.2); }
.custom-tax-entry:hover { background: #5c2eae; }
.custom-tax-entry-kicker { padding: 3px 7px; border: 2px solid rgba(255,255,255,.9); border-radius: 999px; font-size: .68rem; }
.custom-tax-entry-help { flex: none; }
.custom-tax-controls { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--line); border-radius: 12px; background: #fff; box-shadow: var(--shadow-sm); }
.custom-tax-controls[hidden], .custom-tax-workspace[hidden] { display: none !important; }
.custom-back { width: 100%; min-height: 52px; padding: 10px 14px; border: 0; border-radius: 10px; background: #08745b; color: #fff; font: inherit; font-size: .9rem; font-weight: 800; text-align: left; cursor: pointer; box-shadow: 0 5px 14px rgba(8,116,91,.22); }
.custom-back:hover { background: #065f4b; }
.custom-step { overflow: hidden; border: 1px solid #e5dcf5; border-radius: 10px; background: #fff; }
.custom-step summary { display: flex; align-items: center; gap: 9px; padding: 10px 12px; background: #6d3cc3; color: #fff; font-size: .9rem; font-weight: 800; cursor: pointer; list-style: none; }
.custom-step summary::-webkit-details-marker { display: none; }
.custom-step summary .collapse-chevron { margin-left: 0; border-color: rgba(255,255,255,.55); background: rgba(255,255,255,.12); transform: none; }
.custom-step summary .collapse-chevron::before { border-color: #fff; }
.custom-step:not([open]) summary .collapse-chevron { transform: rotate(-90deg); }
.custom-step-reset { margin-left: auto; padding: 5px 8px; border: 1px solid rgba(255,255,255,.8); border-radius: 8px; background: #fff; color: #51279a; font: inherit; font-size: .7rem; font-weight: 800; cursor: pointer; }
.custom-step-content { display: grid; gap: 10px; padding: 11px; }
.custom-field { display: grid; gap: 5px; color: var(--text); font-size: .8rem; font-weight: 700; }
.custom-money-input { display: flex; align-items: center; gap: 7px; padding: 0 9px; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
.custom-money-input input { width: 100%; min-width: 0; padding: 8px 0; border: 0; background: transparent; font: inherit; font-weight: 700; }
.custom-income-range { width: 100%; accent-color: #6d3cc3; }
.custom-field select { padding: 8px 32px 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: #fff; font: inherit; }
.custom-control-group { display: grid; gap: 7px; margin: 0; padding: 10px; border: 1px solid #e5dcf5; border-radius: 9px; background: #faf7ff; }
.custom-control-group > legend { padding: 0 4px; color: #51279a; font-size: .8rem; font-weight: 800; }
.custom-control-group legend .help, .custom-nested-choice legend .help { margin-left: 4px; vertical-align: middle; }
.custom-control-group label, .custom-nested-choice label { display: flex; align-items: flex-start; gap: 7px; color: var(--text); font-size: .76rem; line-height: 1.35; }
.custom-option-row { display: flex; align-items: center; gap: 6px; }
.custom-option-row .help { flex: none; }
.custom-nested-choice { display: grid; gap: 6px; margin: 3px 0 0; padding: 9px; border: 1px dashed #bba6df; border-radius: 8px; }
.custom-nested-choice legend { padding: 0 4px; color: var(--muted); font-size: .72rem; font-weight: 750; }
.custom-band-editor { display: grid; gap: 7px; }
.custom-band-row { display: grid; grid-template-columns: 54px repeat(2, minmax(0, 1fr)); align-items: end; gap: 7px; padding: 8px; border: 1px solid #e5dcf5; border-radius: 9px; }
.custom-band-row strong { align-self: center; color: #51279a; font-size: .76rem; }
.custom-band-row label { display: grid; gap: 3px; color: var(--muted); font-size: .68rem; font-weight: 700; }
.custom-band-row input { width: 100%; min-width: 0; padding: 7px; border: 1px solid var(--line); border-radius: 7px; font: inherit; }
.custom-band-row .custom-money-input { min-height: 34px; }
.custom-band-row .custom-money-input input { padding: 7px 0; border: 0; }
.custom-band-final { align-self: center; padding: 8px; color: var(--muted); font-size: .74rem; }
.custom-error { margin: 0; padding: 8px; border-radius: 8px; background: var(--warn-bg); color: var(--warn-text); font-size: .76rem; }
.custom-tax-workspace { min-height: 100%; padding: 22px; }
.custom-tax-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.custom-tax-header p { margin: 0 0 3px; color: #6d3cc3; font-size: .72rem; font-weight: 850; letter-spacing: .08em; text-transform: uppercase; }
.custom-tax-header h1 { margin: 0; color: var(--navy); font-size: 1.1rem; }
.custom-pay-controls { display: flex; align-items: center; gap: 14px; }
.custom-result-period { display: flex; align-items: center; gap: 4px; margin-left: auto; padding: 4px 5px 4px 9px; border: 2px solid #6d3cc3; border-radius: 10px; color: var(--muted); font-size: .72rem; }
.custom-result-period button { width: 34px; height: 30px; padding: 0; border: 1px solid #dfe5eb; border-radius: 999px; background: #fff; color: var(--text); font: inherit; cursor: pointer; }
.custom-result-period button[aria-pressed="true"] { border-color: #6d3cc3; background: #6d3cc3; color: #fff; }
.custom-tax-result { display: grid; gap: 1px; min-width: 125px; color: var(--muted); font-size: .7rem; }
.custom-tax-result strong { color: var(--navy); font-size: 1rem; }
.custom-illustration-actions { margin-left: auto; display: inline-flex; align-items: center; gap: 7px; }
.custom-illustration-actions .btn-secondary { min-height: 52px; padding-inline: 12px; border: 2px solid #6d3cc3; border-radius: 9px; color: #51279a; font: inherit; font-size: .82rem; font-weight: 700; white-space: nowrap; cursor: pointer; }
.custom-band-summary { display: flex; flex-wrap: wrap; gap: 7px; min-height: 34px; margin: 12px 0 10px; }
.custom-band-chip { padding: 6px 9px; border: 1px solid #d8c9f2; border-radius: 8px; background: #fff; color: #51279a; font-size: .72rem; font-weight: 750; }
.custom-band-chip[data-active="true"] { background: #6d3cc3; color: #fff; }
.custom-graph-legend { display: flex; flex-wrap: wrap; gap: 16px; padding: 12px 14px 0; color: var(--muted); font-size: .74rem; font-weight: 700; }
.custom-graph-legend span { display: inline-flex; align-items: center; gap: 6px; }
.custom-legend-swatch { width: 24px; height: 4px; border-radius: 999px; }
.custom-legend-experiment { background: #6d3cc3; }
.custom-legend-current { background: #08745b; }
.custom-chart-wrap { min-height: 430px; margin-top: 54px; border: 1px solid var(--line); border-radius: 12px; background: #fff; }
.custom-tax-chart { display: block; width: 100%; height: auto; min-height: 430px; }
.custom-grid-line { stroke: #e4eaf0; stroke-width: 1; }
.custom-axis { stroke: #102544; stroke-width: 2; }
.custom-curve { fill: none; stroke: #6d3cc3; stroke-width: 4; stroke-linejoin: round; }
.custom-current-curve { fill: none; stroke: #08745b; stroke-width: 3; stroke-linejoin: round; stroke-dasharray: 9 6; }
.custom-marker-guide { stroke: #6d3cc3; stroke-width: 1.5; stroke-dasharray: 6 5; opacity: .8; }
.custom-marker-hit { fill: transparent; cursor: ew-resize; touch-action: none; }
.custom-marker-halo { fill: #eadffd; stroke: #6d3cc3; stroke-width: 1.5; cursor: ew-resize; transition: r 120ms ease, fill 120ms ease; }
.custom-marker { fill: #6d3cc3; stroke: #fff; stroke-width: 3; cursor: ew-resize; pointer-events: none; }
.custom-marker-halo:hover, .custom-marker-dragging .custom-marker-halo { r: 13px; fill: #d9c6fa; }
.custom-marker-dragging, .custom-marker-dragging [data-custom-marker-handle] { cursor: ew-resize; }
.custom-axis-label, .custom-tick { fill: #5b6670; font-size: 12px; }
.custom-marker-label { fill: #102544; font-size: 13px; font-weight: 800; paint-order: stroke; stroke: #fff; stroke-width: 4px; }
.custom-current-marker-label { fill: #08745b; font-size: 11px; font-weight: 750; paint-order: stroke; stroke: #fff; stroke-width: 4px; }
.custom-chart-note { margin: 8px 0 0; color: var(--muted); font-size: .78rem; }
.custom-tax-workspace:fullscreen {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  max-width: none;
  min-height: 0;
  padding: 18px;
  overflow: hidden;
  background: var(--surface);
}
.custom-tax-workspace:fullscreen .custom-illustration-actions,
.custom-tax-workspace:fullscreen .custom-band-summary { display: none; }
.custom-tax-workspace:fullscreen .custom-tax-header { flex: 0 0 auto; justify-content: flex-start; }
.custom-tax-workspace:fullscreen .custom-pay-controls { margin: 0; }
.custom-tax-workspace:fullscreen .custom-chart-wrap {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  margin-top: 12px;
  overflow: hidden;
}
.custom-tax-workspace:fullscreen .custom-tax-chart {
  flex: 1 1 auto;
  min-height: 0;
  height: calc(100vh - 112px);
}
body[data-custom-tax="true"] .salary-control,
body[data-custom-tax="true"] .deductions-control,
body[data-custom-tax="true"] .step-card,
body[data-custom-tax="true"] .custom-tax-entry-card { display: none !important; }
@media (max-width: 900px) {
  .custom-tax-workspace { padding: 14px; }
  .custom-tax-header { flex-wrap: wrap; }
  .custom-pay-controls { flex-wrap: wrap; }
  .custom-illustration-actions { margin-left: 0; }
  .custom-chart-wrap, .custom-tax-chart { min-height: 320px; }
}
.graph-topbar .bands-and-view-toggle { display: none !important; }
.export-actions { position: sticky; bottom: -22px; display: flex; justify-content: flex-end; gap: 10px; margin: 0 -22px -22px; padding: 14px 22px 22px; border-top: 1px solid var(--line); background: var(--surface); }
.export-pdf-help { align-self: center; max-width: 310px; margin: 0 auto 0 0; color: var(--muted); font-size: 12px; line-height: 1.35; }
.comparison-intro { margin: 0 0 10px; color: var(--muted); }
.comparison-picker { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.comparison-choice { display: inline-flex; align-items: center; gap: 7px; padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-alt); font-size: .82rem; cursor: pointer; }
.comparison-actions { display: flex; gap: 8px; justify-content: flex-end; margin: -4px 0 14px; }
.comparison-chart-controls { display: flex; align-items: end; justify-content: space-between; margin: 0 0 8px; }
.comparison-chart-controls label { display: grid; gap: 5px; color: var(--muted); font-size: .78rem; font-weight: 700; }
.comparison-chart-controls select { min-width: min(360px, 72vw); padding: 9px 34px 9px 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--navy); font: inherit; }
.comparison-chart { margin-bottom: 16px; padding: 8px; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.comparison-chart>svg { display: block; width: 100%; height: auto; max-height: 620px; }
.comparison-chart-note { margin: 2px 6px 6px; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.scenario-crosshair { stroke-width: 1.5; stroke-dasharray: 5 4; opacity: .8; }
.scenario-crosshair-0 { stroke: #2563eb; }
.scenario-crosshair-1 { stroke: #d97706; }
.scenario-crosshair-2 { stroke: #9333ea; }
.scenario-point-label { fill: var(--navy); paint-order: stroke; stroke: #fff; stroke-width: 4px; stroke-linejoin: round; font-size: 11px; font-weight: 800; }
.comparison-chart-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 18px; margin: 4px 0 2px; color: var(--muted); font-size: .76rem; }
.comparison-chart-legend span { display: inline-flex; align-items: center; gap: 6px; }
.comparison-chart-legend i { width: 22px; height: 3px; border-radius: 2px; background: #2563eb; }
.comparison-chart-legend span:nth-child(2) i { background: #d97706; }
.comparison-chart-legend span:nth-child(3) i { background: #9333ea; }
.scenario-name-input { width: 92px; padding: 3px 5px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--navy); font: inherit; font-weight: 700; }
.scenario-name-input:focus { border-color: var(--line); background: var(--surface); }
.scenario-remove { margin-left: 4px; padding: 3px 7px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--muted); font: inherit; font-size: .7rem; cursor: pointer; }
.comparison-table-wrap { overflow-x: auto; }
.comparison-table { width: 100%; border-collapse: collapse; font-size: .84rem; }
.comparison-table th, .comparison-table td { padding: 9px 10px; border-bottom: 1px solid var(--line); text-align: right; white-space: nowrap; }
.comparison-table th:first-child, .comparison-table td:first-child { position: sticky; left: 0; text-align: left; background: var(--surface); }
.comparison-table thead th { color: var(--navy); background: var(--surface-alt); }
.comparison-conclusions { display: grid; gap: 8px; margin-top: 14px; }
.comparison-conclusion { margin: 0; padding: 12px 14px; border-left: 4px solid var(--teal); border-radius: 0 8px 8px 0; background: var(--soft-bg); line-height: 1.45; }
.comparison-empty { padding: 18px; border: 1px dashed var(--line); border-radius: 8px; color: var(--muted); text-align: center; }
.readout-primary { background: var(--navy); color: #fff; border-radius: 12px; padding: 14px 18px; }
.readout-primary .readout-label { color: #cfe0f0; font-size: 0.86rem; }
.readout-primary .readout-value { display: block; font-size: 2rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; margin: 2px 0; }
.readout-primary .readout-sub { color: #a9c2da; font-size: 0.78rem; }
.readout-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.readout-label { display: block; font-size: 0.84rem; color: var(--muted); }
.readout-hint { color: var(--muted); font-size: 0.74rem; }
.plain-summary { margin: 2px 0 0; padding: 8px 10px; border-left: 3px solid var(--teal); border-radius: 0 6px 6px 0; background: var(--soft-bg); color: var(--text); font-size: 0.8rem; line-height: 1.45; }
.plain-summary[hidden] { display: none; }
.readout-value-sm { display: block; font-size: 1.25rem; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
/* pptx S1: "(after all deductions)" must be readable, not a faint hint. */
.readout-caveat { font-size: 0.78rem; font-weight: 600; color: #dbe8f5; }
/* pptx S1: money value + its share of gross, e.g. £3,293 (66% of gross). */
.readout-figure { display: flex; align-items: baseline; gap: 8px; margin: 2px 0; }
.readout-primary .value-pct { color: #a9c2da; font-size: 0.82rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.value-pct { color: var(--muted); font-size: 0.76rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* pptx S1/S4: the two marginal readouts share one row. */
.marginal-pair .readout-value-sm { font-size: 1.1rem; }
/* pptx S3: always-visible per-selection explainer under a control. */
.control-explainer { margin: 7px 0 0; font-size: 0.78rem; line-height: 1.4; color: var(--text); background: var(--soft-bg); border-left: 3px solid var(--teal); border-radius: 0 6px 6px 0; padding: 6px 9px; }
.control-explainer[hidden] { display: none; }
.readout.inspectable:hover, .readout-primary.inspectable:hover { outline: 2px solid var(--teal); outline-offset: 2px; border-radius: 8px; }

/* Bands */
.bands-title { font-size: 1rem; margin: 0 0 8px; color: var(--navy); }
.band-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.band-chip { display: flex; align-items: center; gap: 10px; padding: 5px 9px; border-radius: 8px; font-size: 0.9rem; color: var(--text); }
.band-chip[data-current="true"] { background: var(--band-current-bg); box-shadow: inset 3px 0 0 var(--teal); font-weight: 600; }
.band-chip strong { color: var(--navy); font-variant-numeric: tabular-nums; margin-right: 2px; }
.band-chip .band-range { color: var(--muted); font-size: 0.78rem; margin-left: auto; font-variant-numeric: tabular-nums; }
.band-swatch { width: 11px; height: 11px; border-radius: 3px; flex: none; background: var(--muted); }
.band-swatch[data-rate="0"] { background: #9aa7b2; }
.band-swatch[data-rate="20"] { background: #0f9f7a; }
.band-swatch[data-rate="19"] { background: #3b82a0; }
.band-swatch[data-rate="21"] { background: #6b8e23; }
.band-swatch[data-rate="40"] { background: #b7791f; }
.band-swatch[data-rate="42"] { background: #b7791f; }
.band-swatch[data-rate="45"] { background: #b42318; }
.band-swatch[data-rate="48"] { background: #7f1d1d; }
.band-swatch[data-rate="60"] { background: #6b4fa0; }

.band-chip .band-name { display: flex; align-items: baseline; gap: 4px; }
.band-taper-note { list-style: none; font-size: 0.78rem; color: #6b4fa0; padding: 0 6px 4px 30px; line-height: 1.3; }

/* ── Bands/taper simplification (2026-07-24, owner-directed) — HIDE only ───────
   Engine/maths untouched. The renderer still emits every band chip, range, the
   taper zone/labels and the "ranges changed" note with correct values; they are
   only visually hidden. Reversible: delete this block. See HIDDEN-UI-LOG.md.
     - show only the CURRENT tax band (the chip the salary is in), no other bands;
     - drop the £ range sub-text on the chip;
     - remove the allowance-taper shaded zone + "Adjusted income/Equivalent gross
       salary" labels + their help "?";
     - remove the "tax band ranges have changed…" note. */
.bands-horizontal .band-chip:not([data-current="true"]) { display: none; }
.band-range { display: none; }
.band-taper-note { display: none; }
.taper-zone,
.taper-label,
.taper-boundary-label,
.taper-adjustment-help { display: none; }
/* Single current-band chip: compact, FIXED size (no drift when band/jurisdiction changes,
   e.g. Scotland), left-aligned, no coloured swatch, no highlight (reads as a plain info
   label, not a clickable/selected control). Extra `.bands-and-view-toggle` ancestor raises
   specificity so it wins over the multi-band grid + highlight rules regardless of order.
   Appearance-only. */
.bands-and-view-toggle .bands-horizontal .band-swatch { display: none; }
.bands-and-view-toggle .bands-horizontal .band-legend { display: block; }
.bands-and-view-toggle .bands-horizontal .band-chip[data-current="true"] {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  width: 15rem;
  min-height: 0;
  padding: 7px 12px;
  background: none;
  box-shadow: none;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-weight: 400;
}
.bands-and-view-toggle .bands-horizontal .band-chip[data-current="true"] .band-name { white-space: nowrap; }

/* ── "Chart shows" metric picker simplification (2026-07-24, owner-directed) — HIDE only ──
   Show only the "Take Home Pay" (netPay) option; the other 10 metric options stay in the DOM
   (display:none, NOT disabled/removed) so every code path — and the verify harness setSelect()
   for takeHome / marginalRates / etc. — still works. To restore: delete this rule.
   The picker is resized to fit the short "Take Home Pay" label instead of stretching. */
/* "Chart shows" is now a static, non-clickable caption (2026-07-24, owner-directed): the <select>
   control itself is hidden (kept in the DOM → harness setSelect() and the netPay default still work),
   and a plain "Take Home Pay" value is shown beside the label. Restore: delete these rules + the
   static <span>, and drop the `option:not(...)`/width rules back in if the full picker is wanted again. */
.y-metric { display: none; }
.y-metric-static { font-weight: 700; color: var(--navy); }
/* …and as of 2026-07-30 the whole caption row is hidden too. With one selectable metric it was a dead
   control occupying 211px of the prime left slot — the open item recorded in HIDDEN-UI-LOG §E and
   ReadMe open task 5 — and that width is exactly what the tax-band readout needed to sit on the top
   row. Nothing is lost on screen: the Y-axis title already names the plotted metric. The <select> and
   its options stay in the DOM, so every metric code path and the harness setSelect() still work.
   Restore: delete this one rule. */
.metric-view-row { display: none; }

/* Steps 3 & 4 in the left control column, under Step 2 (2026-07-24, owner-directed).
   Each is a <section> card (same white-card treatment as Steps 1 & 2 via `.control-panel > section`),
   and the button is restyled to be IDENTICAL to the Step 1/2 green header bar (`.card-collapse-toggle`):
   one line, "Step N" pill + title left-aligned, no Reset, no chevron. JS unchanged (binds by data-testid). */
.step-card .results-summary-cta,
.step-card .export-cta {
  width: 100%; box-sizing: border-box;
  display: flex; flex-direction: row; align-items: center; justify-content: flex-start; gap: 7px;
  min-height: 38px; min-width: 0; padding: 5px 9px; border: 0; border-radius: 9px;
  background: var(--teal-deep); color: #fff; box-shadow: 0 4px 12px rgba(10,107,82,.18);
  font: inherit; font-weight: 700; text-align: left;
}
.step-card .step-title {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.45;
}
.step-card .results-summary-cta:hover,
.step-card .export-cta:hover { transform: translateY(-1px); background: #086047; box-shadow: 0 6px 15px rgba(10,107,82,.26); }
/* keep in the DOM (hint value still updates; export icon still there) but hide for single-line uniformity */
.step-card .results-summary-hint,
.step-card .export-icon { display: none; }

/* ── Header: one top row of SEPARATE, self-contained groups (2026-07-30, owner-directed) ────────
   Previously the groups were divided only by a hairline `border-left`. Change D1 darkened that line
   because the row still "seemed all together / blurred", which was treating the symptom: a divider
   says "a boundary passes here", it does not say "these are four distinct objects".
   So each group now carries its OWN hairline container — border, radius, matching height — and the
   dividers are gone. Separation comes from shape, which is what actually reads as separate, and it
   degrades gracefully when the row wraps (a wrapped divider divides nothing).
   Controls keep their pointer affordances; the tax-band READOUT below deliberately gets none. */
.graph-topbar {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 8px;
}
.graph-controls-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  min-width: 0;
}
.graph-actions {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
}
/* Two deliberate omissions from this list:
   • .chart-view-toggle already carries its own 2px teal box — the most distinct shape in the row.
     Adding the generic hairline container would flatten that and fight its grid layout; it only
     borrows the shared 40px height so the row aligns.
   • .metric-view-row is hidden (see the dead-caption rule further down). Listing it here would give
     it `display:flex` at 2-class specificity and silently beat that 1-class `display:none`. */
.graph-topbar .period-toggle {
  flex: 0 0 auto;
  display: flex; align-items: center;
  min-height: 52px; padding: 3px 10px;
  border: 2px solid var(--teal-deep); border-radius: 9px;
  background: var(--surface);
}
.metric-view-row .y-metric-label { width: auto; }
.graph-utilities { margin-left: auto; align-items: center; }
.graph-topbar .period-toggle label { padding: 4px 8px; }

/* Tax band is a bare readout beneath the period control. It deliberately has no container shape,
   fill, hover treatment or pointer cursor, so only its trailing help icon reads as interactive. */
.graph-topbar .bands-and-view-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: default;
  transform: translateX(10px);
}
.graph-topbar .bands-and-view-toggle .bands-section.bands-horizontal {
  display: flex; align-items: center; gap: 8px; margin: 0; min-width: 0;
}
.graph-topbar .bands-and-view-toggle .bands-title {
  margin: 0; flex: 0 0 auto;
  color: var(--muted); font-size: .84rem; font-weight: 650; white-space: nowrap;
}
/* Only the CURRENT chip renders here (the A4 simplification), so this group is content-sized. The
   mobile rule further down gives .band-legend `min-width: 680px` so the full four-chip strip can
   scroll horizontally — correct where the strip is a block in its own column, but in this header it
   would force the whole row to 680px and overflow a 390px viewport by ~339px. Neutralise the floor
   here (a later, more specific rule) rather than weakening the mobile strip rule others depend on. */
.graph-topbar .bands-and-view-toggle,
.graph-topbar .bands-and-view-toggle .bands-section,
.graph-topbar .bands-and-view-toggle .band-legend { min-width: 0; }
.graph-topbar .bands-and-view-toggle .band-legend { min-height: 0; width: auto; }
.graph-topbar .bands-and-view-toggle .bands-section { overflow: visible; }
/* The container already provides the shape, so the chip drops its own border/box and is content-sized. */
.graph-topbar .bands-and-view-toggle .band-chip[data-current="true"] {
  width: auto; min-height: 0; padding: 0; border: 0; background: none; box-shadow: none;
  font-size: .84rem; white-space: nowrap;
}
/* the empty band-context <p> (role=status) is `hidden` in markup but an earlier rule forces
   display:block, reserving a ~44px row — collapse it here too (kept in the DOM, just not shown). */
.graph-topbar .bands-and-view-toggle .band-context { display: none; }
/* view toggle: compact horizontal segmented control (moved out of the plot in Stage 2). It keeps its own
   teal box rather than the shared hairline container — it is the one header item that is a live mode
   switch, and looking different from the rest is correct. It only borrows the shared 40px height so the
   row still aligns. */
.chart-view-toggle {
  position: static; transform: none; top: auto; right: auto; z-index: auto;
  width: 230px; height: 52px; min-height: 52px; grid-template-rows: none; grid-template-columns: 1fr 1fr;
  border-width: 3px;
  gap: 4px; box-shadow: none;
}
.illustration-actions {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.illustration-actions .btn-secondary {
  min-height: 52px;
  padding-inline: 12px;
  border: 2px solid var(--teal-deep);
  color: var(--teal-deep);
  white-space: nowrap;
}
.illustration-download::before {
  content: "↓";
  margin-right: 5px;
  font-size: 1rem;
  font-weight: 900;
}
.illustration-fullscreen::before {
  content: "⛶";
  margin-right: 5px;
  font-size: 1rem;
}
.graph-utilities { grid-column: 1 / -1; width: 100%; margin-left: 0; }
.chart-view-toggle:hover { transform: none; box-shadow: 0 5px 16px rgba(10,107,82,.16); }
.chart-view-option { min-height: 30px; padding: 3px 10px; }

/* Fullscreen deliberately removes every result/control except the illustration and the two controls
   needed to read it: period and illustration type. Escape returns to the complete simulator. */
.graph-panel:fullscreen {
  width: 100vw;
  height: 100vh;
  max-width: none;
  min-height: 0;
  margin: 0;
  padding: 18px;
  border: 0;
  border-radius: 0;
  background: var(--surface);
}
.graph-panel:fullscreen .graph-topbar {
  display: flex;
  flex: 0 0 auto;
  justify-content: flex-start;
  margin: 0;
}
.graph-panel:fullscreen .metric-view-row,
.graph-panel:fullscreen .bands-and-view-toggle,
.graph-panel:fullscreen .illustration-actions,
.graph-panel:fullscreen .scenario-tools,
.graph-panel:fullscreen .graph-utilities {
  display: none;
}
.graph-panel:fullscreen .period-toggle { order: 0; }
.graph-panel:fullscreen .chart-view-toggle { order: 1; }
.graph-panel:fullscreen .chart-grid {
  flex: 1 1 auto;
  min-height: 0;
}
.graph-panel:fullscreen .chart-wrap { overflow: hidden; }

/* ── Read-only Step-2 indicators hidden (2026-07-24, owner-directed) — HIDE only ──

/* ── Read-only Step-2 indicators hidden (2026-07-24, owner-directed) — HIDE only ──
   Both gauges still render into the DOM with correct engine values (markup + testids intact, so the
   unit assertions and any textContent reads keep passing); they're just not shown. Restore: delete. */
.pa-gauge { display: none; }                                   /* "Income-tax-free allowance" + slider */
.derived-gauge { display: none; }                              /* "Pay used to work out income tax" gauge */

/* Income tax bands as a compact HORIZONTAL strip above the graph (moved off the right column so it no
   longer needs to scroll). Same chips + highlight logic, laid along the salary progression. */
/* The title and chips share the first row; the statutory/scenario distinction gets a dedicated second
   row so it can never be squeezed, clipped, or mistaken for another chip. */
.bands-horizontal { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; margin: 0 0 10px; }
.bands-horizontal .bands-title { font-size: 0.82rem; margin: 0; white-space: nowrap; color: var(--muted); }
/* Twelve columns allow four equal statutory cards on row one and three equal cards on row two.
   Both rows are permanently reserved, so changing jurisdiction never moves the graph. */
.bands-horizontal .band-legend { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(64px, auto)) 20px; gap: 6px 14px; align-items: stretch; }
.bands-horizontal .band-chip:nth-child(-n+4) { grid-column: span 3; grid-row: 1; }
.bands-horizontal .band-chip:nth-child(n+5):not(.band-taper-note) { grid-column: span 4; grid-row: 2; }
.band-context { flex: 0 0 auto; order: 3; width: min(760px, 100%); min-block-size: 3.8em; margin: 5px auto 0; padding: 8px 12px; border-left: 3px solid var(--teal); border-radius: 0 7px 7px 0; background: var(--soft-bg); color: var(--text); font-size: 0.72rem; line-height: 1.4; text-align: left; }
.band-context[hidden] { display: block; visibility: hidden; }
.taper-boundary-label { fill: #6b4fa0; font-size: 11px; font-weight: 700; font-family: var(--sans); opacity: 0.85; }
/* Content-sized (flex: 0 0 auto) so each box hugs its own text tightly — the space lives between boxes,
   not inside them. Tight padding + row-gap keep the label/range pair compact. */
.bands-horizontal .band-chip { min-width: 0; min-height: 64px; display: inline-grid; grid-template-columns: auto minmax(0, auto); grid-template-rows: auto auto; justify-content: center; column-gap: 8px; row-gap: 0; align-items: center; padding: 4px 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 0.84rem; }
.bands-horizontal .band-swatch { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
.bands-horizontal .band-name { grid-column: 2; grid-row: 1; }
.bands-horizontal .band-range { grid-column: 2; grid-row: 2; margin: 0 !important; font-size: 0.72rem; }
.bands-horizontal .band-chip[data-current="true"] { background: var(--band-current-bg); box-shadow: inset 0 0 0 1.5px var(--teal); font-weight: 600; }
/* The taper note permanently reserves its own line, so crossing the threshold changes only its visibility
   and never moves the chips or graph. */
.bands-horizontal .band-taper-note { grid-column: 1 / -1; grid-row: 3; width: 100%; margin: 5px 0 0; padding: 0 2px; list-style: none; font-size: 0.74rem; line-height: 1.35; }
.bands-horizontal .band-taper-note { visibility: hidden; }
.bands-horizontal .band-taper-note[data-show="true"] { visibility: visible; }

/* allowance-taper zone on the curve — a shaded region, not a band */
.taper-zone { fill: #6b4fa0; opacity: 0.09; }
.taper-label { fill: #6b4fa0; font-size: 11px; font-weight: 700; font-family: var(--sans); opacity: 0.85; }
.taper-adjustment-help { position: absolute; z-index: 2; transform: translate(-50%, -50%); }
.taper-adjustment-help[hidden] { display: none; }
/* D4/D5: pension-clamped region — the engine capped the contribution here (amber tint + label). */
.clamp-zone { fill: var(--warn-text); opacity: 0.09; }
.clamp-label { fill: var(--warn-text); font-size: 11px; font-weight: 700; font-family: var(--sans); opacity: 0.8; }
.relief-transition-zone { fill: var(--teal); opacity: 0.08; }
.relief-transition-label { fill: var(--teal-deep); font-size: 11px; font-weight: 700; font-family: var(--sans); opacity: 0.9; }

/* ── CP-UI deduction surface (Phase D) — same panel/token grammar as the rest of the control column ── */
.deductions-control { display: flex; flex-direction: column; }
.deductions-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 0.95rem; margin: 0 0 2px; color: var(--navy); }
.deductions-status { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--warn-text); background: var(--warn-bg); border: 1px solid var(--warn-border); border-radius: 999px; padding: 2px 8px; }
.deduction-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 9px 10px 9px 45px; border: 1px solid #d4dde4; border-radius: 10px; background: var(--surface-alt); box-shadow: 0 1px 2px rgba(16,35,63,.04); font-size: 0.85rem; color: var(--text); }
.deduction-step { position: absolute; top: 9px; left: 10px; display: inline-flex; width: 25px; height: 25px; align-items: center; justify-content: center; border-radius: 50%; color: #fff; background: var(--navy); font-size: .76rem; font-weight: 800; }
.deduction-row > .deduction-step + label { color: var(--muted); }
/* min-height 24px so the label (the pointer target that toggles the checkbox) meets WCAG 2.5.8 target size
   (CUB-TOK-05); the text line-height alone was ~20px. */
.switch-label { display: inline-flex; align-items: center; gap: 6px; color: var(--text); cursor: pointer; min-height: 24px; }
.switch-label.inline { margin-left: 4px; }
/* This chrome (padding/border/box look) is for the NUMBER + SELECT inputs. Exclude the range slider:
   padding on a range input insets its track, so the thumb would stop ~10px short of the visual end. */
.deduction-row select, .pension-inputs select, .pension-field input:not([type="range"]) { font-size: 0.85rem; padding: 5px 9px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--navy); font-weight: 600; }
.deduction-hint { font-size: 0.74rem; color: var(--muted); font-style: italic; }
.pension-group { flex-direction: column; align-items: stretch; }
.fix-taxable-action { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.fix-taxable-button { padding: 6px 9px; border: 1px solid var(--navy); border-radius: 7px; background: var(--surface); color: var(--navy); font: inherit; font-size: .72rem; font-weight: 700; cursor: pointer; }
.fix-taxable-button[aria-pressed="true"] { color: #fff; background: var(--teal-deep); border-color: var(--teal-deep); }
.fix-taxable-button:disabled { opacity: .5; cursor: not-allowed; }
.fix-taxable-status { display: block; margin-top: 5px; color: var(--muted); font-size: .7rem; line-height: 1.35; }

/* ── Surface simplification (2026-07-24, owner-directed) ──────────────────────
   These UI surfaces are HIDDEN from the frontend only. All DOM, JS wiring and
   engine capability are retained (cpui-deductions tests still prove capability).
   Reversible: delete this block to restore the surfaces.
     - Fix-taxable pension helper (motivated users reach the same result manually)
     - Save / Compare scenarios (chips + "Show both curves")
     - Marginal-rate readouts inside the Results dialog
   KEPT ON PURPOSE: the combined-marginal CURVE + its INV-D2 verification anchor
   (still written live to the DOM), and the general "Reset zoom" axis utility. */
.fix-taxable-action,
.fix-taxable-status,
.scenario-tools,
.scenario-chips,
[data-testid="toggle-scenario-curves"],
.marginal-pair { display: none; }

.pension-inputs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 6px; padding: 10px; background: var(--surface-alt); border: 1px solid var(--line); border-radius: 8px; }
.pension-inputs[hidden] { display: none; }
.pension-field { display: inline-flex; align-items: center; gap: 5px; font-size: 0.8rem; color: var(--muted); flex-wrap: wrap; }
/* Scalable pension slider: a real full-width range (not the number-input box styling), scaling to gross. */
/* Full-width scalable slider. Inherit the base input[type=range] styling (which renders the thumb FLUSH to
   both ends, like the salary slider); only add the layout it needs. The old override (padding:0 + re-declared
   appearance) left the thumb ~10px short of the right end at max — the salary slider, which doesn't override
   those, sits flush, so we match it. */
.pension-amount-slider { flex: 1 1 100%; width: 100%; min-width: 0; margin-top: 2px; }
.pension-slider-hint { flex-basis: 100%; font-size: 0.7rem; color: var(--muted); font-style: italic; }
.pension-warning { flex-basis: 100%; margin: 4px 0 0; font-size: 0.76rem; font-weight: 600; color: var(--warn-text); }
.pension-warning[hidden] { display: none; }
.pension-field[hidden] { display: none; }
.pension-field input { width: 92px; }
.readout-netpay { background: var(--teal-deep); }
.readout-netpay .readout-label { color: #eafaf4; }
.readout-netpay .readout-sub { color: #dcf4ec; }
.readout-netpay .value-pct, .readout-netpay .readout-caveat { color: #e7f1fb; } /* WCAG-AA on --teal-deep */
.breakdown-caption { margin: 2px 0 0; font-size: 0.78rem; font-weight: 700; color: var(--muted); }
.breakdown-caption .readout-period { font-weight: 600; }
.stream-breakdown { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.stream-row { display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 3px 8px; padding: 7px 4px; font-size: 0.85rem; }
/* Fine divider between each deduction row (matching the deductions control box above) — no zebra fill. */
.stream-row + .stream-row { border-top: 1px solid var(--line); }
/* The pension gross-contribution row is hidden when it equals the cash cost (salary sacrifice / net pay). */
.stream-row[hidden] { display: none; }
.stream-name { color: var(--text); }
.stream-plus { color: var(--muted); font-size: 0.74rem; }
.stream-plus[hidden] { display: none; }
.stream-figure { justify-self: end; display: inline-flex; align-items: baseline; gap: 6px; }
.stream-value { font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.stream-note { grid-column: 1 / -1; font-size: 0.72rem; color: var(--muted); }
.stream-note:empty { display: none; }
/* "off" streams are dimmed via a WCAG-AA muted colour (not opacity, which drops text below 4.5:1). The
   non-colour off-cue is the £0.00 value + the italic note — never colour/dim alone (CUB-A11Y-03). */
.stream-row[data-state="off"], .stream-row[data-state="off"] .stream-value { color: var(--muted); }
.stream-row[data-state="off"] .stream-note { font-style: italic; }
.result-disclosure { margin: 7px 0 0; padding: 7px 9px; border-left: 3px solid var(--warn-border); background: var(--warn-bg); color: var(--warn-text); font-size: 0.76rem; line-height: 1.4; }
.result-disclosure[hidden] { display: none; }
[data-testid="relief-at-source-disclosure"] { display: none !important; }
.status-candidate { color: var(--warn-text) !important; }

/* Persistent M1/M3/M4 trust surface: concise, visible, and outside the dense calculator controls. */
.provenance-stale { margin: 12px 0 0; padding: 9px 12px; border-left: 3px solid var(--warn-border); background: var(--warn-bg); color: var(--warn-text); font-size: 0.78rem; font-weight: 700; }
.provenance-stale[hidden] { display: none; }

/* Inspector */
.inspect-title { font-size: 0.9rem; margin: 0 0 5px; color: var(--navy); }
.inspect-reason { margin: 0; color: var(--text); font-size: 0.87rem; }

.inspectable:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* CUB-A11Y-02: an EXPLICIT, consistent keyboard focus indicator on the primary interactive controls.
   Do not rely on the UA default outline (varies by browser, can be stripped). More specific rules above
   (.help, input[type="range"], .period-toggle) keep their own indicators and win on specificity. */
input:focus-visible, select:focus-visible, button:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.fail-closed { margin: 10px 0 0; padding: 10px 14px; background: var(--danger-bg); border: 1px solid var(--danger-border); border-radius: 8px; color: var(--danger-text); font-weight: 600; }
.fail-closed[hidden] { display: none; }

/* Desktop control-column fit: recover vertical space from internal gaps rather than shrinking the graph,
   headings, inputs or pointer targets. The common default setup fits on a laptop-height viewport while
   longer conditional explanations can still scroll naturally. */
/* Preserve the established single-column flow; the left/right swap applies to the desktop grid only. */
@media (max-width: 900px) {
  /* Single column. Which panel leads depends on whether the user has started:
       • not engaged  → the graph panel holds the WELCOME copy, so it leads;
       • engaged      → it holds the CHART, and a calculator should read input-then-output,
                        so the salary and options lead and the chart follows.
     Driven off the existing `data-engaged` attribute (set in app.js), so no new hook and no
     `:has()`. Attribute selectors out-specify the base `.graph-panel { order: 2 }`. */
  .control-panel { order: 1; }
  .graph-panel[data-engaged="false"] { order: 0; }
  .graph-panel[data-engaged="true"] { order: 2; }
  /* Narrow viewport: never overlay the toggle on the plot/pie (fragile — the curve/circle geometry varies).
     Put it in a static controls row beneath the chart, and neutralise the hover transform so it cannot jump. */
  .chart-view-toggle { position: static; width: 132px; max-width: 92%; margin: 10px auto 2px; top: auto; left: auto; right: auto; transform: none; }
  .chart-view-toggle:hover { transform: none; }
}

@media (min-width: 900px) {
  .control-panel { gap: 8px; }
  .control-panel > section,
  .control-panel > aside { padding: 8px 14px; }
  .card-collapse-toggle { min-height: 32px; }
  .collapsible-card-content { margin-top: 3px; }
  .deductions-card-content,
  .results-card-content { gap: 5px; }

  .salary-number-row { margin-bottom: 5px; }
  .salary-number-row input { padding-block: 7px; }
  .pa-gauge { margin-top: 6px; padding-top: 6px; }
  .tax-region-option,
  .allowance-option { margin-top: 6px; padding-block: 5px; }

  .deduction-row { gap: 7px; padding: 7px 9px 7px 43px; }
  .deduction-step { top: 7px; left: 9px; }
  .control-explainer { margin-top: 4px; padding: 5px 8px; line-height: 1.32; }
  .pension-inputs { gap: 6px; margin-top: 4px; padding: 7px 9px; }
  .derived-gauge { margin-top: 5px; }
  .derived-gauge-note { margin-top: 3px; }
  .fix-taxable-action { margin-top: 6px; }
}

/* A short desktop viewport cannot contain the controls, bands, chart and legend in one fixed screen.
   Let that exceptional viewport scroll and retain a real chart row instead of collapsing it to 0px,
   which would make SVG content overflow underneath the legend/footer and block pointer interaction. */
@media (min-width: 901px) and (max-height: 800px) {
  #simulator-root { height: auto; min-height: 100vh; overflow: visible; }
  .layout { grid-template-rows: auto; }
  .graph-panel { min-height: 840px; }
}

/* CUB-A11Y-04 — screen-reader-only utility for the non-graphical data alternative (visually hidden, but
   in the accessibility tree + keyboard-focusable). Standard clip technique. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.sr-only:focus, .sr-only:focus-within { position: static; width: auto; height: auto; margin: 0; clip: auto; white-space: normal; }

/* CUB-A11Y-05 — reduced-motion: disable non-essential transitions/animations. The graph is redrawn to its
   final SVG state on every change (motion is never the proof of correctness), so it still updates fully. */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; scroll-behavior: auto !important; }
}

/* ── CUB-TOK-03 mobile first-screen (placed LAST so equal-specificity media rules win by source order) ──
   Keep the core workspace — graph + salary control + the net-pay headline — usable on the first mobile
   screen: order the headline result right after the salary control (before the tall deductions panel),
   and compact the graph so the figure isn't pushed below the fold. */
@media (max-width: 640px) {
  /* The explicit order rules that used to live here are deliberately GONE.
     They dated from when `.readouts` was a direct child of `.control-panel`, and read
     salary=1, readouts=2, deductions=3. Two things then changed underneath them:
       • `.readouts` moved inside the results <dialog>, so its rule became dead;
       • Steps 3 and 4 were moved into this column as `.step-card` (change C3) and were
         never given an order — so they defaulted to 0 and sorted ABOVE Step 1.
     Measured on a 375px viewport, the visible order really was Step 3 → 4 → 1 → 2.
     The DOM order is already Step 1 → 2 → 3 → 4, so the correct fix is to remove the
     partial ordering rather than add more of it. Any future card then simply sits where
     it is written. Do not reintroduce `order` here without ordering EVERY sibling. */
  /* Keep the complete threshold information on mobile. It scrolls horizontally rather than being hidden
     or compressed until the figures are unreadable. */
  .bands-section { display: block; overflow-x: auto; padding-bottom: 4px; }
  .bands-horizontal .band-legend { display: flex; width: max-content; min-width: 680px; flex-flow: row nowrap; gap: 8px; }
  .bands-horizontal .band-chip { flex: 0 0 auto; min-height: 0; }
  .bands-horizontal .band-taper-note { white-space: normal; min-width: min(680px, 100%); }
  .band-context { min-width: 680px; text-align: left; }
  /* The zoom sliders are a desktop nicety (the graph auto-fits); hide them on mobile. */
  .chart-grid { grid-template-columns: 1fr; }
  .yzoom-wrap, .xzoom-wrap, .corner { display: none; }
  .overlay-legend { grid-column: 1; }
  .chart-wrap { max-height: none; overflow-x: auto; overscroll-behavior-inline: contain; }
  #chart { width: 720px; min-width: 720px; height: auto; }
  /* min-width:0 lets the panel shrink below its content's min-content width (else the topbar's three-column
     min-content forces a horizontal page scroll); the topbar stacks so nothing imposes a wide floor. */
  .graph-panel { padding: 10px; gap: 6px; min-width: 0; }
  .graph-topbar { grid-template-columns: 1fr; justify-items: center; gap: 8px; }
  .graph-controls-left { align-items: center; }
  .graph-actions { justify-self: stretch; justify-content: flex-start; flex-wrap: nowrap; width: 100%; overflow-x: auto; padding-bottom: 2px; }
  .graph-actions > * { flex: none; }
  .graph-utilities { display: none; }
  .results-summary-cta { min-width: 205px; }
  .period-toggle { flex-wrap: wrap; justify-content: center; }
  .metric-view-row { flex-wrap: wrap; justify-content: center; }
  .btn-ghost { justify-self: center; }
  .graph-title { font-size: 0.9rem; }
  .export-option-grid { grid-template-columns: 1fr; }
  .export-actions { flex-direction: column; }
  .export-pdf-help { align-self: flex-start; max-width: none; }
  .export-actions button { width: 100%; }
  .results-dialog { width: 100vw; max-width: none; max-height: 92vh; margin: auto 0 0; border-radius: 14px 14px 0 0; }
  .results-dialog-shell { max-height: 92vh; padding: 16px; }
  .pa-gauge { margin-top: 2px; }
  .bands-title, .bands-horizontal .band-taper-note, .band-context, .band-context[hidden] { display: none; }
}
.trust-line {
  margin: 8px 50px 0;
  color: var(--muted);
  font-size: 12px;
  text-align: center;
}
@media (max-width: 900px) {
  .trust-line { margin-inline: 16px; }
}
