/* ==========================================================================
   Bookcliff Web — Stylesheet
   Hand-written CSS, no build step. Import order matters: tokens first.
   Mobile-first: base rules target a 375px phone, then sm(640) / md(768) /
   lg(1024) media queries widen the layout. See docs/rebrand/02-brand-system.md.
   ========================================================================== */

/* NOTE: tokens.css is deliberately NOT @import-ed here. A CSS @import
   forces the browser to fetch style.css first, parse it, and only then
   discover tokens.css — two serial round trips before first paint.
   Every page MUST link both, tokens.css first:

     <link rel="stylesheet" href="css/tokens.css">
     <link rel="stylesheet" href="css/style.css">

   Linking only style.css will render the page unstyled, because every
   rule below resolves against custom properties defined in tokens.css. */

/* --------------------------------------------------------------------
   0. Self-hosted type — ACTIVE.

   Both families ship as variable fonts, so one file per family covers
   every weight we use: Inter 400/500/600 and Playfair Display 600/700.
   That is 2 requests and ~59KB total.

   The files are SUBSET with HarfBuzz to printable ASCII, all of Latin-1,
   and common typographic punctuation (dashes, smart quotes, bullet,
   ellipsis, arrows), with the weight axis pinned to the range each family
   uses. That cut ~32% from Google's latin subset. The unicode-range below
   matches the subset exactly. If copy ever needs a character outside it,
   re-run the subsetter (docs/rebrand/10-improvements.md) rather than
   widening unicode-range, or the glyph will silently fall back.

   Because this block is active, the HTML must NOT also load Google
   Fonts. Do not reintroduce the preload + async stylesheet swap —
   pick one loading strategy, not both.

   Files are served from our own origin, so there is no third-party
   connection, no DNS/TLS cost to fonts.gstatic.com, and no privacy
   surface. Preload both in <head> (see 02-brand-system.md).
   -------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-latin-var.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+2013-2014, U+2018-201A, U+201C-201E, U+2022, U+2026, U+2032-2033, U+2039-203A, U+20AC, U+2122, U+2190, U+2192, U+2212;
}
@font-face {
  font-family: 'Playfair Display';
  src: url('../assets/fonts/playfair-latin-var.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+2013-2014, U+2018-201A, U+201C-201E, U+2022, U+2026, U+2032-2033, U+2039-203A, U+20AC, U+2122, U+2190, U+2192, U+2212;
}

/* --------------------------------------------------------------------
   1. Reset / base
   -------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

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

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  color: var(--color-text);
  background: var(--color-bg);
  overflow-x: hidden;
}

img, picture, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: var(--color-link); text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
a:hover { color: var(--color-link-hover); }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }

ul, ol { list-style: none; }

/* Respect reduced-motion universally: kill transitions/animations/smooth
   scroll for anyone who has asked the OS for less motion. DEFECT-07 fix. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------
   2. Focus — visible everywhere, mandatory. DEFECT-12 fix.
   3:1 non-text contrast in both light and dark contexts (see tokens.css
   §2 and 02-brand-system.md for the measured ratios).
   -------------------------------------------------------------------- */
:focus { outline: none; } /* replaced by :focus-visible below, never removed outright */
:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Skip link — DEFECT-16 companion fix (no skip link existed). */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  background: var(--bcw-white);
  color: var(--bcw-juniper);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font-weight: var(--weight-semibold);
  z-index: 2000;
  box-shadow: var(--shadow-lg);
  transition: top var(--duration-base) var(--ease-standard);
}
.skip-link:focus-visible { top: var(--space-4); }

/* --------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  color: var(--color-heading);
}

h1 { font-size: var(--text-4xl); letter-spacing: -0.01em; }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); font-weight: var(--weight-semibold); }
h5 { font-size: var(--text-lg); }
h6 { font-size: var(--text-md); }

@media (min-width: 1024px) {
  h1 { font-size: var(--text-5xl); }
  h2 { font-size: var(--text-4xl); }
  h3 { font-size: var(--text-3xl); }
}

.lead { font-size: var(--text-md); color: var(--color-text-muted); line-height: var(--leading-relaxed); }
.text-muted { color: var(--color-text-muted); }
.text-small { font-size: var(--text-sm); }
.text-eyebrow {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-link);
}
.ink-panel .text-eyebrow,
.dark-panel .text-eyebrow { color: var(--bcw-sand); } /* 7.7:1 on shale, 5.7:1 on juniper — passes at any size */

