/* ui/assets/booking.css
   SeatOps booking wizard stylesheet. Ported structurally from the Suds &
   Seats Co booking page's own booking.css (a separate client's repo,
   READ-ONLY reference, never modified) - same white-card-on-canvas layout,
   pill buttons, small-caps section labels, calendar/times layout - but
   every hardcoded Suds hex is gone. This file is shared by every tenant this
   product serves, so it carries NO tenant colour, font, or brand name of
   its own; it only reaches for `--seatops-*` custom properties, each with
   a neutral (non-branded) fallback so the wizard renders sanely even if
   GET /assets/brand.css (renderBrandCss, ui/index.html.js) somehow failed
   to load.

   Exactly five tenant-supplied custom properties exist, emitted by
   renderBrandCss: --seatops-primary, --seatops-ink, --seatops-surface,
   --seatops-accent, --seatops-font-stack. Rather than widening that
   contract with a pile of new --seatops-border / --seatops-muted /
   --seatops-success tokens for every shade this design needs, every
   shade below is DERIVED from those five with color-mix() - a --bc-*
   (booking-css-local) token computed once here in :root.

   IMPORTANT: --bc-primary/--bc-ink/--bc-surface/--bc-accent/--bc-font
   below are NOT the same names as the --seatops-* properties they read.
   `--seatops-primary: var(--seatops-primary, <fallback>);` looks like it
   would apply a fallback, but per the CSS Custom Properties spec a
   custom property that references itself (directly or through the
   cascade, since brand.css and this file both declare `:root`) is a
   CYCLE, and a cyclic custom property computes to the guaranteed-invalid
   value - not its fallback - which would silently untheme this entire
   file. Giving the resolved-with-fallback token a different name
   (--bc-primary, not --seatops-primary) is what makes the fallback
   actually take effect, and it also means the `var(--seatops-*)`
   coverage test only has to look in ONE place (this mapping block) for
   every tenant property this file depends on.

   Semantic roles used consistently below:
     --bc-primary  -> interactive/brand: buttons, selected states, focus
                      rings, links.
     --bc-accent   -> informational highlight: confirmation banners, hold
                      countdown, suggestion callouts, prices.
     ink/surface mixes -> neutral structure: borders, muted text, and the
                      "connection trouble, retry" notice - there is no
                      dedicated danger/error token, so a retry notice
                      reads as neutral-serious rather than guessing at a
                      colour the tenant never chose. */

:root {
  /* ---- Tenant tokens resolved with a neutral fallback (see header
     comment for why these are NOT named --seatops-*). The font fallback
     matches ui/index.html.js's own DEFAULT_FONT_STACK constant so the two
     independent defaults agree. */
  /* Display face for headings and the wordmark; falls back to the body
     font when a tenant configures only one. */
  --bc-font-heading: var(--seatops-heading-font-stack, var(--bc-font));
  --bc-primary: var(--seatops-primary, #3a3a3a);
  --bc-ink: var(--seatops-ink, #1a1a1a);
  --bc-surface: var(--seatops-surface, white);
  --bc-accent: var(--seatops-accent, #6b7280);
  --bc-font: var(--seatops-font-stack, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);

  /* ---- Derived neutrals (borders, muted/soft text) ---- */
  --bc-border: color-mix(in srgb, var(--bc-ink) 14%, var(--bc-surface) 86%);
  --bc-canvas: color-mix(in srgb, var(--bc-ink) 4%, var(--bc-surface) 96%);
  --bc-ink-soft: color-mix(in srgb, var(--bc-ink) 80%, var(--bc-surface) 20%);
  --bc-ink-muted: color-mix(in srgb, var(--bc-ink) 56%, var(--bc-surface) 44%);
  --bc-neutral-pale: color-mix(in srgb, var(--bc-ink) 8%, var(--bc-surface) 92%);
  --bc-neutral-soft: color-mix(in srgb, var(--bc-ink) 20%, var(--bc-surface) 80%);

  /* ---- Derived primary shades (buttons, focus, selection) ---- */
  --bc-primary-hover: color-mix(in srgb, var(--bc-primary) 82%, black 18%);
  --bc-primary-pale: color-mix(in srgb, var(--bc-primary) 12%, var(--bc-surface) 88%);
  --bc-primary-soft: color-mix(in srgb, var(--bc-primary) 32%, var(--bc-surface) 68%);
  --bc-on-primary: white;

  /* ---- Derived accent shades (informational highlights) ---- */
  --bc-accent-pale: color-mix(in srgb, var(--bc-accent) 14%, var(--bc-surface) 86%);
  --bc-accent-soft: color-mix(in srgb, var(--bc-accent) 38%, var(--bc-surface) 62%);
  --bc-accent-ink: color-mix(in srgb, var(--bc-accent) 70%, var(--bc-ink) 30%);

  /* ---- Elevation (neutral, ink-tinted so shadows never clash with hue) ---- */
  --bc-shadow-sm: 0 2px 8px color-mix(in srgb, var(--bc-ink) 8%, transparent);
  --bc-shadow: 0 4px 20px color-mix(in srgb, var(--bc-ink) 10%, transparent);
  --bc-shadow-md: 0 8px 30px color-mix(in srgb, var(--bc-ink) 12%, transparent);
  --bc-shadow-btn: 0 2px 12px color-mix(in srgb, var(--bc-primary) 35%, transparent);
  --bc-shadow-btn-hover: 0 6px 24px color-mix(in srgb, var(--bc-primary) 40%, transparent);
  --bc-shadow-day: 0 2px 10px color-mix(in srgb, var(--bc-primary) 40%, transparent);
  --bc-focus-ring: 0 0 0 3px var(--bc-primary-pale);

  /* ---- Spacing, radii, motion (layout constants, not tenant-themed) ---- */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;

  --radius-sm: 12px;
  --radius: 16px;
  --radius-lg: 24px;
  --radius-xl: 32px;
  --radius-full: 9999px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --transition-fast: 0.2s var(--ease-out);
  --transition: 0.35s var(--ease-out);
}

/* ---------- Reset and base ---------- */

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

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

body {
  margin: 0;
  padding: 0;
  background: var(--bc-canvas);
  color: var(--bc-ink);
  font-family: var(--bc-font);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--bc-font);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--bc-ink);
  margin: 0 0 var(--space-sm);
}

p { margin: 0 0 var(--space-md); color: var(--bc-ink-soft); }

a { color: var(--bc-primary); text-underline-offset: 2px; }
a:hover { color: var(--bc-primary-hover); }

/* [hidden] must always win, no matter what display rule a later class adds */
[hidden] { display: none !important; }

/* Focus ring, one rule for every interactive element on the page */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--bc-primary);
  outline-offset: 2px;
}
/* Step headings receive programmatic focus on step change for screen
   readers; a visible ring on static text only reads as a glitch. */
