/* Greenville County Tax Estimator
   Diagnostic-instrument UI. See DESIGN.md for the approved contract.

   Three token layers govern this file. Nothing below :root should introduce a
   raw value that belongs in one of them.

   SPACE   A 4px ladder (--space-*). Every responsive pad uses ONE vw
           coefficient (2.4) so the page gutter, the panels and the header
           grow at the same rate and their left edges stay locked together.
   TYPE    Seven sizes (--fs-*): two prose, two data, three display.
           DESIGN.md floors: body 16px at 1.55-1.65, metadata 11-13px.
   COLOUR  Named roles only. --rule is context-scoped: signal-tinted regions
           re-point it, everything else inherits the structural grey.

   Weights: a system stack resolves four steps and silently rounds anything
   else. 400 prose / 500 captions / 600 controls and metadata / 700 display.
   Do not introduce a fifth. */

:root {
  /* Colour */
  --canvas: #eef2f5;
  --surface: #ffffff;
  --surface-subtle: #f7f9fb;
  --surface-signal: #f7fbff;
  --ink: #111820;
  --muted: #5b6875;
  --muted-strong: #465361;
  --line: #c8d1da;
  --line-strong: #767f8c;
  --line-signal: #b8d4f3;
  --line-signal-strong: #9fc5ef;
  --signal: #0b67d1;
  --signal-dark: #064b9b;
  --signal-soft: #eaf3fe;
  --positive: #137a63;
  --positive-soft: #e8f5f1;
  --positive-line: #84bcae;
  --warning: #9a5b13;
  --warning-soft: #fdf3e6;
  --warning-line: #d8b380;
  --danger: #9b2c2c;
  --shadow-float: 0 12px 30px rgba(17, 24, 32, 0.14);

  /* The 1px rule colour for whatever region you are inside. */
  --rule: var(--line);

  /* Space */
  --space-2xs: 4px;
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;

  /* Responsive padding. One coefficient, three bands. */
  --pad-page: clamp(var(--space-sm), 2.4vw, var(--space-xl));
  --pad-panel: clamp(var(--space-md), 2.4vw, var(--space-lg));
  --pad-readout: clamp(var(--space-md), 2.4vw, var(--space-xl));

  /* Derived, not chosen: a disclosure body sits on its summary's text axis,
     which is the marker column (24) plus the column gap (8). If the summary
     grid changes, this changes with it. */
  --disclosure-indent: var(--space-xl);

  /* Every rule-separated row in the parameter list shares this. */
  --row-pad-y: var(--space-sm);

  /* Type */
  --fs-meta: 0.6875rem;   /* 11px  uppercase mono metadata */
  --fs-data: 0.8125rem;   /* 13px  figures, table cells, kickers */
  --fs-body: 1rem;        /* 16px  all running prose */
  --fs-lead: 1.125rem;    /* 18px  prompts, questions, disclosure headings */
  --fs-title: clamp(1.375rem, 3vw, 1.75rem);  /* 22-28px  section titles */
  --fs-display: clamp(2rem, 5vw, 3.25rem);    /* 32-52px  page + rate figures */
  --fs-figure: clamp(3rem, 10vw, 5.5rem);     /* 48-88px  the one result */

  --track-meta: 0.05em;

  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 6px;

  --font-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body.estimator-page {
  margin: 0;
  min-width: 320px;
  padding: var(--pad-page);
  color: var(--ink);
  background: var(--canvas);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.55;
  text-rendering: optimizeLegibility;
}

/* The centred measure lives here, not on <main>: the banner and contentinfo
   landmarks are siblings of <main>, so a container on <main> would let the
   header and footer escape it and break their alignment with the panels. */
.estimator-page .page-shell {
  width: min(100%, 1120px);
  margin: 0 auto;
  padding-bottom: var(--space-2xl);
}

.estimator-page [hidden] {
  display: none !important;
}

/* All three of these resets are wrapped in :where() for the same reason as the
   font reset below: as plain selectors they are (0,1,1) and silently beat every
   single-class component rule at (0,1,0). Measured before the wrap: ten elements
   had their declared top margin zeroed (.or-custom, .custom-income-hint,
   .result-basis, .readout-meta, .disclaimer, .ballot-source-note, .ballot-q-sub,
   .ballot-gis-attrib, .result-annual, .ballot-hint), .result-label lost its muted
   colour to the heading rule, and .next-step lost its ink colour to the link rule.
   The whole vertical rhythm was declared and then discarded. */
:where(.estimator-page h1, .estimator-page h2, .estimator-page h3,
       .estimator-page p, .estimator-page dl, .estimator-page dd) {
  margin-top: 0;
}

:where(.estimator-page h1, .estimator-page h2, .estimator-page h3) {
  color: var(--ink);
  font-family: var(--font-sans);
}

:where(.estimator-page a) {
  color: var(--signal-dark);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.estimator-page a:hover {
  color: var(--signal);
}

/* :where() so this contributes ZERO specificity. As a plain selector it is
   (0,1,1) and silently beat every component's font declaration: .tile, .choice,
   .custom-toggle, .reset-btn and .spending-input all rendered at inherited
   sans 400 rather than the mono and weights declared for them, and
   #custom-income inherited 13.12px, which makes iOS zoom the page on focus. */
:where(.estimator-page button, .estimator-page input, .estimator-page summary) {
  font: inherit;
}

.estimator-page button,
.estimator-page summary {
  -webkit-tap-highlight-color: transparent;
}

.estimator-page :focus-visible {
  outline: 3px solid var(--signal);
  outline-offset: 3px;
}

.estimator-page .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Callout. One grammar: a tinted plane carried on a 3px rule. The fill, the
   boundary and the rule colour vary by context; the padding never does.
   Signal is the default; --callout-rule lets a caveat carry the same shape in
   the warning role without a second set of declarations. */
.rate-readout,
.customize-total,
.ballot-output,
.ballot-source-note,
.result-basis.is-stale,
.method-toc {
  padding: var(--space-md);
  background: var(--callout-fill, var(--signal-soft));
  border: 1px solid var(--callout-line, var(--line-signal-strong));
  border-left: 3px solid var(--callout-rule, var(--signal));
}

/* Instrument header */
.instrument-header {
  margin-bottom: var(--space-lg);
  background: var(--surface);
  border: 1px solid var(--line-strong);
}

.product-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: var(--space-2xl);
  padding: var(--space-xs) var(--pad-panel);
  border-bottom: 1px solid var(--line);
  background: var(--surface-subtle);
}

.system-id,
.system-status {
  margin-bottom: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.system-id {
  color: var(--muted-strong);
}

.system-mark {
  display: inline-grid;
  place-items: center;
  min-width: 2.5rem;
  min-height: var(--space-lg);
  margin-right: var(--space-xs);
  color: var(--surface);
  background: var(--ink);
  border-radius: var(--radius-xs);
  letter-spacing: var(--track-meta);
}

.system-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  color: var(--positive);
  white-space: nowrap;
}

.status-light {
  display: inline-block;
  width: var(--space-xs);
  height: var(--space-xs);
  flex: 0 0 auto;
  background: var(--positive);
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--positive-soft);
}

