/* ============================================================
   BALA design system — component port of letsamerify.css
   Redesign step A6.

   PORT METHOD (deliberate, so fidelity is auditable): everything from the
   "Base" section down is a VERBATIM copy of the prototype letsamerify.css
   (lines 26-end) — the design source of truth per ADR-0006. The tokens block
   moved to bala-tokens.css; nothing else was edited in place.

   Every change we make relative to the prototype lives in the clearly marked
   "A6 AMENDMENTS" layer at the BOTTOM of this file, where it overrides by
   cascade order. That keeps this file diffable against the prototype and makes
   "what did we change and why" a single scroll rather than an archaeology
   exercise. Two categories live down there:
     1. Rev-2 mobile-first amendments (spec Rev-2 addendum, step A6).
     2. Rules the A5 chrome markup needs that the prototype never had — the A6
        hand-off lists in template-parts/bala/*.php name each one.

   Loads AFTER bala-tokens.css and BEFORE bala-woo-reskin.css. Only enqueued
   when the chrome flag is ON (includes/bala/enqueue.php), so this file is inert
   on a flag-OFF deploy.
   ============================================================ */

/* ---------- Base ---------- */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: "IBM Plex Sans", "Plex Sans Fallback", system-ui, -apple-system, Helvetica, Arial, sans-serif;
  background: var(--paper);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: inherit; }
h1, h2, h3, h4 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-weight: 500;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}
p { margin: 0; text-wrap: pretty; }
.mono { font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; }
.wrap { max-width: 1240px; margin: 0 auto; padding: 0 32px; }

/* ---------- Promo bar ---------- */
.promo {
  background: var(--ink);
  color: var(--cream);
  font-size: 13px;
  letter-spacing: 0.02em;
}
.promo .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 10px;
  padding-bottom: 10px;
}
.promo-left { display: flex; align-items: center; gap: 12px; }
.promo-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  border: 1px solid rgba(244,236,216,0.35);
  border-radius: 999px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-2);
}
.promo a { color: var(--gold-2); text-decoration: none; border-bottom: 1px solid rgba(224,177,75,0.4); }
.promo a:hover { border-bottom-color: var(--gold-2); }

/* ---------- Header ---------- */
header.site {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 50;
}
header.site .wrap {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 32px;
  padding-top: 16px;
  padding-bottom: 16px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}
.brand-mark {
  width: 36px; height: 36px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--cream);
  display: grid;
  place-items: center;
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-weight: 600;
  font-size: 22px;
  position: relative;
  overflow: hidden;
}
.brand-mark::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 6px;
  background: linear-gradient(90deg, var(--red) 50%, var(--cream) 50%);
}
.brand-name {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.brand-logo { height: 42px; width: auto; display: block; }
nav.primary { display: flex; align-items: center; justify-content: center; gap: 28px; }
nav.primary a {
  text-decoration: none;
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  padding: 8px 0;
  border-bottom: 1px solid transparent;
}
nav.primary a:hover, nav.primary a.active { border-bottom-color: var(--ink); }
.header-actions { display: flex; align-items: center; gap: 12px; }
/* ⚠ [finding 344] `form.search`, NOT `.search`. WordPress puts `class="search"` on the BODY element
   of every search-results page (`body.search.search-no-results`), so an unscoped `.search` rule
   matches the document body. Measured on staging 2026-07-30 at 360px: body computed to
   `display: inline-flex`, laying the staging banner, promo bar, header, content and footer out
   SIDE BY SIDE in a row — `overflowPx: 493` against a 345px content box, and `/?s=backpack`
   unusable on a phone. Disabling only the three BALA sheets took it 493 -> 0 and restoring them
   returned it to 493, so the attribution is controlled rather than inferred.

   ⚠ The layout was the visible half. `.search svg` and `.search input` below are DESCENDANT
   selectors, so on a results page they also matched EVERY svg and EVERY input on the page —
   `.search input` strips border, background and outline and forces `width: 100%`. Scoping the
   parent fixes both halves at once.

   ⚠ §6.4 measured this same URL as "styled and contained, overflowPx: 0" — at DESKTOP width, where
   a row layout still fits and shows nothing. A desktop-only check cannot fail this. Finding 258's
   family, and the reason B3-7 tests 360 specifically.

   `form.` is the right scope and not merely the narrowest: `.search` is used on exactly ONE element
   in the entire theme — `template-parts/bala/header.php:110`, a `<form>` — so this cannot miss a
   usage. Specificity rises (0,1,0) -> (0,1,1), which only has to beat what it already beat.
   `.header-actions .search` at the mobile breakpoint is already scoped and is left alone. */
form.search {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--cream-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 13px;
  color: var(--ink-soft);
  min-width: 320px;
}
form.search svg { flex-shrink: 0; }
form.search input {
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  color: var(--ink);
  width: 100%;
}
form.search input::placeholder { color: var(--ink-soft); }

/* ---------- Mobile nav toggle (hamburger) ---------- */
.nav-cb { display: none; }
.nav-toggle {
  display: none; /* shown only on mobile via media query below */
  /* FINDING 338 — was 42px, measured at 360 on staging 2026-07-30. Rev-2 specifies >=44px touch
     targets and WCAG 2.5.5 (AAA) sets the same figure; this was 2px short on the ONLY navigation
     control a phone user has. Width and height both raised so the square stays square. */
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-2);
  border-radius: 8px;
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  flex-shrink: 0;
}
.nav-toggle:hover { background: var(--cream-2); border-color: var(--ink); }
.nav-toggle svg { display: block; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: 8px;
  border: 1px solid transparent;
  text-decoration: none;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.06s ease, background-color 0.15s ease, border-color 0.15s ease;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
/* ⚠ FINDING 326, FIXED 2026-07-28 — SPECIFICITY, NOT COLOUR. Do not "tidy" these selectors back.
   Elementor's kit emits `.elementor-kit-155 a { color: var(--e-global-color-accent) }` — specificity
   (0,1,1). Every BALA anchor component below styled `color` with a SINGLE class, (0,1,0), so the kit
   won on specificity and load order never got a say (BALA sheets load at index 58-60, the kit at 31).
   Every <a> styled as a BALA component therefore rendered the kit's OLD accent red #A9002C instead of
   its own token — measured on staging 2026-07-28.
   Worst case: `.btn-primary` put #A9002C text on its own #B5263A background, ~1.21:1 against WCAG
   1.4.3's 4.5:1 — the "List your business" CTA in the header of every page, effectively unreadable.
   ⚠ WHY FIVE REVIEWS MISSED IT: every `:hover` variant is already (0,2,0) and WINS, so hovering any
   of these to check it was interactive showed the right colour. The defect existed only at rest.
   ⚠ AND UNIT (iii) DOES NOT FIX THIS. Repointing the kit's accent to the new red only changes WHICH
   red these components wrongly inherit; they still would not use their own tokens.
   Each rule is raised to (0,2,0) IN PLACE. It must stay in place: a higher-specificity block appended
   at the end of this file would outrank the `:hover` and `.is-current` rules that currently work. */
.btn.btn-primary { background: var(--red); color: var(--cream-2); }
.btn-primary:hover { background: var(--red-deep); }
.btn.btn-ink { background: var(--ink); color: var(--cream-2); }
.btn-ink:hover { background: #07203a; }
.btn.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
.btn-ghost:hover { background: var(--cream-2); border-color: var(--ink); }
.btn-lg { padding: 14px 22px; font-size: 15px; border-radius: 10px; }
.btn-sm { padding: 7px 12px; font-size: 12.5px; border-radius: 6px; }
.btn-block { width: 100%; }

/* ---------- Hero ---------- */
.hero { padding: 56px 0 24px; position: relative; }
.hero .grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 64px;
  align-items: center;
}
.eyebrow {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.eyebrow::before {
  content: "";
  width: 22px; height: 1px; background: var(--gold);
}
h1.title {
  font-size: clamp(44px, 5.4vw, 72px);
  line-height: 1.02;
  margin: 18px 0 20px;
  color: var(--ink);
}
h1.title em {
  font-style: italic;
  color: var(--red);
  font-weight: 500;
}
.lede {
  font-size: 19px;
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 540px;
  margin-bottom: 32px;
}
.lede strong { color: var(--ink); font-weight: 600; }
.cta-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  background: var(--cream);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 18px;
  max-width: 560px;
}
.cta-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 18px 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cta-card .who {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.cta-card .what {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--ink);
}
.cta-card .why {
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.45;
  margin-bottom: 4px;
}

/* Hero visual */
.hero-visual {
  position: relative;
  aspect-ratio: 5/6;
  background: var(--cream);
  border: 1px solid var(--line-2);
  border-radius: 18px;
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: var(--shadow);
}
.hv-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.hv-head .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red); display: inline-block; margin-right: 6px; vertical-align: middle; }
.hv-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1.1fr 0.9fr;
  gap: 12px;
  flex: 1;
}
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
  overflow: hidden;
}
.card.feat { grid-row: 1 / span 2; grid-column: 1; }
.card .photo {
  flex: 1;
  border-radius: 8px;
  background: var(--cream-2);
  border: 1px solid var(--line);
  min-height: 60px;
  overflow: hidden;
}
.card .photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card .name { font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif; font-size: 16px; line-height: 1.2; color: var(--ink); }
.card .meta { display: flex; align-items: center; justify-content: space-between; font-size: 11px; color: var(--ink-soft); }
.card .price { font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; color: var(--ink); font-weight: 500; }

/* ---------- Flag chips & glyphs ---------- */
.flag-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--cream-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 7px;
}
.flag-glyph {
  width: 14px; height: 10px;
  background: linear-gradient(to bottom,
    var(--red) 0 14.3%, var(--paper) 14.3% 28.6%,
    var(--red) 28.6% 42.9%, var(--paper) 42.9% 57.1%,
    var(--red) 57.1% 71.4%, var(--paper) 71.4% 85.7%,
    var(--red) 85.7% 100%);
  position: relative;
  border-radius: 1px;
  flex-shrink: 0;
}
.flag-glyph::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 6px; height: 5px;
  background: var(--ink);
}
.hv-foot {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: var(--ink-soft);
}
.hv-foot strong { color: var(--ink); font-weight: 600; }

/* ---------- Stats strip ---------- */
.stats {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-top: 72px;
  background: var(--cream-2);
}
.stats .wrap {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  padding-top: 28px;
  padding-bottom: 28px;
  gap: 24px;
}
.stat { display: flex; flex-direction: column; gap: 4px; }
.stat .num {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 36px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1;
}
.stat .num small { font-size: 18px; color: var(--ink-soft); font-weight: 400; }
.stat .lbl {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ---------- Featured businesses grid (.biz) ---------- */
.featured { padding-top: 96px; padding-bottom: 0; }
.biz-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}
.biz {
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow);
}
.biz .img { aspect-ratio: 4/3; overflow: hidden; background: var(--cream-2); position: relative; }
.biz .img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.biz .img.placeholder {
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--cream-2) 0%, var(--cream) 100%);
  color: var(--ink-soft);
}
.biz .img.placeholder .ph-mark {
  width: 64px; height: 64px;
  border: 1px dashed var(--line-2);
  border-radius: 12px;
  display: grid; place-items: center;
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 28px;
  color: var(--ink);
  background: var(--paper);
}
.biz .chip-abs {
  position: absolute; left: 12px; bottom: 12px;
  background: rgba(255,253,246,0.94);
  backdrop-filter: blur(2px);
}
.biz .body { padding: 20px 20px 22px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.biz .cat {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft);
}
.biz h3 { font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif; font-size: 23px; font-weight: 500; line-height: 1.12; color: var(--ink); }
.biz p { font-size: 14px; color: var(--ink-soft); line-height: 1.5; }
.biz .foot {
  margin-top: auto; padding-top: 14px; border-top: 1px dashed var(--line);
  display: flex; align-items: center; justify-content: space-between;
  font-size: 13px; color: var(--ink-2);
}
.biz .foot .loc { display: inline-flex; align-items: center; gap: 6px; }
.biz .foot a { color: var(--red); text-decoration: none; font-weight: 600; }
.biz .foot a:hover { text-decoration: underline; }

