/* btcdcacalculator.com
 *
 * One visual direction (plainspoken: friendly, high-contrast, fintech), with a
 * light and a dark palette selected by :root[data-theme="…"]. The page used to
 * carry three directions behind a switchable attribute for review; that
 * switch is gone now the owner has chosen, but the token layer it left behind
 * stays — light and dark are still expressed as custom properties, not
 * literals, so everything below the token block is styled once against them.
 *
 * Two constraints the palette imposes, both measured rather than assumed:
 *   1. --accent is never a text colour. #F7931A reaches only ~2.2:1 against the
 *      light background. It is used as a fill, with --on-accent on top, which
 *      measures 7.3:1.
 *   2. --invested is never a text colour either. It sits at 3.75–5.48:1
 *      depending on theme, which clears the 3:1 floor for a graphical object
 *      but not the 4.5:1 floor for text. It is the chart's invested stroke and
 *      its legend swatch, and nothing else.
 * Body text (--ink) and secondary text (--muted) clear 4.5:1 in both themes,
 * which is why they carry every word on the page.
 */

/* ---------------------------------------------------------------- tokens -- */

:root {
  --accent: #F7931A;

  --font-body: system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* tabular-nums is not optional: without it the figures jitter sideways as
     they update, which reads as instability on a page about money. */
  --font-num: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, monospace;

  --maxw: 900px;
  --gutter: 20px;
}

/* --- plainspoken: friendly, high-contrast, fintech ---------------------- */
:root {
  --bg: #FFFFFF;
  --surface: #F5F7FA;
  --wash: #F5F7FA;
  --ink: #0B1F33;
  --muted: #5A6B7C;
  --rule: #DCE3EA;
  --edge: #5A6B7C;
  --focus: #5A6B7C;
  --on-accent: #0B1F33;
  --invested: #2E7D6B;
  /* Validation messages, which are body-sized text and so must clear 4.5:1.
     Measured: 5.33:1 on --bg (#FFFFFF) and 4.97:1 on --surface (#F5F7FA),
     the two backgrounds an error is ever drawn on. Colour is never the only
     signal -- the message text says what is wrong, and the field carries
     aria-invalid. */
  --danger: #C23B32;

  --cta-bg: #0B1F33;
  --cta-fg: #FFFFFF;
  --band-rule: #DCE3EA;

  --font-display: system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display-weight: 800;
  --display-tracking: -0.03em;
  --display-transform: none;

  --radius: 12px;
  --pill: 999px;
  --lift: 0 1px 2px rgb(11 31 51 / 6%), 0 6px 18px rgb(11 31 51 / 5%);
}
:root[data-theme="dark"] {
  --bg: #0B1420;
  --surface: #132234;
  --wash: #132234;
  --ink: #E8EFF6;
  --muted: #93A5B8;
  --rule: #22364C;
  --edge: #93A5B8;
  --focus: #93A5B8;
  --cta-bg: #E8EFF6;
  --cta-fg: #0B1420;
  --band-rule: #22364C;
  /* 5.78:1 on --surface (#132234), 6.65:1 on --bg (#0B1420). */
  --danger: #F1766B;
  --lift: 0 1px 2px rgb(0 0 0 / 40%), 0 6px 18px rgb(0 0 0 / 30%);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #0B1420;
    --surface: #132234;
    --wash: #132234;
    --ink: #E8EFF6;
    --muted: #93A5B8;
    --rule: #22364C;
    --edge: #93A5B8;
    --focus: #93A5B8;
    --cta-bg: #E8EFF6;
    --cta-fg: #0B1420;
    --band-rule: #22364C;
    --danger: #F1766B;
    --lift: 0 1px 2px rgb(0 0 0 / 40%), 0 6px 18px rgb(0 0 0 / 30%);
  }
}

/* Tells the browser which way to render scrollbars and the native date picker,
   so those do not stay light inside a dark page. */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* ------------------------------------------------------------- structure -- */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 var(--font-body);
  -webkit-text-size-adjust: 100%;
}

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

