/* ============================
   TX SCHOOL OPTIONS — design tokens + components
   Canonical: 03-projects/2026-08-houston-christian-homeschools/blueprint.md §2
              + design/design-spec.md (approved 2026-08-22)
   Fonts load from Google Fonts (see Layout.tsx <link>) — Newsreader (headings)
   + Plus Jakarta Sans (body/UI).
   ============================ */

:root {
  font-size: 112.5%; /* 18px effective base at browser default 16px; still respects user zoom */

  --ink: #123F3A;
  --ink-2: #1E5A52;
  --paper: #FBF8F3;
  --surface: #FFFFFF;
  --panel: #F3EEE5;
  --text: #1E1E1C;
  --muted: #5B5B56;
  --line: #E6DFD2;
  --clay: #C2512E;
  --clay-dark: #A6431F;
  --gold: #E0A52B;
  --gold-soft: #FBEFD4;
  --sky: #DCE8F2;
  --sage: #A8B89F;
  --rose: #F2D7D0;

  --font-heading: "Newsreader", Georgia, "Times New Roman", serif;
  --font-body: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --radius-card: 12px;
  --radius-pill: 999px;
  --radius-input: 8px;
  --shadow-card: 0 4px 16px rgba(18, 63, 58, 0.09);
  --shadow-rest: 0 1px 2px rgba(18, 63, 58, 0.06);

  /* ---- Color system (research/55, 2026-09-29) ----------------------------
     The brand stays ink, clay and gold. Clay is reserved for primary actions
     and gold for Featured; neither is ever a category colour. Colour carries
     meaning: which kind of option (5 families), which section of the page
     (bands), and how complete a card is (tiers). Contrast was checked with
     the WCAG formula: every --fam-*-deep passes AA as text on its tint and
     on white (6.1:1 to 8.8:1). The community (3.8:1) and learning (3.4:1)
     accents are NOT text colours: rules, icons and borders only (3:1). */
  --band: #F4EFE6;      /* alternating section band; --muted on it is 5.96:1 */
  --band-ink: #123F3A;  /* one dark band per page at most; paper on it 11:1 */

  --fam-school-tint: #E2EFEE;    --fam-school-accent: #2B7A74;    --fam-school-deep: #17504B;
  --fam-campus-tint: #E9EAF7;    --fam-campus-accent: #5260B0;    --fam-campus-deep: #333F85;
  --fam-community-tint: #EBF3E1; --fam-community-accent: #5F8F3A; --fam-community-deep: #3B5E22;
  --fam-learning-tint: #FCF0D8;  --fam-learning-accent: #B9821A;  --fam-learning-deep: #7A5210;
  --fam-care-tint: #F4EAF3;      --fam-care-accent: #8A4E88;      --fam-care-deep: #5E2F5C;

  /* Status, named */
  --ok: var(--sage);
  --warn: var(--rose);
  --info: var(--sky);

  /* The neutral family: anything with no option (and the fallback for all
     family-aware components). */
  --fam-tint: var(--panel);
  --fam-accent: var(--line);
  --fam-deep: var(--ink);
}

/* One place maps a family to the three local colours every component reads
   (--fam-tint fill, --fam-accent rule/icon, --fam-deep text on tint). */
[data-family="school"]    { --fam-tint: var(--fam-school-tint);    --fam-accent: var(--fam-school-accent);    --fam-deep: var(--fam-school-deep); }
[data-family="campus"]    { --fam-tint: var(--fam-campus-tint);    --fam-accent: var(--fam-campus-accent);    --fam-deep: var(--fam-campus-deep); }
[data-family="community"] { --fam-tint: var(--fam-community-tint); --fam-accent: var(--fam-community-accent); --fam-deep: var(--fam-community-deep); }
[data-family="learning"]  { --fam-tint: var(--fam-learning-tint);  --fam-accent: var(--fam-learning-accent);  --fam-deep: var(--fam-learning-deep); }
[data-family="care"]      { --fam-tint: var(--fam-care-tint);      --fam-accent: var(--fam-care-accent);      --fam-deep: var(--fam-care-deep); }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: hidden; } /* QA B1: horizontal-overflow guard */

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
}

h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: 600; color: var(--ink); margin: 0 0 0.5em; }
h1 { font-size: 2.5rem; line-height: 1.15; }
h2 { font-size: 1.75rem; line-height: 1.2; }
h3 { font-size: 1.375rem; line-height: 1.3; }
h4 { font-size: 1.1rem; }

@media (max-width: 640px) {
  html { font-size: 106.25%; } /* 17px effective base on mobile */
  h1 { font-size: 2rem; }
}

p { margin: 0 0 1em; max-width: 70ch; }
a { color: var(--clay-dark); }
a.plain { color: inherit; text-decoration: none; }
/* Body-copy links need more than color alone to read as links (WCAG 1.4.1) —
   nav/card/button links stay underline-free by design (icon/position/weight
   already distinguish them), but inline prose links get an underline. */
p a, .lead a, article a, .faq-answer a, li a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
img, svg { max-width: 100%; }

a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, summary:focus-visible {
  outline: 3px solid var(--ink-2);
  outline-offset: 2px;
}

.wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 760px; margin: 0 auto; padding: 0 24px; }

/* ===== THE PAGE GUTTER, AND WHY IT IS WRITTEN TWICE =====================
   This has now shipped broken three times (QA B4, research/32), always the
   same way and never as a typo. `.wrap` sets the 24px gutter with a
   `padding` shorthand. Any LATER rule of equal specificity that also uses
   the `padding` shorthand on an element carrying `.wrap` resets all four
   sides, so the gutter silently becomes 0 and the page renders flush to
   both screen edges at 390. `.home-hero { padding: 18px 0 8px }` did exactly
   that to the fix that was written for the previous occurrence, forty lines
   further down the same file.

   Three things stop the fourth occurrence, in order of how load-bearing
   they are:

   1. The doubled class below. `.wrap.wrap` is specificity (0,2,0), so no
      single-class `padding` shorthand can reach it, whatever the source
      order. It sets only the inline axis, so a co-occurring class is still
      free to own the block axis, which is all any of them ever wanted.
   2. Every rule in this file that pairs with `.wrap` now uses
      `padding-block`, not the shorthand. Belt as well as braces, and it
      makes the intent readable at the call site.
   3. scripts/test-security.mjs greps this stylesheet AND the templates for
      the pattern and fails the build check, so the next occurrence is loud
      instead of shipping to a founder's phone.

   An inline `style="padding: ..."` on a `.wrap` element still beats all of
   this, which is how the /search side of B4 happened. That is what check 3
   covers.
   ======================================================================= */
.wrap.wrap, .wrap-narrow.wrap-narrow { padding-inline: 24px; }

.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--surface); padding: 12px 16px; z-index: 200;
}
.skip-link:focus { left: 0; }

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

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

/* ---------- Header / mega-menu ---------- */

.site-header { background: var(--surface); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 50; }
.header-inner { display: flex; align-items: center; justify-content: space-between; min-height: 68px; gap: 20px; }
.logo { font-family: var(--font-heading); font-weight: 600; font-size: 1.2rem; color: var(--ink); text-decoration: none; display: flex; align-items: center; gap: 8px; }
.logo .mark { width: 30px; height: 30px; border-radius: 8px; background: var(--gold); color: var(--ink); display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-heading); font-weight: 700; font-size: 0.9rem; flex: none; }

.main-nav { display: none; }
@media (min-width: 1024px) { .main-nav { display: block; } }
.main-nav > ul { list-style: none; display: flex; gap: 8px; margin: 0; padding: 0; align-items: center; }
.main-nav > ul > li { position: relative; }
.nav-link { color: var(--ink); text-decoration: none; font-weight: 500; padding: 10px 12px; border-radius: var(--radius-input); display: inline-block; }
.nav-link:hover, .nav-link:focus-visible { background: var(--panel); }
/* QA S1 (research/53): "By option" and "By area" are <button>s and kept the
   browser's grey bevel and smaller font beside styled links. */
button.nav-link {
  background: none; border: 0; font: inherit; font-weight: 500; color: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px; line-height: inherit; -webkit-appearance: none; appearance: none;
}
button.nav-link:hover, button.nav-link:focus-visible { background: var(--panel); }

/* `.main-nav > ul > li { position: relative }` outranks a bare `.has-mega`,
   which anchored the panel to its button: it collapsed to the button's width
   and the area columns spilled over the page (Todd, 2026-10-05). Match that
   specificity so the panel anchors to the sticky header and spans it. */