/* Horizontal padding matches the panels below exactly, so the H1 and the
   panel headings share one left edge at every width. The header's extra
   breathing room is bought vertically, where it disturbs nothing. */
.title-row {
  display: grid;
  gap: var(--space-lg);
  padding: clamp(var(--space-lg), 2.4vw, var(--space-xl)) var(--pad-panel);
}

.eyebrow {
  margin-bottom: var(--space-sm);
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.estimator-page h1 {
  max-width: 16ch;
  margin-bottom: var(--space-sm);
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.98;
}

.intro {
  max-width: 42rem;
  margin-bottom: 0;
  color: var(--muted-strong);
  font-size: var(--fs-lead);
}

.rate-readout {
  --callout-fill: var(--surface-subtle);
  --callout-line: var(--line);

  align-self: start;
  min-width: 13rem;
}

.rate-readout span,
.rate-readout small {
  display: block;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.rate-readout strong {
  display: block;
  margin: var(--space-2xs) 0;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-display);
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.04em;
  line-height: 1;
}

/* Shared instrument panels */
.estimator-workbench {
  display: grid;
  gap: var(--space-lg);
}

.input-section,
.result-section,
.ballot-section {
  min-width: 0;
  padding: var(--pad-panel);
  background: var(--surface);
  border: 1px solid var(--line-strong);
}

.section-heading {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.section-heading span {
  color: var(--signal);
}

.section-heading p {
  margin-bottom: 0;
}

.prompt {
  margin-bottom: var(--space-sm);
  font-size: var(--fs-lead);
  font-weight: 700;
}

.input-explainer {
  max-width: 40rem;
  margin-bottom: var(--space-md);
  color: var(--muted);
  font-size: var(--fs-body);
}

/* The accepted range for the custom income field. This is a standing constraint,
   not a caveat, so its resting state is quiet metadata: a valid entry must not be
   annotated in the warning colour, which reads as an error against a correct value.
   It escalates to --warning only while the input is actually out of range. The
   error itself is stated in words by .result-basis.is-stale, so colour reinforces
   the message rather than carrying it. */
.custom-income-hint {
  margin: var(--space-xs) 0 0;
  margin-bottom: 0;
  color: var(--muted);
  font-size: var(--fs-data);
}

.or-custom:has(#custom-income[aria-invalid="true"]) + .custom-income-hint {
  color: var(--warning);
  font-weight: 500;
}

/* Household inputs */
.tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-xs);
}

