/*
 * BenefitCalculators.com — one light theme, two calculators.
 *
 * A marketing page wrapped around a working tool: a white top bar, a hero
 * that runs the headline against a photograph, the calculator in three
 * columns — what you enter, what it comes to, and how that compares — then
 * the cards that answer "can I trust this" and "how was it worked out".
 *
 * Sized for readers in their sixties and up: 18px base, generous line
 * height, and controls that stay at least 48px tall on a phone.
 */

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

:root {
  color-scheme: light;

  /* A cool, near-white paper with navy ink: the palette of a government
     form, without pretending to be one. */
  --paper: #f5f7fa;
  --band: #eaf0f7;
  --sheet: #ffffff;

  --ink: #18202a;
  --ink-soft: #4b5563;
  /* 7.10:1 on the sheet, 6.19:1 on the band, up from 5.34 and 4.65. */
  --ink-faint: #4f5967;

  --rule: #e2e7ee;
  --rule-strong: #c4ccd7;
  /*
   * The edge of a form control, and only that.
   *
   * --rule-strong is 1.62:1 against white, which is fine for a divider and not
   * fine for the only thing that says where an input begins: WCAG 1.4.11 wants
   * 3:1 for the visual boundary of a user interface component, and a white
   * field on a white card has nothing else to give. This is 3.51:1. The
   * decorative rules keep --rule-strong, because a separator is not a control.
   */
  --field-border: #7d8a9c;

  --accent: #14406e;
  --accent-deep: #0e2c4c;
  --accent-soft: #2f6494;
  --accent-wash: #eaf1fa;
  /*
   * The colour of a link in running text and in the hub's lists.
   *
   * Three rules referenced var(--link) and it was never defined anywhere, so
   * every one of them was invalid at computed-value time and the colour fell
   * back to inherited -- the hub's "find benefits by need" links rendered in
   * body ink at #18202a rather than in the accent, which is most of why that
   * section read as a wall of underlined text rather than as a set of links.
   */
  --link: #14406e;

  --positive: #2c6b4f;
  --caution: #8a5716;
  --caution-wash: #f7efe1;
  --critical: #9b3030;

  --shell-pad: 24px;
  --radius: 8px;
  --radius-sm: 6px;
  --shell: 1240px;
  --btn-lift: 0 5px 14px -4px rgba(14, 44, 76, 0.5);

  --font-display: "Source Serif 4", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-label: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ------------------------------------------------------------------- reset */

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

html {
  font-size: 18px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  /* No -webkit-font-smoothing: antialiased -- on macOS it trades subpixel
     rendering for greyscale, thinning every stroke, and the faces stop at 600
     so the weight cannot be won back. */
}

h1, h2, h3, p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }

/* The scripts hide and show pieces of the result cards with the hidden
   attribute, which the UA stylesheet honours only as display:none — so any
   rule here that sets display wins, and the element stays on screen. It cost
   the Medicaid card a stray "/ year" under a verdict with no figure behind it.
   State beats layout. */
[hidden] { display: none !important; }

a { color: var(--accent); }

:focus-visible {
  outline: 3px solid var(--accent-soft);
  outline-offset: 2px;
  border-radius: 2px;
}

/*
 * The first thing in the tab order, and invisible until it is needed.
 *
 * Every page carries seventeen navigation links above its content, so reaching
 * the first form field took eighteen presses of Tab -- on every page, on every
 * visit, for anyone not using a mouse. This is the standard way out, and it is
 * off-screen rather than `display: none` because a link that is not rendered
 * is not focusable and so would never appear.
 */
.skip-link {
  /* Fixed, not absolute. The header is sticky, so a visitor can scroll and
     then Shift+Tab back to the top of the order; an absolutely positioned link
     would come back at the top of the DOCUMENT, which by then is off screen.
     z-index clears the sticky header at 40 and the language menu at 60. */
  position: fixed;
  left: 8px;
  top: 8px;
  z-index: 200;
  padding: 12px 18px;
  background: var(--sheet);
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  color: var(--accent-deep);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  /* Off-screen, not hidden: still focusable, still read in DOM order. */
  transform: translateY(calc(-100% - 16px));
  transition: transform 0.12s ease-out;
}

.skip-link:focus {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .skip-link { transition: none; }
}

/* Nothing should look focused because a script moved focus there. */
main:focus { outline: none; }
main:focus-visible { outline: 3px solid var(--accent-soft); }

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 var(--shell-pad);
}

/* The right-hand edge of the shell's content, measured from the viewport.
   Anything bled outside a .shell — the hero photograph — lines up with it. */
:root {
  --shell-edge: max(
    var(--shell-pad),
    calc((100vw - var(--shell)) / 2 + var(--shell-pad))
  );
}

/* ------------------------------------------------------------------ topbar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--sheet);
  border-bottom: 1px solid var(--rule);
}

.topbar__inner {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 64px;
}

.brand {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--accent-deep);
  text-decoration: none;
  white-space: nowrap;
}

.brand__tld { color: var(--ink-faint); font-weight: 600; }

.topbar__right {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  gap: 10px;
  /* See the note on .nav: a flex item defaults to min-width:auto, and one
     unbounded ancestor is enough to defeat the scrolling strip inside. */
  min-width: 0;
}

/* --- tabs */

/*
 * Six groups, not sixteen tabs.
 *
 * The flat row had been outgrowing the bar for its whole life. Seven fitted;
 * nine wrapped to three rows on a phone and were changed to a strip that
 * scrolls sideways; by sixteen that strip scrolled at 1280px too, with four
 * calculators past the right edge and a fade as the only sign of them. Every
 * calculator added made it worse, which is what tells you the shape was wrong
 * rather than the widths -- and there are more calculators coming.
 *
 * Grouping is the fix that does not have to be redone. The bar holds one item
 * per family of programmes, so it stops growing with the site, and it says
 * something the flat row could not: which programmes are alternatives to each
 * other. Somebody who knows they need help with food no longer has to know
 * whether that is called SNAP or WIC.
 *
 * Built on <details>, so it opens, closes and takes the keyboard before any
 * script has run. ui.js adds what <details> does not do on its own -- closing
 * the others, Escape, and clicking away.
 */
.nav {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  /* `safe` for the same reason it was here before: a centred flex row that
     overflows pushes its first items off the LEFT, where nothing can reach
     them. Six groups fit at every width the site is read at, but a language
     with long words is not something to leave to chance. */
  justify-content: center;
  /* Wrap rather than scroll.
   *
   * The scrolling strip was the right answer for a row that could not be made
   * to fit; six groups fit at every desktop width, and where they do not -- a
   * phone -- they make exactly two rows and stop, because the count no longer
   * grows with the site. That is the difference from the sixteen tabs, which
   * wrapped to three rows and then four.
   *
   * It is also what lets a group open at all. A scroll container clips on
   * both axes, whatever `overflow-x` alone appears to say, so the panel was
   * cut off at the bar's own edge -- open, correct, and invisible. */
  flex-wrap: wrap;
  gap: 2px;
  padding-inline: 4px;
  min-width: 0;
}

.nav__group { position: relative; flex: 0 0 auto; }

/*
 * The group's button. <summary> is a button to the accessibility tree and
 * announces its own expanded state, so it needs no ARIA -- but it comes with
 * a disclosure triangle that has to go, in two dialects, or the row carries
 * two arrows.
 */
.nav__group-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 48px;
  padding: 0 11px;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
  border-bottom: 3px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.nav__group-btn::-webkit-details-marker { display: none; }
.nav__group-btn::marker { content: ""; }

/* The one thing on the closed bar that says there is more behind it. */
.nav__chev {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  opacity: 0.75;
  transition: transform 0.15s ease;
}

/*
 * Open and current are different facts and must not look the same. Both drew
 * the underline at first, so with one group open you could no longer tell
 * which group held the page you were on -- and on a phone, where a panel
 * covers half the screen, that is the moment you most want to know.
 *
 * The underline now means "you are here" and nothing else. Open is a filled
 * button with a turned chevron, which is also two signals rather than one.
 */
.nav__group[open] > .nav__group-btn {
  color: var(--accent-deep);
  background: var(--accent-wash);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.nav__group[open] > .nav__group-btn .nav__chev { transform: rotate(180deg); }

/* The group holding the page you are on, marked the way the tab used to be. */
.nav__group.is-current > .nav__group-btn {
  color: var(--accent-deep);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

/*
 * The panel. Absolutely positioned so opening a group does not push the page
 * down -- <details> lays its contents out in flow otherwise, and a header that
 * grows by 200px when you look at it is worse than one that scrolls.
 */
.nav__panel {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 50;
  min-width: 200px;
  padding-top: 6px;
}

.nav__panel-inner {
  display: flex;
  flex-direction: column;
  padding: 6px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 28px -12px rgba(14, 44, 76, 0.45);
}

/* A group near the right-hand end opens leftward, so its panel stays on the
   page instead of pushing the document sideways.

   Insurance rather than something currently in play: above 1200px the row is
   centred and the last group stops well short of the edge, and below it the
   panel spans the bar instead. It is here for the seventh group, or the
   language whose labels run long enough to push the row out to the margin --
   nav-desktop.js fails the moment a panel does leave the screen. */
.nav__group:nth-last-child(-n+2) .nav__panel { left: auto; right: 0; }

.nav__cat-chev {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  transition: transform 0.15s ease;
}

.nav__cat-group.is-open .nav__cat-chev {
  transform: rotate(180deg);
}

.nav__cat-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  cursor: pointer;
  flex: 0 0 44px;
}

.nav__cat-toggle:hover {
  background: var(--surface);
  color: var(--accent);
}

.nav__cat-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.nav__calc-link {
  position: relative;
  display: flex;
  align-items: center;
  font-size: 0.89rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 4px 8px;
  min-height: 44px;
  border-radius: var(--radius-sm);
  transition: color 0.15s ease, background 0.15s ease;
}

.nav__calc-link:hover {
  color: var(--accent);
  background: var(--surface);
}

.nav__calc-link.is-current {
  color: var(--accent-deep);
  font-weight: 700;
  background: var(--accent-wash);
}

.nav__link {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  white-space: nowrap;
  min-height: 44px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 0.15s ease, background 0.15s ease;
}

/* The single-calculator group is a tab rather than a menu of one, so it wears
   the bar's shape and not the panel's. */
/* ------------------------------------------------- the header's one row
 *
 * Four items with the full "Benefit Calculators" label need 351px in English
 * and 523, 574 and 651px in Spanish, Vietnamese and Tagalog. A 393px phone
 * offers a 361px bar. Measured from 320 to 430px: three of the six languages
 * cannot hold the bar at any of those widths, and no amount of padding buys
 * 170px back. From 700px up every language fits on one row.
 *
 * So below 700px the four items are a disclosure and the header is one row: a
 * trigger beside the brand. Above it the same markup is the bar, with the
 * disclosure neutralised. There is no second copy of the navigation and no
 * script -- <details> carries its own open and closed state, which is what a
 * screen reader reads and what the keyboard already operates.
 */
.nav__menu { min-width: 0; }

.nav__menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 12px;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
  cursor: pointer;
  /* Both, because engines disagree on which one shows the marker. */
  list-style: none;
  border-radius: var(--radius-sm);
  transition: color 0.15s ease, background-color 0.15s ease;
}

.nav__menu-btn::-webkit-details-marker { display: none; }
.nav__menu-btn::marker { content: ""; }

.nav__menu-icon { width: 20px; height: 20px; flex: none; }

.nav__menu[open] > .nav__menu-btn { color: var(--accent-deep); background: var(--accent-wash); }

@media (hover: hover) and (pointer: fine) {
  .nav__menu-btn:hover { color: var(--accent); }
}

.nav__menu-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* The panel: a column under the trigger, not a bar. */
.nav__menu-list {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: 6px 0 10px;
}

@media (max-width: 699px) {
  /* The bar centres its items; a column of rows starts at the edge of the
     text column instead, or it reads as indented from nothing. */
  .nav { justify-content: flex-start; padding-inline: 0; }
  .nav__menu { width: 100%; }

  .nav__menu-list > .nav__link--solo,
  .nav__menu-list > .nav__group > .nav__group-btn {
    justify-content: flex-start;
    text-align: left;
    width: 100%;
  }
}

@media (min-width: 700px) {
  /*
   * The disclosure stops being one. display:contents lifts the summary and
   * the list into the bar's own flex row; the summary goes; and the list is
   * shown whether or not the element is open -- through both mechanisms
   * engines use to hide a closed <details>, since they do not agree.
   */
  .nav__menu { display: contents; }
  .nav__menu-btn { display: none; }
  .nav__menu::details-content { content-visibility: visible !important; }
  .nav__menu-list {
    display: flex !important;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 2px;
    padding: 0;
    min-width: 0;
  }
}

.nav__link--solo {
  min-height: 48px;
  min-width: 28px;
  justify-content: center;
  text-align: center;
  padding: 0 11px;
  border-radius: 0;
  border-bottom: 3px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .nav__group-btn:hover { color: var(--accent); border-bottom-color: var(--rule-strong); }
  .nav__group.is-current > .nav__group-btn:hover { border-bottom-color: var(--accent); }
  .nav__group[open] > .nav__group-btn:hover { border-bottom-color: transparent; }
  .nav__group.is-current[open] > .nav__group-btn:hover { border-bottom-color: var(--accent); }
  .nav__link:hover { color: var(--accent-deep); background: var(--accent-wash); }
  .nav__link--solo:hover { background: none; border-bottom-color: var(--rule-strong); }
  .nav__link--solo.is-current:hover { border-bottom-color: var(--accent); }
}

.nav__group-btn:active, .nav__link:active { color: var(--accent-deep); }

.nav__link.is-current {
  color: var(--accent-deep);
  font-weight: 600;
  background: var(--accent-wash);
}

.nav__link--solo.is-current {
  background: none;
  border-bottom-color: var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  .nav__chev { transition: none; }
}

@media (forced-colors: active) {
  .nav__panel-inner { border: 1px solid CanvasText; }
  .nav__group[open] > .nav__group-btn,
  .nav__group.is-current > .nav__group-btn,
  .nav__link.is-current { outline: 1px solid CanvasText; }
  .nav__group[open] > .nav__group-btn { background: Highlight; color: HighlightText; }
}

/*
 * The site map's lists.
 *
 * Sixteen calculators in one column on a 1280px page is a stripe of links down
 * the left with the rest of the page empty, and it makes a short list look
 * long. They flow into as many columns as the width allows instead, and each
 * row is a target rather than a word: a site map is read by somebody who did
 * not find what they wanted the first way, which is not the moment to make
 * them aim.
 */
.doc__map {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 0 22px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

/* One column, for rows that read as sentences rather than as names. */
.doc__map--wide { grid-template-columns: 1fr; }

.doc__map li {
  display: flex;
  align-items: center;
  min-height: 40px;
  border-bottom: 1px solid var(--rule);
}

.doc__map a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--link);
  text-decoration: none;
}