.has-mega, .main-nav > ul > li.has-mega { position: static; }
.mega-panel {
  display: none; position: absolute; left: 0; right: 0; top: 100%;
  background: var(--surface); border-bottom: 1px solid var(--line); box-shadow: var(--shadow-card);
  padding: 28px 0;
}
/* The nav button ends ~11px above the header's bottom edge, where the panel
   starts. Without a bridge the pointer leaves `.has-mega` crossing that gap
   and the panel closes before it can be reached (Todd, 2026-10-05). The
   bridge is part of the panel, so it only exists while the panel is open. */
.mega-panel::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 24px; }
.has-mega:hover .mega-panel, .has-mega:focus-within .mega-panel { display: block; }
/* The column heading reuses the footer heading class, whose colour is meant
   for the dark footer band and vanishes on the white panel. */
.mega-panel .footer-col-heading { color: var(--muted); margin-bottom: 12px; }
.mega-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
.mega-col h4 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 12px; }
.mega-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 20px; }
.mega-list a { color: var(--text); text-decoration: none; display: flex; justify-content: space-between; padding: 6px 8px; border-radius: 6px; }
.mega-list a:hover { background: var(--panel); }
.mega-count { color: var(--muted); font-size: 0.8em; }
.cluster-block { margin-bottom: 14px; }
.cluster-block .cluster-name { font-weight: 600; font-size: 0.92rem; color: var(--ink); }
.cluster-block .area-links { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.cluster-block .area-links a { font-size: 0.85rem; color: var(--muted); text-decoration: none; }
.cluster-block .area-links a:hover { color: var(--clay-dark); }

.header-actions { display: flex; align-items: center; gap: 10px; }
/* QA B1: "List your program" / "Sign in" collapse into the hamburger panel
   below the same 1024px breakpoint the mega-nav already collapses at — they
   were never hidden, so header-actions overflowed the viewport on every
   page at mobile widths, pushing the hamburger off-screen and (via the
   resulting horizontal scroll) breaking the fixed mobile-sticky-bar too.
   Both links still render in .mobile-nav (see Layout.tsx) so nothing is lost. */
@media (max-width: 1023px) { .header-actions > a:not(.my-list-link) { display: none; } }
/* research/55 S2: My list stays in the header at every width. */
.my-list-link { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; }
.my-list-count {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: var(--radius-pill); background: var(--clay); color: #fff; font-size: 0.75rem; font-weight: 700; line-height: 1;
}
.my-list-count[hidden] { display: none; }
.site-header .nav-link, .header-actions .btn, .logo { white-space: nowrap; }
@media (max-width: 1439px) and (min-width: 1024px) {
  .main-nav > ul { gap: 0; }
  .header-inner { gap: 10px; }
  .site-header .nav-link { padding-inline: 8px; }
  .header-actions { gap: 4px; }
}
@media (max-width: 1279px) and (min-width: 1024px) {
  .my-list-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
  .logo { font-size: 1.05rem; }
  .header-actions .btn-sm { padding-inline: 12px; }
}
@media (max-width: 480px) { .my-list-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; } }
.hamburger { display: inline-flex; background: none; border: none; padding: 8px; cursor: pointer; color: var(--ink); }
@media (min-width: 1024px) { .hamburger { display: none; } }

.mobile-nav { display: none; background: var(--surface); border-top: 1px solid var(--line); padding: 12px 24px 24px; }
.mobile-nav.open { display: block; }
.mobile-nav details { border-bottom: 1px solid var(--line); padding: 10px 0; }
.mobile-nav summary { cursor: pointer; font-weight: 600; }
.mobile-nav .mega-list { grid-template-columns: 1fr; margin-top: 8px; }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border-radius: var(--radius-input); padding: 12px 22px; font-weight: 600; font-size: 1rem;
  text-decoration: none; min-height: 44px; line-height: 1; border: 2px solid transparent; cursor: pointer;
  font-family: var(--font-body); transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.btn-primary { background: var(--clay); color: #fff; }
.btn-primary:hover { background: var(--clay-dark); }
.btn-outline { background: transparent; border-color: var(--ink); color: var(--ink); }
.btn-outline:hover { background: var(--panel); }
.btn-ghost { background: transparent; color: var(--ink); }
.btn-ghost:hover { background: var(--panel); }
.btn-sm { min-height: 36px; padding: 8px 16px; font-size: 0.9rem; }
.btn[disabled], .btn.disabled { opacity: 0.4; cursor: not-allowed; }
.btn-block { width: 100%; }

/* ---------- Chips / Tags / Badges ---------- */

.tag {
  display: inline-flex; align-items: center; gap: 5px; padding: 6px 14px; border-radius: var(--radius-pill);
  font-size: 0.875rem; font-weight: 500; background: var(--panel); color: var(--ink); border: 1px solid var(--line);
  max-width: 100%;
}
/* QA B1 follow-up: found while re-verifying the mobile-overflow fix — some
   required-copy chips (faith precision, "Support Groups & Communities"
   before its short_name) are long enough on their own to overflow a 390px
   viewport when `white-space: nowrap` forces one unbroken line. Wrapping to
   a second line inside the pill is the safe fix; unlike header nav links
   this text has nowhere else to go (it's the chip's whole content). */
@media (max-width: 480px) {
  .tag { white-space: normal; }
}
.tag-sky { background: var(--sky); border-color: transparent; }
.tag-gold { background: var(--gold); color: var(--ink); border-color: transparent; font-weight: 700; }
.tag-sage { background: var(--sage); border-color: transparent; color: var(--ink); }
.tag-rose { background: var(--rose); border-color: transparent; }

.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: var(--radius-pill);
  font-size: 0.9rem; font-weight: 500; background: var(--surface); border: 1px solid var(--line); color: var(--ink);
  text-decoration: none; cursor: pointer; min-height: 40px;
}
.chip:hover { border-color: var(--ink-2); }
.chip-active { background: var(--ink); color: #fff; border-color: var(--ink); }
.chip-row { display: flex; flex-wrap: wrap; gap: 10px; }
.chip-remove { background: none; border: none; color: inherit; font-size: 1em; cursor: pointer; padding: 0 0 0 4px; }

.badge-verified { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--ink-2); font-size: 0.85rem; }

/* ---------- Cards ---------- */

.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
  padding: 18px; transition: box-shadow 150ms ease; display: block;
}
.card:hover, .card:focus-within { box-shadow: var(--shadow-card); }
.card-featured { background: var(--gold-soft); border: 2px solid var(--gold); overflow: hidden; padding: 0; }
.card-featured .featured-topbar { height: 6px; background: var(--gold); }
.card-featured .card-body { padding: 16px 18px 18px; }

/* ---------- Program card (research/55 M5, M6, S1) ----------
   An <article>: the heading link is stretched over the whole card, and
   Website / Save / Request info are real sibling controls above it (no more
   buttons nested inside a link). A letter tile in the family tint replaces
   the empty image band, so a desktop card is a 56px tile left and text
   right, about 40% shorter than the old 140px-thumb card. */
.program-card {
  position: relative; display: flex; flex-direction: column; gap: 10px; color: inherit; height: 100%;
  border-left: 4px solid var(--fam-accent);
}
.program-card-frame { display: flex; flex-direction: column; gap: 12px; height: 100%; }
.program-card-inner { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 14px; align-items: start; }
.program-card-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.program-card h3 { font-size: 1.08rem; margin: 0; line-height: 1.3; }
.program-card .card-link { color: var(--ink); text-decoration: none; }
.program-card .card-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: 0; }
.program-card .card-link:hover { text-decoration: underline; text-underline-offset: 2px; }
.program-card .card-link:focus-visible { outline: none; }
.program-card:has(.card-link:focus-visible) { outline: 3px solid var(--ink-2); outline-offset: 2px; }
.program-card .card-actions, .program-card .card-actions * { position: relative; z-index: 1; }
.program-card .meta-line { color: var(--muted); font-size: 0.9rem; margin: 0; }
.program-card .schedule-stamp { color: var(--ink-2); font-weight: 600; font-size: 0.88rem; margin: 0; display: flex; align-items: center; gap: 6px; }
.program-card .review-quote { font-size: 0.88rem; color: var(--text); font-style: italic; border-left: 2px solid var(--line); padding-left: 10px; margin: 0; }
.program-card .card-actions { display: flex; gap: 8px; margin-top: auto; flex-wrap: wrap; }
.program-card .card-pills { gap: 6px; }
.program-card .card-pills .tag, .program-card .card-meta .tag { font-size: 0.8rem; padding: 3px 10px; }
.program-card .schedule-unknown { color: var(--muted); font-weight: 500; }
.program-card .card-meta .tag-option { margin-right: 2px; }
.program-card .card-claimed { color: var(--ink-2); font-weight: 600; }
.program-card .card-few { font-style: italic; }

/* Three tiers (research/55 "Card hierarchy"). The grid already sorts
   richest first (lib/display-order.ts); this makes it read that way. */