.tile,
.choice {
  min-height: var(--space-2xl);
  padding: var(--space-xs) var(--space-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  transition: background 120ms ease-out, border-color 120ms ease-out, color 120ms ease-out;
}

.tile small {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: var(--track-meta);
  line-height: 1;
  text-transform: uppercase;
}

.tile:hover,
.choice:hover {
  background: var(--surface-subtle);
  border-color: var(--signal);
}

.tile.selected,
.choice.selected {
  color: var(--surface);
  background: var(--signal-dark);
  border-color: var(--signal-dark);
  box-shadow: inset 0 0 0 1px var(--signal-dark);
}

/* Without this a selected preset is the one control on the page that gives no
   hover feedback: .selected and :hover are both (0,2,0) and .selected wins on
   source order. */
.tile.selected:hover,
.choice.selected:hover {
  background: var(--signal);
  border-color: var(--signal);
  box-shadow: inset 0 0 0 1px var(--signal);
}

.custom-toggle,
.reset-btn {
  min-height: 44px;
  color: var(--signal-dark);
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: var(--fs-body);
  font-weight: 600;
}

.custom-toggle {
  display: block;
  width: 100%;
  margin-top: var(--space-md);
  padding: var(--space-xs) 0;
  text-align: left;
}

.custom-toggle:hover,
.reset-btn:hover {
  color: var(--signal);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* --space-md, not --space-sm, above both of these: the focus ring is a 3px
   outline at a 3px offset, so it extends 6px past the control on every side. At
   12px the ring lands on the preset tiles above. 16px keeps the group tight while
   leaving the ring 10px of clear air. */
.or-custom {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  margin: var(--space-md) 0 0;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-body);
}

.input-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.dollar {
  position: absolute;
  left: var(--space-xs);
  z-index: 1;
  color: var(--muted);
  font-family: var(--font-mono);
  pointer-events: none;
}

/* 16px is a floor, not a preference: iOS zooms the viewport on focus for any
   text input below it. */
#custom-income,
#taxable-value,
.spending-input,
.ballot-address-input {
  min-height: 44px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  font-size: var(--fs-body);
}

#custom-income,
#taxable-value,
.spending-input {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

#custom-income,
#taxable-value {
  width: 9.5rem;
  padding: var(--space-xs) var(--space-sm) var(--space-xs) var(--space-lg);
  font-weight: 600;
}

#custom-income::placeholder,
#taxable-value::placeholder,
.ballot-address-input::placeholder {
  color: var(--muted);
  opacity: 1;
  font-weight: 400;
}

#custom-income:focus-visible,
#taxable-value:focus-visible,
.spending-input:focus-visible,
.ballot-address-input:focus-visible {
  border-color: var(--signal);
}

.per-year {
  white-space: nowrap;
}

/* Primary result */
.result-section {
  border-top: 3px solid var(--signal);
}

.result-readout {
  --rule: var(--line-signal);

  position: relative;
  padding: var(--pad-readout);
  overflow: hidden;
  background: linear-gradient(180deg, var(--surface-signal) 0%, var(--signal-soft) 100%);
  border: 1px solid var(--line-signal-strong);
}

.result-readout::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 4.5rem;
  height: var(--space-2xs);
  background: repeating-linear-gradient(90deg, var(--signal) 0 1px, transparent 1px 9px);
}

/* Customized readout (DESIGN.md: Result readout / customized). The same 3px
   signal rule the customized parameter row carries, so the two states read as
   one idea. Painted inside the border box rather than added to it, so the
   state costs no reflow; the enabled Reset button carries the same meaning
   without colour. */
.result-readout.is-customized::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 3px;
  background: var(--signal);
}

.result-label {
  max-width: 38rem;
  margin: 0 auto;
  color: var(--muted-strong);
  font-size: var(--fs-body);
  font-weight: 500;
  text-align: center;
}

.result-annual {
  margin: var(--space-xs) 0 var(--space-sm);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--fs-figure);
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.05em;
  line-height: 0.98;
  text-align: center;
}

.result-annual .per {
  margin-left: var(--space-xs);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-data);
  font-weight: 600;
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.result-sub {
  margin-bottom: 0;
  color: var(--muted-strong);
  font-size: var(--fs-body);
  text-align: center;
}

.result-sub strong {
  color: var(--ink);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.result-basis {
  margin: var(--space-sm) 0 0;
  color: var(--muted);
  font-size: var(--fs-body);
  text-align: center;
}

/* Stale readout: the figure above this line no longer reflects what is typed.
   The callout grammar in the warning role (DESIGN.md: "caveats that need
   attention but are not errors"). Left-aligned because it is a sentence to
   read, not a caption under the figure. Colour only reinforces it: the line
   says "Estimate not updated" in words, and the field carries aria-invalid. */
.result-basis.is-stale {
  --callout-fill: var(--warning-soft);
  --callout-line: var(--warning-line);
  --callout-rule: var(--warning);

  color: var(--warning);
  text-align: left;
}

/* Model-state strip. One component, used on both pages: the readout's copy
   sits on a signal-tinted plane and the methodology's on white, which is the
   only thing --rule resolves differently. */
.readout-meta,
.method-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: var(--space-md) 0 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.readout-meta > div,
.method-meta > div {
  min-width: 0;
  padding: var(--space-sm) var(--space-xs);
  border-right: 1px solid var(--rule);
  text-align: center;
}

.readout-meta > div:last-child,
.method-meta > div:last-child {
  border-right: 0;
}

.readout-meta dt,
.readout-meta dd,
.method-meta dt,
.method-meta dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  letter-spacing: var(--track-meta);
  line-height: 1.35;
  text-transform: uppercase;
}

.readout-meta dt,
.method-meta dt {
  margin-bottom: var(--space-2xs);
  color: var(--muted);
}

