/* lvt-explainer — warm, light, California-ish. One reading column; the plot
   stretches to its full width. Every editable field is 16px so iOS Safari never
   auto-zooms on focus. The rules for v2's two narrative pages went with the
   pages in WP4; what is left is this page and the furniture under it. */

:root {
  --accent: #e8772e;
  --accent-soft: #fbe7d5;
  --bg: #fdfaf5;
  --card: #ffffff;
  --text: #2c2622;
  --muted: #766a60;
  --border: #e7ddcf;
  --bar: #9fb0b8;
  --bar-dark: #7d919b;
  --roof: #7d919b;
  --wall: #fffdf9;
  --ground: #d9cfbf;
  --good: #2f7d5d;
  --bad: #b2503a;
  --shadow: 0 1px 2px rgba(60, 45, 30, .07);
  /* The two systems on the income-tax tab. Orange is the income tax (it is the
     app's accent, and the tax that exists today); the blue-green is the land
     tax. Used for the swap tiles, the stacked bars, the lifetime chart and the
     archetype cards, and nowhere else. */
  --pit: #e8772e;
  --pit-soft: #fbe7d5;
  --lvt: #2b7f8c;
  --lvt-soft: #dcedef;
  /* The other three taxes, wherever a bar is split by tax. Land and income
     keep the two colours above; these three were picked to stay apart from
     them and from each other for colour-blind readers too (checked with the
     dataviz validator: adjacent CVD ΔE ≥ 9 in both modes). */
  --tx-bld: #5b3f8f;
  --tx-gains: #24703a;
  --tx-sales: #cfa22a;
}

@media (prefers-color-scheme: dark) {
  :root {
    --accent: #f28c46;
    --accent-soft: #46301f;
    --bg: #191614;
    --card: #221e1a;
    --text: #ece4da;
    --muted: #a89c90;
    --border: #3b342c;
    --bar: #6d7d85;
    --bar-dark: #8a9aa2;
    --roof: #6d7d85;
    --wall: #2e2823;
    --ground: #3b342c;
    --good: #5fbe92;
    --bad: #e08067;
    --shadow: none;
    --pit: #f28c46;
    --pit-soft: #46301f;
    --lvt: #5cb4c2;
    --lvt-soft: #1d3439;
    --tx-bld: #8a6fd0;
    --tx-gains: #2c7a3a;
    --tx-sales: #b08a26;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0 auto;
  padding: 1rem 1rem 3rem;
  max-width: 780px;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 1rem;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  -webkit-text-size-adjust: 100%;
}

header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  flex-wrap: wrap;
}

h1 { margin: .2rem 0; font-size: 1.5rem; line-height: 1.2; }
h2 { font-size: 1.2rem; margin: 0 0 .6rem; line-height: 1.3; }
h3 { font-size: 1rem; margin: 0 0 .5rem; letter-spacing: .01em; }
p { margin: 0 0 .8rem; }

.home-link { color: var(--muted); text-decoration: none; font-size: .9rem; white-space: nowrap; }
.home-link:hover { color: var(--accent); }

.lede { color: var(--muted); margin: .4rem 0 1.2rem; }

/* ── Page furniture ────────────────────────────────────────────────────── */

.framing {
  border-left: 3px solid var(--accent);
  padding: .1rem 0 .1rem .75rem;
  margin: 1rem 0;
}

.note, .hint { font-size: .85rem; color: var(--muted); margin: .5rem 0 0; }
.hint { margin: .3rem 0 0; }

.ticks { margin: .4rem 0 1rem; padding-left: 1.1rem; }
.ticks li { margin: .3rem 0; }

footer { color: var(--muted); font-size: .82rem; margin-top: 1.5rem; }

/* ── Levers ────────────────────────────────────────────────────────────── */

/* One lever = label on its own line, then the control row. Same order in every
   cell: the label leads, then the input (a $ affix may sit beside it). */
.lever > label {
  display: block;
  font-size: .85rem;
  font-weight: 600;
  color: var(--muted);
  margin: 0 0 .3rem;
}

.ctl { display: flex; flex-direction: column; gap: .15rem; }
.ctl input[type=range] { width: 100%; }
.row { display: flex; align-items: center; gap: .5rem; }

.affix { font-size: 1rem; color: var(--muted); white-space: nowrap; }
/* Every control row reserves the same prefix slot, with or without a "$", so
   the input boxes in a group all start at the same x. */
.affix.pre { width: .85rem; flex: none; }

input[type=number] {
  font: inherit;
  font-size: 1rem;              /* never below 16px: iOS zooms on focus */
  height: 2.4rem;
  padding: 0 .55rem;
  width: 100%;
  min-width: 0;
  max-width: 11rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg);
  color: var(--text);
}
input[type=number]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

input[type=range] {
  flex: 1;
  min-width: 0;
  height: 2.4rem;
  accent-color: var(--accent);
  background: transparent;
}

