/* ============================================================================
   Tax pages — /market/taxes/check and /market/taxes/ohio.

   Staged as a /v2 preview beside the originals, compared live, and promoted
   over them on 4 Sep 2026; the previous design is in git history. The brief:
   an audience that is typically 55+, on phones as often as desktops, reading
   about money they are worried about.

   The rules this file exists to enforce:
   - nothing under 1rem, body copy at 1.14rem on a 1.7 line;
   - one column, top to bottom — no grids that reflow, no reveal animation,
     nothing that moves or appears late;
   - controls at least 3.5rem tall with visible labels and the example in
     helper text, never in a placeholder (a placeholder reads as a value
     already entered, and vanishes the moment you click);
   - the answer before the reasoning, and the reasoning in sentences.

   Everything reads the b.css tokens, so both themes come for free.
   ========================================================================== */

.v2{font-size:1.0625rem}
.v2 .shell{max-width:52rem}

/* ------------------------------- header -------------------------------- */
.v2-hero{margin-bottom:2.6rem}
.v2-hero .eyebrow{font-size:1rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--fern-light);margin-bottom:.9rem}
.v2-hero h2{font-size:clamp(2.1rem,5.2vw,3.1rem);line-height:1.12;
  letter-spacing:-.015em;color:var(--text-strong);margin:0 0 1.1rem;
  text-wrap:balance}
.v2-hero .v2-lede{font-size:clamp(1.14rem,2vw,1.28rem);line-height:1.65;
  color:var(--text-soft);max-width:38rem;margin:0}
/* A second paragraph, set back a step: the first says the surprising thing,
   this one says what the site is. One size for both made the hero read as a
   wall and buried the sentence that has to land. */
.v2-hero .v2-lede-sub{font-size:1.08rem;color:var(--text-softer);
  margin-top:1.4rem}
/* The answer a page opens with, above its lede (the Ohio grid, 6 Oct
   2026): a paragraph of its own, so it needs the gap the lede has none of. */
.v2-hero .v2-answer{margin-bottom:1rem}

/* ---------------------- the hero's worked example ----------------------- */
/* Two bars, real money, no axis. The sentence this replaced asked a reader
   to hold a 1976 law, a rate cut, a pass-through share and their own school
   district in their head at once, and the fact underneath all four is a
   comparison — the bill rises by less than the value did. A comparison is a
   length, and the second bar being shorter than the first says it before
   anybody reads a word. */
.worked{margin:1.7rem 0 1.9rem;padding:1.25rem 1.35rem 1.15rem;
  border:1px solid var(--edge);border-radius:14px;max-width:38rem}
.worked .setup{font-size:1.04rem;line-height:1.55;color:var(--text-soft);
  margin:0 0 1.05rem}
.worked .setup strong{color:var(--text-strong);font-weight:600}
.worked ul{list-style:none;margin:0;padding:0;display:grid;gap:.75rem}
.worked li{display:grid;grid-template-columns:minmax(0,11rem) 1fr auto;
  align-items:center;gap:.3rem .9rem}
.worked .lbl{font-size:1rem;color:var(--text-soft)}
.worked .track{display:flex;height:1.55rem;border-radius:6px;overflow:hidden}
.worked .fill{display:block;height:100%;width:var(--w)}
.worked .fill.val{background:var(--warm)}
.worked .fill.bill{background:var(--fern-light)}
/* The stretch that did NOT happen. Faint rather than absent: the gap is the
   law doing its job, and a bar that simply stops shows the shortfall without
   naming a cause. */
.worked .ghost{flex:1;height:100%;background:var(--fern-light);opacity:.17}
.worked .delta{font-family:"Inter var",Inter,sans-serif;
  font-variant-numeric:tabular-nums;font-weight:600;font-size:1.1rem;
  color:var(--text-strong);min-width:3.4rem;text-align:right}
.worked figcaption{font-size:1rem;line-height:1.6;color:var(--muted-dark);
  margin-top:1.05rem}
.worked figcaption strong{color:var(--text-soft);font-weight:600}
@media (max-width:640px){
  /* Label over bar: at 375px an 11rem label column leaves the bars too short
     to compare, which is the one thing they exist to do. */
  .worked li{grid-template-columns:1fr auto}
  .worked .lbl{grid-column:1/-1}
  .worked .track{height:1.35rem}
}
.v2-trust{display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;list-style:none;
  margin:1.6rem 0 0;padding:0}
.v2-trust li{font-size:1rem;color:var(--text-soft);display:flex;
  align-items:baseline;gap:.5rem}
.v2-trust li::before{content:"✓";color:var(--fern-light);font-weight:700}

/* -------------------------------- cards -------------------------------- */
.v2-card{background:var(--surface-raise);border:1px solid var(--line);
  border-radius:18px;padding:clamp(1.4rem,4vw,2.4rem);margin-bottom:1.6rem}
.v2-card>h3{font-size:1.45rem;line-height:1.3;color:var(--text-strong);
  margin:0 0 1.1rem;text-wrap:balance}
.v2-card p{font-size:1.14rem;line-height:1.7;color:var(--text-soft);
  margin:0 0 1rem}
.v2-card p:last-child{margin-bottom:0}
.v2-card strong{color:var(--text-strong);font-weight:600}

/* -------------------------------- form ---------------------------------- */
.v2-form .field{margin:0 0 1.7rem}
.v2-form label{display:block;font-size:1.1rem;font-weight:600;
  color:var(--text-strong);margin-bottom:.5rem;line-height:1.4}
.v2-form .opt{font-weight:400;color:var(--muted-dark)}
.v2-form input,.v2-form select{display:block;width:100%;min-height:3.5rem;
  font:inherit;font-size:1.3rem;color:var(--text-strong);
  background:transparent;border:1.5px solid var(--edge);border-radius:12px;
  padding:.7rem 1rem}
.v2-form select{cursor:pointer}
.v2-form select option,.v2-form select optgroup{color:#1D1D1A;background:#F4F1EA}
.v2-form input:focus-visible,.v2-form select:focus-visible{
  outline:3px solid var(--fern-glow);outline-offset:2px}
.v2-form .hint{font-size:1rem;line-height:1.55;color:var(--muted-dark);
  margin:.55rem 0 0}
.v2-form .hint strong{color:var(--text-soft)}
/* Money fields get a fixed $ so nobody wonders whether to type one. */
.v2-money{display:block;position:relative}
.v2-money input{padding-left:2.1rem}
.v2-money::before{content:"$";position:absolute;left:1rem;top:.98rem;
  font-size:1.3rem;color:var(--muted-dark)}

.v2-btn{display:flex;align-items:center;justify-content:center;width:100%;
  min-height:3.6rem;font:inherit;font-size:1.15rem;font-weight:600;
  letter-spacing:.01em;color:var(--ink);background:var(--fern-glow);
  border:0;border-radius:999px;padding:.9rem 2rem;cursor:pointer;
  transition:filter .2s}
.v2-btn:hover{filter:brightness(1.06)}
.v2-btn:focus-visible{outline:3px solid var(--text-strong);outline-offset:3px}
.v2-after{font-size:1rem;color:var(--muted-dark);margin:.9rem 0 0;
  text-align:center}

.v2-error{border:1.5px solid var(--fall);border-radius:14px;
  padding:1.1rem 1.3rem;margin-bottom:1.6rem;background:var(--surface-raise)}
.v2-error p{font-size:1.14rem;line-height:1.6;color:var(--text-strong);margin:0}
.v2-error p::before{content:"⚠ ";color:var(--fall)}

/* ------------------------------ the verdict ----------------------------- */
.v2-verdict{border:1px solid var(--edge);background:var(--surface-raise);
  border-radius:20px;padding:clamp(1.6rem,4.5vw,2.6rem);margin-bottom:1.6rem}
.v2-verdict .kicker{font-size:1rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--fern-light);margin:0 0 .6rem}
.v2-verdict .fig{font-family:"Inter var",Inter,sans-serif;
  font-size:clamp(1.9rem,5.5vw,2.9rem);font-weight:640;line-height:1.15;
  color:var(--text-strong);font-variant-numeric:tabular-nums;margin:0 0 .4rem;
  letter-spacing:-.01em}
.v2-verdict .fig em{font-style:normal;font-size:.55em;font-weight:450;
  color:var(--text-soft)}
.v2-verdict p{font-size:1.14rem;line-height:1.7;color:var(--text-soft);
  margin:.8rem 0 0}
.v2-verdict strong{color:var(--text-strong)}
.v2-monthly{font-size:1.2rem;color:var(--text-strong)}

/* --------------------------- comparison rows ---------------------------- */
.v2-rows{display:flex;flex-direction:column;gap:.9rem;margin:1.2rem 0}
.v2-row{display:flex;justify-content:space-between;align-items:baseline;
  gap:1.2rem;border:1px solid var(--line);border-radius:14px;
  padding:1rem 1.3rem}
.v2-row .what{font-size:1.08rem;line-height:1.5;color:var(--text-soft)}
.v2-row .what small{display:block;font-size:1rem;color:var(--muted-dark)}
.v2-row b{font-family:"Inter var",Inter,sans-serif;font-size:1.65rem;
  font-weight:620;color:var(--text-strong);white-space:nowrap;
  font-variant-numeric:tabular-nums}

/* --------------------------- results plumbing --------------------------- */
.v2-result h3{font-size:1.45rem;line-height:1.3;color:var(--text-strong);
  margin:0 0 1rem;text-wrap:balance}
.v2-note{font-size:1rem;line-height:1.6;color:var(--muted-dark);margin:1rem 0 0}
.v2-note a,.v2-card a,.v2-verdict a,.v2-qa a{color:var(--fern-light);
  text-decoration:underline;text-underline-offset:2px}
/* A button is a button inside a card too. `.v2-card a` (a class and an
   element) outranks every `.btn-*` colour (a class alone), so any link styled
   as a button came out fern-green and underlined — unreadable on Facebook's
   blue, and merely wrong on "Send another link" and "Your account", which it
   had been doing unnoticed (18 Sep 2026). Each variant restated, not just the
   one that was spotted. */