.readout-meta dd,
.method-meta dd {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  color: var(--ink);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Disclosures and parameter controls */
.exempt-callout,
.customize,
.ballot-combined-disclosure {
  margin: 0;
  border: 0;
  border-bottom: 1px solid var(--line);
}

.exempt-callout {
  margin-top: var(--space-md);
  border-top: 1px solid var(--line);
}

/* Ruled row, part 1: the disclosure headers. Same vertical rhythm as the
   parameter rows below them. */
.customize summary,
.exempt-callout summary,
.ballot-combined-disclosure summary {
  display: grid;
  grid-template-columns: var(--space-lg) minmax(0, 1fr);
  column-gap: var(--space-xs);
  align-items: center;
  min-height: 52px;
  padding: var(--row-pad-y) 0;
  color: var(--ink);
  cursor: pointer;
  font-size: var(--fs-lead);
  font-weight: 600;
  list-style: none;
}

.customize summary::-webkit-details-marker,
.exempt-callout summary::-webkit-details-marker,
.ballot-combined-disclosure summary::-webkit-details-marker {
  display: none;
}

.customize summary::before,
.exempt-callout summary::before,
.ballot-combined-disclosure summary::before {
  content: "+";
  display: grid;
  grid-column: 1;
  grid-row: 1;
  place-items: center;
  width: var(--space-lg);
  height: var(--space-lg);
  color: var(--signal-dark);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xs);
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  line-height: 1;
}

.customize[open] > summary::before,
.exempt-callout[open] > summary::before,
.ballot-combined-disclosure[open] > summary::before {
  content: "−";
}

.customize summary span,
.customize summary small,
.exempt-callout summary span {
  display: block;
  grid-column: 2;
}

.customize summary small,
.exempt-preview {
  margin-top: var(--space-2xs);
  color: var(--muted);
  font-size: var(--fs-body);
  font-weight: 400;
}

.exempt-lead {
  color: var(--positive);
}

/* auto-fit rather than a breakpoint: the list drops to one column whenever
   there is not room for two, which is the only thing the old 500px query did. */
.exempt-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-xs) var(--space-md);
  margin: 0 0 var(--space-md) var(--disclosure-indent);
  padding-left: var(--space-md);
  color: var(--muted-strong);
  font-size: var(--fs-body);
}

.exempt-list li::marker {
  color: var(--positive);
}

/* Expanded content stays on the summary's text axis. If the summary grid
   columns change, --disclosure-indent changes with them. */
.customize-body {
  padding: 0 0 var(--space-md) var(--disclosure-indent);
}

.customize-hint {
  margin: 0 0 var(--space-md);
  color: var(--muted);
  font-size: var(--fs-body);
}

.customize-total {
  --callout-fill: var(--surface-signal);

  position: sticky;
  top: var(--space-xs);
  z-index: 2;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-sm);
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-data);
  font-variant-numeric: tabular-nums;
}

.customize-total strong {
  font-size: var(--fs-lead);
  font-weight: 700;
}

#customize-sliders {
  border-top: 1px solid var(--line);
}

/* Ruled row, part 2: the parameter rows. .slider-row and .other-row are
   adjacent siblings in the same list, so they must share one rhythm. */
.slider-row {
  position: relative;
  padding: var(--row-pad-y) 0;
  border-bottom: 1px solid var(--line);
}

/* Customized parameter (DESIGN.md: Parameter row / customized). The signal
   rule is painted in the disclosure gutter rather than added to the box, so
   toggling the state moves nothing. The class is applied by estimator.js. */
.slider-row.is-customized::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-1 * (var(--space-xs) + 3px));
  width: 3px;
  background: var(--signal);
}

/* --space-xs, not --space-2xs: the range input below carries the same 6px focus
   ring as every other control, and at 4px it painted over this label. */
.slider-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: var(--space-xs);
  font-size: var(--fs-body);
}

.slider-name {
  font-weight: 600;
}

.category-tax {
  flex: 0 0 auto;
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.slider-controls {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-sm);
}

.spending-input-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
}

.spending-input {
  width: 5rem;
  padding: var(--space-2xs) var(--space-xs);
  font-weight: 600;
  text-align: right;
}

.slider-row input[type="range"] {
  width: 100%;
  height: 44px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.slider-row input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  background: var(--line);
  border-radius: 0;
}

/* 28px, not the 20/16 this drifted to: WCAG 2.5.8 floors a target at 24px.
   The -12px centres a 28px thumb on a 4px track. */
.slider-row input[type="range"]::-webkit-slider-thumb {
  width: 28px;
  height: 28px;
  margin-top: -12px;
  background: var(--surface);
  border: 3px solid var(--signal);
  border-radius: 50%;
  appearance: none;
  -webkit-appearance: none;
}

.slider-row input[type="range"]::-moz-range-track {
  height: 4px;
  background: var(--line);
}

.slider-row input[type="range"]::-moz-range-progress {
  height: 4px;
  background: var(--signal);
}

.slider-row input[type="range"]::-moz-range-thumb {
  width: 28px;
  height: 28px;
  background: var(--surface);
  border: 3px solid var(--signal);
  border-radius: 50%;
}

