  /* Two greys carry the type hierarchy below --ink: --muted for secondary prose,
     --faint for the smallest labels. Both clear WCAG AA (4.5:1) against every
     surface they land on, which is why they sit closer together than a purely
     visual ramp would put them — the small type here is 10–12.5px, so none of it
     qualifies for the large-text exemption.
     --hairline and --edge split what used to be one token: --hairline stays a
     decorative rule (card borders, chart gridlines, table rules) with no contrast
     duty, while --edge bounds interactive controls and clears the 3:1 that WCAG
     1.4.11 requires of a UI component boundary. */
  :root {
    --paper:#E9EDF3; --surface:#FFFFFF; --surface-2:#F3F6FA;
    --ink:#14202E; --muted:#44586B; --faint:#5C6E80; --hairline:#D6DEE8; --edge:#748496;
    --brand:#3B4DA6; --brand-strong:#2C3B84; --brand-soft:#E6E9F7;
    --good:#0D6A4B; --warn:#8C6100; --danger:#B23B2E;
    --band-outer:#CBD2F0; --band-mid:#93A0E0; --band-line:#2C3B84;
    --shadow: 0 1px 2px rgba(20,32,46,.05), 0 6px 20px rgba(20,32,46,.06);
    --font-serif:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,"Times New Roman",serif;
    --font-sans:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --font-mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  }
  @media (prefers-color-scheme: dark) {
    :root {
      --paper:#0C131C; --surface:#131E2B; --surface-2:#18273A;
      --ink:#E7EDF4; --muted:#A6B6C6; --faint:#8B9CAD; --hairline:#243747; --edge:#647B92;
      --brand:#8E9BEE; --brand-strong:#AEB8F6; --brand-soft:#1E2E48;
      --good:#3FB488; --warn:#D6A23E; --danger:#E3695B;
      --band-outer:#2C3C61; --band-mid:#4A5DA0; --band-line:#AEB8F6;
      --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
    }
  }
  :root[data-theme="dark"] {
    --paper:#0C131C; --surface:#131E2B; --surface-2:#18273A;
    --ink:#E7EDF4; --muted:#A6B6C6; --faint:#8B9CAD; --hairline:#243747; --edge:#647B92;
    --brand:#8E9BEE; --brand-strong:#AEB8F6; --brand-soft:#1E2E48;
    --good:#3FB488; --warn:#D6A23E; --danger:#E3695B;
    --band-outer:#2C3C61; --band-mid:#4A5DA0; --band-line:#AEB8F6;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
  }
  :root[data-theme="light"] {
    --paper:#E9EDF3; --surface:#FFFFFF; --surface-2:#F3F6FA;
    --ink:#14202E; --muted:#44586B; --faint:#5C6E80; --hairline:#D6DEE8; --edge:#748496;
    --brand:#3B4DA6; --brand-strong:#2C3B84; --brand-soft:#E6E9F7;
    --good:#0D6A4B; --warn:#8C6100; --danger:#B23B2E;
    --band-outer:#CBD2F0; --band-mid:#93A0E0; --band-line:#2C3B84;
    --shadow: 0 1px 2px rgba(20,32,46,.05), 0 6px 20px rgba(20,32,46,.06);
  }

  * { box-sizing: border-box; }
  [hidden] { display: none !important; }
  body { margin: 0; background: var(--paper); color: var(--ink); font-family: var(--font-sans); line-height: 1.5; -webkit-font-smoothing: antialiased; }
  .wrap { max-width: 1180px; margin: 0 auto; padding: 32px 22px 80px; }

  /* Off-screen but still announced — for the live region and for label text that
     would be redundant on screen. Not `display:none`, which would mute it. */
  .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

  /* The controls column runs to ~40 focusable elements, so a keyboard user needs a
     way past it. Hidden until focused. */
  .skip-link { position: absolute; left: 8px; top: -60px; z-index: 50; padding: 10px 14px; background: var(--surface); color: var(--brand); border: 1px solid var(--edge); border-radius: 8px; font-size: 13px; font-weight: 600; text-decoration: none; box-shadow: var(--shadow); transition: top .12s; }
  .skip-link:focus { top: 8px; }

  /* One visible focus treatment for everything focusable. The UA default ring is
     unreliable against these custom surfaces, and `summary` carries custom markers. */
  :where(a, button, summary, [tabindex]):focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

  header.masthead { margin-bottom: 26px; }
  .masthead-top { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
  .eyebrow { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--brand); font-weight: 600; }
  h2.eyebrow { margin: 0; font-family: var(--font-sans); }
  h1 { font-family: var(--font-serif); font-weight: 600; letter-spacing: -.01em; font-size: clamp(28px, 4.4vw, 44px); line-height: 1.08; margin: 8px 0 10px; text-wrap: balance; }
  .lede { color: var(--muted); max-width: 62ch; font-size: 15.5px; margin: 0; }

  .layout { display: grid; grid-template-columns: 340px 1fr; gap: 22px; align-items: start; }
  @media (max-width: 880px) { .layout { grid-template-columns: 1fr; } }
  /* Grid and flex items default to min-width:auto, which means they refuse to
     shrink below their content — so an overflow-x scroller *inside* one can't
     contain anything, and a wide data table drags the whole page into horizontal
     scroll on a phone. These two zeroes are what make .scroll-x actually work. */
  .layout > * { min-width: 0; }

  .card { background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px; box-shadow: var(--shadow); }
  .controls { position: sticky; top: 18px; padding: 20px 20px 22px; max-height: calc(100vh - 36px); overflow-y: auto; }
  @media (max-width: 880px) { .controls { position: static; max-height: none; } }

  .card-title { font-family: var(--font-serif); font-size: 18px; font-weight: 600; margin: 0 0 2px; }
  .card-sub { color: var(--faint); font-size: 12.5px; margin: 0 0 18px; }

  .field { margin-bottom: 16px; }
  /* The value sits opposite its label on one row. It's a separate control from the
     slider below it, so the row is a plain div — a <label for> may only name one. */
  .field-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 6px; }
  .field label, .field-label { display: block; font-size: 12.5px; color: var(--muted); font-weight: 500; margin-bottom: 6px; }
  .field-head label, .field-head .field-label { margin-bottom: 0; }
  .val { font-family: var(--font-mono); font-size: 13px; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

  /* The live readout doubles as an entry field, so anyone who can't work a slider
     can type the figure instead. It's sized to its digits and borderless until
     hovered or focused, so it still reads as a readout rather than a form field.
     Native spin buttons are ~10px targets — worse than the slider for the very
     people this is for — so they're dropped; arrow keys step the field itself. */
  .val-num { width: 4.6ch; padding: 1px 3px; border: 1px solid transparent; background: transparent; color: var(--ink); font-family: var(--font-mono); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; border-radius: 5px; appearance: textfield; -moz-appearance: textfield; }
  .val-num.wide { width: 6.4ch; }
  .val-num::-webkit-outer-spin-button, .val-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .val-num:hover { border-color: var(--edge); }
  .val-num:focus { border-color: var(--brand); background: var(--surface-2); }
  .val-num:out-of-range { border-color: var(--danger); color: var(--danger); }

  .input-money { position: relative; }
  .input-money::before { content: "$"; position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--faint); font-family: var(--font-mono); font-size: 14px; }
  input[type="text"].money { padding-left: 24px; }
  input[type="text"], input[type="number"]:not(.val-num), select { width: 100%; padding: 9px 11px; border: 1px solid var(--edge); background: var(--surface-2); color: var(--ink); border-radius: 8px; font-family: var(--font-mono); font-size: 14px; font-variant-numeric: tabular-nums; }
  select { font-family: var(--font-sans); cursor: pointer; }
  input:focus, select:focus, input[type="range"]:focus-visible, input[type="checkbox"]:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

  input[type="range"] { -webkit-appearance: none; appearance: none; width: 100%; height: 5px; border-radius: 4px; background: var(--edge); margin: 8px 0 2px; }
  input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 17px; height: 17px; border-radius: 50%; background: var(--brand); border: 2px solid var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.25); cursor: pointer; }
  input[type="range"]::-moz-range-thumb { width: 15px; height: 15px; border-radius: 50%; background: var(--brand); border: 2px solid var(--surface); cursor: pointer; }
  .range-ends { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--faint); font-family: var(--font-mono); margin-top: 1px; }

  .subpanel { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: 10px; padding: 13px 13px 3px; margin: -2px 0 16px; }
  .subpanel .field { margin-bottom: 12px; }
  .subpanel .field label { font-size: 11.5px; }
  .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px; }

  .btn { width: 100%; padding: 10px; border: 1px solid var(--edge); background: var(--surface-2); color: var(--ink); border-radius: 8px; cursor: pointer; font-family: var(--font-sans); font-size: 13px; font-weight: 500; }
  .btn:hover { border-color: var(--brand); color: var(--brand); }
  .btn:active { transform: translateY(1px); }
  .btn.small { padding: 7px; font-size: 12px; }
  .btn:disabled { opacity: .45; cursor: not-allowed; }
  .btn:disabled:hover { border-color: var(--edge); color: var(--ink); }

  /* Private mode: relative figures instead of dollars, for screen sharing. */
  .priv-toggle { width: auto; flex: none; padding: 7px 12px; white-space: nowrap; }
  .priv-toggle[aria-pressed="true"] { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); font-weight: 600; }
  .priv-note { margin: 14px 0 0; max-width: 62ch; padding: 10px 13px; border: 1px solid var(--hairline); border-left: 3px solid var(--brand); border-radius: 8px; background: var(--brand-soft); color: var(--muted); font-size: 12.5px; line-height: 1.5; }
  .priv-note b { color: var(--ink); }
  body.private .input-money::before { content: none; }
  body.private input[type="text"].money { padding-left: 11px; }
  input[data-priv-real] { color: var(--muted); cursor: default; }
  .divider { height: 1px; background: var(--hairline); margin: 18px 0; border: 0; }
  .hint { font-size: 11.5px; color: var(--faint); margin: 8px 0 0; line-height: 1.45; }

  /* income streams */
  .stream { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: 9px; padding: 11px 11px 10px; margin-bottom: 8px; }
  .stream-top { display: flex; gap: 8px; margin-bottom: 8px; }
  .stream-top .s-label { flex: 1; padding: 6px 9px; font-family: var(--font-sans); font-size: 13px; }
  .s-del { flex: 0 0 34px; min-height: 34px; border: 1px solid var(--edge); background: var(--surface); border-radius: 7px; cursor: pointer; color: var(--faint); font-size: 17px; line-height: 1; }
  .s-del:hover { color: var(--danger); border-color: var(--danger); }
  .stream .input-money { margin-bottom: 8px; }
  .stream-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 9px; }
  .s-basis-field { margin-bottom: 8px; }
  .mini { display: flex; flex-direction: column; gap: 4px; font-size: 10.5px; color: var(--muted); font-weight: 500; margin: 0; }
  .mini input, .mini select { padding: 6px 8px; font-size: 13px; }
  /* The ages a retirement-relative stream currently resolves to. */
  .stream-note { font-size: 10.5px; color: var(--faint); margin: -3px 0 9px; line-height: 1.4; }
  .stream-note[hidden] { display: none; }
  .cola { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--muted); cursor: pointer; margin: 0; font-weight: 500; }
  .cola input { width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }

  .results { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
  .results > * { min-width: 0; }
  .outcome { padding: 22px 24px 24px; }
  .outcome-head { display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 14px; }
  .big-prob { font-family: var(--font-serif); font-weight: 600; line-height: .95; font-size: clamp(52px, 9vw, 78px); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
  .verdict { font-size: 13px; font-weight: 600; letter-spacing: .02em; margin-top: 4px; }
  .prob-ci { font-family: var(--font-mono); font-size: 11.5px; color: var(--faint); margin-top: 4px; font-variant-numeric: tabular-nums; cursor: help; }
  #tornado text.tor-name { font-family: var(--font-sans); font-size: 11px; fill: var(--ink); }
  #tornado text.tor-val { font-family: var(--font-mono); font-size: 9.5px; fill: var(--faint); font-variant-numeric: tabular-nums; }
  .prob-label { text-align: right; }
  .prob-label .k { font-size: 12px; color: var(--muted); }
  .prob-label .sub { font-family: var(--font-mono); font-size: 12.5px; color: var(--faint); margin-top: 3px; font-variant-numeric: tabular-nums; }

  .meter { height: 9px; border-radius: 6px; margin: 20px 0 6px; position: relative; background: linear-gradient(90deg, var(--danger) 0%, var(--warn) 55%, var(--good) 100%); opacity: .9; }
  .meter .mk { position: absolute; top: -4px; width: 3px; height: 17px; border-radius: 2px; background: var(--ink); box-shadow: 0 0 0 2px var(--surface); transition: left .25s ease; }
  .meter-scale { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--faint); font-family: var(--font-mono); }

  .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); border-radius: 10px; overflow: hidden; margin-top: 22px; }
  .stat { background: var(--surface); padding: 13px 14px; }
  .stat .k { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); font-weight: 600; }
  .stat .v { font-family: var(--font-mono); font-size: 18px; font-weight: 600; margin-top: 5px; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
  .stat .v.sm { font-size: 15.5px; }

  .chart-card { padding: 20px 22px 18px; }
  .chart-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 10px; margin-bottom: 4px; }
  .legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 11.5px; color: var(--muted); }
  .legend .li { display: flex; align-items: center; gap: 6px; }
  .swatch { width: 12px; height: 12px; border-radius: 3px; }
  .swatch.line { height: 3px; border-radius: 2px; width: 16px; }

  svg { display: block; width: 100%; height: auto; }
  .axis text { font-family: var(--font-mono); font-size: 10px; fill: var(--faint); font-variant-numeric: tabular-nums; }
  .grid line { stroke: var(--hairline); stroke-width: 1; }
  .axis-title { font-family: var(--font-sans); font-size: 10.5px; fill: var(--muted); font-weight: 500; }

  .sweep-controls { display: grid; grid-template-columns: 1.5fr 1fr 1fr .7fr; gap: 12px; margin-bottom: 16px; }
  @media (max-width: 620px) { .sweep-controls { grid-template-columns: 1fr 1fr; } }
  .sweep-controls .field { margin: 0; }
  .sweep-controls label { font-size: 11px; }

  .tooltip { position: fixed; pointer-events: none; z-index: 40; background: #1c2637; color: #e8eef6; padding: 8px 10px; border-radius: 7px; font-size: 11.5px; font-family: var(--font-mono); line-height: 1.5; box-shadow: 0 6px 20px rgba(0,0,0,.4); opacity: 0; transition: opacity .1s; white-space: nowrap; font-variant-numeric: tabular-nums; }
  .tooltip .tt-t { font-family: var(--font-sans); font-weight: 600; margin-bottom: 3px; color: #ffffff; }
  .tooltip b { color: #9fb2ff; font-weight: 600; }

  /* Sits below both columns, so it clears the sticky controls rail. */
  .site-footer { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 34px; padding-top: 14px; border-top: 1px solid var(--hairline); font-size: 12px; color: var(--faint); }
  .site-footer a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--hairline); }
  .site-footer a:hover { color: var(--brand); border-bottom-color: currentColor; }
  .site-footer-version { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

  details.method { margin-top: 22px; font-size: 13px; color: var(--muted); }
  details.method summary { cursor: pointer; font-weight: 600; color: var(--ink); font-size: 13px; }
  details.method p { margin: 10px 0; max-width: 74ch; }
  details.method code, .hint code { font-family: var(--font-mono); background: var(--surface-2); padding: 1px 5px; border-radius: 4px; font-size: 12px; }

  table.datatable { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 12px; margin-top: 12px; font-variant-numeric: tabular-nums; }
  table.datatable caption { text-align: left; color: var(--muted); font-family: var(--font-sans); font-size: 12px; padding-bottom: 8px; }
  table.datatable th, table.datatable td { text-align: right; padding: 5px 10px; border-bottom: 1px solid var(--hairline); }
  table.datatable th:first-child, table.datatable td:first-child { text-align: left; }
  table.datatable thead th { color: var(--faint); font-weight: 600; font-family: var(--font-sans); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
  table.datatable tbody th { font-weight: 600; color: var(--ink); }
  /* A scrollable region must be reachable by keyboard to be scrollable by keyboard. */
  .scroll-x { overflow-x: auto; }
  .scroll-x:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

  .heat-controls { display: grid; grid-template-columns: 1.4fr .9fr .9fr .7fr; gap: 12px; margin-bottom: 12px; }
  @media (max-width: 620px) { .heat-controls { grid-template-columns: 1fr 1fr; } }
  .heat-controls .field { margin: 0; }
  .heat-controls label { font-size: 11px; }
  .btn.heat-swap { width: auto; flex: 0 0 auto; align-self: center; white-space: nowrap; }

  .seq-attr { display: grid; grid-template-columns: 158px 1fr; gap: 22px; align-items: center; }
  @media (max-width: 560px) { .seq-attr { grid-template-columns: 1fr; gap: 14px; } }
  .seq-share-num { font-family: var(--font-serif); font-weight: 600; font-size: 46px; line-height: 1; color: var(--warn); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
  .seq-share-lab { font-size: 12px; color: var(--muted); margin-top: 5px; line-height: 1.35; }
  .seqbar { display: flex; height: 22px; border-radius: 6px; overflow: hidden; background: var(--surface-2); }
  .seqbar > div { height: 100%; }
  .seq-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 11px; font-size: 11.5px; color: var(--muted); }
  .seq-legend .li { display: flex; align-items: center; gap: 6px; }
  .seq-legend .sw { width: 11px; height: 11px; border-radius: 3px; }
  .seq-legend b { color: var(--ink); font-variant-numeric: tabular-nums; }
  .seq-safe-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; margin-bottom: 10px; flex-wrap: wrap; }
  .seq-target-field { margin: 0; max-width: 118px; }
  .seq-target-field label { font-size: 11px; }
  #seq-summary { font-size: 12.5px; color: var(--muted); }

  /* ---- Step-up ladder ---- */
  /* Fractions, not fixed pixels. This card sits in the right-hand column, which is
     only about 430px wide just above the 880px layout breakpoint — narrower than
     three fixed boxes need, so a third control turned the whole page into a
     sideways scroll between 881px and 1005px. Fractions cannot overflow, and the
     620px rule below still drops to two columns on a phone. */
  .ladder-controls { display: grid; grid-template-columns: .8fr 1.1fr 1fr; gap: 12px; margin-bottom: 4px; }
  @media (max-width: 620px) { .ladder-controls { grid-template-columns: 1fr 1fr; } }
  .ladder-controls .field { margin: 0; }
  .ladder-controls label { font-size: 11px; }

  .ladder-editors { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin: 16px 0 6px; }
  @media (max-width: 760px) { .ladder-editors { grid-template-columns: 1fr; } }
  .ladder-pane { min-width: 0; }
  .ladder-pane > .btn { margin-top: 8px; }
  .ladder-h { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); font-weight: 700; margin: 0 0 4px; }
  .ladder-pane > .hint { margin: 0 0 10px; }

  /* The analysis-prompt block, sitting under the ladder chart. Set on the panel
     background so it reads as a distinct action rather than as more chart chrome —
     it is the one control on the page whose effect leaves the page. */
  /* The corridor is its own card now, so it needs no panel chrome of its own — only
     the one control row, which reuses the ladder's field layout because it is the
     same kind of row with one field in it. */
  #corridor-card .ladder-controls { margin-bottom: 4px; }
  #corridor-card > .hint { margin-top: 6px; }
  #corridor-card > .legend { margin: 12px 0 0; }

  .prompt-copy { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: 10px;
    padding: 13px 13px 12px; margin: 16px 0 4px; }
  .prompt-copy > .hint { margin: 0 0 8px; }
  /* The privacy warning is deliberately in the flow at full contrast rather than in
     a tooltip: it is the sentence that makes pasting an informed act, and a tooltip
     is not read by anyone who has already decided to click. */
  .prompt-warn { color: var(--ink) !important; border-left: 3px solid var(--warn); padding-left: 9px; }
  .prompt-copy .scenario-row { margin-top: 10px; }
  .prompt-out { width: 100%; margin-top: 8px; padding: 9px 11px; border: 1px solid var(--edge);
    background: var(--surface); color: var(--ink); border-radius: 8px; font-family: var(--font-mono);
    font-size: 11.5px; line-height: 1.5; resize: vertical; }

  /* A tier is two lines: what to call it, then what it's anchored on and at what
     figure. One line would fit on a wide screen — but the pane is half a card wide
     whatever the viewport is doing, so "Spend → earliest age" truncates to
     "Spend → ea" at every width worth designing for. */
  .ldtier { display: grid; grid-template-columns: minmax(0, 1fr) minmax(84px, 110px) 34px; gap: 6px; align-items: center;
    grid-template-areas: "name name del" "anchor value value";
    background: var(--surface-2); border: 1px solid var(--hairline); border-radius: 9px; padding: 9px 10px; margin-bottom: 7px; }
  .ldtier > :nth-child(1) { grid-area: name; }
  .ldtier > :nth-child(2) { grid-area: anchor; }
  .ldtier > :nth-child(3) { grid-area: value; }
  .ldtier > .lt-del { grid-area: del; justify-self: end; }
  .ldtier input, .ldtier select { padding: 6px 9px; font-size: 13px; }
  /* .s-del sizes itself with a flex basis, which a grid cell ignores. */
  .ldtier .lt-del { width: 34px; background: var(--surface); }
  .ldtier .lt-label { font-family: var(--font-sans); }
  .ldtier .input-money::before { font-size: 12px; left: 9px; }
  .ldtier input.money { padding-left: 20px; }
  body.private .ldtier input.money { padding-left: 9px; }

  .ldscen { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: 9px; padding: 10px 11px; margin-bottom: 8px; }
  /* An active scenario carries a dot in its own colour; the border echoes it so the
     card and the dumbbell it produces are matchable at a glance. */
  .ldscen.on { border-color: var(--edge); }
  .ldscen-top { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
  .ldscen-dot { flex: 0 0 10px; width: 10px; height: 10px; border-radius: 50%; }
  .ldscen-top .lv-label { flex: 1; min-width: 0; padding: 6px 9px; font-family: var(--font-sans); font-size: 13px; }
  .ldscen .cola { margin-bottom: 6px; }
  .ldscen-mode { margin-bottom: 8px; }
  .ldscen-acts { display: flex; gap: 8px; margin-top: 8px; }
  .ldscen-acts .btn { flex: 1; }
  .ldstreams:not(:empty) { margin: 8px 0 0; }
  .ldstream { background: var(--surface); border: 1px solid var(--hairline); border-radius: 8px; padding: 9px 9px 7px; margin-bottom: 7px; }
  .ldstream .stream-grid { grid-template-columns: 1fr 1fr 1fr; }
  @media (max-width: 520px) { .ldstream .stream-grid { grid-template-columns: 1fr 1fr; } }

  /* The legend sits with the chart rather than up in the card head: the tier and
     scenario editors come between them, so a head legend scrolls out of sight
     before you reach the dots it names. */
  .ladder-legend { margin: 14px 0 2px; padding-top: 12px; border-top: 1px solid var(--hairline); }
  .ladder-legend:empty { display: none; }
  .ladder-legend .li { font-weight: 500; color: var(--ink); }
  .ladder-legend .li-agree { color: var(--muted); font-weight: 400; font-style: italic; }
  .ladder-legend .swatch { border-radius: 50%; }

  #ladder text.ld-name { font-family: var(--font-sans); font-size: 11px; fill: var(--ink); }
  #ladder text.ld-val { font-family: var(--font-mono); font-size: 9.5px; fill: var(--faint); font-variant-numeric: tabular-nums; }

  .scenario { background: var(--brand-soft); border: 1px solid var(--hairline); border-radius: 10px; padding: 12px; margin-bottom: 18px; }
  /* --faint is tuned for the two card surfaces; on the tinted scenario panel it
     lands just under 4.5:1, so hint text there steps up to --muted. */
  .scenario .hint { color: var(--muted); }
  .scenario > select { margin-bottom: 8px; }
  .scenario-row { display: flex; gap: 8px; }
  .scenario-row + .scenario-row { margin-top: 8px; }
  .scenario .btn { flex: 1; }
  .scen-more { margin-top: 10px; }
  .scen-more > summary { cursor: pointer; font-size: 11.5px; color: var(--muted); font-weight: 600; list-style: none; }
  .scen-more > summary::-webkit-details-marker { display: none; }
  .scen-more > summary::before { content: "\25B8  "; color: var(--faint); }
  .scen-more[open] > summary::before { content: "\25BE  "; }
  #scen-code { margin: 8px 0; font-size: 12px; }
  .toast { font-size: 11.5px; color: var(--good); font-weight: 600; margin-top: 8px; min-height: 14px; opacity: 0; transition: opacity .2s; }
  .toast.show { opacity: 1; }

  details.nerd { margin: 0 0 4px; }
  details.nerd > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); padding: 3px 0; }
  details.nerd > summary::-webkit-details-marker { display: none; }
  details.nerd > summary::before { content: "\25B8"; font-size: 9px; color: var(--faint); }
  details.nerd[open] > summary::before { content: "\25BE"; }
  details.nerd > summary:hover { color: var(--brand); }
  .nerd-body { padding-top: 14px; }

  @media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

  /* ---------- Narrow screens ---------- */

  /* The pinned headline. Desktop keeps it hidden — the outcome card is right there. */
  .mini-result { display: none; }

  @media (max-width: 880px) {
    .mini-result {
      display: flex; align-items: baseline; gap: 10px;
      position: sticky; top: 0; z-index: 30;
      padding: 9px 22px; background: var(--surface);
      border-bottom: 1px solid var(--edge); box-shadow: 0 2px 10px rgba(0,0,0,.07);
    }
    .mini-k { font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
    .mini-v { font-family: var(--font-mono); font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
    .mini-verdict { font-size: 12px; font-weight: 600; margin-left: auto; text-align: right; }

    /* iOS Safari zooms the whole page when a focused field is under 16px, so every
       tap into an input jerked the layout. 16px is the threshold, not a preference.
       (The fix is never `maximum-scale=1` in the viewport meta — that would block
       pinch-zoom, which is its own accessibility failure.) */
    /* The later three selectors out-specify the bare element one, so they have to
       be named explicitly or they keep their 12–13px and keep triggering the zoom. */
    input[type="text"], input[type="number"], select, .val-num,
    #scen-code, .stream-top .s-label, .mini input, .mini select,
    .ldtier input, .ldtier select, .ldscen-top .lv-label { font-size: 16px; }

    /* Thumb-sized targets. Everything below was 17–34px tall. */
    input[type="text"], input[type="number"]:not(.val-num), select, .btn, .btn.small { min-height: 44px; }
    .val-num { min-height: 44px; padding: 4px 7px; width: 5.4ch; }
    .val-num.wide { width: 7.2ch; }
    .s-del { flex: 0 0 44px; min-height: 44px; font-size: 20px; }
    .ldtier .lt-del { width: 44px; }
    .stream-top .s-label, .mini input { min-height: 44px; }
    /* Padding rather than flex: `display:flex` on a summary drops its disclosure
       marker in Chrome, and .method rows rely on the native one. */
    summary, details.nerd > summary, .scen-more > summary { padding-top: 14px; padding-bottom: 14px; }
    .skip-link { padding: 12px 16px; }
    /* The whole .cola label toggles the box, so the row is the real target — but
       size the box itself past the 24px minimum for anyone aiming straight at it. */
    .cola { padding: 7px 0; }
    .cola input { width: 24px; height: 24px; }

    /* Once .outcome-head wraps, a right-aligned block under left-aligned content
       reads as a layout bug. */
    .prob-label { text-align: left; }
  }

  /* Chart text is drawn in user units on a fixed 760-wide viewBox, so it scales
     with the container: at a 375px viewport that's 0.38x, which put 10px axis
     labels on screen at under 4px. These steps hold the rendered size near 10px.
     They only start once the container is meaningfully narrower than the viewBox —
     above ~700px the natural size is already right. */
  @media (max-width: 700px) {
    .axis text { font-size: 14px; }
    .axis-title { font-size: 15px; }
    #tornado text.tor-name { font-size: 15px; }
    #tornado text.tor-val { font-size: 13px; }
    #ladder text.ld-name { font-size: 15px; }
    #ladder text.ld-val { font-size: 13px; }
  }
  @media (max-width: 520px) {
    .axis text { font-size: 19px; }
    .axis-title { font-size: 20px; }
    #tornado text.tor-name { font-size: 21px; }
    #tornado text.tor-val { font-size: 18px; }
    #ladder text.ld-name { font-size: 21px; }
    #ladder text.ld-val { font-size: 18px; }
  }
  @media (max-width: 400px) {
    .axis text { font-size: 25px; }
    .axis-title { font-size: 26px; }
    #tornado text.tor-name { font-size: 27px; }
    #tornado text.tor-val { font-size: 23px; }
    #ladder text.ld-name { font-size: 27px; }
    #ladder text.ld-val { font-size: 23px; }
  }