p { margin-bottom: var(--space-4); }
p:last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------
   4. Layout
   -------------------------------------------------------------------- */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

section { padding-block: var(--space-16); }

@media (min-width: 768px) {
  section { padding-block: var(--space-24); }
  :root { --container-padding: var(--space-8); }
}

.section-header {
  max-width: 640px;
  margin-inline: auto;
  margin-bottom: var(--space-10);
  text-align: center;
}
.section-header .text-eyebrow { margin-bottom: var(--space-2); }
.section-header h2 { margin-bottom: var(--space-3); }

/* --------------------------------------------------------------------
   5. Buttons — primary / secondary / ghost. Every state (hover, focus,
   active, disabled) is defined; none rely on color alone.
   -------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-decoration: none;
  border: 2px solid transparent;
  transition: background-color var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard),
              color var(--duration-base) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}

.btn--primary {
  background: var(--color-cta-bg);
  color: var(--color-cta-text);
  border-color: var(--color-cta-bg);
}
.btn--primary:hover { background: var(--color-cta-bg-hover); border-color: var(--color-cta-bg-hover); }
.btn--primary:active { background: var(--color-cta-bg-active); border-color: var(--color-cta-bg-active); transform: translateY(1px); }
.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  background: color-mix(in srgb, var(--bcw-juniper) 25%, var(--bcw-bone));
  border-color: transparent;
  color: color-mix(in srgb, var(--bcw-juniper) 55%, var(--bcw-bone));
  cursor: not-allowed;
}

.btn--secondary {
  background: transparent;
  color: var(--color-link);
  border-color: var(--color-link);
}
.btn--secondary:hover { background: var(--color-link); color: var(--bcw-white); }
.btn--secondary:active { background: var(--color-link-hover); border-color: var(--color-link-hover); color: var(--bcw-white); }
.btn--secondary:disabled,
.btn--secondary[aria-disabled="true"] {
  border-color: color-mix(in srgb, var(--bcw-juniper) 25%, var(--bcw-bone));
  color: color-mix(in srgb, var(--bcw-juniper) 45%, var(--bcw-bone));
  cursor: not-allowed;
}
.dark-panel .btn--secondary,
.ink-panel .btn--secondary { color: var(--bcw-white); border-color: var(--bcw-white); }
.dark-panel .btn--secondary:hover,
.ink-panel .btn--secondary:hover { background: var(--bcw-white); color: var(--bcw-juniper); }

.btn--ghost {
  background: transparent;
  color: var(--color-link);
  border-color: transparent;
  padding-inline: var(--space-2);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-decoration-color: transparent;
}
.btn--ghost:hover { text-decoration-color: currentColor; color: var(--color-link-hover); }
.btn--ghost:disabled,
.btn--ghost[aria-disabled="true"] { color: color-mix(in srgb, var(--bcw-juniper) 45%, var(--bcw-bone)); cursor: not-allowed; }

/* --------------------------------------------------------------------
   6. Cards — generic surface used by features/services.
   -------------------------------------------------------------------- */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}
.card:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.card__icon {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--bcw-rust) 10%, transparent);
  color: var(--bcw-rust);
  margin-bottom: var(--space-4);
}
.card__icon svg { width: var(--text-xl); height: var(--text-xl); }
.card h3 { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.card p { color: var(--color-text-muted); }

.card-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}

/* --------------------------------------------------------------------
   7. Pricing card + Stripe button
   -------------------------------------------------------------------- */
.pricing-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  max-width: var(--container-max);
  margin-inline: auto;
}
@media (min-width: 640px) {
  .pricing-grid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
}

/* Add-Ons only. Reuses the 480px breakpoint already established for .cta-row
   rather than inventing a new one. Add-on cards carry no feature list (icon +
   price + one-line description + button), so two columns stay readable at a
   narrower width than the feature-list cards ever could. */
@media (min-width: 480px) {
  .pricing-grid.pricing-grid--compact { grid-template-columns: repeat(2, 1fr); }
}

.pricing-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  position: relative;
  transition: border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}