.slider-row input[type="range"]:focus-visible {
  outline-offset: 0;
}

/* Ruled row, part 3. flex-wrap rather than a breakpoint: the amount drops to
   its own line whenever the label cannot hold its 14rem basis. */
.other-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-xs) var(--space-md);
  padding: var(--row-pad-y) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-body);
}

.other-label {
  display: flex;
  flex: 1 1 14rem;
  flex-direction: column;
  gap: var(--space-2xs);
  font-weight: 600;
}

.other-hint {
  color: var(--muted);
  font-size: var(--fs-body);
  font-weight: 400;
}

.other-monthly {
  flex: 0 0 auto;
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-data);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.utilities-row .other-monthly {
  color: var(--positive);
}

.utilities-amount,
.utilities-monthly {
  font-variant-numeric: tabular-nums;
}

.exempt-badge {
  display: inline-block;
  margin-left: var(--space-2xs);
  padding: 0 var(--space-2xs);
  color: var(--positive);
  background: var(--positive-soft);
  border: 1px solid var(--positive-line);
  border-radius: var(--radius-xs);
  font-size: var(--fs-meta);
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.reset-btn {
  display: block;
  margin: var(--space-sm) 0 0 auto;
  padding: var(--space-xs) 0;
}

.reset-btn:disabled {
  color: var(--muted);
  cursor: default;
  opacity: 0.55;
  text-decoration: none;
}

.disclaimer {
  margin: var(--space-md) 0 0;
  color: var(--muted);
  font-size: var(--fs-body);
}

/* Ballot context */
.ballot-section {
  margin-top: var(--space-lg);
}

.ballot-h {
  margin-bottom: var(--space-sm);
  font-size: var(--fs-title);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.ballot-intro {
  max-width: 50rem;
  margin-bottom: 0;
  color: var(--muted);
  font-size: var(--fs-body);
}

.plan-comparison {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 2px solid var(--signal-dark);
}

.comparison-kicker {
  margin: 0 0 var(--space-2xs);
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.plan-comparison h3 {
  max-width: 48rem;
  margin-bottom: var(--space-sm);
  font-size: var(--fs-lead);
  line-height: 1.3;
}

.plan-comparison > p:not(.comparison-kicker, .comparison-note) {
  max-width: 52rem;
}

.comparison-key {
  font-weight: 700;
}

.plan-comparison-table {
  display: block;
  width: 100%;
  margin-top: var(--space-md);
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.plan-comparison-table thead {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.plan-comparison-table tbody,
.plan-comparison-table tr,
.plan-comparison-table th,
.plan-comparison-table td {
  display: block;
}

.plan-comparison-table tr {
  padding: var(--space-xs) 0;
  border-top: 1px solid var(--line);
}

.plan-comparison-table th,
.plan-comparison-table td {
  padding: var(--space-2xs) 0;
  text-align: left;
  vertical-align: top;
}

.plan-comparison-table th[scope="row"] {
  color: var(--ink);
  font-weight: 700;
}

.plan-comparison-table td {
  display: grid;
  grid-template-columns: minmax(8.5rem, 1fr) auto;
  gap: var(--space-sm);
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-weight: 700;
}

.plan-comparison-table td::before {
  content: attr(data-label);
  color: var(--muted);
  font-family: var(--font-sans);
  font-weight: 500;
}

.comparison-subuses {
  display: block;
  margin-top: var(--space-2xs);
  color: var(--muted);
  font-size: var(--fs-meta);
  font-weight: 500;
  line-height: 1.4;
}

.comparison-note {
  margin: var(--space-xs) 0 0;
  color: var(--muted);
  font-size: var(--fs-meta);
}

.comparison-lanes {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-md);
}

.comparison-lanes p {
  margin: 0;
  padding: var(--space-sm);
  background: var(--signal-soft);
  border-left: 3px solid var(--signal-dark);
}

.comparison-lanes strong,
.comparison-lanes span {
  display: block;
}

.comparison-lanes strong {
  margin-bottom: var(--space-2xs);
}

.comparison-lanes span {
  color: var(--muted);
  font-size: var(--fs-body);
}

.comparison-thesis {
  margin-top: var(--space-md);
}

.comparison-thesis p {
  margin: var(--space-2xs) 0;
}

.ballot-step {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--line);
}

.ballot-q {
  margin-bottom: var(--space-sm);
  font-size: var(--fs-lead);
  font-weight: 700;
  line-height: 1.35;
}

.ballot-q-sub {
  margin-top: var(--space-lg);
}

/* 12px top and bottom. Adjacent-sibling margins collapse to 12px against
   .ballot-q, which is why the old negative correction is gone. */
.ballot-hint {
  margin: var(--space-sm) 0;
  color: var(--muted);
  font-size: var(--fs-body);
}

.ballot-hint a,
.ballot-link {
  color: var(--signal-dark);
  font-weight: 600;
}

.ballot-choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  gap: var(--space-xs);
}

.ballot-cities {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.choice {
  font-family: var(--font-sans);
  line-height: 1.25;
}

.ballot-input-row {
  margin: 0;
}

.ballot-output {
  --rule: var(--line-signal);

  margin-top: var(--space-lg);
}

.ballot-out-h {
  margin-bottom: var(--space-sm);
  color: var(--ink);
  font-size: var(--fs-lead);
  font-weight: 700;
  line-height: 1.3;
}

.ballot-p {
  margin-bottom: var(--space-sm);
  color: var(--ink);
  font-size: var(--fs-body);
}

.ballot-p:last-child {
  margin-bottom: 0;
}

.ballot-attrib {
  color: var(--muted);
  font-size: var(--fs-body);
}

.ballot-combined {
  margin-top: var(--space-md);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--rule);
}

.ballot-ledger {
  width: 100%;
  margin: 0 0 var(--space-sm);
  border-collapse: collapse;
  color: var(--ink);
  font-size: var(--fs-data);
}

.ballot-ledger caption {
  padding: 0 0 var(--space-sm);
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: 700;
  line-height: 1.35;
  text-align: left;
}

/* Ruled row, part 4. */
.ballot-ledger th,
.ballot-ledger td {
  padding: var(--row-pad-y) 0;
  vertical-align: top;
  border: 0;
  border-bottom: 1px solid var(--rule);
}

.ballot-ledger th {
  width: 48%;
  padding-right: var(--space-sm);
  font-weight: 500;
  text-align: left;
}

.ballot-ledger td {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* The figure column's head. Same uppercase mono metadata voice as
   .rate-readout, because it does the same job: it labels a column of figures
   without competing with them. width:auto is required — .ballot-ledger th
   above sets 48% for the ROW headers, and a width on any cell sizes its whole
   column, so without this the head would try to make the figures 48% too. */
.ballot-ledger thead th {
  width: auto;
  padding-top: 0;
  padding-right: 0;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  font-weight: 600;
  letter-spacing: var(--track-meta);
  text-align: right;
  text-transform: uppercase;
}

.ballot-ledger thead td {
  padding-top: 0;
}

/* The sign glyph is aria-hidden (see signedFigure in estimator.js); the
   accessible text is the visually-hidden "plus"/"minus" beside it. A margin
   rather than a space character, so the gap does not enter the announced
   string and does not depend on the mono font's space metrics. Deliberately
   carries NO colour of its own: a red minus would make this column argue with
   the reader, which is the one thing the ledger may not do. */
.ledger-sign {
  margin-right: 0.2em;
}

.ballot-ledger-total th,
.ballot-ledger-total td {
  color: var(--signal-dark);
  border-top: 2px solid var(--signal-dark);
  border-bottom: 0;
  font-weight: 700;
}

/* The total in words, immediately under the ruled row that states it in
   figures. It is the same claim twice, so it reads as part of the table
   rather than as the first of the footnotes below it. */
.ballot-ledger-plain {
  margin-bottom: var(--space-md);
}

.ballot-combined-disclosure {
  border-bottom: 0;
}

/* Address lookup */
.ballot-paths {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  margin-top: var(--space-sm);
}

.ballot-path {
  min-width: 0;
  padding: var(--space-md);
  background: var(--surface-subtle);
  border: 1px solid var(--line);
}

.ballot-paths.single .ballot-path {
  padding: 0;
  background: transparent;
  border: 0;
}

.ballot-path-h {
  display: block;
  margin-bottom: var(--space-xs);
  font-size: var(--fs-body);
  font-weight: 700;
}

.ballot-combo {
  position: relative;
}

.ballot-address-input {
  width: 100%;
  padding: var(--space-xs) var(--space-sm);
}

/* The one floating surface on the site, and so the one place the largest
   radius and the single approved shadow belong (DESIGN.md: shape, depth). */
.ballot-suggestions {
  position: absolute;
  top: calc(100% + var(--space-2xs));
  right: 0;
  left: 0;
  z-index: 5;
  max-height: 15rem;
  margin: 0;
  padding: var(--space-2xs);
  overflow-y: auto;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-float);
}

.ballot-option {
  min-height: 44px;
  padding: var(--space-sm);
  color: var(--ink);
  border-radius: var(--radius-xs);
  cursor: pointer;
  font-size: var(--fs-body);
  line-height: 1.35;
}

.ballot-option:hover,
.ballot-option.active {
  color: var(--surface);
  background: var(--signal-dark);
}

.ballot-candidates {
  margin-top: var(--space-sm);
}

.ballot-candidate-list {
  display: grid;
  gap: var(--space-xs);
}

.choice-candidate {
  display: block;
  width: 100%;
  padding: var(--space-sm);
  text-align: left;
}

.candidate-street,
.candidate-place,
.candidate-value {
  display: block;
}

.candidate-street {
  font-size: var(--fs-body);
  font-weight: 700;
}

.candidate-place {
  margin-top: var(--space-2xs);
  color: var(--ink);
  font-size: var(--fs-data);
  font-weight: 600;
}

.candidate-value {
  margin-top: var(--space-2xs);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
}

.choice-candidate.selected .candidate-place,
.choice-candidate.selected .candidate-value {
  color: var(--surface);
}

.ballot-gis-attrib {
  margin: var(--space-xs) 0 0;
}

.ballot-source-note {
  margin: var(--space-md) 0 0;
  color: var(--signal-dark);
  font-size: var(--fs-body);
}

.ballot-switch {
  margin: 0 0 var(--space-sm);
  padding-bottom: var(--space-sm);
  color: var(--signal-dark);
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-body);
  font-weight: 600;
}

/* Supporting paths and footer */
.next-steps {
  display: grid;
  gap: var(--space-sm);
  margin-top: var(--space-lg);
}

.next-step {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-md);
  min-height: 58px;
  padding: var(--space-sm) var(--space-md);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  text-decoration: none;
}