/* ---------- Image band (mission overlay) ---------- */
.band {
  position: relative;
  margin-top: 96px;
  min-height: 460px;
  display: grid;
  align-items: center;
  overflow: hidden;
}
.band .bg { position: absolute; inset: 0; }
.band .bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.band .bg::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(11,28,49,0.92) 0%, rgba(11,28,49,0.78) 42%, rgba(11,28,49,0.30) 100%);
}
.band .wrap { position: relative; z-index: 1; }
.band-card { max-width: 620px; color: var(--cream); }
.band-card .eyebrow { color: var(--gold-2); }
.band-card .eyebrow::before { background: var(--gold-2); }
.band-card blockquote {
  margin: 18px 0 0;
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.12;
  font-weight: 500;
  color: var(--cream);
}
.band-card blockquote em { font-style: italic; color: var(--gold-2); }
.band-card .by { margin-top: 20px; font-size: 14px; color: rgba(244,236,216,0.8); }

/* ---------- Section header ---------- */
section { padding: 96px 0; }
.sec-head {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 64px;
  align-items: end;
  margin-bottom: 48px;
}
.sec-head h2 {
  font-size: clamp(32px, 3.4vw, 48px);
  line-height: 1.05;
  color: var(--ink);
}
.sec-head h2 em { font-style: italic; color: var(--red); font-weight: 500; }
.sec-head .sub {
  font-size: 17px;
  color: var(--ink-soft);
  max-width: 520px;
  line-height: 1.55;
}

/* ---------- Pricing ---------- */
.pricing {
  background: var(--ink);
  color: var(--cream);
}
.pricing h2 { color: var(--cream); }
.pricing h2 em { color: var(--gold-2); }
.pricing .sub { color: rgba(244,236,216,0.7); }
.price-grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 32px;
  align-items: stretch;
}
.price-card {
  background: var(--cream-2);
  color: var(--ink);
  border-radius: 16px;
  padding: 36px;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.price-card .ribbon {
  position: absolute;
  top: 24px; right: -36px;
  background: var(--red);
  color: var(--cream-2);
  padding: 6px 44px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transform: rotate(35deg);
}
.price-row { display: flex; align-items: baseline; gap: 14px; }
.price-now {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 76px;
  line-height: 1;
  font-weight: 500;
}
.price-was {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 14px;
  color: var(--ink-soft);
  text-decoration: line-through;
}
.price-period {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.price-list { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; list-style: none; }
.price-list li {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  gap: 12px;
  align-items: baseline;
  padding-bottom: 12px;
  border-bottom: 1px dashed var(--line);
  font-size: 15px;
  color: var(--ink-2);
}
.price-list li:last-child { border-bottom: 0; padding-bottom: 0; }
.price-list .k { font-weight: 600; color: var(--ink); }
.price-list .v { font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; font-size: 13px; color: var(--ink-soft); }
.check {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--cream-2);
  display: grid; place-items: center;
  font-size: 10px;
  flex-shrink: 0;
}
.price-side { display: flex; flex-direction: column; gap: 24px; justify-content: space-between; }
.promo-card {
  background: rgba(244,236,216,0.06);
  border: 1px solid rgba(224,177,75,0.4);
  border-radius: 14px;
  padding: 24px;
}
.promo-card .label {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-2);
  margin-bottom: 8px;
}
.promo-card h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 24px;
  color: var(--cream);
  margin-bottom: 8px;
  line-height: 1.2;
}
.promo-card p { font-size: 14px; color: rgba(244,236,216,0.75); line-height: 1.5; }
.code-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 8px 14px;
  background: var(--cream-2);
  color: var(--ink);
  border-radius: 8px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
}

/* ---------- How it works (3 steps) ---------- */
.how .steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.step {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 28px;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.step .n {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--gold);
}
.step h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--ink);
}
.step p { color: var(--ink-soft); font-size: 15px; }

/* ---------- Flag key (4 cells explaining USA-manufacturing levels) ---------- */
.flagkey { background: var(--cream-2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.flagkey-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border-left: 1px solid var(--line);
}
.flagkey-cell {
  border-right: 1px solid var(--line);
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.flagkey-cell .glyph-stack { display: flex; gap: 4px; align-items: center; }
.flagkey-cell .big-flag {
  width: 44px; height: 32px;
  background: linear-gradient(to bottom,
    var(--red) 0 14.3%, var(--paper) 14.3% 28.6%,
    var(--red) 28.6% 42.9%, var(--paper) 42.9% 57.1%,
    var(--red) 57.1% 71.4%, var(--paper) 71.4% 85.7%,
    var(--red) 85.7% 100%);
  position: relative;
  border: 1px solid var(--line-2);
  border-radius: 2px;
}
.big-flag::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 18px; height: 17px;
  background: var(--ink);
}
.flagkey-cell.dim .big-flag { opacity: 0.45; }
.flagkey-cell.partial .big-flag { opacity: 0.7; }
.flagkey-cell .tag {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.flagkey-cell h4 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 19px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.2;
}

/* ---------- Mission / Purpose ---------- */
.purpose .grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 80px;
  align-items: start;
}
.purpose-side .eyebrow { color: var(--red); }
.purpose-side .eyebrow::before { background: var(--red); }
.purpose h2 { font-size: clamp(36px, 4vw, 56px); margin-top: 18px; line-height: 1.02; }
.purpose-body { font-size: 17px; line-height: 1.6; color: var(--ink-2); display: flex; flex-direction: column; gap: 20px; }
.purpose-body p strong { color: var(--ink); font-weight: 600; }

/* ---------- NAICS code explainer ---------- */
.naics {
  background: var(--cream);
  border-radius: 18px;
  padding: 48px;
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 48px;
  align-items: start;
  margin: 32px 0;
}
.naics h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 28px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--ink);
  margin-bottom: 12px;
}
.naics p { color: var(--ink-soft); font-size: 15px; margin-bottom: 16px; line-height: 1.55; }
.naics .actions { display: flex; gap: 10px; flex-wrap: wrap; }
.naics .code-demo {
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  padding: 22px;
}
.naics .code-demo .lbl {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 12px;
}
.naics .codebar {
  display: flex;
  gap: 8px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 28px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 18px;
}
.naics .codebar span {
  background: var(--cream-2);
  border: 1px solid var(--line);
  padding: 10px 14px;
  border-radius: 8px;
  min-width: 52px;
  text-align: center;
}
.naics .codebar span.h { background: var(--ink); color: var(--cream-2); border-color: var(--ink); }
.naics .legend { font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; font-size: 11px; color: var(--ink-soft); line-height: 1.6; }
.naics .legend strong { color: var(--ink); font-weight: 600; }

/* ---------- Final CTA (dual card on navy) ---------- */
.final {
  background: var(--ink);
  color: var(--cream);
  padding: 96px 0;
}
.final .grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.final-card {
  background: var(--cream-2);
  color: var(--ink);
  border-radius: 16px;
  padding: 36px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 240px;
}
.final-card.ink { background: transparent; color: var(--cream); border: 1px solid rgba(244,236,216,0.2); }
.final-card .eyebrow { color: var(--gold-2); }
.final-card.ink .eyebrow::before { background: var(--gold-2); }
.final-card h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 32px;
  font-weight: 500;
  line-height: 1.1;
}
.final-card.ink h3 { color: var(--cream); }
.final-card p { font-size: 15px; line-height: 1.5; }
.final-card.ink p { color: rgba(244,236,216,0.75); }
.final-card .btn-row { margin-top: auto; display: flex; gap: 10px; }

/* ---------- Footer ---------- */
footer.site {
  background: var(--paper);
  border-top: 1px solid var(--line);
  padding: 48px 0 32px;
  font-size: 13px;
  color: var(--ink-soft);
}
footer.site .row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 32px;
}
/* h2 per [finding 342] — see template-parts/bala/footer.php. The h1-h4 base rule now also
   matches these headings; all four properties it would impose (font-family, font-weight,
   letter-spacing, margin) are restated below at higher specificity. The one property it adds
   that is NOT restated is `text-wrap: balance`, which is inert on one- and two-word column
   labels — it only changes where a heading that wraps chooses to break. */
footer.site h2 {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 14px;
  font-weight: 500;
}
footer.site ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
footer.site a { text-decoration: none; color: var(--ink-2); }
footer.site a:hover { color: var(--ink); text-decoration: underline; }
footer.site .bottom {
  border-top: 1px solid var(--line);
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
}
footer.site .brand { gap: 10px; margin-bottom: 12px; }
footer.site .tag { color: var(--ink-soft); max-width: 320px; line-height: 1.5; }

/* ---------- Decorative stripe ---------- */
.stripe-bar {
  height: 6px;
  background: repeating-linear-gradient(90deg, var(--red) 0 80px, var(--cream-2) 80px 96px);
}

/* ---------- Map (Leaflet) ---------- */
.amap {
  height: 460px;
  width: 100%;
  border: 1px solid var(--line-2);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--shadow);
  position: relative;
  z-index: 1; /* establish stacking context so Leaflet panes stay below the sticky header */
  background: var(--cream-2);
}
.amap-mini { height: 280px; border-radius: 14px; }
.leaflet-container { font-family: "IBM Plex Sans", "Plex Sans Fallback", system-ui, -apple-system, Helvetica, Arial, sans-serif; background: var(--cream-2); }
.amap-pin {
  width: 20px; height: 20px;
  background: var(--red);
  border: 2.5px solid var(--paper);
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  box-shadow: 0 3px 8px rgba(14,42,71,0.45);
}
.amap-pin.ink { background: var(--ink); }
.amap-pop { min-width: 180px; }
.amap-pop .nm { font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif; font-size: 17px; font-weight: 600; color: var(--ink); line-height: 1.15; }
.amap-pop .ct { font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); margin: 5px 0 4px; }
.amap-pop .ad { font-size: 12px; color: var(--ink-2); line-height: 1.45; margin-bottom: 8px; }
.amap-pop a.view { color: var(--red); font-weight: 600; text-decoration: none; font-size: 13px; }
.amap-pop a.view:hover { text-decoration: underline; }
.leaflet-popup-content-wrapper { border-radius: 12px; box-shadow: 0 12px 32px -12px rgba(14,42,71,0.4); }
.leaflet-popup-content { margin: 14px 16px; }
.map-head {
  display: flex; justify-content: space-between; align-items: end;
  gap: 24px; flex-wrap: wrap; margin-bottom: 22px;
}