/*
 * In a sentence row the link is part of the sentence, so it stays inline:
 * inline-flex swallowed the space after the state's colon and pushed each
 * comma away from the word before it -- "California:Medicaid ,SNAP".
 * WCAG 2.5.8 exempts a link inline in a sentence from the target size, and
 * the row around it is still 40px tall.
 */
.doc__map--wide a { display: inline; min-height: 0; }
/*
 * A sentence row is a block, not a flex row. As a flex row the <li> made every
 * word a flex item and dropped the whitespace between them, so the state rows
 * came out as "California:Medicaid,SNAP" with no spaces at all -- the same
 * class of bug as the card foot whose accessible name ran two words together,
 * and invisible for the same reason: the markup is right and the layout eats
 * it.
 */
.doc__map--wide li {
  display: block;
  padding: 10px 0;
  line-height: 1.6;
}

@media (hover: hover) and (pointer: fine) {
  .doc__map a:hover { text-decoration: underline; }
}

/*
 * Room for the sticky header when something is scrolled into view.
 *
 * The header grew a row when it gained a seventh group, and a rejected field
 * is scrolled to by the browser: on the ACA and Medicaid pages the field it
 * scrolled to came to rest underneath the header, which axe reports as a
 * target that cannot be hit. Nothing about the fields changed -- the thing
 * above them did.
 *
 * `scroll-margin-top` is what tells the browser where "into view" ends. It is
 * set on the elements anything actually scrolls to: a field the validation
 * moves to, a section a header menu item links to, and the main landmark the
 * skip link lands on.
 */
:root { --sticky-header: 116px; }

/*
 * scroll-padding on the scroller, not scroll-margin on the targets. The margin
 * is honoured only when the browser decides to scroll for that element; the
 * padding applies to every scroll into view within the page, which is what
 * catches the case the header actually broke -- a field brought into view by
 * focus() after a rejected submission.
 */
html { scroll-padding-top: var(--sticky-header); }

input,
select,
textarea,
main,
section[id] { scroll-margin-top: var(--sticky-header); }

/* ------------------------------------------------ Benefits & Updates hub */

/*
 * The article card. Deliberately the hub card's shape rather than a new one:
 * the site already has one way of saying "this is a route you can take", and a
 * second one that looked slightly different would read as a different kind of
 * thing. What is added is the metadata line an article needs and a calculator
 * does not -- which family it belongs to, when it was last checked, how long
 * it takes to read, and which calculator it leads to.
 *
 * It must not read as an advertisement, which in practice means no accent
 * fill, no badge shouting at the corner, and a summary that is the article's
 * own question rather than a pitch.
 */
.updates { margin-top: 34px; }

/* --- language listbox (a real <select> cannot be opened by hovering) */

.lang-switch { position: relative; flex: 0 0 auto; }

.lang-trigger {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  white-space: nowrap;
  flex-shrink: 0;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  background: var(--sheet);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-sm);
  color: var(--accent-deep);
  font: inherit;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.lang-trigger__globe {
  width: 18px;
  height: 18px;
  flex: none;
  flex-shrink: 0;
}

.lang-trigger__label {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
  flex-shrink: 0;
  line-height: 1.2;
}

@media (hover: hover) and (pointer: fine) {
  .lang-trigger:hover { border-color: var(--accent); background: var(--accent-wash); }
}

.lang-trigger[aria-expanded="true"] {
  border-color: var(--accent);
  background: var(--accent-wash);
}

.lang-trigger__caret {
  width: 0; height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}

.lang-trigger[aria-expanded="true"] .lang-trigger__caret { transform: rotate(180deg); }

.lang-list {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  z-index: 60;
  min-width: 182px;
  padding: 5px;
  background: var(--sheet);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 16px 36px -12px rgba(14, 44, 76, 0.4);
}

.lang-list__item {
  padding: 10px 12px;
  border-radius: 4px;
  font-size: 0.95rem;
  color: var(--ink);
  white-space: nowrap;
  cursor: pointer;
}

.lang-list__item.is-active { background: var(--accent-wash); color: var(--accent-deep); }
.lang-list__item[aria-selected="true"] { font-weight: 600; color: var(--accent-deep); }

.lang-list__item[aria-selected="true"]::after {
  content: "\2713";
  float: right;
  margin-left: 10px;
}

/* ----------------------------------------------------------- breadcrumbs */

.breadcrumb {
  background-color: var(--paper);
  border-bottom: 1px solid var(--rule);
  padding: 0.625rem 0;
  font-size: 0.89rem;
  line-height: 1.4;
}

.breadcrumb .shell {
  display: flex;
  align-items: center;
}

.breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: 0.35rem 0.5rem;
}

.breadcrumb__item {
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0;
}

.breadcrumb__link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 500;
  padding: 0.15rem 0;
}

.breadcrumb__link:hover,
.breadcrumb__link:focus-visible {
  color: var(--accent-deep);
  text-decoration-thickness: 2px;
}

.breadcrumb__separator {
  color: var(--ink-soft);
  user-select: none;
  margin: 0 0.1rem;
}

.breadcrumb__current {
  color: var(--ink-soft);
  font-weight: 600;
}

@media (max-width: 600px) {
  .breadcrumb {
    padding: 0.5rem 0;
  }
}

/* ------------------------------------------------------ homepage additions */

.hub-needs__other a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
}

.hub-final__head {
  text-align: center;
  max-width: 680px;
  margin: 0 auto 2.5rem;
}

.hub-states {
  margin-top: 3.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--rule);
}

.hub-states__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

@media (max-width: 900px) {
  .hub-states__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
  }
}

@media (max-width: 600px) {
  .hub-states__grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

.hub-state-card {
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  min-width: 0;
}

@media (max-width: 600px) {
  .hub-state-card {
    padding: 1.125rem 1rem;
  }
}

.hub-state-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
}

.hub-state-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 0.875rem;
  padding-bottom: 0.625rem;
  border-bottom: 1px solid var(--rule);
  min-width: 0;
}

.hub-state-card__name {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0;
  min-width: 0;
  word-break: break-word;
}

.hub-state-card__badge,
.hub-state-card__count {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  font-size: 0.83rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent-deep);
  background: var(--accent-wash);
  border: 1px solid rgba(20, 64, 110, 0.2);
  border-radius: 9999px;
  /*
   * The pill wraps rather than pushing the page sideways.
   *
   * It used to be white-space: nowrap, which makes its intrinsic minimum the
   * full width of the label -- and the label is translated. "6 Benefit Tools"
   * is 176px; "6 HERRAMIENTAS DE BENEFICIOS", uppercased and letter-spaced,
   * is 285px. The grid goes to two columns above 600px, and a column is not
   * 285px wide until about 648px, so between those widths the pill was wider
   * than the card holding it and the whole document scrolled sideways.
   *
   * Two bands, not one, because the 620px breakpoint steps the base font from
   * 17px to 18px: the pill grows 270px -> 285px exactly as the column starts
   * to fit it, and the race begins again. 604-612px overflowed by up to 5px
   * and 624-644px by up to 12px, with 616-620px clean in between -- which is
   * where the responsive matrix happened to sample, so it saw nothing.
   *
   * max-width keeps it inside the card; letting it wrap means a long label
   * takes two lines instead of taking the page with it. Nothing is clipped,
   * nothing is hidden, and no translation had to be shortened to fit.
   */
  max-width: 100%;
}

.hub-state-card__reps {
  list-style: none;
  padding: 0;
  margin: 0 0 1.25rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  flex-grow: 1;
}

.hub-state-card__rep {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.hub-state-card__rep::before {
  content: "•";
  color: var(--accent);
  font-weight: bold;
}

.hub-state-card__action {
  margin-top: auto;
  padding-top: 0.875rem;
  border-top: 1px solid var(--rule);
}

.hub-state-card__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.625rem 1rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: #ffffff;
  background: var(--accent);
  border-radius: 6px;
  text-decoration: none;
  transition: background 0.15s ease;
  min-height: 44px;
}

.hub-state-card__btn:hover {
  background: var(--accent-deep);
  color: #ffffff;
}

.hub-state-card--expanding {
  background: var(--surface);
  border-style: dashed;
}

.hub-state-card--expanding .hub-state-card__count,
.hub-state-card--expanding .hub-state-card__badge {
  color: #7a4b08;
  background: #fcf6ec;
  border-color: #f2dab3;
}

.hub-state-card__status-text {
  font-size: 0.89rem;
  color: var(--ink-soft);
  line-height: 1.45;
  margin: 0 0 1.25rem 0;
  flex-grow: 1;
}

/* --- Tool type badge system --- */
.tool-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  font-size: 0.83rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-radius: 4px;
  line-height: 1.2;
  white-space: nowrap;
}

.tool-badge--calc {
  background: var(--accent-wash);
  color: var(--accent-deep);
  border: 1px solid rgba(20, 64, 110, 0.22);
}

.tool-badge--screener {
  background: #f0f7f4;
  color: #185936;
  border: 1px solid #b7dfca;
}

.tool-badge--guide {
  background: #fcf6ec;
  color: #7a4b08;
  border: 1px solid #f2dab3;
}

.hero__badge-tool {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

/* --- Level 2 State Benefit Page Styles --- */
.state-hub {
  padding-bottom: 3.5rem;
}

.state-section {
  margin-top: 2.75rem;
}

.state-section__header {
  margin-bottom: 1.25rem;
}

.state-section__title {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 0.35rem;
}

.state-section__intro {
  font-size: 0.95rem;
  color: var(--ink-soft);
  line-height: 1.5;
  max-width: 720px;
  margin: 0;
}

.state-tool-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
}

@media (max-width: 640px) {
  .state-tool-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

.state-tool-card {
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 1.35rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.state-tool-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
}

.state-tool-card__badge-row {
  margin-bottom: 0.625rem;
}

.state-tool-card__title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.5rem 0;
  line-height: 1.35;
}

.state-tool-card__desc {
  font-size: 0.95rem;
  color: var(--ink-soft);
  line-height: 1.45;
  margin: 0 0 1.25rem 0;
  flex-grow: 1;
}

.state-tool-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 0.75rem;
  border-top: 1px solid var(--rule);
  font-size: 0.89rem;
  gap: 8px;
}

.state-tool-card__outcome {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}

.state-tool-card__link {
  font-weight: 700;
  color: var(--accent);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
}

.state-tool-card__link:hover {
  color: var(--accent-deep);
  text-decoration: underline;
}

.state-resources-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
}

@media (max-width: 640px) {
  .state-resources-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

.state-resource-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.state-resource-card__title {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 0.4rem 0;
  line-height: 1.35;
}

.state-resource-card__title a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.state-resource-card__title a:hover {
  color: var(--accent-deep);
}

.state-resource-card__desc {
  font-size: 0.89rem;
  color: var(--ink-soft);
  line-height: 1.45;
  margin: 0;
}

.state-notice-card {
  background: var(--surface);
  border: 1px dashed var(--rule-strong);
  border-radius: 8px;
  padding: 1.5rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}

.hero__badge-wrap {
  margin-bottom: 0.75rem;
}

.state-disclaimer-banner {
  margin-top: 1rem;
  font-size: 0.89rem;
  color: var(--ink-soft);
  line-height: 1.45;
  border-left: 3px solid var(--accent);
  padding-left: 0.75rem;
}

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

/* The headline sits on the page's own ground and the photograph runs off the
   right edge behind it, so the two meet in a wash rather than at a seam. */
.hero {
  position: relative;
  overflow: hidden;
  background: var(--sheet);
  border-bottom: 1px solid var(--rule);
  /*
   * One banner height for every page.
   *
   * The band used to be exactly as tall as whatever text sat in it, so it was
   * 359px on a state page, 362px on the hub, 379px on ACA and 436px on WIC --
   * and because the photograph is cropped to fill the band, the same picture
   * was framed four different ways as you moved around the site.
   *
   * 290px, which is the tallest hero body on any English page (LIHEAP, at
   * 286px) plus room -- measured, not guessed. It has come down twice: from
   * 500 to 400 by trimming the band's padding and the gaps between its four
   * blocks and widening the text column so the longest headings wrap to two
   * lines instead of three, and from 400 to 290 by bringing the type down with
   * it -- the heading from 2.3rem to 1.95rem, the subtitle from 1.02rem to
   * 0.95rem, the trust row from 0.87rem to 0.82rem. There is no way to take
   * a third off a band that is four blocks of text without the text: the first
   * pass had already spent the spacing.
   *
   * English is the published locale, so English is what the floor is set to.
   * A Vietnamese or Tagalog heading takes a third line on two of the pages
   * and runs to about 430px there. That is a floor doing its job rather than
   * a clamp: a band that held 400px whatever the text did would cut the
   * heading off, and an unreadable heading is worse than an uneven band.
   *
   * The text is centred in that band rather than sitting at the top of it.
   * With one height for every page, a short heading like the hub's would
   * otherwise leave empty white under it and read as a mistake; centred, the
   * same space sits above and below and reads as a margin.
   */
  min-height: 290px;
  display: flex;
  align-items: center;
}

.hero__media {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Stops where the cards below it stop, rather than running to the window
     edge: the banner is content, and content shares one pair of verticals. */
  right: var(--shell-edge);
  width: min(52%, calc((var(--shell) - 2 * var(--shell-pad)) * 0.52));
  z-index: 1;
  /* Stands in until a photograph is dropped in, and sits behind one that is
     still loading, so the hero never shows an empty box. Warm light over a
     cool ground, which is what the photograph will be too. */
  /* Three layers, first that resolves wins: a photograph if one is supplied,
     otherwise the drawn banner, otherwise a wash. A background layer that
     404s simply does not paint, which an <img> cannot do. */
  background:
    /* Anchored near the top: on a wide screen the band is short relative to
       the picture, and centring it would crop the taller head. */
    url("images/hero.jpg") 50% 6% / cover no-repeat,
    url("images/hero.svg") 50% 50% / cover no-repeat,
    radial-gradient(38% 48% at 70% 24%, rgba(255, 237, 211, 0.95) 0%, rgba(255, 237, 211, 0) 70%),
    radial-gradient(30% 40% at 93% 64%, rgba(206, 224, 241, 0.9) 0%, rgba(206, 224, 241, 0) 72%),
    radial-gradient(48% 62% at 52% 92%, rgba(190, 209, 230, 0.85) 0%, rgba(190, 209, 230, 0) 70%),
    linear-gradient(135deg, #f4f7fa 0%, #e5edf6 46%, #d2e0ee 100%);
}

/* Fades the photograph into the page rather than cropping it at a hard line. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  /* A narrow blend, not a long wash: the headline needs clean white behind
     it and the picture needs to stay a picture. Wider than this and the wash
     reaches the nearer face; narrower and the two meet at a visible seam. */
  background: linear-gradient(
    90deg,
    var(--sheet) 0%,
    rgba(255, 255, 255, 0.98) 5%,
    rgba(255, 255, 255, 0.62) 12%,
    rgba(255, 255, 255, 0.16) 19%,
    rgba(255, 255, 255, 0) 25%
  );
}

.hero__body {
  position: relative;
  z-index: 2;
  padding-top: 17px;
  padding-bottom: 15px;
}

/* Says the figures are current before the headline does. It names no year: a
   year is a date stamp that reads as stale the moment the next one arrives,
   and this line is a claim about being current, not about being 2026. Which
   year the figures come from is stated where it is load-bearing instead — the
   bend points, the limits and the line under the estimate.

   One line in every language at 320px, which is what keeps the banner the same
   height whatever the visitor picked. */
.hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 8px;
  padding: 4px 12px;
  background: var(--accent-wash);
  border: 1px solid rgba(20, 64, 110, 0.16);
  border-radius: 999px;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.2;
  color: var(--accent);
  white-space: nowrap;
}