.levers {
  margin: 1rem 0 .3rem;
  padding: .75rem .8rem .1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.levers + .levers { margin-top: .5rem; }
.lever { margin: 0 0 .7rem; }
.lever .row { gap: .5rem; }
.lever input[type=number] { width: 8rem; max-width: 100%; flex: none; }

details.bx { border: 1px dashed var(--border); border-radius: 9px; padding: .3rem .45rem; }
details.bx > summary {
  cursor: pointer; font-size: .78rem; font-weight: 600; color: var(--muted);
  list-style-position: inside;
}
details.bx > summary:hover { color: var(--accent); }
details.bx[open] > summary { margin-bottom: .35rem; }
.bx-body { display: flex; flex-direction: column; gap: .25rem; }
.bx-row { display: flex; align-items: center; gap: .3rem; }
.bx-lab { font-size: .78rem; color: var(--muted); white-space: nowrap; }
.bx-row .affix { font-size: .78rem; }
.bx-row .affix.pre { width: auto; }
/* ── Big number ────────────────────────────────────────────────────────── */

.bignum {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  flex-wrap: wrap;
  margin: 1rem 0;
  padding: .7rem .85rem;
  background: var(--accent-soft);
  border-radius: 12px;
}
.bignum strong { font-size: 1.9rem; line-height: 1.05; color: var(--accent); font-variant-numeric: tabular-nums; }
.bignum span { font-size: .88rem; flex: 1 1 12rem; min-width: 0; }

.chip {
  font: inherit;
  font-size: .85rem;
  padding: .35rem .7rem;
  border: 1px solid var(--border);
  border-radius: 99px;
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }

/* ── Toggle ────────────────────────────────────────────────────────────── */

.toggle { display: flex; align-items: center; gap: .5rem; font-size: .9rem; margin: .6rem 0; cursor: pointer; }
.toggle input { width: 1.15rem; height: 1.15rem; accent-color: var(--accent); }

/* ── Show the math ─────────────────────────────────────────────────────── */

details.math { margin: 1rem 0 0; border-top: 1px dashed var(--border); padding-top: .6rem; }
details.math summary { cursor: pointer; font-size: .85rem; font-weight: 600; color: var(--muted); }
details.math summary:hover { color: var(--accent); }
details.math > div { font-size: .82rem; color: var(--muted); margin-top: .5rem; }
details.math p { margin: 0 0 .5rem; }
details.math code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .95em;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: .05rem .25rem;
  overflow-wrap: anywhere;
}
details.math ul { margin: 0 0 .5rem; padding-left: 1.1rem; }
details.math li { margin: .2rem 0; }

/* ── Wider screens ─────────────────────────────────────────────────────── */

@media (min-width: 620px) {
  body { padding: 1.5rem 1.5rem 4rem; }
  h1 { font-size: 1.9rem; }
  h2 { font-size: 1.35rem; }
  .bignum strong { font-size: 2.4rem; }
  .lever { display: grid; grid-template-columns: 13rem 1fr; align-items: center; gap: .2rem .75rem; }
  .lever > label { margin: 0; }
  .lever .hint { grid-column: 2; margin-top: .25rem; }
}

/* ── Chips ─────────────────────────────────────────────────────────────── */

.chip.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
/* Links in the prose take the app's accent, not the UA blue. */
footer a, #sources-body a, .math a { color: var(--accent); }

.keys { display: flex; flex-wrap: wrap; gap: .2rem .9rem; margin-top: .35rem; }
.key { display: flex; align-items: center; gap: .35rem; font-size: .75rem; color: var(--muted); }
.key .sw { width: .7rem; height: .7rem; border-radius: 3px; flex: none; }
.key b { color: var(--text); font-variant-numeric: tabular-nums; }

/* ── The region chips ──────────────────────────────────────────────────── */

/* One row that scrolls sideways, never three rows that wrap: on a phone the
   wrapped version costs the plot ~75px of the screen. The selected chip is
   scrolled into view from syncChipRow(), so the current region is always
   readable. */