.step h1:focus, .step h1:focus-visible { outline: none; }

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

/* ---------- Small-caps section label ---------- */

.section-label {
  display: block;
  font-family: var(--bc-font);
  font-size: 0.6875rem;
  color: var(--bc-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  margin: var(--space-lg) 0 var(--space-sm);
}

/* ---------- Header and footer ---------- */

/* ---------- Page copy blocks (tenant.content) ----------
   Restores four blocks the Plan 3 port dropped from the Suds original.
   Every one is absent from the DOM entirely when its tenant config key is
   missing, so these rules simply never match for a tenant without copy. */

/* Service-area strip above the header. Reversed contrast (primary as the
   background) so it reads as a band rather than another card, matching the
   Suds original's role: the first thing that answers "do you come to me?" */
.site-topbar {
  background: var(--bc-primary);
  color: var(--bc-on-primary, #fff);
  text-align: center;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  padding: 8px var(--space-md);
  line-height: 1.5;
}

.site-header .tagline {
  display: block;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bc-ink-muted);
  margin-top: 2px;
}
/* The brand becomes an <a> when the tenant configures a siteUrl; it must
   not suddenly look like body-copy link text. */
.site-header a.brand { text-decoration: none; }
.site-header a.brand:hover { text-decoration: underline; }

/* The explainer. Ships `open`, so it must sit comfortably as a full block
   rather than read as a collapsed afterthought. */
.how-it-works {
  max-width: 640px;
  margin: 0 auto var(--space-lg);
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--bc-radius, 12px);
  padding: var(--space-md) var(--space-lg);
  text-align: left;
  box-shadow: var(--bc-shadow-sm);
}
.how-it-works-summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--bc-primary);
  text-align: center;
  list-style: none;
}
/* Safari renders a default disclosure marker that ignores list-style. */
.how-it-works-summary::-webkit-details-marker { display: none; }
.how-it-works-summary::after { content: ' ▾'; }
.how-it-works[open] .how-it-works-summary::after { content: ' ▴'; }
.how-it-works-body { margin-top: var(--space-md); }
.how-it-works-welcome { margin: 0 0 var(--space-sm); }
.how-it-works-steps { margin: 0 0 var(--space-sm); padding-left: 1.3em; }
.how-it-works-steps li { margin-bottom: 6px; }
.how-it-works-closing {
  margin: var(--space-sm) 0 0;
  color: var(--bc-ink-muted);
  font-size: 0.9rem;
}

.site-footer a { color: inherit; }

.site-header {
  background: var(--bc-surface);
  border-bottom: 1px solid var(--bc-border);
  text-align: center;
  padding: var(--space-md) var(--space-lg) 10px;
  /* Stays pinned while the wizard scrolls. */
  position: sticky;
  top: 0;
  z-index: 40;
  box-shadow: var(--bc-shadow-sm);
}

.site-header .brand {
  font-family: var(--bc-font);
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.4;
  color: var(--bc-ink);
}

.site-footer {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-md) var(--space-2xl);
  color: var(--bc-ink-muted);
  font-size: 0.8rem;
  text-align: center;
}
.site-footer p { color: var(--bc-ink-muted); margin: 0; }

/* Structured footer rows (content.footer): nav links, socials, contact.
   Rendered only when a tenant configures them; the single-line footer
   above stays the default. */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm) var(--space-lg);
  margin: 0 0 var(--space-md);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.footer-links a,
.footer-contact a { color: inherit; text-decoration: none; }
.footer-links a:hover,
.footer-contact a:hover { text-decoration: underline; }
.footer-social { font-size: 0.75rem; }
.footer-contact { margin: 0 0 var(--space-md); }

/* ---------- Wizard canvas ---------- */

.wizard {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-md);
}

.step h1 {
  font-size: 1.75rem;
  line-height: 1.2;
  text-align: center;
  margin: 0 0 var(--space-sm);
}

.step h1 + p {
  text-align: center;
  color: var(--bc-ink-muted);
  max-width: 46ch;
  margin: 0 auto var(--space-lg);
}

/* White (surface) card */
.card {
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  margin: 0 0 var(--space-md);
}

/* ---------- Progress ---------- */

.progress {
  display: flex;
  justify-content: center;
  gap: var(--space-lg);
  list-style: none;
  margin: 0 0 var(--space-xl);
  padding: 0;
  counter-reset: step;
}

.progress li {
  position: relative;
  padding-top: 32px;
  text-align: center;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bc-ink-muted);
}

.progress li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 24px;
  height: 24px;
  border-radius: var(--radius-full);
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  color: var(--bc-ink-muted);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 22px;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.progress li.current { color: var(--bc-primary); }
.progress li.current::before {
  background: var(--bc-primary);
  border-color: var(--bc-primary);
  color: var(--bc-on-primary);
  box-shadow: var(--bc-shadow-btn);
}

.progress li.done { color: var(--bc-accent-ink); }
.progress li.done::before {
  background: var(--bc-accent-pale);
  border-color: var(--bc-accent-soft);
  color: var(--bc-accent-ink);
  content: '\2713';
}

/* ---------- Mode banner (paused notice / in-area confirmation) ---------- */

#mode-banner {
  background: var(--bc-accent-pale);
  border: 1px solid var(--bc-accent-soft);
  border-radius: var(--radius);
  padding: var(--space-sm) var(--space-lg);
  margin: 0 0 var(--space-lg);
  color: var(--bc-accent-ink);
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
}
#mode-banner:empty { display: none; }

/* ---------- Notice ---------- */

/* Sits below the active step's content (under the address card, above the
   map; after the buttons on later steps - see ui/index.html.js), so the
   gap it needs is above it, not below. */
.notice {
  background: var(--bc-primary-pale);
  border: 1px solid var(--bc-primary-soft);
  border-radius: var(--radius);
  padding: var(--space-md) var(--space-lg);
  margin: var(--space-lg) 0 0;
  color: var(--bc-ink);
  font-size: 0.9rem;
}

/* No dedicated --seatops-danger token exists (see file header); a retry
   notice reads as neutral-serious rather than assuming a colour the tenant
   never configured. */
.notice.retry {
  background: var(--bc-neutral-pale);
  border-color: var(--bc-neutral-soft);
}

/* ---------- Form elements ---------- */

label {
  display: block;
  font-weight: 600;
  color: var(--bc-ink);
  font-size: 0.9rem;
  margin: 0 0 var(--space-xs);
}