.pricing-card:hover { border-color: var(--bcw-rust); box-shadow: var(--shadow-md); transform: translateY(-4px); }
.pricing-card--featured {
  border-color: var(--bcw-rust);
  background: color-mix(in srgb, var(--bcw-rust) 5%, var(--color-surface));
  box-shadow: var(--shadow-md);
}

/* Tighter padding for the simpler add-on card content (no feature list),
   proportional to how much less each card is carrying versus a package/hosting card. */
.pricing-card.pricing-card--compact { padding: var(--space-5); }

.pricing-card__badge {
  position: absolute;
  top: -14px;
  right: var(--space-5);
  background: var(--bcw-rust);
  color: var(--bcw-white);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.pricing-card h4 { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.pricing-card .price {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  color: var(--bcw-rust);
  margin-bottom: var(--space-1);
}
.pricing-card .price span { font-family: var(--font-body); font-size: var(--text-md); font-weight: var(--weight-regular); color: var(--color-text-muted); }

.pricing-card__features {
  margin: var(--space-5) 0 var(--space-6);
  flex-grow: 1;
}
.pricing-card__features li {
  padding: var(--space-2) 0;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  gap: var(--space-2);
}
.pricing-card__setup { font-size: var(--text-sm); color: var(--color-text-muted); margin-bottom: 0; }
/* "Everything in Care, plus:" — a lead-in, not a feature, so no check mark. */
.pricing-card__features li.is-lead { color: var(--color-text); font-weight: var(--weight-semibold); }
.pricing-card__features li.is-lead::before { content: none; }
.pricing-card__features li::before {
  content: '\2713';
  color: var(--bcw-rust);
  font-weight: var(--weight-bold);
  flex-shrink: 0;
}

/* .stripe-btn — binding surface for payments, see 01-inventory.md §2.3.
   Class name and data-name attribute contract are preserved verbatim;
   only the visual treatment changes. */
.stripe-btn {
  width: 100%;
  padding: var(--space-3) var(--space-6);
  background: var(--color-cta-bg);
  color: var(--color-cta-text);
  border: none;
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  transition: background-color var(--duration-base) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.stripe-btn:hover { background: var(--color-cta-bg-hover); }
.stripe-btn:active { background: var(--color-cta-bg-active); transform: translateY(1px); }
.stripe-btn:disabled { background: color-mix(in srgb, var(--bcw-juniper) 25%, var(--bcw-bone)); color: color-mix(in srgb, var(--bcw-juniper) 55%, var(--bcw-bone)); cursor: not-allowed; }

/* --------------------------------------------------------------------
   8. Forms
   -------------------------------------------------------------------- */
.form-group { margin-bottom: var(--space-6); }
.form-group label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  margin-bottom: var(--space-2);
  color: var(--color-heading);
}
.form-group .hint { font-size: var(--text-xs); color: var(--color-text-muted); margin-top: var(--space-1); }

.form-control {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--text-base);
  transition: border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}
.form-control::placeholder { color: var(--color-text-muted); }
.form-control:hover { border-color: color-mix(in srgb, var(--bcw-rust) 40%, var(--color-border-strong)); }
.form-control:focus-visible {
  border-color: var(--bcw-rust);
  box-shadow: var(--shadow-glow-cta);
}
.form-control:disabled { background: var(--color-surface-sunken); color: var(--color-text-muted); cursor: not-allowed; }
.form-control:invalid:not(:placeholder-shown) { border-color: color-mix(in srgb, var(--bcw-juniper) 55%, red 15%); }

textarea.form-control { resize: vertical; min-height: 8rem; }

/* Native select needs its own affordance since appearance varies by OS */
select.form-control {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%231F3A32' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  padding-right: var(--space-8);
}

.form-success {
  padding: var(--space-10) var(--space-6);
  text-align: center;
  border: 1px solid var(--color-success-border);
  border-radius: var(--radius-lg);
  background: var(--color-success-bg);
  animation: fadeIn var(--duration-slow) var(--ease-standard);
}
.form-success h3 { color: var(--bcw-rust); margin-bottom: var(--space-3); }
.form-success p { color: var(--color-text-muted); }

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------------
   9. Site header / nav / logo lockup
   -------------------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1000;
  background: color-mix(in srgb, var(--bcw-bone) 92%, transparent);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6); /* guard so the logo and nav links can never touch */
  padding-block: var(--space-3);
}