.card.program-card.card-tier-rich { box-shadow: var(--shadow-rest); }
.card.program-card.card-tier-thin { background: var(--paper); box-shadow: none; }
.card.program-card:hover, .card.program-card:focus-within { box-shadow: var(--shadow-card); }
.card-featured.program-card { border-left-width: 2px; border-left-color: var(--gold); }

/* Paid ladder (SAAS_OS research/57 C7, C8). Enhanced is a bigger card with
   a photo, never a better position; Featured is a labeled block of at most
   two cards above the grid, on the one page its slot belongs to. */
.card.program-card.card-large { box-shadow: var(--shadow-rest); }
.program-card .card-photo { margin: -18px -18px 4px; border-radius: var(--radius-card) var(--radius-card) 0 0; overflow: hidden; aspect-ratio: 16 / 9; background: var(--panel); }
.card-featured.program-card .card-photo { margin: 0; border-radius: 0; }
.program-card .card-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.program-card .card-excerpt { font-size: 0.92rem; line-height: 1.5; margin: 0; color: var(--text); }
.program-card .tag-paid { align-self: flex-start; font-size: 0.78rem; letter-spacing: 0.02em; }
.featured-block { margin: 8px 0 20px; }
.featured-block + .card-grid { margin-top: 0; }
.paid-disclosure { font-size: 0.85rem; }
.paid-disclosure a { color: var(--ink-2); }
.listing-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; margin-bottom: 20px; }
.listing-gallery .gallery-thumb { aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden; background: var(--panel); }
.listing-gallery .gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 560px) {
  .program-card-inner { grid-template-columns: 48px minmax(0, 1fr); gap: 12px; }
  .program-card h3 { font-size: 1rem; }
  .program-card .meta-line, .program-card .schedule-stamp { font-size: 0.85rem; }
  .program-card .card-pills { gap: 4px; }
  .program-card .card-pills .tag, .program-card .card-meta .tag { font-size: 13px; padding: 3px 9px; }
  .program-card .card-actions { flex-wrap: nowrap; gap: 6px; }
  .program-card .card-actions .btn { flex: 1 1 auto; min-width: 0; padding-inline: 8px; min-height: 44px; white-space: nowrap; font-size: 0.88rem; }
  .program-card .card-actions .btn-primary { flex-grow: 2; }
  .card.program-card { padding: 14px; }
  .program-card .card-photo { margin: -14px -14px 4px; }
  .listing-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- Monogram tile (research/55 M6) ---------- */
.mono {
  position: relative; display: inline-grid; place-items: center; flex: none;
  width: 56px; height: 56px; border-radius: 11px;
  background: var(--fam-tint); color: var(--fam-deep);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fam-accent) 25%, transparent);
}
.mono-letters { font-family: var(--font-heading); font-weight: 600; font-size: 1.35rem; letter-spacing: -0.02em; line-height: 1; }
.mono-badge {
  position: absolute; right: -6px; bottom: -6px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface); color: var(--fam-accent); display: grid; place-items: center;
  box-shadow: 0 0 0 1px var(--line);
}
.mono-verified {
  position: absolute; top: -3px; right: -3px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--fam-school-accent); box-shadow: 0 0 0 2px var(--surface);
}
.mono-featured { box-shadow: 0 0 0 2px var(--gold), inset 0 0 0 1px color-mix(in srgb, var(--fam-accent) 25%, transparent); }
.mono-header { width: 72px; height: 72px; border-radius: 14px; }
.mono-header .mono-letters { font-size: 1.75rem; }
.mono-header .mono-badge { width: 26px; height: 26px; }
@media (min-width: 900px) {
  .mono-header { width: 96px; height: 96px; border-radius: 18px; }
  .mono-header .mono-letters { font-size: 2.35rem; }
  .mono-header .mono-badge { width: 30px; height: 30px; }
}
@media (max-width: 560px) {
  .mono:not(.mono-header) { width: 48px; height: 48px; border-radius: 10px; }
  .mono:not(.mono-header) .mono-letters { font-size: 1.15rem; }
}

.card-ring { box-shadow: 0 0 0 3px var(--ink-2), var(--shadow-card); }

/* QA N1: raised the column floor from 260px to 300px so auto-fill picks
   fewer, wider columns at a given container width (fewer 4-up grids
   squeezing every card down to the old floor). The container query above
   is what actually guarantees a readable body at whatever width auto-fill
   lands on, though — this floor change alone was not the fix. */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }

/* ---------- Filter rail / quick chips ---------- */

.filter-rail { background: var(--panel); border-radius: var(--radius-card); padding: 18px; }
.filter-rail details { border-bottom: 1px solid var(--line); padding: 12px 0; }
.filter-rail details:last-of-type { border-bottom: none; }
.filter-rail summary { cursor: pointer; font-weight: 600; display: flex; justify-content: space-between; align-items: center; list-style: none; }
.filter-rail summary::-webkit-details-marker { display: none; }
/* QA P7: collapsed groups read as empty headings with no marker. */
.filter-rail summary::after { content: ""; width: 8px; height: 8px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg); margin: -4px 4px 0 12px; flex: none; transition: transform 150ms ease; }
.filter-rail details[open] > summary::after { transform: rotate(-135deg); margin-top: 4px; }
.filter-rail summary { min-height: 32px; }
.filter-rail .opt-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.filter-rail label { display: flex; align-items: center; gap: 8px; font-size: 0.92rem; }
.filter-clear { font-size: 0.85rem; color: var(--muted); text-decoration: underline; background: none; border: none; cursor: pointer; padding: 0; }

.quick-filters { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0; }

/* QA S2: quick-filter row — 4 <details> dropdowns, not a 14-chip dump. */
.qf-row { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0; }
.qf-details { position: relative; }
.qf-details summary { list-style: none; }
.qf-details summary::-webkit-details-marker { display: none; }
.qf-details[open] summary { border-color: var(--ink-2); }
.qf-panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 25; min-width: 220px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
  box-shadow: var(--shadow-card); padding: 12px; display: flex; flex-direction: column; gap: 8px;
}

.disclosure-line { color: var(--muted); font-size: 0.9rem; padding: 10px 0; }

/* ---------- Results layout ---------- */

.results-layout { display: grid; grid-template-columns: 260px 1fr; gap: 24px; align-items: start; }
@media (min-width: 1024px) { .results-layout.with-map { grid-template-columns: 260px 1fr 420px; } }
@media (max-width: 1023px) { .results-layout { grid-template-columns: 1fr; } .filter-rail-col { order: 3; } }
@media (max-width: 1023px) {
  .js .filter-rail-col { display: none; }
  .js body.filters-open .filter-rail-col {
    display: block; position: fixed; inset: 0 0 64px 0; z-index: 55; overflow-y: auto;
    background: var(--paper); padding: 16px 16px 24px; box-shadow: 0 4px 16px rgba(18, 63, 58, .12);
  }
}
/* research/55 P3: filter checkboxes and labels at a 44px tap height. */
.filter-rail label { min-height: 44px; }
.filter-rail input[type="checkbox"], .filter-rail input[type="radio"] { width: 20px; height: 20px; flex: none; accent-color: var(--ink-2); }

/* QA B1 follow-up: /tefa reused .results-layout but overrode its columns
   via an *inline* style ("1fr 260px") to get a content+TOC-rail pair
   instead of the 3-up search layout — inline styles beat the media query
   above at any width, so the 260px rail never collapsed and the page
   overflowed to 592px on a 390px viewport. A dedicated class fixes this
   properly (desktop-only 2-column, real mobile collapse) instead of
   another inline style that would just re-trigger the same bug. */
.tefa-layout { grid-template-columns: 1fr 260px; }
@media (max-width: 1023px) { .tefa-layout { grid-template-columns: 1fr; } }
.map-col { position: sticky; top: 84px; height: calc(100vh - 100px); border-radius: var(--radius-card); overflow: hidden; border: 1px solid var(--line); }
@media (max-width: 1023px) { .map-col { display: none; } }
#leaflet-map { width: 100%; height: 100%; background: var(--panel); margin-bottom: 14px; }
/* Lighthouse target-size: Leaflet's own bottom-left attribution control has
   no built-in clearance from whatever sits right below the map (listing
   "Get directions" link, area-hub content) — the margin above gives real
   space; program.tsx also adds explicit spacing on its own link for the
   same reason. */

.mobile-sticky-bar {
  display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 60;
  background: var(--surface); border-top: 1px solid var(--line); padding: 10px 16px;
  justify-content: space-around; box-shadow: 0 -4px 16px rgba(18,63,58,.08);
}
@media (max-width: 1023px) { .mobile-sticky-bar { display: flex; } }
.mobile-sticky-bar button, .mobile-sticky-bar a {
  background: none; border: none; color: var(--ink); font-weight: 600; font-size: 0.9rem;
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 10px; min-height: 44px;
}