.hero__badge-icon {
  width: 14px;
  height: 14px;
  flex: none;
}

.hero h1 {
  max-width: min(620px, 52%);
  font-family: var(--font-display);
  font-size: 1.95rem;
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.022em;
  color: var(--accent-deep);
  text-wrap: balance;
}

.hero__sub {
  max-width: min(52ch, 52%);
  margin-top: 10px;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* --- the three claims that decide whether a stranger keeps reading */

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

.trust li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: var(--accent-wash);
  border-radius: var(--radius-sm);
  font-size: 0.89rem;
  font-weight: 600;
  color: var(--accent-deep);
}

.trust svg { width: 18px; height: 18px; flex: none; color: var(--accent);
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; }

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

.calc { padding: 30px 0 34px; }

.calc__grid {
  display: grid;
  gap: 20px;
}

@media (min-width: 760px) {
  .calc__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .calc__form { grid-column: 1 / -1; }
}

/* Three columns is the shape this page is really for: what you enter, what it
   comes to, and how that compares with claiming at another age. */
@media (min-width: 1240px) {
  .calc__grid {
    grid-template-columns: minmax(0, 1.36fr) minmax(0, 0.85fr) minmax(0, 1fr);
  }
  .calc__form { grid-column: auto; }
}

/* The row the reader came for. aria-current too, so it is not colour alone. */
.compare tr.is-current > td {
  background: var(--surface-accent, #eef4ff);
  font-weight: 600;
}

.card {
  padding: 20px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.card__title {
  margin: 0 0 16px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--rule);
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent-deep);
}

/* --- fields */

.fields {
  display: grid;
  gap: 16px 14px;
}

@media (min-width: 520px) {
  .fields { grid-template-columns: 1fr 1fr; }
  .field--full { grid-column: 1 / -1; }
  .field label { min-height: 2.6em; }
}

.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.89rem;
  font-weight: 600;
  line-height: 1.45;
  color: var(--ink);
}

.input-wrap { position: relative; display: block; }

input[type="number"],
select {
  width: 100%;
  min-height: 50px;
  padding: 11px 14px;
  background: var(--sheet);
  border: 1px solid var(--field-border);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.95rem;
  line-height: 1.45;
  /* The thickening on hover and focus is an inset shadow, not a wider
     border: a real border would change the box height and shift the row. */
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input[type="number"] { -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

input.has-prefix { padding-left: 30px; }
input.has-unit { padding-right: 88px; }

select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 28px;
  padding-left: 11px;
  /* Matches the text inputs it sits beside. It used to be 0.88rem, which made
     a dropdown visibly smaller than the box under it in the same form. */
  font-size: 0.95rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%234b5563' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

@media (hover: hover) and (pointer: fine) {
  input[type="number"]:hover,
  select:hover {
    border-color: var(--ink-faint);
    box-shadow: inset 0 0 0 1px var(--ink-faint);
  }
}

input[type="number"]:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-wash);
}

/*
 * A field the page refused, marked by weight as well as by colour.
 *
 * ui.js sets this alongside aria-invalid when it writes the error message.
 * Colour alone would leave a red border and nothing else for anyone who cannot
 * tell it from the grey one; the doubled edge is visible without it, and the
 * message underneath says in words what is wrong either way.
 *
 * Focus still wins: a field being edited shows the focus ring, not this.
 */
input.is-invalid,
select.is-invalid {
  border-color: var(--critical);
  box-shadow: inset 0 0 0 1px var(--critical);
}

@media (forced-colors: active) {
  /* The colour is replaced by the system; the doubled edge is what survives. */
  input.is-invalid,
  select.is-invalid { border-width: 2px; }
}

.input-prefix,
.input-unit {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-faint);
  font-size: 0.95rem;
  pointer-events: none;
}

.input-prefix { left: 14px; }
.input-unit { right: 14px; }

.hint {
  margin-top: 5px;
  font-size: 0.89rem;
  line-height: 1.45;
  color: var(--ink-faint);
}

/* A note that qualifies the question above it rather than the answer below,
   so it sits inside the field and reads before the control it applies to. */
.inline-note {
  margin: 0 0 10px;
  padding: 10px 12px;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink);
  background: var(--accent-wash);
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
}

/* The only checkbox on the site. The whole row is the label, so the tap target
   is the sentence and not just the 20px box at the start of it. */
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 44px;
  padding: 10px 0;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--ink);
  cursor: pointer;
}

.check input[type="checkbox"] {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.check input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A scope note under the actions, separated from them the way the actions are
   separated from the fields, so it reads as a footnote to the whole form
   rather than as a hint on the last control. */
.hint--scope {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

.error {
  margin-top: 5px;
  font-size: 0.89rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--critical);
}

.error:empty { display: none; }

/* --- actions */

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 22px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}

.btn { font-family: var(--font-body); font-size: 0.95rem; cursor: pointer; }

/* The TANF directory is a link wearing the primary button, and a link brings
   an underline and the anchor colour with it. A button that is really an <a>
   should still look like a button. */
a.btn--primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  text-decoration: none;
}

.btn--primary {
  min-height: 50px;
  padding: 0 26px;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  color: #fff;
  font-weight: 600;
  transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover {
    background: var(--accent-deep);
    border-color: var(--accent-deep);
    transform: translateY(-1px);
    box-shadow: var(--btn-lift);
  }
}

.btn--primary:active {
  transform: translateY(1px);
  box-shadow: none;
  background: var(--accent-deep);
}

.btn--link {
  min-height: 44px;
  padding: 0 2px;
  background: none;
  border: 0;
  color: var(--accent);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: color 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .btn--link:hover { color: var(--accent-deep); }
}

.btn--link:active { color: var(--ink); }

/* --------------------------------------------------------------- estimate */

.calc__side { display: grid; gap: 16px; }

.estimate {
  display: flex;
  flex-direction: column;
  padding: 20px 22px;
  background: var(--accent-wash);
  border: 1px solid #d7e3f1;
  border-radius: var(--radius);
}

.estimate > div { display: flex; flex-direction: column; flex: 1; }

/*
 * "How this figure was worked out" sits with the explanation it belongs to.
 *
 * It used to carry margin-top: auto, which in a flex column pushes an element
 * to the foot of its container. The result card is as tall as the form beside
 * it, so on a short result -- Medicaid's, which is a verdict and one sentence
 * -- the link ended up marooned two hundred pixels below the text it explains,
 * with nothing in between. Reading down the card you finished the answer and
 * then met a gap.
 *
 * Now it follows the last line of the result, and the leftover height is where
 * leftover height belongs: underneath everything, at the bottom of the card.
 */
.estimate .detail { margin-top: 13px; }

.estimate__title {
  margin: 0 0 12px;
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent);
}

.estimate__empty {
  font-style: italic;
  color: var(--ink-soft);
}

/* Marks figures that were worked out from a sample rather than from anything
   the visitor typed, so a number on arrival cannot be mistaken for theirs.
   It flows with the heading rather than sitting in a flex row beside it: the
   heading is longer in some languages, and a flex row would squeeze it. */
.estimate__tag {
  display: inline-block;
  margin-left: 8px;
  vertical-align: 1px;
  padding: 2px 8px;
  background: var(--sheet);
  border: 1px solid var(--accent-soft);
  border-radius: 999px;
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--accent);
}

/* Names the source of the number rather than leaving it to look like the
   site's own invention: the arithmetic really is SSA's published 2026 formula.
   It sits under the amount, above the example note, so the first thing read
   after the figure is where the figure came from. */
/* Full ink on a white ground rather than grey on the card's blue: this is the
   sentence that tells a reader the figure is SSA's arithmetic and not the
   site's invention, and at 0.8rem in --ink-soft it read as fine print to be
   skipped. Its own panel gives it the contrast the rest of the card gets for
   free. */
.estimate__basis {
  margin-top: 12px;
  padding: 11px 13px;
  background: var(--sheet);
  border-left: 4px solid var(--accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}

.estimate__example {
  margin-top: 11px;
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.estimate__figure {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 8px;
}

.estimate__amount {
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--accent-deep);
}

.estimate__per {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink-soft);
}

/* The yearly figure restated: a number, so it carries full ink and a little
   weight rather than sitting in the same grey as the notes under it. */
.estimate__note {
  margin-top: 10px;
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
  text-wrap: pretty;
}

.verdict {
  margin-bottom: 8px;
  font-size: 1.05rem;
  font-weight: 700;
}

.verdict--yes { color: var(--positive); }
.verdict--no { color: var(--critical); }