/* Horizontal lockup: mark + wordmark. Stays legible and does not overflow
   at 320px — the mark shrinks to its 24px display minimum before the
   wordmark ever wraps; see brand/index.html for the live check. */
.logo-lockup {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: var(--bcw-juniper);
  min-width: 0;
}
.logo-lockup__mark {
  height: 32px;
  width: auto;
  flex-shrink: 0;
}
.logo-lockup__word {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-md);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (min-width: 480px) {
  .logo-lockup__mark { height: 36px; }
  .logo-lockup__word { font-size: var(--text-lg); }
}

.nav-links {
  display: none;
  align-items: center;
  gap: var(--space-8);
}
.nav-links a {
  color: var(--color-text);
  text-decoration: none;
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
  position: relative;
  padding-block: var(--space-1);
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 0;
  height: 2px;
  background: var(--bcw-rust);
  transition: width var(--duration-base) var(--ease-standard);
}
.nav-links a:hover { color: var(--bcw-rust); }
.nav-links a:hover::after,
.nav-links a.active::after { width: 100%; }
.nav-links a.active { color: var(--bcw-rust); }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
}
.nav-toggle:hover { background: var(--color-surface-sunken); }
.nav-toggle svg { width: var(--text-xl); height: var(--text-xl); }

@media (min-width: 1024px) {
  .nav-links { display: flex; }
  .nav-toggle { display: none; }
}

/* --------------------------------------------------------------------
   10. Footer
   -------------------------------------------------------------------- */
.site-footer {
  padding-block: var(--space-16) var(--space-8);
}
.site-footer .container {
  display: grid;
  gap: var(--space-8);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .site-footer .container { grid-template-columns: repeat(3, 1fr); }
}
.footer-section h3 {
  font-size: var(--text-md);
  margin-bottom: var(--space-3);
  color: var(--color-heading-on-dark);
}
.footer-section p { color: var(--color-text-on-dark-muted); margin-bottom: var(--space-2); }
.footer-section a { color: var(--color-text-on-dark-muted); text-decoration: none; }
.footer-section a:hover { color: var(--bcw-sand); text-decoration: underline; }

.social-links { display: flex; gap: var(--space-3); margin-top: var(--space-3); }
.social-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--color-border-on-dark-strong);
  border-radius: var(--radius-md);
  color: var(--bcw-white);
  transition: background-color var(--duration-base) var(--ease-standard), border-color var(--duration-base) var(--ease-standard);
}
.social-links a:hover { background: var(--bcw-sand); border-color: var(--bcw-sand); color: var(--bcw-juniper); }

.footer-bottom {
  margin-top: var(--space-10);
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border-on-dark);
  text-align: center;
  color: var(--color-text-on-dark-muted);
  font-size: var(--text-sm);
}

/* --------------------------------------------------------------------
   11. Testimonial card
   -------------------------------------------------------------------- */
.testimonial-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  transition: border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard);
}
.testimonial-card:hover { border-color: var(--color-border-strong); box-shadow: var(--shadow-md); }
.testimonial-card__stars { color: var(--color-heading); font-size: var(--text-lg); letter-spacing: 0.1em; margin-bottom: var(--space-3); }

/* Cards need a background tint on dark panels — var(--color-surface) is a hardcoded
   white, and a card can't be simultaneously white and legible against juniper/shale. */
.dark-panel .card,
.ink-panel .card,
.dark-panel .testimonial-card,
.ink-panel .testimonial-card {
  background: color-mix(in srgb, var(--bcw-white) 6%, transparent);
}
.testimonial-card__quote { font-style: italic; color: var(--color-text-muted); line-height: var(--leading-relaxed); margin-bottom: var(--space-3); }
.testimonial-card__author { font-weight: var(--weight-semibold); font-size: var(--text-sm); color: var(--color-heading); }

/* --------------------------------------------------------------------
   12. Stat row
   -------------------------------------------------------------------- */
.stat-row {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(3, 1fr);
  margin-top: var(--space-10);
}
.stat { text-align: center; padding: var(--space-6); border: 1px solid var(--color-border); border-radius: var(--radius-lg); }
.stat__value { font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--weight-bold); color: var(--bcw-rust); margin-bottom: var(--space-1); }
.stat__label { color: var(--color-text-muted); font-size: var(--text-sm); }