input[type="text"],
input[type="email"],
input[type="tel"],
input:not([type]),
select,
textarea {
  display: block;
  width: 100%;
  padding: 12px var(--space-md);
  margin: 0 0 var(--space-md);
  background: var(--bc-surface);
  color: var(--bc-ink);
  font-family: var(--bc-font);
  font-size: 16px;
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input:not([type]):focus,
select:focus,
textarea:focus {
  border-color: var(--bc-primary);
  box-shadow: var(--bc-focus-ring);
  outline: none;
}

textarea { resize: vertical; min-height: 64px; }

/* ---------- Address autocomplete (booking-autocomplete.js, Task 6) ---------- */

.autocomplete-wrap { position: relative; }

.autocomplete-list {
  position: absolute;
  top: calc(100% - var(--space-md) + 4px);
  left: 0;
  right: 0;
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--bc-shadow-md);
  z-index: 30;
  overflow: hidden;
}

.autocomplete-item {
  padding: 10px var(--space-md);
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--bc-ink-soft);
  cursor: pointer;
}

.autocomplete-item.active {
  background: var(--bc-primary-pale);
  color: var(--bc-ink);
}

input::placeholder, textarea::placeholder { color: var(--bc-ink-muted); opacity: 0.7; }

fieldset {
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md) var(--space-md);
  margin: 0 0 var(--space-md);
}

fieldset legend {
  padding: 0 var(--space-xs);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--bc-ink);
}

.legend-note {
  display: block;
  margin-top: 2px;
  font-weight: 400;
  font-size: 0.82rem;
  color: var(--bc-ink-muted);
}

fieldset label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  margin: var(--space-xs) var(--space-lg) 0 0;
  font-weight: 400;
  color: var(--bc-ink-soft);
}

input[type="radio"], input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--bc-primary);
}

.terms {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-weight: 400;
  font-size: 0.875rem;
  color: var(--bc-ink-soft);
  margin: var(--space-md) 0;
}
.terms input { margin-top: 3px; flex-shrink: 0; }

/* #intake-fields wrapper: tenant-configured intake questions (Task 3) render
   here at runtime, one .intake-field per question - a plain vertical stack,
   consistent with the rest of the contact form. */
.intake-fields { display: block; }
.intake-field { margin: 0 0 var(--space-md); }
/* Option rows inside yesno/checklist groups: one full-width row per
   option, 44px minimum - a phone thumb's tap target - with the control
   pinned top-left so multi-line option labels (the coffee menu) hang
   cleanly beside it. */
.intake-field fieldset label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 0;
  min-height: 44px;
  margin: 0;
}
.intake-field fieldset input[type="radio"],
.intake-field fieldset input[type="checkbox"] {
  margin-top: 3px;
  flex-shrink: 0;
}

/* Fine print a field can carry above its input (tenant terms clauses sit
   above the consent checkbox, exactly as the tenant's own Acuity form
   shows them). Deliberately quieter than the field labels around it. */
.intake-field-body {
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--bc-ink-soft);
  margin: 0 0 var(--space-sm);
}
.intake-field-body p { color: inherit; font-size: inherit; margin: 0 0 var(--space-xs); }

/* Required-field marker; inputs carry the required attribute for AT, the
   asterisk is the visual signal (aria-hidden) */
.req { color: var(--bc-accent-ink); margin-left: 2px; font-weight: 700; }
.req-hint {
  font-size: 0.8rem;
  color: var(--bc-ink-muted);
  text-align: right;
  margin: 0 0 var(--space-sm);
}

.field-error {
  color: var(--bc-accent-ink);
  font-size: 0.85rem;
  font-weight: 600;
  margin: calc(var(--space-xs) * -1) 0 var(--space-sm);
}

/* Fields flagged by client-side validation (aria-invalid set on submit) */
input[aria-invalid="true"],
textarea[aria-invalid="true"],
fieldset[aria-invalid="true"] {
  border-color: var(--bc-accent-ink);
}
input[type="checkbox"][aria-invalid="true"] {
  outline: 2px solid var(--bc-accent-ink);
  outline-offset: 2px;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 var(--space-md);
}

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

.btn-primary {
  display: inline-block;
  min-height: 48px;
  padding: 13px 28px;
  background: var(--bc-primary);
  color: var(--bc-on-primary);
  border: none;
  border-radius: var(--radius-full);
  font-family: var(--bc-font);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  box-shadow: var(--bc-shadow-btn);
  transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.btn-primary:hover:not(:disabled) {
  background: var(--bc-primary-hover);
  transform: translateY(-2px);
  box-shadow: var(--bc-shadow-btn-hover);
}
.btn-primary:active:not(:disabled) { transform: translateY(0); }
.btn-primary:disabled {
  background: var(--bc-neutral-soft);
  color: var(--bc-ink-muted);
  cursor: not-allowed;
  box-shadow: none;
}

.btn-link {
  display: inline-block;
  background: none;
  border: none;
  padding: var(--space-xs) 0;
  margin-top: var(--space-sm);
  color: var(--bc-primary);
  font-family: var(--bc-font);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.btn-link:hover { color: var(--bc-primary-hover); }

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--bc-surface);
  color: var(--bc-primary);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-full);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}
.btn-icon:hover:not(:disabled) { background: var(--bc-primary-pale); border-color: var(--bc-primary-soft); }
.btn-icon:disabled { color: var(--bc-ink-muted); cursor: not-allowed; opacity: 0.5; }

/* Step-level actions: primary centered, back link centered under it */
.step-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
}
.step-actions .btn-primary { min-width: 240px; }

/* ---------- Items step ---------- */

/* Appointment summary on the schedule step */
.appt-summary {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  background: var(--bc-surface);
  border: 1.5px solid var(--bc-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md) var(--space-lg);
  margin: 0 0 var(--space-md);
}
.appt-summary .btn-link { margin: 0; flex-shrink: 0; }

.items-section-optional {
  font-family: var(--bc-font);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--bc-ink-muted);
}

.items-category-heading {
  font-family: var(--bc-font);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bc-primary);
  margin: var(--space-lg) 0 var(--space-sm);
}
.main-items > .items-category-heading:first-child { margin-top: 0; }

.items-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin: 0 0 var(--space-md);
}

.item-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
  padding: var(--space-md) var(--space-lg);
  background: var(--bc-surface);
  border: 1.5px solid var(--bc-border);
  border-radius: var(--radius-lg);
  font-family: var(--bc-font);
  font-size: 1rem;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.item-row:hover { box-shadow: var(--bc-shadow); }
.item-row.selected {
  border-color: var(--bc-primary);
  box-shadow: 0 0 0 1px var(--bc-primary), var(--bc-shadow);
}