.estimate__label {
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.reasons {
  margin-top: 12px;
  display: grid;
  gap: 6px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.reasons li { padding-left: 18px; position: relative; }
.reasons li::before { content: "\2022"; position: absolute; left: 4px; color: var(--critical); }

/* --- breakdown, brackets, limits */

.breakdown {
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px solid #d7e3f1;
  display: grid;
  gap: 8px;
}

.breakdown__row {
  display: grid;
  gap: 1px;
  font-size: 0.89rem;
}

.breakdown__row dt { color: var(--ink-soft); }

.breakdown__row dd {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.detail { margin-top: 13px; }

/*
 * "How this figure was worked out" is the second most important thing in the
 * card, after the figure itself -- it is where somebody checks whether to
 * believe the number. It read as a footnote: 0.86rem, no surface of its own,
 * and a default disclosure triangle, sitting on a card where everything else
 * had a box around it.
 *
 * It now uses the same idiom as the FAQ rows -- a row with the label at one
 * end and a chevron at the other that turns when it opens -- on the white
 * surface the explanation blocks in this card already use, so it reads as a
 * control rather than as small print. It is deliberately NOT the primary
 * button's fill: the submit button is the one solid thing on the page, and
 * this sits below a result somebody has already got.
 *
 * The chevron is drawn in CSS rather than added to sixteen pages' markup.
 */
.detail summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
  background: var(--sheet);
  border: 1px solid #d7e3f1;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent);
  list-style: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.detail summary::-webkit-details-marker { display: none; }

.detail summary::after {
  content: "";
  flex: none;
  width: 14px;
  height: 10px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='10' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%2314406e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.18s ease;
}

.detail[open] summary::after { transform: rotate(180deg); }

@media (hover: hover) and (pointer: fine) {
  .detail summary:hover {
    border-color: var(--accent);
    background: var(--accent-wash);
  }
}

@media (prefers-reduced-motion: reduce) {
  .detail summary,
  .detail summary::after { transition: none; }
}

.detail__sub {
  margin-top: 14px;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.detail .breakdown { border-top: 0; padding-top: 0; }

.tiers {
  margin-top: 10px;
  display: grid;
  gap: 7px;
  font-size: 0.89rem;
  color: var(--ink-soft);
}

.tiers li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px 12px;
}

.tiers li span:last-child { font-weight: 600; font-variant-numeric: tabular-nums; }

.caps {
  margin-top: 13px;
  padding: 11px 13px;
  background: var(--caution-wash);
  border-radius: var(--radius-sm);
}

.caps__label {
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--caution);
}

.caps__list {
  margin-top: 6px;
  display: grid;
  gap: 5px;
  font-size: 0.89rem;
  color: var(--ink);
}

.caps__list li { padding-left: 16px; position: relative; }
.caps__list li::before { content: "\2022"; position: absolute; left: 3px; color: var(--caution); }

/* The disclaimer sits outside the estimate, in view before a figure exists
   and still in view beside it afterwards. */
.estimate-note {
  display: flex;
  gap: 11px;
  margin-top: 20px;
  padding: 14px 18px;
  background: var(--accent-wash);
  border-radius: var(--radius);
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.estimate-note svg {
  width: 17px; height: 17px;
  flex: none;
  margin-top: 2px;
  color: var(--accent);
}

.estimate-note a { color: var(--accent); text-underline-offset: 3px; }

/* ---------------------------------------------------------- compare table */

.compare {
  display: flex;
  flex-direction: column;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

/* The card matches its neighbours' height, but the rows keep theirs: letting
   the table absorb the difference gave the SSI page 128px-tall rows. */
.compare__scroll { flex: 0 0 auto; }
.compare::after { content: ""; flex: 1; }

/* The card clips, for its rounded corners. So a table wider than the card was
   silently cut off rather than scrolled: WIC lost its Hawaii column at 320px
   and LIHEAP lost the right-hand half of every sentence at every width, with no
   scrollbar and no sign anything was missing. The cell padding below keeps this
   from triggering on the common widths; when it does trigger the reader can at
   least reach the rest. */
.compare__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* Narrow enough to need scrolling is narrow enough to want the bar visible. */
.compare__scroll { scrollbar-width: thin; }

/*
 * The comparison tables are laid out when they are scrolled to, not on load.
 *
 * They are the most expensive thing on a page to lay out -- a table with
 * `table-layout: auto` is measured twice, and these hold whole sentences in
 * cells -- and on every page that has one they are well below the fold. On a
 * 4x-throttled phone this took layout on /wic-eligibility from 620ms to 534ms
 * and on /states/texas/snap from 644ms to 541ms, measured with
 * tools/measure-performance.js.
 *
 * `auto` and not `hidden`: the content stays in the accessibility tree, stays
 * findable with the browser's own find, and an anchor link into it still works.
 * The intrinsic size is a placeholder for a table that has not been measured
 * yet; `auto` in front of it means the real height is remembered once it has,
 * so scrolling past one does not shift the page a second time.
 *
 * Scoped to these tables deliberately. The same rule on the FAQ, the footer or
 * the recommendation cards measured slightly WORSE -- the skipped work is
 * smaller than the bookkeeping -- so it is applied where the evidence is and
 * nowhere else.
 */
.compare__scroll {
  content-visibility: auto;
  contain-intrinsic-size: auto 480px;
}

.compare__scroll table { min-width: 100%; }

.compare__title {
  padding: 18px 16px 14px;
  font-size: 0.83rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent-deep);
}

.compare table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.89rem;
}

.compare th,
.compare td {
  padding: 12px 15px;
  text-align: right;
  white-space: nowrap;
}

/* Only the amounts are held to one line. The headings and the row labels are
   longer in some languages — "Comparación por edad de solicitud" with
   "62 años (anticipada)" under it overflowed the card by 34px in Spanish, and
   the SSI headings did the same in Tagalog at 320px — so they wrap instead.
   Keeping the label on one line was only there to hold the chosen row's check
   mark against its text; the script now does that with a nowrap span around
   the last word and the mark (.compare__chosen below). */
.compare th { white-space: normal; }

/* Two of these tables hold sentences rather than amounts — LIHEAP's "what the
   money pays for" and Section 8's three income tiers — and nowrap made each
   sentence one unbreakable line. The LIHEAP table came out 1,182px wide inside
   a 286px card and the card, which clips, simply cut it off: no scrollbar, no
   sign anything was missing, just a paragraph ending mid-word. Sentences wrap. */


/* The agency and its own address, one cell and one link: whose decision it is
   and where they say so are one fact, and on a phone they are also the only
   way three columns of English words fit a 320px card. */
.sources__agency {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  text-decoration: none;
}

.sources__agency > span:first-child { text-decoration: underline; text-underline-offset: 3px; }

.sources__host {
  font-family: var(--font-body);
  font-size: 0.89rem;
  color: var(--ink-faint);
}

.compare th:first-child,
.compare td:first-child { text-align: left; white-space: normal; }

.compare thead th {
  background: var(--accent-deep);
  color: #fff;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.compare tbody tr + tr { border-top: 1px solid var(--rule); }

.compare tbody td { font-variant-numeric: tabular-nums; }
.compare tbody td:nth-child(2) { font-weight: 600; }
.compare tbody td:last-child { color: var(--ink-soft); }

/* Two tables need more columns than the 357px sidebar they sit in comfortably
   holds. WIC has four — household size beside the 48 states, Alaska and Hawaii
   — and needed 406px, so the Hawaii column was cut off. Unemployment has three,
   but its middle cell is a whole formula ("quarter ÷ 26, $40–$450") held on one
   line, which alone takes 205px.

   The figures themselves are short; the padding is what does not fit, so the
   padding is what gives way. */
.compare--tight table {
  font-size: 0.89rem;
}

/* At 16px the middle cell's compound fact sets a width that overflows 357px in
   Spanish and Tagalog. Break at spaces; the figures still never break. */
.compare--prose td,
.compare--tight td { white-space: normal; }

.compare--tight th,
.compare--tight td { padding-inline: 3px; }

.compare--tight th:first-child,
.compare--tight td:first-child { padding-left: 6px; }

.compare--tight th:last-child,
.compare--tight td:last-child { padding-right: 6px; }

.compare tbody tr.is-chosen { background: var(--accent-wash); }
.compare tbody tr.is-chosen td { color: var(--accent-deep); font-weight: 600; }

/* Holds the label's last word and the mark together. */
.compare__chosen { white-space: nowrap; }

.compare__mark {
  display: inline-block;
  width: 15px; height: 15px;
  margin-left: 6px;
  vertical-align: -2px;
  color: var(--accent);
}

/* Names the full-retirement-age row in the advanced comparison. Its own block
   under the age rather than beside it, so it does not wrap around the number. */
.compare__fra {
  display: block;
  margin-top: 2px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--accent-soft);
}

/* ---------------------------------------------------------------- features */

/* Says once, at the top of the form, what would otherwise need a marker on
   every field: almost everything is required, so marking the exceptions is
   quieter than marking the rule. */
.form-note {
  margin: -4px 0 18px;
  padding-bottom: 14px;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--rule);
}

/*
 * The same note, below the buttons instead of above the fields.
 *
 * Five pages -- Section 8, WIC, LIHEAP, unemployment and CTC -- end their form
 * with a note saying what the page does not cover. It reused the class of the
 * note that sits at the TOP of a form, and inherited its -4px top margin: the
 * sentence was pulled up against the submit button, and the rule meant to
 * close off the top note drew a stray line underneath it. On the eleven pages
 * with no closing note the button row simply ended the form and looked right,
 * which is why only these five ever looked wrong.
 *
 * Matched on position rather than by adding a class, so a note moved below the
 * actions is corrected wherever it appears, including on generated pages.
 */
.actions + .form-note {
  margin: 18px 0 0;
  padding-bottom: 0;
  border-bottom: none;
}

/* --- the requirement checklist (WIC, and the screeners that follow it)

   Some programmes are not one test but several, and reporting them as a single
   verdict hides which one actually decided the answer -- and hides the ones a
   web page has no business deciding at all. This list gives each requirement
   its own row, its own status and its own sentence, so "not eligible" always
   says which gate closed and "eligible" never overclaims. */

.req__title {
  margin: 22px 0 10px;
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.req-list {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.req {
  display: flex;
  gap: 10px;
  padding: 11px 12px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule-strong);
  border-radius: 4px;
}

/* Met, failed, and "nobody here can answer this" read differently on purpose:
   a requirement settled at the appointment is not a failure and must not look
   like one. */

.req__mark {
  flex: 0 0 auto;
  width: 18px;
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
  color: var(--ink-faint);
}

.req--yes .req__mark { color: var(--positive); }
.req--no .req__mark { color: var(--critical); }

.req__body { display: block; min-width: 0; }

.req__name {
  display: block;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
}

.req__status {
  display: block;
  margin-top: 1px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.req--yes .req__status { color: var(--positive); }
.req--no .req__status { color: var(--critical); }

.req__detail {
  display: block;
  margin-top: 5px;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* --- the income band (LIHEAP)

   Some programmes do not have a threshold to report, only a range their state
   must work inside. A verdict cannot say "somewhere between these two lines,
   and your state picks where"; a band with the household marked on it can, and
   makes the near misses visible -- how far under the floor, how close to the
   ceiling -- which a yes or a no destroys. */

.band { margin: 18px 0 4px; }

.band__title {
  margin: 0 0 12px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.band__track {
  position: relative;
  height: 10px;
  margin: 0 0 8px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-radius: 999px;
}

/* The stretch states differ over. Filled, because it is the part of the scale
   that is genuinely undecided rather than empty. */
.band__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--accent-wash);
  border-left: 2px solid var(--rule-strong);
  border-right: 2px solid var(--rule-strong);
}

.band__tick {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  background: var(--rule-strong);
}

/* Where the household sits. Coloured by outcome, because the same position
   means different things: under the floor is settled, in the band is not. */
.band__marker {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  background: var(--accent-deep);
  border: 2px solid var(--sheet);
  border-radius: 50%;
  box-shadow: 0 0 0 1px var(--rule-strong);
}

.band__marker[data-outcome="belowFloor"],
.band__marker[data-outcome="categorical"] { background: var(--positive); }
.band__marker[data-outcome="aboveCeiling"] { background: var(--ink-faint); }

.band__value {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.band__keys {
  display: grid;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.89rem;
  line-height: 1.45;
  color: var(--ink-faint);
}

/* The thing a household most needs to know and is least often told: being
   eligible is not being paid. Set apart so it cannot read as boilerplate. */
.band__funds {
  margin-top: 14px;
  padding: 11px 12px;
  background: var(--band);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}

/* --- benefits discovery hub (index.html)
   Same tokens, same card system and same type scale as the calculators; the
   homepage is a different arrangement of the existing identity, not a new one.
   Mobile-first: every grid below is one column until there is room for more. */

/* Brand above the H1: the heading says what you came to do, this says whose
   site it is. 46% ceiling as elsewhere in the hero; the tight line-height is
   what keeps this banner the same height as every other page's. */
.hub-hero__kicker {
  /* 52%, the same column the lede takes. At 46% the brand line went to a
     second line in Spanish and Tagalog on a phone; at 50% it still did in
     Spanish at exactly 1200px, where half the shell is 576px and that line
     needs 582. The banner is one height in six languages or it is not one
     height. */
  max-width: 52%;
  margin: 0 0 6px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The 46% ceilings are what hold the text clear of the photograph, which is
   absolutely positioned over the right 52% of the band. Without them the
   headline runs under the picture and is swallowed by it. */
.hub-hero__title {
  max-width: min(560px, 46%);
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 1.14;
  font-weight: 700;
  letter-spacing: -0.022em;
  color: var(--accent-deep);
  text-wrap: balance;
}

/* Matched to .hero__sub, which is the same sentence in the same place on the
   other twenty pages and was a different size and a different width here. */
.hub-hero__lede {
  /* 54ch, not 52: at 52 the Tagalog lede took a fourth line and the banner
     with it, 315px against every other language's 289. 54 is 502px, which is
     the width that language needs for three, and still inside the measure a
     lede should keep. */
  max-width: min(54ch, 52%);
  margin: 0 0 12px;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/*
 * Two lines' worth, reserved, from 900px up.
 *
 * English and Chinese fit this sentence on one line; Korean, Spanish,
 * Vietnamese and Tagalog need two. Without the reservation the whole banner
 * jumped 26px the moment a visitor changed language -- four of the six
 * languages moved it, so this was the common case rather than the exception.
 *
 * 3em is exactly two lines: line-height is 1.5, so 2 x 1.5em. Reserving the
 * taller of the two costs English a line of empty space and costs nobody a
 * layout shift.
 *
 * Below 900px the photograph sits above the text and the band is expected to
 * animate between heights instead, so this deliberately does not apply there.
 */
@media (min-width: 1200px) {
  .hub-hero__lede { min-height: 3em; }
}

.hub-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  max-width: min(60ch, 60%);
  margin: 0 0 11px;
}

.btn--outline-hero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 0 22px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--accent-deep);
  background: var(--sheet);
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn--outline-hero:hover {
  background: var(--accent-wash);
  color: var(--accent-deep);
  border-color: var(--accent-deep);
}

/*
 * There is no large button.
 *
 * .btn--lg existed for the hub's two calls to action and made them 52px and
 * 1.02rem against the 50px and 0.98rem of every other primary button on the
 * site. Two pixels and four hundredths of a rem is not emphasis anybody reads
 * as deliberate; it reads as the home page having drifted. One primary button,
 * one size, everywhere -- tests/browser/ui-consistency.js holds it there.
 */

/* The four things a visitor most needs to know, in the same glance as the
   headline. They were a line of faint monospace; they are now the .trust chips
   every calculator page carries, so type and colour come from that component.
   No 46% cap: prose runs to any width it is given and ran under the picture,
   chips stop where they run out. Capping them is what made them wrap, and a
   second row is 44px this banner has not got. */
.hub-hero__trust { margin-top: 8px; }

.hub-section { padding: 34px 0; }
.hub-section--band { background: var(--band); border-block: 1px solid var(--rule); }

.hub-section__title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ink);
}

.hub-section__intro {
  margin: 0 0 20px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.hub-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
}

.hub-all-group__title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
  margin: 28px 0 6px;
  padding-bottom: 8px;
  border-bottom: 1.5px solid var(--rule);
}

.hub-all-group__title:first-of-type {
  margin-top: 0;
}

.hub-all-group__icon {
  width: 20px;
  height: 20px;
  color: var(--accent);
  flex-shrink: 0;
}

/*
 * The full index: a list, where it used to be sixteen cards.
 *
 * A card carried a sentence of description, and fourteen of the sixteen say
 * that sentence again further up the page. What is left here is what an index
 * is for -- the name, what the tool hands back, and whether it computes or
 * screens -- so it is set as rows a reader can run an eye down rather than
 * blocks they must read.
 */
.hub-list {
  display: grid;
  /* minmax(0, ...) and not the default auto: an auto column takes the widest
     row's max-content, and these rows do not wrap, so the list grew past the
     shell and scrolled the phone sideways by 45px. */
  grid-template-columns: minmax(0, 1fr);
  gap: 2px;
  margin: 0 0 6px;
  padding: 0;
  list-style: none;
}

.hub-list__link {
  display: flex;
  align-items: center;
  gap: 12px;
  /* 48px of target, which is above the 44px minimum and worth having: this is
     a list of sixteen adjacent links on a phone. */
  min-height: 48px;
  min-width: 0;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--ink);
}

.hub-list__name {
  font-weight: 600;
  flex: 0 0 auto;
}

/* Takes the room between the name and the badge, so the badges line up down
   the column instead of sitting wherever a name happens to end. Both it and
   the name stay on one line: a wrapped row is a taller row, and a column of
   rows that are not the same height is harder to scan than a longer list. */
.hub-list__outcome {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.89rem;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hub-list__name { white-space: nowrap; }

.hub-list .tool-badge { flex: none; }

@media (hover: hover) and (pointer: fine) {
  .hub-list__link:hover { background: var(--accent-wash); }
  .hub-list__link:hover .hub-list__name { color: var(--accent-deep); }
}

.hub-list__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/*
 * Below 700px the row is two lines, because one line cannot hold it.
 *
 * Held on one line at 390px the outcome ran out of room and the ellipsis ate
 * it on five of the sixteen rows, and on all sixteen at 320px -- which throws
 * away the one thing this column is here to say. The name and the badge take
 * the first line, the outcome takes the second, and nothing is hidden.
 */
@media (max-width: 699px) {
  .hub-list__link { flex-wrap: wrap; row-gap: 1px; padding: 8px 10px; }
  .hub-list__name { order: 1; }
  .hub-list .tool-badge { order: 2; margin-left: auto; }
  .hub-list__outcome {
    order: 3;
    flex: 1 0 100%;
    white-space: normal;
    overflow: visible;
  }
}

/* Two columns, not three, and only once there is room for the longest row on
   one line: "Medicaid  Monthly amount  ELIGIBILITY CHECK" is 384px, and in a
   third-width column it wrapped, which left the rows different heights and the
   badges scattered instead of in a column. */
@media (min-width: 1000px) {
  .hub-list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 18px; }
}

.hub-card {
  display: block;
  min-height: 44px;
  padding: 17px 18px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/*
 * A calculator card says three things now, in the order somebody needs them:
 * which programme it is, what it does, and what it hands back.
 *
 * It used to say two -- a name and a sentence, in a plain white box -- so six
 * of them read as six paragraphs and nothing on any of them said whether you
 * would get a figure or a yes-or-no. The outcome line is the useful addition:
 * it comes from the registry's `figure` field, so it is a fact about the
 * calculator rather than a caption, and it is the thing that lets somebody
 * choose between two cards instead of opening both.
 */
.hub-card {
  display: flex;
  flex-direction: column;
  gap: 9px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.hub-card-badge-row {
  display: flex;
  align-items: center;
  margin-bottom: 2px;
}

.hub-card-head {
  display: flex;
  align-items: center;
  gap: 11px;
}

.hub-card-icon {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  padding: 8px;
  background: var(--accent-wash);
  border-radius: 50%;
  color: var(--accent);
  transition: background 0.15s ease, color 0.15s ease;
}

.hub-card-name {
  display: block;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--accent-deep);
}

.hub-card-text {
  display: block;
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* Pushed to the foot so the row of cards ends on one line, whatever length
   the sentence above it runs to. */
.hub-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 11px;
  border-top: 1px solid var(--rule);
}

.hub-card-outcome {
  font-family: var(--font-label);
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hub-card-go {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  font-size: 0.89rem;
  font-weight: 700;
  color: var(--link);
}

/* A real glyph rather than a background image, so it takes its colour from
   the link it sits in and High Contrast Mode can repaint it. A data-URI arrow
   has its stroke baked in and goes invisible there. */
.hub-card-arrow {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  transition: transform 0.15s ease;
}

.hub-needs, .hub-trust {
  display: grid;
  gap: 18px;
  grid-template-columns: 1fr;
}

/*
 * "Find benefits by need": six routes in, not six paragraphs.
 *
 * This section was six unlabelled stacks of underlined text on one flat band.
 * Nothing had an edge, so the three columns read as one block of prose; the
 * links were body-coloured (see --link above) so they did not read as links;
 * and the one category with a paragraph in it made its row ragged.
 *
 * It is now six cards carrying the same edge, radius and hover as the
 * calculator cards in the section above -- the page has one card, and this is
 * it -- with each link a full-width row that says where it goes. Somebody who
 * does not know which programme they want is the whole audience for this
 * section, and a row you can hit is easier to act on than a word you have to
 * aim at.
 */
.hub-need {
  display: flex;
  flex-direction: column;
  padding: 18px 18px 14px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.hub-need__head {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 0 0 13px;
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--accent-deep);
}

/* The icon gets a disc, so each card has one place the eye lands first. */
.hub-need__icon {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  padding: 7px;
  background: var(--accent-wash);
  border-radius: 50%;
  color: var(--accent);
}

/* A pill, not an aside: it is the one thing that distinguishes this card. */

/*
 * The rows sit under the heading they belong to.
 *
 * margin-top: auto here pushed them to the foot of the card, which lined the
 * six cards up neatly and left "Food Assistance" with one link floating at the
 * bottom of an empty box. It is the same mistake the result card's working
 * link had, made again three sections down the same page: in a flex column
 * `auto` is not alignment, it is exile. The cards are equal height because the
 * grid stretches them; the leftover height belongs at the bottom.
 */
.hub-need__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.hub-need__list li + li { border-top: 1px solid var(--rule); }

.hub-need__list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 44px;
  padding: 10px 10px 10px 11px;
  margin: 0 -10px;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--link);
  transition: background 0.14s ease, color 0.14s ease;
}