/* ---------- Listing contact bar (phones) ---------- */
/* Product ask (research/53 top 5, #2): Call / Website / Request info kept in
   reach on a phone, where the side box renders at the bottom of the page.
   Only the actions the listing has are rendered (routes/program.tsx). */
.listing-action-bar { display: none; }
@media (max-width: 900px) {
  .listing-action-bar {
    display: flex; gap: 8px; position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    background: var(--surface); border-top: 1px solid var(--line); box-shadow: 0 -4px 16px rgba(18,63,58,.08);
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  }
  .listing-action-bar .btn { flex: 1 1 0; min-height: 44px; justify-content: center; gap: 6px; padding-inline: 8px; white-space: nowrap; }
  /* research/55 sticky bar: Request info leads at twice the width. */
  .listing-action-bar .btn-primary { flex: 2 1 0; order: -1; }
  body.has-action-bar { padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px)); }
}

/* QA P2 (research/53): option and cluster section headings sat flush
   against the last card of the section before. */
.option-section { margin-top: 48px; }
.option-section:first-of-type { margin-top: 24px; }
/* research/55 M5: family swatch before each option heading, count in the
   family's deep colour. */
.opt-swatch { display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 7px; background: var(--fam-tint); color: var(--fam-accent); vertical-align: 0.08em; margin-right: 10px; }
.option-section h2 .mega-count { color: var(--fam-deep); font-family: var(--font-body); font-weight: 700; font-size: 0.9rem; background: var(--fam-tint); border-radius: var(--radius-pill); padding: 2px 10px; vertical-align: 0.3em; white-space: nowrap; }
.chip-option[data-family] { background: var(--fam-tint); color: var(--fam-deep); border-color: transparent; }
.chip-option[data-family]:hover { border-color: var(--fam-accent); }
.chip-option[data-family] .mega-count { color: var(--fam-deep); }
.hub-hero { margin-top: -20px; padding-block: 20px 14px; margin-bottom: 20px; }
.hub-hero .meta-line { margin-bottom: 0; color: var(--text); }

/* QA P5: the rest of the /houston essay, one tap away. */
.intro-more { margin: 0 0 20px; }
.intro-more summary { cursor: pointer; font-weight: 600; color: var(--ink-2); min-height: 44px; display: flex; align-items: center; }

/* QA P4 (research/53): at 1280 the results column was about 420px between
   the filter rail and the map. A slimmer rail and map on laptop widths give
   the cards the room. */
@media (min-width: 1024px) and (max-width: 1439px) {
  .results-layout.with-map { grid-template-columns: 220px minmax(0, 1fr) 320px; gap: 20px; }
}

/* ---------- Search: box, relaxed results ---------- */
.search-dock { margin: 8px 0 16px; box-shadow: none; }
.relaxed-note { background: var(--gold-soft); border-radius: var(--radius-card); padding: 14px 16px; margin: 0 0 16px; }
.relaxed-note .relaxed-lead { font-weight: 600; margin: 0; color: var(--ink); }
.relaxed-note .meta-line { margin: 6px 0 0; }
.relaxed-group { margin-bottom: 20px; }
.relaxed-heading { font-size: 1.05rem; margin: 18px 0 10px; }
.relaxed-more { margin: 10px 0 0; }
.relaxed-try { margin: 8px 0 20px; }
.unmet-capture { margin: 12px 0 24px; }
.unmet-capture summary { cursor: pointer; font-weight: 600; color: var(--ink-2); min-height: 44px; display: flex; align-items: center; }
.inline-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: stretch; }
.inline-form input[type="email"] { flex: 1 1 220px; }

/* ---------- Pagination ---------- */

.pagination { display: flex; gap: 8px; align-items: center; justify-content: center; margin: 32px 0; flex-wrap: wrap; }
.pagination a, .pagination span {
  min-width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center;
  text-decoration: none; color: var(--text); font-weight: 600; padding: 0 8px;
}
.pagination .current { background: var(--ink); color: #fff; }
.pagination a:hover { background: var(--panel); }

/* ---------- Forms ---------- */

/* QA S7: bare text inputs (newsletter bar, /for-providers, the search
   capture) rendered as 21px native boxes beside 36px buttons. Same tokens as
   .field inputs; the home dock and .field rules below still win on order. */
input[type="email"], input[type="text"], input[type="tel"], input[type="search"], input[type="url"], .input {
  font-family: inherit; font-size: 1rem; border: 1px solid var(--line); border-radius: var(--radius-input);
  padding: 10px 12px; background: var(--surface); color: var(--text); min-height: 44px; max-width: 100%;
}
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 5px; }
.field input, .field select, .field textarea {
  width: 100%; font-family: inherit; font-size: 1rem; border: 1px solid var(--line);
  border-radius: var(--radius-input); padding: 12px; background: var(--surface); color: var(--text); min-height: 44px;
}

/* QA P7: bare <select>s outside a .field (results sort, hero area picker)
   rendered as an unstyled native control next to fully-branded buttons, and
   clipped at the mobile viewport edge with no width constraint. */
select {
  font-family: inherit; font-size: 1rem; border: 1px solid var(--line);
  border-radius: var(--radius-input); padding: 8px 12px; background: var(--surface);
  color: var(--text); min-height: 40px; max-width: 100%;
}
.field textarea { min-height: 100px; }
.field .hint { font-size: 0.8rem; color: var(--muted); margin-top: 4px; }
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: var(--clay); background: var(--rose); }
.checkbox-field { display: flex; align-items: flex-start; gap: 8px; font-size: 0.9rem; }
.checkbox-field input { width: auto; min-height: auto; }
.honeypot-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.toast { padding: 12px 18px; border-radius: 8px; font-size: 0.9rem; display: inline-flex; align-items: center; gap: 10px; }
.toast-success { background: var(--ink); color: #fff; }
.toast-error { background: var(--rose); color: var(--text); }

/* ---------- Listing page (research/55 M7) ---------- */

/* Full-bleed band from inside a .wrap: the background paints past both
   gutters without restructuring the page. html has overflow-x: hidden, and
   clip-path keeps the shadow from bleeding vertically. */
.band-bleed { background: var(--fam-tint); box-shadow: 0 0 0 100vmax var(--fam-tint); clip-path: inset(0 -100vmax); }

.listing-header { padding-block: 20px 20px; margin-bottom: 28px; }
.listing-header .breadcrumb { margin-bottom: 14px; }
.listing-head { display: flex; gap: 20px; align-items: flex-start; }
.listing-head-text { min-width: 0; flex: 1; }
.listing-head h1 { margin: 0 0 8px; overflow-wrap: anywhere; }
.listing-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0 0 10px; color: var(--text); font-weight: 500; max-width: none; }
.listing-meta > * + span:not(.tag)::before { content: "·"; margin-right: 10px; color: var(--muted); }
.listing-pills { gap: 8px; margin-bottom: 10px; }
.listing-pills:empty { display: none; }
.tag-state { background: var(--surface); border-color: var(--line); color: var(--ink-2); font-weight: 600; }
.listing-actions { display: flex; gap: 4px; flex-wrap: wrap; margin-left: -10px; }
.icon-btn { min-height: 44px; min-width: 44px; padding: 8px 12px; gap: 6px; font-size: 0.95rem; }
.icon-btn:hover { background: color-mix(in srgb, var(--surface) 70%, transparent); }
@media (max-width: 479px) {
  .icon-btn .icon-btn-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
  .icon-btn { padding: 8px; }
}
.listing-claim-line { margin: 12px 0 0; font-size: 0.92rem; color: var(--text); }
.listing-claim-line a { font-weight: 600; }
.listing-header .tag-option[data-family] { background: var(--surface); }
@media (max-width: 640px) {
  /* Tile and name share the first row; meta, pills and actions run the
     full width under them instead of a narrow column. */
  .listing-head { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px 14px; align-items: center; }
  .listing-head-text { display: contents; }
  .listing-head h1 { font-size: 1.7rem; margin: 0; }
  .listing-meta, .listing-pills, .listing-actions { grid-column: 1 / -1; margin-bottom: 0; }
  .listing-actions { margin-left: -8px; }
  .listing-pills .tag { font-size: 0.82rem; padding: 4px 11px; }
  .listing-header { padding-block: 16px 18px; }
}

.listing-layout { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 40px; align-items: start; }
@media (max-width: 900px) { .listing-layout { grid-template-columns: minmax(0, 1fr); } }
.listing-section { margin-bottom: 36px; }
.listing-section h2 { font-size: 1.45rem; margin-bottom: 12px; }