.next-step:hover {
  color: var(--ink);
  background: var(--surface-subtle);
  border-color: var(--signal);
}

.next-step span,
.next-step strong {
  display: block;
}

.next-step span {
  color: var(--muted);
  font-size: var(--fs-data);
}

.next-step strong {
  color: var(--signal-dark);
  font-size: var(--fs-body);
}

.estimator-page footer {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  color: var(--muted);
  border-top: 1px solid var(--line);
  font-size: var(--fs-body);
}

/* Sponsor attribution (OneGreenville Fund, supplied 2026-08-17). Sits above the
   data credits and reads a shade stronger, because it is an attribution rather
   than a footnote. Deliberately plain: this is an informational sponsor line,
   NOT a committee "Paid for by" disclosure, and it must not be styled to look
   like one — that disclosure belongs only on the advocacy property. */
.sponsor-note {
  max-width: 64rem;
  margin: 0 0 var(--space-sm);
}

.sponsor-note strong {
  color: var(--muted-strong);
}

/* Scope line. Smaller than the attribution above it because it is a
   qualification of that attribution, not a second sponsor. */
.sponsor-scope {
  max-width: 64rem;
  margin: 0 0 var(--space-md);
  font-size: var(--fs-data);
}

.foot-note {
  max-width: 64rem;
  margin-bottom: 0;
}