/* ---------- Company detail page ---------- */
.biz-meta-row { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-top: 18px; }
.biz-meta-row .loc { display: inline-flex; align-items: center; gap: 6px; font-size: 15px; color: var(--ink-2); }
.story { font-size: 17px; line-height: 1.7; color: var(--ink-2); display: flex; flex-direction: column; gap: 18px; }
.story h2 { font-size: clamp(26px, 2.8vw, 34px); line-height: 1.1; color: var(--ink); margin-bottom: 6px; }
.story p strong { color: var(--ink); font-weight: 600; }
/* Doubled class = (0,2,0); see finding 326 above. Only one class exists to work with here. */
.back-link.back-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace; font-size: 11px;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-soft); text-decoration: none; margin-bottom: 18px;
}
.back-link:hover { color: var(--red); }


/* ============================================================
   New components added for the rest of the site
   ============================================================ */

/* ---------- Compact hero (used by legal & utility pages) ---------- */
.hero-compact { padding: 64px 0 40px; }
.hero-compact h1 {
  font-size: clamp(38px, 4.2vw, 60px);
  line-height: 1.05;
  margin: 16px 0 0;
  color: var(--ink);
}
.hero-compact h1 em { font-style: italic; color: var(--red); font-weight: 500; }
.hero-compact .lede { margin-top: 18px; margin-bottom: 0; }

/* ---------- Legal documents ---------- */
.legal-doc {
  max-width: 760px;
  margin: 0 auto;
  padding: 16px 0 32px;
  color: var(--ink-2);
  font-size: 16px;
  line-height: 1.7;
}
.legal-doc .updated {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 32px;
}
.legal-doc h2 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 28px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
  margin: 40px 0 14px;
}
.legal-doc h2:first-of-type { margin-top: 0; }
.legal-doc h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 21px;
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
  margin: 28px 0 10px;
}
.legal-doc h4 {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 22px 0 8px;
  font-weight: 500;
}
.legal-doc p { margin: 0 0 16px; }
.legal-doc p strong { color: var(--ink); font-weight: 600; }
.legal-doc a {
  color: var(--red);
  text-decoration: none;
  border-bottom: 1px solid rgba(181,38,58,0.35);
}
.legal-doc a:hover { border-bottom-color: var(--red); }
.legal-doc ul, .legal-doc ol { margin: 0 0 16px; padding-left: 22px; }
.legal-doc li { margin-bottom: 6px; }
.legal-doc blockquote {
  margin: 18px 0;
  padding: 14px 18px;
  border-left: 3px solid var(--gold);
  background: var(--cream-2);
  font-style: italic;
  color: var(--ink-2);
}
.legal-doc hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 36px 0;
}

/* ---------- Two-column page grid (used by Contact, Register, Account) ---------- */
.split-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: start;
}
.split-2.weighted-left { grid-template-columns: 1.1fr 0.9fr; }
.split-2.weighted-right { grid-template-columns: 0.9fr 1.1fr; }

/* ---------- Forms ---------- */
.form-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 32px;
  box-shadow: var(--shadow);
}
.form-card.cream { background: var(--cream-2); }
.form-stack { display: flex; flex-direction: column; gap: 18px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  font-weight: 500;
}
.field .hint { font-size: 12px; color: var(--ink-soft); margin-top: 2px; }
.field .hint a { color: var(--red); text-decoration: none; }
.input, .textarea, .select {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 11px 14px;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  width: 100%;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(22,49,90,0.08);
}
.input::placeholder, .textarea::placeholder { color: var(--ink-soft); }
.textarea { min-height: 140px; resize: vertical; line-height: 1.5; }
.select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%2316315A' stroke-width='1.6' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
}
.checkbox-row {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 10px;
  align-items: start;
  font-size: 14px;
  color: var(--ink-2);
  line-height: 1.5;
}
.checkbox-row input[type="checkbox"] {
  appearance: none;
  width: 18px; height: 18px;
  border: 1.5px solid var(--line-2);
  border-radius: 4px;
  background: var(--paper);
  cursor: pointer;
  margin: 2px 0 0;
  position: relative;
}
.checkbox-row input[type="checkbox"]:checked {
  background: var(--ink);
  border-color: var(--ink);
}
.checkbox-row input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1px;
  width: 5px; height: 10px;
  border: solid var(--cream-2);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.checkbox-row a { color: var(--red); text-decoration: none; border-bottom: 1px solid rgba(181,38,58,0.35); }
.form-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.form-divider {
  height: 1px;
  background: var(--line);
  margin: 6px 0;
}

/* ---------- Inline contact / key-value rows ---------- */
.kv-card {
  background: var(--cream);
  border: 1px solid var(--line-2);
  border-radius: 16px;
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.kv-row {
  display: grid;
  grid-template-columns: 38px 1fr;
  gap: 14px;
  align-items: start;
}
.kv-row .icon {
  width: 38px; height: 38px;
  border-radius: 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  display: grid; place-items: center;
  color: var(--ink);
}
.kv-row .lbl {
  display: block;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 4px;
}
.kv-row .val {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.25;
  word-break: break-word;
}
.kv-row .val a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-2); }
.kv-row .val a:hover { border-bottom-color: var(--ink); }
.kv-row .sub { font-size: 13px; color: var(--ink-soft); margin-top: 4px; line-height: 1.5; }

/* ---------- Callout (small inline aside) ---------- */
.callout {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 20px;
  padding: 12px 16px;
  background: var(--cream-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 13px;
  color: var(--ink-2);
}
.callout .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--gold);
  flex-shrink: 0;
}
.callout strong { color: var(--ink); font-weight: 600; }

/* ---------- Filter strip (Directory & Shop) ---------- */
.filter-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 16px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 32px;
}
.filter-bar .lbl {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-right: 6px;
}
.filter-bar .spacer { flex: 1; }
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--paper);
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.filter-chip:hover { background: var(--cream-2); border-color: var(--ink); }
.filter-chip.active {
  background: var(--ink);
  color: var(--cream-2);
  border-color: var(--ink);
}
.filter-chip.active .flag-glyph::before { background: var(--cream-2); }
.search-hero {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 14px 18px;
  box-shadow: var(--shadow);
  max-width: 720px;
  margin-top: 24px;
}
.search-hero svg { color: var(--ink-soft); flex-shrink: 0; }
.search-hero input {
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  font-size: 16px;
  color: var(--ink);
  width: 100%;
}
.search-hero input::placeholder { color: var(--ink-soft); }

/* ---------- Shop layout (sidebar + grid) ---------- */
.shop-layout {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 40px;
  align-items: start;
}
.facet-group {
  border-bottom: 1px solid var(--line);
  padding: 18px 0;
}
.facet-group:first-child { padding-top: 0; }
.facet-group:last-child { border-bottom: 0; }
.facet-group h5 {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 12px;
  font-weight: 500;
}
.facet-group .facet-list { display: flex; flex-direction: column; gap: 8px; }
.facet-group .facet-row {
  display: grid;
  grid-template-columns: 16px 1fr auto;
  gap: 10px;
  align-items: center;
  font-size: 13.5px;
  color: var(--ink-2);
}
.facet-group .facet-row input[type="checkbox"] {
  appearance: none;
  width: 16px; height: 16px;
  border: 1.5px solid var(--line-2);
  border-radius: 3px;
  background: var(--paper);
  cursor: pointer;
  position: relative;
}
.facet-group .facet-row input[type="checkbox"]:checked {
  background: var(--ink);
  border-color: var(--ink);
}
.facet-group .facet-row input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 4px; top: 0;
  width: 5px; height: 10px;
  border: solid var(--cream-2);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.facet-group .facet-row .count {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--ink-soft);
}
.range-row { display: flex; align-items: center; gap: 8px; }
.range-row .input { padding: 8px 10px; font-size: 13px; }
.range-row span { font-size: 12px; color: var(--ink-soft); }

/* ---------- Product cards (.product-card) ---------- */
.product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}
.product-card {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.product-card .img {
  aspect-ratio: 1/1;
  background: var(--cream-2);
  position: relative;
  overflow: hidden;
}
.product-card .img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.product-card .img.placeholder {
  display: grid;
  place-items: center;
  background:
    linear-gradient(135deg, var(--cream-2) 0%, var(--cream) 100%);
}
.product-card .img.placeholder .ph-shape {
  width: 56%; height: 56%;
  background: var(--paper);
  border: 1px dashed var(--line-2);
  border-radius: 12px;
  display: grid; place-items: center;
  color: var(--ink);
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 24px;
}
.product-card .chip-abs {
  position: absolute; left: 12px; top: 12px;
  background: rgba(255,253,246,0.94);
  backdrop-filter: blur(2px);
}
.product-card .body {
  padding: 16px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.product-card .vendor {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.product-card h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
  margin: 2px 0 0;
}
.product-card .foot {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.product-card .price {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 500;
  color: var(--ink);
}

/* ---------- Pagination ---------- */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  margin-top: 48px;
}
.pagination a, .pagination span {
  min-width: 36px;
  padding: 8px 12px;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 13px;
  color: var(--ink-2);
  text-decoration: none;
  background: var(--paper);
}
.pagination a:hover { border-color: var(--ink); }
.pagination .active {
  background: var(--ink);
  color: var(--cream-2);
  border-color: var(--ink);
}
.pagination .ellipsis { border: 0; background: transparent; }

/* ---------- Dashboard (My Account) ---------- */
.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 40px;
  align-items: start;
  padding: 56px 0 96px;
}
.acct-nav {
  background: var(--cream);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: sticky;
  top: 100px;
}
.acct-nav .who {
  padding: 4px 8px 14px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 8px;
}
.acct-nav .who .lbl {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.acct-nav .who .name {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
}
.acct-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 8px;
  text-decoration: none;
  font-size: 13.5px;
  color: var(--ink-2);
  font-weight: 500;
}
.acct-nav a:hover { background: var(--cream-2); color: var(--ink); }
.acct-nav a.active {
  background: var(--ink);
  color: var(--cream-2);
}
.acct-nav a.danger { color: var(--red); }
.acct-nav .sep { height: 1px; background: var(--line); margin: 8px 4px; }

.acct-content { display: flex; flex-direction: column; gap: 36px; }
.acct-welcome h1 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: clamp(32px, 3.4vw, 44px);
  line-height: 1.05;
  color: var(--ink);
  margin-bottom: 8px;
}
.acct-welcome h1 em { font-style: italic; color: var(--red); font-weight: 500; }
.acct-welcome p { color: var(--ink-soft); font-size: 16px; max-width: 520px; }