main.wrap { padding-bottom: 56px; }

h1, h2, h3, .display {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  transform: var(--display-transform);
  transform-origin: left center;
  line-height: 1.15;
  margin: 0;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

.num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.eyebrow {
  font-family: var(--font-num);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 12px;
}

.panel {
  background: var(--wash);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--lift);
  padding: 20px;
}

/* Skip link and screen-reader-only text. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 10;
  background: var(--surface); color: var(--ink);
  padding: 10px 14px; border: 1px solid var(--edge); border-radius: var(--radius);
}
.skip:focus { left: var(--gutter); top: 8px; }

/* Every interactive element gets the same ring, and never --accent: it has to
   be visible on the accent-filled button too, and #F7931A does not clear the
   3:1 floor for a UI component on a light background.

   No border-radius here. Setting one would override whatever radius the focused
   element actually has, so a control would visibly change shape the moment it
   received focus -- the currency select, rounded 0 12px 12px 0 as the last
   segment of the amount group, snapped to a hard rectangle. Outlines follow the
   element's own border-radius in every current browser, so the ring traces the
   real shape with nothing specified.

   --focus rather than --ink: ink rings at ~16:1 in both themes, which is far
   past what a focus indicator needs and reads as harsh -- a near-black bar in
   light, a near-white one in dark. --focus sits at 5.5:1 (light) and 7.3:1
   (dark) against the surfaces it lands on: unmistakable, comfortably clear of
   the 3:1 floor for a UI component, and quiet. Do not soften it further without
   re-measuring; the next step down lands at 3.2:1 against --surface, which
   leaves no margin at all. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------------- header -- */

.site-header {
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
  padding: 12px 0;
  margin-bottom: 28px;
}
.header-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
}