/* At a glance: six fixed slots; unknowns are quieter and end in a question. */
.glance-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; }
@media (max-width: 1100px) { .glance-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.glance-tile { background: var(--surface); border: 1px solid var(--line); border-top: 3px solid var(--fam-accent); border-radius: 10px; padding: 12px 14px; }
.glance-tile dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.glance-tile dd { margin: 4px 0 0; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.glance-unknown { background: transparent; border-style: dashed; border-top-style: solid; border-top-color: var(--line); }
.glance-unknown dd { font-weight: 500; color: var(--muted); }
.glance-ask { display: inline-block; font-weight: 600; padding-block: 10px; margin-block: -10px; }
.glance-more { display: grid; grid-template-columns: minmax(0, max-content) minmax(0, 1fr); gap: 6px 16px; margin: 14px 0 0; font-size: 0.92rem; }
.glance-more > div { display: contents; }
.glance-more dt { color: var(--muted); }
.glance-more dd { margin: 0; }
@media (max-width: 560px) {
  .glance-grid { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .glance-tile { border-top-color: var(--line); display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: 10px; align-items: baseline; padding: 10px 12px; border-top-width: 1px; border-top-style: solid; border-left: 3px solid var(--fam-accent); }
  .glance-unknown { border-left-color: var(--line); }
  .glance-tile dd { margin: 0; }
}

.listing-about-source { margin-top: -4px; }
.tefa-fact { margin: 0 0 8px; }
.tefa-what { margin-top: 8px; }
.tefa-what summary { cursor: pointer; font-weight: 600; color: var(--ink-2); min-height: 44px; display: inline-flex; align-items: center; }
.tefa-what p { color: var(--muted); font-size: 0.92rem; }
.listing-location { margin-top: 10px; }
.directions-link { display: inline-block; padding-block: 12px; }
.listing-reviews .review:last-of-type { border-bottom: 0; }

/* Source strip: where the listing came from, at the foot of the main column. */
.listing-source { background: var(--band); border-radius: var(--radius-card); padding: 18px 20px; }
.listing-source h2 { font-size: 1.15rem; }
.listing-source .source-line { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 6px; }
.listing-source-verified .source-line { color: var(--ink-2); font-weight: 600; }
.listing-source .claim-banner { background: var(--surface); margin: 12px 0 4px; }
.listing-source .source-links { margin: 8px 0 0; }
.listing-source .source-links a { display: inline-block; padding-block: 10px; }

/* Nearby: four compact cards; a swipe row on phones. */
.nearby-row .card-pills, .nearby-row .review-quote, .nearby-row .card-actions .btn-outline { display: none; }
@media (max-width: 640px) {
  .nearby-row { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 12px; padding-bottom: 8px; margin-inline: -24px; padding-inline: 24px; scroll-padding-inline: 24px; }
  .nearby-row > .program-card { flex: 0 0 82%; scroll-snap-align: start; }
}

/* Contact block container and sticky bar: visual only. The markup, the
   reveal and relay behaviour and every route behind it belong to the
   contact build (research/55 M1, M2), so these rules only restyle the
   existing .inquiry-rail and .listing-action-bar. */
.inquiry-rail {
  position: sticky; top: 88px; background: var(--surface); border: 1px solid var(--line);
  border-top: 4px solid var(--fam-accent); border-radius: var(--radius-card); padding: 20px;
  box-shadow: var(--shadow-rest);
}
.inquiry-rail h3 { font-size: 1.2rem; }
@media (max-width: 900px) { .inquiry-rail { position: static; } }

/* Phones: the request form sits behind a collapsed card after "At a glance"
   (public/assets/js/request-card.js moves the one form into .request-slot).
   Wider screens keep the rail; the card never shows there. */
.request-collapse { display: none; }
@media (max-width: 900px) {
  .request-collapse {
    display: block; margin-bottom: 36px; scroll-margin-top: 76px; background: var(--surface); border: 1px solid var(--line);
    border-top: 4px solid var(--fam-accent); border-radius: var(--radius-card); box-shadow: var(--shadow-rest); overflow: hidden;
  }
  .request-collapse[hidden] { display: none; }
  .request-toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; min-height: 64px; padding: 14px 18px;
    background: transparent; border: 0; text-align: left; font: inherit; color: var(--text); cursor: pointer;
  }
  .request-toggle-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .request-toggle-text strong { font-size: 1.1rem; color: var(--ink-2); }
  .request-toggle-text span { font-size: 0.92rem; color: var(--muted); }
  .request-toggle .icon { flex: none; transition: transform .15s ease; }
  .request-collapse.is-open .request-toggle .icon { transform: rotate(180deg); }
  .request-collapse .inquiry-rail { border: 0; border-radius: 0; box-shadow: none; padding: 4px 18px 20px; }
  .request-collapse .inquiry-rail > h3 { display: none; }
}
@media (prefers-reduced-motion: reduce) { .request-toggle .icon { transition: none; } }

/* ---------- Newsletter bar / claim banner ---------- */

.newsletter-bar {
  background: var(--gold-soft); border-radius: 10px; padding: 20px 24px; display: flex; justify-content: space-between;
  align-items: center; gap: 16px; flex-wrap: wrap;
}
.newsletter-bar form { display: flex; gap: 8px; flex-wrap: wrap; }
.newsletter-bar input { min-width: 220px; }

.claim-banner {
  background: var(--panel); border-radius: 10px; padding: 18px 20px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.claim-banner .grow { flex: 1; min-width: 220px; }
.claim-banner .remove-link { font-size: 0.85rem; color: var(--muted); }

/* ---------- Stat bar / facts grid / breadcrumb ---------- */

.stat-bar { display: flex; gap: 28px; flex-wrap: wrap; padding: 18px 0; font-weight: 600; color: var(--ink); }
.stat-bar .stat-num { font-family: var(--font-heading); font-size: 1.4rem; }
.stat-bar .stat-label { display: block; font-weight: 400; font-size: 0.85rem; color: var(--muted); }

.breadcrumb { font-size: 0.85rem; color: var(--muted); margin-bottom: 16px; }
/* research/55 P3: 44px tap height without moving the line. */
.breadcrumb a { color: var(--muted); text-decoration: none; display: inline-block; padding-block: 12px; margin-block: -12px; }
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb-back { display: none; font-size: 0.92rem; margin-bottom: 12px; }
.breadcrumb-back a { color: var(--ink-2); font-weight: 600; text-decoration: none; display: inline-block; padding-block: 12px; margin-block: -12px; }
@media (max-width: 639px) {
  .breadcrumb.breadcrumb-has-back { display: none; }
  .breadcrumb-back { display: block; }
}

.facts-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.facts-grid .fact-tile { background: var(--panel); border-radius: 10px; padding: 14px 16px; }
.facts-grid .fact-tile .fact-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.facts-grid .fact-tile .fact-value { font-weight: 600; margin-top: 4px; }

.tefa-popover-wrap { position: relative; display: inline-block; }
.tefa-popover-btn { background: none; border: none; color: var(--ink-2); cursor: pointer; padding: 0; display: inline-flex; }
.tefa-popover {
  display: none; position: absolute; bottom: 130%; left: 0; z-index: 30; width: 300px;
  background: var(--ink); color: var(--paper); padding: 14px 16px; border-radius: 10px; font-size: 0.85rem;
  box-shadow: var(--shadow-card);
}
.tefa-popover-wrap:hover .tefa-popover, .tefa-popover-wrap:focus-within .tefa-popover { display: block; }

/* ---------- FAQ accordion ---------- */

.faq-list details { border-bottom: 1px solid var(--line); padding: 14px 0; }
.faq-list summary { cursor: pointer; font-weight: 600; list-style: none; display: flex; justify-content: space-between; gap: 12px; }
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list .faq-answer { margin-top: 10px; color: var(--text); }

/* ---------- Reviews ---------- */

.review { border-bottom: 1px solid var(--line); padding: 16px 0; }
.review .review-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.review .stars { color: var(--gold); font-weight: 700; }
.review .role { font-size: 0.85rem; color: var(--muted); }
.vendor-response { margin-top: 10px; margin-left: 18px; padding: 10px 14px; background: var(--panel); border-radius: 8px; font-size: 0.9rem; }

/* ---------- Hero / home ---------- */

.hero { padding-block: 56px 40px; }
.hero .lead { font-size: 1.125rem; color: var(--muted); max-width: 60ch; }
.hero-search { display: flex; gap: 10px; flex-wrap: wrap; margin: 24px 0; }
.hero-search input[type="search"] { flex: 1; min-width: 240px; }
.hero-search select { min-width: 200px; }
/* QA (WP5 polish): the search field above was relying on nothing but the
   global input:focus-visible outline — no border/radius/background/height
   of its own, so at mobile widths it rendered as a bare native <input>
   sitting above the (already-styled, see the `select` rule above) area
   picker, and the row's own min-widths (240px + 200px) don't fit a 390px
   viewport, so it wrapped in a way that read as broken rather than
   intentional. Gives the field the same tokens every other input/select
   already uses, then turns the row into one coherent stacked control group
   below the same 640px breakpoint the rest of the page uses. */
.hero-search input[type="search"] {
  border: 1px solid var(--line); border-radius: var(--radius-input);
  background: var(--surface); color: var(--text); padding: 12px; min-height: 44px;
}
@media (max-width: 640px) {
  .hero-search { flex-direction: column; align-items: stretch; }
  .hero-search input[type="search"], .hero-search select, .hero-search button { width: 100%; min-width: 0; }
}

.tile-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 20px; }
@media (max-width: 900px) { .tile-grid { grid-template-columns: repeat(2, 1fr); } }
.type-tile {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
  padding: 16px; text-decoration: none; color: var(--ink); display: flex; flex-direction: column; gap: 8px;
}
.type-tile:hover { box-shadow: var(--shadow-card); }
.type-tile .tile-count { color: var(--muted); font-size: 0.85rem; }

.section { padding-block: 48px; }
/* research/55 bands: major sections alternate --paper and --band; at most
   one --band-ink section per page (the providers call to action on home). */
.section-panel { background: var(--band); }
.section-ink { background: var(--band-ink); color: var(--paper); }
.section-ink h2, .section-ink h3 { color: var(--paper); }
.section-ink .meta-line, .section-ink p { color: rgba(251, 248, 243, 0.88); }
.section-ink a:not(.btn) { color: var(--gold); }
.section-title-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 20px; flex-wrap: wrap; gap: 8px; }

.cluster-grid { display: grid; gap: 24px; }
.cluster-row h3 { margin-bottom: 8px; }
.cluster-row .area-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }

.finder-block, .toc-rail { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 20px; }
.toc-rail h3 { font-size: 1.1rem; } /* QA P8: promoted from h4 to fix heading-order; kept the original visual size */

table.data-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.data-table th, table.data-table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); }
table.data-table th { color: var(--muted); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: .02em; }
.table-scroll { overflow-x: auto; }

.tefa-tier-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 800px) { .tefa-tier-row { grid-template-columns: 1fr; } }
.tefa-tier-card { border-radius: var(--radius-card); border: 1px solid var(--line); padding: 18px; border-top: 6px solid var(--line); background: var(--surface); }
.tefa-tier-card.tier-sky { border-top-color: var(--sky); }
.tefa-tier-card.tier-gold { border-top-color: var(--gold); }
.tefa-tier-card.tier-clay { border-top-color: var(--clay); }

/* ---------- Footer ---------- */

.site-footer { background: var(--ink); color: var(--paper); padding: 48px 0 24px; margin-top: 48px; }
.site-footer a { color: var(--paper); opacity: 0.85; text-decoration: none; }
.site-footer a:hover { opacity: 1; text-decoration: underline; }
/* QA P6: footer links were 21px tap targets. */
.site-footer li a { display: inline-block; padding-block: 8px; min-height: 40px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }
.footer-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }
@media (max-width: 800px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
.footer-grid h4, .footer-col-heading { color: var(--paper); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.7; margin-bottom: 12px; font-family: var(--font-body); }
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; font-size: 0.92rem; }
.footer-tagline { max-width: 60ch; color: var(--paper); opacity: 0.9; }
.footer-legal-line { font-size: 0.85rem; opacity: 0.75; margin-top: 8px; }
/* Inline prose links in the footer need real contrast + underline, not the
   nav-list treatment (WCAG 1.4.1 — Lighthouse link-in-text-block). */
.footer-legal-line a { color: var(--paper); opacity: 1; text-decoration: underline; }
.footer-bottom { font-size: 0.875rem; opacity: 0.7; border-top: 1px solid rgba(251, 248, 243, 0.15); padding-top: 16px; margin-top: 32px; }

/* ---------- Misc ---------- */