.stat-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.stat-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  box-shadow: var(--shadow);
}
.stat-card .lbl {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.stat-card .val {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 32px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1;
}
.stat-card .delta { font-size: 12px; color: var(--ink-soft); }
.stat-card .delta.up { color: #1f7a4b; }

.acct-panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 24px 28px 28px;
  box-shadow: var(--shadow);
}
.acct-panel .panel-head {
  display: flex;
  justify-content: space-between;
  align-items: end;
  margin-bottom: 18px;
}
.acct-panel .panel-head h3 {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 22px;
  font-weight: 500;
  color: var(--ink);
}
.acct-panel .panel-head a { font-size: 13px; color: var(--red); text-decoration: none; font-weight: 600; }

.order-list { display: flex; flex-direction: column; gap: 0; }
.order-row {
  display: grid;
  grid-template-columns: 80px 1fr auto auto;
  gap: 18px;
  align-items: center;
  padding: 14px 0;
  border-top: 1px solid var(--line);
}
.order-row:first-child { border-top: 0; padding-top: 0; }
.order-row .date {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}
.order-row .title {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 16px;
  color: var(--ink);
}
.order-row .title small { display: block; font-family: "IBM Plex Sans", "Plex Sans Fallback", system-ui, -apple-system, Helvetica, Arial, sans-serif; font-size: 12px; color: var(--ink-soft); margin-top: 2px; }
.order-row .amount {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
}

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--cream-2);
  border: 1px solid var(--line);
  color: var(--ink-2);
}
.status-chip.ok { background: rgba(31,122,75,0.1); border-color: rgba(31,122,75,0.35); color: #1f7a4b; }
.status-chip.warn { background: rgba(200,147,46,0.1); border-color: rgba(200,147,46,0.4); color: var(--gold); }
.status-chip.pending { background: rgba(74,96,125,0.1); border-color: rgba(74,96,125,0.3); color: var(--ink-soft); }

/* ---------- Mobile ---------- */
@media (max-width: 980px) {
  .hero .grid, .sec-head, .price-grid, .purpose .grid, .naics, .final .grid, footer.site .row { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .stats .wrap, .how .steps, .flagkey-grid { grid-template-columns: repeat(2, 1fr); }
  .cta-split { grid-template-columns: 1fr; }
  .split-2, .split-2.weighted-left, .split-2.weighted-right { grid-template-columns: 1fr; gap: 32px; }
  .shop-layout { grid-template-columns: 1fr; gap: 32px; }
  .product-grid, .biz-grid { grid-template-columns: repeat(2, 1fr); }
  .stat-row { grid-template-columns: 1fr; }
  .dashboard { grid-template-columns: 1fr; padding: 32px 0 64px; }
  .acct-nav { position: static; }
  .form-row { grid-template-columns: 1fr; }
  .order-row { grid-template-columns: 1fr auto; gap: 8px; }
  .order-row .date { grid-column: 1; }
  .order-row .amount { grid-column: 2; grid-row: 1; }
  .order-row .title { grid-column: 1 / -1; }
  form.search { min-width: 0; } /* [finding 344] scoped — see the note at the `.search` block */
  /* header becomes: logo | (Sign in) | hamburger; nav drops into a panel */
  header.site .wrap { display: flex; align-items: center; gap: 12px; }
  .brand { margin-right: auto; }
  .header-actions { order: 2; }
  .nav-toggle { order: 3; display: inline-flex; }
  .header-actions .search { display: none; }
  .header-actions .btn-primary { display: none; } /* "List your business" lives in the menu */
  nav.primary {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
    padding: 6px 0;
  }
  .nav-cb:checked ~ nav.primary { display: flex; }
  nav.primary a { padding: 13px 24px; font-size: 15px; border-bottom: 0; }
  nav.primary a:hover, nav.primary a.active { background: var(--cream-2); border-bottom: 0; }
  section { padding: 64px 0; }
}

@media (max-width: 600px) {
  .product-grid, .biz-grid { grid-template-columns: 1fr; }
  .stats .wrap, .how .steps, .flagkey-grid { grid-template-columns: 1fr; }
  .flagkey-grid { border-left: 0; }
  .flagkey-cell { border-right: 0; border-bottom: 1px solid var(--line); }
  .naics { padding: 28px 20px; gap: 28px; }
  .naics .codebar { font-size: 20px; gap: 6px; flex-wrap: wrap; }
  .naics .codebar span { min-width: 40px; padding: 8px 10px; }
  .wrap { padding: 0 20px; }
  .legal-doc { padding: 0; }
}

/* ============================================================
   ▼▼▼ A6 AMENDMENTS — everything below diverges from the prototype ▼▼▼
   Two sources, both cited per rule:
     [REV2]  spec Rev-2 addendum, step A6 (mobile-first amendments)
     [A5]    a rule the A5 chrome markup needs that the prototype never had;
             see the "A6 CSS hand-off" docblocks in template-parts/bala/*.php
   Placed last so these override the verbatim port by cascade order.
   ============================================================ */

/* ---------- [A5] Hamburger: keyboard-operable ---------- */
/* The prototype hid the checkbox with `display:none` (and the markup carried the
   `hidden` attribute). Both remove it from the tab order, which left the mobile nav
   with NO keyboard path at all — a WCAG 2.1.1 (A) failure, and a regression against
   the live Elementor menu, which IS keyboard-operable. All three A5 technical
   reviewers flagged it. The checkbox is the real control (Space toggles it natively,
   no JS), so it must stay focusable: hide it visually with the same clip pattern WP
   uses for .screen-reader-text, and surface focus on the visible label. */
/* SCOPED to <=980px on purpose (Compliance A6 finding 2). Above that breakpoint the
   checkbox has no function at all — `.nav-toggle` is display:none and nav.primary is
   always visible — so the prototype's own `.nav-cb{display:none}` earlier in this file
   is left to stand. An unconditional clip would have left a focusable control in the
   desktop tab order whose only styled proxy isn't rendered there: a keyboard user would
   hit an invisible stop with no indicator anywhere on the page (WCAG 2.4.7). The first
   version of this fix had exactly that bug. */
@media (max-width: 980px) {
  .nav-cb {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .nav-cb:focus-visible ~ .nav-toggle,
  .nav-cb:focus ~ .nav-toggle {
    outline: 2px solid var(--ink);
    outline-offset: 2px;
  }
}
/* Note: the closed panel needs no extra rule — the prototype already hides
   nav.primary with `display:none` at <=980px, which removes its links and the
   in-panel search from the tab order. Verified by tracing the cascade, not assumed. */

/* ---------- [A5] Visible focus on every search control ---------- */
/* The prototype sets `outline:none` on `.search input` and `.search-hero input` with no
   replacement, and A6's new `.nav-search input` inherited that pattern — leaving an
   invisible focus stop on the very control a keyboard user lands on right after opening
   the mobile panel (Compliance A6 findings 4 and 5). Fixed for all three at once. */
form.search input:focus,
form.search input:focus-visible,
.nav-search input:focus,
.nav-search input:focus-visible,
.search-hero input:focus,
.search-hero input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
  border-radius: 4px;
}
.search-submit:focus,
.search-submit:focus-visible,
.nav-search button:focus,
.nav-search button:focus-visible,
.cart-link:focus,
.cart-link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---------- [A5] In-panel search (the Rev-2 divergence) ---------- */
/* CSS cannot reparent a node, so the header renders two search forms: the desktop
   one in .header-actions (hidden <=980px by the ported block) and this one inside
   nav.primary. Deliberately NOT reusing the .search class — .search carries
   min-width:320px, which would overflow a 360px viewport. */
.nav-search { display: none; }

/* ---------- [A5] Chrome bits with no prototype rule ---------- */
.promo-how { font-size: 12px; }
/* WP core's custom-logo markup uses .custom-logo, not the prototype's .brand-logo (which
   already has this exact rule earlier in the ported layer — not repeated here, so this
   amendments layer keeps its promise that everything in it is a real divergence). */
.brand .custom-logo { height: 42px; width: auto; display: block; }
.brand-text { font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif; font-size: 20px; font-weight: 600; }
footer.site .brand .custom-logo,
.brand-logo-footer { height: 40px; width: auto; display: block; }
.footer-address { margin-top: 8px; font-size: 12px; color: var(--ink-soft); }
.built-usa {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
/* The magnifier SVG is decorative/inert; give the real submit button a visible target
   rather than leaving mouse users with Enter-in-input as the only route. */
.search-submit {
  position: relative;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--cream-2);
  cursor: pointer;
}
/* Rev-2 sets >=44px as our own touch bar (above WCAG 2.1 AA, which has no target-size
   criterion at all). The button stays 28px visually — a 44px pill would burst the search
   field it sits inside — and gains the missing 16px as an invisible hit area instead.
   Standard technique; changes no layout. */
.search-submit::before {
  content: "";
  position: absolute;
  inset: -8px;
}
.search-submit:hover { background: var(--red); }
.search-submit::after {
  content: "\2192"; /* → */
  display: block;
  font-size: 14px;
  line-height: 28px;
}
/* Doubled class = (0,2,0); see finding 326 above. */
.cart-link.cart-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px; /* our own >=44px bar; the sibling .btn already computes to ~45.7px */
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  padding: 8px 4px;
}
.cart-link:hover { color: var(--red); }
.cart-count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--red);
  color: var(--paper);
  font-size: 10px;
  line-height: 1;
}

/* ---------- [REV2] Fluid map heights ---------- */
/* Prototype fixed 460px / 280px. The px value stays first as the fallback for engines
   without small-viewport units, then the fluid value wins where supported. */
.amap { height: 460px; height: clamp(300px, 55svh, 460px); }
.amap-mini { height: 280px; height: clamp(220px, 38svh, 280px); }

/* ---------- [REV2] Targeted overflow guard ---------- */
/* Deliberately NOT `overflow-x:hidden` on html/body: header.site (and .acct-nav) use
   position:sticky, which an overflow-clipping ancestor silently breaks. */
img, svg, video, canvas, iframe { max-width: 100%; }
img, video, canvas { height: auto; }
pre, code { max-width: 100%; overflow-x: auto; }
h1, h2, h3, h4, h5, p, li, a, dd, dt { overflow-wrap: break-word; }
.wrap > * { min-width: 0; }

@media (max-width: 980px) {
  /* [REV2] Chip rail: the prototype wrapped chips at ~30px tall. Below 980px they
     become a single horizontal scroll rail with thumb-sized targets, bleeding to the
     viewport edges so it reads as scrollable. */
  .filter-bar {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Bleed must match `.wrap`'s padding at THIS tier, which is still 32px — it only
       drops to 20px below 600px (overridden in the 600px block further down). The first
       version used -20px across the whole <=980px range, leaving a 12px gap either side
       at tablet widths like the 768px in the Rev-2 QA matrix. */
    margin-inline: -32px;
    padding-inline: 32px;
  }
  .filter-bar::-webkit-scrollbar { display: none; }
  .filter-bar .spacer { display: none; }
  .filter-chip {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 12px 16px;
    font-size: 12px;
    scroll-snap-align: start;
  }

  /* [REV2] Thumb-sized nav rows (prototype padding was close but not guaranteed). */
  nav.primary a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }

  /* [A5] Surface the in-panel search once the panel is open. */
  .nav-search {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 6px 24px 10px;
    padding: 8px 14px;
    background: var(--cream-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    min-width: 0;
  }
  .nav-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    outline: none;
    font: inherit;
    font-size: 16px; /* >=16px: stops iOS zooming the viewport on focus */
    color: var(--ink);
  }
  .nav-search button {
    flex-shrink: 0;
    min-height: 44px; /* was 32px — inside the open panel there is room for the full bar */
    padding: 6px 12px;
    border: 0;
    border-radius: 999px;
    background: var(--ink);
    color: var(--cream-2);
    font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
  }
}

@media (max-width: 600px) {
  /* [REV2] Promo bar clean at 360px — the prototype has no .promo rule in either
     mobile block, yet Rev-2 names "promo clean @360" as an acceptance criterion.
     The row is pill + full sentence + trailing link, which cannot fit on one line. */
  .promo .wrap {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    text-align: left;
  }
  .promo-how { align-self: flex-start; }

  /* [REV2] Shorter maps on the smallest screens. */
  .amap { height: 300px; height: clamp(240px, 45svh, 320px); }
  .amap-mini { height: 220px; height: clamp(190px, 32svh, 240px); }

  /* [REV2] `.wrap` drops to 0 20px below 600px, so the chip rail's bleed follows it. */
  .filter-bar {
    margin-inline: -20px;
    padding-inline: 20px;
  }
}