.item-row-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
/* Appointment-type illustration (from the tenant's own Acuity account,
   origin-allowlisted in core/catalog.js). Decorative: contained, never
   cropped, and it must not squash the text column beside it. */
.item-row-img {
  width: 104px;
  height: 84px;
  object-fit: contain;
  flex-shrink: 0;
  align-self: center;
}

.item-row-name {
  font-family: var(--bc-font);
  font-weight: 700;
  font-size: 1.125rem;
  line-height: 1.3;
  color: var(--bc-ink);
}
.item-row-price {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--bc-accent-ink);
}
.item-row-desc {
  font-size: 0.875rem;
  color: var(--bc-ink-soft);
  line-height: 1.5;
  margin-top: 2px;
}

/* The Select / Selected pill on main-item cards */
.item-row-cta {
  flex-shrink: 0;
  align-self: center;
  padding: 9px 20px;
  border: 1.5px solid var(--bc-primary);
  border-radius: var(--radius-full);
  color: var(--bc-primary);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.item-row:hover .item-row-cta { background: var(--bc-primary-pale); }
.item-row.selected .item-row-cta {
  background: var(--bc-primary);
  color: var(--bc-on-primary);
}

/* Add-ons: one card, hairline-separated checkbox rows */
.addons-section { margin: 0 0 var(--space-md); }

.addon-items {
  display: flex;
  flex-direction: column;
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin: 0 0 var(--space-md);
}

.addon-items .item-row {
  border: none;
  border-bottom: 1px solid var(--bc-border);
  border-radius: 0;
  padding: var(--space-md) var(--space-lg);
}
.addon-items .item-row:last-child { border-bottom: none; }
.addon-items .item-row:hover { box-shadow: none; background: var(--bc-canvas); }
.addon-items .item-row.selected {
  box-shadow: none;
  background: var(--bc-primary-pale);
}
.addon-items .item-row-name { font-size: 0.9375rem; font-weight: 600; }
.addon-items .item-row-price { white-space: nowrap; }

.item-row-addon { align-items: flex-start; }
.item-row-addon input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; }

/* An add-on the current cart leaves no room for. It stays on the list rather
   than vanishing (BugHerd #8), so the styling only has to read as "not
   selectable": the disabled checkbox and the replacement description text are
   the real cues. No blanket opacity - that would fade the very sentence
   explaining why the row is off. */
.item-row-unavailable { cursor: not-allowed; background: var(--bc-canvas); }
.item-row-unavailable .item-row-name,
.item-row-unavailable .item-row-price { color: var(--bc-ink-muted); }
.item-row-unavailable .item-row-desc { color: var(--bc-ink-soft); font-style: italic; }

/* The payment-due sentence above the Pay now button on the confirmation
   screen (BugHerd #10). Weighted like the total line it echoes, and given
   room above the button so the two read as one instruction. */
.pay-due {
  font-weight: 700;
  color: var(--bc-ink);
  margin: var(--space-sm) 0 var(--space-xs);
}

/* The travel fee, stated directly under the confirmed address. It is the
   first price the customer sees, so it reads as a plain fact: same weight as
   the confirmation above it, muted enough not to look like a warning. */
.area-mileage {
  margin: var(--space-xs) 0 0;
  color: var(--bc-ink-soft);
  font-weight: 600;
}

.items-total {
  text-align: center;
  font-weight: 700;
  color: var(--bc-ink);
  margin: 0 0 var(--space-xs);
}

.tax-note {
  text-align: center;
  color: var(--bc-ink-muted);
  font-size: 0.8rem;
  margin: 0 0 var(--space-md);
}

.mileage-note {
  text-align: center;
  color: var(--bc-ink-soft);
  font-size: 0.85rem;
  margin: 0 0 var(--space-md);
}

.suggestion {
  background: var(--bc-accent-pale);
  border: 1px solid var(--bc-accent-soft);
  border-radius: var(--radius);
  padding: var(--space-md) var(--space-lg);
  margin: 0 0 var(--space-md);
  color: var(--bc-ink);
  font-size: 0.9375rem;
}
.suggestion strong { color: var(--bc-accent-ink); }
.suggestion .btn-link { margin-left: var(--space-xs); margin-top: 0; }

/* ---------- Service-area map (progressive enhancement, Task 6) ---------- */

#service-map { height: 260px; border-radius: var(--radius-lg); border: 1px solid var(--bc-border); margin: var(--space-lg) 0 0; }

/* Inline in-area confirmation strip, directly under the map */
.area-confirm {
  margin: var(--space-md) 0 0;
  padding: var(--space-md) var(--space-lg);
  background: var(--bc-accent-pale);
  border: 1px solid var(--bc-accent-soft);
  border-radius: var(--radius);
  text-align: center;
}
.area-confirm p { margin: 0 0 var(--space-sm); color: var(--bc-accent-ink); }

/* ---------- Schedule step: calendar + times ---------- */

.schedule-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-md);
  align-items: start;
  margin: 0 0 var(--space-sm);
}
@media (min-width: 700px) {
  .schedule-layout { grid-template-columns: 380px 1fr; }
  /* Until a day is picked there is no times panel; keep the calendar centered */
  .schedule-layout:has(#times-wrap[hidden]) { grid-template-columns: 1fr; }
  .schedule-layout:has(#times-wrap[hidden]) .cal-panel {
    width: 100%;
    max-width: 460px;
    margin: 0 auto;
  }
}

.cal-panel {
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-xl);
  padding: var(--space-lg);
}

.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 var(--space-md);
}

#cal-label {
  font-family: var(--bc-font);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--bc-ink);
}

.cal-nav { display: flex; gap: var(--space-sm); }

#calendar {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 var(--space-sm);
}

#calendar.cal-loading {
  opacity: 0.45;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

.cal-loading-note {
  margin: 0 0 var(--space-sm);
  text-align: center;
  color: var(--bc-ink-soft);
  font-size: 0.875rem;
}

.cal-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.cal-row.cal-dow span {
  display: block;
  text-align: center;
  padding: var(--space-xs) 0;
  color: var(--bc-ink-muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.cal-cell {
  position: relative;
  min-width: 40px;
  min-height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--bc-ink-muted);
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--bc-font);
  font-size: 0.9rem;
  cursor: default;
  transition: background var(--transition-fast), color var(--transition-fast);
}

/* Available day */
.cal-cell.selectable {
  background: var(--bc-primary-pale);
  color: var(--bc-primary);
  font-weight: 600;
  cursor: pointer;
}
.cal-cell.selectable:hover { background: var(--bc-primary-soft); }

/* Selected day */
.cal-cell.selected {
  background: var(--bc-primary);
  color: var(--bc-on-primary);
  font-weight: 700;
  box-shadow: var(--bc-shadow-day);
}