/* Where the row goes: a chevron for a page on this site, an arrow leaving the
   corner for one that is not. Driven by target="_blank", which the builder
   already sets on the outbound links, rather than by a class to keep in step. */
.hub-need__list a::after {
  content: "";
  flex: none;
  width: 13px;
  height: 13px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 12 12'%3E%3Cpath d='M4 2l4.5 4L4 10' fill='none' stroke='%2314406e' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  opacity: 0.55;
  transition: opacity 0.14s ease, transform 0.14s ease;
}

.hub-need__list a[target="_blank"]::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 12 12'%3E%3Cpath d='M4.5 1.5h6v6' fill='none' stroke='%2314406e' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.5 1.5L5 7' fill='none' stroke='%2314406e' stroke-width='1.7' stroke-linecap='round'/%3E%3Cpath d='M9 8.6v1.9h-7.5V3h1.9' fill='none' stroke='%2314406e' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

@media (hover: hover) and (pointer: fine) {
  .hub-need:hover { border-color: var(--rule-strong); }

  .hub-need__list a:hover {
    background: var(--accent-wash);
    color: var(--accent-deep);
  }
  .hub-need__list a:hover::after { opacity: 1; transform: translateX(2px); }
  .hub-need__list a[target="_blank"]:hover::after { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hub-need__list a,
  .hub-need__list a::after { transition: none; }
  .hub-need__list a:hover::after { transform: none; }
}

@media (forced-colors: active) {
  .hub-need { border: 1px solid CanvasText; }
  .hub-need__icon { border: 1px solid CanvasText; }
  .hub-need__list a:hover { outline: 1px solid Highlight; }
}

.hub-categories__cta {
  text-align: center;
  margin: 32px 0 0;
}

.hub-help-header {
  margin-bottom: 20px;
}

.hub-help-grid {
  display: grid;
  gap: 18px;
  grid-template-columns: 1fr;
  margin-bottom: 32px;
}

@media (min-width: 620px) {
  .hub-help-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.hub-help-card {
  display: flex;
  flex-direction: column;
  padding: 22px 20px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .hub-help-card:hover {
    border-color: var(--accent);
    box-shadow: 0 4px 12px rgba(20, 64, 110, 0.08);
    transform: translateY(-2px);
  }
}

.hub-help-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--accent-wash);
  color: var(--accent);
  margin-bottom: 14px;
}

.hub-help-card__icon svg {
  width: 24px;
  height: 24px;
}

.hub-help-card__title {
  margin: 0 0 6px 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.hub-help-card__text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.hub-steps {
  display: grid;
  gap: 18px;
  grid-template-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.hub-step { display: flex; gap: 13px; }

.hub-step__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  font-family: var(--font-label);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--sheet);
  background: var(--accent);
  border-radius: 50%;
}

.hub-step h3 {
  margin: 4px 0 3px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}

.hub-step p, .hub-trust__item p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.hub-trust__item h3 {
  margin: 0 0 5px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}

.hub-learn { margin: 0; padding: 0; list-style: none; }
.hub-learn li { margin-bottom: 4px; }

.hub-learn a {
  display: inline-block;
  min-height: 40px;
  padding: 9px 0;
  font-size: 0.95rem;
  color: var(--link);
}

.hub-final {
  padding: 34px 0 42px;
  background: var(--band);
  border-top: 1px solid var(--rule);
}

.hub-final__cta { margin: 22px 0 0; text-align: center; }

@media (min-width: 620px) {
  .hub-grid, .hub-needs, .hub-trust, .hub-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Below 1200px the photograph becomes a banner above the text, so nothing has
   to leave room for it any more: the column caps go, and the headline and lede
   take the sizes that suit a full-width measure. */
@media (max-width: 1199px) {
  .hub-hero__kicker, .hub-hero__title, .hub-hero__lede, .hub-hero__actions {
    max-width: none;
  }
  .hub-hero__title { font-size: 1.95rem; margin-bottom: 10px; }
  .hub-hero__lede { font-size: 1rem; margin-bottom: 18px; }
  .hub-hero__actions { margin-bottom: 12px; }
}

/*
 * Full-width stacked buttons are a phone answer, not a stacked-banner answer.
 * They came up with the picture when the banner started stacking at 1200px
 * instead of 900, and two 950px-wide buttons on a laptop is not what the
 * change was for. The picture stacks from 1200px; the buttons stack where a
 * row of two would actually crowd, which is the phone.
 */
@media (max-width: 620px) {
  .hub-hero__actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .hub-hero__actions .btn,
  .hub-hero__actions .btn--outline-hero {
    width: 100%;
    text-align: center;
  }
}

/* The hero's headline grows only where the hero is beside the picture. */
@media (min-width: 1200px) {
  .hub-hero__title { font-size: 2.9rem; }
}

@media (min-width: 900px) {
  .hub-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hub-needs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hub-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .hub-trust { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (hover: hover) and (pointer: fine) {
  .hub-card:hover {
    border-color: var(--accent-soft);
    box-shadow: 0 6px 18px -8px rgba(14, 44, 76, 0.45);
    transform: translateY(-2px);
  }

  /* The icon fills in and the arrow moves: the card answers the pointer in
     two places, so it reads as one thing you are about to open. */
  .hub-card:hover .hub-card-icon {
    background: var(--accent);
    color: #fff;
  }
  .hub-card:hover .hub-card-arrow { transform: translateX(3px); }
}

@media (prefers-reduced-motion: reduce) {
  .hub-card,
  .hub-card-icon,
  .hub-card-arrow { transition: none; }
  .hub-card:hover { transform: none; }
  .hub-card:hover .hub-card-arrow { transform: none; }
}

@media (forced-colors: active) {
  .hub-card { border: 1px solid CanvasText; }
  .hub-card-icon { border: 1px solid CanvasText; }
  .hub-card:hover { outline: 2px solid Highlight; }
}

.hub-card:focus-visible, .hub-need__list a:focus-visible, .hub-learn a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- estimate modes (retirement)
   Two ways to answer the same question: a quick one that assumes a flat wage,
   and one that works from a real earnings record. Both stay in the document so
   that switching between them loses nothing anyone typed. */

.modes {
  display: flex;
  gap: 6px;
  margin-bottom: 18px;
  padding: 4px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.modes__tab {
  flex: 1 1 0;
  min-height: 44px;
  padding: 0 14px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.modes__tab.is-active {
  font-weight: 600;
  color: var(--accent-deep);
  background: var(--sheet);
  box-shadow: 0 1px 3px -1px rgba(14, 44, 76, 0.3);
}

.modes__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/*
 * The inactive tab answers the pointer.
 *
 * It had a transition on background and colour and nothing that ever changed
 * either, so hovering the one control on the page that switches what you are
 * looking at did nothing at all -- it read as a label rather than as something
 * you could press. The hover is a step towards the active state, not the
 * active state itself, so the two never look the same.
 *
 * Only where there is a real pointer: on a touch screen :hover sticks after a
 * tap and would leave a tab looking half-selected.
 */
@media (hover: hover) and (pointer: fine) {
  .modes__tab:hover {
    color: var(--accent-deep);
    background: rgba(255, 255, 255, 0.6);
  }

  /* The selected one is already white; hovering it lifts the shadow instead. */
  .modes__tab.is-active:hover {
    background: var(--sheet);
    box-shadow: 0 2px 6px -1px rgba(14, 44, 76, 0.38);
  }
}

.modes__tab:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  .modes__tab { transition: none; }
  .modes__tab:active { transform: none; }
}

/*
 * A gate: this mode cannot run, and here is what to do instead.
 *
 * The site's rule is that a refusal carries no dollar figure at all, and this
 * is the form-level version of it -- said before the fields rather than after
 * a submission, so nobody fills in a birth year and five years of earnings to
 * be told at the end that the answer cannot be produced.
 *
 * The caution palette, not the critical one: nothing has gone wrong and
 * nothing the visitor did caused it. It carries the primary button because the
 * way out -- the quick estimate, which needs none of the missing data -- is a
 * real action and the only one on offer here.
 */
.gate {
  margin: 0 0 20px;
  padding: 16px 18px;
  background: var(--caution-wash);
  border: 1px solid #e3d3b4;
  border-radius: var(--radius-sm);
}

.gate__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--caution);
}

.gate__text {
  margin: 7px 0 0;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink);
}

.gate__action { margin-top: 14px; }

@media (forced-colors: active) {
  .gate { border: 1px solid CanvasText; }
}

/* Says which of the two this is, and what it does not do, before the fields. */
.mode-note {
  margin: -2px 0 14px;
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

.field__legend {
  display: block;
  margin-bottom: 6px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
}

/* The earnings history. Two narrow number columns and a remove button, which
   is the whole of it: a row is a year and an amount. */
.earnings {
  width: 100%;
  margin-top: 4px;
  border-collapse: collapse;
}

.earnings th {
  padding: 0 0 6px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
  color: var(--ink-faint);
}

.earnings th:last-child { width: 44px; }
.earnings td { padding: 0 0 8px; vertical-align: top; }
.earnings td:first-child { width: 34%; padding-right: 8px; }
.earnings td:last-child { width: 44px; padding-left: 8px; }

.earnings input { min-height: 46px; }

.earnings__remove {
  width: 44px;
  min-height: 46px;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--ink-faint);
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .earnings__remove:hover { color: var(--critical); border-color: var(--rule-strong); }
}

.earnings__remove:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.earnings__add { margin: 2px 0 0; }

/* Available to a screen reader, absent from the page. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- related calculators
   Real links between the calculators, sitting at the end of a page once it has
   answered the question it was opened for. Built from data/related-benefits.js
   by build-related.js; the card text is the target calculator's own name and
   subtitle, so it is translated everywhere the rest of the site is. */

/* -------------------------------------------------------------------- guides
 *
 * An article is a .doc page with three extra parts: the question it answers,
 * the short answer set apart from the explanation, and the chain out of it --
 * calculator, related calculators, sibling guides, official sources, in that
 * order. The reader who wants only the answer should be able to stop after the
 * second one.
 */

/* ---------------------------------------------------------------- state pages
 *
 * The band between the banner and the calculator on /states/<state>/<program>.
 * Three cards, because there are exactly three things a visitor cannot get
 * from the national page: what is different here, who runs it, and where the
 * application starts. The third is the one they came for, so it is the one
 * that carries a button.
 */

.hero__back {
  margin: 0 0 10px;
  font-size: 0.95rem;
}

.hero__back a {
  /* The banner is a light sheet, not a dark one, so this is the same accent
   * every other link on the page uses. */
  color: var(--accent-soft);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}

.hero__back a:hover { color: var(--accent); }

.state-band { padding: 26px 0 4px; }

.state-band__grid {
  display: grid;
  gap: 16px;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 860px) {
  .state-band__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.state-band__card {
  display: flex;
  flex-direction: column;
  padding: 20px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

/* The application card is the point of the page, so it says so. */
.state-band__card--apply {
  border-color: var(--accent);
  box-shadow: inset 0 2px 0 var(--accent);
}

.state-band__title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
}

.state-band__card p {
  margin: 0 0 10px;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

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

.state-facts {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
}

.state-facts li {
  position: relative;
  padding-left: 18px;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.state-facts li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

.state-band__link {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

.state-band__apply {
  /* Pushed to the bottom of its card so the three cards' buttons line up
   * however much text sits above them. */
  margin-top: auto;
  display: inline-block;
  text-align: center;
}

.state-band__note {
  font-size: 0.89rem !important;
  color: var(--ink-faint, var(--ink-soft));
}

.state-updated {
  padding: 0 0 30px;
}

.state-updated p {
  margin: 0 0 4px;
  font-size: 0.89rem;
  color: var(--ink-faint, var(--ink-soft));
}

.state-updated__when { font-weight: 600; }

.related { padding-bottom: 34px; }

.related__title {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--ink);
}

.related__intro {
  margin: 0 0 16px;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.related__grid {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
}

@media (min-width: 620px) {
  .related__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .related__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Appears once the visitor has an answer of their own; see related.js. */
.related--answered {
  padding: 24px 20px 32px;
  background: var(--surface-soft, rgba(20, 64, 110, 0.03));
  border: 1px solid var(--accent-wash, rgba(20, 64, 110, 0.15));
  border-radius: var(--radius);
  margin-top: 1.5rem;
}

.related__prompt {
  margin: 0 0 14px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--accent-deep);
}

.related--answered .related__prompt {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  background: var(--accent-wash);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}

.related__card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 44px;
  padding: 16px 17px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.related__name {
  display: block;
  margin-bottom: 3px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--accent-deep);
}

.related__text {
  display: block;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* Why this one, from this calculator. Never a finding -- see the note in
   data/related-benefits.js -- so it is set as supporting text, not a verdict. */
.related__why {
  display: block;
  margin-top: 8px;
  padding-top: 8px;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-faint);
  border-top: 1px solid var(--rule);
}

.related__cta {
  display: block;
  margin-top: 10px;
  font-size: 0.89rem;
  font-weight: 600;
  color: var(--link);
}

.related__cta::after { content: " \2192"; }

/* A programme with no calculator here: the card leaves the site, and says so
   before it is clicked rather than after. */
.related__offsite {
  display: block;
  margin-top: 2px;
  font-family: var(--font-label);
  font-size: 0.83rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

@media (hover: hover) and (pointer: fine) {
  .related__card:hover {
    border-color: var(--accent-soft);
    box-shadow: 0 2px 10px -4px rgba(14, 44, 76, 0.35);
  }
  .related__card:hover .related__cta { color: var(--accent-deep); }
}

.related__card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* -------------------------------------------------- state comparison table */

.state-compare-scroll {
  margin-block: 20px 24px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.state-compare-table {
  width: 100%;
  min-width: 540px;
  border-collapse: collapse;
}

.state-compare-table th {
  background: var(--band);
  color: var(--accent-deep);
  font-weight: 700;
  text-align: left;
  padding: 12px 16px;
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

.state-compare-table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule);
  font-size: 0.95rem;
  color: var(--ink);
  vertical-align: middle;
}

.state-compare-table tbody tr:last-child td {
  border-bottom: none;
}

.state-compare-table tbody tr:hover {
  background: var(--accent-wash);
}

.state-compare-table .state-link {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.state-compare-table .state-link:hover {
  color: var(--accent-deep);
}

.features { padding-bottom: 34px; }

.features__card {
  display: grid;
  gap: 24px 26px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding: 24px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

@media (min-width: 900px) {
  .features__card { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.feature { display: flex; gap: 13px; }

.feature__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px; height: 42px;
  flex: none;
  background: var(--accent-deep);
  border-radius: var(--radius-sm);
  color: #fff;
}

.feature__icon svg { width: 21px; height: 21px; }

.feature h3 {
  margin-bottom: 4px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--accent-deep);
}

.feature p {
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* ----------------------------------------------------------------- content */

.content { padding-bottom: 54px; }

.content__grid { display: grid; gap: 20px; }

@media (min-width: 900px) {
  /* Stretch closes the last few dozen pixels the content balance cannot, so
     the two columns always end on the same line. */
  .content__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .content__col { grid-template-rows: auto 1fr; align-content: stretch; }
}

/* The explainer is far longer than the questions beside it, so its closing
   sections move under them: two columns that end together rather than one
   running 1,400px past the other. */
.content__col {
  display: grid;
  gap: 20px;
  align-content: start;
}

/* Opens the explanation with the two names the rest of it assumes you know.
   SSA and SSI sound alike, are run by the same agency, and answer completely
   different questions; a reader who has them confused reads every paragraph
   below wrong. It spans both columns so it is the first thing in the section
   on either calculator, and the two terms sit side by side from 720px up
   precisely because the point is that they are not the same thing. */
.primer {
  padding: 26px 28px;
  background: var(--accent-wash);
  border: 1px solid #d7e3f1;
  border-radius: var(--radius);
}

@media (min-width: 900px) {
  .primer { grid-column: 1 / -1; }
}

.primer__title {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--accent-deep);
}

.primer__list {
  display: grid;
  gap: 18px;
  margin: 0;
}

/* One definition, not a glossary: each calculator defines the programme it
   actually works out, and the note under it points anyone on the wrong page at
   the right tab.

   It used to be held to 68ch, a reading measure, which left the white card
   filling 62% of the blue box it sits in and stopping in mid-air. On a page
   that is mostly form and figures that read as the text being cut off rather
   than as a measure, so the card fills its box and the line-height carries the
   longer line instead. */
.primer__item {
  padding: 15px 17px;
  background: var(--sheet);
  border-radius: var(--radius-sm);
}

.primer__item dt {
  margin-bottom: 7px;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--accent-deep);
  text-wrap: pretty;
}

.primer__item dd {
  margin: 0;
  font-size: 0.95rem;
  /* A little more than the 1.62 it had: the line is the width of the card now,
     and a longer line needs more room between the lines to track along. */
  line-height: 1.72;
  color: var(--ink);
  text-wrap: pretty;
}

.primer__note {
  margin-top: 16px;
  font-size: 0.95rem;
  line-height: 1.6;
  font-weight: 500;
  color: var(--accent-deep);
  text-wrap: pretty;
}

/* The TANF page has no figure to put in the third column, because TANF has no
   federal figure at all. What goes there instead is the one thing the page can
   give with certainty: the way to the visitor's own state office. It borrows
   .compare's card so the three columns still line up. */
.tanf-directory {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: flex-start;
}

.tanf-directory__note {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink);
  text-wrap: pretty;
}

.content__card {
  padding: 28px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.prose h2 {
  margin: 30px 0 13px;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--accent-deep);
}

.prose h2:first-child { margin-top: 0; }

/* A heading in its own <section> got NO space above it: the rule above is for a
   heading that opens the card, but build-documents.js wraps each heading and
   its paragraph in a <section>, so every heading is a first child and it
   matched all of them -- measured margin-top 0px on the accessibility and site
   map pages against 30px on the flat ones, with the paragraph's own bottom
   margin collapsing out through the section. The space belongs to the section,
   whatever it opens with; the heading rule is left for the pages it was for. */
.prose > section { margin-top: 36px; }
.prose > section > h2 { margin-top: 0; }

/* Vertical rhythm, not a narrower column. These paragraphs run ~150 characters
   a line, so a reading measure is the obvious fix and is the wrong one here:
   "an explanation fills the box it is in" records that these pages were capped
   at 68ch/74ch, left the text filling ~62% of its panel, and had the caps
   removed for it. Capping again measured 63%. So: more leading instead. */
.prose--doc p {
  font-size: 0.95rem;
  line-height: 1.78;
  margin-bottom: 15px;
}

.prose--doc h2 {
  margin-top: 36px;
  margin-bottom: 10px;
}

.prose p { margin-bottom: 13px; font-size: 0.95rem; line-height: 1.65; text-wrap: pretty; }
.prose p:last-child { margin-bottom: 0; }

.prose__list { display: grid; gap: 11px; margin: 0 0 15px; }

.prose__list li {
  padding-left: 15px;
  border-left: 2px solid var(--rule-strong);
  font-size: 0.95rem;
  line-height: 1.6;
}

.prose__list strong { display: block; color: var(--accent-deep); }

.prose__formula {
  padding: 12px 15px;
  background: var(--accent-wash);
  border-radius: var(--radius-sm);
  font-family: var(--font-label);
  font-size: 0.89rem;
  line-height: 1.55;
  color: var(--accent-deep);
}

/* The one box a reader must not mistake for the tool's own promise. */
.callout {
  margin-top: 26px;
  padding: 16px 18px;
  background: var(--band);
  border-radius: var(--radius-sm);
}

.callout__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.callout__head svg { width: 18px; height: 18px; flex: none; color: var(--accent); }

.callout p { font-size: 0.89rem; line-height: 1.6; color: var(--ink-soft); }
.callout a { color: var(--accent); }

/* --- FAQ: <details> so it opens and closes with no script at all */

.faq h2 {
  margin-bottom: 16px;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--accent-deep);
}

.faq__list { display: grid; gap: 11px; }

.faq__item {
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .faq__item:hover { border-color: var(--rule-strong); }
}

.faq__item[open] { border-color: var(--rule-strong); }

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 16px;
  cursor: pointer;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--accent-deep);
  list-style: none;
}

.faq__item summary::-webkit-details-marker { display: none; }

.faq__chevron {
  width: 16px; height: 16px;
  flex: none;
  color: var(--ink-soft);
  transition: transform 0.18s ease;
}

.faq__item[open] .faq__chevron { transform: rotate(180deg); }

.faq__body {
  padding: 0 16px 15px;
  font-size: 0.95rem;
  line-height: 1.62;
  color: var(--ink-soft);
}

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

.footer {
  padding: 34px 0 30px;
  background: var(--accent-deep);
  color: #d5dde4;
  font-size: 0.89rem;
}

.footer__brand {
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 700;
  color: #fff;
}

.footer__tagline {
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 500;
  color: #cfe0ec;
  margin-top: 2px;
}

.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin-top: 16px;
}

.footer__links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  color: #eef3f6;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease, color 0.15s ease;
}