.brand {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  font-size: 19px;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
/* The one place --accent is allowed to be a glyph rather than a fill. It is a
   logotype, which WCAG exempts from contrast (SC 1.4.3), and it is safe here
   for a second reason that matters more than the exemption: the ₿ is
   aria-hidden and purely decorative, so the brand still reads as "DCA
   Calculator" to anyone who cannot make it out. Nothing about the mark carries
   information the words do not. Do not copy this to accent text that means
   something -- #F7931A is ~2.2:1 on the light background. */
.brand-mark {
  display: inline-grid;
  place-items: center;
  width: 26px; height: 26px;
  color: var(--accent);
  border-radius: var(--radius);
  font-size: 17px;
  font-weight: 700;
  font-family: var(--font-body);
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  order: 3;
  flex-basis: 100%;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.site-nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover { color: var(--ink); border-bottom-color: var(--edge); }

.site-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-left: auto;
}

.pricechip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  padding: 5px 10px;
  white-space: nowrap;
}
.pricechip .num { color: var(--ink); }
.pricechip-label {
  font-family: var(--font-num);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.pricechip-chg { font-size: 12px; }
.pricechip-chg.up { color: #1f8a5f; }
.pricechip-chg.down { color: #c23b32; }

/* A quiet "this is updating" cue once the first live snapshot or tick has
   landed -- absent while the header still shows the build-time price. */
.pricechip.is-live { border-color: var(--edge); }
.pricechip.is-live .pricechip-label::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  margin-right: 4px;
  border-radius: 50%;
  background: #1f8a5f;
  vertical-align: middle;
}

/* The tick flash: an instant colour change on price update, held for ~600ms
   by the script above, not a CSS transition. Disabled under
   prefers-reduced-motion rather than merely un-animated, since even an
   instant colour flip every few seconds is motion some readers asked not to
   see. */
.pricechip .num.tick-up { color: #1f8a5f; }
.pricechip .num.tick-down { color: #c23b32; }
@media (prefers-reduced-motion: reduce) {
  .pricechip .num.tick-up, .pricechip .num.tick-down { color: var(--ink); }
}

.iconbtn {
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--pill);
  color: var(--ink);
  font: inherit;
  line-height: 1;
  padding: 7px 10px;
  cursor: pointer;
}
.iconbtn:hover { background: var(--bg); }
/* The toggle shows the destination, not the current state: a moon in light
   mode, a sun in dark. Driven off the same attributes as the palette so the
   no-JS media-query path stays in step. */
.icon-light { display: none; }
:root[data-theme="dark"] .icon-dark { display: none; }
:root[data-theme="dark"] .icon-light { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .icon-dark { display: none; }
  :root:not([data-theme]) .icon-light { display: inline; }
}

/* ------------------------------------------------------------------ hero -- */

.hero { text-align: center; padding: 12px 0 26px; }
.hero h1 {
  font-size: clamp(30px, 6.4vw, 46px);
  transform-origin: center;
}
.hero-sub {
  color: var(--muted);
  font-size: clamp(15px, 3.4vw, 19px);
  margin: 10px 0 0;
}

/* ------------------------------------------------------------ calculator -- */

.calc { margin-bottom: 18px; }

.fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}
/* Subgrid so label / control / chips are three shared rows across every column,
   not three independent stacks that happen to line up. Without it a label that
   wraps at some width silently pushes one column's control and pills out of
   step with its neighbours. */
.fields { grid-template-rows: auto auto auto; align-items: start; }
.field { min-width: 0; }
@supports (grid-template-rows: subgrid) {
  .field { display: grid; grid-template-rows: subgrid; grid-row: span 3; }
}
.field > label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 5px;
}
.field-note { font-size: 12px; color: var(--muted); margin: 6px 0 0; }

.control {
  width: 100%;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  padding: 9px 10px;
  font: inherit;
  font-size: 15px;
  /* A fixed height, not a minimum. Left to themselves a <select>, a text input
     and an <input type="date"> render at three different heights -- measured
     here at 40.0, 44.8 and 46.8px -- so the fields' bottoms staggered, and
     because each field's chips sit directly beneath its control, the pill rows
     inherited exactly that stagger across the columns. One height fixes both. */
  height: 44px;
}
.control-sm { width: auto; min-height: 34px; padding: 5px 8px; font-size: 14px; }

/* An input with a currency or percent affix. The affix is decorative — the
   real label is the <label>, so screen readers never hear a bare number. */
.control-group { display: flex; align-items: stretch; }
.control-group .prefix,
.control-group .suffix {
  display: grid;
  place-items: center;
  padding: 0 10px;
  background: var(--bg);
  border: 1px solid var(--edge);
  color: var(--muted);
  font-size: 15px;
}
.control-group .prefix {
  border-right: 0;
  border-radius: var(--radius) 0 0 var(--radius);
}
.control-group .suffix {
  border-left: 0;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.control-group .prefix + .control { border-radius: 0 var(--radius) var(--radius) 0; }
.control-group .control:has(+ .suffix) { border-radius: var(--radius) 0 0 var(--radius); }
.control-group-sm { flex: 0 0 auto; width: 116px; }
/* The escalation select was an unclassed <select> -- browser default styling,
   86x34 against the amount group's 116x44.8 beside it. Same class, same width,
   so the two halves of one sentence read as one control. */
.control-sm { flex: 0 0 auto; width: 116px; }

/* Segments in a flush group share edges, so an outward ring is drawn over its
   neighbours and reads as a heavy box floating on top of the control. Inset it
   instead: it sits on the segment it belongs to, traces that segment's own
   corners, and cannot be clipped by a sibling -- so the z-index shuffle the
   outward ring needed is gone too. `position: relative` stays; the ring is
   painted within the segment's own box either way. */
.control-group > * { position: relative; }
.control-group > *:focus-visible { outline-offset: -2px; }

/* Amount and currency are one decision, not two, so the currency picker is a
   third flush segment on the amount field rather than a separate labelled
   control beside it — the $ prefix stays for the at-a-glance symbol, the
   select for changing it. */
.control-group-amount .prefix + .control {
  border-radius: 0;
}
.control-group-amount .currency-select {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  border-left: 0;
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 9px 8px;
  font-size: 14px;
  color: var(--muted);
}

/* Belt and braces: `hidden` is a UA default (display: none), but a later rule
   with a display of its own would silently defeat it, and these three elements
   are empty in the build output -- an unhidden empty box would be a visible
   gap on a page that is otherwise complete without JavaScript. */
[hidden] { display: none !important; }

/* An engine validation message, shown beside the input that caused it. The
   text comes from the engine verbatim (it is written as user-facing copy);
   this only decides where it sits and how loud it is. --danger rather than
   colour alone: the message itself says what is wrong, so colour is never the
   only carrier. */
.field-error,
.form-error {
  font-size: 13px;
  line-height: 1.45;
  color: var(--danger);
  margin: 6px 0 0;
}
.form-error {
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  background: var(--surface);
}
.control[aria-invalid="true"] { border-color: var(--danger); }

/* The range-was-adjusted notice. Quiet: it reports a correction the page made
   on the reader's behalf, not a mistake they need to fix. */
.notice {
  max-width: 62ch;
  margin: 0 auto 16px;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.chip {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: var(--pill);
  padding: 4px 11px;
  font: inherit;
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
.chip:hover { color: var(--ink); border-color: var(--edge); }
.chip.is-on {
  color: var(--ink);
  border-color: var(--edge);
  background: var(--bg);
  font-weight: 600;
}

/* The escalation row. Visible and first-class rather than a disclosure: a
   default that quietly raises the contribution has to be something the reader
   can see, or the total will disagree with what they think they entered. */
.escalate {
  margin-top: 18px;
  padding: 14px 16px;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.escalate-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
}
.escalate-label { font-weight: 600; font-size: 15px; }
.escalate-why { color: var(--muted); font-size: 14px; }
.escalate-chips { margin-top: 0; margin-left: auto; }

.info {
  width: 20px; height: 20px;
  display: inline-grid; place-items: center;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font: 600 11px/1 var(--font-body);
  cursor: help;
  padding: 0;
}
.info:hover { color: var(--ink); }

/* Sized to its label rather than the panel. Full width, the button becomes a
   slab as loud as the profit tile, competing with it for the same meaning. */
.cta {
  margin-top: 18px;
  min-width: 210px;
  background: var(--cta-bg);
  color: var(--cta-fg);
  border: 1px solid var(--cta-bg);
  border-radius: var(--radius);
  padding: 13px 20px;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
}
.cta:hover { filter: brightness(1.08); }

/* --------------------------------------------------------------- results -- */

.sentence {
  text-align: center;
  font-size: clamp(15px, 3.6vw, 18px);
  line-height: 1.6;
  color: var(--muted);
  max-width: 62ch;
  margin: 22px auto;
}
.sentence strong { color: var(--ink); }

.results-note {
  text-align: center;
  max-width: 62ch;
  margin: 0 auto 16px;
}
.results-note a { color: var(--ink); }

.stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.stat {
  background: var(--surface);
  padding: 16px 14px;
  min-width: 0;
}
.stat-label {
  display: block;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 6px;
}
.stat-value {
  display: block;
  font-size: clamp(18px, 3.6vw, 24px);
  font-weight: 600;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
.stat-unit {
  display: block;
  font-size: 11px;
  color: var(--muted);
  margin-top: 6px;
}

/* Profit is the thesis: the only saturated tile, and the largest figure on the
   page. Nothing else competes with it. */
.stat-hero {
  background: var(--accent);
  color: var(--on-accent);
}
.stat-hero .stat-label,
.stat-hero .stat-unit { color: var(--on-accent); opacity: 0.75; }
.stat-hero .stat-value {
  font-size: clamp(24px, 7vw, 42px);
  font-weight: 700;
}

/* Satoshis are the unit, so all eight decimals are shown — but the digits past
   the fourth drop back, and the figure reads as a value with structure rather
   than a wall of numerals. */
/* 0.66 is a contrast floor, not a taste choice. These are real figures on a money
   page, so they must clear 4.5:1 as body text. Measured against --surface:
   0.55 gives 3.75:1 light / 5.15:1 dark — light fails. 0.62 is the break-even
   (4.65:1); 0.66 leaves margin at 5.30:1 light and 6.76:1 dark. Do not lower it
   to sharpen the effect without re-measuring both themes. */
.btc .sats { opacity: 0.66; }

/* ----------------------------------------------------------------- chart -- */

.chart { margin-top: 22px; }
.chart-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  margin-bottom: 12px;
}
.chart-head .eyebrow { margin: 0; }
.chart-head .chips { margin-top: 0; }
.chart-share { margin-left: auto; }

.plot {
  height: 190px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--bg);
  overflow: hidden;
}
.plot svg { display: block; width: 100%; height: 100%; }

/* Once the real chart has mounted. The height stays fixed: chart.js sizes the
   canvas from the container's own box and re-sizes it from a ResizeObserver on
   that same box, so an auto height would feed the legend's height back into
   the canvas and grow without bound.

   uPlot's legend (which doubles as its hover readout) lives inside the
   container, so it is allowed to spill past the fixed box and the margin below
   reserves the room. --legend-reserve is measured and set by the controller
   rather than guessed: the legend wraps to two rows around 400px wide, and a
   fixed reserve either collides with the caption below it or leaves a hole
   above it. The fallback covers the instant before the first measurement. */
.plot.is-live {
  overflow: visible;
  margin-bottom: var(--legend-reserve, 40px);
}

/* The gap between what went in and what it is worth. Held back to a tint while
   the chart is a placeholder: at full saturation this shape is several times
   the area of the profit tile and takes the emphasis off the figure that is
   supposed to carry it. The real chart can take the saturation back once it is
   showing data rather than a drawing. */
.plot-gap { fill: var(--accent); fill-opacity: 0.22; }
.plot-value { fill: none; stroke: var(--ink); stroke-width: 2.5; vector-effect: non-scaling-stroke; }
.plot-invested {
  fill: none; stroke: var(--invested); stroke-width: 2;
  stroke-dasharray: 5 4; vector-effect: non-scaling-stroke;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  font-size: 12px;
  color: var(--muted);
  margin: 10px 0 0;
}
.key {
  width: 14px; height: 3px;
  border-radius: 2px;
  display: inline-block;
  margin-right: 2px;
  vertical-align: middle;
}
.key-value { background: var(--ink); }
.key-invested { background: var(--invested); }
.key-gap { background: var(--accent); height: 10px; border-radius: 1px; }

/* --------------------------------------------------------------- ad slot -- */

/* Reserved at a fixed height whether or not ADSENSE_CLIENT is set, so a
   local review build shows the real space the ad will occupy and there is
   no layout shift once the account is approved and ads go live. */
.ad-slot {
  margin-top: 22px;
  min-height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
}
.ad-slot-placeholder {
  font-size: 12px;
  color: var(--muted);
}

/* ------------------------------------------------------------------ band -- */

.band {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 40px 0 16px;
  font-family: var(--font-num);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.band::before, .band::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--band-rule);
}

/* ------------------------------------------------------------------ hook -- */

.hook h2 {
  font-size: clamp(21px, 4.6vw, 28px);
  margin-bottom: 14px;
}
.hook p { max-width: 68ch; }
.hook-links { margin-top: 18px; }

/* ------------------------------------------------------------------- faq -- */

.faq {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--wash);
}
.faq details { border-bottom: 1px solid var(--rule); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  cursor: pointer;
  padding: 14px 18px;
  font-weight: 600;
  font-size: 16px;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  margin-left: auto;
  color: var(--muted);
  font-family: var(--font-num);
  font-weight: 400;
}
.faq details[open] summary::after { content: "\2212"; }
.faq summary:hover { background: var(--bg); }
.faq .answer {
  padding: 0 18px 18px;
  color: var(--muted);
  max-width: 72ch;
}
.faq .answer strong { color: var(--ink); }
/* The 2.5% default is the one answer the page owes the reader, so it is marked
   in the list rather than buried among the other six. */
.faq-featured summary { box-shadow: inset 3px 0 0 var(--accent); }

/* ----------------------------------------------------------------- prose -- */

/* The article and policy pages. A single measured column: body text stays at
   --ink (not --muted) because this is the page's primary content rather than
   supporting notes, and 1,300 words of secondary-colour text is tiring to read
   even when it clears the contrast floor. --muted carries the standfirst,
   breadcrumb and captions, which are genuinely secondary. */
.prose {
  max-width: 68ch;
  margin: 0 auto;
}
.prose h1 {
  font-size: clamp(28px, 6vw, 42px);
  margin-bottom: 14px;
}
.prose h2 {
  font-size: clamp(20px, 4.2vw, 26px);
  margin: 38px 0 12px;
}
.prose h3 {
  font-size: clamp(17px, 3.4vw, 20px);
  margin: 26px 0 8px;
}
.prose p,
.prose li { line-height: 1.72; }
.prose ul, .prose ol { margin: 0 0 1em; padding-left: 22px; }
.prose li { margin-bottom: 8px; }
.prose li:last-child { margin-bottom: 0; }
/* Underlined, not colour-coded: --accent is never a text colour here either,
   and an underline is the one link affordance that survives both themes and
   colour blindness. */
.prose a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.prose a:hover { text-decoration-thickness: 2px; }
.prose code {
  font-family: var(--font-num);
  font-size: 0.92em;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 1px 5px;
}

.crumbs {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 18px;
}
.crumbs a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--rule); }
.crumbs a:hover { color: var(--ink); }