@media (max-width: 639px) {
  .stat-row { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------
   13. FAQ accordion
   -------------------------------------------------------------------- */
.faq-list { max-width: 800px; margin-inline: auto; }
/* No overflow:hidden here — it clipped the 5px :focus-visible ring on every
   FAQ button (07a S1). Corner rounding moves to the inner elements instead. */
.faq-item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
}
.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  text-align: left;
  transition: background-color var(--duration-base) var(--ease-standard);
}
.faq-question:hover { background: var(--color-surface-sunken); }
.faq-question[aria-expanded="true"] { background: color-mix(in srgb, var(--bcw-rust) 6%, var(--color-surface)); }
.faq-icon { flex-shrink: 0; color: var(--bcw-rust); transition: transform var(--duration-base) var(--ease-standard); }
.faq-question[aria-expanded="true"] .faq-icon { transform: rotate(45deg); }

.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-standard);
}
.faq-answer > div { overflow: hidden; border-radius: 0 0 var(--radius-md) var(--radius-md); }
.faq-item:has(.faq-question[aria-expanded="true"]) .faq-answer { grid-template-rows: 1fr; }
/* Collapsed panels get the hidden attribute from initFAQ() so they leave the
   accessibility tree (07a S2); .faq-answer's display:grid must not override it. */
.faq-answer[hidden] { display: none; }
.faq-question { border-radius: var(--radius-md); }
.faq-item:has(.faq-question[aria-expanded="true"]) .faq-question {
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.faq-answer p { padding: var(--space-5); color: var(--color-text-muted); line-height: var(--leading-relaxed); }

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

/* Spacing and alignment utilities. These replace ten inline style=""
   attributes that Wave 3 left in index.html. */
.text-center { text-align: center; }
.mt-6  { margin-top: var(--space-6); }
.mt-10 { margin-top: var(--space-10); }
.mt-12 { margin-top: var(--space-12); }
.mb-6  { margin-bottom: var(--space-6); }
.mb-16 { margin-bottom: var(--space-16); }
.form-narrow { max-width: var(--form-max); margin-inline: auto; }
.measure { max-width: var(--measure); margin-inline: auto; }

/* Legal-page body headings (privacy.html): the reset zeroes all heading margin,
   and .section-header's h2 rule doesn't apply here since these aren't inside a
   .section-header. Restores the same heading rhythm every other h2 on the site has. */
.measure h2 {
  margin-top: var(--space-10);
  margin-bottom: var(--space-3);
}
.measure h2:first-child { margin-top: 0; }
.btn--block { width: 100%; }

/* Formspree honeypot (_gotcha). Moved off-screen rather than display:none,
   which some bots detect and skip. Real users never reach it: tabindex=-1
   and aria-hidden keep it out of keyboard and screen-reader paths (D-10). */
.hp-field { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* ==========================================================================
   Wave 3 additions — web-builder (docs/rebrand/03-content.md build).
   Everything below composes tokens and components already defined above;
   no new hex value or hue is introduced anywhere in this block.
   ========================================================================== */

/* --------------------------------------------------------------------
   15. Anchor scroll offset — every section sits under a fixed header
   (~56-64px). Without this, both native CSS smooth-scroll and JS
   scrollIntoView() land an anchor's heading directly behind the nav.
   -------------------------------------------------------------------- */
[id] { scroll-margin-top: 88px; }
@media (min-width: 768px) {
  [id] { scroll-margin-top: 96px; }
}

/* --------------------------------------------------------------------
   16. Two-up grid variants — several sections in the content deck render
   exactly two symmetric items (about bio cards, the two-tile stat row,
   the footer when the social column is hidden per D-05). The fixed
   3-column .card-grid / .stat-row / footer grid would leave one empty,
   lopsided track with only two children, so each gets a modifier
   specific enough to win over the base rule at every breakpoint.
   -------------------------------------------------------------------- */
@media (min-width: 640px) {
  .card-grid.card-grid--two { grid-template-columns: repeat(2, 1fr); }
  .stat-row.stat-row--two { grid-template-columns: repeat(2, 1fr); }
  .site-footer .container.footer-grid--two { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .card-grid.card-grid--two { grid-template-columns: repeat(2, 1fr); }
}

/* A single portfolio entry: keep it a readable width and centred, rather than
   letting it sit in one third of a three-column grid with two empty tracks. */
.card-grid.card-grid--single {
  grid-template-columns: 1fr;
  max-width: var(--measure);
  margin-inline: auto;
}

/* Screenshots inside cards (portfolio work). */
.card img {
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  margin-bottom: var(--space-4);
}

/* --------------------------------------------------------------------
   17. Hero
   -------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--space-8) + 56px); /* was space-24. Short phones need the CTAs above the fold; see 10-improvements.md */
  padding-bottom: calc(var(--space-16) + 24px);
  text-align: center;
}
@media (min-width: 768px) {
  .hero { padding-top: calc(var(--space-32) + 64px); padding-bottom: calc(var(--space-20) + 24px); }
}
/* The layered mountains from the mark, as a faint band along the bottom of
   the hero. A mask, not an image, so the colour stays a token. Decorative only. */
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: clamp(48px, 8vw, 96px);
  background: var(--color-accent);
  opacity: 0.28;
  pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath fill-rule='evenodd' d='M0 120V60L180 22l100 40L470 0l150 50 70-28 170 40 100-30 240 30V120zM0 70h1200v6H0zM0 88h1200v6H0zM0 106h1200v6H0z'/%3E%3C/svg%3E") left bottom / 100% 100% no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath fill-rule='evenodd' d='M0 120V60L180 22l100 40L470 0l150 50 70-28 170 40 100-30 240 30V120zM0 70h1200v6H0zM0 88h1200v6H0zM0 106h1200v6H0z'/%3E%3C/svg%3E") left bottom / 100% 100% no-repeat;
}
.hero__inner { position: relative; z-index: 1; max-width: 720px; margin-inline: auto; }
.hero h1 { margin-bottom: var(--space-4); }
/* The narrowest phones (320px) get one type-scale step down on the headline,
   which is what finally lets both hero CTAs clear a 568px-tall screen. */