/* [A5] `.header-actions` at <=980px — the header.php hand-off asked for this to be
   checked now that a cart link shares the row. Traced rather than styled: at that width
   the ported rules already hide `.search` and `.btn-primary`, leaving only the cart link
   (min-height 44px) and the account ghost button — a two-item row that does not need its
   own rule. Recorded here so the hand-off item is closed by evidence, not silence.
   Confirm visually at 360px during the B3 sweep. */
/* ▲▲▲ end A6 amendments ▲▲▲ */

/* ============================================================
   ▼▼▼ A7a-1 AMENDMENTS — directory surface ▼▼▼
   Same convention as the A6 layer: appended last, every rule tagged, nothing above
   this point edited in place. Per the A6 finding-100 lesson, any rule here that is
   meant to countermand an earlier same-selector rule re-declares EVERY property that
   rule set, not only the ones being changed.
   ============================================================ */

/* ---------- [A7a] Directory card (rewritten anatomy) ---------- */
/* Deliberate override of TWO rules, both flagged because the amendments layer promises no
   silent supersessions:
     1. the prototype's `.biz-grid { grid-template-columns: repeat(3,1fr) }` + its two
        media-query variants — auto-fill reflows continuously instead of stepping;
     2. ⚠ the LIVE, frozen `css/custom-overrides.css:167` rule
        `#dokan-seller-listing-wrap.grid-view ul.dokan-seller-wrap` (1 ID + 2 classes + 1
        element = 1,2,1) which sets `repeat(3,1fr)` + `gap:20px` and `display:grid !important`.
   Point 2 is why this selector carries the ID and the element: the rewrite deliberately KEEPS
   the `dokan-seller-listing-wrap`/`grid-view`/`dokan-seller-wrap` classes, so a plain
   `.bala-directory-grid .biz-grid` (0,2,0) LOST to that live rule and the fluid grid the
   comment promised would never have applied. Found only by cross-referencing the two files —
   the same invisible-in-isolation class as A6 finding 101, caught here by the A7a-1 QA pass
   (finding 2). `display` keeps `!important` because the live rule uses it. */
#dokan-seller-listing-wrap.bala-directory-grid ul.biz-grid {
  display: grid !important;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
  list-style: none;
  margin: 20px 0;
  padding: 0;
}

/* ⚠ CRITICAL, and the single most important rule in this layer: without it the client-side
   filtering is invisible. The JS hides cards with the `hidden` ATTRIBUTE, which relies on the
   UA stylesheet's `[hidden]{display:none}` — and ANY author-stylesheet `display` declaration
   beats the UA stylesheet regardless of specificity, because cascade origin is compared before
   specificity. The ported `.biz { display: flex }` is exactly such a declaration, so filtering
   would set the attribute, update the live-region count and sync the map markers while the
   grid visibly did nothing. The prototype never hit this because it used an inline
   `style.display`, which always wins. Caught by the A7a-1 front-end review (finding 1). */
.bala-directory-grid .biz[hidden] { display: none; }

/* The `<li>` carries the prototype's `.biz`, which is itself a full card treatment (border,
   radius, shadow, background, overflow). The redesign's card lives on the `<article>` inside
   it, so leaving `.biz` intact produced a visible double frame with mismatched radii and a
   hover that slid the inner card inside a static outer frame. Neutralised here — every
   property `.biz` set is explicitly reset, per the A6 finding-100 rule. */
.bala-directory-grid .biz {
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  overflow: visible;
}

.biz-card {
  position: relative; /* positioning context for the avatar, which must escape the media box */
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  /* NOT overflow:hidden — that clipped the avatar's intended overlap flat. The media child
     does its own clipping instead (A7a-1 front-end finding 2). */
  overflow: visible;
  box-shadow: var(--shadow);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.biz-card:hover { border-color: var(--line-2); transform: translateY(-2px); }
/* `.biz-media` is the positioning context and does NOT clip — the avatar has to overhang it.
   `.biz-media-frame` is the clipping box for the banner. Splitting them is what lets the
   avatar's overlap survive (front-end finding 2). */
.biz-media {
  position: relative;
  display: block;
}
.biz-media-frame {
  display: block;
  aspect-ratio: 16 / 7;
  background: var(--cream);
  border-radius: 15px 15px 0 0; /* 1px inside the card's 16px so the border reads cleanly */
  overflow: hidden;
}
.biz-media-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.biz-media-blank {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, var(--cream) 0%, var(--cream-2) 100%);
}
.biz-avatar {
  position: absolute;
  left: 16px;
  bottom: -22px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 2px solid var(--paper);
  object-fit: cover;
  background: var(--paper);
}
.biz-body { display: flex; flex-direction: column; gap: 6px; padding: 30px 18px 18px; }

/* ⚠ Every text rule below is scoped under `.biz-card` on purpose. The prototype's OLD card
   anatomy left behind `.biz h3` and `.biz p` — bare-tag descendant selectors at specificity
   (0,1,1) — and `.biz` is still on the <li>. Plain single-class rules (0,1,0) therefore LOSE
   to them, so titles rendered 23px serif instead of 18px and every caption ran oversized.
   This is A6's finding-100 lesson in its harder form: not a same-selector re-declaration, but
   an unaccounted-for higher-specificity rule from the design being replaced. Caught by the
   A7a-1 front-end review (finding 3). Do not un-scope these. */