@media (hover: hover) and (pointer: fine) {
  .footer__links a:hover { border-bottom-color: #8fb0c6; color: #fff; }
}

.footer__links svg { width: 13px; height: 13px; opacity: 0.75; }

.footer__fine {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 0.89rem;
  line-height: 1.6;
  color: #a9bccb;
}

.footer__fine p + p { margin-top: 9px; }
.footer__fine a { color: #cfe0ec; }

/* ------------------------------------------------------------- static pages */

/* About, privacy and terms: one column of running text, no calculator. */
.doc { padding: 44px 0 56px; }

/* Filling the column rather than stopping at 74ch, which left every card two
   thirds of the way across its own box and reading as truncated. The extra
   line-height is what makes the longer line trackable. */
.doc .content__card { line-height: 1.75; }

.doc h1 {
  margin-bottom: 6px;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--accent-deep);
  /*
   * "BenefitCalculators.com" is one unbreakable word, and at 2rem it is wider
   * than a 320px phone's text column -- which pushed the whole About page
   * 13px sideways. Breaking it is the only way a heading containing the site's
   * own name fits on the narrowest phone still in use.
   */
  overflow-wrap: break-word;
}

.doc__updated {
  margin-bottom: 26px;
  font-size: 0.89rem;
  color: var(--ink-faint);
}

.doc .prose h2 { font-size: 1.24rem; }

/* --------------------------------------------------- about page redesign */

.about-page {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 36px 36px 44px;
}

/* Reset default prose margins inside about-page so components have intentional rhythm */
.about-page h2 {
  margin: 0;
}

.about-page p,
.sources-page p {
  margin-bottom: 0;
}

/* --- hero header */
.about-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--rule);
  width: 100%;
}

.about-hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  background: var(--accent-wash);
  border: 1px solid rgba(20, 64, 110, 0.18);
  border-radius: 9999px;
  font-family: var(--font-body);
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.about-hero__badge-icon {
  width: 14px;
  height: 14px;
  stroke: var(--accent);
}

.about-hero__title {
  margin: 0;
  width: 100%;
  font-family: var(--font-display);
  font-size: 2.15rem;
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.025em;
  color: var(--accent-deep);
  overflow-wrap: anywhere;
  word-break: break-word;
}

.about-hero__meta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.about-updated-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: 0.89rem;
  font-weight: 500;
  color: var(--ink-soft);
}

.about-updated-pill__icon {
  width: 14px;
  height: 14px;
  stroke: var(--ink-faint);
}

.about-lead {
  margin: 4px 0 0;
  font-size: 1.06rem;
  line-height: 1.75;
  color: var(--ink);
  font-weight: 400;
  text-wrap: pretty;
}

/* --- section wrapper */
.about-section {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* --- 3-card pillars grid */
.about-pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.about-card {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: 0 1px 3px rgba(14, 44, 76, 0.03);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.about-card:hover {
  border-color: var(--rule-strong);
  box-shadow: 0 4px 12px rgba(14, 44, 76, 0.06);
}

.about-card__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--accent-wash);
  color: var(--accent);
  margin-bottom: 16px;
  flex-shrink: 0;
}

.about-card__icon-wrap svg {
  width: 22px;
  height: 22px;
}

.about-card__icon-wrap--mission {
  background: var(--accent-wash);
  color: var(--accent);
}

.about-card__icon-wrap--purpose {
  background: rgba(44, 107, 79, 0.12);
  color: var(--positive);
}

.about-card__icon-wrap--vision {
  background: rgba(118, 39, 187, 0.1);
  color: #5b21b6;
}

.about-card__icon-wrap--caution {
  background: var(--caution-wash);
  color: var(--caution);
}

.about-card__icon-wrap--data {
  background: var(--accent-wash);
  color: var(--accent);
}

.about-card__icon-wrap--privacy {
  background: rgba(44, 107, 79, 0.12);
  color: var(--positive);
}

.about-card__icon-wrap--lang {
  background: rgba(118, 39, 187, 0.1);
  color: #5b21b6;
}

.about-card__icon-wrap--a11y {
  background: var(--caution-wash);
  color: var(--caution);
}

.about-card__icon-wrap--map {
  background: var(--band);
  color: var(--accent-deep);
}

.about-card__icon-wrap--fix {
  background: rgba(155, 48, 48, 0.1);
  color: var(--critical);
}

.about-card__header {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 12px;
}

.about-card__header .about-card__icon-wrap {
  margin-bottom: 0;
}

.about-card__title {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--accent-deep);
}

.about-card__header .about-card__title {
  margin-bottom: 0;
}

.about-card__text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.about-card__text + .about-card__text {
  margin-top: 10px;
}

.about-card__text--sub {
  font-size: 0.89rem;
  line-height: 1.6;
  color: var(--ink-faint);
}

.about-card__text a {
  color: var(--link);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.about-card__text a:hover {
  color: var(--accent-deep);
}

/* --- positioning callout */
.about-callout {
  display: flex;
  gap: 20px;
  padding: 24px 28px;
  background: linear-gradient(135deg, rgba(20, 64, 110, 0.04) 0%, rgba(47, 100, 148, 0.07) 100%);
  border: 1px solid rgba(20, 64, 110, 0.18);
  border-left: 5px solid var(--accent);
  border-radius: var(--radius);
}

.about-callout__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent);
  color: #ffffff;
  flex-shrink: 0;
  margin-top: 2px;
}

.about-callout__icon-wrap svg {
  width: 22px;
  height: 22px;
}

.about-callout__content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.about-callout__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.28rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.about-callout__text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.68;
  color: var(--ink);
}

/* --- user journey 4-step card */
.about-journey-card {
  display: flex;
  flex-direction: column;
  gap: 22px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 28px;
}

.about-journey-card__header {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.about-journey-card__title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 1.28rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.about-journey-card__desc {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

.about-steps {
  display: grid;
  /* minmax(0, ...): a bare 1fr will not shrink below its content. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}

.about-step {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 18px 16px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.about-step__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.about-step__num {
  font-family: var(--font-label);
  font-size: 0.89rem;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-wash);
  padding: 2px 7px;
  border-radius: 4px;
}

.about-step__badge {
  font-size: 0.89rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.about-step__desc {
  margin: 0;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* --- core values card */
.about-values-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 28px;
}

.about-values-card__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.28rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.about-values-card__desc {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-soft);
}

.about-values-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 4px;
}

.about-value-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: 9999px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--accent-deep);
  transition: all 0.15s ease;
}

.about-value-pill:hover {
  background: var(--accent-wash);
  border-color: var(--accent-soft);
  color: var(--accent-deep);
  transform: translateY(-1px);
}

.about-value-pill svg {
  width: 16px;
  height: 16px;
  stroke: var(--accent);
}

/* --- trust & governance grid */
.about-trust-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

.about-card--trust {
  padding: 22px 24px;
}

.about-card--fullwidth {
  grid-column: 1 / -1;
}

.about-card--notice {
  background: #fffdfa;
  border-color: #edd5b3;
}

/* --- responsive media queries */
@media (max-width: 960px) {
  .about-pillars {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .about-steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .about-trust-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .about-page {
    padding: 22px 18px 36px;
    gap: 24px;
  }
  .about-hero__title {
    font-size: 1.55rem;
  }
  .about-callout {
    flex-direction: column;
    gap: 14px;
    padding: 18px 16px;
  }
  .about-journey-card {
    padding: 20px 16px;
  }
  .about-journey-card__header {
    flex-direction: column;
    gap: 12px;
  }
  .about-steps {
    grid-template-columns: minmax(0, 1fr);
  }
  .about-values-card {
    padding: 20px 16px;
  }
  .about-card {
    padding: 18px 16px;
  }
}

/* ==========================================================================
   Sources Page Redesign (.sources-page)
   ========================================================================== */

.sources-page {
  display: flex;
  flex-direction: column;
  gap: 32px;
  max-width: 100%;
}

/* --- hero header */
.sources-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--rule);
  width: 100%;
}