@media (max-width: 359px) { .hero h1 { font-size: var(--text-3xl); } }
.hero .lead { margin-bottom: var(--space-6); }
.hero-tagline {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--color-text-muted);
  margin-top: var(--space-6);
}
.hero-note { margin-top: var(--space-4); font-size: var(--text-sm); color: var(--color-text-muted); }

/* --------------------------------------------------------------------
   18. CTA row — stacked full-width buttons on mobile, inline from
   480px. Used in the hero and the #work empty state.
   -------------------------------------------------------------------- */
.cta-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  justify-content: center;
}
@media (min-width: 480px) {
  .cta-row { flex-direction: row; flex-wrap: wrap; }
}
.cta-row .btn { width: 100%; }
@media (min-width: 480px) {
  .cta-row .btn { width: auto; }
}

/* --------------------------------------------------------------------
   19. Mobile nav panel — .nav-toggle existed with no expanded state
   defined; this is that state. script.js toggles `.nav-open` on
   `.site-header` and `aria-expanded` on `.nav-toggle`.
   -------------------------------------------------------------------- */
.site-header.nav-open .nav-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  position: absolute;
  inset-inline: 0;
  top: 100%;
  gap: var(--space-3);
  padding: var(--space-4) var(--container-padding) var(--space-6);
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-md);
}
@media (min-width: 1024px) {
  .site-header.nav-open .nav-links {
    position: static;
    flex-direction: row;
    padding: 0;
    border: 0;
    box-shadow: none;
    background: none;
  }
}

/* --------------------------------------------------------------------
   20. Callout — icon + text + link row (services "also available" note).
   -------------------------------------------------------------------- */
.callout {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-10);
  padding: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
.callout__icon { flex-shrink: 0; }
.callout__icon svg { width: var(--text-xl); height: var(--text-xl); display: block; }
.callout__text { flex: 1 1 240px; color: var(--color-text-muted); margin: 0; }

/* --------------------------------------------------------------------
   21. Pricing add-on cards — .pricing-card reused without a features
   list; needs its own header row (icon + price) and a description that
   grows to push the button to a consistent baseline across a row.
   -------------------------------------------------------------------- */
.pricing-card__addon-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
  font-size: var(--text-lg);
}
.pricing-card__addon-head svg { width: var(--text-lg); height: var(--text-lg); flex-shrink: 0; }
.pricing-card__addon-price {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  color: var(--bcw-rust);
}
.pricing-card__desc { flex-grow: 1; margin-bottom: var(--space-5); color: var(--color-text-muted); }