.noscript-message {
  position: fixed;
  right: var(--space-md);
  bottom: var(--space-md);
  left: var(--space-md);
  z-index: 10;
  max-width: 40rem;
  margin: auto;
  padding: var(--space-md);
  color: var(--surface);
  background: var(--danger);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-float);
}

.noscript-message a {
  color: var(--surface);
}

/* Methodology */
.methodology-page .page-shell {
  width: min(100%, 840px);
}

/* Same horizontal padding and same vertical generosity as the estimator's
   instrument header, from the same coefficient. */
.methodology-page .method-header {
  margin-bottom: var(--space-lg);
  padding: clamp(var(--space-lg), 2.4vw, var(--space-xl)) var(--pad-panel);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-top: 3px solid var(--signal);
}

.methodology-page .method-header h1 {
  max-width: none;
  margin-bottom: var(--space-sm);
}

.methodology-page .method-header p:last-child {
  margin-bottom: 0;
  color: var(--muted-strong);
}

.methodology-page h2 {
  margin: var(--space-xl) 0 var(--space-sm);
  padding: 0 0 var(--space-xs);
  border-bottom: 1px solid var(--line-strong);
  font-size: var(--fs-title);
  letter-spacing: -0.02em;
}

.methodology-page h3 {
  margin: var(--space-lg) 0 var(--space-sm);
  font-size: var(--fs-lead);
}

.methodology-page p,
.methodology-page li {
  line-height: 1.6;
}

/* The only navigation on this page, so it gets a real target. */
.methodology-page .back,
.methodology-page .back-to-top {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--signal-dark);
  font-family: var(--font-mono);
  font-size: var(--fs-data);
  font-weight: 600;
}

.methodology-page .back {
  margin-bottom: var(--space-md);
}

.methodology-page .method-toc {
  --callout-fill: var(--surface);
  --callout-line: var(--line-strong);

  margin: var(--space-lg) 0 var(--space-xl);
}

.methodology-page .method-toc h2 {
  margin: 0 0 var(--space-sm);
  padding: 0;
  border: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

.methodology-page .method-toc ul {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2xs) var(--space-lg);
  margin: 0;
  padding-left: var(--space-md);
  font-size: var(--fs-body);
}

.methodology-page .table-scroll {
  margin: var(--space-md) 0;
  overflow-x: auto;
  border: 1px solid var(--line-strong);
}

.methodology-page table {
  width: 100%;
  min-width: 500px;
  margin: 0;
  border-collapse: collapse;
  background: var(--surface);
  font-size: var(--fs-data);
}