/* Every non-open day looks the same quiet "unavailable": booked, route-
   blocked, and never-offered are indistinguishable on purpose (booking.js
   deliberately maps capacity/route reasons onto the same class). */
.cal-cell.blocked-capacity,
.cal-cell.not-offered {
  color: var(--bc-ink-muted);
  opacity: 0.55;
  cursor: not-allowed;
}

.cal-cell.out { opacity: 0.25; }

/* Today marker: a small dot, not a colour swap - so it never fights the
   selectable/selected/blocked states above for attention. */
.cal-cell.today::after {
  content: '';
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
}

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  margin: var(--space-sm) 0 var(--space-xs);
  color: var(--bc-ink-muted);
  font-size: 0.78rem;
}
.cal-legend-item { display: inline-flex; align-items: center; gap: var(--space-xs); }
.cal-legend-item::before {
  content: '';
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--bc-ink-muted);
}
.cal-legend-item.legend-open::before { background: var(--bc-primary-pale); box-shadow: inset 0 0 0 1px var(--bc-primary); }
.cal-legend-item.legend-unavailable::before { background: var(--bc-neutral-soft); }

#btn-next-available { margin-top: var(--space-xs); }

/* Times panel: vertical pill list beside the calendar */
#times-wrap { min-width: 0; }

#times-heading {
  font-family: var(--bc-font);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--bc-ink);
  margin: var(--space-xs) 0 var(--space-md);
  text-align: center;
}

#times {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
#times p { text-align: center; font-size: 0.9rem; color: var(--bc-ink-muted); }

.time-btn {
  width: 100%;
  min-height: 46px;
  padding: 10px 18px;
  background: var(--bc-surface);
  color: var(--bc-ink);
  border: 1.5px solid var(--bc-border);
  border-radius: var(--radius-full);
  font-family: var(--bc-font);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}
.time-btn:hover {
  border-color: var(--bc-primary);
  color: var(--bc-primary);
  background: var(--bc-primary-pale);
}
.time-btn.selected {
  background: var(--bc-primary);
  border-color: var(--bc-primary);
  color: var(--bc-on-primary);
  box-shadow: var(--bc-shadow-btn);
}

.hold {
  padding: var(--space-sm) var(--space-md);
  margin: 0 0 var(--space-md);
  background: var(--bc-accent-pale);
  border: 1px solid var(--bc-accent-soft);
  color: var(--bc-accent-ink);
  border-radius: var(--radius);
  font-weight: 700;
  font-size: 0.9375rem;
  text-align: center;
}
.hold:empty { display: none; }

/* ---------- Review ---------- */

.summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  margin: 0 0 var(--space-md);
}
/* Checkout-style receipt (BugHerd #4): one row per item with its price,
   mileage as its own row, the total set apart, then the details list. */
.receipt {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--space-sm);
}
.receipt caption {
  text-align: left;
  color: var(--bc-ink-muted);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0 0 var(--space-sm);
}
.receipt th,
.receipt td {
  padding: var(--space-sm) 0;
  border-bottom: 1px dashed var(--bc-border);
  vertical-align: top;
  color: var(--bc-ink);
}
.receipt th { text-align: left; font-weight: 500; padding-right: var(--space-md); }
.receipt td { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; font-weight: 600; }
.receipt-mileage th,
.receipt-mileage td { color: var(--bc-ink-soft); }
.receipt-total th,
.receipt-total td {
  border-bottom: none;
  border-top: 2px solid var(--bc-ink);
  padding-top: var(--space-md);
  color: var(--bc-ink);
  font-weight: 800;
  font-size: 1.125rem;
}
.receipt-note {
  margin: 0 0 var(--space-md);
  text-align: right;
  color: var(--bc-ink-soft);
  font-size: 0.85rem;
}
.details {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin: 0;
}
.details > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
  padding-bottom: var(--space-sm);
  border-bottom: 1px dashed var(--bc-border);
}
.details > div:last-child { border-bottom: none; padding-bottom: 0; }
.details dt {
  color: var(--bc-ink-muted);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding-top: 4px;
}
.details dd { margin: 0; color: var(--bc-ink); font-weight: 600; text-align: right; }

/* ---------- Done ---------- */

#step-done { text-align: center; }
#step-done h1 {
  font-size: 2.2rem;
  color: var(--bc-accent-ink);
  letter-spacing: 0;
}
#done-details {
  background: var(--bc-surface);
  border: 1px solid var(--bc-border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  margin: 0 auto var(--space-lg);
  max-width: 440px;
}
#done-details p { margin: 0 0 var(--space-sm); }
#done-details p:last-child { margin: 0; }

/* ---------- Mobile ---------- */

@media (max-width: 520px) {
  .wizard { padding: var(--space-lg) var(--space-sm); }

  .site-header .brand { font-size: 1.35rem; }

  .progress { gap: var(--space-md); }
  /* Labels are hidden on small screens; keep each dot its full width so the
     absolutely-positioned circles don't collapse onto each other. */
  .progress li { font-size: 0; letter-spacing: 0; min-width: 24px; padding-top: 24px; }

  .step h1 { font-size: 1.5rem; }

  .grid-2 { grid-template-columns: 1fr; }

  .card, .cal-panel { padding: var(--space-md); }

  .cal-cell { min-width: 44px; min-height: 44px; font-size: 1rem; }

  .item-row { padding: var(--space-md); gap: var(--space-sm); flex-wrap: wrap; }
  /* On a phone the image, text, and Select pill cannot share one row
     without squeezing the title to a word per line. The pill drops to its
     own full-width row instead: the text gets its width back and the tap
     target grows to a comfortable bar. Add-on rows have no cta and keep
     their compact layout. */
  .item-row-cta {
    flex: 1 0 100%;
    text-align: center;
    padding-top: 9px;
    padding-bottom: 9px;
  }
  .item-row-img { width: 64px; height: 56px; }

  .step-actions .btn-primary { width: 100%; }

  #service-map { height: 200px; }
}

/* ---------- color-mix() fallback (two interaction-critical declarations) ---------- */