.regions {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: .4rem;
  margin: .9rem 0 .3rem;
  padding-bottom: .15rem;
  scrollbar-width: none;                /* Firefox */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.regions::-webkit-scrollbar { display: none; }
.regions .chip { flex: none; }

@media (min-width: 900px) {
  /* A hidden sideways scrollbar is a phone affordance. On a desktop there is
     vertical room to spare and no touch, so the chips wrap again and every
     region stays visible without scrolling. */
  .regions { flex-wrap: wrap; overflow-x: visible; }
}

/* The scatter: one SVG for the dots, with the axis labels as HTML in a left
   gutter and a strip underneath, so they keep their size on a phone instead of
   scaling with the viewBox. */
.scatter { position: relative; margin: .9rem 0 .3rem; padding-left: 2.9rem; }
.sc-svg { display: block; width: 100%; height: auto; touch-action: pan-y; }

.sc-y { position: absolute; left: 0; top: 0; bottom: 1.15rem; width: 2.6rem; }
.sc-y span {
  position: absolute; right: 0; transform: translateY(-50%);
  font-size: .7rem; color: var(--muted); white-space: nowrap;
}
.sc-y span.band { color: var(--lvt); font-weight: 700; }

.sc-x { position: relative; height: 1.15rem; }
.sc-x span {
  position: absolute; transform: translateX(-50%);
  font-size: .7rem; color: var(--muted); white-space: nowrap;
}
.sc-x span.first { transform: none; }
.sc-x span.last { transform: translateX(-100%); }

/* The view switch over the plot. Same chip as everywhere else, a size down,
   because it picks a drawing rather than a place. */
.views { display: flex; gap: .35rem; margin: .2rem 0 0; }
.views .chip { font-size: .78rem; padding: .25rem .6rem; }

.sc-tip {
  position: absolute; z-index: 3; pointer-events: none;
  max-width: 13rem; padding: .35rem .5rem;
  font-size: .75rem; line-height: 1.35;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 8px; box-shadow: var(--shadow);
}
.sc-tip .down { color: var(--good); }
.sc-tip .up { color: var(--bad); }

.sw.pit { background: var(--pit); }
.sw.lvt { background: var(--lvt); }

@media (min-width: 620px) {
  .scatter { padding-left: 3.2rem; }
  .sc-y span, .sc-x span { font-size: .76rem; }
}

/* ══ Tax trades ════════════════════════════════════════════════════════════
   The page: one plot at the top, a revenue bar, five lever cards. Everything
   above is shared furniture (type, inputs, chips, the scatter, disclosures);
   everything below belongs to this page alone. */

/* The picture stays on screen while the levers scroll under it, but only where
   there is vertical room for both. Below 900px it scrolls away like anything
   else, and trades.js sizes the SVG to ~45% of the screen instead. */
.plotwrap { margin: .2rem 0 .6rem; }

@media (min-width: 900px) {
  .plotwrap {
    position: sticky; top: 0; z-index: 4;
    background: var(--bg);
    padding: .4rem 0 .5rem;
    border-bottom: 1px solid var(--border);
  }
}

/* Dots and bars in this page's own slot. Same meanings as block 5a: the
   blue-green is the household that comes out ahead, the orange the one that
   does not, and a change of under a dollar either way is neither. */
#plot-dots circle { fill-opacity: .5; }
#plot-dots .d-less { fill: var(--lvt); }
#plot-dots .d-more { fill: var(--pit); }
#plot-dots .d-same { fill: var(--muted); fill-opacity: .32; }
#plot-bars .bb-before { fill: var(--pit); }
#plot-bars .bb-after { fill: var(--lvt); }
.sw.same { background: var(--muted); opacity: .45; }

/* The imputed indirect burden, wherever it is drawn: the same colour as the
   layer under it, paler — the page's one existing way of saying "this is not
   the household's own bill" (see .nh on the stacked bars below). */
#plot-bars .ind { fill-opacity: .55; }
.sw.ind, .sw.nh {
  background: repeating-linear-gradient(45deg, var(--muted) 0 3px, transparent 3px 5px);
  opacity: .8;
}
/* The hatch's stripes are the page colour, and every stacked segment and
   bar is ringed in it, so neighbours never touch. */
.sc-svg .hatch-line { fill: var(--bg); fill-opacity: .7; }
#stack-bars rect, #plot-bars rect { stroke: var(--bg); stroke-width: 1.5px; }
#stack-bars rect.hatch, #plot-bars rect.hatch { stroke: none; }

/* Who bears the state's collections, the third bar of "Where the money comes
   from". Its three slices are payers, not taxes, so they take three weights of
   the page's own ink rather than any of the five tax colours, which mean one
   thing each: solid is the household's own bill, half is the imputed share, and
   the faintest is the part that cannot be put on a California household. */
#stack-bars .p-direct, #stack-bars .p-indirect, #stack-bars .p-unassigned { fill: var(--text); }
.sw.p-direct, .sw.p-indirect, .sw.p-unassigned { background: var(--text); }
#stack-bars .p-direct { fill-opacity: .78; }
#stack-bars .p-indirect { fill-opacity: .4; }
#stack-bars .p-unassigned { fill-opacity: .22; }
.sw.p-direct { opacity: .78; }
.sw.p-indirect { opacity: .4; }
.sw.p-unassigned { opacity: .22; }

/* The one-line note under any view that draws the imputed layer. */
.note.imputed { margin: .25rem 0 0; font-style: italic; }
.note.imputed b { font-style: normal; }

/* "What this shows": one section of METHODOLOGY.md under the plot. It borrows
   the document styling from the Methodology tab, so the two renderings of the
   same file look like the same file. */
details.howto { margin: .4rem 0 .9rem; }
details.howto .md-body { margin-top: .4rem; }
details.howto .md-body h3 { margin-top: 0; }
details.howto .md-body p, details.howto .md-body li { font-size: .85rem; }
details.howto > .hint { margin: .5rem 0 0; }

/* ── The revenue bar ──────────────────────────────────────────────────── */

.revbar {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  box-shadow: var(--shadow);
  padding: .7rem .8rem .75rem;
  margin: 0 0 .9rem;
}
.rev-line { margin: 0 0 .6rem; font-size: .95rem; line-height: 1.45; }
.rev-line b { font-variant-numeric: tabular-nums; }
.gap.short { color: var(--bad); }
.gap.over { color: var(--accent); }
.gap.balanced { color: var(--good); }

.rev-act { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .7rem; }

.btn {
  font: inherit;
  font-size: .95rem;
  font-weight: 600;
  padding: .55rem 1rem;
  min-height: 2.6rem;
  border: 1px solid var(--accent);
  border-radius: 99px;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  flex: none;
}
.btn:hover { filter: brightness(1.05); }
.btn:disabled { background: var(--bg); color: var(--muted); border-color: var(--border); cursor: default; filter: none; }

/* The tick boxes: which taxes the balancer may move. They wrap on a phone
   rather than scrolling, because missing one would change what the button
   does without saying so. */
.rev-ticks { display: flex; flex-wrap: wrap; align-items: center; gap: .15rem .7rem; }
.tick-lab { font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.tick { display: flex; align-items: center; gap: .35rem; font-size: .85rem; cursor: pointer; }
.tick input { width: 1.15rem; height: 1.15rem; accent-color: var(--accent); flex: none; }
.revbar .hint { margin: .45rem 0 0; }

/* ── The lever cards ──────────────────────────────────────────────────── */

.lev {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  box-shadow: var(--shadow);
  padding: .7rem .8rem .75rem;
  margin: 0 0 .6rem;
}
.lev-top { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.lev-top label { font-size: 1rem; font-weight: 700; margin: 0; cursor: pointer; }
.lev-rev {
  font-size: .85rem; font-weight: 600; color: var(--accent);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.lev-ctl { display: flex; flex-direction: column; gap: .15rem; margin-top: .35rem; }
.lev-ctl .row { gap: .5rem; }
.lev-ctl input[type=range] { width: 100%; }
.lev input[type=number] { width: 7.5rem; max-width: 100%; flex: none; }
.lev input:disabled, .lev input[type=range]:disabled { opacity: .45; cursor: default; }
.lev.off .lev-ctl .affix { opacity: .45; }

.lev-foot {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem;
  margin: .1rem 0 0; font-size: .8rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.lev-delta {
  font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border-radius: 99px; padding: .05rem .45rem;
}
.lev-sched { margin: .35rem 0 0; font-size: .82rem; color: var(--muted); }
.lev .hint { margin: .3rem 0 0; }
.lev .toggle { margin: .45rem 0 .1rem; font-size: .85rem; }

/* The exact-values table inside the income card. Same editor as the old tab,
   so it needs the same override of the full-width number input. */
.lev details.bx { margin-top: .55rem; }
.lev .bx-row input[type=number] {
  height: 1.8rem; padding: 0 .25rem; text-align: right; flex: none;
  -moz-appearance: textfield; appearance: textfield;
}
.lev .bx-row input[type=number]::-webkit-outer-spin-button,
.lev .bx-row input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none; appearance: none; margin: 0;
}
.lev .bx-row input.bx-from { width: calc(7ch + 1.1rem); }
.lev .bx-row input.bx-rate { width: calc(4ch + 1.1rem); }
.lev .bx-row input:disabled { color: var(--muted); background: transparent; border-style: dashed; }
.lev .bx-body { overflow-x: auto; }
.lev .bx-note { margin: .35rem 0 0; }

/* ── The assumptions group ────────────────────────────────────────────── */

details.assume {
  border: 1px dashed var(--border); border-radius: 12px;
  padding: .5rem .7rem; margin: 0 0 .9rem;
}
details.assume > summary { cursor: pointer; font-size: .9rem; font-weight: 600; color: var(--muted); }
details.assume > summary:hover { color: var(--accent); }
details.assume[open] > summary { margin-bottom: .5rem; }
details.assume .levers { border: none; background: transparent; padding: 0; }
/* The one toggle in here has a label long enough to wrap on a phone, and a box
   centred against two lines sits between them. Pin it to the first line. */
details.assume .toggle { align-items: flex-start; }
details.assume .toggle input { margin-top: .1rem; }

/* ── The five views in one slot ───────────────────────────────────────────
   The x-label row is one CSS variable tall and the y-label gutter stops
   exactly where it starts, so a view with two rows of labels (or wrapped
   ones) declares its height once rather than in two places that can drift.
   trades.js puts the class on the container; the percentages it computes are
   percentages of the SVG, which is what is left above the labels. */
.trades .scatter { --xh: 1.15rem; }
.trades .sc-y { bottom: var(--xh); }
.trades .sc-x { height: var(--xh); }
.trades .scatter.x2 { --xh: 2.35rem; }
/* Wide labels (three group names) wrap and need a box; the decile numbers do
   not, and giving them one pushed the tenth label past the right edge of the
   page. */
.trades .scatter.xwide { --xh: 2.5rem; }
/* "Show incomes" on a decile view: one more row, the income at each boundary
   between two tenths, centred on the gap between their bars. */
.trades .scatter.xinc { --xh: 2.35rem; }
.trades .scatter.x2.xinc { --xh: 3.5rem; }
.trades .sc-x span.edge {
  bottom: 0; font-size: .66rem; color: var(--text); font-variant-numeric: tabular-nums;
}
.trades .sc-x span.edge i { font-style: normal; }
/* Nine boundaries in a phone's width: the $ goes, the key says what they are. */
@media (max-width: 619px) { .trades .sc-x span.edge i { display: none; } }
.dec-toggle { cursor: pointer; }
.dec-toggle input { width: 1rem; height: 1rem; margin: 0; accent-color: var(--accent); }
.trades .scatter.xwide .sc-x span {
  white-space: normal; width: 6.4rem; text-align: center; line-height: 1.2;
}
.trades .sc-x em {
  display: block; font-style: normal; font-size: .66rem; opacity: .85;
}
.trades .sc-x b { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }

/* The view chips are one sideways-scrolling row on a phone, like the region
   chips: five of them wrap to three lines otherwise, and every line comes out
   of the plot's own height. */
.trades .views {
  flex-wrap: nowrap; overflow-x: auto; padding-bottom: .15rem;
  scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.trades .views::-webkit-scrollbar { display: none; }
.trades .views .chip { flex: none; }

@media (min-width: 900px) {
  .trades .views { flex-wrap: wrap; overflow-x: visible; }
}

/* Diverging bars (views 3 and 5): the same two colours as the dots, so "above
   the line" and "orange" never mean two different things on one page. */
#plot-div .db-more, #plot-who .db-more { fill: var(--pit); }
#plot-div .db-less, #plot-who .db-less { fill: var(--lvt); }

/* Where the money comes from: one colour per tax, and the part of each block
   billed to somebody who is not a household drawn in the same colour, paler.
   Land keeps the app's blue-green and the income tax its orange; buildings
   take the roof colour they are drawn in everywhere else. */
#stack-bars .s-lvt, .sw.s-lvt { fill: var(--lvt); background: var(--lvt); }
#stack-bars .s-bld, .sw.s-bld { fill: var(--tx-bld); background: var(--tx-bld); }
#stack-bars .s-income, .sw.s-income { fill: var(--pit); background: var(--pit); }
#stack-bars .s-gains, .sw.s-gains { fill: var(--tx-gains); background: var(--tx-gains); }
#stack-bars .s-sales, .sw.s-sales { fill: var(--tx-sales); background: var(--tx-sales); }
#stack-bars .nh { fill-opacity: .55; }

/* ── The income card's graph ──────────────────────────────────────────── */

/* The live line under the bracket graph: what the schedule raises, and the one
   thing the graph cannot draw, which is the multiplier applied on top of it. */
.lev-live { margin: .5rem 0 0; font-size: .85rem; color: var(--text); }
.lev .bgr { margin-top: .5rem; }
.lev .bgr-out { margin-top: .4rem; }
.lev .bgr-actions { margin-top: .35rem; }

/* ── Sources ─────────────────────────────────────────────────────────── */

.flag {
  font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--bad); border: 1px solid var(--bad); border-radius: 99px; padding: 0 .35rem;
  white-space: nowrap;
}
#sources-body li { margin: 0 0 .6rem; }
#sources-body i { color: var(--muted); }
#claims ol.ticks { margin-bottom: .6rem; }
#claims li { margin: 0 0 .35rem; }

/* ── The tab bar ──────────────────────────────────────────────────────────
   Two pages, one bar, on both of them. These are links, not buttons, so they
   borrow the chip and switch off the UA's underline and blue; the current page
   wears the same treatment a selected chip does, driven by aria-current so the
   markup states it once for the screen reader and the stylesheet both. */
.tabs { display: flex; gap: .35rem; margin: .6rem 0 .2rem; flex-wrap: wrap; }
.tabs .chip { text-decoration: none; display: inline-block; line-height: 1.3; }
.tabs .chip[aria-current="page"] {
  border-color: var(--accent); background: var(--accent-soft);
  color: var(--accent); font-weight: 600;
}

/* ── The methodology page ─────────────────────────────────────────────────
   One long document rendered from METHODOLOGY.md by md.js, with a contents
   list built from its own headings. The reading column stays narrow; the
   contents list becomes a sticky sidebar only when there is room beside it. */
body.methodology { max-width: 1080px; }
.md-wrap { display: block; }
.md-toc {
  border: 1px dashed var(--border); border-radius: 12px;
  padding: .6rem .8rem; margin: 0 0 1.2rem;
}
.md-toc h2 { font-size: .85rem; color: var(--muted); margin: 0 0 .4rem; }
.md-toc ol, .md-toc ul { margin: 0; padding-left: 1.1rem; }
.md-toc ul { list-style: none; padding-left: .6rem; }
.md-toc li { margin: .15rem 0; }
.md-toc a { color: var(--text); text-decoration: none; font-size: .85rem; }
.md-toc a:hover { color: var(--accent); text-decoration: underline; }
.md-toc ul a { color: var(--muted); font-size: .8rem; }

/* The document itself. Every heading keeps a scroll margin so an anchor jump
   does not park the title hard against the top of the viewport. */
.md-body { min-width: 0; }
/* The document's own H1 is its title on GitHub; on this page the header above
   already says Methodology, so the rendered copy is hidden rather than printed
   twice. It stays in the DOM, because it is the anchor target for #methodology
   and the row the contents list hangs under. */
.md-body > h1:first-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.md-body h2, .md-body h3, .md-body h4 { scroll-margin-top: .8rem; }
.md-body h2 {
  font-size: 1.2rem; margin: 1.8rem 0 .6rem; padding-top: .8rem;
  border-top: 1px dashed var(--border);
}
.md-body h3 { font-size: 1rem; margin: 1.2rem 0 .4rem; color: var(--accent); }
.md-body h4 { font-size: .95rem; margin: 1rem 0 .3rem; }
.md-body p, .md-body li { font-size: .95rem; }
.md-body ul, .md-body ol { padding-left: 1.3rem; margin: 0 0 .8rem; }
.md-body li { margin: .25rem 0; }
.md-body a { color: var(--accent); overflow-wrap: anywhere; }
.md-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .88em; background: var(--card); border: 1px solid var(--border);
  border-radius: 5px; padding: .05rem .25rem; overflow-wrap: anywhere;
}
.md-body pre {
  background: var(--card); border: 1px solid var(--border); border-radius: 9px;
  padding: .6rem .7rem; overflow-x: auto; margin: 0 0 .9rem;
}
.md-body pre code { background: none; border: none; padding: 0; font-size: .82rem; }
.md-body blockquote {
  margin: 0 0 .9rem; padding: .1rem 0 .1rem .75rem;
  border-left: 3px solid var(--accent); color: var(--muted);
}
.md-body hr { border: none; border-top: 1px dashed var(--border); margin: 1.4rem 0; }

/* A wide table scrolls inside its own box; the page must never scroll
   sideways at 390px. methodology.html wraps every table in .md-scroll. */
.md-scroll { overflow-x: auto; margin: 0 0 .9rem; -webkit-overflow-scrolling: touch; }
.md-body table { border-collapse: collapse; font-size: .82rem; min-width: 100%; }
.md-body th, .md-body td {
  border-bottom: 1px solid var(--border); padding: .3rem .5rem; text-align: left;
  vertical-align: top;
}
.md-body th { background: var(--accent-soft); color: var(--text); white-space: nowrap; }
/* Short code spans in a cell keep their spacing; long source URLs are links,
   and a link in a cell gets a floor on its width so it wraps at a readable
   ~25 characters instead of one character per line in a 40px column. */
.md-body td code, .md-body th code { white-space: pre; overflow-wrap: normal; }
.md-body td a {
  display: inline-block; min-width: 11rem; max-width: 100%;
  word-break: break-all; font-size: .95em;
}
/* Cells sit between two bounds: wide enough that a short cell does not wrap
   every word, narrow enough that a long one does not become a 60-word line. */
.md-body td { min-width: 6rem; max-width: 21rem; }
.md-body tbody tr:last-child td { border-bottom: none; }

/* An unfinished methodology should look unfinished: the markers WP5 and WP7
   still have to fill are highlighted rather than hidden. */
.md-todo {
  background: var(--accent-soft); color: var(--text);
  border: 1px dashed var(--bad); border-radius: 6px;
  padding: .05rem .3rem; font-size: .9em;
}

@media (min-width: 900px) {
  .md-wrap { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 2rem; }
  .md-toc {
    position: sticky; top: 1rem; align-self: start; margin: 0;
    max-height: calc(100vh - 2rem); overflow-y: auto;
  }
}

/* The printed value on a bar that runs off the "Change as % of income" axis:
   HTML like every other axis label, so it keeps its size on a phone. */
.trades .db-vals {
  position: absolute; top: 0; bottom: var(--xh); right: 0; left: 2.9rem;
  pointer-events: none;
}
.trades .db-val {
  position: absolute; transform: translate(4px, 0);
  font-size: .72rem; font-weight: 700; color: var(--pit); white-space: nowrap;
  pointer-events: none;
}
@media (min-width: 620px) { .trades .db-vals { left: 3.2rem; } }

/* ── Saved plans ───────────────────────────────────────────────────────── */

/* One card, one row, after the FIRE calculator's plan bar: the picker takes
   whatever Save and ⋯ leave, and all three share one height, one radius and
   one border so nothing in the row looks like it belongs to another control.
   The select stays a real 16px field so iOS never zooms on it; a long name
   clips with an ellipsis rather than pushing Save off the row. */
.planbar {
  --pb-h: 2.5rem;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: .4rem;
  margin: .75rem 0 .3rem;
  padding: .4rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
}
.planbar select {
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  flex: 1 1 auto;
  min-width: 0;
  height: var(--pb-h);
  padding: 0 .5rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  text-overflow: ellipsis;
}
.pb-btn {
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  height: var(--pb-h);
  padding: 0 .8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
  flex: none;
}
.pb-btn:hover { border-color: var(--accent); color: var(--accent); }
/* Save: accent while there is something to save, muted otherwise. */
.pb-save { background: var(--accent); border-color: var(--accent); color: #fff; }
.pb-save:hover { color: #fff; filter: brightness(.94); }
.pb-save:disabled { background: var(--bg); border-color: var(--border); color: var(--muted); cursor: default; filter: none; }
.pb-more { width: var(--pb-h); padding: 0; font-size: 1.15rem; line-height: 1; }
/* Share: icon and word; on a phone just the icon, so the plan's name keeps
   its room. */
.pb-share { display: inline-flex; align-items: center; gap: .35rem; }
@media (max-width: 519px) {
  .pb-share { width: var(--pb-h); padding: 0; justify-content: center; }
  .pb-share span { display: none; }
  .planbar { gap: .3rem; }
  .planbar select { padding: 0 .35rem; }
  .pb-save { padding: 0 .6rem; }
}
.plan-menu { position: relative; flex: none; display: flex; }
.plan-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-width: 13rem;
  padding: .3rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
}
.plan-pop[hidden], .plan-pop button[hidden] { display: none; }
.plan-pop button {
  font: inherit;
  font-size: .9rem;
  font-weight: 500;
  text-align: left;
  padding: .5rem .6rem;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.plan-pop button:hover { background: var(--bg); color: var(--accent); }

/* The unsaved-changes dialog. */
.modal-back {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  background: rgba(20, 20, 20, .45);
}
.modal {
  width: 100%; max-width: 24rem;
  padding: 1.2rem 1.2rem 1rem;
  background: var(--card);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .25);
}
.modal-title { margin: 0 0 .4rem; font-size: 1.05rem; }
.modal-msg { margin: 0 0 .9rem; font-size: .92rem; }
.modal-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; }

/* The negative income tax and the universal income: three levers under the
   bracket table, in the income card, with the Assumptions group's markup. */
.lev .levers.nit { margin: .7rem 0 .3rem; }
/* Where a stack has a slice below zero, the net it collects. */
#stack-bars .s-net { stroke: var(--text); stroke-width: 2; stroke-dasharray: 5 3; }

/* ── Your household ────────────────────────────────────────────────────────
   One disclosure between the revenue bar and the levers. Its summary carries
   the one number (the change in your bill) so a reader with it shut still
   sees why to open it. Inputs reuse the lever rows; the pictures are HTML
   bars, so their labels keep their size on a phone. */
details.you {
  margin: .9rem 0;
  padding: .55rem .8rem .7rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
}
details.you > summary {
  cursor: pointer;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem;
  font-weight: 700;
  list-style-position: inside;
}
details.you > summary::-webkit-details-marker { display: none; }
details.you > summary::before { content: '▸'; color: var(--muted); font-size: .85rem; }
details.you[open] > summary::before { content: '▾'; }
.you-title { font-size: 1rem; }
.you-sum { font-size: .88rem; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.you-sum.less, .hh-ch.less, .hh-plan-val.less { color: var(--lvt); }
.you-sum.more, .hh-ch.more, .hh-plan-val.more { color: var(--pit); }
.you-body { margin-top: .6rem; }
/* The untouched example household says so: a pill in the summary (seen with
   the panel shut) and one line at the top of the panel. */
.you-cta {
  font-size: .78rem; font-weight: 700; white-space: nowrap;
  padding: .1rem .55rem; border-radius: 99px;
  background: var(--accent-soft); color: var(--accent);
}
.you-cta[hidden], .hh-example[hidden] { display: none; }
.hh-example {
  margin: 0 0 .6rem; padding: .5rem .7rem; font-size: .88rem;
  border-left: 3px solid var(--accent); border-radius: 6px; background: var(--accent-soft);
}

.hhbar { margin: 0 0 .2rem; box-shadow: none; }
.hh-in { margin-top: .6rem; }
.hh-in .lever > .lab { display: block; font-size: .85rem; font-weight: 600; color: var(--muted); }
.hh-in [hidden] { display: none !important; }
.hh-select {
  font: inherit; font-size: 1rem;          /* 16px: no iOS zoom */
  height: 2.4rem; padding: 0 .5rem;
  width: 100%; max-width: 17rem; min-width: 0;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--bg); color: var(--text);
}
.seg { display: flex; gap: .4rem; flex-wrap: wrap; }
.seg .chip { height: 2.4rem; padding: 0 .9rem; font-size: .9rem; }
.hh-in .lev-live { font-size: .85rem; color: var(--muted); margin: -.2rem 0 .7rem; }
.hh-more { margin: .2rem 0 .8rem; }
.hh-more .bx-body { padding-top: .4rem; }
.hh-more .lever .affix { font-size: 1rem; }

@media (min-width: 620px) {
  .hh-in .lever > .lab { margin: 0; }
  .hh-in .lev-live { margin-left: 13.75rem; }
}

.hh-out { margin-top: .9rem; }
.hh-h { margin: 1.1rem 0 .45rem; font-size: .95rem; }

/* The three headline tiles: today, this plan, the change. */
.hh-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
.hh-tile {
  display: flex; flex-direction: column; gap: .05rem; min-width: 0;
  padding: .5rem .6rem; border-radius: 10px; background: var(--bg); border: 1px solid var(--border);
}
.hh-tile span { font-size: .75rem; color: var(--muted); font-weight: 600; }
.hh-tile strong { font-size: 1.02rem; line-height: 1.2; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hh-tile em { font-style: normal; font-size: .72rem; color: var(--muted); }
.hh-tile.less { background: var(--lvt-soft); border-color: transparent; }
.hh-tile.less strong { color: var(--lvt); }
.hh-tile.more { background: var(--pit-soft); border-color: transparent; }
.hh-tile.more strong { color: var(--pit); }
@media (min-width: 620px) { .hh-tile strong { font-size: 1.45rem; } }
#hh-home { margin: .6rem 0 0; font-size: .85rem; }

/* The two stacked bars. A 2px card-coloured gap between segments keeps
   neighbours apart where the colours alone would not. */
.hh-stack { display: flex; flex-direction: column; gap: .45rem; }
.hh-bar { display: grid; grid-template-columns: 4.6rem minmax(0, 1fr) 5.2rem; align-items: center; gap: .5rem; }
.hh-bar-lab { font-size: .8rem; color: var(--muted); font-weight: 600; white-space: nowrap; }
.hh-bar-val { font-size: .85rem; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hh-track { position: relative; height: 1.7rem; background: var(--bg); border-radius: 6px; }
.hh-seg {
  position: absolute; top: 0; bottom: 0;
  border-right: 2px solid var(--card); border-radius: 4px;
  cursor: pointer;
}
.hh-seg:focus-visible { outline: 2px solid var(--text); outline-offset: 1px; }
.hh-zero { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text); }
.hh-seg.s-lvt, .sw.s-lvt { background: var(--lvt); }
.hh-seg.s-bld, .sw.s-bld { background: var(--tx-bld); }
.hh-seg.s-income, .sw.s-income { background: var(--pit); }
.hh-seg.s-gains, .sw.s-gains { background: var(--tx-gains); }
.hh-seg.s-sales, .sw.s-sales { background: var(--tx-sales); }
.hh-seg.s-rentRise, .sw.s-rentRise { background: var(--bad); }
.hh-seg.s-indirect, .sw.s-indirect {
  background: repeating-linear-gradient(45deg, var(--muted) 0 3px, transparent 3px 5px);
}
#hh-tip { min-height: 1.3em; margin: .35rem 0 0; }

/* The per-tax table: exact numbers, and a small diverging bar for the change. */
.hh-table { width: 100%; border-collapse: collapse; margin-top: .7rem; font-size: .82rem; font-variant-numeric: tabular-nums; }
.hh-table th, .hh-table td { padding: .3rem .25rem; text-align: right; border-bottom: 1px solid var(--border); white-space: nowrap; }
.hh-table th[scope=row], .hh-table thead th:first-child { text-align: left; white-space: normal; font-weight: 500; }
.hh-table thead th { font-size: .72rem; color: var(--muted); font-weight: 600; }
.hh-table tr.sub th, .hh-table tr.sub td { color: var(--muted); font-size: .76rem; padding-left: .8rem; }
.hh-table tr.tot th, .hh-table tr.tot td { font-weight: 700; border-bottom: none; }
.hh-chw { display: inline-flex; align-items: center; justify-content: flex-end; gap: .35rem; }
.hh-mini { position: relative; display: inline-block; width: 2.6rem; height: .55rem; flex: none; }
.hh-mini::after { content: ''; position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--border); }
.hh-mini i { position: absolute; top: 0; bottom: 0; border-radius: 3px; background: var(--muted); }
.hh-ch.less .hh-mini i, .hh-mini i.less { background: var(--lvt); }
.hh-ch.more .hh-mini i, .hh-mini i.more { background: var(--pit); }

/* Across your plans: one row per plan on one diverging scale. */
.hh-plans { display: flex; flex-direction: column; gap: .3rem; }
.hh-plan { display: grid; grid-template-columns: minmax(0, 1fr) 6rem 5.4rem; align-items: center; gap: .5rem; font-size: .85rem; }
.hh-plan.on .hh-plan-name { font-weight: 700; }
.hh-plan-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hh-plan-val { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hh-mini.wide { width: 100%; height: .7rem; }
@media (min-width: 620px) { .hh-plan { grid-template-columns: minmax(0, 1fr) 12rem 6rem; } }

/* The share dialog: the household box, then the link field. */
.share-hh { margin: .2rem 0 .7rem; }
.share-hh em { font-style: normal; color: var(--muted); }
.share-row { display: flex; gap: .4rem; margin: 0 0 .9rem; }
.share-url {
  flex: 1; min-width: 0; height: 2.5rem; padding: 0 .55rem;
  font: inherit; font-size: 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text);
}
@media (max-width: 419px) {
  /* A phone's table has no room for the change bars; the numbers carry it. */
  .hh-table .hh-mini { display: none; }
  .hh-tiles { gap: .35rem; }
  .hh-tile { padding: .45rem .45rem; }
}