.standfirst {
  font-size: clamp(16px, 3.4vw, 19px);
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 8px;
}

/* Same shape as the calculator's range notice, reused rather than reinvented:
   accent as a left rule (a graphical object, well clear of the 3:1 floor),
   never as text. */
.callout {
  margin: 24px 0;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}

/* Tables scroll inside their own box rather than pushing the page sideways at
   360px. */
.table-wrap {
  overflow-x: auto;
  margin: 0 0 1.2em;
}
.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}
.prose th, .prose td {
  text-align: left;
  padding: 9px 12px 9px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
.prose thead th {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.prose tfoot th, .prose tfoot td { border-bottom: 0; font-weight: 700; }
.prose td.num, .prose th.num {
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  padding-right: 0;
}

.contact-email {
  font-family: var(--font-num);
  font-size: clamp(16px, 4vw, 21px);
  margin: 0 0 1.4em;
  overflow-wrap: anywhere;
}

.keep-reading {
  margin-top: 44px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
.keep-reading .chips { margin-top: 0; }
/* `.prose h2` (0,1,1) outranks `.eyebrow` (0,1,0), so this strip's heading
   would otherwise render at article-heading size. Same specificity, later in
   the file, so the eyebrow treatment wins back its own size and spacing. */
.keep-reading h2 { font-size: 11px; margin: 0 0 12px; }

/* ---------------------------------------------------------------- footer -- */

.site-footer {
  border-top: 1px solid var(--rule);
  padding: 26px 0 40px;
  margin-top: 20px;
}
.disclaimer {
  font-size: 13px;
  color: var(--muted);
  max-width: 68ch;
}
.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 13px;
  color: var(--muted);
  margin-top: 14px;
}
.foot-nav a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--rule); }
.foot-nav a:hover { color: var(--ink); }
.foot-legal { margin-left: auto; }

/* ------------------------------------------------------------ responsive -- */

@media (max-width: 720px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .escalate-chips { margin-left: 0; }
  .chart-share { margin-left: 0; }
  .foot-legal { margin-left: 0; }
}

@media (max-width: 480px) {
  :root { --gutter: 16px; }
  .site-tools { margin-left: 0; width: 100%; }
  .pricechip { margin-left: auto; }
  .panel { padding: 16px 14px; }
  .stat { padding: 13px 11px; }
  .escalate { padding: 12px; }
  .escalate-label, .escalate-why { font-size: 14px; }
  .cta { width: 100%; }
  .plot { height: 150px; }
}