/* `--bc-primary-hover` and `--bc-accent-ink` (both defined with color-mix()
   in :root above) compute to the guaranteed-invalid value in a browser
   without color-mix() support. That is harmless almost everywhere in this
   file (an invalid value just falls back to the property's inherited or
   initial value, and most uses are decorative), but these two are not
   decorative:
     - .btn-primary:hover:not(:disabled)'s `background` would fall to
       transparent while `color` stays the plain (non-color-mix) white from
       the base .btn-primary rule - white text on a transparent background.
     - input[type="checkbox"][aria-invalid="true"]'s `outline` is a
       shorthand, so an invalid value resets outline-style to `none` too -
       the invalid-checkbox ring disappears entirely, not just its colour.

   Declaring the property a second time with a literal value BEFORE the
   color-mix() one does NOT fix this: cascade picks the winning declaration
   by specificity/source-order alone (var() always parses as syntactically
   valid), and only AFTER that resolves does the browser discover the
   winning declaration is invalid at computed-value time - it does not then
   fall through to an earlier, lower-priority declaration. The only way to
   make a fallback declaration win the cascade in a non-supporting browser
   is to make it conditional with @supports, so the color-mix()-based rules
   above are never in that browser's cascade to begin with.

   This block must stay physically AFTER the two rules it overrides: with
   equal selector specificity, cascade breaks the tie by source order, and
   in a supporting browser this block does not apply at all (the `not (...)`
   condition is false), so the normal tenant-themed rules above always win
   there regardless of position. The fallback values below reference
   --bc-primary / --bc-accent directly (plain var() chains with no
   color-mix() in them, so still valid here) rather than a hardcoded hex,
   which keeps even this fallback path tenant-themed instead of inventing
   an unrelated neutral colour. */
@supports not (color: color-mix(in srgb, red, blue)) {
  .btn-primary:hover:not(:disabled) {
    background: var(--bc-primary);
  }
  input[type="checkbox"][aria-invalid="true"] {
    outline: 2px solid var(--bc-accent);
  }
}

/* ---------- Display typography ----------
   Applied last so it wins over the base rules without editing each one.
   Only headings, the wordmark and the explainer summary take the display
   face: body copy, labels, inputs and buttons stay in the readable stack,
   because a booking form has to be legible before it is on-brand. */
.site-header .brand,
.step h1,
.step h2,
.how-it-works-summary {
  font-family: var(--bc-font-heading);
}
.step h1 { letter-spacing: -0.01em; }

/* When a tenant supplies a logo the wordmark is an <img>, which must not
   inherit heading sizing. Capped so a large source file cannot dominate
   the header on a phone. */
.site-header .brand-logo {
  display: block;
  margin: 0 auto;
  max-width: min(260px, 70vw);
  height: auto;
}

/* ---------- Bold theme (opt-in: brand.theme "bold") ----------
   For a tenant whose own site is PRIMARY-DOMINANT: a dark brand colour as
   the page ground with light panels sitting on it, rather than the light
   near-surface canvas the default paints. Opting in inverts the shell -
   the ground becomes primary, panels keep surface, and the main CTA moves
   to accent - while everything inside a panel keeps its ink-on-surface
   treatment.

   Every rule below reaches only for --bc-* tokens (never --seatops-*; the
   mapping block at the top of this file must remain the single place those
   appear), so the theme is tenant-neutral: it assumes a dark primary, a
   light surface, and a mid accent, and nothing else.

   Contrast: a bold tenant's surface is typically a SATURATED brand tint,
   not near-white, which shifts every color-mix() derivation darker. The
   text-carrying tokens are re-derived with a higher ink share so in-card
   helper text keeps >= 4.5:1 against that stronger surface. Audited
   against the most saturated surface shipped (#F9B1A4 on primary #5F3046,
   ink #3A1D2B, accent #E17CAD): ground copy 4.7:1+, in-card muted text
   4.9:1, accent-ink 5.1:1, CTA label 5.5:1 - all WCAG AA. */

body.theme-bold {
  /* Text sitting directly on the primary ground. The surface hue IS the
     light ink (exactly what a dark-ground brand site does), with a soft
     variant for secondary copy that still clears 4.5:1 on primary. */
  --bc-ground-ink: var(--bc-surface);
  --bc-ground-ink-soft: color-mix(in srgb, var(--bc-surface) 84%, var(--bc-primary) 16%);
  /* Re-derived in-card text tokens - see the contrast note above. */
  --bc-ink-muted: color-mix(in srgb, var(--bc-ink) 76%, var(--bc-surface) 24%);
  --bc-accent-ink: color-mix(in srgb, var(--bc-accent) 30%, var(--bc-ink) 70%);
  --bc-border: color-mix(in srgb, var(--bc-ink) 22%, var(--bc-surface) 78%);

  /* The body token --bc-canvas is deliberately NOT remapped: it doubles as
     the in-card neutral hover tint (.addon-items .item-row:hover), which
     must stay near-surface. Only the page itself goes primary. */
  background: var(--bc-primary);
  /* Brand sites of this kind set body copy larger than form-app copy
     (measured 19.6px on the reference); 17px meets it partway without
     inflating the controls, which are all sized in rem and unaffected. */
  font-size: 17px;
  /* The full-bleed bands below reach 50vw past their column; 100vw
     includes the scrollbar gutter, so clip the sliver of overflow. */
  overflow-x: clip;
}

/* Shell chrome on the dark ground */
.theme-bold .site-topbar {
  background: color-mix(in srgb, var(--bc-ink) 50%, var(--bc-primary) 50%);
  color: var(--bc-ground-ink);
}
.theme-bold .site-header {
  background: transparent;
  border-bottom: none;
  box-shadow: none;
  /* The light theme pins a compact, OPAQUE header; transparent + sticky
     would float the logo over content on scroll. A bold tenant's header
     carries a tall logo anyway - pinning it would spend the viewport on
     branding a booking form does not need twice. */
  position: static;
}
.theme-bold .site-header .brand { color: var(--bc-ground-ink); }
.theme-bold .site-header .tagline { color: var(--bc-ground-ink-soft); }
.theme-bold .site-header .brand-logo { max-width: min(300px, 78vw); }

/* Stepper */
.theme-bold .progress li { color: var(--bc-ground-ink-soft); }
.theme-bold .progress li::before {
  background: color-mix(in srgb, var(--bc-surface) 14%, transparent);
  border-color: color-mix(in srgb, var(--bc-surface) 45%, transparent);
  color: var(--bc-ground-ink);
}
.theme-bold .progress li.current { color: var(--bc-ground-ink); }
.theme-bold .progress li.current::before {
  background: var(--bc-accent);
  border-color: var(--bc-accent);
  color: var(--bc-ink);
  box-shadow: 0 2px 12px color-mix(in srgb, black 30%, transparent);
}
.theme-bold .progress li.done { color: var(--bc-ground-ink-soft); }
.theme-bold .progress li.done::before {
  background: var(--bc-surface);
  border-color: var(--bc-surface);
  color: var(--bc-primary);
}

/* Headings and step copy on the ground. The display face earns marketing
   scale here: on the brand ground the heading IS the hero. */