.sources-hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  background: var(--accent-wash);
  border: 1px solid rgba(20, 64, 110, 0.18);
  border-radius: 9999px;
  font-family: var(--font-body);
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.sources-hero__badge-icon {
  width: 14px;
  height: 14px;
  stroke: var(--accent);
}

.sources-hero__title {
  margin: 0;
  width: 100%;
  font-family: var(--font-display);
  font-size: 2.15rem;
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.025em;
  color: var(--accent-deep);
  overflow-wrap: anywhere;
  word-break: break-word;
}

.sources-hero__meta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sources-updated-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  font-size: 0.89rem;
  font-weight: 500;
  color: var(--ink-soft);
}

.sources-updated-pill__icon {
  width: 14px;
  height: 14px;
  stroke: var(--ink-faint);
}

.sources-lead {
  margin: 4px 0 0;
  font-size: 1.06rem;
  line-height: 1.75;
  color: var(--ink);
  font-weight: 400;
  text-wrap: pretty;
}

/* --- 3-card pillars grid */
.sources-pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.sources-card {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: 0 1px 3px rgba(14, 44, 76, 0.03);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.sources-card:hover {
  border-color: var(--rule-strong);
  box-shadow: 0 4px 12px rgba(14, 44, 76, 0.06);
}

.sources-card__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  margin-bottom: 16px;
  flex-shrink: 0;
}

.sources-card__icon-wrap svg {
  width: 22px;
  height: 22px;
}

.sources-card__icon-wrap--primary {
  background: var(--accent-wash);
  color: var(--accent);
}

.sources-card__icon-wrap--sync {
  background: rgba(44, 107, 79, 0.12);
  color: var(--positive);
}

.sources-card__icon-wrap--audit {
  background: rgba(118, 39, 187, 0.1);
  color: #5b21b6;
}

.sources-card__icon-wrap--missing {
  background: var(--accent-wash);
  color: var(--accent);
}

.sources-card__icon-wrap--update {
  background: var(--caution-wash);
  color: var(--caution);
}

.sources-card__icon-wrap--contact {
  background: rgba(155, 48, 48, 0.1);
  color: var(--critical);
}

.sources-card__header {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 12px;
}

.sources-card__header .sources-card__icon-wrap {
  margin-bottom: 0;
}

.sources-card__title {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--accent-deep);
}

.sources-card__header .sources-card__title {
  margin-bottom: 0;
}

.sources-card__text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.sources-card__text a {
  color: var(--link);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.sources-card__text a:hover {
  color: var(--accent-deep);
}

/* --- decisional authority callout */
.sources-callout {
  display: flex;
  gap: 20px;
  padding: 24px 28px;
  background: linear-gradient(135deg, rgba(20, 64, 110, 0.04) 0%, rgba(47, 100, 148, 0.07) 100%);
  border: 1px solid rgba(20, 64, 110, 0.18);
  border-left: 5px solid var(--accent);
  border-radius: var(--radius);
}

.sources-callout__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent);
  color: #ffffff;
  flex-shrink: 0;
  margin-top: 2px;
}

.sources-callout__icon-wrap svg {
  width: 22px;
  height: 22px;
}

.sources-callout__content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sources-callout__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.28rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.sources-callout__text {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.68;
  color: var(--ink);
}

/* --- sources table card */
.sources-table-card {
  display: flex;
  flex-direction: column;
  gap: 20px;
  background: #ffffff;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 28px;
  box-shadow: 0 1px 3px rgba(14, 44, 76, 0.03);
}

.sources-table-card__header {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

.sources-table-card__header-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: var(--accent-wash);
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 2px;
}

.sources-table-card__header-icon svg {
  width: 22px;
  height: 22px;
}

.sources-table-card__title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--accent-deep);
}

.sources-table-card__desc {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.62;
  color: var(--ink-soft);
}

.sources__agency {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  text-decoration: none;
}

.sources__agency > span:first-child {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 3px;
  line-height: 1.4;
}

.sources__agency:hover > span:first-child {
  color: var(--accent-deep);
}

.sources__host {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  padding: 2px 8px;
  background: var(--band);
  border: 1px solid var(--rule);
  border-radius: 4px;
  font-family: var(--font-label);
  font-size: 0.89rem;
  font-weight: 600;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
  text-decoration: none !important;
}

.sources__agency:hover .sources__host {
  background: var(--accent-wash);
  border-color: rgba(20, 64, 110, 0.2);
  color: var(--accent);
}

/* The agency directory: sixteen term/definition pairs. It was a two-column
   table inheriting .compare, which right-aligns cells so amounts line up --
   right for "Alabama / $275", wrong here: it pinned the name to the left edge
   and the agency to the right with the middle empty. A <dl> says what this is,
   grids two-up without losing that to a screen reader, and halves the height. */
.sources-dir {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
}

.sources-dir__item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 14px 16px;
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  transition: border-color 0.12s ease, background 0.12s ease;
}

.sources-dir__item:hover {
  background: #ffffff;
  border-color: var(--rule-strong);
}

.sources-dir__calc {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--accent-deep);
}

.sources-dir__calc a {
  color: inherit;
  text-decoration: none;
}

.sources-dir__calc a:hover { color: var(--link); text-decoration: underline; }

.sources-dir__who { margin: 0; min-width: 0; }

/* Agency and domain on one line where there is room; the domain drops beneath
   when the name is long. */
.sources-dir .sources__agency {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
}

@media (max-width: 760px) {
  .sources-dir { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}


/* --- trust & governance grid */
.sources-trust-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

.sources-card--trust {
  padding: 22px 24px;
}

.sources-card--fullwidth {
  grid-column: 1 / -1;
}

.sources-card--contact {
  background: #fffdfc;
  border-color: #edd8d8;
}

/* --- responsive media queries */
@media (max-width: 960px) {
  .sources-pillars {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .sources-trust-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .sources-page {
    padding: 17px 16px 32px;
    gap: 22px;
  }
  .sources-hero__title {
    font-size: 1.55rem;
  }
  .sources-callout {
    flex-direction: column;
    gap: 14px;
    padding: 18px 16px;
  }
  .sources-card {
    padding: 18px 16px;
  }
  .sources-card--trust {
    padding: 18px 16px;
  }
  .sources-card__header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .sources-card__title {
    font-size: 1.15rem;
    overflow-wrap: anywhere;
    word-break: break-word;
  }
  .sources-card__text {
    overflow-wrap: anywhere;
    word-break: break-word;
  }
  .sources-table-card {
    padding: 16px 10px;
  }
  .sources-table-card__header {
    flex-direction: column;
    gap: 10px;
  }
  .sources-dir__item { padding: 12px 12px; }
}

@media (max-width: 430px) {
  .sources-page {
    padding: 16px 12px 28px;
  }
  .sources-table-card {
    padding: 10px 6px;
    border-radius: var(--radius-sm);
  }
  .sources-dir__item { padding: 10px 12px; }
  .sources__agency > span:first-child {
    font-size: 0.89rem;
  }
  .sources-dir__calc { font-size: 0.89rem; }
  .sources__host {
    padding: 1px 5px;
  }
}

@media (max-width: 360px) {
  .sources-table-card {
    padding: 8px 4px;
  }
  .sources-dir__item { padding: 10px; }
}

/* --------------------------------------------------------------- no script */

/* Some file viewers and in-app browsers on phones open an HTML file with
   scripting turned off. The page still has to read as a finished page there:
   every explanatory line ships as static English markup, and this banner says
   plainly why the calculator itself will not respond. */
.noscript {
  display: block;
  margin: 0 0 20px;
  padding: 14px 16px;
  background: var(--caution-wash);
  border: 1px solid var(--caution);
  border-radius: var(--radius-sm);
  color: var(--caution);
  font-size: 0.89rem;
  line-height: 1.55;
  text-align: left;
}

.noscript strong {
  display: block;
  margin-bottom: 3px;
  font-family: var(--font-label);
  font-size: 0.89rem;
  color: var(--ink);
}

/* ------------------------------------------------------------- narrow view */

/* iOS Safari zooms the whole page when a field it is focusing has text under
   16px, which throws the layout sideways mid-entry and has to be pinched back.
   A hard 16px floor on the controls is the documented way to stop it, and it
   costs nothing: these are already the largest text in the form. */
@media (max-width: 899px) {
  input[type="number"],
  select {
    font-size: 16px;
  }
}

/*
 * The photograph stops being a backdrop and becomes a banner: at these widths
 * it would otherwise sit behind the headline and swallow it.
 *
 * 1200px, not 900px. Beside the picture the text has 46% of the shell, which
 * is 443px at 900px wide -- and into that go a kicker, a 2.9rem headline, a
 * lede and two buttons. English took ten lines and Tagalog fifteen, so the
 * band was 289px on one page and 432px on another: the banner was a different
 * height in different languages, which is the one thing it is not supposed to
 * be. Stacked, the height is the strip's own and the text takes what it needs
 * below it, so every language gets the same band.
 */
@media (max-width: 1199px) {
  /* The fixed desktop band does not apply once the picture stacks above the
     text: the height here is the strip's, and the text takes what it needs. */
  .hero { display: flex; flex-direction: column-reverse; min-height: 0; }
  .hero h1, .hero__sub { max-width: none; }

  .hero__media {
    position: static;
    right: auto;
    width: 100%;
    /*
     * One banner SHAPE for every phone width, rather than one height.
     *
     * It was 190px between 600 and 899px and 150px below that, so the picture
     * jumped to a different crop as the window narrowed -- and at 150px the
     * band was tight enough to cut the tops of their heads off, which is the
     * one thing a photograph of two people must not do.
     *
     * A fixed pixel height does not fix that, it just moves it: the picture is
     * scaled to the width and cropped to the height, so 200px on a 320px
     * screen and 200px on an 880px one are two completely different crops of
     * the same photograph. Holding the RATIO is what keeps the framing
     * constant. The cap stops the band from becoming half the screen on a
     * tablet, and above it the crop tightens gently rather than jumping.
     */
    height: auto;
    aspect-ratio: 21 / 10;
    max-height: 230px;

    /*
     * The same picture at the size a phone actually uses.
     *
     * Above this breakpoint the banner is a 600px-wide panel beside the
     * headline and wants the full file. Below it, it is a 150-190px strip
     * across a 320-430px screen: the 1536px original was 146 KB to fill a box
     * a fifth of its width, on exactly the connection least able to afford it.
     * hero-900.jpg is 62 KB and covers a 430px screen at 2x.
     *
     * The layer order is the desktop rule's, repeated because `background` is
     * a shorthand: photograph, then the drawn fallback, then the wash. A layer
     * that 404s does not paint, so deleting a file falls back rather than
     * breaking.
     */
    background:
      url("images/hero-900.jpg") 50% 6% / cover no-repeat,
      url("images/hero.svg") 50% 50% / cover no-repeat,
      radial-gradient(38% 48% at 70% 24%, rgba(255, 237, 211, 0.95) 0%, rgba(255, 237, 211, 0) 70%),
      radial-gradient(30% 40% at 93% 64%, rgba(206, 224, 241, 0.9) 0%, rgba(206, 224, 241, 0) 72%),
      radial-gradient(48% 62% at 52% 92%, rgba(190, 209, 230, 0.85) 0%, rgba(190, 209, 230, 0) 70%),
      linear-gradient(135deg, #f4f7fa 0%, #e5edf6 46%, #d2e0ee 100%);
  }

  .hero__media::after {
    background: linear-gradient(180deg, rgba(255, 255, 255, 0) 55%, rgba(255, 255, 255, 0.5) 100%);
  }

  /* A banner is an introduction, not a screen. On a 393px phone the old
     54/46 desktop padding plus reserved boxes put the first calculator below
     the fold on every page. */
  .hero__body { padding-top: 24px; padding-bottom: 24px; }
  .hero h1 { max-width: 20ch; font-size: 2.05rem; }
  .hero__sub { max-width: 46ch; }

  /* These three used to reserve the tallest line count any of the six
     languages needs, so the banner was one height whichever was showing. It
     worked, and it was the wrong trade: the headline reserved three lines for
     an English headline that takes one, the line under it five for three, and
     the chips three rows for two -- 151px of empty banner on a 393px phone,
     paid by every visitor on every visit, to smooth a reflow that only
     happens at the moment someone switches language.

     The banner now takes the height its own text needs. The jump is handled
     where it actually occurs instead: ui.js measures the hero before a
     language switch and animates it to its new height, which costs nothing
     when nobody switches. */
  .trust li { white-space: nowrap; min-height: 2.3rem; }
}

/*
 * Above 1200px the nav takes a line of its own too, now that there are seven
 * groups.
 *
 * Six fitted beside the brand and the language control; "Benefits & Updates"
 * is the seventh and they do not. Widening the window does not help, because
 * the header sits in the same max-width shell as the page, so the row is
 * capped around 806px however large the screen is -- and seven groups need
 * 868px in English and 940px in Tagalog. Measured, not guessed.
 *
 * So the header is two lines at every width now: brand and language on the
 * first, the nav across the full width of the second. The alternative was the
 * row wrapping into two ragged halves beside the brand, which is the same
 * height and worse to read.
 *
 * Below 1200px nothing changes -- that block is tuned for a phone and is left
 * exactly as it was.
 */
@media (min-width: 1200px) {
  /* The same arrangement the narrow block uses, and for the same reason: the
     nav is a child of .topbar__right, so giving IT the second line is what
     puts the nav there. Setting the nav to 100% instead sized it against its
     parent and left it starting after the brand -- 106px off the side of a
     1280px page. */
  .topbar__inner {
    position: relative;
    flex-wrap: wrap;
    align-items: center;
    gap: 0;
    min-height: 0;
    padding-top: 10px;
  }

  /* The brand keeps its corner -- this is the one thing that differs from the
     phone, where it is centred. */
  .brand { flex: 0 0 auto; }

  .topbar__right { flex: 1 1 100%; min-width: 0; margin-top: 4px; }

  .nav { justify-content: center; padding-inline: 0; }

  /* Lifted to the corner it used to sit in, so the first line still reads
     brand on the left, language on the right. */
  .lang-switch { position: absolute; top: 10px; right: 0; }
}

/*
 * Below 1200px the nav takes a line of its own.
 *
 * Measured rather than picked: the six groups need 744px at their widest --
 * Tagalog, where every label is a full word -- and on one line with the brand
 * and the language control they do not get that until about 1200px. Above it
 * the header is one line; below it the nav has the full width of the bar,
 * which is enough for one row down to 768px and two on a phone.
 *
 * It used to change at 720px, from a time when the bar held sixteen tabs that
 * could not be made to fit at any width. They wrapped to three rows between
 * 768 and 900 rather than being given their own line, because a fourth row
 * was no better than a third. Six groups can actually fit, so the breakpoint
 * is now where they stop fitting.
 *
 * The language control is lifted out of the row and pinned to the corner: the
 * labels are nowrap and cannot shrink, so in Tagalog and Spanish they pushed
 * it 41px off the side of a 393px screen and dragged the first tab with it.
 */
@media (max-width: 1199px) {
  .topbar__inner {
    position: relative;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0;
    min-height: 0;
    padding-top: 8px;
  }

  .brand { flex: 0 0 100%; text-align: center; }

  /* min-width:0 so the scrolling tab strip inside can actually be bounded.
     A flex item defaults to min-width:auto, which means "never narrower than
     my content" -- and the content here is a nowrap row of nine tabs, so this
     box grew to 612px inside a 320px bar and the strip had nothing to scroll
     within. It has to be set here as well as on .nav: one unbounded ancestor
     is enough to defeat the whole arrangement. */
  .topbar__right { flex: 1 1 100%; gap: 0; min-width: 0; }

  /* On a phone the six groups take the full width of the wrapped bar and
     start at the left, with room kept at the right for the language control
     pinned over that end. They fit without scrolling in every language the
     site ships, which sixteen tabs never did at any width. */
  .nav {
    width: 100%;
    gap: 0 2px;
    justify-content: center;
    padding-inline: 0;
  }

  .nav__group-btn {
    padding: 0 9px;
    font-size: 0.89rem;
    /* 44px keeps the touch target legal. */
    min-height: 44px;
  }

  .nav__link--solo {
    justify-content: center;
    padding: 0 9px;
    font-size: 0.89rem;
    min-height: 44px;
  }

  .lang-switch {
    position: absolute;
    top: 4px;
    right: 0;
  }
}

/*
 * Wherever the bar can wrap, the panel spans it rather than hanging off its
 * group.
 *
 * Two reasons, and the second is the one that decides it. A 200px panel
 * dropped from a group near the right-hand edge of a 320px screen has nowhere
 * to go -- it runs off the side or has to be flipped, and which depends on how
 * wide the label is in the current language. And on a bar that has wrapped to
 * two rows, a dropdown opened from the first row lands on top of the second
 * row's buttons: the seventh group made the bar wrap at 768px and covering a
 * button you can still see is worse than either.
 *
 * The columns are auto-fit rather than a fixed two, which is what makes one
 * rule work across the whole range: six narrow columns at 1024px, two at
 * 390px. A fixed two left the links marooned at opposite ends of a 1000px
 * band on a tablet.
 */
@media (min-width: 1200px) {
  .nav__group:not(.nav__group--states) {
    position: static;
  }

  .nav__panel {
    left: 50%;
    transform: translateX(-50%);
    min-width: 900px;
    max-width: calc(100vw - 40px);
  }

  .nav__panel-inner {
    padding: 14px 18px 12px;
  }

  .nav__panel-all {
    margin-bottom: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--rule);
  }

  .nav__all-link {
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--accent);
  }

  .nav__panel-categories {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 12px;
  }

  .nav__cat-group {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .nav__cat-head {
    display: flex;
    align-items: flex-start;
    width: 100%;
    min-width: 0;
    border-bottom: 1px solid var(--rule);
    padding-bottom: 6px;
    margin-bottom: 6px;
    min-height: 44px;
  }

  .nav__cat-link {
    display: block;
    width: 100%;
    min-width: 0;
    flex: 1 1 100%;
    font-weight: 700;
    font-size: 0.89rem;
    color: var(--ink);
    padding: 2px 2px;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: break-word;
    line-height: 1.45;
    text-align: left;
  }

  .nav__cat-link:hover {
    color: var(--accent);
  }

  .nav__cat-toggle {
    display: none;
  }

  .nav__cat-list {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 2px;
  }

  .nav__calc-link {
    display: block;
    width: 100%;
    min-width: 0;
    padding: 4px 6px;
    min-height: 30px;
    line-height: 1.45;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: break-word;
  }

  .nav__panel--states {
    left: 0;
    right: auto;
    transform: none;
    min-width: 240px;
    max-width: 280px;
    width: max-content;
  }

  .nav__panel-states-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .nav__state-link {
    display: flex;
    align-items: center;
    min-height: 36px;
    padding: 6px 12px;
    font-size: 0.89rem;
    font-weight: 500;
    color: var(--ink);
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: background 0.12s ease, color 0.12s ease;
  }

  .nav__state-link:hover,
  .nav__state-link:focus-visible {
    background: var(--accent-wash);
    color: var(--accent-deep);
  }

  .nav__state-link.is-current {
    color: var(--accent-deep);
    font-weight: 700;
    background: var(--accent-wash);
  }

  .nav__panel-states-all {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--rule);
  }

  .nav__all-states-link {
    display: flex;
    align-items: center;
    min-height: 36px;
    padding: 6px 12px;
    font-size: 0.89rem;
    font-weight: 700;
    color: var(--accent);
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: background 0.12s ease, color 0.12s ease;
  }

  .nav__all-states-link:hover,
  .nav__all-states-link:focus-visible {
    background: var(--accent-wash);
    color: var(--accent-deep);
  }
}

@media (min-width: 900px) and (max-width: 1200px) {
  .nav__group-btn, .nav__link--solo {
    padding: 0 7px;
    font-size: 0.89rem;
  }
}

@media (min-width: 768px) and (max-width: 1199px) {
  .nav__panel-categories {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
  }

  .nav__panel-states-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 4px;
  }

  .nav__state-link {
    display: flex;
    align-items: center;
    min-height: 38px;
    padding: 6px 10px;
    font-size: 0.89rem;
    font-weight: 500;
    color: var(--ink);
    border-radius: var(--radius-sm);
    text-decoration: none;
  }

  .nav__state-link:hover,
  .nav__state-link:focus-visible {
    background: var(--accent-wash);
    color: var(--accent-deep);
  }

  .nav__panel-states-all {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--rule);
  }

  .nav__all-states-link {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    padding: 6px 10px;
    font-size: 0.89rem;
    font-weight: 700;
    color: var(--accent);
    text-decoration: none;
  }

  .nav__cat-group {
    min-width: 0;
  }

  .nav__cat-head {
    display: flex;
    align-items: flex-start;
    width: 100%;
    min-width: 0;
    border-bottom: 1px solid var(--rule);
    padding-bottom: 4px;
    margin-bottom: 4px;
    min-height: 38px;
  }

  .nav__cat-link {
    display: block;
    width: 100%;
    min-width: 0;
    flex: 1 1 100%;
    font-weight: 700;
    font-size: 0.89rem;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: break-word;
    line-height: 1.45;
    text-align: left;
  }

  .nav__cat-toggle {
    display: none;
  }

  .nav__cat-list {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 2px;
  }

  .nav__calc-link {
    display: block;
    width: 100%;
    min-width: 0;
    padding: 4px 6px;
    min-height: 32px;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: break-word;
  }
}