.coming-soon { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 20px 24px; color: var(--ink-2); max-width: 60ch; }
.empty-state { background: var(--panel); border-radius: var(--radius-card); padding: 28px; text-align: center; }
.badge-preview-box { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 20px; display: inline-flex; align-items: center; gap: 10px; }
.error-page { padding-block: 64px; text-align: center; }
.icon { flex: none; }
.sr-price-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-pill); overflow: hidden; }
.sr-price-toggle button { border: none; background: var(--surface); padding: 10px 18px; cursor: pointer; font-weight: 600; }
.sr-price-toggle button.active { background: var(--ink); color: #fff; }

/* ---------- Vendor dashboard / admin (WP2) ---------- */

.dashboard-layout { display: grid; grid-template-columns: 200px 1fr; gap: 32px; align-items: start; margin-top: 16px; }
@media (max-width: 768px) { .dashboard-layout { grid-template-columns: 1fr; } }
.dashboard-nav { display: flex; flex-direction: column; gap: 4px; background: var(--panel); border-radius: var(--radius-card); padding: 16px; position: sticky; top: 16px; }
.dashboard-nav a { padding: 8px 10px; border-radius: 8px; color: var(--ink); text-decoration: none; font-weight: 500; font-size: 0.92rem; }
.dashboard-nav a:hover { background: var(--surface); }
.dashboard-nav a.active { background: var(--ink); color: #fff; }
.dashboard-content { min-width: 0; }

.stat-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 12px; margin: 16px 0; }
.stat-tile { background: var(--panel); border-radius: var(--radius-card); padding: 14px; text-align: center; }
.stat-tile .stat-num { display: block; font-family: var(--font-heading); font-size: 1.6rem; color: var(--ink); }
.stat-tile .stat-label { font-size: 0.8rem; color: var(--muted); }

.completeness-bar { background: var(--panel); border-radius: 999px; height: 10px; overflow: hidden; margin: 8px 0 12px; }
.completeness-bar > div { background: var(--sage); height: 100%; }
.checklist { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.checklist li { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 0.9rem; }
.checklist li.done { color: var(--ink); }
.checklist li.done .icon { color: var(--sage); }

.leads-table { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 0.9rem; }
.leads-table th, .leads-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.leads-table th { color: var(--muted); font-weight: 600; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.02em; }
/* QA N2 (research/15): a data table wider than its viewport should scroll
   within its own box, not push the page's whole layout viewport wider than
   the device (the /sponsor status column was going fully off-screen at
   390px with no way to reach it). */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll .leads-table { min-width: 480px; }

.remove-link { font-size: 0.85rem; color: var(--muted); margin-left: auto; text-decoration: underline; }

/* ============================================================================
   HOMEPAGE — "The Map of Houston" blend (founder ruling 2026-09-06, "go map")
   Design ported from the Astro prototypes in _repos/coops-homepage-directions
   (Direction 2 atlas + dock + cluster cards, Direction 3 type wall, Direction
   5 faith pills + spec card, Direction 1 tag cloud). Rationale:
   research/24-homepage-directions-review.md. Tokens only — no new colors, no
   new fonts, nothing from the prototypes' own palettes.

   Two rules every block below obeys, because they are the two things the
   review measured Direction 2 failing at on a phone:
     - No page-level horizontal overflow at 390 / 768 / 1280. Every grid track
       is minmax(0,…) or minmax(min(Npx,100%),…); every nowrap row lives in
       its own overflow-x container.
     - The map is labelled and the readout never sits on top of it.
   ============================================================================ */

/* `.wrap` supplies the 24px page gutter, but `.section`/`.hero`/`.home-hero`
   all set `padding` as a shorthand, which zeroes the inline padding of any
   element carrying both classes — the old homepage rendered flush to both
   edges at 390 because of it. `.home-sec` restores the gutter on the
   homepage's own combined-class sections without touching `.section` for
   every other page (they nest a plain `.wrap` inside and are unaffected). */
.home-sec { padding-inline: 24px; }

/* ---------- 1. Search dock ---------- */
.home-dock-band { background: linear-gradient(180deg, var(--gold-soft), var(--paper) 78%); padding: 20px 0 4px; }
.home-dock {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px 18px 18px 6px;
  padding: 10px 12px;
  box-shadow: var(--shadow-card);
}
.home-dock-field { display: flex; flex-direction: column; gap: 2px; padding: 2px 6px; min-width: 0; }
.home-dock-label { font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.home-dock-field:focus-within .home-dock-label { color: var(--ink); }
.home-dock input, .home-dock select {
  border: 0; background: transparent; font: inherit; font-size: 1rem; color: var(--text);
  padding: 4px 0; width: 100%; min-width: 0; min-height: 32px;
}
.home-dock input:focus, .home-dock select:focus { outline: 2px solid var(--ink-2); outline-offset: 2px; border-radius: 4px; }
.home-dock-split { display: none; width: 1px; background: var(--line); margin: 6px 0; }
.home-dock-go { border-radius: 14px 14px 14px 4px; gap: 8px; }
.home-dock-note {
  display: flex; flex-wrap: wrap; gap: 4px 18px;
  margin: 10px 2px 0; font-size: 0.85rem; color: var(--muted); max-width: none;
}
@media (min-width: 720px) {
  .home-dock { grid-template-columns: minmax(0, 1fr) auto minmax(0, 15rem) auto; align-items: center; gap: 0; }
  .home-dock-split { display: block; }
  .home-dock-field { padding-inline: 14px; }
}

/* ---------- 2. Hero + atlas ---------- */
.home-hero { padding-block: 18px 8px; }
.home-eyebrow {
  display: flex; align-items: center; gap: 6px; margin: 0 0 10px;
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--clay-dark);
}
.home-hero h1 { margin-bottom: 6px; letter-spacing: -0.02em; }
.home-hero h1 em { font-style: italic; color: var(--clay-dark); }
.home-hero-sub { margin-bottom: 22px; }
.home-h2-sm { font-size: 1.35rem; margin-bottom: 10px; }
.section-tight { padding-block: 20px 28px; }

.atlas { position: relative; }
.atlas-frame {
  position: relative;
  background: linear-gradient(160deg, var(--surface), var(--gold-soft));
  border: 1px solid var(--line);
  border-radius: 20px 20px 20px 6px;
  padding: 8px 8px 2px;
  min-width: 0;
}
.atlas-corner { position: absolute; width: 24px; height: 24px; border: 2px solid var(--clay); opacity: 0.6; }
.atlas-corner-tl { top: 10px; left: 10px; border-right: 0; border-bottom: 0; border-radius: 6px 0 0 0; }
.atlas-corner-br { bottom: 10px; right: 10px; border-left: 0; border-top: 0; border-radius: 0 0 6px 0; }
.atlas-svg { display: block; width: 100%; height: auto; }
.atlas-water { fill: var(--sky); opacity: 0.85; }
.atlas-grat line { stroke: var(--muted); stroke-width: 0.6; opacity: 0.16; }
.atlas-roads * { fill: none; stroke: var(--clay); stroke-width: 1.1; opacity: 0.22; stroke-dasharray: 5 6; }
.atlas-roads circle { stroke-dasharray: none; opacity: 0.2; stroke-width: 1.3; }

.atlas-region { cursor: pointer; }
.atlas-shape { fill: #FCF4E6; stroke: var(--ink); stroke-width: 1.4; stroke-linejoin: round; transition: fill 200ms ease, stroke-width 200ms ease; }
.atlas-halo { fill: none; stroke: none; stroke-linejoin: round; }
.atlas-labels, .atlas-label { pointer-events: none; }
/* Leader line for the two central clusters whose real outline is too small to
   hold their own name (Inner Loop, Memorial), the way a paper map does it. */
.atlas-leader line { stroke: var(--ink); stroke-width: 1; opacity: 0.42; }
.atlas-leader circle { fill: var(--ink); opacity: 0.55; }
/* Labels are painted with a paper-coloured outline behind the glyphs, so a
   name that overhangs its own coastline is still readable over water or a
   neighbouring shape. */
.atlas-name, .atlas-count {
  paint-order: stroke fill; stroke: var(--paper); stroke-width: 3.5; stroke-linejoin: round;
}
.atlas-name { text-anchor: middle; font-family: var(--font-heading); font-size: 18px; font-weight: 600; fill: var(--ink); letter-spacing: -0.01em; }
.atlas-name-narrow { display: none; }
.atlas-count { text-anchor: middle; font-family: var(--font-body); font-size: 14px; font-weight: 700; fill: var(--clay-dark); stroke-width: 3; }
.atlas-region:hover .atlas-shape { fill: var(--gold-soft); stroke-width: 2.4; }
/* Visible keyboard focus: SVG ignores `outline` inconsistently across
   engines, so the ring is a second copy of the same polygon painted behind
   the shape and revealed only on focus-visible. The selected-state fill is
   declared *after* it, because focusing a polygon also selects it and the
   gold selected fill has to win over the hover/focus tint. */
.atlas-region:focus-visible { outline: none; }
.atlas-region:focus-visible .atlas-halo { stroke: var(--clay-dark); stroke-width: 8; stroke-dasharray: 7 5; }
.atlas-region:focus-visible .atlas-shape { fill: var(--gold-soft); stroke-width: 2.4; }
.atlas-region.is-active .atlas-shape { fill: var(--gold); stroke-width: 2.6; }
.atlas-region.is-active .atlas-count { fill: var(--ink); }
.atlas-label-g.is-active .atlas-count { fill: var(--ink); }
.atlas-compass-ring { fill: none; stroke: var(--ink); stroke-width: 1; opacity: 0.32; }
.atlas-needle-a { fill: var(--ink); opacity: 0.45; }
.atlas-needle-b { fill: var(--clay); }
.atlas-compass-n { text-anchor: middle; font-family: var(--font-heading); font-size: 13px; font-weight: 700; fill: var(--ink); }
.atlas-scale line { stroke: var(--muted); stroke-width: 1.2; opacity: 0.6; }
.atlas-scale text { font-family: var(--font-body); font-size: 12px; fill: var(--muted); letter-spacing: 0.1em; }
.atlas-hint {
  margin: 2px 0 8px; text-align: center; font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--muted); max-width: none;
}

.atlas-readout {
  display: block;
  margin-top: 14px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 16px 16px 16px 5px;
  padding: 16px 18px 18px;
  min-width: 0;
}
.atlas-readout[hidden] { display: none; }
.atlas-readout-tag { display: inline-block; font-size: 0.62rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--gold); }
.atlas-readout-name { margin: 6px 0 2px; color: var(--paper); font-size: 1.5rem; letter-spacing: -0.02em; }
.atlas-readout-count { margin: 0 0 8px; font-size: 0.88rem; color: rgba(251, 248, 243, 0.78); max-width: none; }
.atlas-readout-count b { color: var(--gold); font-size: 1.1rem; }
.atlas-readout-blurb { margin: 0 0 12px; font-size: 0.9rem; line-height: 1.5; color: rgba(251, 248, 243, 0.92); max-width: none; }
.atlas-readout-areas { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.atlas-area-chip {
  font-size: 0.8rem; padding: 4px 10px; border-radius: var(--radius-pill);
  text-decoration: none; color: var(--paper);
  background: rgba(251, 248, 243, 0.12); border: 1px solid rgba(251, 248, 243, 0.3);
}
.atlas-area-chip:hover, .atlas-area-chip:focus-visible { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.atlas-readout-go {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--gold); color: var(--ink); text-decoration: none;
  font-weight: 700; font-size: 0.92rem; padding: 10px 18px; border-radius: var(--radius-pill);
  min-height: 44px; box-sizing: border-box;
}
.atlas-readout-go:hover { background: #F0B948; }

@media (max-width: 767px) {
  /* Real polygons run 20-45px wide at phone scale, too tight for a full
     cluster name, so a short recognisable place name replaces it rather than
     the label being hidden outright (the prototype's mobile failure). */
  .atlas-name-wide { display: none; }
  .atlas-name-narrow { display: block; font-size: 21px; }
  .atlas-count { font-size: 15px; transform: translateY(4px); }
}
@media (min-width: 1024px) {
  /* Readout sits beside the map, never over it — a flex sibling, not an
     overlay. The frame is capped so the whole hero (headline, sub, atlas,
     readout) still clears an 844px-tall desktop fold. The real-geography
     viewBox is slightly taller than it is wide, so the cap is tighter than
     the 700px the old landscape box used. */
  .home-hero { padding-top: 12px; }
  .atlas { display: flex; align-items: flex-start; justify-content: center; gap: 24px; }
  .atlas-frame { flex: 1 1 auto; min-width: 0; max-width: 545px; }
  .atlas-readouts { flex: 0 1 21rem; width: 21rem; min-width: 0; }
  .atlas-readout { margin-top: 0; }
}

/* ---------- 3. Faith pills ---------- */
.faith-row { display: flex; flex-wrap: wrap; gap: 8px; }
.faith-pill {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 9px 15px; border-radius: var(--radius-pill);
  background: var(--surface); border: 1px solid var(--clay);
  color: var(--ink); text-decoration: none; font-weight: 600; font-size: 0.92rem;
  min-height: 44px; box-sizing: border-box; align-content: center;
}
.faith-pill:hover, .faith-pill:focus-visible { background: var(--gold-soft); border-color: var(--clay-dark); }
.faith-pill-count { font-size: 0.82rem; font-weight: 700; color: var(--clay-dark); }
.faith-pill-all { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.faith-pill-all .faith-pill-count { color: var(--gold); }
.faith-pill-all:hover, .faith-pill-all:focus-visible { background: var(--ink-2); border-color: var(--ink-2); }
.faith-note { margin: 12px 0 0; font-size: 0.86rem; color: var(--muted); }

/* ---------- 4. Cluster cards ---------- */
.cluster-card-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); }
.cluster-card-cell { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cluster-card {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 14px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 16px 16px 16px 5px; padding: 14px 16px;
  text-decoration: none; color: inherit;
}
.cluster-card:hover, .cluster-card:focus-visible { box-shadow: var(--shadow-card); border-color: var(--ink-2); }
.cluster-thumb {
  display: grid; place-items: center; width: 54px; height: 54px; flex: none;
  border-radius: 12px 12px 12px 4px; background: var(--gold-soft); border: 1px solid var(--line); color: var(--ink);
}
.cluster-thumb svg { width: 76%; height: 76%; }
/* Real outlines carry far more detail than the old stylised cells, so the
   thumbnail stroke is thinner: at 2px it filled in the coastline. */
.cluster-thumb path { fill: var(--gold); stroke: var(--ink); stroke-width: 1.25; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.cluster-card-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cluster-card-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.cluster-card-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.1rem; color: var(--ink); }
.cluster-card-count { font-weight: 700; font-size: 1.25rem; color: var(--clay-dark); line-height: 1; }
.cluster-card-blurb { font-size: 0.86rem; line-height: 1.45; color: var(--muted); }
.cluster-card-chips { display: flex; flex-wrap: wrap; gap: 6px; padding-left: 2px; }
.chip-sm { font-size: 0.8rem; padding: 5px 11px; }
@media (min-width: 640px) { .cluster-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .cluster-card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; } }

/* ---------- 5. Type wall ---------- */
.type-wall { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(min(270px, 100%), 1fr)); }
.type-tile {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px 14px 14px 4px; padding: 16px 16px 14px;
}
.type-tile:hover, .type-tile:focus-within { box-shadow: var(--shadow-card); border-color: var(--ink-2); }
.type-tile-main { display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: inherit; min-width: 0; }
.type-tile-icon { color: var(--fam-accent, var(--clay-dark)); display: block; }
/* research/55 M5: a 4px accent rule on top, the count stays clay-dark. */
.type-tile[data-family] { border-top: 4px solid var(--fam-accent); }
.type-tile-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.08rem; color: var(--ink); line-height: 1.25; }
.type-tile-blurb { font-size: 0.85rem; line-height: 1.45; color: var(--muted); }
.type-tile-count { font-size: 0.85rem; color: var(--muted); margin-top: 2px; }
.type-tile-count b { font-size: 1.15rem; color: var(--clay-dark); margin-right: 4px; }
.type-tile-count em { font-style: normal; font-weight: 600; color: var(--ink-2); }
.type-tile-empty { background: var(--panel); border-style: dashed; }
.type-tile-jump { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.type-tile-jump-label { width: 100%; font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }

/* ---------- 6. Spec card ---------- */
.spec-layout { display: grid; gap: 24px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 900px) { .spec-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; } }
.spec-card { margin: 0; background: var(--surface); border: 1px solid var(--line); border-top: 6px solid var(--gold); border-radius: 14px; padding: 6px 18px 10px; }
.spec-card > div { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.spec-card > div:last-child { border-bottom: none; }
.spec-card dt { font-size: 0.72rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--muted); }
.spec-card dd { margin: 0; font-weight: 600; color: var(--ink); }