.theme-bold .step h1 {
  color: var(--bc-ground-ink);
  font-size: 2.75rem;
}
/* :not(.hold): the contact step's hold-countdown banner is ALSO the
   paragraph adjacent to its h1, and it is a panel with its own bg - the
   ground-copy colour on it would be light-on-light. */
.theme-bold .step h1 + p:not(.hold) { color: var(--bc-ground-ink-soft); }
.theme-bold #step-done h1 { color: var(--bc-ground-ink); }
.theme-bold #step-done > p { color: var(--bc-ground-ink-soft); }
.theme-bold .section-label { color: var(--bc-ground-ink-soft); }
/* Category headings sit between item cards ON the ground; their default
   primary colour would vanish into the primary ground. */
.theme-bold .items-category-heading { color: var(--bc-ground-ink); }
.theme-bold .items-total { color: var(--bc-ground-ink); }
.theme-bold .items-section-optional { color: var(--bc-ground-ink-soft); }
.theme-bold .tax-note { color: var(--bc-ground-ink-soft); }
.theme-bold .mileage-note { color: var(--bc-ground-ink-soft); }
.theme-bold #times-heading { color: var(--bc-ground-ink); }
.theme-bold #times p { color: var(--bc-ground-ink-soft); }
.theme-bold .site-footer,
.theme-bold .site-footer p { color: var(--bc-ground-ink-soft); }
/* With a structured footer configured, the footer reads as the site's own
   bottom bar: full width under a hairline, roomy, nav links in the
   stronger ground ink. */
.theme-bold .site-footer {
  max-width: none;
  margin-top: var(--space-2xl);
  border-top: 1px solid color-mix(in srgb, var(--bc-surface) 18%, transparent);
  padding-top: var(--space-2xl);
}
.theme-bold .footer-links a { color: var(--bc-ground-ink); }

/* Ground-level back links. `.step >` scopes this to the step-actions rows
   sitting directly on the ground - the ones inside a .card (address,
   contact form) keep the primary-on-surface treatment. */
.theme-bold .step > .step-actions .btn-link { color: var(--bc-ground-ink-soft); }
.theme-bold .step > .step-actions .btn-link:hover { color: var(--bc-ground-ink); }

/* The CTA moves to accent with ink text (audited 5.5:1); a primary
   button would vanish into the primary ground. Geometry follows the
   reference brand site's measured button: near-square 4px corners, flat
   (no shadow anywhere on that site), 50px tall, wide horizontal padding. */
.theme-bold .btn-primary {
  background: var(--bc-accent);
  color: var(--bc-ink);
  border-radius: 4px;
  min-height: 50px;
  padding: 13px 48px;
  box-shadow: none;
}
.theme-bold .btn-primary:hover:not(:disabled) {
  /* Lightened, not darkened: hover must not cost the ink label its AA. */
  background: color-mix(in srgb, var(--bc-accent) 88%, white 12%);
  box-shadow: none;
  transform: none;
}

/* ---- Full-bleed bands ----
   The reference site is not cards floating on a background: it is
   full-width colour bands stacked flush, square-edged, unshadowed, with
   ~77px of vertical padding and the text centred in a ~680px column
   inside (all measured). The wizard's three big panels take that band
   treatment: the explainer (accent), the form cards (surface), and the
   review summary (surface). margin-inline reaches from the centred
   column to the viewport edges; the max() padding centres the inner
   column back to 680px. body overflow-x: clip above absorbs the
   scrollbar-gutter sliver 100vw includes. */
.theme-bold .how-it-works,
.theme-bold .card,
.theme-bold .summary {
  margin-inline: calc(50% - 50vw);
  /* The base explainer carries max-width: 640px; a capped box + negative
     margins renders as a half-width band pinned left, so the cap must go. */
  max-width: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 56px max(var(--space-lg), calc(50vw - 340px)) 64px;
}
/* Bands stack flush, like the reference site's sections. */
.theme-bold .how-it-works { margin-block: var(--space-xl) 0; }
.theme-bold .how-it-works + .card { margin-top: 0; }

/* The explainer band is accent; every line inside goes full ink because
   the soft/muted mixes fall under AA on an accent bg. */
.theme-bold .how-it-works { background: var(--bc-accent); }
.theme-bold .how-it-works-summary,
.theme-bold .how-it-works-welcome,
.theme-bold .how-it-works-closing { color: var(--bc-ink); }

/* Inner cards (the ones that sit INSIDE the plum ground or a band, like
   the reference site's price cards): flat, small 12px radius. */
.theme-bold .cal-panel,
.theme-bold .appt-summary,
.theme-bold #done-details,
.theme-bold .addon-items,
.theme-bold .item-row {
  border-color: transparent;
  border-radius: 12px;
  box-shadow: none;
}
/* Re-assert the states the blanket rule above would otherwise win over
   (same specificity, later in the file). */
.theme-bold .item-row.selected {
  border-color: var(--bc-primary);
  box-shadow: 0 0 0 1.5px var(--bc-primary);
}
.theme-bold .item-row-cta { border-radius: 4px; }
/* The banners and callouts follow the smaller radius scale. */
.theme-bold #mode-banner,
.theme-bold .notice,
.theme-bold .suggestion,
.theme-bold .hold,
.theme-bold .area-confirm { border-radius: 8px; }
/* A keyed tenant whose map failed to paint leaves #service-map un-hidden
   but empty; the bold border otherwise draws it as a bare outlined box. */
.theme-bold #service-map:empty { border: none; }

/* Inputs sit on a surface panel; when surface is a saturated tint they
   need their own lighter field so the boundary reads. */
.theme-bold input[type="text"],
.theme-bold input[type="email"],
.theme-bold input[type="tel"],
.theme-bold input:not([type]),
.theme-bold select,
.theme-bold textarea {
  background: color-mix(in srgb, white 62%, var(--bc-surface) 38%);
  border-color: color-mix(in srgb, var(--bc-ink) 30%, var(--bc-surface) 70%);
  border-radius: 8px;
}

/* Time buttons sit directly on the ground: flat surface blocks with the
   reference site's near-square corners, and the selected state moves to
   accent for the same reason the CTA does (a primary block would vanish
   into the primary ground). */
.theme-bold .time-btn {
  border-color: transparent;
  border-radius: 4px;
  box-shadow: none;
}
.theme-bold .time-btn:hover {
  border-color: var(--bc-accent);
  background: var(--bc-surface);
  color: var(--bc-ink);
}
.theme-bold .time-btn.selected {
  background: var(--bc-accent);
  border-color: var(--bc-accent);
  color: var(--bc-ink);
  box-shadow: none;
}

/* Focus rings for the interactive elements that sit ON the ground: the
   default primary outline is invisible against a primary ground. In-card
   elements keep the primary outline (visible on surface). */