@media (max-width: 1199px) {
  .nav__group { position: static; }

  .nav__panel {
    left: 0;
    right: 0;
    min-width: 0;
    padding: 0;
  }

  /* A menu label may wrap inside its column. */
  .nav__panel .nav__link { white-space: normal; }

  .nav__panel-inner {
    padding: 8px 12px;
    border-radius: 0;
    border-inline: 0;
    border-bottom: 1px solid var(--rule);
  }
}

@media (max-width: 767px) {
  .nav__panel-categories {
    display: flex;
    flex-direction: column;
  }

  .nav__panel-states-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }

  .nav__state-link {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 12px;
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--ink);
    border-bottom: 1px solid var(--rule);
    text-decoration: none;
  }

  .nav__state-link:hover,
  .nav__state-link:focus-visible {
    background: var(--accent-wash);
    color: var(--accent-deep);
  }

  .nav__panel-states-all {
    margin-top: 4px;
    padding-top: 4px;
  }

  .nav__all-states-link {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 12px;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--accent);
    text-decoration: none;
  }

  .nav__cat-group {
    display: flex;
    flex-direction: column;
    border-bottom: 1px solid var(--rule);
  }

  .nav__cat-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 44px;
  }

  .nav__cat-link {
    flex: 1 1 auto;
    font-weight: 600;
    font-size: 0.95rem;
    min-height: 44px;
  }

  .nav__cat-toggle {
    display: flex;
  }

  .nav__cat-list {
    display: none;
    flex-direction: column;
    padding-left: 12px;
    padding-bottom: 6px;
    background: var(--surface);
    border-radius: var(--radius-sm);
    margin-bottom: 6px;
  }

  .nav__cat-group.is-open .nav__cat-list {
    display: flex;
  }

  .nav__calc-link {
    min-height: 44px;
    padding: 8px 10px;
  }

  .nav__panel-all {
    border-bottom: 1px solid var(--rule);
  }
}

/*
 * The narrowest phones, where two rows is worth a little type size.
 *
 * At 320px the six labels take three rows in Spanish, Vietnamese and Tagalog,
 * where every one of them is a whole word -- a 175px header on a screen 568px
 * tall. Nothing is hidden by it, which is the thing that matters, but a third
 * of the screen given to navigation before a word of the page is a poor trade
 * when a shade smaller label buys the row back.
 */


@media (max-width: 620px) {
  html { font-size: 17px; }

  :root { --shell-pad: 16px; }
  .brand { font-size: 1.2rem; }
  .nav { gap: 0; }
  /*
   * 3px, not 5. The five labels need 379px of a 361px bar at 393px, so English
   * and Korean wrapped and left "Sources" alone on a second row; 3px buys the
   * 20px back. The type pass raised these labels from 13.26px to 15.13px and
   * that is what cost the row -- the row is bought back from the padding
   * rather than from the reader, who is the point of the larger label.
   *
   * Spanish, Vietnamese and Tagalog cannot fit on one row at any size: they
   * need 593, 582 and 640px, because every label there is a whole word. They
   * wrap, as they did before, and nothing is hidden by it.
   */
  .nav__group-btn, .nav__link--solo { padding: 0 3px; font-size: 0.89rem; }
  .nav__chev { width: 11px; height: 11px; }
  .lang-trigger { padding: 0 10px; gap: 6px; }
  .lang-trigger__label { display: none; }

  .hero h1 { font-size: 1.72rem; }
  .hero__sub { margin-top: 11px; }
  .hero__badge { margin-bottom: 11px; }
  .trust { margin-top: 16px; }
  .trust li { padding: 7px 11px; }
  .hub-hero__title { font-size: 1.72rem; }

  .card, .content__card, .features__card, .primer { padding: 17px 16px; }
  .estimate { padding: 17px 16px; }
  .estimate__amount { font-size: 2.3rem; }

  .compare th, .compare td { padding: 11px 14px; }
  .compare__title { padding: 15px 14px 12px; }

  .prose h2, .faq h2 { font-size: 1.24rem; }
}

@media (max-width: 400px) {
  /*
   * The label drops one step here, to the 0.83rem floor the type pass keeps
   * for a label, which is 14.11px against the bar's 15.13px.
   *
   * That is what this block was written for and it had stopped working twice
   * over: the 620px block below is later in the file and won at equal
   * specificity, so its padding and size never applied, and the type pass then
   * set both blocks to the same 0.89rem, which left nothing to win. At 15.13px
   * the bar takes a third row in Vietnamese and Tagalog at 393px and in
   * Spanish at 320px. At 14.11px it takes two, and English, Korean and Chinese
   * still fit on one -- still up from the 13.26px this replaced.
   *
   * The declaration order matters: this block must stay after the 620px one.
   */
  .nav__group-btn, .nav__link--solo { font-size: 0.83rem; }
  .nav__chev { width: 10px; height: 10px; }
}

@media (max-width: 430px) {
  .actions { gap: 10px; }
  .actions .btn--primary { width: 100%; }
  /* WIC is the only four-column table on the site — 48 states, Alaska and
     Hawaii beside the household size — and at 320px its amounts needed 326px
     inside a 286px card, so the last column was cut off. Unemployment's three
     were 22px over. Narrowing the cells fits both: a table of figures that
     scrolls sideways on a phone hides the column nobody thinks to look for. */
  .compare th, .compare td { padding: 10px 5px; font-size: 0.89rem; }
  .compare th:first-child, .compare td:first-child { padding-left: 10px; }
  .compare th:last-child, .compare td:last-child { padding-right: 10px; }
  /* Four columns in a 286px card leaves 71px each. */
  .compare--tight th, .compare--tight td { padding-inline: 3px; }
  .compare--tight th:first-child, .compare--tight td:first-child { padding-left: 7px; }
  .compare--tight th:last-child, .compare--tight td:last-child { padding-right: 7px; }
  .tiers li { display: grid; gap: 1px; }
  .tiers li span:last-child { justify-self: start; }
  .features__card { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------- language tweaks */

/* Korean wraps mid-word by default; keep-all breaks on spaces instead. */
:lang(ko) { word-break: keep-all; }

/* Uppercase and wide tracking are Latin devices. On CJK they do nothing but
   pull the characters apart, so those labels drop them. */
:lang(ko) .card__title, :lang(zh) .card__title,
:lang(ko) .estimate__title, :lang(zh) .estimate__title,
:lang(ko) .estimate__label, :lang(zh) .estimate__label,
:lang(ko) .compare__title, :lang(zh) .compare__title,
:lang(ko) .caps__label, :lang(zh) .caps__label {
  letter-spacing: 0;
  text-transform: none;
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ------------------------------------------------- windows high contrast */

/*
 * In forced-colors mode the operating system replaces every colour on the
 * page, and it discards box-shadows entirely. Two things on this site were
 * drawn only with a shadow, and both of them disappeared:
 *
 *   the focus ring on inputs and selects, which trades `outline: none` for a
 *   coloured border plus a shadow halo -- so a keyboard user in High Contrast
 *   had no idea which field they were in;
 *
 *   the raised edge on buttons and cards, which is decoration and does not
 *   matter.
 *
 * The fix is to put a real outline back wherever a shadow was doing the work,
 * and to let the system colours through everywhere else. `forced-color-adjust`
 * is deliberately NOT set to none anywhere: the point of the mode is that the
 * user's colours win.
 */
@media (forced-colors: active) {
  /* The site's own focus ring is a shadow; this is one the OS will honour. */
  input:focus,
  select:focus,
  textarea:focus,
  :focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* A control's edge must stay visible when its colour is replaced. */
  input,
  select,
  textarea,
  .btn,
  .lang-trigger,
  .lang-list {
    border: 1px solid ButtonBorder;
  }

  .skip-link {
    background: Canvas;
    color: CanvasText;
    border-color: CanvasText;
  }

  /*
   * The requirement rows say yes/no with a colour, a glyph and a word. The
   * colour goes here; the glyph is aria-hidden decoration, so the border that
   * carries the same distinction is kept explicitly rather than left to be
   * flattened into one shade.
   */

  /* The current page in the navigation is marked with weight and colour; in
     forced colours only the underline survives, so it is made explicit. */
  .nav__link.is-current,
  .nav__group.is-current > .nav__group-btn {
    text-decoration: underline;
    text-underline-offset: 4px;
  }
}