.methodology-page th,
.methodology-page td {
  padding: var(--space-sm);
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

.methodology-page th:last-child,
.methodology-page td:last-child {
  border-right: 0;
}

.methodology-page tbody tr:last-child td,
.methodology-page tbody tr:last-child th {
  border-bottom: 0;
}

/* thead only. The first column of both evidence tables is th[scope="row"] for
   screen-reader association, and unscoped this rule turned it into a second
   header strip: 11px uppercase mono on a filled cell, beside 13px data. */
.methodology-page thead th {
  color: var(--muted-strong);
  background: var(--surface-subtle);
  font-family: var(--font-mono);
  font-size: var(--fs-meta);
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
}

/* A row header is a data cell that labels its row. Weight alone separates it
   from the cells beside it: same size, same face, no transform, no fill, so
   the column reads as the table's spine rather than as a header band. */
.methodology-page tbody th {
  font-weight: 600;
}

.methodology-page td.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.methodology-page code {
  padding: 0 var(--space-2xs);
  overflow-wrap: break-word;
  color: var(--signal-dark);
  background: var(--signal-soft);
  border-radius: var(--radius-xs);
  font-family: var(--font-mono);
  font-size: 1em;
}

.methodology-page .method-source-note,
.methodology-page .method-updated {
  color: var(--muted);
  font-size: var(--fs-body);
}

.methodology-page .method-source-note {
  margin-top: var(--space-xl);
  margin-bottom: var(--space-2xs);
  padding-top: var(--space-md);
  border-top: 1px solid var(--line);
}

/* DESIGN.md declares three breakpoints and this file implements exactly
   those three: 380 control compaction, 720 ballot/path reflow, 860 workbench
   split. Anything that used to need a fourth is now intrinsic (auto-fit,
   flex-wrap) rather than queried. */

@media (max-width: 379px) {
  .product-line {
    align-items: flex-start;
  }

  .system-id {
    max-width: 13rem;
  }

  .system-mark {
    display: none;
  }

  /* Reduced, never removed: the customized-parameter rule is painted in this
     gutter, so it has to survive down to 320px. */
  .customize-body {
    padding-left: var(--space-sm);
  }

  .exempt-list {
    margin-left: var(--space-sm);
  }

  .ballot-choices {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .readout-meta,
  .method-meta {
    grid-template-columns: 1fr;
  }

  .readout-meta > div,
  .method-meta > div {
    border-right: 0;
    border-bottom: 1px solid var(--rule);
  }

  .readout-meta > div:last-child,
  .method-meta > div:last-child {
    border-bottom: 0;
  }

  .slider-controls {
    grid-template-columns: 1fr;
    gap: var(--space-2xs);
  }

  /* The ledger stacks: a row becomes its label on one line and its figure on
     the next. Verified in Chrome's accessibility tree that table / row /
     rowheader / cell survive display:block, which is the only reason this is
     allowed at all — the row-header pairing is what makes the figures mean
     anything. Both cells of every row are kept for the same reason, including
     the head row's empty corner cell. */
  .ballot-ledger th,
  .ballot-ledger td {
    display: block;
    width: 100%;
    text-align: left;
  }

  .ballot-ledger th {
    padding: var(--space-xs) 0 0;
    border-bottom: 0;
  }

  /* Stacked, the figures keep their column: right-aligned to the same edge, so
     the signs still line up down the right side and the block still scans as a
     ledger rather than as label/value pairs. This is the phone form of the
     alignment the desktop table gets for free. */
  .ballot-ledger td {
    padding: 0 0 var(--space-xs);
    text-align: right;
  }

  /* The head row: a lone right-aligned column label over the figures, ruled
     off from the rows beneath it. The corner cell is empty, so it collapses to
     nothing rather than opening a blank ruled row above the head. */
  .ballot-ledger thead th {
    padding: 0 0 var(--space-xs);
    border-bottom: 1px solid var(--rule);
  }

  .ballot-ledger thead td {
    padding: 0;
    border-bottom: 0;
  }

  .ballot-ledger-total th {
    border-top: 2px solid var(--signal-dark);
  }

  .ballot-ledger-total td {
    border-top: 0;
  }
}

@media (min-width: 720px) {
  .title-row {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
  }

  .tiles {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .ballot-cities {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .plan-comparison-table {
    display: table;
    table-layout: fixed;
  }

  .plan-comparison-table thead {
    position: static;
    display: table-header-group;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }

  .plan-comparison-table tbody {
    display: table-row-group;
  }

  .plan-comparison-table tr {
    display: table-row;
    padding: 0;
  }

  .plan-comparison-table th,
  .plan-comparison-table td {
    display: table-cell;
    padding: var(--space-xs);
    border-top: 1px solid var(--line);
    text-align: center;
  }

  .plan-comparison-table thead th,
  .plan-comparison-table th[scope="row"] {
    text-align: left;
  }

  .plan-comparison-table thead th {
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: 0.02em;
  }

  .plan-comparison-table th:first-child {
    width: 28%;
  }

  .plan-comparison-table td::before {
    display: none;
  }

  .comparison-lanes {
    grid-template-columns: 1fr 1fr;
  }

  .ballot-paths {
    grid-template-columns: 1fr 1fr;
  }

  .ballot-paths.single {
    grid-template-columns: 1fr;
  }

  .methodology-page .method-toc ul {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 860px) {
  .estimator-workbench {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: start;
  }

  .result-section {
    position: relative;
  }
}

/* DESIGN.md: remove ALL transitions. Stated universally so a transition added
   later cannot escape it. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  body.estimator-page {
    padding: 0;
    background: var(--surface);
  }

  .instrument-header,
  .input-section,
  .result-section,
  .ballot-section,
  .methodology-page .method-header,
  .methodology-page .method-toc {
    break-inside: avoid;
  }

  .custom-toggle,
  .reset-btn,
  .next-steps {
    display: none;
  }
}