/* ---------- 7. Popular searches, funding, leaders ---------- */
.tag-cloud { display: flex; flex-wrap: wrap; gap: 10px; }
.tag-cloud-item {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 15px; border-radius: var(--radius-pill);
  background: var(--surface); border: 1px dashed var(--line);
  color: var(--ink); text-decoration: none; font-size: 0.92rem;
  min-height: 44px; box-sizing: border-box;
}
.tag-cloud-item:hover, .tag-cloud-item:focus-visible { border-style: solid; border-color: var(--clay); background: var(--gold-soft); }
.tag-cloud-item .icon { color: var(--clay-dark); flex: none; }
.funding-layout { display: grid; gap: 28px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 900px) { .funding-layout { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 48px; } }
.plain-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.leaders-block { max-width: 44rem; }

@media (prefers-reduced-motion: reduce) {
  .atlas-shape, .cluster-card, .type-tile, .faith-pill, .tag-cloud-item, .atlas-readout-go { transition: none !important; }
}


/* ---------- QA fix round, 2026-09-07 (research/33-qa-fixes.md) ---------- */

/* P5: /search set its h1 size with an inline style, on the same element
   family that caused B4. Structural styling belongs here. */
.search-h1 { font-size: 1.6rem; }

/* B5: the honest coverage line under the hero sub-headline. */
.home-hero-note { margin: 0 0 20px; max-width: 62ch; }

/* B3: every popular search now carries the count it returns, so the module
   is self-evidencing rather than a promise. */
.tag-cloud-count {
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 0.8rem;
  color: var(--ink-2); background: var(--paper); border-radius: var(--radius-pill);
  padding: 1px 8px; margin-left: 2px;
}

/* S4/B2: an area with no listings stays visible on a cluster hub (the
   geography is honest) but stops being a clickable dead end. */
.card-muted { opacity: 0.72; }
.card-muted h3 { font-weight: 600; }

/* S1: the mobile menu's first row is the way into search. */
.mobile-nav-search { margin: 0 0 12px; }
.mobile-nav-search .btn { width: 100%; justify-content: center; }
.nav-link-search { display: inline-flex; align-items: center; gap: 6px; }

/* S9: 44px minimum on the two hero-dock fields and the atlas area chips.
   Lighthouse's tap-targets audit does not run on these pages, so this will
   never show up in a score; it is still the first thing a thumb meets. */
.home-dock input, .home-dock select { min-height: 44px; }
.atlas-area-chip { min-height: 44px; display: inline-flex; align-items: center; }

/* S5: /houston grouped its area chips by cluster, but the gap above a
   heading (54px) and the gap below it (36-73px) were indistinguishable, so
   on a scan the chips read as belonging to the previous cluster. Pure
   proximity: tight to its own chips, generous to the group above. */
.metro-cluster-group { margin-block-start: 48px; }
.metro-cluster-group:first-of-type { margin-block-start: 24px; }
.metro-cluster-group .section-title-row { margin-bottom: 12px; }

/* S8 is superseded by research/55 M5/M6: the 16 per-type thumb colours
   became 5 family colours (the tokens at the top of this file), carried by
   the monogram tile and the card's left rule. Photos, when they arrive,
   still render in a plain .thumb. */
.thumb { border-radius: 8px; background: var(--panel); overflow: hidden; }
.thumb img { width: 100%; height: 100%; object-fit: cover; }

/* The option pill, everywhere: family tint, deep text. */
.tag-option[data-family] { background: var(--fam-tint); color: var(--fam-deep); border-color: transparent; font-weight: 600; }

/* S4: a zero-count area chip is plain text, not a link into an empty page. */
.chip-muted { opacity: 0.55; cursor: default; }

/* release-v2: shared section copy (lib/section-copy.ts) and list styling for
   written intros (content/v2 option intros carry "What to ask" bullets). */
.section-explainer { max-width: 70ch; color: var(--muted); font-size: 0.95rem; margin: 4px 0 16px; }
.section-explainer p { margin: 0 0 10px; }
.lead ul, .lead ol { padding-left: 1.25em; margin: 8px 0 14px; }
.lead li { margin: 4px 0; }
.lead { overflow-wrap: anywhere; }

/* Flash confirmations (public/assets/js/flash.js, components/Layout.tsx). */
.flash-slot { margin-top: 16px; }
.flash-card { background: var(--sage); border: none; }
.footer-grid ul { gap: 0; }

/* ---------- Tap targets and focus (research/55 P3) ----------
   44px on phones for the controls the audit measured short: .btn-sm (Save,
   Share, Compare, Claim, Write a review), pagination, footer links and the
   small inline links that stand alone on a line. */
@media (max-width: 640px) {
  .btn-sm { min-height: 44px; }
  .pagination a, .pagination span { min-width: 44px; height: 44px; }
  .site-footer li a { min-height: 44px; }
  .remove-link, .claim-banner .remove-link { display: inline-block; padding-block: 12px; }
  .chip { min-height: 44px; }
}
.site-footer a:focus-visible, .section-ink a:focus-visible { outline-color: var(--gold); }

/* research/55 S2: with "My list" and "For programs" in the header, the
   "List your program" button steps aside on narrow laptops (1024-1199px).
   It stays in the footer, the mobile menu and on /for-providers. */
@media (min-width: 1024px) and (max-width: 1199px) { .header-actions > .btn { display: none; } }