.theme-bold .step > .step-actions .btn-primary:focus-visible,
.theme-bold .step > .step-actions .btn-link:focus-visible,
.theme-bold .site-footer a:focus-visible,
.theme-bold .site-header a.brand:focus-visible,
.theme-bold .time-btn:focus-visible {
  outline-color: var(--bc-surface);
}

/* ---- Bold theme polish ----
   The refinements that separate on-brand from designed: brand texture,
   editorial spacing, and component detailing. Same rules as the theme
   itself: --bc-* tokens only, no DOM changes, everything scoped under
   .theme-bold. */

/* Soft bubble decoration on the ground. Implemented as stacked
   radial-gradient layers on the body itself (NOT pseudo-elements, which
   either hide behind the body background at negative z-index or tint the
   panels above it). Centers sit in the margins outside the 720px content
   column; the only overlap is behind opaque panels, never behind ground
   copy, so the audited contrast pairs are untouched. Desktop-only: on a
   phone the column is the full viewport, and faint circles behind text
   are contrast risk with no payoff. No background-attachment: fixed -
   iOS Safari janks it. */
@media (min-width: 700px) {
  body.theme-bold {
    background-image:
      radial-gradient(circle 200px at 88% 60px, color-mix(in srgb, var(--bc-accent) 8%, transparent) 0 99%, transparent 100%),
      radial-gradient(circle 56px at 76% 240px, color-mix(in srgb, var(--bc-surface) 7%, transparent) 0 99%, transparent 100%),
      radial-gradient(circle 120px at 6% 420px, color-mix(in srgb, var(--bc-surface) 6%, transparent) 0 99%, transparent 100%),
      radial-gradient(circle 40px at 12% 300px, color-mix(in srgb, var(--bc-accent) 8%, transparent) 0 99%, transparent 100%),
      radial-gradient(circle 160px at 94% calc(100% - 180px), color-mix(in srgb, var(--bc-surface) 5%, transparent) 0 99%, transparent 100%);
  }
}

/* Editorial spacing: air between the stepper and the headline turns the
   heading into a hero moment instead of a form label. */
.theme-bold .site-header { padding-top: var(--space-xl); }
.theme-bold .step h1 { margin-top: var(--space-lg); }

/* The brand-site button: small caps, tracked out, confident. The base
   hover rule is untouched, so the @supports fallback contract holds. */
.theme-bold .btn-primary {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 700;
}

/* Stepper: a connector line joins the dots into one journey. Equal
   flex-basis makes every li the same width, which is what lets the
   pure-percentage connector geometry reach the previous dot; --pg mirrors
   the flex gap so the line spans it exactly at every breakpoint.

   The stepper is also the FROZEN BAR: it pins while the wizard scrolls -
   the one element worth a slice of a phone viewport, because it answers
   "where am I, how much is left" on every step. Full-bleed with an opaque
   primary background so the colour bands scroll cleanly under it (flex
   centering keeps the dots in the column; the full logo header
   deliberately does not pin - it would spend a quarter of a phone
   viewport on branding; body overflow-x: clip, not hidden, is what keeps
   sticky working under the bands). */
.theme-bold .progress {
  --pg: var(--space-lg);
  gap: var(--pg);
  position: sticky;
  top: 0;
  z-index: 60;
  margin-inline: calc(50% - 50vw);
  background: var(--bc-primary);
  padding: 12px var(--space-md) 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--bc-surface) 12%, transparent);
}
/* Step change focuses the h1; without a scroll margin the browser would
   scroll it up underneath the pinned stepper. */
.theme-bold .step h1 { scroll-margin-top: 96px; }
.theme-bold .progress li { flex: 0 1 96px; }
.theme-bold .progress li::before { z-index: 1; }
.theme-bold .progress li + li::after {
  content: '';
  position: absolute;
  top: 11px;
  height: 2px;
  right: calc(50% + 14px);
  left: calc(14px - 50% - var(--pg));
  border-radius: 2px;
  background: color-mix(in srgb, var(--bc-surface) 30%, transparent);
  z-index: 0;
}

/* Explainer steps: numbered chips instead of plain list markers. Ink
   chip, accent numeral - the ink/accent pair is already audited at
   5.5:1. The <ol> semantics survive; only the marker is painted. */
.theme-bold .how-it-works-steps {
  list-style: none;
  counter-reset: hiw;
  padding-left: 0;
  margin-top: var(--space-md);
}
.theme-bold .how-it-works-steps li {
  counter-increment: hiw;
  position: relative;
  padding-left: 38px;
  margin-bottom: 10px;
  min-height: 26px;
}
.theme-bold .how-it-works-steps li::before {
  content: counter(hiw);
  position: absolute;
  left: 0;
  top: 0;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-full);
  background: var(--bc-ink);
  color: var(--bc-accent);
  font-weight: 700;
  font-size: 0.8125rem;
  line-height: 26px;
  text-align: center;
}

/* Item prices earn brand-site weight: the price is the second thing a
   customer reads on a card. Primary on surface is the audited 5.9:1. */
.theme-bold .item-row-price {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--bc-primary);
}

@media (max-width: 520px) {
  .theme-bold .step h1 { font-size: 1.9rem; }
  /* The 13-area strip wrapped to three loud lines on a phone - too tall
     for a bar that now stays PINNED. One swipeable line instead:
     text-align left, because centered nowrap content overflows past the
     inline-start edge where no scroll can reach it. */
  .theme-bold .site-topbar {
    font-size: 0.6875rem;
    line-height: 1.7;
    padding: 5px 12px;
    white-space: nowrap;
    overflow-x: auto;
    text-align: left;
    scrollbar-width: none;
  }
  .theme-bold .site-topbar::-webkit-scrollbar { display: none; }
  .theme-bold .progress { --pg: var(--space-md); }
  /* Bands keep the reference site's generous rhythm at phone scale. */
  .theme-bold .how-it-works,
  .theme-bold .card,
  .theme-bold .summary { padding: 36px var(--space-lg) 44px; }
}

/* color-mix() fallbacks for the bold theme, mirroring the @supports block
   above: without color-mix the derived tokens are invalid, so pin the
   ground copy and re-derived text to plain tenant tokens. */
@supports not (color: color-mix(in srgb, red, blue)) {
  body.theme-bold {
    --bc-ground-ink-soft: var(--bc-surface);
    --bc-ink-muted: var(--bc-ink);
    --bc-accent-ink: var(--bc-ink);
    --bc-border: var(--bc-ink);
  }
  .theme-bold .site-topbar { background: var(--bc-ink); }
  .theme-bold .btn-primary:hover:not(:disabled) { background: var(--bc-accent); }
}