.v2-card a.btn{text-decoration:none}
.v2-card a.btn-solid{color:var(--ink)}
.v2-card a.btn-line{color:var(--bone)}
.v2-card a.btn-fb{color:#FFFFFF}
.v2-card a.btn-google{color:#1F1F1F}

/* The where-your-money-goes block reuses the ts-* markup from market.css;
   these bring its type up to the v2 floor. */
.v2 .tax-split{margin-top:0;border:0;padding:0}
.v2 .ts-lead{font-size:1.14rem;line-height:1.7}
.v2 .ts-legend span,.v2 .ts-note{font-size:1rem}
.v2 .ts-cat{font-size:1.08rem}
.v2 .ts-cat em{font-size:.98rem}
.v2 .ts-amt strong{font-size:1.12rem}
.v2 .ts-levies summary{font-size:1.05rem;padding:.6rem 0;cursor:pointer}
.v2 .ts-levies td{font-size:1.02rem;line-height:1.55}
.v2 .tax-split h4{font-size:1.45rem;color:var(--text-strong)}
.v2 .ts-detail h5{font-size:1.15rem}

/* --------------------------- what you can do ---------------------------- */
.v2-actions{display:flex;flex-direction:column;gap:1rem;margin:1.2rem 0 0}
.v2-action{border:1px solid var(--line);border-radius:14px;
  padding:1.2rem 1.4rem}
.v2-action h4{font-size:1.18rem;color:var(--text-strong);margin:0 0 .45rem}
.v2-action p{font-size:1.08rem;line-height:1.65;color:var(--text-soft);margin:0}

/* ------------------------------ ohio: v2 -------------------------------- */
.v2-short{border:1px solid var(--edge);border-radius:20px;
  background:var(--surface-raise);padding:clamp(1.5rem,4vw,2.4rem);
  margin:0 0 2.8rem}
.v2-short h3{font-size:1.3rem;color:var(--text-strong);margin:0 0 1.1rem}
.v2-short ol{list-style:none;margin:0;padding:0;display:flex;
  flex-direction:column;gap:1rem;counter-reset:short}
.v2-short li{position:relative;padding-left:2.6rem;font-size:1.16rem;
  line-height:1.65;color:var(--text-soft);counter-increment:short}
.v2-short li::before{content:counter(short);position:absolute;left:0;top:.15rem;
  width:1.8rem;height:1.8rem;border-radius:50%;background:var(--fern-glow);
  color:var(--ink);font-size:1.02rem;font-weight:650;display:flex;
  align-items:center;justify-content:center}
.v2-short strong{color:var(--text-strong)}

.v2-qa{max-width:44rem}
/* b.css gives every <section> the page-level padding-block; these are
   sections of an article. Same undo the essay layout carries. */
.v2-qa section{padding:2.6rem 0 0;margin-top:2.6rem;
  border-top:1px solid var(--line)}
.v2-qa section:first-child{padding-top:0;margin-top:0;border-top:0}
.v2-qa h3{font-size:clamp(1.4rem,3.2vw,1.75rem);line-height:1.25;
  color:var(--text-strong);margin:0 0 1.1rem;text-wrap:balance}
.v2-qa p{font-size:1.16rem;line-height:1.72;color:var(--text-soft);
  margin:0 0 1.05rem}
.v2-qa strong{color:var(--text-strong);font-weight:600}
.v2-qa .v2-aside{border-left:3px solid var(--fern-light);padding:.2rem 0 .2rem 1.2rem;
  margin:1.4rem 0;font-size:1.08rem;line-height:1.65;color:var(--text-soft)}

/* The worked example, set as the receipt it is. */
.v2-receipt{border:1px solid var(--edge);border-radius:16px;max-width:26rem;
  padding:1.4rem 1.5rem;margin:1.5rem 0;background:var(--surface-raise)}
.v2-receipt div{display:flex;justify-content:space-between;gap:1rem;
  align-items:baseline;padding:.55rem 0;font-size:1.08rem;
  color:var(--text-soft);border-bottom:1px dashed var(--line)}
.v2-receipt div:last-child{border-bottom:0;padding-top:.8rem}
.v2-receipt b{font-family:"Inter var",Inter,sans-serif;font-weight:620;
  color:var(--text-strong);font-variant-numeric:tabular-nums;
  white-space:nowrap}
.v2-receipt div:last-child b{font-size:1.35rem}
.v2-receipt .cap{display:block;border:0;font-size:1rem;color:var(--muted-dark);
  padding:.7rem 0 0;line-height:1.55}

/* Distribution chart reuse (dist-* from market.css), scaled up. */
.v2 .dist-label,.v2 .dist-n{font-size:1rem}
.v2 .essay-fig{margin:1.5rem 0}
.v2 .essay-fig figcaption{font-size:1.05rem;color:var(--text-strong)}
.v2 .essay-caption{font-size:1rem;line-height:1.6;color:var(--muted-dark)}

/* Numbered how-to steps (the challenge section). */
.v2-numsteps{list-style:none;margin:1.2rem 0;padding:0;display:flex;
  flex-direction:column;gap:1.1rem;counter-reset:ns}
.v2-numsteps li{position:relative;padding-left:2.9rem;font-size:1.12rem;
  line-height:1.68;color:var(--text-soft);counter-increment:ns}
.v2-numsteps li::before{content:counter(ns);position:absolute;left:0;top:.1rem;
  width:2rem;height:2rem;border-radius:50%;border:1.5px solid var(--fern-light);
  color:var(--fern-light);font-weight:650;display:flex;align-items:center;
  justify-content:center;font-size:1.02rem}

/* An unnumbered sibling of .v2-numsteps: these are three things that can
   happen, not three steps in an order. Same type and rhythm, a marker that
   does not imply a sequence. */
.v2-ul{list-style:none;margin:1.2rem 0;padding:0;display:flex;
  flex-direction:column;gap:.9rem}
.v2-ul li{position:relative;padding-left:1.6rem;font-size:1.12rem;
  line-height:1.68;color:var(--text-soft)}
.v2-ul li::before{content:"";position:absolute;left:.2rem;top:.72rem;
  width:.5rem;height:.5rem;border-radius:50%;background:var(--fern-light)}
.v2-ul strong{color:var(--text-strong)}

.v2-cta{border:1px solid var(--edge);border-radius:20px;text-align:center;
  background:var(--surface-raise);padding:clamp(1.8rem,5vw,2.8rem);
  margin-top:3rem}
.v2-cta h3{font-size:1.5rem;color:var(--text-strong);margin:0 0 .7rem}
.v2-cta p{font-size:1.1rem;line-height:1.65;color:var(--text-soft);
  margin:0 0 1.4rem}
.v2-cta .v2-btn{max-width:24rem;margin-inline:auto}

/* Subnav pills, sized up for the v2 pages only. */
.v2 .subnav a{font-size:1rem;padding:.65rem 1.35rem}
/* The topic buttons take their own padding, not the pill's: they are wider
   labels in a squarer shape, and a button whose text touches its own border
   does not read as a button. This held .1rem a side while they were
   underlined text, which is why the current one looked shrink-wrapped the
   moment they grew edges. Loads after market.css, so it is the tie-breaker
   on purpose — and any change to the row's padding belongs here, not there. */
.v2 .subnav.taxes-tabs a{padding:.72rem 1.05rem}

/* ------------------------------- print ---------------------------------- */
.v2-print{display:inline-flex;align-items:center;gap:.5rem;font:inherit;
  font-size:1rem;color:var(--text-soft);background:transparent;
  border:1px solid var(--edge);border-radius:999px;padding:.55rem 1.2rem;
  cursor:pointer;margin-top:1.2rem}
.v2-print:hover{color:var(--text-strong);border-color:var(--edge-strong)}
@media print{
  .nav-wrap,.progress,.subnav,.v2-form-wrap,.v2-print,
  .v2-hero .v2-trust,footer,.foot{display:none !important}
  .on-dark.market{background:#fff !important;color:#111 !important;
    padding-top:0 !important}
  .v2-card,.v2-verdict,.v2-row,.v2-action{border-color:#bbb !important;
    background:#fff !important;color:#111 !important;break-inside:avoid}
  .v2 *{color:#111 !important}
}

/* ------------------------------ small screens --------------------------- */
@media(max-width:640px){
  .v2-row{flex-direction:column;align-items:flex-start;gap:.35rem}
  .v2-row b{font-size:1.5rem}
  .v2-verdict .fig{font-size:1.75rem}
}
/* Motion: the v2 pages ship none of the reveal choreography, and the one
   transition they do have is trivial — but respect the setting anyway. */
@media(prefers-reduced-motion:reduce){
  .v2 *{transition:none !important}
}

/* The special-assessment checkbox on the district step. A native checkbox
   at readable size beside its whole label — the same reasoning as the
   delinquency page's filters: a checkbox is what says "optional fact",
   and this audience gets a full-size target. */
.v2-check label{display:flex;gap:.7rem;align-items:flex-start;cursor:pointer;
  font-size:1.02rem;line-height:1.55}
.v2-check input{width:1.25rem;height:1.25rem;margin-top:.2rem;flex:none;
  accent-color:var(--fern-glow)}
.v2-check .hint{margin-top:.45rem}

/* ---------------------- the saved-analysis header ----------------------- */
/* b.css lays .sec-head out as a two-column band above 900px and right-aligns
   the lede against the heading. That works on a wide market page; inside the
   52rem v2 shell it leaves a narrow column of ragged-left text beside a
   ragged-right one. This page is read top to bottom like the rest of the
   promoted design, so it gets one column and one alignment. */
.v2.share-page .sec-head{grid-template-columns:1fr;gap:1.1rem}
.v2.share-page .sec-head .lede{justify-self:start;text-align:left}


/* ------------------------------ the Ohio hub ---------------------------- */
/* One call in the hero. It carried a second, to the housing data, which
   cut on 8 Sep 2026 — this page has one job and the market pages are
   in the bar above it. .v2-btn is the check form's full-width submit
   everywhere else, so the width is overridden here rather than weakened
   where it earns its size. */
.hub-actions{display:flex;flex-wrap:wrap;gap:.8rem;margin:1.8rem 0 0}
.hub-actions .v2-btn{width:auto;font-size:1.08rem;min-height:3.3rem}
.hub-actions .btn{display:inline-flex;align-items:center;min-height:3.3rem;
  border-radius:999px;padding:.9rem 1.6rem}
/* The hub's tiles sit under a v2 hero rather than the market pages' own
   header, which already carries the space below it. */
.v2 .tiles{margin:2.4rem 0 clamp(30px,4vw,52px)}


/* ----------------------------- the county map --------------------------- */
/* Three fills, one per rung of the cycle, and the outline colour is --ink so
   it flips with the theme: dark hairlines between pale counties on the dark
   page, cream ones on the light. The fills are the chart palette's amber,
   fern and blue, deepened for light mode where a pale wash on cream stops
   reading as a colour at all. */
.ohmap{margin:0 0 clamp(28px,3.6vw,48px);display:grid;gap:1.2rem;
  grid-template-columns:minmax(0,1.15fr) minmax(258px,1fr);align-items:center}
.ohmap svg{display:block;width:100%;height:auto;max-height:78vh}
.ohmap path{stroke:var(--ink);stroke-width:1.6;stroke-linejoin:round}
.ohmap .y-now,.ohmap .y-now-upd{fill:#E4B363}
/* This year's counties, split by what they are actually getting. The
   reappraisal is the heavier event, so it takes the heavier tone of the
   same hue — one colour family, because both are "your turn is now". */
.ohmap .y-now-reap{fill:#C6762E}
.ohmap .y-1{fill:#8FBCA4}
.ohmap .y-2{fill:#7FA8D4}
.ohmap .y-3{fill:#B48EC7}
.ohmap .y-none{fill:var(--muted-dark)}
.ohmap path:hover{stroke:var(--text-strong);stroke-width:2.6}
:root[data-theme="light"] .ohmap .y-now,
:root[data-theme="light"] .ohmap .y-now-upd{fill:#C88E33}
:root[data-theme="light"] .ohmap .y-now-reap{fill:#9C4F14}
:root[data-theme="light"] .ohmap .y-1{fill:#5E9B7B}
:root[data-theme="light"] .ohmap .y-2{fill:#5286BE}
:root[data-theme="light"] .ohmap .y-3{fill:#8E62A8}

/* The wave: six years, one ramp. Sequential rather than categorical because
   the values are years — amber for the county being repriced now, cooling
   through fern to blue for the one that waits until 2031. Read the legend
   top to bottom and it is a gradient, which is the point. */
.ohmap .r-2026{fill:#F0C078}
.ohmap .r-2027{fill:#D9A45E}
.ohmap .r-2028{fill:#B9A672}
.ohmap .r-2029{fill:#8FBCA4}
.ohmap .r-2030{fill:#6E9EB5}
.ohmap .r-2031{fill:#5C7FC0}
:root[data-theme="light"] .ohmap .r-2026{fill:#D89A2C}
:root[data-theme="light"] .ohmap .r-2027{fill:#B87C2A}
:root[data-theme="light"] .ohmap .r-2028{fill:#8E8B45}
:root[data-theme="light"] .ohmap .r-2029{fill:#54916F}
:root[data-theme="light"] .ohmap .r-2030{fill:#3B7E96}
:root[data-theme="light"] .ohmap .r-2031{fill:#3A5FA8}
.ohmap figcaption{align-self:center}
.ohmap-key{list-style:none;margin:0 0 1rem;padding:0;display:flex;
  flex-direction:column;gap:.7rem}
.ohmap-key li{display:flex;align-items:baseline;gap:.6rem;font-size:1.05rem;
  color:var(--text-soft)}
.ohmap-key li::before{content:"";width:1rem;height:1rem;border-radius:4px;
  flex:0 0 auto;border:1px solid var(--edge)}
.ohmap-key .y-now::before,.ohmap-key .y-now-upd::before{background:#E4B363}
.ohmap-key .y-now-reap::before{background:#C6762E}
.ohmap-key .y-1::before{background:#8FBCA4}
.ohmap-key .y-2::before{background:#7FA8D4}
.ohmap-key .y-3::before{background:#B48EC7}
.ohmap-key .r-2026::before{background:#F0C078}
.ohmap-key .r-2027::before{background:#D9A45E}
.ohmap-key .r-2028::before{background:#B9A672}
.ohmap-key .r-2029::before{background:#8FBCA4}
.ohmap-key .r-2030::before{background:#6E9EB5}
.ohmap-key .r-2031::before{background:#5C7FC0}
:root[data-theme="light"] .ohmap-key .y-now::before,
:root[data-theme="light"] .ohmap-key .y-now-upd::before{background:#C88E33}
:root[data-theme="light"] .ohmap-key .y-now-reap::before{background:#9C4F14}
:root[data-theme="light"] .ohmap-key .y-1::before{background:#5E9B7B}
:root[data-theme="light"] .ohmap-key .y-2::before{background:#5286BE}
:root[data-theme="light"] .ohmap-key .y-3::before{background:#8E62A8}
:root[data-theme="light"] .ohmap-key .r-2026::before{background:#D89A2C}
:root[data-theme="light"] .ohmap-key .r-2027::before{background:#B87C2A}
:root[data-theme="light"] .ohmap-key .r-2028::before{background:#8E8B45}
:root[data-theme="light"] .ohmap-key .r-2029::before{background:#54916F}
:root[data-theme="light"] .ohmap-key .r-2030::before{background:#3B7E96}
:root[data-theme="light"] .ohmap-key .r-2031::before{background:#3A5FA8}
.ohmap-key li span{color:var(--text-strong);font-weight:600}
/* The count never breaks mid-phrase: "28" on one line and "counties" on the
   next reads as a different number. The label may wrap; this may not. */
.ohmap-key li .n{color:var(--text-soft);font-weight:400;white-space:nowrap}
.ohmap figcaption p{font-size:1rem;line-height:1.6;color:var(--muted-dark);
  margin:0}
@media (max-width:760px){
  .ohmap{grid-template-columns:1fr}
  /* The hover readout is the only way to identify a county, and there is no
     hover on a phone — so the map becomes the picture and the lists below
     do the identifying. */
  .ohmap figcaption p{display:none}
}

/* The view toggle and its one-line explanation, above the map. Two plain
   links, not a control: each view is its own URL, so a reader can share the
   one they are looking at and the edge can cache both. */
.ohmap-head{grid-column:1/-1;margin-bottom:.4rem}
.ohmap-views{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:.9rem}
.ohmap-views a{font-size:1rem;color:var(--muted-dark);border:1px solid var(--edge);
  border-radius:999px;padding:.5rem 1.1rem;text-decoration:none;
  transition:color .2s,border-color .2s}
.ohmap-views a:hover{color:var(--text-strong);border-color:var(--edge-strong)}
.ohmap-views a[aria-current]{color:var(--ink);background:var(--text-strong);
  border-color:var(--text-strong)}
.ohmap-what{font-size:1.05rem;line-height:1.6;color:var(--text-soft);
  margin:0;max-width:64ch}
.ohmap-what strong{color:var(--text-strong)}

/* The cycle sentence sits under the saved page's lede as a second
   paragraph of the same voice — a touch quieter, since the lede above it
   is what the page IS and this is context for it. */
.v2 .lede-cycle{margin-top:.9rem;color:var(--muted-dark)}
.v2 .lede-cycle strong{color:var(--text-soft)}


/* ============================ the Ohio hub ============================== */
/* Written for a reader in their sixties who has never had property tax
   explained to them and is holding a letter. Bigger type than the rest of
   the section, generous tap targets, and every section headed with the
   question it answers rather than the noun it covers. */
.v2.hub .v2-card p{font-size:1.17rem;line-height:1.72}
.v2.hub .v2-card > h3{font-size:clamp(1.5rem,2.6vw,1.85rem)}
/* Subheads inside a card. Scoped to .hub while the hub was the only page
   with them, which left every h4 on the schools page and in the terms
   sitting flush against its own paragraph — the browser's default top
   margin collapses into the paragraph above and there is nothing to
   separate a heading from the text it heads. */
.v2 .v2-card h4{font-size:1.28rem;color:var(--text-strong);
  margin:2rem 0 .6rem}

/* On this page. A long page on a phone is fine if there is a way in. */
.hub-jump{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center;
  margin:0 0 clamp(28px,3.4vw,44px)}
.hub-jump > span{font-size:.95rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted-dark);margin-right:.3rem}
.hub-jump a{font-size:1.02rem;color:var(--text-soft);text-decoration:none;
  border:1px solid var(--edge);border-radius:999px;padding:.6rem 1.1rem;
  transition:color .2s,border-color .2s,background .2s}
.hub-jump a:hover,.hub-jump a:focus-visible{color:var(--ink);
  background:var(--text-strong);border-color:var(--text-strong)}

/* The door at the foot of every card, and the fix for the page's real
   problem: the summaries were being read as the whole answer, because a
   trailing text link looks like a footnote rather than a way out. So each
   card ends with the same bar — a tag saying what kind of thing is on the
   other side, the destination's own name (from app/topics.py, so it is
   word-for-word the button for that page in the tab row above), and what
   that page has that a summary cannot. */
.hub-next{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:.5rem 1rem;margin-top:1.8rem;padding:.95rem 1.15rem;
  border:1px solid var(--edge);border-radius:12px;
  transition:border-color .2s,background .2s}
.v2-card a.hub-next{text-decoration:none;color:inherit}
.hub-next:hover,.hub-next:focus-visible{border-color:var(--fern-light);
  background:rgba(143,188,164,.09)}
.hub-next .tag{font-size:.72rem;letter-spacing:.13em;text-transform:uppercase;
  font-weight:700;color:var(--ink);background:var(--fern-light);
  border-radius:999px;padding:.32rem .62rem;white-space:nowrap}
.hub-next .txt{font-size:1.05rem;line-height:1.45;color:var(--text-soft)}
/* Name over description rather than "name — description": the blurbs are
   sentence fragments and read wrong with a capital after a dash, and this is
   the same two-line shape the footer's buttons use. */
.hub-next .txt strong{display:block;color:var(--text-strong);font-weight:600;
  font-size:1.1rem}
.hub-next .txt .what{font-size:.98rem;color:var(--muted-dark)}
.hub-next .arw{font-size:1.35rem;line-height:1;color:var(--fern-light)}
@media (max-width:640px){
  /* The tag onto its own line rather than squeezing the sentence into
     nothing: at 375px three columns leave the middle about 12 characters. */
  .hub-next{grid-template-columns:1fr auto;gap:.5rem .8rem}
  .hub-next .tag{grid-column:1/-1;justify-self:start}
}

.v2.hub .hub-aside{background:none;border-style:dashed}
.v2.hub .hub-aside p{font-size:1.08rem}

/* ------------------- where every $100 of a bill goes -------------------- */
/* A bar per category rather than a pie: pies cannot be read to two decimal
   places, cannot be labelled on a phone, and the question here is "how much
   bigger is schools than everything else", which is a length. Bars are
   drawn relative to the largest, so the lead category fills the row. */
.bill-split{list-style:none;margin:1.6rem 0 1.8rem;padding:0;display:grid;
  gap:.55rem}
.bill-split li{display:grid;grid-template-columns:minmax(0,15rem) 1fr auto;
  align-items:center;gap:.9rem}
.bill-split .what{font-size:1.08rem;color:var(--text-soft)}
/* Dollars under each spending bar (26 Sep 2026): the total, then per student. */
.bill-split .what small{display:block;font-size:.84rem;color:var(--text-softer);margin-top:.1rem}
.bill-split .bar{display:block;height:1.5rem;border-radius:5px;
  background:var(--line-faint)}
.bill-split .bar i{display:block;height:100%;width:var(--w);border-radius:5px;
  background:var(--fern-light);opacity:.55}
.bill-split .amt{font-family:"Inter var",Inter,sans-serif;
  font-variant-numeric:tabular-nums;font-size:1.12rem;font-weight:600;
  color:var(--text-strong);min-width:4.6rem;text-align:right}
.bill-split .is-lead .what,.bill-split .is-lead .amt{color:var(--text-strong)}
.bill-split .is-lead .what{font-weight:600}
.bill-split .is-lead .bar i{background:#E4B363;opacity:1}
:root[data-theme="light"] .bill-split .bar{background:rgba(20,20,18,.07)}
:root[data-theme="light"] .bill-split .bar i{background:#3A6B52;opacity:.5}
:root[data-theme="light"] .bill-split .is-lead .bar i{background:#C88E33;
  opacity:1}
@media (max-width:640px){
  /* Label above, bar and amount below: three columns at 375px leaves the
     bar too short to compare and the label wrapping to three lines. */
  .bill-split li{grid-template-columns:1fr auto;gap:.3rem .9rem}
  .bill-split .what{grid-column:1/-1}
  .bill-split .bar{height:1.25rem}
}

/* --------------------- the schools map, four bands --------------------- */
/* Light green to red, the counties map's own four colours (Property Tax
   Report, 26 Sep 2026): one scale across the section, so a colour reads
   the same way on every map — green the smaller share of a bill, red the
   larger. It was one green hue in four steps until then. */
.ohmap.schools .sc-1{fill:#A9D3A6}
.ohmap.schools .sc-2{fill:#E2D46B}
.ohmap.schools .sc-3{fill:#E5944A}
.ohmap.schools .sc-4{fill:#D6514D}
.ohmap-key .sc-1::before{background:#A9D3A6}
.ohmap-key .sc-2::before{background:#E2D46B}
.ohmap-key .sc-3::before{background:#E5944A}
.ohmap-key .sc-4::before{background:#D6514D}
:root[data-theme="light"] .ohmap.schools .sc-1{fill:#9CCB98}
:root[data-theme="light"] .ohmap.schools .sc-2{fill:#D9C74A}
:root[data-theme="light"] .ohmap.schools .sc-3{fill:#D9832F}
:root[data-theme="light"] .ohmap.schools .sc-4{fill:#C4413D}
:root[data-theme="light"] .ohmap-key .sc-1::before{background:#9CCB98}
:root[data-theme="light"] .ohmap-key .sc-2::before{background:#D9C74A}
:root[data-theme="light"] .ohmap-key .sc-3::before{background:#D9832F}
:root[data-theme="light"] .ohmap-key .sc-4::before{background:#C4413D}
/* Tappable like the counties map: each county opens its own page. */
.ohmap.schools a,.ohmap.sheriff a{outline:none;cursor:pointer}
.ohmap.schools a:hover path,.ohmap.sheriff a:hover path{filter:brightness(1.18)}
.ohmap.schools a:focus-visible path,.ohmap.sheriff a:focus-visible path{stroke:var(--text-strong);stroke-width:3.2}
/* Sheriff sales by county (22 Oct 2026): the schools map's four colours,
   green for fewer homes set for sale against Ohio's rate and red for more,
   each its own rule like the schools map's (tests/test_ohio_hub.py reads
   those one by one). The Ohio page's copy is smaller, its heading in the
   caption. */
.ohmap.sheriff .sc-1{fill:#A9D3A6}
.ohmap.sheriff .sc-2{fill:#E2D46B}
.ohmap.sheriff .sc-3{fill:#E5944A}
.ohmap.sheriff .sc-4{fill:#D6514D}
:root[data-theme="light"] .ohmap.sheriff .sc-1{fill:#9CCB98}
:root[data-theme="light"] .ohmap.sheriff .sc-2{fill:#D9C74A}
:root[data-theme="light"] .ohmap.sheriff .sc-3{fill:#D9832F}
:root[data-theme="light"] .ohmap.sheriff .sc-4{fill:#C4413D}
.ohmap.sheriff{margin:0}
.ohmap-lede{font-size:1.02rem;line-height:1.55;color:var(--text-soft);margin:0 0 1rem}
/* Side by side only where there is room: on a phone the smaller copy
   stacks like every map (it had kept two columns and shrunk to a thumbnail,
   23 Oct 2026). */
@media (min-width:761px){
  .ohmap.is-compact{grid-template-columns:minmax(0,.85fr) minmax(240px,1fr)}
}
.ohmap.is-compact svg{max-height:26rem}
.ohmap.is-compact h4{margin:0 0 .5rem;font-size:1.24rem}
.ohmap.is-compact .ohmap-key li{font-size:.98rem}
.ohmap figcaption p.ohmap-note{margin:0 0 .6rem}
/* A county page's own county (23 Oct 2026), outlined over its neighbours. */
.ohmap .here-outline{fill:none;stroke:var(--text-strong);stroke-width:6;
  stroke-linejoin:round;pointer-events:none}
.ohmap figcaption p.ohmap-here{font-size:1.02rem;line-height:1.55;color:var(--text-soft);margin:0 0 .8rem}
/* A phone hides a map's caption lines, which are hover hints elsewhere;
   these two say what the colours measure and what they miss. */
@media (max-width:760px){
  .ohmap figcaption p.ohmap-lede,.ohmap figcaption p.ohmap-note,.ohmap figcaption p.ohmap-here{display:block}
}
/* The county list under the Ohio door's schools map, inside its card. */
.ohio-pick{margin:1.8rem 0 2rem}

/* ------------------- reappraisal vs update, side by side ---------------- */
/* The difference a homeowner can picture is whether anybody comes and
   looks, so the two are set as a pair and read across rather than down. A
   single sentence in the map's caption made the reader hold two abstract
   processes in a clause each. */
.two-kinds{display:grid;gap:1.2rem;grid-template-columns:1fr 1fr;
  margin:1.3rem 0 .4rem}
.two-kinds > div{border:1px solid var(--edge);border-radius:12px;
  padding:1.1rem 1.15rem}
.two-kinds .kind-when{display:block;font-size:.74rem;letter-spacing:.13em;
  text-transform:uppercase;font-weight:700;color:var(--fern-light);
  margin-bottom:.35rem}
.v2 .two-kinds h4{margin:0 0 .5rem;font-size:1.22rem}
.two-kinds p{margin:0}
@media (max-width:720px){
  /* Stacked, because two columns at 375px give each about 20 characters
     and the pairing is carried by the eyebrows either way. */
  .two-kinds{grid-template-columns:1fr;gap:.9rem}
}

/* The tapped county's dates, under the map. Empty and unstyled until the
   script fills it, so it takes no space on a page whose script is blocked —
   and it is the same sentence the desktop tooltip shows, read out of the
   same <title>. */
.ohmap-readout{margin:.7rem 0 0;font-size:1.02rem;line-height:1.55;
  color:var(--text-strong);min-height:0}
.ohmap-readout.on{padding:.7rem .9rem;border:1px solid var(--fern-light);
  border-radius:10px;background:rgba(143,188,164,.09)}
/* The tapped county keeps the map's fill and gains an edge, so the answer
   below is anchored to a shape the reader can see they chose. */
.ohmap path.is-picked{stroke:var(--text-strong);stroke-width:3.2}
/* The tapped county's link (7 Oct 2026), on a map whose counties are
   links: the figure first, then the way to the county. */
.ohmap-readout a{color:var(--fern-light);font-weight:600;white-space:nowrap;
  text-underline-offset:.16em}

/* ------------------------ the taxing-district picker ------------------- */
/* A radio list rather than a <select>, because the state's own district name
   has to be legible BESIDE the choice: three of 45414's options read
   VANDALIA-BUTLER CSD and differ only inside an abbreviation, and an
   <option> cannot carry a second line.

   Everything here is scoped under .v2-form on purpose. That form styles its
   own labels `display:block` and its own inputs `width:100%;min-height:3.5rem`
   — sensible for a money field, and it silently flattened this control:
   the radio stretched to full width and the two lines laid out side by side,
   which is the one thing the control exists to avoid. Unscoped rules lost on
   specificity and the layout looked like a bug in the markup. */
.v2-form .district-pick{border:0;padding:0;margin:0 0 1.7rem}
.v2-form .district-pick legend{font-size:1.1rem;font-weight:600;
  color:var(--text-strong);padding:0;margin-bottom:.3rem;line-height:1.4}
/* Every cell placed explicitly. Auto-placement with a row-spanning input put
   the radio on its own line even once the display was fixed. */
.v2-form .district-row{display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:.05rem .75rem;padding:.55rem .6rem;border-radius:9px;cursor:pointer;
  margin-bottom:0;font-weight:400}
.v2-form .district-row input{grid-column:1;grid-row:1/4;align-self:center;
  width:1.2rem;min-width:1.2rem;height:1.2rem;min-height:0;margin:0;
  padding:0;border:0;border-radius:50%;accent-color:var(--fern)}
.v2-form .district-row .dr-main{grid-column:2;grid-row:1;font-size:1.05rem;
  font-weight:600;color:var(--text-strong);line-height:1.35}
.v2-form .district-row .dr-sub{grid-column:2;grid-row:2;font-size:.92rem;
  color:var(--muted-dark);line-height:1.4}
/* The state's name for the district, to hold against the bill's. */
.v2-form .district-row .dr-name{grid-column:2;grid-row:3;margin-top:.15rem;
  font-size:.85rem;color:var(--muted-dark);line-height:1.4;
  overflow-wrap:anywhere}
.v2-form .district-row:hover{background:rgba(143,188,164,.09)}
.v2-form .district-row:has(input:checked){background:rgba(143,188,164,.16);
  outline:1px solid var(--fern-light)}
/* The district questions, one per screen (13 Sep 2026). A short list of
   big rows — at most a school system's worth, never a county's — so no
   scroll box, no filter and no group headings. */
.v2-form .pick-list{display:grid;gap:.35rem;margin-top:.75rem}
.v2-form .pick-list .district-row{border:1px solid var(--edge);
  padding:.8rem .85rem}
.v2-form .pick-actions{display:flex;flex-wrap:wrap;gap:.8rem 1.4rem;
  align-items:center;margin-top:.4rem}
/* "I'm not sure" is a way out, not a second answer, so it reads as a link. */
.v2-form .v2-skip{background:none;border:0;padding:.4rem 0;min-height:0;
  font:inherit;font-size:1rem;color:var(--fern-light);text-decoration:underline;
  text-underline-offset:3px;cursor:pointer;width:auto}
.v2-form .v2-skip:hover{color:var(--text-strong)}
.v2-form .v2-skip:focus-visible{outline:2px solid var(--fern-light);
  outline-offset:3px;border-radius:4px}
/* Every other school system in the county, folded away but one tap off. */
.v2-form .pick-more{margin:.7rem 0 1.2rem}
.v2-form .pick-more summary{cursor:pointer;padding:.55rem 0;font-size:1rem;
  color:var(--fern-light);text-decoration:underline;text-underline-offset:3px}
.v2-form .pick-more summary:focus-visible{outline:2px solid var(--fern-light);
  outline-offset:3px;border-radius:4px}
/* The district the answers settled on, before the figures are shown. */
.v2-form .pick-found{margin:0 0 1.4rem;padding:.8rem .95rem;border-radius:10px;
  background:rgba(143,188,164,.1);border:1px solid var(--edge);line-height:1.5}
.v2-form .pick-found .pf-name{display:block;margin-top:.2rem;font-size:.92rem;
  color:var(--muted-dark)}

/* ---------- the share block: two cards, two posts ----------
   One page advertises one og:image, so the levy ladder lives at ?card=levy
   and each card gets its own button set here. Grid + gap rather than
   per-element margins, so the two boxes cannot drift apart. */
.share-head{font-size:1.35rem;margin:3rem 0 .9rem}
.share-cards{display:grid;gap:1.1rem;grid-template-columns:1fr}
@media (min-width:820px){.share-cards{grid-template-columns:1fr 1fr}}
.share-one{border:1px solid var(--line);border-radius:14px;
  background:var(--surface-raise);padding:.9rem .9rem 1.1rem;min-width:0;
  display:flex;flex-direction:column;gap:.7rem}
/* The thumbnail IS the card, at whatever width the column gives it. The
   width/height attributes are there so the box is reserved before it
   loads; without height:auto they win and it renders 630px tall. */
.share-thumb{display:block;width:100%;height:auto;border-radius:8px;
  border:1px solid var(--line-faint)}
.share-one h4{font-size:1.12rem;margin:0}
.share-one .post-text{white-space:pre-line;font-size:.95rem;line-height:1.6;
  color:var(--text-soft);margin:0;
  /* A pasted URL has no spaces and would otherwise push the column past
     its grid track on a phone. */
  overflow-wrap:anywhere}
.share-one .share-actions{margin-top:auto;gap:.5rem}
/* Four full-size buttons in a half-width column wrapped onto three ragged
   lines. They are secondary to the card above them, so: a smaller size. */
.share-one .share-actions .btn{padding:.62rem 1rem;font-size:.92rem;
  min-height:0}
.share-actions-common{margin-top:1rem}
@media print{
  /* A Board of Revision packet does not need the share machinery. */
  .share-cards,.share-actions,.share-actions-common,.share-head{display:none}
}

/* ---------- the slip: the statement at the top of a check ----------
   Pale paper on the dark page, because before/now/difference is a shape
   this audience has read off the county's own envelope for decades. It is
   a statement and must never read as an imitation of an official bill —
   hence no seal, no auditor marks, and a plain caption naming us.

   Fixed light tokens, not theme tokens: this surface is paper in both
   themes, so its text colours cannot follow the page's. */
.slip{--paper:#FAF7F2;--paper-ink:#1D1D1A;--paper-soft:#3D3C35;
  --paper-quiet:#5E5D55;--paper-rule:rgba(29,29,26,.28);--paper-up:#965F19;
  --paper-down:#2F6B4F;
  background:var(--paper);color:var(--paper-ink);border-radius:8px;
  margin:0 0 1.4rem;padding:1.15rem 1.25rem 1.35rem;position:relative;
  box-shadow:0 20px 40px -24px rgba(0,0,0,.55);
  font-variant-numeric:tabular-nums}
/* A torn top edge, drawn: it says "statement" without saying "official". */
.slip:before{content:"";position:absolute;left:0;right:0;top:0;height:6px;
  border-radius:8px 8px 0 0;opacity:.14;
  background:repeating-linear-gradient(90deg,var(--paper-ink) 0 6px,
    transparent 6px 12px)}
.slip-head{font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--paper-quiet);margin:0 0 .2rem}
.slip-head strong{color:var(--paper-ink)}
.slip-grp{font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--fern);margin:1rem 0 0;font-weight:600}
:root[data-theme="light"] .slip-grp{color:#2F6B4F}
.slip-ln{display:flex;justify-content:space-between;align-items:baseline;
  gap:.75rem;margin:0;padding:.45rem 0;font-size:1.05rem;
  color:var(--paper-soft);border-bottom:1px dotted var(--paper-rule)}
.slip-ln b{font-family:"Inter var",Inter,sans-serif;font-size:1.2rem;
  font-weight:600;color:var(--paper-ink);white-space:nowrap}
.slip-ln b.up{color:var(--paper-up)}
.slip-ln b.down{color:var(--paper-down)}
/* The line the statement exists for: ruled off, and bigger. */
.slip-tot{border-bottom:0;border-top:2px solid var(--paper-ink);
  margin-top:.35rem;padding-top:.7rem;font-weight:600;
  color:var(--paper-ink)}
.slip-tot b{font-size:1.6rem}
.slip-sub{display:flex;justify-content:flex-end;margin:.1rem 0 0;
  font-size:1rem;color:var(--paper-soft)}
.slip-sub b{font-family:"Inter var",Inter,sans-serif;color:var(--paper-ink);
  margin-left:.35rem}
/* The stamp. Rotated and outlined so it reads as a rubber stamp rather
   than as another data row — it is a judgement, not a figure. */
.slip-stamp{display:block;width:max-content;max-width:100%;
  margin:1.15rem auto .1rem;padding:.5rem .9rem;
  border:3px solid var(--paper-up);border-radius:8px;color:var(--paper-up);
  font-size:.85rem;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;text-align:center;transform:rotate(-3deg)}
.slip-stamp.is-inline,.slip-stamp.is-slower,.slip-stamp.is-already,
.slip-stamp.is-same{
  border-color:var(--paper-down);color:var(--paper-down)}
@media (prefers-reduced-motion:reduce){.slip-stamp{transform:none}}
@media print{
  /* Where these pages end up: a Board of Revision packet, in black and
     white, on one sheet. */
  .slip{box-shadow:none;border:1px solid #000}
  .slip:before{display:none}
}

/* The small print, under the statement instead of in front of it. */
.slip-note{font-size:.95rem;line-height:1.6;color:var(--text-softer);
  margin:0 0 .8rem;max-width:62ch}
.slip-note strong{color:var(--text-soft)}
.slip-turn{display:flex;gap:.55rem;align-items:baseline;margin:1.5rem 0 0;
  font-size:1.08rem;color:var(--text-strong)}
.slip-turn span{color:var(--fern-light);font-size:1.3rem;line-height:1}
.v2-print-row{display:flex;flex-wrap:wrap;gap:.6rem;margin:1.4rem 0 2.4rem}
@media print{.slip-turn,.v2-print-row{display:none}}
/* The fresh-check link inside the small print was rendering as plain grey
   text — a link nobody could see was a link. */
.slip-note a,.not-advice a{color:var(--fern-light);text-decoration:underline;
  text-decoration-color:var(--fern-light);text-underline-offset:.18em}
:root[data-theme="light"] .slip-note a,:root[data-theme="light"] .not-advice a{color:#2F6B4F;
  text-decoration-color:#2F6B4F}
/* The district the bill fits better, in the estimate's place (14 Sep
   2026). Each row is a fresh check one press away. */
.slip-doubt p{margin:0 0 .8rem}
.doubt-list{list-style:none;padding:0;margin:0 0 1rem;display:grid;gap:.5rem}
.doubt-list li{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:.6rem 1rem;padding:.75rem .85rem;
  border:1px solid var(--edge);border-radius:10px;overflow-wrap:anywhere}
.doubt-list form{margin:0}
.doubt-btn{font:inherit;font-size:1rem;font-weight:600;color:var(--ink);
  background:var(--fern-glow);border:0;border-radius:999px;
  min-height:2.75rem;padding:.55rem 1.2rem;cursor:pointer}
.doubt-btn:hover{filter:brightness(1.06)}
.doubt-btn:focus-visible{outline:3px solid var(--text-strong);outline-offset:3px}
/* "Is this your new value after all?" under a page that read "no new value
   yet" from the bill (15 Sep 2026): one press to the forecast. */
.slip-override{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1rem}

/* ---------- the numbered walk-through ----------
   The four steps are a real sequence of reasoning — what changed, why,
   where it goes, what you can do — so they are numbered. The county
   context between 3 and 4 is not a step and gets no number. */
.v2-step{display:flex;align-items:baseline;gap:.7rem;margin:2.6rem 0 .9rem;
  font-size:1.06rem;font-weight:600;letter-spacing:-.01em;
  color:var(--text-strong)}
.v2-step span{display:inline-grid;place-items:center;width:1.85rem;
  height:1.85rem;border-radius:50%;background:var(--fern);color:var(--bone);
  font-family:"Inter var",Inter,sans-serif;font-size:.92rem;flex:none}
:root[data-theme="light"] .v2-step span{background:#2F6B4F;color:#FAF7F2}
.v2-step-plain{color:var(--text-softer);font-weight:500;font-size:.95rem;
  letter-spacing:.08em;text-transform:uppercase;margin-top:3rem}

/* Step 2's three bars: the reader's rise, the rise the cut is calculated
   on, and where the bill lands between them. */
.why-bars{list-style:none;margin:1.2rem 0 1.4rem;padding:0}
.why-bars li{margin:0 0 1rem}
.why-bars .lbl{display:block;font-size:.78rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--text-softer);margin-bottom:.4rem}
.why-bars .track{display:block;height:1.75rem;border-radius:6px;
  background:var(--line-faint);overflow:hidden}
.why-bars .fill{display:block;height:100%;width:var(--w);border-radius:6px}
.why-bars .fill.mine{background:var(--warm)}
.why-bars .fill.area{background:var(--muted-dark)}
.why-bars .fill.bill{background:var(--fern-light)}
.why-bars .delta{display:block;margin-top:.3rem;
  font-family:"Inter var",Inter,sans-serif;font-size:1.15rem;font-weight:600;
  color:var(--text-strong)}
@media (min-width:620px){
  .why-bars li{display:grid;grid-template-columns:1fr 4.5rem;
    grid-template-areas:"lbl lbl" "track delta";gap:0 .9rem;
    align-items:center}
  .why-bars .lbl{grid-area:lbl}
  .why-bars .track{grid-area:track}
  .why-bars .delta{grid-area:delta;margin:0;text-align:right}
}


/* ---------- the saved analysis: chrome that scrolls away ----------
   The site banner and the menu pill are position:fixed everywhere else.
   On the one page most people reach from a shared link they took the top
   third of every phone screen, above a statement that needs the room.
   Absolute keeps their place at the top and lets the page carry them off;
   the opened menu (.menu) stays fixed, as it must. */
.page-share .site-banner,.page-share .nav-wrap{position:absolute}
.page-share .tabbar{display:none}
.page-share .keep-reading{margin-top:3.5rem}

/* ---------- "Does this match your bill?" (16 Sep 2026) ---------- */
.fb{margin:1.2rem 0 .3rem;padding:1rem 1.1rem;border:1px solid var(--edge);
  border-radius:12px}
.fb p{margin:0}
.fb-q{margin:0 0 .6rem}
.fb-note{display:block;font-size:.95rem}
.fb-note textarea{display:block;width:100%;margin-top:.4rem;padding:.6rem .7rem;
  font:inherit;font-size:1rem;color:inherit;background:transparent;
  border:1px solid var(--edge);border-radius:8px;resize:vertical}
.fb-note textarea:focus-visible{outline:3px solid var(--text-strong);outline-offset:2px}
.fb-btns{display:flex;flex-wrap:wrap;gap:.6rem;margin:.8rem 0 .6rem}
.fb-no{background:var(--warm)}
.fb .hint{margin-top:.2rem}
.cant-see ul{margin:.6rem 0 .8rem 1.1rem;padding:0;display:grid;gap:.45rem}

/* ---------- the saved analysis, v2 layout (16 Sep 2026) ----------
   The page is six numbered parts with one way to move between them: a
   rail beside the column on a wide screen, a Previous / Next bar pinned
   to the top of a phone with the list folded behind the current part's
   name. Both are the same <nav class="parts">; the breakpoint is 1000px
   here and in tax-share.js — change both. Everything is a plain anchor
   link, and b.js already smooth-scrolls those. */
.share-v2 .shell-parts{max-width:52rem}
.parts-grid{display:grid;grid-template-columns:minmax(0,1fr)}
.parts-main{min-width:0}
/* An anchor lands under the pinned bar, never behind it. The site-wide
   .anchor offset is for the floating nav pill, which scrolls away here. */
.share-v2 .anchor{scroll-margin-top:calc(var(--parts-h,0px) + 1.25rem)}

/* Part headings: an h2 in the walk-through's step style, a little larger
   than the step markers were — it is the heading now, not a label. */
.part-head{font-size:1.2rem;margin-top:3rem}
.part-head span{width:2rem;height:2rem;font-size:.98rem}
.part-no{display:inline-grid;place-items:center;width:1.85rem;height:1.85rem;
  border-radius:50%;background:var(--fern);color:var(--bone);
  font-family:"Inter var",Inter,sans-serif;font-size:.92rem;font-weight:600;
  font-style:normal;flex:none}
:root[data-theme="light"] .part-no{background:#2F6B4F;color:#FAF7F2}
.share-lede{font-size:1.14rem;line-height:1.7;color:var(--text-soft);
  margin:0 0 1.1rem;max-width:62ch}

/* "Next · 3 Where every dollar goes", at the foot of each part: the
   linear reader's rhythm, and a second way to the next part that needs
   no bar at all. */
.part-next{display:flex;align-items:center;gap:.55rem;width:fit-content;
  margin:-.4rem 0 .4rem auto;padding:.5rem .95rem .5rem .6rem;min-height:2.75rem;
  border:1px solid var(--edge);border-radius:999px;color:var(--text-strong);
  text-decoration:none;font-size:1rem;line-height:1.3}
.part-next:hover{border-color:var(--edge-strong);background:var(--line-faint)}
.part-next:focus-visible{outline:3px solid var(--text-strong);outline-offset:3px}
.part-next small{font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--text-softer)}
.part-top{margin-top:1.6rem}

/* The nav itself. */
.parts-kicker{font-size:.8rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-softer);margin:0 0 .6rem}
.parts-list{list-style:none;margin:0 0 1.6rem;padding:0;display:grid;gap:.25rem}
.parts-list a{display:flex;align-items:center;gap:.65rem;min-height:2.75rem;
  padding:.45rem .65rem;border-radius:10px;color:var(--text-soft);
  text-decoration:none;font-size:1rem;line-height:1.3}
.parts-list a:hover{color:var(--text-strong);background:var(--line-faint)}
.parts-list a:focus-visible{outline:3px solid var(--text-strong);outline-offset:2px}
.parts-list a .part-no{background:transparent;border:1.5px solid var(--edge);
  color:var(--text-soft)}
/* "You are here": the row fills, the number fills, the words go bold. */
.parts-list a.is-current{color:var(--text-strong);font-weight:600;
  background:rgba(143,188,164,.12)}
.parts-list a.is-current .part-no{background:var(--fern);border-color:var(--fern);
  color:var(--bone)}
:root[data-theme="light"] .parts-list a.is-current{background:rgba(47,107,79,.1)}
:root[data-theme="light"] .parts-list a.is-current .part-no{background:#2F6B4F;
  border-color:#2F6B4F;color:#FAF7F2}

/* The bar (phones and tablets, scripting on). Three big targets: the
   previous part, the current part's name — which opens the list — and
   the next part. */
.parts-bar{display:none}
.parts-step{display:grid;place-items:center;width:2.75rem;height:2.75rem;
  border:1px solid var(--edge);border-radius:999px;color:var(--text-strong);
  text-decoration:none;font-size:1.7rem;line-height:1}
.parts-step span{position:relative;top:-.08em}
.parts-step:hover{border-color:var(--edge-strong)}
.parts-step.is-off{opacity:.3;pointer-events:none}
.parts-cur{display:flex;align-items:center;justify-content:center;gap:.55rem;
  min-height:2.75rem;min-width:0;padding:.3rem .4rem;font:inherit;
  font-size:1.02rem;font-weight:600;color:var(--text-strong);background:none;
  border:0;border-radius:10px;cursor:pointer;text-align:center}
.parts-cur:hover{background:var(--line-faint)}
/* A long name wraps to a second line rather than losing its end: an
   older reader gets the whole of "Where every dollar goes". */
.parts-label{min-width:0;line-height:1.2}
.parts-caret{font-size:.85rem;color:var(--text-softer)}
.parts-cur:focus-visible,.parts-step:focus-visible{outline:3px solid var(--text-strong);
  outline-offset:2px}

@media (max-width:999.98px){
  .parts.is-live{position:sticky;top:0;z-index:60;margin:0 calc(-1 * var(--pad)) 1.2rem;
    padding:0 var(--pad);background:var(--ink);border-bottom:1px solid var(--line)}
  .parts.is-live .parts-kicker{display:none}
  .parts.is-live .parts-bar{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
    gap:.5rem;align-items:center;min-height:3.4rem}
  .parts.is-live .parts-list{display:none;position:absolute;left:0;right:0;top:100%;
    margin:0;padding:.6rem var(--pad) 1rem;background:var(--ink);
    border-bottom:1px solid var(--edge);box-shadow:0 24px 40px -20px rgba(0,0,0,.6)}
  .parts.is-live.is-open .parts-list{display:grid}
  .parts.is-live.is-open .parts-caret{transform:rotate(180deg)}
}
@media (min-width:1000px){
  .share-v2 .shell-parts{max-width:70.5rem}
  .parts-grid{grid-template-columns:15.5rem minmax(0,52rem);gap:3rem;align-items:start}
  .parts{position:sticky;top:1.5rem}
}
@media print{.parts,.part-next{display:none !important}}

/* ---------- the about page (16 Sep 2026) ---------- */
.about .v2-card ul{padding-left:1.2rem;margin:0 0 1rem}
.about .v2-card li{font-size:1.14rem;line-height:1.7;color:var(--text-soft);
  margin:0 0 .7rem}
.about .v2-card li strong{color:var(--text-strong)}
/* The section's topics, from app/topics.py, as a plain list: the page
   is prose, and the tab row is not far away. */
.about-topics{list-style:none !important;padding:0 !important;
  margin:1rem 0 1.2rem !important;display:grid;gap:.55rem}
.about-topics a{font-weight:600}
.about-topics span{color:var(--text-softer)}

/* ---------- keeping a check, and the member's own pages (17 Sep 2026) ---------- */
.keep{margin:1.6rem 0 .4rem}
.keep h3{margin-top:0}
.keep-form{margin:1rem 0 .6rem}
.keep-label{display:block;font-size:1rem;color:var(--text-soft);margin-bottom:.4rem}
.keep-row{display:flex;flex-wrap:wrap;gap:.6rem;align-items:stretch}
.keep-row input{flex:1 1 16rem;min-width:0;font:inherit;font-size:1.1rem;padding:.75rem .9rem;
  border-radius:12px;border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong)}
.keep-row input:focus-visible{outline:3px solid var(--text-strong);outline-offset:2px}
.keep-note{font-size:1rem;color:var(--text-strong);margin:.4rem 0 .6rem}
.keep .hint{margin:.4rem 0 0}
.hub-home{margin-bottom:1.6rem}
.hub-home h4{font-size:1.15rem;color:var(--text-strong);margin:1.4rem 0 .5rem}
.hub-links{display:flex;flex-wrap:wrap;gap:.6rem;margin:.9rem 0 0}
.hub-cal{list-style:none;padding:0;margin:0}
.hub-cal li{display:grid;grid-template-columns:minmax(7.5rem,10rem) 1fr;gap:.6rem 1rem;
  padding:.6rem 0;border-top:1px solid var(--line);font-size:1.08rem;line-height:1.55}
.hub-cal li:first-child{border-top:0}
.hub-when{color:var(--text-soft);font-variant-numeric:tabular-nums}
.hub-what{color:var(--text-soft)}
.hub-what strong{color:var(--text-strong)}
.hub-foot{margin-top:1.4rem;font-size:1.02rem}
.hub-row{margin:.8rem 0 .2rem}
.hub-row label{display:block;font-size:.98rem;color:var(--text-soft);margin-bottom:.35rem}
.hub-forget{margin:0 0 1.1rem}
.linklike{font:inherit;font-size:.95rem;color:var(--text-soft);background:none;border:0;
  padding:0;text-decoration:underline;cursor:pointer}
.hub-check{display:flex;gap:.6rem;align-items:flex-start;font-size:1.08rem;line-height:1.55;
  color:var(--text-soft)}
.hub-check input{margin-top:.35rem;width:1.15rem;height:1.15rem}
@media (max-width:520px){.hub-cal li{grid-template-columns:1fr}}

/* ---------- the hub's tabs, picker and figures (17 Sep 2026) ---------- */
.hub-tabs{margin-bottom:clamp(20px,2.6vw,32px)}
.hub-picker{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center;margin:0 0 1rem}
.hub-picker label{font-size:.95rem;color:var(--text-soft)}
.hub-picker select{font:inherit;font-size:1.02rem;padding:.55rem .7rem;border-radius:12px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);max-width:22rem}
.hub-picker select:focus-visible{outline:3px solid var(--text-strong);outline-offset:2px}
.hub-hero .chart{margin-top:1.2rem}
/* currentColor throughout, so the bars follow the card's text in both
   themes — the printed sheet's copy is black-on-white and cannot be. */
.hub-bars{width:100%;height:auto;display:block;margin:1rem 0 .6rem;color:var(--text-strong)}
.hub-chips{display:flex;flex-wrap:wrap;gap:.8rem;margin:.4rem 0 .2rem}
.hub-chip{flex:1 1 12rem;border:1px solid var(--line);border-radius:14px;padding:.85rem 1rem}
.hub-chip-h{display:block;font-size:.88rem;color:var(--text-soft);margin-bottom:.2rem}
.hub-chip strong{display:block;font-size:1.35rem;color:var(--text-strong);line-height:1.2}
.hub-chip-s{display:block;font-size:.92rem;color:var(--text-soft);margin-top:.15rem}
.hub-fig{width:100%;border-collapse:collapse;margin:.6rem 0 .4rem}
.hub-fig th{text-align:left;font-weight:400;color:var(--text-soft);padding:.55rem 0;
  font-size:1.06rem;border-bottom:1px solid var(--line)}
.hub-fig td{text-align:right;font-weight:500;color:var(--text-strong);padding:.55rem 0;
  font-size:1.12rem;font-variant-numeric:tabular-nums;white-space:nowrap;
  border-bottom:1px solid var(--line)}
.hub-fig tr.rule th,.hub-fig tr.rule td{border-bottom:0;border-top:1.5px solid var(--line);
  padding-top:.7rem}
@media (max-width:520px){.hub-chip{flex:1 1 100%}}

/* ---------- v2b: rate charts, the levy calculator, comparisons ---------- */
.hub-since ul{margin:.4rem 0 0;padding-left:1.1rem}
.hub-since li{font-size:1.08rem;line-height:1.6;color:var(--text-soft);margin-bottom:.4rem}
.hub-pulse{display:grid;grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));gap:1.4rem;margin-top:1rem}
.hub-tile .chart h3{font-size:1.06rem}
.hub-calc{margin:1rem 0 .6rem}
.hub-calc label{font-size:.95rem;color:var(--text-soft);align-self:center}
.hub-calc input{flex:0 1 8rem;min-width:0;font:inherit;font-size:1.1rem;padding:.7rem .8rem;
  border-radius:12px;border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong)}
.hub-calc input:focus-visible{outline:3px solid var(--text-strong);outline-offset:2px}
.hub-calc-answer{font-size:1.16rem;line-height:1.65;color:var(--text-soft);margin:.8rem 0 .4rem}
.hub-scroll{overflow-x:auto;margin:.6rem 0 .2rem}
.hub-table{width:100%;border-collapse:collapse;font-size:1.02rem}
.hub-table th,.hub-table td{padding:.6rem .7rem;border-bottom:1px solid var(--line);text-align:left}
.hub-table thead th{font-size:.86rem;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-soft);font-weight:600;white-space:nowrap}
.hub-table tbody th{font-weight:500;color:var(--text-strong)}
.hub-table .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
/* Headings that may wrap, for the tables whose columns need a phrase
   rather than a word. A header is nowrap everywhere else so a figure and
   its label stay on one line — but six columns of "Pupils per
   administrator" then set a width no card has, and the whole table goes
   behind a horizontal scroll on a desktop that had room for it. The
   numbers still never wrap; only the heading does. */
.hub-table.wrap-head thead th{white-space:normal}
/* ...and the size-band table's row labels, which are ranges, kept on one
   line for the same reason a figure is: "500-1,000" broken over two rows
   reads as two numbers. Only this table — the county one's row labels are
   district names and would set a width no card has. */
.hub-table.size-bands tbody th{white-space:nowrap}
.hub-sub{display:block;font-size:.88rem;color:var(--text-soft);font-weight:400}
/* A group's heading row inside one table: the body that charges the
   levies under it (the county Levies section, 26 Sep 2026). */
.hub-table tr.is-group th{padding-top:1.3rem;font-weight:600;color:var(--text-strong)}
.hub-table tr.is-group th .hub-sub{display:inline;margin-left:.4rem}
@media (max-width:640px){.hub-calc .keep-row{flex-direction:column;align-items:stretch}
  .hub-calc input{flex:1 1 auto}}

/* ==== v2c: the market overview's treatment, brought to the hub's figures ==
   Asked for 17 Sep 2026, of the payment card on /market: "it looks much
   better and does not blend into the page". True — the hub's charts and
   tables sat on var(--surface-raise), which is the page with the contrast
   turned up slightly, so a table of numbers read as more prose.

   This is .pay-card's panel, reused deliberately rather than approximated:
   the same opaque gradient stops, the same fern hairline, the same radius.
   Opaque, not rgba, for the reason market.css records — a translucent panel
   composites against whatever is behind it and renders as two different
   colours in the two themes while its text keeps the dark-surface tokens.

   One adaptation, made on purpose. On /market the kicker is a .72rem label
   above a huge number; here an h3 is a section heading a reader navigates
   by, and this audience is largely over 60. So the heading keeps a legible
   size and takes the family's COLOUR and letterspacing, while the .72rem
   uppercase treatment goes where /market puts it too: on the labels inside
   the figures (.tn-label is the model). */
.hub-panel{background:linear-gradient(150deg,#18251E,#191917);
  border:1px solid rgba(143,188,164,.28);border-radius:20px}
.hub-panel>h3{font-size:1.24rem;letter-spacing:.04em;color:var(--fern-glow);
  margin:0 0 1rem}
.hub-panel p{color:var(--text-soft)}
.hub-panel strong{color:var(--bone)}
/* The kicker proper, for a panel whose content IS one number. */
.hub-kicker{display:block;font-size:.78rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--fern-glow);margin-bottom:.6rem}
.hub-figure{display:block;font-size:clamp(2.1rem,4.2vw,3rem);line-height:1;
  color:var(--bone);letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.hub-figure em{font-style:normal;font-size:.42em;color:var(--muted-dark);
  letter-spacing:0}
/* .hub-panel scopes it: `.v2-card p{margin:0 0 1rem}` is one point more
   specific than a bare class and its shorthand resets margin-top to zero,
   which put the note hard against the figure's baseline. */
.hub-panel .hub-figure-note{margin:.85rem 0 0;font-size:1.02rem;
  line-height:1.6;color:var(--text-soft)}
.hub-panel .hub-figure + .hub-figure-note{margin-top:.75rem}
/* Warm is a cost rising, never green: this is a bill, not a return. The
   two hexes are market.css's .pay-up / .pay-down, same meaning. */
.hub-up{color:var(--warm)}
.hub-down{color:#8FBCA4}

/* Tables inside a panel: the label column in the kicker's small caps, the
   figures in bone and tabular so columns line up on the decimal. */
.hub-panel .hub-fig th,
.hub-panel .hub-table thead th{font-size:.74rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--muted-dark);font-weight:600;
  border-bottom-color:rgba(143,188,164,.22)}
.hub-panel .hub-fig td,
.hub-panel .hub-table td{color:var(--bone);font-variant-numeric:tabular-nums;
  letter-spacing:-.01em;border-bottom-color:rgba(143,188,164,.16)}
.hub-panel .hub-table tbody th{color:var(--text-soft);font-weight:500;
  border-bottom-color:rgba(143,188,164,.16)}
.hub-panel .hub-fig tr.rule th,
.hub-panel .hub-fig tr.rule td{border-top-color:rgba(143,188,164,.3)}
.hub-panel .hub-sub{color:var(--muted-dark)}
.hub-panel .hub-chip{border-color:rgba(143,188,164,.24)}
.hub-panel .hub-chip-h{font-size:.74rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--muted-dark)}
.hub-panel .hub-chip strong{color:var(--bone);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.hub-panel .hub-chip-s{color:var(--text-soft)}
.hub-panel .hub-calc-answer{color:var(--text-soft)}
.hub-panel .hub-calc input{background:rgba(10,10,9,.5);color:var(--bone);
  border-color:rgba(143,188,164,.3)}
.hub-panel .hub-calc label{color:var(--text-soft)}
.hub-panel .hub-bars{color:var(--bone)}
.hub-panel .gap-note{color:var(--muted-dark)}

/* ---------------- v2c: the distribution strip, the rail, the map -------- */
/* preserveAspectRatio="none" on the strip: it is a bar chart of counts, so
   stretching it horizontally is honest — the bars keep their heights and
   only their widths change with the viewport. */
.hub-strip{width:100%;height:132px;display:block;margin:1.1rem 0 .3rem}
.hub-strip .bar{fill:rgba(143,188,164,.32)}
.hub-strip .bar.mine{fill:var(--warm)}
.hub-strip .axis{stroke:rgba(143,188,164,.35);stroke-width:1}
.hub-strip .here{stroke:var(--warm);stroke-width:1;stroke-dasharray:3 3;opacity:.55}
.hub-scale{display:flex;justify-content:space-between;gap:1rem;margin:0;
  font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted-dark);font-variant-numeric:tabular-nums}
.hub-scale span:nth-child(2){letter-spacing:.08em;text-align:center}
/* On a phone the middle caption wraps to three lines and pushes the two
   end figures apart, which is the one thing the row exists to show. The
   ends carry the scale on their own. */
@media (max-width:560px){.hub-scale span:nth-child(2){display:none}}

/* The rail scrolls rather than shrinks. An 860-wide drawing squeezed into a
   360px phone puts six dates at four pixels of type, which is unreadable
   for anyone and unusable for this audience — so it keeps its size and the
   reader swipes, with the ordered list underneath saying all of it anyway. */
.hub-rail-wrap{overflow-x:auto;margin:1.1rem 0 .2rem;
  scrollbar-width:thin}
/* min-width only for a phone: at the card's own ~700px the 760 viewBox
   sits at nearly 1:1, so nothing scrolls on a desktop and nothing is
   hidden behind a scrollbar. Below ~560 the reader swipes. */
.hub-rail{display:block;min-width:560px;width:100%;height:auto;
  aspect-ratio:760/215}
.hub-rail .rail{stroke:rgba(143,188,164,.4);stroke-width:2}
.hub-rail .lead{stroke:rgba(143,188,164,.38);stroke-width:1}
.hub-rail .lead.is-next{stroke:var(--warm);stroke-width:1.5}
.hub-rail .dot{fill:#8FBCA4}
.hub-rail .dot.is-next{fill:var(--warm)}
.hub-rail .today{stroke:var(--bone);stroke-width:1;stroke-dasharray:4 3;opacity:.5}
/* Sized for the card's own scale, not the viewBox's: the SVG renders at
   about 0.87 in a 700px card, so 14px on the date lands near 12px on the
   page. This audience is largely over 60 and the first draft's 11.5px
   arrived as nine. */
.hub-rail .today-t{fill:var(--muted-dark);font-size:12px;letter-spacing:.1em;
  text-transform:uppercase}
.hub-rail .mark-w{fill:#8FBCA4;font-size:14px;font-weight:600}
.hub-rail .mark-w.is-next{fill:var(--warm)}
.hub-rail .mark-t{fill:var(--text-soft);font-size:13px}

/* The reader's own county, outlined rather than recoloured: the fill still
   has to say where it is in the cycle, which is the map's whole job.

   vector-effect is what makes the outline visible at all. stroke-width is
   in USER units, so the viewBox transform scales it: the map renders about
   340px wide from a 1000-unit box, and the first attempt's 3.5 arrived on
   screen as 1.2px — applied, computed, and invisible. non-scaling-stroke
   draws it at 3 real pixels whatever the map's size.

   No paint-order:stroke here: that paints the stroke UNDER the fill and
   halves the width you see, which is right for text and wrong for an
   outline that is the point of the drawing. county_map also renders this
   county last, so a neighbour drawn later cannot paint over its edge. */
.hub-map{margin:1.1rem 0 0}
/* Inside a min-width query on purpose. `.ohmap` and `.hub-map` are both one
   class, so source order decides — and an unconditional rule here, at the
   end of the sheet, beat the max-width:760 rule above that collapses the
   map to one column. The key's 220px minimum then squeezed the map itself
   to 49px on a phone. */
@media (min-width:761px){
  .hub-map{grid-template-columns:minmax(0,1.3fr) minmax(220px,1fr)}
}
.hub-map svg{max-height:440px}
/* The caption's prose is hidden below 760 (no hover, so it cannot help);
   this is a link, not prose, and it is the way out of the card. */
.hub-map figcaption p.hub-map-link{display:block}
.hub-map .is-mine{stroke:var(--bone);stroke-width:3;
  vector-effect:non-scaling-stroke}
:root[data-theme="light"] .hub-panel .hub-map .is-mine{stroke:#FAF7F2}

/* ---------- Facebook sign-in (18 Sep 2026) ---------- */
/* Meta's current brand blue, #0866FF, not the older #1877F2: white text on
   it is 4.8:1 against 4.2:1, so it clears WCAG AA at body size — and this
   audience reads at body size. Both colours are stated literally because the
   button is the same in both themes. */
.btn-fb{background:#0866FF;color:#FFFFFF;font-size:1.05rem;font-weight:600;
  padding:.95rem 1.8rem}
.btn-fb:hover{background:#0759DB;color:#FFFFFF;text-decoration:none}
.btn-fb:focus-visible{outline:3px solid var(--text-strong);outline-offset:3px}
.keep-or{margin:.9rem 0 .5rem;font-size:.95rem;color:var(--text-soft)}
.keep-fb-lead{font-size:1.08rem;color:var(--text-soft);margin:0 0 .8rem}

/* ---------- Google sign-in button (18 Sep 2026) ---------- */
/* Google's own light button: white, a grey hairline, near-black text, the
   multicolour G. Recognised on sight by an audience that reads plain words
   as just another link. Both colours literal: it is the same in both themes. */
.btn-google{background:#FFFFFF;color:#1F1F1F;border:1px solid #747775;
  font-size:1.05rem;font-weight:600;padding:.95rem 1.8rem}
.btn-google:hover{background:#F2F2F2;color:#1F1F1F;text-decoration:none}
.btn-google:focus-visible{outline:3px solid var(--text-strong);outline-offset:3px}
.btn-google .g-mark{flex:none;display:block}

/* ---------- Signed in, everywhere (19 Sep 2026) ---------- */
/* The `member` and `kept-here` classes come from the first script on every
   page (b/base.html), which reads what the hub told the browser — so a
   cached page, identical for everyone, still shows each reader their own
   state. Default is the stranger's view: nothing below hides anything
   unless the browser has said otherwise, so a reader with scripting off
   gets the plain, working card. */
.keep-have,.keep-member-form{display:none}
.member .keep-member-form{display:block;margin:1rem 0 .4rem}
.member .keep-anon{display:none}
.kept-here .keep-ask{display:none}
.kept-here .keep-have{display:block}
.keep-have h3{margin:0 0 .7rem}

.hub-whoami{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:.6rem 1rem;margin:0 0 1rem;font-size:.98rem;color:var(--text-soft)}
.hub-whoami strong{color:var(--text-strong);font-weight:600;word-break:break-all}
.hub-whoami .btn{padding:.55rem 1.2rem;font-size:.9rem}
.hub-whoami-actions{display:flex;flex-wrap:wrap;gap:.5rem}
.hub-rename{margin:-.2rem 0 .9rem;font-size:1rem}
.hub-rename a{color:var(--fern-light);text-underline-offset:2px}

/* Not advice, on the check itself (19 Sep 2026): after the last part, before
   "Back to Summary" — read by anyone who has reached the end, quiet enough
   not to compete with the figures above it. */
.not-advice{max-width:68ch;margin:1.8rem 0 1.2rem}

/* ==== your case: the Board of Revision tab (20 Sep 2026) ================
   One address form, a verdict, and three tables. The panels are the hub's
   own (.hub-panel, .hub-table); only the form, the picker and the two
   lists are new. */
.case-row{display:flex;gap:.8rem;align-items:flex-end;flex-wrap:wrap;margin:.9rem 0 .4rem}
.case-field{display:flex;flex-direction:column;gap:.3rem;flex:1 1 12rem;min-width:0}
.case-field.case-no{flex:0 0 7rem}
.case-field label{font-size:.86rem;color:var(--text-soft)}
.case-field input{font:inherit;padding:.7rem .8rem;border-radius:10px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);
  min-width:0}
.case-find .btn{flex:0 0 auto}
.case-miss{margin:.9rem 0 0;padding:.8rem .9rem;border-left:3px solid var(--fern-light);
  background:rgba(143,188,164,.08);border-radius:0 10px 10px 0}
.case-warn{border-color:var(--fern-light)}
.case-picks{list-style:none;padding:0;margin:.8rem 0 1rem;display:grid;gap:.6rem}
.case-picks label{display:flex;gap:.7rem;align-items:baseline;cursor:pointer;
  padding:.7rem .8rem;border:1px solid var(--line);border-radius:10px}
.case-picks label:hover{border-color:var(--fern-light)}
.case-cautions,.case-rules{margin:.6rem 0 1rem;padding-left:1.1rem;display:grid;gap:.55rem}
.case-cautions li,.case-rules li{color:var(--text-soft)}
.case-cautions strong,.case-rules strong{color:var(--text-strong)}
.case-verdict .hub-table th[scope="row"]{font-weight:400;color:var(--text-soft)}
.case-verdict .hub-table td{font-size:1.1rem;font-weight:500}
.case-subject th,.case-subject td{border-bottom-width:2px;font-weight:600}
@media (max-width:640px){.case-row{flex-direction:column;align-items:stretch}
  .case-field.case-no{flex:1 1 auto}}

/* ==== the blog (21 Sep 2026) ===========================================
   Memory Keep's shape — stated hero, two-column cards of date, reading
   time and title, then a post with its tag over a hero and the piece at a
   readable measure — in this site's theme rather than its cream and
   photography. A card with no image gets a typographic tile: this site
   has no photo library and stock images of worried homeowners would be
   worse than none. */
.blog-hero{max-width:44rem;margin:0 0 2.6rem}
.blog-hero h1{font-size:clamp(2.1rem,5vw,3.1rem);line-height:1.08;margin:.5rem 0 .8rem;
  color:var(--text-strong);letter-spacing:-.02em}
.blog-hero-sub{font-size:1.12rem;line-height:1.6;color:var(--text-soft);max-width:38rem}
.blog-grid{display:grid;gap:2rem;grid-template-columns:1fr;margin:0 0 2.4rem}
@media(min-width:820px){.blog-grid{grid-template-columns:1fr 1fr;gap:2.4rem}}
.blog-card-link{display:block;color:inherit;text-decoration:none}
.blog-card-img,.blog-card-tile{display:block;width:100%;aspect-ratio:3/2;border-radius:16px;
  border:1px solid var(--line);object-fit:cover;margin:0 0 1rem}
.blog-card-tile{background:linear-gradient(150deg,#18251E,#191917);display:grid;
  place-items:center}
.blog-card-tile span{font-size:.78rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--fern-glow)}
.blog-meta{font-size:.78rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted-dark);margin:0 0 .45rem}
.blog-card h2{font-size:1.5rem;line-height:1.25;color:var(--text-strong);margin:0 0 .5rem;
  letter-spacing:-.01em}
.blog-card-link:hover h2{color:var(--fern-light)}
.blog-card-sum{color:var(--text-soft);line-height:1.6;margin:0}
.blog-foot{color:var(--text-soft);max-width:44rem}
.blog-foot a{color:var(--fern-light);text-decoration:underline;text-underline-offset:2px}

/* the post */
.blog-post-hero{border:1px solid var(--line);border-radius:20px;padding:2.6rem 1.8rem;
  background:linear-gradient(150deg,#18251E,#191917);margin:0 0 1.2rem}
.blog-post-hero.has-image{background-size:cover;background-position:center;
  min-height:clamp(14rem,32vw,20rem);display:flex;flex-direction:column;
  justify-content:flex-end}
.blog-tag{display:inline-block;font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--fern-glow);border:1px solid rgba(143,188,164,.4);border-radius:999px;
  padding:.3rem .8rem;margin:0 0 1rem}
/* Over a picture the pill needs its own ground. The flat hero it was drawn
   for is dark everywhere; a photograph is bright exactly where the pill
   sits, and a translucent border with glow-green text disappeared into the
   sky. Same reasoning as .hero and .prop re-declaring the dark tokens in
   b.css: text on an image scrim does not sit on the page's surface. */
.blog-post-hero.has-image .blog-tag{background:rgba(10,12,11,.62);
  border-color:rgba(255,255,255,.3);color:#D8EDE0}
.blog-post-hero h1{font-size:clamp(1.9rem,4.4vw,2.9rem);line-height:1.12;margin:0;
  color:var(--bone);letter-spacing:-.02em;max-width:24ch}
.blog-crumbs{font-size:.86rem;color:var(--muted-dark);margin:0 0 1.4rem}
.blog-crumbs a{color:var(--text-soft);text-decoration:none}
.blog-crumbs a:hover{color:var(--fern-light);text-decoration:underline}
.blog-byline{font-weight:500;color:var(--text-strong);margin:0 0 1.8rem;
  padding-bottom:1.1rem;border-bottom:1px solid var(--line);max-width:40rem}
.blog-byline-sub{display:block;font-weight:400;font-size:.9rem;color:var(--muted-dark);
  margin-top:.2rem}
/* The measure lives on the prose, not on the container: a figure has to be
   able to be wider than the text it interrupts, and while .blog-body itself
   carried the 38rem the chart inside it was capped at the same width — a
   line chart at reading width is a chart nobody can read off. */
.blog-body{max-width:none;font-size:1.08rem;line-height:1.72;color:var(--text-soft)}
.blog-body > *:not(.blog-figure){max-width:38rem}
.blog-body > p:first-of-type{font-size:1.2rem;line-height:1.62;color:var(--text-strong)}
.blog-body h2{font-size:1.5rem;line-height:1.3;color:var(--text-strong);
  margin:2.4rem 0 .9rem;letter-spacing:-.01em}
.blog-body h3{font-size:1.18rem;color:var(--text-strong);margin:1.8rem 0 .6rem}
.blog-body p{margin:0 0 1.1rem}
.blog-body strong{color:var(--text-strong)}
.blog-body a{color:var(--fern-light);text-decoration:underline;text-underline-offset:2px}
.blog-body ul,.blog-body ol{margin:0 0 1.2rem;padding-left:1.3rem;display:grid;gap:.55rem}
.blog-body li{padding-left:.2rem}
.blog-body blockquote{margin:1.4rem 0;padding-left:1rem;border-left:2px solid var(--fern-light);
  color:var(--text-soft)}
/* ------------------------------- figures inside an article ------------- */
/* A figure breaks the measure. The prose is 38rem because that is where a
   line stops being comfortable; a chart at 38rem is a chart nobody can read
   off, so figures widen to 52rem and sit centred against the same left
   edge as the text they interrupt.

   The panel is .hub-panel, reused rather than reinvented: it is already in
   b.css's light-mode token pin, so these inherit the one thing a new
   fixed-dark surface always forgets. */
.blog-figure{max-width:52rem;margin:2.2rem 0;padding:1.4rem 1.3rem 1.1rem}
.blog-figure .chart-frame{background:transparent;border:0;padding:0}
.blog-figure figcaption{margin:0 0 1.1rem;max-width:44ch}
.blog-figure h3{font-size:1.24rem;line-height:1.3;color:var(--fern-glow);
  letter-spacing:.02em;margin:0 0 .4rem}
.blog-figure figcaption p{font-size:.92rem;line-height:1.55;color:var(--text-soft);
  margin:0}
.fig-source{font-size:.76rem;line-height:1.5;color:var(--muted-dark);
  margin:1.1rem 0 0;padding-top:.8rem;border-top:1px solid var(--line-faint)}

/* Ranked bars. One track per row, every fill a share of the same widest
   value — see _bar_geometry; scaling each direction to its own maximum is
   how a chart lies without anybody deciding to. */
.fig-bars ul{list-style:none;margin:0;padding:0;display:grid;gap:.5rem}
.fig-bars li{display:grid;grid-template-columns:8.5rem 1fr 4rem;
  align-items:center;gap:.4rem .8rem}
.fig-label{font-size:.92rem;color:var(--text-strong);line-height:1.25}
.fig-track{display:block;height:1.15rem;border-radius:4px;
  background:rgba(255,255,255,.05)}
.fig-track i{display:block;height:100%;width:var(--w);border-radius:4px;
  background:var(--fern-light);opacity:.62}
/* Warm for a value that fell. The rule in this codebase is that warm is a
   cost rising, never "bad news" — on a price chart a fall is the thing
   that needs marking, and it gets the same colour for the same reason:
   it is the direction the reader is not expecting. */
.fig-bars .is-down .fig-track i{background:var(--fall);opacity:.72}
.fig-value{font-family:"Inter var",Inter,sans-serif;font-size:1rem;
  font-variant-numeric:tabular-nums;color:var(--text-strong);text-align:right}
.fig-detail{grid-column:2/-1;font-size:.78rem;color:var(--muted-dark);
  font-variant-numeric:tabular-nums;margin-top:-.15rem}
.fig-gap{grid-template-columns:1fr;text-align:center;color:var(--muted-dark);
  font-size:.76rem;letter-spacing:.1em;text-transform:uppercase;
  padding:.5rem 0;border-top:1px dashed var(--line);border-bottom:1px dashed var(--line)}

/* Tables. Same small caps as every other figure header on the site. */
.fig-scroll{overflow-x:auto;position:relative}
/* A table too wide for a phone scrolls sideways — and until 23 Sep 2026
   nothing said so. The levy table clipped a rate mid-digit ("3.89") at
   the screen's edge, which reads as a wrong number rather than as a
   hidden column, and the columns carrying the argument (what goes to
   administration, pupils per administrator) were off screen entirely
   with no sign they existed.

   The answer is the one the housing section already uses for
   `.datatable`: the row's identity stays pinned so you always know what
   you are reading, a fade at the right edge says there is more, and a
   line of text says to swipe — because a fade alone is a gradient, not
   an instruction, and this audience is largely reading on a phone in a
   Facebook thread.

   Phone only. There is nothing to hint at when the table fits. */
@media(max-width:720px){
  .fig-scroll{margin-inline:calc(-1 * var(--pad));padding-inline:var(--pad)}
  /* The right edge fades, as a MASK rather than an overlay. An absolutely
     positioned pseudo-element inside a scroll container scrolls with the
     content, so the fade slid into the middle of the table the moment
     anyone swiped and dimmed a column at random. A mask paints against
     the element's own box and stays where it belongs. */
  .fig-scroll{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 20px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 20px),transparent)}
  /* `.fits` is set by b.js on the tables that do not overflow. A fade at
     the edge of a table with nothing past it dims its own last column
     and promises a swipe that goes nowhere. */
  .fig-scroll.fits{-webkit-mask-image:none;mask-image:none}
  .fig-scroll.fits table th[scope="row"],
  .fig-scroll.fits table thead th:first-child{box-shadow:none}
  /* The pinned column needs the card's colour OPAQUE, and
     `--surface-raise` is translucent in both themes — .72 over the
     section in dark, .8 in light. Painting the column with it let the
     scrolled text show straight through: "2024" sat on top of "Current
     expense". The card's appearance is that overlay composited over the
     section, and the section is exactly `--ink`, so stacking the two
     reproduces the card opaquely and keeps flipping with the theme.

     The first column is the row's name; it is what the numbers belong
     to, so it does not leave with them. */
  .fig-scroll table th[scope="row"],
  .fig-scroll table thead th:first-child{
    position:sticky;left:0;z-index:2;
    background:linear-gradient(var(--surface-raise),var(--surface-raise)),
               var(--ink);
    /* A hairline so the pinned column reads as an edge once the rest
       slides under it, rather than as text that failed to move. */
    box-shadow:1px 0 0 var(--line)}
  .fig-scroll table{font-size:.96rem}
  .fig-scroll table th,.fig-scroll table td{padding:.55rem .55rem}
}
/* The one line that tells a reader the table moves. Written into the
   page next to the table it describes, hidden above phone width where
   there is nothing to swipe. */
/* `p.fig-swipe`, not `.fig-swipe`: this is a <p> inside a .v2-card, and
   `.v2-card p` sets 1.14rem at the same specificity — a bare class lost
   and the hint rendered at body size, wrapping to two lines. */
/* ---- "Now yours": the hop to a county or a district ------------------
   Two native selects in GET forms, styled like the unpaid page's county
   picker so the section has one control idiom rather than two. No script:
   a select and a submit is the whole thing. */
.find-yours .find-row{margin:1.1rem 0 0}
.find-yours .find-row + .find-scope{margin:.55rem 0 0;font-size:.9rem;
  color:var(--text-soft)}
.find-yours .find-scope + .v2-note{margin-top:1.1rem}
.find-yours .find-row + .v2-note{margin-top:1.3rem}
.find-yours label{display:block;font-size:.82rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-soft);margin-bottom:.45rem}
.find-controls{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center}
.find-yours select{font:inherit;font-size:1rem;color:var(--text-strong);
  background:transparent;border:1px solid var(--line);border-radius:10px;
  padding:.7rem 2.2rem .7rem .85rem;min-width:16rem;flex:1 1 16rem;
  min-height:3rem;cursor:pointer;appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%238a8a80' stroke-width='1.4' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right .85rem center;
  background-size:.65rem}
.find-yours select:focus-visible{outline:2px solid var(--fern-glow);
  outline-offset:2px}
/* The options list is painted by the OS, which does not read our tokens —
   without this it renders white-on-white in dark mode on some platforms. */
.find-yours select option,.find-yours select optgroup{color:#1D1D1A;
  background:#F4F1EA}
/* Its own class, NOT .btn-apply: that one is hidden whenever scripting
   is on, because the chart controls it belongs to auto-submit on change.
   This picker deliberately does not — a phone's select fires `change` as
   the wheel turns, which would navigate away mid-scroll — so its button
   has to be there always. */
.find-yours .btn-go{align-self:center;font:inherit;font-size:.95rem;
  letter-spacing:.02em;color:var(--ink);background:var(--bone);border:0;
  border-radius:999px;padding:.7rem 1.4rem;min-height:3rem;cursor:pointer;
  white-space:nowrap}
.find-yours .btn-go:hover:not(:disabled){background:var(--fern-glow)}
/* Disabled until something is chosen — with script only, because without
   it nothing sets the state back and a permanently dead button is worse
   than one that reloads the page. */
.find-yours .btn-go:disabled{opacity:.45;cursor:default}
.find-yours .btn-go:focus-visible{outline:2px solid var(--fern-glow);
  outline-offset:3px}
@media(max-width:640px){
  .find-yours select{flex:1 1 100%;min-width:0}
  .find-yours .btn-go{flex:1 1 100%}
}

p.fig-swipe{display:none}
@media(max-width:720px){
  p.fig-swipe{display:flex;align-items:baseline;gap:.45rem;margin:.6rem 0 1.1rem;
    font-size:.92rem;line-height:1.5;color:var(--text-soft)}
  p.fig-swipe svg{width:16px;height:16px;flex:none;opacity:.75;
    transform:translateY(2px)}
  /* An author `display` beats the browser's own rule for [hidden], so
     the script setting `hidden = true` on a table that fits did nothing
     at all until this line existed. */
  p.fig-swipe[hidden]{display:none}
}
.fig-table table{width:100%;border-collapse:collapse;font-size:.95rem}
.fig-table th{font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted-dark);font-weight:500;text-align:left;padding:0 .7rem .6rem 0;
  border-bottom:1px solid var(--line)}
.fig-table td{padding:.6rem .7rem .6rem 0;color:var(--text-soft);
  border-bottom:1px solid var(--line-faint)}
.fig-table tr:last-child td{border-bottom:0}
.fig-table td:first-child{color:var(--text-strong)}
.fig-table .num{text-align:right;font-variant-numeric:tabular-nums;
  padding-right:0}
.fig-table th.num{padding-right:0}

@media (max-width:640px){
  /* Label above its own bar: three columns at 375px leaves the track too
     short to compare, which is the only thing a ranked chart is for. */
  .fig-bars li{grid-template-columns:1fr 4rem;gap:.25rem .7rem}
  .fig-label{grid-column:1/-1}
  /* Full width, not "column two onwards": with the label promoted to its
     own row, column two is the 4rem value cell, and the detail line was
     wrapping "$199,499 → $248,492" into four lines inside it. */
  .fig-detail{grid-column:1/-1;text-align:left}
  .blog-figure{padding:1.1rem 1rem .9rem}
  .fig-table table{font-size:.88rem}
}

.blog-end{max-width:38rem;margin:2.6rem 0 0;padding-top:1.6rem;border-top:1px solid var(--line)}
.blog-more-head{font-size:1.1rem;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted-dark);margin:2rem 0 .9rem}
.blog-more{list-style:none;padding:0;margin:0;display:grid;gap:1rem}
.blog-more a{display:block;color:inherit;text-decoration:none}
.blog-more-title{display:block;font-size:1.16rem;color:var(--text-strong);line-height:1.3}
.blog-more a:hover .blog-more-title{color:var(--fern-light)}

/* ------------------------ the county cards (21 Sep 2026) ------------------ */
/* The map's four bands: what homes are billed per $1,000 of taxable value.
   Light green to red, the scale everyone reads the same way without a key
   (22 Sep 2026) — the question is "is my county one of the expensive
   ones", and the answer is red. Four fixed steps, not quantiles, so a colour
   means the same rate on every visit. The card renderer does not draw this
   map shaded, so there is no Pillow twin to keep in step. */
.ohmap.bills .b-1{fill:#A9D3A6}
.ohmap.bills .b-2{fill:#E2D46B}
.ohmap.bills .b-3{fill:#E5944A}
.ohmap.bills .b-4{fill:#D6514D}
.ohmap-key .b-1::before{background:#A9D3A6}
.ohmap-key .b-2::before{background:#E2D46B}
.ohmap-key .b-3::before{background:#E5944A}
.ohmap-key .b-4::before{background:#D6514D}
/* Links wrap the paths so a click works without script; the outline they
   draw on focus is the map's own picked stroke, not a browser box around a
   county-shaped hole. Hover lifts the county a shade, so a pointer learns
   the map is tappable before the text says so. */
.ohmap.bills a{outline:none;cursor:pointer}
.ohmap.bills a:hover path{filter:brightness(1.18)}
.ohmap.bills a:focus-visible path{stroke:var(--text-strong);stroke-width:3.2}
/* The tap hint: the one line that tells a phone the map is a control.
   Strong, in the accent, with a pointer beside it — a figcaption's muted
   grey read as a footnote and was missed (22 Sep 2026). */
.ohmap figcaption p.ohmap-tap{display:flex;align-items:flex-start;gap:.55rem;
  font-size:1.05rem;color:var(--text-strong);line-height:1.45}
.ohmap figcaption p.ohmap-tap svg{flex:0 0 auto;width:1.3rem;height:1.3rem;
  margin-top:.15rem;color:var(--fern-light)}
/* .ohmap path strokes every path in the figure in the page's ink — the
   county borders — which made the pointer invisible on its own background. */
.ohmap figcaption p.ohmap-tap path{stroke:currentColor;stroke-width:1.9;fill:none}
.ohmap-tap strong{color:var(--fern-light);font-weight:600}
/* The other maps hide their caption on a phone because hover is their only
   readout; this map's readout is the tap, so its hint stays. */
@media (max-width:760px){
  .ohmap figcaption p.ohmap-tap{display:flex}
}

/* The panel a tapped county fills. Sits between the map and the prose; a
   figure, so it takes the panel treatment via .hub-panel inside. */
.cty-pop{position:relative;margin:0 0 1.6rem}
.cty-close{position:absolute;top:.6rem;right:.7rem;z-index:1;width:2.2rem;height:2.2rem;
  border-radius:50%;border:1px solid rgba(143,188,164,.35);background:rgba(10,12,11,.7);
  color:#FAF7F2;font-size:1.4rem;line-height:1;cursor:pointer}
.cty-close:hover{border-color:var(--fern-glow)}

.cty-card{padding:1.5rem 1.4rem 1.3rem;max-width:52rem}
.cty-card .hub-kicker{margin-bottom:.35rem}
.cty-name{font-size:clamp(1.6rem,3.2vw,2.2rem);color:var(--bone);margin:0 0 1.1rem;
  letter-spacing:-.02em}
.cty-facts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1.1rem 1.6rem;
  margin:0 0 1.1rem}
.cty-facts dt{font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted-dark);margin:0 0 .25rem}
.cty-facts dd{margin:0;color:var(--bone)}
.cty-facts dd strong{font-size:clamp(1.5rem,3vw,2rem);letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;font-weight:600}
.cty-unit{font-size:1rem;color:var(--text-soft);margin-left:.25rem}
.cty-note{display:block;font-size:.88rem;color:var(--text-soft);margin-top:.15rem}
.cty-reset,.cty-unpaid{color:var(--text-soft);margin:0 0 .5rem;font-size:1.02rem}
.cty-reset strong{color:var(--bone)}
.cty-source{font-size:.78rem;line-height:1.5;color:var(--muted-dark);
  margin:.9rem 0 1rem;padding-top:.8rem;border-top:1px solid rgba(143,188,164,.16)}
.cty-share{display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1rem;margin:0}
.cty-link{font-size:.86rem;color:var(--text-soft);word-break:break-all;
  text-decoration:underline;text-underline-offset:2px}
/* The 88-county list keeps its names plain; the Schools section's money
   table does not, so its drill-down reads as links, like the spending table
   beside it (25 Sep 2026). */
.cty-table:not(.cty-revenue) th[scope=row] a{color:var(--text-strong);text-decoration:none}
.cty-table:not(.cty-revenue) th[scope=row] a:hover{color:var(--fern-light);text-decoration:underline}
/* A state star rating as five stars, the rating's count filled
   (Property Tax Report, 25 Sep 2026). The empty ones are the same glyph
   outlined, so filled and empty are one shape in every font. */
.stars{white-space:nowrap;letter-spacing:.08em;font-size:1.05em;line-height:1}
.stars-on{color:var(--star)}
.stars-off{color:transparent;-webkit-text-stroke:1px var(--star)}
.hub-table .stars{font-size:.95em;letter-spacing:.02em}
.stars-half{color:transparent;-webkit-text-stroke:1px var(--star);
  background:linear-gradient(90deg,var(--star) 50%,transparent 50%);
  -webkit-background-clip:text;background-clip:text}
/* The overall rating under a district's name: a link to its scores. */
.overall-rating{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .6rem;
  margin:.2rem 0 .9rem;color:var(--text-soft);text-decoration:none;font-size:1rem}
.overall-rating .stars{font-size:1.35rem}
.overall-rating .overall-text{text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--line)}
.overall-rating:hover .overall-text{text-decoration-color:currentColor}
.rating-list{list-style:none;margin:.4rem 0 1rem;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));gap:.35rem 1.2rem}
.rating-list li{display:flex;justify-content:space-between;gap:.8rem;align-items:baseline;
  padding:.35rem 0;border-bottom:1px solid var(--line)}
.rating-list li.is-overall{font-weight:600}
.rating-list small{display:block;color:var(--text-softer);font-weight:400}
/* The county Schools section's dollar headline (26 Sep 2026). */
.cty-headline{font-size:1.12rem;line-height:1.6;color:var(--text-strong)}
/* A school year is one token: "2025-26", never "2025-" over "26". */
.score-year{white-space:nowrap}
.cty-neighbours,.cty-towns{color:var(--text-soft)}
.cty-neighbours a,.cty-towns a{color:var(--fern-light);text-decoration:underline;text-underline-offset:2px}
@media (max-width:640px){
  .cty-facts{grid-template-columns:1fr;gap:.9rem}
  .cty-card{padding:1.2rem 1rem 1.1rem}
}
/* Light mode keeps the same four steps a shade deeper, as the schools map
   does: the palest green vanished on cream. */
:root[data-theme="light"] .ohmap.bills .b-1{fill:#9CCB98}
:root[data-theme="light"] .ohmap.bills .b-2{fill:#D9C74A}
:root[data-theme="light"] .ohmap.bills .b-3{fill:#D9832F}
:root[data-theme="light"] .ohmap.bills .b-4{fill:#C4413D}
.cty-share .post-text[hidden]{display:none}
/* The change lines take the bill palette: warm for a value rising, fern
   for falling. Stated with both classes because .cty-note alone sets the
   colour later in the file and was winning the tie. */
.cty-note.hub-up,.cty-reset .hub-up{color:var(--warm)}
.cty-note.hub-down,.cty-reset .hub-down{color:#8FBCA4}

/* The bridge between the total and its two cuts: spans both columns of the
   facts grid, in the kicker's small caps, so the pair beneath it reads as
   two views of one number rather than two numbers. */
.cty-bridge{grid-column:1/-1;font-size:.78rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--fern-glow);margin:.2rem 0 -.3rem;padding-top:.6rem;
  border-top:1px solid rgba(143,188,164,.16)}
/* Two complete splits of one total (21 Sep 2026). Each row is a full-width
   bar whose two segments are the two halves, with both figures under it —
   so a row adds up to the total by itself, and one row cannot be added to
   the other. The idiom is .bill-split's: a track, a fill that is a length. */
.cty-splits{margin:.2rem 0 1.1rem;display:grid;gap:1rem}
.cty-splits .cty-bridge{margin:0;padding-top:.6rem;border-top:1px solid rgba(143,188,164,.16)}
.cty-split-head{font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted-dark);margin:0 0 .4rem}
.cty-split-bar{display:flex;height:1.1rem;border-radius:5px;overflow:hidden;
  background:rgba(255,255,255,.12)}
.cty-split-bar i{display:block;height:100%;width:var(--w);background:var(--fern-light);
  opacity:.85}
.cty-split-ends{display:flex;justify-content:space-between;gap:1.2rem;margin-top:.45rem;
  font-size:.95rem;color:var(--text-soft);line-height:1.35}
.cty-split-ends .b{text-align:right}
.cty-split-ends strong{font-size:1.25rem;color:var(--bone);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;font-weight:600}
.cty-split-ends small{display:block;font-size:.8rem;color:var(--muted-dark);margin-top:.15rem;
  max-width:28ch}
.cty-split-ends .b small{margin-left:auto}
/* The state's leg, one line under the schools' split: the other money
   these districts run on, and where the state gets it. Full width — it is
   a sentence, not a column note — and the soft text colour, because it is
   a different denominator: a budget, not the bill. */
.cty-state-line{font-size:.9rem;color:var(--text-soft);line-height:1.45;margin:.55rem 0 0}
/* The county's rank among the 88: the line a reader quotes, so it is the
   one line on the card set in the accent, bold and a size up
   (22 Sep 2026). Stated with both classes to beat .cty-note's colour. */
.cty-note.cty-rank{font-size:1.08rem;font-weight:600;color:var(--warm);margin-top:.3rem}
.cty-revenue{margin-top:.6rem;font-size:.95rem}
.cty-revenue th,.cty-revenue td{padding:.5rem .45rem}
/* Seven columns in a 40rem card: the uppercase headers set the widths, so
   they may wrap to two lines while the figures beneath stay on one. */
.cty-revenue thead th.num{white-space:normal;vertical-align:bottom}
.cty-revenue tbody th{min-width:9rem}
/* The income-tax mark: a dagger after the name, explained under the table.
   A badge in the cell pushed the last three columns off the card. */
.cty-flag{text-decoration:none;color:var(--text-soft);margin-left:.15rem;
  font-size:.85em;vertical-align:super;line-height:0}
.cty-state .cty-source{margin-top:.8rem}
@media (max-width:640px){
  .cty-split-ends{flex-direction:column;gap:.5rem}
  .cty-split-ends .b{text-align:left}
  .cty-split-ends .b small{margin-left:0}
  .cty-split-ends small{max-width:none}
}

/* Footnote markers (24 Sep 2026). A superscript "1" after the report's
   district count, pointing at the section that explains 606 against
   Ohio's 611. The link is padded so a thumb can hit a one-character
   target, and it drops the underline, which under a superscript reads as
   a stray mark. The target's heading carries the same "1". */
sup.fn{font-size:.62em;line-height:0;vertical-align:super;margin-left:.08em}
.v2-card sup.fn a,.v2-lede sup.fn a,.tile sup.fn a,sup.fn a{
  color:var(--fern-glow);text-decoration:none;padding:.1em .2em;font-weight:600}
sup.fn a:hover,sup.fn a:focus-visible{text-decoration:underline}
.fn-mark{font-size:.6em;vertical-align:super;line-height:0;margin-right:.3em;
  color:var(--fern-glow);font-weight:600}
/* "The figures on this page are still all of Ohio": shown by market.js
   once a county is picked, because picking one changes nothing below and
   the figures read as that county's (the user, 24 Sep 2026). */
.find-yours .find-note{margin:.4rem 0 1rem;padding:.7rem .9rem;border-radius:12px;
  border:1px solid var(--line);background:var(--surface-raise);
  color:var(--bone);font-size:1rem;line-height:1.5}
.find-yours .find-note[hidden]{display:none}



/* ------------------------------------- the county-first preview (v2) ---- */
/* Three doors in place of nine topic buttons, and a county page that shows
   one section at a time (Property Tax Report, 24 Sep 2026). A preview at
   /market/taxes/v2, beside the live pages. Tokens only, so light mode is
   the same inversion as everywhere else; the one filled door is --bone on
   --ink, which inverts as a pair. */
.v2-sections a:focus-visible,.v2-parts a:focus-visible,.v2-door:focus-visible,
.v2-read a:focus-visible{outline:3px solid var(--fern-glow);outline-offset:3px}

.v2-door-list,.v2-read{list-style:none;margin:0 0 2rem;padding:0;
  display:grid;gap:1rem}
.v2-door,.v2-read a{display:flex;flex-direction:column;gap:.45rem;
  padding:1.35rem 1.4rem;border-radius:20px;border:1px solid var(--line);
  background:var(--surface-raise);color:var(--text-strong);
  text-decoration:none}
.v2-door:hover,.v2-read a:hover{border-color:var(--fern-light)}
.v2-door-kicker{font-size:.8rem;letter-spacing:.14em;text-transform:uppercase;
  font-weight:600;color:var(--fern-glow)}
.v2-door-title{font-family:"Inter var",Inter,sans-serif;
  font-size:clamp(1.3rem,2.6vw,1.55rem);line-height:1.2;letter-spacing:-.02em;
  color:var(--text-strong);text-wrap:balance}
.v2-door-blurb{font-size:1.05rem;line-height:1.5;color:var(--text-soft)}
.v2-door.is-primary{background:var(--bone);border-color:var(--bone);
  color:var(--ink);padding:1.6rem 1.4rem}
.v2-door.is-primary .v2-door-kicker,.v2-door.is-primary .v2-door-title,
.v2-door.is-primary .v2-door-go{color:var(--ink)}
.v2-door.is-primary .v2-door-kicker,.v2-door.is-primary .v2-door-blurb{
  color:var(--ink);opacity:.72}
.v2-door.is-primary .v2-door-title{font-size:clamp(1.5rem,3vw,1.8rem)}
.v2-door-go{font-size:1.08rem;font-weight:600;text-decoration:underline;
  text-underline-offset:.2em}
.v2-door.has-map{flex-direction:row;align-items:center;gap:1.1rem}
.v2-door-text{display:flex;flex-direction:column;gap:.45rem;min-width:0}
/* The front door's thumbnail of the map. .ohmap brings the fills and their
   light-mode remaps; everything about its size is undone here. */
.ohmap.v2-mini{display:block;margin:0;width:5.6rem;flex-shrink:0}
.ohmap.v2-mini svg{max-height:none}
.ohmap.v2-mini path{stroke-width:3}

.v2-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:.6rem;margin:0 0 2rem}
.v2-stats.two{grid-template-columns:repeat(2,minmax(0,1fr));margin:1.2rem 0}
.v2-stats>div{display:flex;flex-direction:column;gap:.2rem;padding:.85rem;
  border-radius:14px;border:1px solid var(--line);background:var(--surface-raise)}
.v2-stats dt{font-size:.78rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-softer)}
.v2-stats dd{margin:0;font-family:"Inter var",Inter,sans-serif;
  font-size:clamp(1.35rem,3vw,1.7rem);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;color:var(--text-strong)}
.v2-stats p,.v2-card .v2-stats p{margin:0;font-size:.92rem;line-height:1.35;
  color:var(--text-softer)}

/* The county's panel, and the figure that leads it. */
.v2-sum{padding:1.4rem 1.4rem 1.2rem;margin:0 0 1.4rem}
.v2-sum p{margin:0 0 .75rem;font-size:1.08rem;line-height:1.55}
.v2-sum .cty-split-bar{margin:0 0 .75rem}
.v2-sum .cty-share{margin-top:1.1rem;padding:0;border:0;background:none;
  align-items:flex-start}
.v2-sum-fig{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .6rem}
.v2-sum-fig strong,.v2-card .v2-sum-fig strong{font-family:"Inter var",Inter,sans-serif;
  font-size:clamp(2.3rem,6vw,2.9rem);line-height:1.05;letter-spacing:-.035em;
  font-weight:500;font-variant-numeric:tabular-nums}
.v2-sum-fig span{color:var(--text-soft)}
.v2-card p.v2-lead{font-size:1.24rem;color:var(--text-strong)}

/* The county's sections: plain links, one address each, set as one
   segmented control like the doors above them. A scrolling row of pills
   hid the fifth, Levies, off the right edge of a 390px phone — and a
   section nobody can see is a section nobody opens. */
/* Columns at least as wide as their label, the rest shared: "Foreclosures"
   is twice "Bill", and equal columns cut it on a 390px phone (27 Sep 2026). */
.v2-sections{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(max-content,1fr);
  gap:.25rem;padding:.3rem;margin:0 0 1.4rem;border:1px solid var(--line);
  border-radius:16px;background:var(--surface-raise)}
.v2-sections a{display:flex;align-items:center;justify-content:center;
  min-height:2.75rem;padding:0 .2rem;border-radius:12px;font-size:1.02rem;
  color:var(--text-soft);text-decoration:none;white-space:nowrap}
.v2-sections a:hover{color:var(--text-strong)}
.v2-sections a[aria-current="page"]{background:var(--bone);color:var(--ink);
  font-weight:600}
/* A section's parts, as small buttons under the tabs (26 Sep 2026): plain
   fragment links, quieter than the tabs so the two rows read as levels. */
.v2-parts{display:flex;flex-wrap:wrap;gap:.45rem;margin:-.3rem 0 1.6rem}
.v2-parts a{display:inline-flex;align-items:center;min-height:2.5rem;
  padding:0 1rem;border:1px solid var(--line);border-radius:999px;
  font-size:.95rem;color:var(--text-soft);text-decoration:none}
.v2-parts a:hover{color:var(--text-strong);border-color:var(--text-soft)}

.v2-map{grid-template-columns:minmax(0,1.3fr) minmax(220px,1fr)}
.v2-pick{margin-bottom:2rem}
.v2-pick .field{margin-bottom:1.1rem}
.cty-next .btn{display:inline-flex}

@media (max-width:640px){
  .v2-map{grid-template-columns:1fr}
  .v2-stats{gap:.45rem}
  .v2-stats>div{padding:.7rem .6rem}
  .v2-door,.v2-read a{padding:1.15rem 1.1rem}
  .ohmap.v2-mini{width:4.6rem}
  .v2-sections a{font-size:.95rem}
}

/* Phone check of the preview, 24 Sep 2026. */
.v2-county-hero{margin-bottom:1.2rem}
.v2-county-hero .eyebrow{margin-bottom:.5rem}
.v2-approved{margin:0 0 1.2rem}
/* The card's split bar has a track made for the dark card panel; on the
   Bill tab's page-coloured card in light mode it vanished, and 87% drew as
   a full bar. The same track the bill split above it uses. */
:root[data-theme="light"] .v2-approved .cty-split-bar{background:rgba(20,20,18,.07)}
/* "Compare all 88": a card-shaped button that opens to the live table. */
.v2-more{margin:0 0 2rem}
.v2-more>summary{list-style:none;display:grid;grid-template-columns:1fr auto;
  gap:.25rem 1rem;align-items:center;padding:1.1rem 1.3rem;cursor:pointer;
  border:1px solid var(--line);border-radius:20px;background:var(--surface-raise)}
.v2-more>summary::-webkit-details-marker{display:none}
.v2-more>summary::after{content:"+";grid-row:1/3;grid-column:2;
  font-size:1.6rem;line-height:1;color:var(--fern-light)}
.v2-more[open]>summary::after{content:"\2212"}
.v2-more>summary:hover{border-color:var(--fern-light)}
.v2-more>summary:focus-visible{outline:3px solid var(--fern-glow);outline-offset:3px}
.v2-more-title{font-family:"Inter var",Inter,sans-serif;font-size:1.2rem;
  color:var(--text-strong)}
.v2-more-what{font-size:.98rem;line-height:1.45;color:var(--text-soft)}
.v2-more[open]>summary{margin-bottom:1rem}
@media (max-width:640px){
  /* The Ohio door's four tiles two by two, not four screens of one. */
  .v2-ohio .tiles{grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem}
  .v2-ohio .tile{padding:1rem .9rem 1.05rem}
  .v2-ohio .tile-rent{font-size:1.75rem}
  .v2-ohio .tile-sub{margin-bottom:0;font-size:.8rem;line-height:1.4}
}

/* "Not in Ohio?" on the front door: what works for the other 49 states,
   as a short list and two ways in (25 Sep 2026). */
.not-ohio ul{margin:0 0 1.3rem;padding-left:1.3rem}
.not-ohio li{font-size:1.08rem;line-height:1.6;color:var(--text-soft);margin:.3rem 0}
.not-ohio .not-ohio-go{display:flex;flex-wrap:wrap;gap:.6rem;margin:0}

/* "Why the state's Report Card shows different numbers" on a district page
   (25 Sep 2026): three short reasons, as a list. */
.other-figures ul{margin:0;padding-left:1.3rem}
.other-figures li{font-size:1.08rem;line-height:1.6;color:var(--text-soft);margin:.45rem 0}

/* The new-levy calculator (26 Sep 2026): the district line under the hero,
   the checkbox row, and the error card, in the section's own tokens. */
.lc-where{margin:0 0 1.4rem;color:var(--text-soft)}
.lc-where strong{color:var(--text-strong)}
.v2-form .lc-check{display:flex;gap:.6rem;align-items:flex-start;margin:0 0 1.6rem;
  font-size:1.02rem;font-weight:400;color:var(--text-soft);cursor:pointer}
.v2-form .lc-check input{width:1.15rem;height:1.15rem;min-height:0;margin-top:.2rem;
  accent-color:var(--fern-glow)}
.lc-errors ul{margin:.4rem 0 0;padding-left:1.2rem}
.lc-errors li{margin:.25rem 0}

/* The levy calculator's ways in (26 Sep 2026): the front door's card in
   the weeks before an election, its line otherwise, and the check's
   start-page option. Amber for the ballot, as the stars and the lead bars
   use it; nothing else on the page is. */
.v2-ballot{margin:0 0 1rem;border-color:var(--star)}
.v2-ballot .v2-door-kicker{color:var(--star)}
.v2-ballot .v2-door-go{color:var(--text-strong);font-weight:600}
.v2-aside-link{margin:-1rem 0 2rem;color:var(--text-soft)}
.v2-alt{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  margin:0 0 1.4rem;padding:1rem 1.25rem;border:1px solid var(--line);border-radius:16px;
  background:var(--surface-raise);color:var(--text-soft);text-decoration:none}
.v2-alt strong{color:var(--text-strong)}
.v2-alt:hover{border-color:var(--fern-light)}
.v2-alt-go{color:var(--text-strong);font-size:1.2rem}
/* A button inside a card never runs past its edge (phone check, 26 Sep
   2026): the house button keeps to one line, which on a 390px phone put
   "What would a new levy cost you?" beyond the card. Here it may wrap. */
.v2-card .btn{max-width:100%;white-space:normal;text-align:center;line-height:1.3}


/* ---------------------------------------------------------------------
   The Ohio page (Property Tax Report, 27 Sep 2026): the front door and
   the Ohio door in one. Ohio's message and the two things a reader came
   to do, then the proof, then everything else in three short lists. */
.oh-hero h2{font-size:clamp(1.9rem,4.4vw,2.7rem);line-height:1.12;text-wrap:balance}
.oh-hero .v2-lede{margin-bottom:0}
.oh-act{display:grid;gap:.7rem;margin:1.4rem 0 1rem}
@media (min-width:700px){.oh-act{grid-template-columns:1fr 1fr;align-items:stretch}}
.oh-act .btn{justify-content:center;text-align:center}
.oh-act .ohio-pick{display:flex;gap:.5rem;margin:0}
.oh-act .ohio-pick select{flex:1;min-width:0;padding:.85rem 1rem;border-radius:14px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);
  font:inherit;font-size:1rem}
.oh-act .ohio-pick select:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
.oh-act .ohio-pick .btn{padding-inline:1.4rem}
.oh-page .v2-trust{margin:0 0 1.8rem}
.oh-proof{margin:0 0 1.6rem}
.oh-ballot{display:flex;flex-wrap:wrap;gap:.3rem 1rem;align-items:baseline;
  justify-content:space-between;padding:1rem 1.25rem;border:1px solid var(--star);
  border-radius:16px;margin:0 0 1.6rem;text-decoration:none;color:var(--text-strong)}
.oh-ballot b{color:var(--star);flex:1 0 100%}
.oh-ballot-go{font-weight:600;color:var(--text-strong)}
.oh-ballot-go:hover{color:var(--star)}
/* Each tile is the way into the page that explains it. */
.oh-tiles a.tile{display:flex;flex-direction:column;text-decoration:none;color:inherit}
.oh-tiles .tile-go{margin-top:auto;padding-top:.5rem;font-size:.9rem;color:var(--fern-light)}
.oh-tiles a.tile:hover .tile-go{text-decoration:underline}
/* Where every $100 goes: one bar split eight ways, the amounts beside. */
.oh-stack{display:flex;height:34px;border-radius:8px;overflow:hidden;
  margin:1.2rem 0 .9rem;background:var(--line)}
.oh-stack i{display:block;width:var(--w);background:var(--k)}
.oh-legend{list-style:none;padding:0;margin:0 0 1.3rem;display:grid;gap:.35rem 2rem}
@media (min-width:700px){.oh-legend{grid-template-columns:1fr 1fr}}
.oh-legend li{display:flex;gap:.55rem;align-items:baseline;font-size:.98rem;
  color:var(--text-soft)}
.oh-legend .sw{width:.7rem;height:.7rem;border-radius:3px;flex:none;
  background:var(--k);transform:translateY(1px)}
.oh-legend .amt{margin-left:auto;padding-left:.6rem;font-variant-numeric:tabular-nums;
  font-weight:600;color:var(--text-strong)}
.oh-legend .is-lead .what{color:var(--text-strong);font-weight:600}
.k-schools{--k:#7FA8D4}.k-county{--k:#8FBCA4}.k-local{--k:#E4B363}
.k-career{--k:#D98A72}.k-library{--k:#A8D4BC}.k-parks{--k:#8A8A80}
.k-college{--k:#C4B0E0}.k-other{--k:#5F6B66}
:root[data-theme="light"] .k-schools{--k:#3F6F9F}
:root[data-theme="light"] .k-county{--k:#2F6B4F}
:root[data-theme="light"] .k-local{--k:#B7811A}
:root[data-theme="light"] .k-career{--k:#B45A3E}
:root[data-theme="light"] .k-library{--k:#6FAE8E}
:root[data-theme="light"] .k-parks{--k:#7A7A70}
:root[data-theme="light"] .k-college{--k:#7B62A8}
:root[data-theme="light"] .k-other{--k:#A9B1AC}
.oh-fold{margin:1rem 0 0}
.oh-fold>summary{cursor:pointer;color:var(--fern-light);font-size:.98rem}
.oh-fold>summary:focus-visible{outline:3px solid var(--fern-glow);outline-offset:3px}
/* Explore: three short lists, not seven tall cards. After `.v2-card a`,
   which would turn every title green and underline it. */
.oh-explore{display:grid;gap:1.4rem 2rem}
@media (min-width:760px){.oh-explore{grid-template-columns:repeat(3,minmax(0,1fr))}}
.v2-card .oh-explore h4{margin:0 0 .35rem;font-size:.78rem;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-soft)}
.oh-explore ul,.oh-blog ul{list-style:none;margin:0;padding:0}
.oh-explore li,.oh-blog li{border-top:1px solid var(--line)}
.v2-card .oh-explore a,.v2-card.oh-blog a{display:block;padding:.7rem 0;
  text-decoration:none;color:inherit}
.oh-explore .v2-door-title,.oh-blog .v2-door-title{display:block;font-size:1rem;
  font-weight:600;line-height:1.35;color:var(--text-strong)}
.oh-explore .v2-door-blurb,.oh-blog .v2-door-blurb{display:block;margin-top:.15rem;
  font-size:.9rem;line-height:1.45;color:var(--text-soft)}
.oh-explore a:hover .v2-door-title,.oh-blog a:hover .v2-door-title{color:var(--fern-light)}
/* The wide chart keeps a fixed 138-unit strip for its line labels, and
   "Property tax charged $17.3B" is longer: bare on the page, with no card
   padding to run into, it crossed the frame's edge (27 Sep 2026). */
.oh-proof .chart-wide{padding-right:4.5rem}
/* market.js adds a tap readout after each map's svg (not the counties
   map's, which opens a card). In the two-column layout that empty <p>
   took the key's cell, and every such map's key dropped below it with a
   blank beside the map — the reappraisals map since the readout arrived,
   and the Ohio page's (27 Sep 2026). The readout goes under the map; the
   key keeps its column; `dense` lets it fill the row beside the map. */
@media (min-width:761px){
  .ohmap{grid-auto-flow:row dense}
  .ohmap .ohmap-readout{grid-column:1}
  .ohmap figcaption{grid-column:2}
}

/* The year in progress on a county's Foreclosures tab (28 Sep 2026): its
   months under the year, on one line of their own. */
.fc-months{white-space:nowrap;font-size:.85em;font-weight:400;color:var(--text-soft)}
/* Cases filed each year, as bars (28 Sep 2026). The county's amber, as its
   line in the chart below, remapped for light mode as the line is. Heights
   are fractions of one plot height, so every bar stands on the same
   baseline and the tallest fits. The year in progress is lighter, with a
   dashed outline at its pace for the year. A phone keeps the first, last
   and current values; the table has the rest. */
.fc-bars{--fc:#E4B363;--plot:9.5rem;padding:1.4rem 1rem .8rem}
:root[data-theme="light"] .fc-bars{--fc:#965F19}
.fc-cols{list-style:none;margin:0;padding:0;display:grid;
  grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:.35rem;align-items:end}
.fc-cols li{position:relative;display:flex;flex-direction:column;
  justify-content:flex-end;align-items:center;min-width:0}
.fc-bar,.fc-pace{display:block;width:100%;max-width:2.6rem;border-radius:4px 4px 0 0}
.fc-bar{height:calc(var(--plot) * var(--h));background:var(--fc)}
.fc-cols .is-so-far .fc-bar{opacity:.55;position:absolute;bottom:1.4rem;
  left:50%;transform:translateX(-50%)}
.fc-pace{height:calc(var(--plot) * var(--p));border:1.5px dashed var(--fc);
  border-bottom:0;background:transparent;box-sizing:border-box}
.fc-val{font-size:.78rem;line-height:1;margin-bottom:.35rem;white-space:nowrap;
  color:var(--text-soft);font-variant-numeric:tabular-nums}
.fc-yr{height:1.4rem;line-height:1.4rem;font-size:.78rem;color:var(--muted-dark);
  white-space:nowrap}
/* Each bar is its own target, its whole column (7 Oct 2026): it lifts while
   the readout shows its value, and its year darkens. */
.js .fc-cols li[data-when]{cursor:pointer}
.fc-cols li.is-on .fc-bar{filter:brightness(1.22)}
.fc-cols li.is-on .fc-yr{color:var(--text-strong);font-weight:600}
.fc-bars .readout{top:.5rem}
/* `.v2-card p` outranked the bare class and set it at body size. */
.fc-bars-fig .fc-bars-key{font-size:.88rem;line-height:1.55;color:var(--muted-dark);margin:.6rem 0 0}
.fc-bars-fig{margin:0 0 1.6rem}
/* Ohio's unpaid tax under the foreclosure bars (1 Oct 2026): the same
   bars in the unpaid page's colour for its total, remapped for light mode
   as b.css remaps that line. */
.unpaid-bars{--fc:#A8D4BC}
:root[data-theme="light"] .unpaid-bars{--fc:#2F6B4F}
.unpaid-bars-fig{margin-bottom:1rem}
/* Sheriff sales each month (22 Oct 2026): thirty-odd bars, so narrower
   gaps and only the newest and the highest labelled; this month lighter,
   its later sale days still to change. */
.sheriff-bars .fc-cols{gap:.18rem}
.sheriff-bars .fc-cols li:not(.is-newest):not(.is-peak) .fc-val{visibility:hidden}
.sheriff-bars .is-current .fc-bar{opacity:.55}
@media (max-width:640px){
  /* A value is wider than a phone's column, so only the newest bar keeps
     one — "1,740" ran into "1,194" (phone check, 28 Sep 2026) — and it
     overflows toward the frame's edge, never into the bar beside it. */
  .fc-bars{--plot:8rem;padding:1.2rem .7rem .6rem}
  .fc-cols{gap:.2rem}
  .fc-cols li:not(.is-newest) .fc-val{visibility:hidden}
  .sheriff-bars .fc-cols{gap:1px}
  .fc-cols .is-newest .fc-val{align-self:flex-end}
  .fc-val{font-size:.72rem}
  .fc-yr{font-size:.7rem}
}

/* ==== School district forecasts (28 Sep 2026) ============================
   The state's own forecast report, redrawn on the figure panel: the same
   lines, the same column heads, negatives in parentheses and red, and the
   report's shading on its totals — green for revenue, amber for spending,
   blue for the balances. The panel is a fixed dark surface in both themes
   (.hub-panel is in b.css's light-mode pin), so the tints below are drawn
   once, for dark. */
.fcst-crumbs{display:flex;flex-wrap:wrap;gap:.45rem;align-items:baseline;
  font-size:.95rem;color:var(--text-soft);margin:0 0 1.2rem}
.fcst-crumbs a{color:var(--fern-glow)}
.fcst-crumbs [aria-current]{color:var(--text-strong)}
.fcst-hero h2{margin-bottom:.4rem}
.fcst-hero .fcst-filing{font-size:clamp(1.2rem,2.6vw,1.5rem);color:var(--text-strong);
  margin:0 0 .2rem}
.fcst-hero .fcst-date{font-size:1.02rem;color:var(--text-soft);margin:0 0 1rem}
.fcst-hero .fcst-levy-note strong{color:var(--warm)}
.fcst-switch{display:flex;flex-wrap:wrap;gap:.6rem;margin:0 0 1.8rem}
.fcst-switch a{display:flex;flex-direction:column;gap:.1rem;padding:.65rem 1rem;
  border:1px solid var(--line);border-radius:12px;color:var(--text-soft);
  text-decoration:none;flex:1 1 9.5rem;min-width:0;max-width:17rem}
.fcst-switch a b{color:var(--text-strong);font-weight:600}
.fcst-switch a span{font-size:.88rem}
.fcst-switch a[aria-current]{border-color:var(--fern-glow);
  box-shadow:inset 0 0 0 1px var(--fern-glow)}
.fcst-switch a:focus-visible{outline:2px solid var(--fern-glow);outline-offset:2px}

.hub-panel .fcst-table,.hub-panel .fcst-ladder-table{font-size:.92rem}
.hub-panel .fcst-table th,.hub-panel .fcst-table td{padding:.42rem .5rem}
.hub-panel .fcst-table thead th,.hub-panel .fcst-ladder-table thead th,
.hub-panel .fcst-list thead th{vertical-align:bottom}
.fcst-kind{display:block;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-dark);font-weight:600;
  white-space:nowrap}
.hub-panel thead .fcst-kind{margin-bottom:.15rem}
/* The year's kind wraps ("Current year / budget") so the figures, not
   the heading, set a column's width. */
.hub-panel .fcst-table thead th{white-space:normal}
.hub-panel .fcst-table thead .fcst-kind{white-space:normal;min-width:5.5rem}
.fcst-list thead .fcst-kind{display:inline;margin-left:.2rem}
.fcst-code{color:var(--muted-dark);font-variant-numeric:tabular-nums;
  margin-right:.35rem;white-space:nowrap}
/* The state's report is a wide sheet: seven year columns beside a line's
   description. The page takes a wider column than the site's reading
   measure so the table fits a desktop without scrolling, and the
   descriptions wrap, as they do there — one of them is 95 characters. */
.fcst-page .shell{max-width:1320px}
.fcst-page .v2-lede,.fcst-page .hub-panel>p,.fcst-page .hub-figure-note{max-width:52rem}
.hub-panel .fcst-table tbody th{white-space:normal;min-width:14rem;max-width:22rem;
  line-height:1.35}
/* Red for a negative, as the state's report prints it: a deficit, which
   warm (a cost rising) does not say. 6:1 on the panel. */
.hub-panel td.is-neg{color:#F0907F}
.hub-panel .fcst-table tr.band-rev>*{background:rgba(143,188,164,.09)}
.hub-panel .fcst-table tr.band-rev-all>*{background:rgba(143,188,164,.2)}
.hub-panel .fcst-table tr.band-spend>*{background:rgba(228,179,99,.08)}
.hub-panel .fcst-table tr.band-spend-all>*{background:rgba(228,179,99,.18)}
.hub-panel .fcst-table tr.band-bal>*{background:rgba(126,166,214,.13)}
.hub-panel .fcst-table tr[class^="band-"]>*{font-weight:600}
/* The ladder: balances bold and ruled, the steps between them quieter. */
.hub-panel .fcst-ladder-table tr.is-balance th,
.hub-panel .fcst-ladder-table tr.is-balance td{font-weight:600;color:var(--bone);
  border-top:1px solid rgba(143,188,164,.3)}
.hub-panel .fcst-ladder-table tr.is-step td{color:var(--text-soft)}
.hub-panel .fcst-ladder-table tbody th{min-width:15rem}
.hub-panel .fcst-ladder-table .hub-sub{font-size:.86rem;margin-top:.15rem;
  max-width:34rem}
.hub-panel .fcst-list td{white-space:nowrap}
.hub-panel .fcst-list tbody th a{color:var(--bone)}
.fcst-more{margin:-.4rem 0 1.8rem;font-size:1.05rem}
.fcst-more a{color:var(--fern-glow)}
.fcst-source{max-width:52rem}
/* A pinned first column inside the panel has to be the panel, opaque —
   the rule above it paints the page's card colour, which on this surface
   showed as a lighter stripe. The band tint rides on top of it. */
@media(max-width:720px){
  /* And pinned to the scroller's outer edge, not its padding edge: sticky
     insets count from inside the padding, so at left:0 the rows slid
     under a 20px strip beside the pinned column and showed there. */
  .fcst-page .hub-panel .fig-scroll table th[scope="row"]{
    background:linear-gradient(var(--band,transparent),var(--band,transparent)),#18231D;
    color:#C9C7C1;left:calc(-1 * var(--pad))}
  .fcst-page .hub-panel .fig-scroll table thead th:first-child{
    background:#18231D;color:#8A8A80;left:calc(-1 * var(--pad))}
  /* The list tables' headings wrapped to five lines in a phone's narrow
     columns, and the pinned corner cell showed as a dark box above
     "District" (phone check, 29 Sep 2026). Wider columns wrap to two or
     three; and the whole header row takes the corner's shade, so it reads
     as a band rather than a stray rectangle. */
  .hub-panel .fcst-list thead th{min-width:6.6rem}
  .hub-panel .fcst-list thead th:first-child{min-width:0}
  .fcst-page .hub-panel .fig-scroll table thead th{background:#18231D;color:#8A8A80}
  .hub-panel .fcst-table tr.band-rev{--band:rgba(143,188,164,.09)}
  .hub-panel .fcst-table tr.band-rev-all{--band:rgba(143,188,164,.2)}
  .hub-panel .fcst-table tr.band-spend{--band:rgba(228,179,99,.08)}
  .hub-panel .fcst-table tr.band-spend-all{--band:rgba(228,179,99,.18)}
  .hub-panel .fcst-table tr.band-bal{--band:rgba(126,166,214,.13)}
  .hub-panel .fcst-table tbody th{white-space:normal;min-width:0;width:10.5rem;
    max-width:10.5rem;font-size:.9rem}
  .hub-panel .fcst-table thead th:first-child{white-space:normal}
  .hub-panel .fcst-ladder-table tbody th{min-width:11rem}
}

/* School budgets in three figures (28 Sep 2026) — on the budgets page, a
   district's page and a county's Schools tab, always inside a figure
   panel, so the dark tokens hold in both themes. The kicker's small caps
   over each figure, as the panel recipe has them. */
.budget-figs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1.2rem 1.6rem;margin:0 0 .6rem}
/* Each figure's three parts share rows with its neighbours', so a label
   that wraps to two lines in a narrow card no longer drops its figure
   below the other two (desktop look-and-feel check, 29 Sep 2026). */
.budget-figs>div{border-top:1px solid rgba(143,188,164,.22);padding-top:.8rem;
  display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:0;align-content:start}
.budget-figs dt{font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted-dark);margin:0 0 .45rem}
.budget-figs dd{margin:0;font-size:clamp(1.6rem,3.4vw,2.2rem);line-height:1.05;
  color:var(--bone);letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.budget-figs dd em{font-style:normal;font-size:.5em;color:var(--muted-dark);
  letter-spacing:0}
.hub-panel .budget-figs p{margin:.45rem 0 0;font-size:.92rem;line-height:1.45;
  color:var(--text-soft)}
.fcst-figs .budget-figs{margin:0}
.district-budget .budget-figs,.county-budget .budget-figs{margin:1rem 0 1.2rem}
@media(max-width:640px){.budget-figs{grid-template-columns:1fr;gap:1rem}}
/* The county card sits in the county page's reading column, narrower than
   the budgets page's: a heading's second half drops to the small caps so
   the figures, not the words, set each width, and the new-levy cell wraps
   rather than running off the card. */
.county-budget .fcst-list thead .fcst-kind{display:block;margin:.15rem 0 0}
.hub-panel .county-budget-table td.budget-levy,.county-budget .fcst-list td.budget-levy{white-space:normal;min-width:8rem}

/* What a budget total adds up, over its three figures (28 Sep 2026): the
   kicker's small caps, so it reads as the panel's label, not a note. */
.hub-panel .budget-scope{font-size:.8rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--fern-glow);margin:0 0 1rem;line-height:1.5;text-wrap:pretty}
/* The way to your county, under the budgets headline (28 Sep 2026). */
.fcst-jump{display:flex;flex-wrap:wrap;align-items:flex-end;gap:.6rem 1.4rem;
  margin:0 0 1.8rem}
.fcst-jump form{flex:1 1 22rem;max-width:34rem}
.fcst-jump label{display:block;font-size:.82rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-soft);margin-bottom:.45rem}
.fcst-jump-row{display:flex;gap:.5rem}
.fcst-jump select{flex:1;min-width:0;padding:.85rem 1rem;border-radius:14px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);
  font:inherit;font-size:1rem;min-height:3rem}
.fcst-jump select option{color:#1D1D1A;background:#F4F1EA}
.fcst-jump select:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
.fcst-jump .btn{padding-inline:1.4rem}
.fcst-jump-district{font-size:1rem;color:var(--fern-glow);padding-bottom:.85rem}
/* The line under the forecast table's heading: whose filing it is. */
.hub-panel .fcst-report-sub{margin:-.5rem 0 1rem;font-size:.98rem;color:var(--text-soft)}
/* Who pays for it (29 Sep 2026): the pie as three bars, each as long as
   its share of the whole, and the definition of "homes" under the reason. */
.who-pays-split{margin:1rem 0 1.4rem}
p.who-pays-def{font-size:.98rem;color:var(--text-soft)}
/* What each forecast line means (29 Sep 2026): the line's name is a
   <details> summary — tap on a phone, click or hover (its title) on a
   computer — and the plain-words meaning opens under it. The dotted
   underline is the cue that the name does something. */
.fcst-help summary{cursor:pointer;list-style:none}
.fcst-help summary::-webkit-details-marker{display:none}
.fcst-help .fcst-descr{text-decoration:underline dotted rgba(168,212,188,.55);
  text-underline-offset:.22em}
.fcst-help summary:focus-visible{outline:2px solid var(--fern-glow);outline-offset:2px;border-radius:4px}
.fcst-help[open] .fcst-descr{text-decoration-color:var(--fern-glow)}
.hub-panel .fcst-help p{margin:.35rem 0 .15rem;font-size:.86rem;line-height:1.45;
  color:var(--text-soft);font-weight:400;white-space:normal;max-width:24rem}

/* Column headings that stay in view (the user, 29 Sep 2026). On a screen
   where a budgets table fits, its box stops being a scroll container (b.js
   marks it .fits, and re-measures on resize) so the heading row can stick
   to the page, just under the fixed menu. On a phone the state's report
   scrolls sideways, and a sideways box cannot pin a row to the page — so
   that one table gets a box of its own height, with the heading row pinned
   at its top and the line names at its left, like a spreadsheet. The
   headings are opaque so rows pass underneath, and state their own colour
   (the panel is dark in both themes). */
.fcst-page .fig-scroll.fits{overflow:visible}
.fcst-page .hub-panel .fig-scroll.fits thead th{position:sticky;
  top:calc(5.9rem + var(--banner-now,var(--banner-h,0px)));z-index:3;background:#1A231D;color:#8A8A80;
  transition:top .5s var(--easing)}
/* The menu slides away on the way down and back on the way up (b.js); the
   headings follow it, under the announcement strip, which stays. */
:root:has(.nav-wrap.is-hidden) .fcst-page .hub-panel .fig-scroll.fits thead th{
  top:var(--banner-now,var(--banner-h,0px))}
@media(max-width:720px){
  .fcst-page .fcst-report .fig-scroll:not(.fits){max-height:75vh;overflow:auto}
  .fcst-page .fcst-report .fig-scroll:not(.fits) thead th{position:sticky;top:0;z-index:3}
  .fcst-page .fcst-report .fig-scroll:not(.fits) thead th:first-child{z-index:4}
}
/* The district's own forecast notes, under its filing date (29 Sep 2026). */
.fcst-hero .fcst-notes{margin:-.4rem 0 1rem;font-size:1rem}
.fcst-hero .fcst-notes a{color:var(--fern-glow)}

/* ================================================= on the ballot (29 Sep 2026)
   Every local tax issue on an Ohio ballot (app/ballot.py). A county's issues
   are a list, not a table: each carries a sentence or two of its own, and a
   phone reads a list. Ohio's school issues are a table in the figure panel,
   because they are compared row against row. Warm marks an ask for new
   money — a cost rising, as everywhere on this site — and nothing marks a
   pass or a fail as good or bad: the page takes no side. */
.bal-jump-row form{flex:1 1 18rem}
.bal-sections{display:flex;flex-wrap:wrap;gap:.5rem;margin:0 0 1.2rem}
.bal-sections a{display:inline-flex;align-items:center;gap:.45rem;padding:.45rem .85rem;
  border:1px solid var(--line);border-radius:999px;font-size:.95rem;color:var(--text-strong);
  text-decoration:none;background:var(--surface-raise)}
.bal-sections a:hover{border-color:var(--edge)}
.bal-sections a span,.bal-count{font-variant-numeric:tabular-nums;color:var(--text-soft);font-size:.88em}
.bal-filter{margin:0 0 1.4rem;max-width:34rem}
.bal-filter label{display:block;font-size:.82rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-soft);margin-bottom:.45rem}
.bal-filter input{width:100%;padding:.85rem 1rem;border-radius:14px;border:1px solid var(--line);
  background:var(--surface-raise);color:var(--text-strong);font:inherit;font-size:1rem;min-height:3rem}
.bal-filter input:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
.bal-filter-none{margin:.6rem 0 0;color:var(--text-soft)}
.bal-section h3{display:flex;align-items:baseline;gap:.6rem}
.bal-list{list-style:none;margin:0;padding:0}
.bal-issue{padding:1.1rem 0;border-top:1px solid var(--line)}
.bal-issue:first-child{border-top:0;padding-top:.4rem}
.bal-issue p{margin:.3rem 0 0}
.bal-head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:.3rem .8rem}
.bal-head h4{margin:0;font-size:1.18rem;font-weight:500;color:var(--text-strong)}
.bal-chip{display:inline-block;padding:.12rem .6rem;border:1px solid var(--line);border-radius:999px;
  font-size:.8rem;letter-spacing:.04em;color:var(--text-soft);white-space:nowrap}
.bal-chip.is-new{color:var(--warm);border-color:color-mix(in srgb,var(--warm) 55%,transparent)}
.bal-chip.is-less{color:var(--fern-light);border-color:color-mix(in srgb,var(--fern-light) 55%,transparent)}
/* What it pays for (1 Oct 2026): the same pill, filled rather than ruled, so
   a kind ("Fire & EMS") reads apart from a status ("New", "Renewal"). */
.bal-chips{display:inline-flex;flex-wrap:wrap;gap:.35rem;align-items:baseline}
/* Share this list (1 Oct 2026): the button, and what it sends, in a line. */
/* Share a county's ballot list (1 Oct 2026): a row of small buttons under
   what it shares, not the boxed card the saved check's share uses — three
   full-size buttons stacked a phone's screen tall. */
.bal-share{flex-direction:row;flex-wrap:wrap;align-items:center;gap:.5rem;
  margin:.9rem 0 0;padding:0;border:0;background:none}
.bal-share .btn{padding:.55rem .95rem;font-size:.92rem;min-height:0}
.bal-share-note{flex-basis:100%;color:var(--text-softer);font-size:.93rem}
/* How earlier votes went (5 Oct 2026): a line under the lede, the spot
   the question box lands on for a question about results. */
.bal-history{max-width:44rem;color:var(--text-soft);margin:.8rem 0 0}
.bal-history b{font-weight:500;color:var(--text-strong)}
.bal-chip.is-type{background:color-mix(in srgb,var(--text-soft) 14%,transparent);
  border-color:transparent;color:var(--text-strong)}
.bal-who{font-size:.9rem;color:var(--text-softer)}
.bal-what{color:var(--text-strong)}
.bal-what b{font-weight:500}
.bal-purpose{color:var(--text-soft)}
.bal-cost{font-size:1.02rem;color:var(--text-soft)}
.bal-cost b{font-size:1.3rem;font-weight:500;color:var(--text-strong);font-variant-numeric:tabular-nums}
.bal-note{font-size:.95rem;color:var(--text-softer);max-width:44rem}
.bal-note b{font-weight:500;color:var(--text-strong)}
/* A levy's cost, worked out (30 Sep 2026): the sum, three homes, the
   calculator. The homes wrap as whole pairs, never mid-figure. */
.bal-worked{font-size:.93rem;color:var(--text-softer);font-variant-numeric:tabular-nums}
.bal-examples{display:flex;flex-wrap:wrap;align-items:baseline;gap:.15rem .9rem;color:var(--text-soft)}
.bal-examples b{color:var(--text-strong);font-weight:500;font-variant-numeric:tabular-nums}
.bal-ex{white-space:nowrap}
.bal-issue-note{padding-left:.8rem;border-left:2px solid color-mix(in srgb,var(--warm) 60%,transparent)}
.bal-source a,.bal-calc a{color:var(--fern-light)}
.bal-calc a{font-weight:500}
/* Homeowners 65 and over (1 Oct 2026): the figure, then the county's and
   Ohio's beside it, then the note. */
.older-figure{font-size:1.05rem;color:var(--text-soft)}
.older-figure strong{font-size:1.5rem;font-weight:500;color:var(--text-strong);font-variant-numeric:tabular-nums}
.older-compare{color:var(--text-softer);font-variant-numeric:tabular-nums}
.older-compare strong{color:var(--text-strong);font-weight:500}
.older-compare span{white-space:nowrap}
.bal-result{font-variant-numeric:tabular-nums;color:var(--text-soft)}
.bal-result b{color:var(--text-strong);font-weight:600}
.bal-budget{font-size:.97rem;color:var(--text-soft);padding-left:.8rem;
  border-left:2px solid color-mix(in srgb,var(--fern-light) 60%,transparent)}
.bal-budget a{color:var(--fern-light);white-space:nowrap}
.bal-past{margin:.55rem 0 0}
.bal-past summary{cursor:pointer;font-size:.93rem;color:var(--fern-light)}
.bal-past ul{margin:.5rem 0 0;padding-left:1.1rem;font-size:.93rem;color:var(--text-soft)}
.bal-past li{margin:.3rem 0}
.bal-past-passed,.bal-past-failed{font-weight:600;color:var(--text-strong)}
.bal-table .bal-for{white-space:normal;min-width:12rem;font-size:.95rem}
.bal-table tbody th{min-width:10rem}
.bal-table td .bal-chip{margin-bottom:.25rem}
.bal-table .hub-sub{white-space:normal}
.bal-issue[hidden],.bal-section[hidden]{display:none}
.county-ballot{margin:0 0 1.4rem}
.county-ballot-done{margin:0 0 1.2rem}
.bal-district .bal-more{margin:.8rem 0 0}

/* ======================================= place-first navigation (29 Sep 2026)
   docs/NAVIGATION-ROADMAP.md, Phase 1. Every tax page says where it is —
   Ohio › a county › a school district — and the three place pages share one
   strip of chapters in one order. Tokens only: the header and the strip sit
   on the page, not on a figure panel, so they follow the theme. */
.place-head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:.4rem 1.2rem;margin:0 0 1.1rem;font-size:.97rem}
.place-crumbs{display:flex;flex-wrap:wrap;align-items:baseline;gap:.3rem .5rem;min-width:0}
.place-crumbs a{color:var(--text-soft);text-underline-offset:.16em}
.place-crumbs a:hover{color:var(--text-strong)}
.place-crumbs span[aria-current]{color:var(--text-strong);font-weight:600}
.place-crumbs .sep{color:var(--text-faint)}
/* Each step carries its separator (Phase 3, 29 Sep 2026): the gap goes
   after it, so a wrapped line starts with "›" rather than ending on one. */
.place-step .sep{margin-right:.5rem}
/* A chapter's full detail: its place's strip, under the breadcrumb. */
.place-head .place-chapters{flex:1 0 100%;margin-top:.85rem}
.place-crumbs .place-chapter{color:var(--fern-light)}
.place-you{margin:0;font-size:.93rem;color:var(--text-softer)}
.place-you a{color:var(--fern-light)}
.place-you .place-find{font-weight:500}

.place-chapters{display:flex;gap:.45rem;overflow-x:auto;scrollbar-width:none;
  margin:0 0 1.4rem;padding:.4rem 0}
.place-chapters::-webkit-scrollbar{display:none}
.place-chapters a{flex:0 0 auto;display:inline-flex;align-items:center;min-height:44px;
  padding:.4rem 1rem;border-radius:999px;border:1px solid var(--line);background:var(--surface-raise);
  color:var(--text-strong);text-decoration:none;font-size:.97rem;white-space:nowrap}
.place-chapters a b{font-weight:500;color:var(--text-softer);margin-right:.45rem;
  font-variant-numeric:tabular-nums}
.place-chapters a:hover{border-color:var(--edge)}
.place-chapters a[aria-current="page"]{background:var(--bone);color:var(--ink);border-color:var(--bone)}
.place-chapters a[aria-current="page"] b{color:var(--ink)}
.place-chapters a.place-deeper{color:var(--fern-light);border-style:dashed}
.place-chapters a:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
/* On a wide screen every chapter is in view: the reading column holds
   about five, so the row wraps rather than hiding the rest behind a scroll
   a mouse cannot find. It stays where it is rather than following the
   page: two rows pinned under the nav would cover a fifth of the screen
   (look-and-feel check, 29 Sep 2026). On a phone it is one row that
   scrolls sideways, and its right edge fades to say so. */
@media(min-width:721px){.place-chapters{flex-wrap:wrap;overflow:visible}}
@media(max-width:720px){
  .place-chapters{-webkit-mask-image:linear-gradient(90deg,#000 88%,transparent);
    mask-image:linear-gradient(90deg,#000 88%,transparent);padding-right:2rem}
}
.place-xref{margin:0 0 1rem;font-size:.97rem}
.place-xref a{color:var(--fern-light)}

/* The Ohio page: the zip box beside the county list, and the line that
   replaced its Explore lists. */
.oh-act .ohio-zip{display:flex;gap:.5rem;margin:0}
.oh-act .ohio-zip input{flex:1;min-width:0;padding:.85rem 1rem;border-radius:14px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);
  font:inherit;font-size:1rem;min-height:3rem}
.oh-act .ohio-zip input:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
.oh-act .ohio-zip .btn{padding-inline:1.4rem}
@media (min-width:700px){.oh-act>.btn{grid-column:1 / -1}}
.oh-topics-line{margin:0 0 1.6rem;font-size:1.05rem}
.oh-topics-line a{display:inline-flex;gap:.4rem;align-items:baseline;color:var(--fern-light)}

/* Topics: the one index. Three lists of question cards. */
.topic-group{margin:0 0 1.8rem}
.topic-group h3{font-size:1.25rem;margin:0 0 .8rem}
.topic-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:1rem}
.topics-page .topic-card{display:flex;flex-direction:column;gap:.35rem;margin:0}
.topics-page .topic-card h4{margin:0;font-size:1.12rem;color:var(--text-strong)}
.topic-blurb{margin:0;color:var(--text-soft)}
.topic-fig{margin:.3rem 0 0;color:var(--text-soft);font-size:.95rem}
.topic-fig b{display:block;font-size:1.6rem;font-weight:500;color:var(--text-strong);
  letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.topics-page .topic-go{margin:auto 0 0;padding-top:.6rem;display:flex;flex-wrap:wrap;gap:.3rem 1.2rem}
.topic-go a{color:var(--fern-light);font-weight:500}

/* Find my place. */
/* minmax(0,1fr), not the default auto: a grid column grows to its widest
   item's content, and the district list's longest name made the page
   472px wide on a 375px phone (found 29 Sep 2026). */
.find-card{display:grid;grid-template-columns:minmax(0,1fr);gap:1.3rem;max-width:40rem}
.find-form label{display:block;font-size:.82rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-soft);margin-bottom:.45rem}
.find-row{display:flex;gap:.5rem}
.find-row input,.find-row select{flex:1;min-width:0;padding:.85rem 1rem;border-radius:14px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);
  font:inherit;font-size:1rem;min-height:3rem}
.find-row select option,.find-row select optgroup{color:#1D1D1A;background:#F4F1EA}
.find-row input:focus-visible,.find-row select:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
.find-row .btn{padding-inline:1.4rem}
.find-msg{margin:0 0 1rem;padding:.8rem 1rem;border-left:3px solid var(--warm);color:var(--text-strong);
  background:var(--surface-raise);border-radius:0 12px 12px 0;max-width:40rem}
.find-choices{max-width:40rem}
.find-choice-row{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:.8rem}
.find-note{max-width:40rem;color:var(--text-softer);font-size:.95rem}

/* Ask a question (place-first navigation, Phase 5, 29 Sep 2026). The box
   itself is styled in b.css, beside the menu that carries it everywhere;
   here, where it sits on a page, and the buttons an answer offers. */
@media (min-width:700px){.oh-act .ask-form{grid-column:1 / -1}}
.oh-act .ask-form{margin:.3rem 0 0}
.topics-ask{max-width:40rem;margin:0 0 2rem}
.ask-card{max-width:40rem}
.ask-choices{max-width:40rem;margin:0 0 1.2rem}
.ask-choices h3{margin:0 0 .8rem}
.ask-choice-list{list-style:none;margin:0;padding:0;display:grid;gap:.6rem}
/* Two classes deep, to outrank .v2-card a, which underlines body links. */
.ask-choice-list .ask-choice{display:flex;flex-direction:column;gap:.2rem;padding:.9rem 1.1rem;
  border-radius:14px;border:1px solid var(--line);background:var(--surface-raise);
  text-decoration:none;min-height:3rem}
.ask-choice b{font-size:1.15rem;font-weight:500;color:var(--text-strong)}
.ask-choice span{font-size:.95rem;color:var(--text-soft)}
.ask-choice-list .ask-choice:hover{border-color:var(--fern-light);text-decoration:none}
.ask-choice-list .ask-choice:hover b{color:var(--fern-glow)}
.ask-choice:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}
/* The page's own first sentence under each button (the Ask review, 8 Oct
   2026): what the reader will meet, quoted, in the page's quieter ink. */
.ask-choice .ask-choice-says{display:block;margin-top:.25rem;font-size:.9rem;line-height:1.45;
  color:var(--text-soft);font-style:normal;quotes:"\201C" "\201D"}
.ask-more{margin:.9rem 0 0;font-size:.95rem;color:var(--text-soft)}
.ask-examples{max-width:40rem;margin:1.6rem 0}
.ask-examples h3{font-size:1.1rem;margin:0 0 .6rem}
.ask-examples ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.5rem}
.ask-examples form{margin:0}
.ask-other{max-width:40rem;margin:1.4rem 0 .6rem}
.ask-other a{color:var(--fern-light);font-weight:500}

/* Place-first navigation, Phase 2 (29 Sep 2026): the Ohio page and a
   district page laid out in chapter order, each chapter under a heading
   with its number, its question, and its parts as links. */
.chapter-head{margin:2.6rem 0 1.1rem;padding-top:1.1rem;border-top:1px solid var(--line)}
.chapter-strip-first + .chapter-head,.place-chapters + .chapter-head{margin-top:1rem;border-top:0;padding-top:0}
.chapter-head h2{display:flex;align-items:baseline;gap:.7rem;margin:0;font-size:clamp(1.45rem,3vw,1.9rem);
  font-weight:500;letter-spacing:-.02em;color:var(--text-strong)}
.chapter-head h2 b{font-weight:500;color:var(--text-softer);font-size:.7em;font-variant-numeric:tabular-nums}
.chapter-q{margin:.25rem 0 0;color:var(--text-soft);font-size:1rem}
.chapter-parts{display:flex;flex-wrap:wrap;gap:.3rem 1.1rem;margin:.55rem 0 0;font-size:.95rem}
.chapter-parts a{color:var(--fern-light)}
/* The Ohio page's opening (30 Sep 2026): who made it, under what it does;
   and Ohio's figures, which led until then, opening the Your bill chapter. */
.oh-community{margin:.9rem 0 0;font-size:.97rem;color:var(--text-softer);max-width:40rem}
.oh-chapter-lede{margin:0 0 1.2rem;font-size:1.08rem;line-height:1.6;color:var(--text-soft);max-width:46rem}
.oh-chapter-lede strong{color:var(--text-strong);font-weight:600}
.oh-chapter-go{display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;margin:0 0 1rem;font-size:1rem}
.oh-chapter-go a{color:var(--fern-light);font-weight:500}
.oh-chapter-figs{margin:0 0 1.1rem}
.oh-chapter-figs dd em{font-style:normal;font-size:.5em;color:var(--text-softer)}
.oh-county-list{list-style:none;margin:.8rem 0 1rem;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.15rem 1rem}
.oh-county-list a{display:inline-flex;align-items:center;min-height:40px;color:var(--text-strong)}
.oh-county-list a:hover{color:var(--fern-light)}
/* A county's school districts, at the foot of every section. */
.county-districts{margin-top:1.6rem}
.county-districts tbody th{min-width:10rem}
/* A county's ballot, the issues themselves, at the top of its Levies &
   the ballot chapter. The warm edge before the vote, as the ballot-season
   card on the Ohio page has it. */
.county-ballot-card.is-season{border-color:var(--star)}
.bal-mini{list-style:none;margin:.6rem 0 .4rem;padding:0}
.bal-mini li{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .6rem;padding:.55rem 0;
  border-top:1px solid var(--line)}
.bal-mini li:first-child{border-top:0}
.bal-mini .n{font-weight:500;color:var(--text-strong)}
.bal-mini .v{flex:1 0 100%;color:var(--text-soft);font-size:.95rem;font-variant-numeric:tabular-nums}
.bal-mini-more{color:var(--text-softer);margin:.2rem 0 .8rem}
.bal-mini .n .t{font-weight:400;color:var(--text-softer);font-size:.9em;margin-left:.2rem}

/* ---------- school leaders' pay (1 Oct 2026) ---------- */
/* What a contract adds to the salary, as a short list inside the method
   card: the card's own measure, spaced like its paragraphs. */
.pay-adds{padding-left:1.2rem;margin:0 0 1rem}
.pay-adds li{margin:0 0 .6rem;line-height:1.6}
/* The size bands: a range reads as one figure, so it never breaks. */
.pay-bands td,.pay-bands th[scope="row"]{white-space:nowrap}

/* ================== Ask first: the Ohio page's head (6 Oct 2026) ======== */
/* The question is the page (the user; option A of docs/mockup/ask-first).
   Sizes are a step up from the rest of the site on purpose: the readers
   are older. 48px tap targets, a visible label on the box, examples as
   buttons with quotation marks so they read as questions, the Ask button
   under the box on a phone where beside it the placeholder was clipped. */
.oh-ask-hero h2{font-size:clamp(2.05rem,5.4vw,3.2rem);line-height:1.08;max-width:40rem}
.oh-ask-hero .eyebrow{font-size:.95rem}
.ask-xl .ask-form label{font-size:1.12rem;letter-spacing:0;text-transform:none;
  color:var(--text-strong);font-weight:500;margin-bottom:.6rem}
.ask-xl .ask-row{gap:.6rem}
.ask-xl .ask-row input{min-height:4.1rem;font-size:1.25rem;border-radius:16px;
  border:1.5px solid var(--edge);padding:0 1.1rem}
.ask-xl .ask-row .btn{min-height:4.1rem;font-size:1.15rem;padding-inline:1.9rem}
@media (max-width:560px){
  .ask-xl .ask-row{flex-direction:column}
  .ask-xl .ask-row .btn{width:100%;justify-content:center}
}
.ask-hint{margin:.75rem 0 0;font-size:1.02rem;line-height:1.5;color:var(--text-soft);max-width:40rem}
.ask-xl .ask-guide-line{margin-top:.35rem}
.oh-try{margin:1.4rem 0 .6rem;font-size:1.02rem;color:var(--text-soft)}
.oh-examples{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.6rem}
.oh-examples form,.oh-canask form{margin:0}
.oh-examples .ask-example,.oh-canask .ask-example{font-size:1.02rem;color:var(--text-strong);
  border:1.5px solid var(--edge);padding:.6rem 1.05rem;min-height:3rem;line-height:1.3}
.oh-examples .ask-example::before,.oh-canask .ask-example::before{content:"\201C"}
.oh-examples .ask-example::after,.oh-canask .ask-example::after{content:"\201D"}
.oh-examples .ask-example:hover,.oh-canask .ask-example:hover{color:var(--fern-glow);border-color:var(--fern-light)}
.oh-ask-hero .v2-trust{margin:1.5rem 0 0}
.oh-h3{font-size:clamp(1.5rem,3vw,1.95rem);line-height:1.15;letter-spacing:-.02em;
  color:var(--text-strong);margin:2.6rem 0 1rem}
/* The two tools, side by side from 700px. The button is the page's primary:
   fern-glow with the page's own ink on it, which the light theme swaps for
   dark green and bone (b.css's tokens, the way .v2-btn does it). */
.oh-tools{display:grid;gap:1rem}
@media (min-width:700px){.oh-tools{grid-template-columns:1fr 1fr;gap:1.3rem}}
.oh-tool{display:flex;flex-direction:column;gap:.85rem}
.oh-tool>h3{margin:0}
.oh-tool p{margin:0}
.oh-tool-icon{width:32px;height:32px;color:var(--fern-light)}
.oh-tool .btn{margin-top:auto;justify-content:center;text-align:center;background:var(--fern-glow);
  color:var(--ink);min-height:3.5rem;font-size:1.05rem}
.oh-tool .btn:hover{filter:brightness(1.07)}
.oh-tool-note{font-size:.95rem;color:var(--text-softer)}
.oh-today{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;flex-wrap:wrap}
.oh-today .oh-h3{margin-bottom:.2rem}
.oh-today a{font-size:1rem}
.oh-page .oh-tiles{margin-top:1rem}
/* What the site knows, chapter by chapter: the chapter's name is a link
   to its heading below, the question beside it goes into the box. */
.oh-canask-lede{font-size:clamp(1.08rem,2vw,1.2rem);line-height:1.6;color:var(--text-soft);
  max-width:42rem;margin:0}
.oh-canask{list-style:none;padding:0;margin:1.2rem 0 0}
.oh-canask li{display:grid;gap:.6rem;padding:1rem 0;border-top:1px solid var(--line)}
.oh-canask li:last-child{border-bottom:1px solid var(--line)}
@media (min-width:760px){.oh-canask li{grid-template-columns:1fr 1.25fr;align-items:center;gap:1.5rem}}
.oh-canask a{text-decoration:none;color:inherit}
.oh-canask a b{display:block;font-family:"Inter var",Inter,sans-serif;font-weight:500;
  font-size:1.25rem;letter-spacing:-.02em;color:var(--text-strong)}
.oh-canask a:hover b{color:var(--fern-glow)}
.oh-canask a span{color:var(--text-softer);font-size:1rem;line-height:1.45}
.oh-canask form{justify-self:start}
.oh-page .place-chapters{margin-top:2.2rem}
.oh-community{margin:2rem 0 1.6rem}
.oh-counties .ohio-pick{display:flex;gap:.5rem;margin:0 0 1rem}
.oh-counties .ohio-pick select{flex:1;min-width:0;padding:.85rem 1rem;border-radius:14px;
  border:1px solid var(--line);background:var(--surface-raise);color:var(--text-strong);font:inherit;font-size:1rem}
.oh-counties .ohio-pick select:focus-visible{outline:3px solid var(--fern-glow);outline-offset:2px}

/* ================= Where you are: the place pin (6 Oct 2026) ============ */
/* One line pinned under the announcement strip once the place header has
   scrolled away (js/place.js), and under the nav pill whenever the pill is
   back — b.js hides the pill on the way down and returns it on the way
   up, so on a phone the two take turns rather than stacking. The place
   gives way to "…" before the chapter does; the county is dropped on a
   phone. Under the menu (65), which covers it, and over the page. */
:root{--pin-h:2.75rem}
.place-pin{position:fixed;inset-inline:0;top:var(--banner-now,var(--banner-h,0px));z-index:64;
  height:var(--pin-h);display:flex;align-items:center;padding:0 var(--pad);
  background:var(--ink);
  border-bottom:1px solid var(--line);color:var(--text-strong);text-decoration:none;
  font-size:1rem;opacity:0;pointer-events:none;
  transition:opacity .25s var(--easing),transform .5s var(--easing)}
.place-pin[hidden]{display:none}
.place-pin.is-shown{opacity:1;pointer-events:auto}
:root:has(.nav-wrap:not(.is-hidden)) .place-pin{transform:translateY(var(--nav-h,0px))}
/* Under the pill, the pin's ground reaches up behind it, so the page does
   not show through the gap round the pill and the two read as one header.
   With the pill away it sits above the screen, out of sight. */
.place-pin::before{content:"";position:absolute;inset-inline:0;bottom:100%;
  height:var(--nav-h,0px);background:inherit;pointer-events:none}
.pin-in{display:flex;align-items:baseline;gap:.4rem;width:100%;max-width:52rem;margin:0 auto;
  min-width:0;white-space:nowrap}
.pin-place{font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto}
.pin-county{color:var(--text-soft);flex:none}
.pin-chapter{color:var(--fern-light);flex:none}
.pin-chapter[hidden]{display:none}
.pin-sep{color:var(--text-faint)}
.pin-up{margin-left:auto;padding-left:.8rem;flex:none;font-size:.9rem;color:var(--text-softer)}
.place-pin:hover .pin-up{color:var(--text-strong)}
@media (max-width:560px){.pin-county{display:none}}
/* A jump to a card lands below the pin as well as the pill. */
:root:has(.place-pin) .anchor{scroll-margin-top:calc(8.5rem + var(--pin-h) + var(--banner-now,var(--banner-h,0px))))}
/* The budget forecast's pinned table headings sit under the pin too. */
:root:has(.place-pin.is-shown) .fcst-page .hub-panel .fig-scroll.fits thead th{
  top:calc(5.9rem + var(--pin-h) + var(--banner-now,var(--banner-h,0px)))}
:root:has(.place-pin.is-shown):has(.nav-wrap.is-hidden) .fcst-page .hub-panel .fig-scroll.fits thead th{
  top:calc(var(--pin-h) + var(--banner-now,var(--banner-h,0px)))}
@media print{.place-pin{display:none !important}}

/* ============ Scenes behind the first screen (§27, 7 Oct 2026) ========== */
/* On /market/ohio/v2 only, until promoted. The rentals hero's frames and
   drift (b.css .hero-media), on a full-bleed stage from under the nav to
   the foot of the trust line. Two scrims as the rentals hero has — down
   the page for the nav and the fade, left-weighted so the words keep
   contrast while the right of the picture stays open — and the fade ends
   in the page's own ground, which light mode turns to paper. The stage
   keeps the dark theme's tokens (b.css photo surfaces), so its words stay
   light on the picture in both themes; --page-ground is taken from the
   body, outside that exemption, so the fade still meets the real page. No
   words sit on the fade: the content ends above the stage's last stretch,
   where only the caption is. */
body{--page-ground:var(--ink)}
/* Its own ground fades too: a stage of fractional height left its last
   part-pixel row showing #111110 under the scrim, a grey line on paper. */
/* The fade is the stage's own bottom padding, in length, not a share of
   its height (7 Oct 2026): at 84%–96% it began a fixed fraction down a
   stage whose words end a fixed length from its foot, so on a laptop the
   trust line sat on it, light words going pale with the paper behind them
   in light mode. Now it starts where the words end, whatever the height. */
.oh-stage{--stage-fade:clamp(4.2rem,9vw,6.5rem);position:relative;overflow:hidden;
  background:linear-gradient(180deg,#111110 0%,#111110 calc(100% - var(--stage-fade)),
    var(--page-ground) calc(100% - var(--stage-fade) * .25));
  padding-bottom:var(--stage-fade)}
/* The pictures end where the fade has reached the page's ground: on a
   part-pixel last row, a picture's edge showed under the scrim as a dark
   line across the paper. */
.oh-scenes{z-index:0;bottom:calc(var(--stage-fade) * .25)}
.oh-scenes picture{display:contents}
/* A slower, even crossfade than the rentals hero's (the user, 8 Oct 2026):
   these pictures sit behind a question being read and typed, and a quick
   dissolve at the edge of the eye pulls at it where a slow one does not.
   The rentals hero, a showcase, keeps its own. */
.hero-media.oh-scenes img{transition:opacity 2.4s ease-in-out}
/* Each frame says where its subject is (app/scenes.py): --focus on the
   landscape files, --focus-phone inside its tall phone cut. The media query
   is scenes.PHONE_MEDIA, the one the cut's <source> answers to; a test
   holds the two equal. */
.oh-scenes img{object-position:var(--focus,50% 50%)}
@media (max-width: 539px){.oh-scenes img{object-position:var(--focus-phone,var(--focus,50% 50%))}}
.oh-stage::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:
  linear-gradient(180deg,rgba(17,17,16,.62) 0%,rgba(17,17,16,.4) 26%,rgba(17,17,16,.66) 68%,
    rgba(17,17,16,.82) calc(100% - var(--stage-fade)),var(--page-ground) calc(100% - var(--stage-fade) * .25),
    var(--page-ground) 100%),
  linear-gradient(90deg,rgba(17,17,16,.74) 0%,rgba(17,17,16,.46) 48%,rgba(17,17,16,.08) 100%)}
.oh-stage-inner{position:relative;z-index:2}
.oh-stage .v2-hero{margin-bottom:0}
/* Where the picture is, in one small line, out of the way — and the way
   to see it whole (the viewer, §27.12): the little arrow-out-of-a-box says
   so, and on a touch screen the pill is a thumb's height. */
.oh-scene-caption{position:absolute;right:var(--pad);bottom:1.1rem;z-index:2;margin:0;
  font-size:.8rem;letter-spacing:.01em;color:rgba(250,247,242,.8);max-width:calc(100% - 2 * var(--pad));
  text-align:right}
/* Dark enough to read on its own: it sits where the stage has faded to the
   page, which light mode makes paper, and a half-clear pill there was light
   words on pale grey. */
.oh-scene-caption a{display:inline-flex;align-items:center;gap:.45rem;color:#F2EEE6;text-decoration:none;
  background:rgba(17,17,16,.78);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  padding:.38rem .8rem;border-radius:999px;text-align:left}
.oh-scene-caption a:hover,.oh-scene-caption a:focus-visible{color:#FFFFFF;background:rgba(17,17,16,.92)}
.oh-scene-caption a:hover [data-hero-caption]{text-decoration:underline;text-underline-offset:2px}
.oh-scene-open{flex:none;opacity:.85}
/* A picture's credit, when it is not the user's own (25 Oct 2026): beside
   the caption, smaller and quieter, on the same dark pill in both themes,
   and under it where the two do not fit on one line (a phone). */
.oh-scene-words{display:inline-flex;flex-wrap:wrap;align-items:baseline;column-gap:.5rem;row-gap:.05rem}
.oh-scene-credit{font-size:.7rem;color:rgba(242,238,230,.74)}
.oh-scene-credit[hidden]{display:none}
@media (pointer:coarse){.oh-scene-caption a{min-height:44px;padding:.5rem 1rem}}
.oh-scene-caption[hidden]{display:none}
.oh-after-stage{padding-top:.5rem}
@media print{.oh-scenes,.oh-scene-caption{display:none}}

/* =============== Not in Ohio, up the page (7 Oct 2026) ================== */
.oh-elsewhere{margin:2rem 0 0;padding:1.1rem 1.2rem;border:1px solid var(--line);
  border-radius:16px;background:var(--surface-raise)}
.oh-elsewhere p{margin:0;font-size:1.05rem;line-height:1.55;color:var(--text-soft)}
.oh-elsewhere strong{color:var(--text-strong)}
.oh-elsewhere-go{display:flex;flex-wrap:wrap;gap:.5rem 1.4rem;margin-top:.6rem !important}
.oh-elsewhere-go a{color:var(--fern-light);font-weight:500;min-height:44px;display:inline-flex;align-items:center}

/* ======== The box's examples in turn, gently (7 Oct 2026) =============== */
.ask-xl .ask-row input::placeholder{transition:opacity .45s var(--easing)}
.ask-xl .ask-row input.is-swapping::placeholder{opacity:0}
@media (prefers-reduced-motion:reduce){.ask-xl .ask-row input::placeholder{transition:none}}

/* A school's record in its district's table (8 Oct 2026): its name opens
   every year held, and the row the question box sends a reader to is
   marked. */
.school-more summary{cursor:pointer;color:var(--text-strong);list-style:none}
.school-more summary::-webkit-details-marker{display:none}
.school-more summary::after{content:" \25B8";color:var(--fern-light);font-size:.85em}
.school-more[open] summary::after{content:" \25BE"}
.school-more summary:hover,.school-more summary:focus-visible{text-decoration:underline;text-underline-offset:3px}
/* Open, the record takes the room a year's line needs, so each reads on
   one line on a laptop; the table scrolls sideways on a phone as it did. */
.school-more[open]{min-width:min(19rem,72vw)}
.school-more .school-more-what,.school-more .school-years{font-weight:400;font-size:.84rem;line-height:1.45;color:var(--text-soft)}
.school-more .school-more-what{margin:.45rem 0 .3rem}
.school-more .school-years{list-style:none;margin:0 0 .3rem;padding:0}
.school-more .school-years li{display:grid;grid-template-columns:4.4rem 1fr;gap:.4rem;padding:.14rem 0;font-variant-numeric:tabular-nums}
.school-more .school-years span{color:var(--text-strong)}
tr.anchor:target > th,tr.anchor:target > td,
tr.anchor.is-here > th,tr.anchor.is-here > td{background:rgba(127,168,140,.16)}