/* --------------------------------------------------------------------
   22. Pricing category title — leading emoji is decorative
   (aria-hidden in markup); this restores the gap the inline span
   otherwise collapses.
   -------------------------------------------------------------------- */
.category-title { margin-bottom: var(--space-6); }
.category-title .icon-prefix { margin-right: var(--space-2); display: inline-flex; vertical-align: -0.35em; }
.category-title .icon-prefix svg { width: var(--text-xl); height: var(--text-xl); }

/* --------------------------------------------------------------------
   23. FAQ heading wrapper — DEFECT-11 wraps each button in an <h3>;
   reset its default heading margin so it doesn't add space on top of
   the .faq-question padding.
   -------------------------------------------------------------------- */
.faq-item h3 { margin: 0; }

/* --------------------------------------------------------------------
   24. Form error state — DEFECT-18 fix (was a native alert()). Same
   red-tinted derivation already used by .form-control:invalid, so it
   introduces no new hue.
   -------------------------------------------------------------------- */
.form-error {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid color-mix(in srgb, var(--bcw-juniper) 55%, red 15%);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, red 6%, var(--color-surface));
  color: var(--color-text);
}
.form-error a { font-weight: var(--weight-semibold); }
.form-error p { margin: 0; }

/* --------------------------------------------------------------------
   25. Work section — staging-only placeholder chip (docs/rebrand/03-
   content.md §8.5). Deliberately loud; never meant to ship.
   -------------------------------------------------------------------- */
/* Real work for a real business that isn't launched yet. Sits under the
   screenshot so every card's image lines up; shale on sandstone is 7.7:1. */
.work-concept-chip {
  display: inline-block;
  align-self: flex-start;
  margin-bottom: var(--space-3);
  padding: var(--space-1) var(--space-3);
  background: var(--bcw-sand);
  color: var(--bcw-shale);
  font-weight: var(--weight-bold);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: var(--radius-sm);
}
.work-placeholder-chip {
  display: inline-block;
  margin-bottom: var(--space-3);
  padding: var(--space-1) var(--space-3);
  background: color-mix(in srgb, red 70%, var(--bcw-shale) 10%);
  color: var(--bcw-white);
  font-weight: var(--weight-bold);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------
   26. IT band — homepage cross-sell into Local IT, and the IT page's
   reverse cross-sell back to web design. Deliberately NOT a <section>:
   the bare `section{padding-block}` rhythm (64/96px) would give this the
   same visual weight as #pricing and #faq, which the brief rules out.
   -------------------------------------------------------------------- */
.it-band { padding-block: var(--space-10); }

/* .callout already reads as secondary (muted text, ghost-style CTA via
   .btn--ghost — underlined text, no fill, so it never competes with the
   primary "Get a free quote" buttons above it). This modifier only
   removes the margin-top .callout normally carries when nested at the
   tail of a section (not needed — .it-band already supplies spacing) and
   swaps the surface a shade quieter than the white pricing cards above it. */
.callout--band {
  margin-top: 0;
  background: var(--color-surface-sunken);
}

/* Local IT + Privacy footer-bottom links — a bare <a> inside .footer-bottom
   would otherwise resolve to the brighter --color-link (full white on
   .ink-panel), which reads louder than the copyright line beside it. Match
   .footer-section a's muted treatment instead. */
.footer-bottom a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
}
.footer-bottom a:hover { color: var(--bcw-sand); }

/* --------------------------------------------------------------------
   27. Credentials cards (IT page) — icon + title only, no body copy, so
   the default top-aligned .card content left a gap under the shorter
   cards whenever a sibling's title wrapped to two lines. Center the
   content instead of stretching it to fill the row height.
   -------------------------------------------------------------------- */
#credentials .card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
#credentials .card__icon { margin-inline: auto; }

/* --------------------------------------------------------------------
   Extras & terms — a plain two-column list under the pricing cards.
   -------------------------------------------------------------------- */
.terms-list { display: grid; gap: var(--space-2) var(--space-8); grid-template-columns: 1fr; margin: 0; padding: 0; list-style: none; }
@media (min-width: 768px) { .terms-list { grid-template-columns: 1fr 1fr; } }
.terms-list li { position: relative; padding-left: var(--space-5); color: var(--color-text-muted); }
.terms-list li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: 6px; height: 6px; border-radius: 50%; background: var(--bcw-rust); }