.biz-card .biz-flags { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.biz-card .biz-featured,
.biz-card .biz-open,
.biz-card .biz-closed {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  line-height: 1.4;
}
/* Filled pill rather than gold-on-paper text: that pairing computes to ~2.7:1, under the
   4.5:1 AA floor at this size (A7a-1 compliance finding 14). Navy-on-cream is 12:1. The
   same gold-on-light pattern exists elsewhere in the ported design and is logged as its own
   systemic item rather than patched piecemeal here. */
.biz-card .biz-featured { background: var(--ink); color: var(--cream-2); }
.biz-card .biz-open { background: rgba(31, 122, 75, 0.12); color: #1f7a4b; }
.biz-card .biz-closed { background: var(--cream); color: var(--ink-soft); }
.biz-card .biz-name {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
  margin: 0;
}
.biz-card .biz-name a { text-decoration: none; }
.biz-card .biz-name a:hover { color: var(--red); }
.biz-card .biz-origin { display: inline-flex; align-items: center; gap: 2px; }
/* Company-FORMATION claim (2026-07-26 leadership decision, Emails.md §8). Renders on the directory
   card and the store page behind bala_formation_claim_enabled().

   ⚠ Styled deliberately QUIETER than the surrounding card, not louder. It is a factual statement
   about corporate registration, not a badge or an endorsement — the graded flag rating that used to
   sit here was the visual claim, and that is now gated off. Giving this the weight the flags had
   would reinstate the impression the gate exists to remove. No icon, no colour accent, no border. */
.biz-card .biz-formed,
.bala-store-hero .biz-formed {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 2px;
}
.biz-card .biz-class {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}
.biz-card .biz-loc,
.biz-card .biz-phone { font-size: 13px; line-height: 1.4; color: var(--ink-soft); margin: 0; }
.biz-card .biz-loc a,
.biz-card .biz-phone a { text-decoration: none; border-bottom: 1px solid var(--line-2); }
.biz-card .biz-loc a:hover,
.biz-card .biz-phone a:hover { color: var(--red); }
.biz-card .biz-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin: auto 0 0;
  padding-top: 10px;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  line-height: 1.4;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

/* Client-side "no results" state — the PHP `.dokan-error` only covers a server-side zero,
   which client filtering never triggers, so a sighted user got a blank grid while only the
   live region announced it (front-end finding 13). */
.bala-dir-empty {
  display: none;
  padding: 28px 0;
  color: var(--ink-soft);
}
.bala-dir-empty.is-visible { display: block; }

/* ---------- [A7a] Directory controls ---------- */
.bala-dir-controls .wrap { display: flex; flex-direction: column; gap: 14px; }
.bala-dir-tools { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
/* Three things the base ported `.input/.select` rules get wrong for this row:
   `width:100%` made every control claim its own line even on desktop (the prototype used
   inline max-widths, which the port dropped); `font-size:15px` is under the 16px iOS
   focus-zoom threshold that Rev-2 mandates — A6 shipped that fix only against WooCommerce
   selectors and never reached the prototype's own `.input`/`.select` classes, which is what
   these controls use; and the 44px touch bar needs stating. Front-end findings 5 and 6. */
.bala-dir-tools .input,
.bala-dir-tools .select {
  min-height: 44px;
  font-size: 16px;
  width: auto;
}
.bala-dir-tools .input { flex: 1 1 220px; }
.bala-dir-tools .select { flex: 0 1 180px; }
.bala-dir-count {
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}
.bala-dir-map-section .map-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.bala-map-toggle { display: none; } /* desktop shows the map outright — no toggle needed */

/* ---------- [A7a] Mobile map/list toggle (Rev-2: list-first at <=980px) ---------- */
@media (max-width: 980px) {
  /* The map is collapsed by default so the LIST is what a phone user meets first.
     `display:none` (not height/opacity) so the collapsed map is fully out of the tab
     order and Leaflet does not measure a zero-size container. */
  .bala-dir-map-wrap { display: none; }
  .bala-dir-map-wrap.is-open { display: block; }
  .bala-map-toggle { display: inline-flex; min-height: 44px; }
  .bala-dir-map-section .map-head { margin-bottom: 0; }
  .bala-dir-map-wrap.is-open { margin-top: 14px; }
}

@media (max-width: 600px) {
  /* Specificity must match the base rule above, which had to out-rank the live
     custom-overrides.css grid rule — a plain `.bala-directory-grid .biz-grid` here would lose
     to our own base rule as well as to the live one. */
  #dokan-seller-listing-wrap.bala-directory-grid ul.biz-grid { grid-template-columns: 1fr; gap: 18px; }
}
/* ▲▲▲ end A7a-1 amendments ▲▲▲ */

/* ============================================================
   ▼▼▼ A7a-2 AMENDMENTS — homepage ▼▼▼
   Same convention as the layers above: appended last, every rule tagged, nothing
   above this point edited in place.
   ============================================================ */

/* ---------- [A7a-2] Variable stat/step counts ---------- */
/* The ported grids are hard-coded `repeat(4,1fr)` (.stats .wrap) and `repeat(3,1fr)`
   (.how .steps). Both sections now render a REAL number of cells rather than a fixed
   one — the stats strip shows only counts the install can actually report, and the
   how-it-works section loses its middle step until decision E2 lands. Without these
   rules a 2- or 3-cell strip leaves empty columns hanging off the right.

   ⚠ THE MEDIA-QUERY COPIES BELOW ARE LOAD-BEARING, NOT DUPLICATION. The responsive
   rules at :1582 and :1621 are `.stats .wrap` / `.how .steps` = (0,2,0). These
   modifier rules are (0,3,0), so they would out-rank the responsive rules at EVERY
   width and pin 3 columns onto a 360px phone — specificity is compared before source
   order, so appending later does not save you. Each tier therefore needs its own
   matching-specificity override. This is the same cross-rule cascade trap as A6
   finding 101 and A7a-1 findings 2 and 137; writing it out is cheaper than
   rediscovering it a fifth time. */
.stats.stats-2 .wrap { grid-template-columns: repeat(2, 1fr); }
.stats.stats-3 .wrap { grid-template-columns: repeat(3, 1fr); }
.how.steps-2 .steps { grid-template-columns: repeat(2, 1fr); }

@media (max-width: 980px) {
  .stats.stats-2 .wrap,
  .stats.stats-3 .wrap,
  .how.steps-2 .steps { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .stats.stats-2 .wrap,
  .stats.stats-3 .wrap,
  .how.steps-2 .steps { grid-template-columns: 1fr; }
}

/* ---------- [A7a-2] Mission band without a background photo ---------- */
/* ⚠ THIS IS A CONTRAST FIX, NOT A STYLE PREFERENCE. In the ported CSS `.band` has no
   background of its own: the entire dark field comes from `.band .bg::after`, a
   gradient overlay that exists only when there is an image to overlay. The band's
   prototype photo is an unlicensed stock image and is not shipped (see
   bala_home_band_background()), so with no `.bg` element the band's `--cream` text
   would render on the `--paper` page background — a straight WCAG 1.4.3 failure, not
   a missing flourish.

   `--cream` on `--ink` measures ~10:1, and the muted `.by` line ~7:1, both AAA for
   their sizes. Applied via a modifier so that if a licensed photo is ever supplied the
   original treatment returns untouched. */
.band.band-flat {
  background: linear-gradient(100deg, var(--ink) 0%, var(--ink-2) 100%);
}

/* ---------- [A7a-2] Editor content below the designed sections ---------- */
/* Whatever the front page holds in the editor still renders beneath the sections, so it
   needs the same rhythm as the rest of the page rather than butting against the
   stripe bar. */
.bala-home-content { padding: 72px 0 0; }
.bala-home-content .wrap > *:first-child { margin-top: 0; }

/* An earlier draft here set `.hero .search-hero { margin-top: 26px }`. DELETED, for two
   reasons the front-end pass measured rather than argued: (a) it was INERT — `.lede` carries
   `margin-bottom: 32px` (:246) which collapses with it, so the rendered gap was 32px either
   way; and (b) `.search-hero` already sets `margin-top: 24px` at :1228, so the rule silently
   superseded a ported value without naming it — exactly what this layer's convention and the
   A6 finding-100 lesson forbid. A rule that changes nothing and breaks a convention is pure
   cost. (A7a-2 front-end finding 6.) */

/* ---------- [A7a-2] Hero search submit button ---------- */
/* ⚠ THIS BUTTON HAD NO CSS RULE AT ALL, anywhere in the theme. Measured by the front-end pass
   at 1280px: `appearance:auto`, grey #F0F0F0, 2px outset border, square corners, Arial
   13.33px, and a box of **58×21px** — a raw operating-system button sitting inside the
   design-system pill, in the most prominent control on the busiest page of the site.

   The cause is a genuine porting gap rather than an oversight: the prototype's `.search-hero`
   is a `<label>` containing an SVG and an input and NO button at all, so there was nothing to
   copy. 21px also fails WCAG 2.2 AA 2.5.8 (24px floor) and Rev-2's own 44px bar.

   Reuses the header's `.search-submit` pattern (:1728, from A6 finding 87): 28px visually so
   it does not burst the field, plus an invisible 16px hit area via ::before to clear 44px.
   Deliberately NOT scoped to `.hero` — template-directory.php's hero search has the identical
   button and the identical defect, and one rule should fix both. */
.search-hero button[type="submit"] {
  position: relative;
  flex-shrink: 0;
  min-height: 28px;
  padding: 5px 14px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--cream-2);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  appearance: none;
}
.search-hero button[type="submit"]::before {
  content: "";
  position: absolute;
  inset: -8px;
}
.search-hero button[type="submit"]:hover { background: var(--red); }
.search-hero button[type="submit"]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ---------- [A7a-2] Gold text on LIGHT backgrounds — WCAG 1.4.3 ---------- */
/* ⚠ CONTRAST FIX, measured. `--gold` (#C8932E) computes 2.69:1 on `--paper`, 2.54:1 on
   `--cream-2` and 2.33:1 on `--cream`; `--gold-2` (#E0B14B) is worse at 1.84:1 on `--cream-2`.
   All are normal-size text, so the AA floor is 4.5:1 — these are failures, not preferences,
   and the site's own published Accessibility Statement asserts WCAG conformance, so shipping
   them would make a public accessibility representation inaccurate. A7a-1 finding 128 logged
   the gold-on-light family systemically at "≈2.7:1"; the true worst case is 1.8:1, and A7a-2
   is the step that puts all five instances on the highest-traffic page.

   `--gold-ink` (#856010) measures 5.61:1 on paper, 5.29:1 on cream-2 and 4.85:1 on cream —
   AA with margin on all three, and still recognisably the brand gold.

   ⚠ SCOPED TO LIGHT CONTEXTS ONLY, and that precision is the point: gold and gold-2 on the
   navy surfaces already PASS (`.final .eyebrow` 4.7:1, `.band-card .eyebrow` 6.5:1,
   `.promo-card .label` on navy). Recolouring them globally would have broken working design
   for no benefit. Each selector below names the light surface it sits on.

   ⚠ [finding 341] `.final-card` was the one selector in this list that does NOT name a single
   surface, and listing it bare undid the scoping this comment describes. `.final-card` has two
   variants: the base at `background: var(--cream-2)` (light — correct to recolour) and
   `.final-card.ink` at `background: transparent`, which shows the navy `.final` section behind
   it. `.final-card .eyebrow` matched both, so the light-surface gold landed on navy at
   **#856010 on #16315A = 2.26:1**, against 4.5:1 required at 12px normal weight — a WCAG 1.4.3
   failure, measured by Lighthouse axe on staging and re-derived by hand. It was self-evidently
   unintended: line ~838 was still painting the same eyebrow's ::before dash `--gold-2`, so the
   rule and its own leading dash rendered in visibly different colours.
   `:not(.ink)` restores the invariant the paragraph above claims, rather than bolting on an
   override — every selector in this list now genuinely names one light surface. The `.ink`
   variant falls back to the `--gold-2` rule (6.51:1 on navy, verified). */
:root {
  --gold-ink: #856010;
}
.hero .eyebrow,
.featured .eyebrow,
.how .eyebrow,
.pricing .sec-head .eyebrow,
.naics .eyebrow,
.price-card .eyebrow,
.final-card:not(.ink) .eyebrow,
.step .n { color: var(--gold-ink); }

/* ---------- [A7a-2] Grids that now hold a variable number of children ---------- */
/* The step fixed this class of defect for `.stats` and `.how .steps` and left it in three
   other places, all measured by the front-end pass (findings 1, 4, 5). Same reasoning
   throughout: the data layer is deliberately built to return fewer real items than the
   prototype's fixed grid assumed, and a hard `repeat(N, 1fr)` undoes that on the rendering
   side. */

/* `.price-side` lost the prototype's fabricated launch-promotion card, leaving one child in a
   `justify-content: space-between` column stretched to the price card's height — measured as
   **318px of empty navy** beside the pricing table at 1280px, on the page a prospective vendor
   reads before signing up. Every property the base rule (:610) sets is re-declared here per
   the finding-100 convention. */
.price-side.price-side-1 {
  display: flex;
  flex-direction: column;
  gap: 24px;
  justify-content: flex-start;
}

/* Featured-business grid: `auto-fill` reflows for 1, 2 or 3 real vendors instead of leaving
   376px (2 cards) or 774px (1 card) of empty track. Same solution the directory already uses. */
.featured .biz-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* Hero panel at exactly two tiles: `.hv-grid` is a fixed 2×2 with `.card.feat` spanning both
   rows of column 1, so a second tile leaves the bottom-right cell empty (measured ≈234×220).
   Two tiles becomes a single column instead, which is complete at any count. */
.hv-grid.hv-2 { grid-template-columns: 1fr; grid-template-rows: auto auto; }
.hv-grid.hv-2 .card.feat { grid-row: auto; grid-column: auto; }

/* ---------- [A7a-2] screen-reader-text insurance ---------- */
/* `.screen-reader-text` is emitted by these templates but defined only by the PARENT theme's
   stylesheet, which is enqueued behind the `hello_elementor_enqueue_theme_style` filter. If
   that filter is ever disabled, every visually-hidden label on the page becomes visible body
   text. Re-declaring it here costs six lines and removes the dependency (front-end finding 10). */
.bala-chrome .screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ⚠ [finding 352] The rule above hid the SKIP LINK even when focused, and that was ours.
   `header.php:51` emits `<a class="skip-link screen-reader-text" href="#content">`, so the
   insurance block above applies to it. The PARENT theme ships a working reveal —
   `.screen-reader-text:focus { clip: auto !important; width: auto; height: auto; … }` in
   `hello-elementor/assets/css/theme.css` — but ours is `.bala-chrome .screen-reader-text`,
   specificity (0,2,0), exactly EQUAL to the parent's `.screen-reader-text:focus`, also (0,2,0).
   At equal specificity source order decides, and our sheet loads later. The parent's
   `clip: auto !important` still wins on that one property, so the link un-clips on focus — but
   our non-important `width: 1px; height: 1px; overflow: hidden` do not lose, and a 1×1 box with
   hidden overflow is invisible no matter how unclipped it is.

   Net effect: a keyboard user tabs to the skip link, it takes focus, and nothing appears. That is
   WCAG 2.4.7 Focus Visible (AA) and it defeats 2.4.1 Bypass Blocks in practice. It also matches
   the "Skip links are not focusable" line in the live Lighthouse report.

   The insurance block was written to remove a dependency on the parent stylesheet. It removed
   half of one: it re-declared the hidden state and inherited the reveal it did not re-declare.
   ⚠ **A defensive copy of someone else's rule must copy the whole state machine, not the state
   that happens to be visible when you look.** */
.bala-chrome .screen-reader-text:focus {
  position: absolute;
  top: 8px;
  left: 8px;
  width: auto;
  height: auto;
  padding: 12px 20px;
  margin: 0;
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
  background: var(--cream, #faf7f2);
  color: var(--ink, #1a1a1a);
  border: 2px solid var(--ink, #1a1a1a);
  border-radius: 8px;
  font-size: 16px;
  line-height: normal;
  text-decoration: none;
  z-index: 100000;
}

@media (max-width: 980px) {
  /* stats-3 in two columns leaves the third cell alone on row 2 beside a 332px empty track
     (measured at 768px) — the very problem this amendment set exists to remove, reintroduced
     one breakpoint down. Three across still reads fine at 768px for a numeral plus a short
     label. (front-end finding 7) */
  .stats.stats-3 .wrap { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 600px) {
  .bala-home-content { padding-top: 48px; }

  /* ⚠ MUST BE RE-DECLARED HERE, and this is not belt-and-braces. The ≤600px block earlier in
     this layer already sets `.stats.stats-3 .wrap` to `1fr`, but the `repeat(3, 1fr)` rule I
     just added in the ≤980px block sits LATER in source order at identical specificity — and
     at 360px both media queries match, so the later declaration wins and the strip would have
     rendered three columns on a phone.

     This is the same cascade trap this layer's own opening comment warns about, walked into
     while fixing a different instance of it — which is precisely why the rule is that when two
     rules can both match, you settle the order deliberately instead of trusting the one you
     wrote most recently. */
  .stats.stats-3 .wrap { grid-template-columns: 1fr; }
}
/* ▲▲▲ end A7a-2 amendments ▲▲▲ */

/* ============================================================
   ▼▼▼ A7b AMENDMENTS — vendor store page ▼▼▼
   Appended last, every rule tagged, nothing above edited in place. The store page reuses
   the prototype's company-page components (.hero-compact, .split-2.weighted-left, .story,
   .kv-card, .amap-mini, .final) so most of its styling already exists and is NOT repeated
   here. What follows is only what the real store page has and the prototype's company page
   did not: a product grid, vendor CTA buttons, store tabs and social links. (An earlier version of
   this line also listed a share control; that control was removed during review because Dokan Pro
   already ships one.)
   Map heights are already fluid from A6 — that Rev-2 A7b item needed no new rule.
   ============================================================ */

.bala-store-hero { padding-bottom: 20px; }
.bala-store-body { padding-top: 16px; padding-bottom: 72px; }

/* ---------- [A7b] Store tabs ---------- */
/* Rendered from dokan_get_store_tabs(), so Pro's reviews/biography tabs appear too. A horizontal
   scroll rail at narrow widths rather than a wrap, because an unknown number of Pro-added tabs
   wrapping to three lines pushes the whole page down. Same rail pattern as the directory chips. */
.bala-store-tabs {
  display: flex;
  gap: 8px;
  margin-top: 20px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.bala-store-tabs::-webkit-scrollbar { display: none; }
/* Descendant form = (0,2,0); see finding 326 above. `:hover` and `.is-current` below are also
   (0,2,0) and follow this rule, so they still win — which is why this is raised HERE and not
   restated at the end of the file. */
.bala-store-tabs .bala-store-tab {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* Rev-2 touch bar */
  padding: 0 16px;
  /* --line-2 (#D6C8A4) measured 1.63:1 against --paper; WCAG 1.4.11 wants 3:1 for the visual
     boundary of a UI component, and a tab whose edge you cannot find is a tab you cannot use.
     #9C8447 measures 3.55 / 3.07 / 3.35 on paper / cream / cream-2 (A7b Compliance finding 10). */
  border: 1px solid var(--line-3);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.bala-store-tab:hover { border-color: var(--ink); color: var(--ink); }
.bala-store-tab.is-current { background: var(--ink); border-color: var(--ink); color: var(--cream-2); }

/* ---------- [A7b] Store banner ---------- */
.bala-store-banner {
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--line);
  margin-bottom: 18px;
  background: var(--cream-2);
}
.bala-store-banner img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- [A7b] Vendor CTA buttons (Rev-2 TAP item 5) ---------- */
/* ⚠ These four buttons are a REAL vendor-configurable feature of this install that was documented
   nowhere before A7b — the live theme renders them via a [store_cta_buttons] shortcode with no CSS
   of its own anywhere in the theme (custom-overrides.css has no `store-cta` rule; grep confirmed),
   so on the live site they are styled by Elementor or not at all. Rev-2 requires the row to be
   thumb-reachable: min 44px tall, wrapping rather than scrolling, because these are destinations
   rather than filters and a hidden one is a lost lead. */
.bala-store-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 24px;
}
.bala-store-cta-btn { min-height: 44px; }

/* ---------- [A7b] Sidebar extras ---------- */
.bala-store-aside .kv-card + .bala-store-social { margin-top: 16px; }
.bala-store-social .lbl {
  display: block;
  font-family: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 8px;
}
.bala-store-social ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.bala-store-social a {
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* Rev-2 touch bar — these are links in a tight sidebar */
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink-2);
  text-decoration: none;
}
.bala-store-social a:hover { border-color: var(--ink); color: var(--ink); }

/* Container for Dokan Pro's own modules rail (share / follow / support / live-chat), which emits
   bare `<li>` elements onto `dokan_after_store_tabs` and therefore needs a real `<ul>` to land in. */
.bala-store-modules { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* ⚠ NO `:empty` COLLAPSE RULES HERE — three of them were written and all three were proven inert.
   `:empty` does not match an element containing whitespace, and PHP emits a newline plus tabs inside
   both `.bala-store-modules` and `.bala-store-hooked`; one of them also targeted a `.wrap` descendant
   that does not exist (`.bala-store-hooked` sits INSIDE `.wrap`, not around it). Verified empirically
   in the front-end pass's harness. Dead CSS carrying a confident comment is worse than no CSS, so the
   rules are gone and the containers simply carry no margin of their own (A7b front-end finding 8). */

/* Seller star rating, restored to the hero during the A7b fold. It renders Dokan's own star markup,
   so this rule only positions the container — but without it the block sits flush against the h1
   with browser-default margins. Caught by a self-audit of "every class I emit has a rule", which is
   the check A7a-2's most visible defect (an unstyled system button) taught this project to run. */
.bala-store-rating { margin-top: 10px; display: flex; align-items: center; gap: 6px; font-size: 14px; }

/* Store logo, used when a vendor has no banner — which live sampling says is the COMMON case. */
.bala-store-logo { margin-bottom: 18px; }
.bala-store-logo img { width: 96px; height: 96px; object-fit: cover; border-radius: 14px; border: 1px solid var(--line); display: block; }

/* Attribution note under a vendor biography. */
.bala-store-bio-note { margin-top: 10px; font-size: 12px; color: var(--ink-soft); font-style: italic; }

/* ---------- [A7b] Product grid ---------- */
/* WooCommerce's own `content-product` cards, per ADR-0006 (native Woo surfaces, restyled). Woo's
   default `ul.products` is a float/percentage-width grid from a pre-flexbox era, so every property
   that layout depends on is re-declared here rather than partially overridden — the A6 finding-100
   rule. `float:none` and `width:auto` are the two that matter: without them the grid children keep
   their inline-ish float widths and the CSS grid silently does nothing. */
.bala-store-products { padding-bottom: 80px; }
.bala-store-products > .wrap > h2 { margin-bottom: 20px; }
.bala-store-products ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 24px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.bala-store-products ul.products::before,
.bala-store-products ul.products::after { content: none; display: none; } /* Woo clearfix, now inert */
.bala-store-products ul.products li.product {
  float: none;
  width: auto;
  margin: 0;
  clear: none;
}
.bala-store-empty { color: var(--ink-soft); font-size: 15px; }

@media (max-width: 980px) {
  /* `.split-2.weighted-left` already collapses to one column at this tier (:1584), so the sidebar
     lands under the story. Pull the map's card up tight to the story it belongs to. */
  .bala-store-body { padding-bottom: 56px; }
  .bala-store-aside { margin-top: 8px; }
}

@media (max-width: 600px) {
  .bala-store-products ul.products { grid-template-columns: 1fr; gap: 18px; }
  /* Long single-word store names (a URL-ish or hyphenated business name) would otherwise push the
     h1 past the viewport at 360px — Rev-2 names a long-name sweep as an A7b acceptance item. */
  .bala-store-hero h1 { overflow-wrap: anywhere; }
  .bala-store-cta { gap: 8px; }
  .bala-store-cta-btn { width: 100%; justify-content: center; }
}
/* ▲▲▲ end A7b amendments ▲▲▲ */

/* ============================================================
   ▼▼▼ A7b FOLLOW-UP — defects the front-end pass found by RENDERING ▼▼▼
   Every rule below fixes something measured in a browser, not read in a diff. Most are
   invisible to source review by construction: they are cases where a rule that exists
   somewhere else does not match here, or matches when nobody expected it to.
   ============================================================ */

/* ---------- [A7b] Horizontal scroll at 360px — 214px of it ---------- */
/* Measured: a long single-word store name gave scrollWidth 559 against clientWidth 345 at 360px.
   Rev-2 names "no h-scroll @360" as an acceptance item for THIS step, and the long-name sweep
   meant to deliver it fixed `.bala-store-hero h1` only — while the template prints the SAME name
   again, twelve lines below, in an unconditional "About {store}" h2 with no equivalent rule.
   Three independent contributors, isolated one at a time in the reviewer's harness:
     1. `.story h2` had no wrap rule                                        -> 142px
     2. `.split-2` grid items keep their automatic min-content minimum, so the story column is
        sized by its longest word. `.wrap > * { min-width: 0 }` already exists at :1796 as this
        project's established fix for exactly this, and was never extended to `.split-2`  -> 70px
     3. `.btn { white-space: nowrap }` (:195) is inherited by the vendor CTA buttons, so a long
        vendor-typed label overflows on its own even with a short store name -> 72px, independently
   All three are vendor-typed values nobody at LetsAmerify controls. (front-end finding 2) */
.split-2 > * { min-width: 0; }
.story h2 { overflow-wrap: anywhere; }
.bala-store-cta-btn { white-space: normal; }

/* ---------- [A7b] 168px of dead space above the products ---------- */
/* `section { padding: 96px 0 }` (:509) is global. `.bala-store-body` correctly restates BOTH sides;
   `.bala-store-products` set only `padding-bottom`, so it silently kept the 96px top — measured as
   a 168px empty band between the sidebar and the "What they sell" heading, about a third of a
   laptop viewport. The A6 finding-100 rule again: countermand a rule and you must re-declare every
   property it set (front-end finding 3). */
.bala-store-products { padding: 8px 0 80px; }

/* ---------- [A7b] Hero status flags ---------- */
/* `.biz-open` / `.biz-closed` / `.biz-featured` are styled ONLY as `.biz-card .biz-open` etc
   (:2015), so in the store hero they rendered as 16px body text — indistinguishable from the
   neutral "7 products" span beside them, and the A7a-1 contrast fix that made them filled pills
   never reached this surface (front-end finding 6). Re-declared here rather than by loosening the
   directory rule, which would change that surface too. */
.biz-meta-row .biz-open,
.biz-meta-row .biz-closed,
.biz-meta-row .biz-featured {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.biz-meta-row .biz-open { background: var(--ink); color: var(--cream-2); }
.biz-meta-row .biz-closed { background: var(--line); color: var(--ink); }
.biz-meta-row .biz-featured { background: var(--red); color: var(--cream-2); }

/* ---------- [A7b] Map credit ---------- */
/* `.amap-credit` was emitted with no rule anywhere, so a licence footnote rendered at 16px in full
   --ink — heavier and darker than the "Opens in Google Maps" micro-copy two rows above it, making
   the least important line in the card the most prominent. Second instance in this step of the
   "class with no rule" defect, which is what the self-audit was meant to catch and did not, because
   it ran before this element existed (front-end finding 5). */
.amap-credit { margin-top: 8px; font-size: 11px; line-height: 1.4; color: var(--ink-soft); }
.amap-credit a { color: var(--ink-soft); }

/* ---------- [A7b] Product grid: the missing .woocommerce ancestor ---------- */
/* THE STEP'S WORST DEFECT, and unreachable by reading the diff. The template emits WooCommerce's
   own `content-product` markup — but every `ul.products` rule in woocommerce-layout.css, every
   `.star-rating` and `.button` rule in woocommerce.css, every product rule in the frozen
   custom-overrides.css, AND our own bala-woo-reskin.css button rules are all `.woocommerce`-scoped.
   A Dokan store page gets no `woocommerce` body class (`wc_body_class()` adds it only for
   shop/cart/checkout/account — confirmed against the saved live page), and Dokan's own template
   supplies the class explicitly on its container. This one did not.

   Measured at 1280px with the class absent: `li.product` had no background, border or padding;
   `a.button` (Add to cart) computed to `display:inline`, transparent, no padding, 79x21px — a bare
   text link where the only revenue control on a vendor's shopfront should be, well under the 44px
   touch floor this same layer enforces on tabs and social links; `.star-rating` lost its glyph font
   and printed "Rated 4.50 out of 5" as literal text; `.onsale` went static and knocked its card out
   of row alignment.

   Fixed by adding the class in the template (ADR-0006's stated architecture: native Woo surfaces,
   restyled), which engages Woo's base CSS and the reskin at once. The rules below then settle the
   cascade fight that engaging it starts: custom-overrides.css:396-417 styles
   `.woocommerce .products .product .button` at (0,4,0) with a blue that is not our ink, while the
   reskin's `body.bala-chrome .woocommerce a.button` is (0,3,2) — so at rest the frozen rule won and
   the reskin's `!important` hover won, i.e. a button that changed palette between its own states.
   Scoping through `.bala-store-products` reaches (0,5,3) and settles it in one place.
   (front-end finding 1) */
.bala-store-products.woocommerce ul.products li.product a.button,
.bala-store-products.woocommerce ul.products li.product a.added_to_cart {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: var(--cream-2);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
}
.bala-store-products.woocommerce ul.products li.product a.button:hover,
.bala-store-products.woocommerce ul.products li.product a.added_to_cart:hover {
  background: var(--red);
  color: var(--cream-2);
}
.bala-store-products.woocommerce ul.products li.product .woocommerce-loop-product__title {
  font-family: "Newsreader", "Newsreader Fallback", Georgia, "Times New Roman", serif;
  font-size: 19px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--ink);
}
.bala-store-products.woocommerce ul.products li.product .price { color: var(--ink-2); font-size: 15px; }
.bala-store-products.woocommerce ul.products li.product .onsale {
  background: var(--red);
  color: var(--cream-2);
  border-radius: 999px;
}

/* ---------- [A7b] Product pagination ---------- */
/* `dokan_content_nav()` emits Dokan's own pager plus an always-empty `ul.pager` (its only filling
   branch is `is_single()`). Without a rule the visitor met grey Dokan defaults between a BALA grid
   and a BALA CTA band (front-end finding 11). */
.bala-store-products .dokan-pagination-container { margin-top: 32px; }
.bala-store-products ul.dokan-pagination { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.bala-store-products ul.dokan-pagination li a,
.bala-store-products ul.dokan-pagination li span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 10px;
  border: 1px solid var(--line-3);
  border-radius: 999px;
  color: var(--ink-2);
  text-decoration: none;
}
.bala-store-products ul.dokan-pagination li.active span {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream-2);
}
.bala-store-products ul.pager { display: none; }

@media (max-width: 600px) {
  .bala-store-products { padding-bottom: 56px; }
}
/* end A7b follow-up */

/* ============================================================
   ▼▼▼ A8 AMENDMENTS — defects the static harness found ▼▼▼
   Appended last, every rule tagged. Everything here was surfaced mechanically by
   tools/verify_redesign.py on its first run, on surfaces that had already passed
   multiple human review passes.
   ============================================================ */

/* ---------- [A8] Directory section rhythm ---------- */
/* ⚠ FOUND BY THE "EMITTED CLASS HAS NO CSS RULE" GATE, and it is the same defect as A7b finding
   235 sitting undetected on a surface four reviewers had already signed off.

   `.bala-dir-listing` had no rule at all — and neither did `.bala-dir-map-section` or
   `.bala-dir-controls`. All three are `<section>` elements, so all three inherited the global
   `section { padding: 96px 0 }` (:509). The arithmetic that follows was never intended by anyone:

     .hero-compact bottom  40px  +  map-section top  96px  =  136px
     map-section bottom    96px  +  controls top     96px  =  192px
     controls bottom       96px  +  listing top      96px  =  192px

   Two ~192px voids — roughly two thirds of a laptop viewport each — between blocks that are meant
   to read as one continuous control surface: search, then map, then filters, then results. The
   gate caught it because an unstyled class is exactly the signature of "nobody ever looked at this
   element's box", which is what had happened.

   Rhythm below matches `.hero-compact`'s own deliberate 64/40 asymmetry: tight between coupled
   controls, generous only at the end of the page. */
.bala-dir-map-section { padding: 24px 0 0; }
.bala-dir-controls { padding: 28px 0 0; }
.bala-dir-listing { padding: 24px 0 80px; }
.bala-dir-content { padding: 0 0 80px; }

@media (max-width: 600px) {
  .bala-dir-map-section { padding-top: 16px; }
  .bala-dir-controls { padding-top: 20px; }
  .bala-dir-listing { padding: 20px 0 56px; }
  .bala-dir-content { padding-bottom: 56px; }
}
/* end A8 amendments */

/* ---------- [A8] Store page with no sidebar content ---------- */
/* Surfaced by rendering the sparse fixture: with no contact card and no social links the `<aside>`
   is now correctly omitted, which left `.split-2.weighted-left` holding an empty second track open —
   the story squeezed into the narrower left column with a dead band beside it. `grid-template-columns`
   is the only property being countermanded here, deliberately: the parent's gap and alignment still
   apply and are still wanted. */
.split-2.weighted-left.bala-store-solo { grid-template-columns: minmax(0, 1fr); }

/* ---------- [A8] Homepage horizontal scroll at 360px ---------- */
/* ⚠ MEASURED, NOT INFERRED: 34px of document scroll at 360px on the homepage — the same defect
   class as A7b front-end finding 2, on a surface built before this harness existed and therefore
   never checked at a real viewport width. Rev-2's "no h-scroll @360" acceptance covers the homepage
   too.

   `.final-card .btn-row` (:831) is `display:flex` with the default `flex-wrap: nowrap`, holding two
   `.btn-lg` buttons whose `.btn { white-space: nowrap }` (:195) and 22px side padding cannot both
   fit in a 345px content box. Isolated in the browser by toggling one property at a time:
   `flex-wrap: wrap` alone takes 34px to 0. Letting the button TEXT wrap was also tried and is not
   needed, so it is not applied — the labels stay on one line each.

   ⚠ A second element was reported as overflowing and is NOT fixed, because testing showed it is a
   false positive: `.ribbon` is `position:absolute; right:-36px` inside `.price-card`, which is
   `overflow:hidden`. Its bounding box extends past the viewport but it is clipped and contributes
   zero document scroll — removing it entirely left the overflow at 34px. Worth recording: a
   bounding-box audit flags clipped elements, so "it sticks out" and "it causes scroll" are different
   questions and the second one is the one that matters. */
.final-card .btn-row { flex-wrap: wrap; }

/* ---------- [A8] Pricing fee-disclosure micro-copy ---------- */
/* `.price-note` was emitted with no rule anywhere in the theme — the THIRD instance of this defect
   class in the redesign (A7b finding 237's licence footnote, the seller rating, now this), and the
   one the widened class-audit gate was rewritten to catch (A8 full-stack finding 12: the gate had
   been checking 36 of 173 emitted classes because it filtered to `bala-`/`amap`/`biz-` prefixes).

   ⚠ Deliberately NOT shrunk to footnote size. This paragraph is the fee and rate DISCLOSURE on the
   vendor-facing pricing card — the sentence that says the displayed rates are standard, that
   individual accounts may differ, and that processing fees apply on top. Setting a disclosure in 11px
   grey is how disclosures get ignored, and it is the opposite of what a claim surface needs. It is
   distinguished from the card's body copy by being smaller and softer, and no more. */
.price-note {
  margin-top: 16px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* ============================================================
   ▼▼▼ T38 AMENDMENTS — constant-gated imagery slots (Phase 2 Stage 1) ▼▼▼
   Same convention as the layers above: appended last, every rule tagged, nothing
   above this point edited in place. Both slots SHIP DARK — no element matches any
   selector here until a wp-config constant names a licensed file in assets/img/
   (bala_home_purpose_image() / bala_dir_hero_image(), pattern precedent
   BALA_HOME_BAND_IMAGE), so this whole layer is inert on every install today,
   deliberately. Reveal = file + define; rollback = remove the define.
   ============================================================ */

/* ---------- [T38] Purpose editorial inset (unit B) ---------- */
/* Ratio container, no width/height attributes on the img — house style: the theme reserves
   image space in CSS (`.biz .img` 4/3, `.biz-media-frame` 16/7, `.bala-store-banner` 16/9),
   which is what the measured CLS 0.029 depends on. An unsized lazy image here would hand that
   back. 18px radius matches `.naics`, the inset's sibling panel in the same section. The
   max-height exists for the STACKED layout: at <=980px `.purpose .grid` collapses to one
   column (:1625) and a full-column 4:3 box would run ~690px tall on a tablet — the cap widens
   the crop instead (object-fit keeps it centered), and desktop never reaches it (left column
   ~500px wide => ~375px tall). No extra media query needed: the inset is a plain block, so the
   section's existing grid collapse is the whole responsive story. */
.purpose-inset {
  margin: 32px 0 0;
  aspect-ratio: 4 / 3;
  max-height: 420px;
  overflow: hidden;
  border-radius: 18px;
  background: var(--cream);
  box-shadow: var(--shadow);
}
.purpose-inset img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- [T38] Directory strip (unit C) ---------- */
/* Full-bleed like the homepage band — the design system's one precedent for an edge-to-edge
   photograph. The 3/1 ratio presents the plan's wide editorial crop from a 16:9 master;
   max-height clamps it on very wide viewports and object-fit keeps the center crop honest
   either way. No text overlay ever goes in here — that is what keeps this slot free of new
   contrast obligations (the band's band-flat interlock exists because IT carries text).

   ⚠ The explicit padding is not optional: `.bala-dir-strip` is a <section>, and an unstyled
   section on this page inherits the global `section { padding: 96px 0 }` — the exact defect
   class the [A8] directory-rhythm layer above exists to prevent. 24px top matches the
   map-section's own rhythm against the hero. */
.bala-dir-strip { padding: 24px 0 0; }
/* ⚠ WIDTH IS EXPLICIT, AND max-width IS LOAD-BEARING — do not "simplify" either away.
   Measured on live 2026-08-13 at a 2560px viewport: with `aspect-ratio: 3/1` + `max-height: 420px`
   and NO width, the frame computed to **1260px** (= 420 x 3) and sat LEFT-ALIGNED in a full-width
   section. When max-height clamps the height, the browser re-derives the WIDTH from the ratio
   instead of keeping the box stretched — so the strip was half-width on any monitor wider than
   ~1260px. It looked correct on the 1346px viewport the options pack was photographed at (1260 of
   1346 = 94%), which is exactly why it shipped: the defect is invisible at laptop widths.
   Capping at 1240 (= .wrap) rather than going full-bleed is deliberate, CTO decision 2026-08-13:
   it lines the strip up with the map and the listing grid below it, keeps the 3:1 crop Wayne
   actually approved, and never upscales the 1600px-wide source. Full-bleed would have stretched it
   to 2545px (soft) and flattened it to a 6:1 letterbox. */
.bala-dir-strip .strip-frame {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  aspect-ratio: 3 / 1;
  max-height: 420px;
  overflow: hidden;
  background: var(--cream);
}
.bala-dir-strip .strip-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 980px) {
  /* List-first on phones (Rev-2): at this width the map — a FUNCTIONAL surface — is collapsed
     behind a toggle so the list is what a phone user meets first. A purely decorative strip
     does not get to push the filters and listings further down than the map is allowed to, so
     it is hidden outright rather than toggled: there is nothing in it to interact with.
     Bonus, not the reason: a display:none subtree never intersects the viewport, so with
     loading="lazy" phones skip the image download entirely. */
  .bala-dir-strip { display: none; }
}
/* ▲▲▲ end T38 amendments ▲▲▲ */
