/* Booking door — THEME-DRIVEN (ADR-0015 + shop theme system).
   The shop's chosen palette is stamped on <html data-theme> and defined in /shared/themes.css as
   canonical --pb-* vars. This file remaps the shared tokens (/shared/tokens.css) AND its own local
   --gold onto those canonical vars, so every shared component (.btn/.choice/.slot/.date-chip/
   .banner/.field) and the storefront re-skin automatically when the theme swaps — zero per-component
   work. Fonts are injected by app.js (installChrome). booking.css loads AFTER tokens.css + themes.css,
   so these later same-specificity rules win. */

html { background: var(--pb-bg); }

body {
  /* Palette remap — the whole app subtree inherits these, overriding tokens.css defaults. */
  --c-primary: var(--pb-accent);       /* accent — actions, highlights */
  --c-accent: var(--pb-accent);
  --c-on-primary: var(--pb-accent-ink);/* text on the accent */
  --c-bg: var(--pb-bg);                /* theme canvas */
  --c-surface: var(--pb-surface);      /* panels / cards */
  --c-ink: var(--pb-text);             /* body text */
  --c-muted: var(--pb-dim);            /* dim — AA on the canvas */
  --c-line: var(--pb-edge);            /* hairline edges */
  --c-danger: #FF7A6B;
  --c-ok: var(--pb-accent);
  --c-warn-bg: rgba(var(--pb-accent-rgb), .10);
  --c-danger-bg: rgba(255, 122, 107, .12);
  --c-ok-bg: rgba(var(--pb-accent-rgb), .08);

  /* Brand-kit font theme: --pb-font-heading/body are set by applyFontTheme() in brand.js.
     Falls back to the neon chrome pair (Michroma + Inter) when no font theme is selected. */
  --font-heading: var(--pb-font-heading, 'Michroma', system-ui, sans-serif);
  --font-body:    var(--pb-font-body,    'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);

  --gold: var(--pb-accent);
  --glow: 0 0 24px rgba(var(--pb-accent-rgb), .28);

  background: var(--pb-bg);
  color: var(--pb-text);
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;
}

/* Single soft accent haze anchored to the bottom of the viewport. Theme-aware: light themes
   set --pb-haze≈0 so the glow all but disappears. */
body::after {
  content: ""; position: fixed; left: 0; right: 0; bottom: 0; height: 38vh;
  z-index: 0; pointer-events: none;
  background: radial-gradient(120% 90% at 50% 130%, rgba(var(--pb-accent-rgb), var(--pb-haze)), transparent 70%);
}
.wrap { position: relative; z-index: 1; }

/* Display type. Michroma is a single-weight face — lean on letter-spacing, not weight. */
h1, h2, h3 { font-family: var(--font-heading); letter-spacing: .02em; }
h1 { font-size: 1.4rem; line-height: 1.25; }
/* One gold accent word per heading — the brand's signature (funnel review #46). */
h1 em { font-style: normal; color: var(--gold); text-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .35); }
.accent-rule { border-top-color: var(--gold); box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .5); }

/* Progress dot-segment bar (funnel review #45). */
.pdots { display: inline-flex; gap: .34rem; align-items: center; }
.pdot { width: 22px; height: 5px; border-radius: 3px; background: var(--c-line); transition: background .15s; }
.pdot-done { background: rgba(var(--pb-accent-rgb), .55); }
.pdot-cur { background: var(--gold); box-shadow: 0 0 8px rgba(var(--pb-accent-rgb), .6); }

/* ── 3-step booking wayfinder — storefront band + modal + checkout (Chris 2026-07-09) ── */
.bstep { list-style: none; display: flex; margin: 0; padding: 0; }
.bstep-i {
  flex: 1 1 0; min-width: 0; position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: .38rem;
}
.bstep-i + .bstep-i::before {
  content: ""; position: absolute; left: -50%; right: 50%; top: 12px; height: 2px;
  background: var(--pb-edge); z-index: 0;
}
.bstep-done + .bstep-i::before, .bstep-cur + .bstep-i::before { background: rgba(var(--pb-accent-rgb), .5); }
.bstep-dot {
  position: relative; z-index: 1; width: 25px; height: 25px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 12px; line-height: 1;
  border: 2px solid var(--pb-edge); background: var(--pb-bg); color: var(--pb-dim);
  transition: border-color .2s, background .2s, color .2s, box-shadow .2s;
}
.bstep-label { font-size: 11px; color: var(--pb-dim); line-height: 1.25; }
.bstep-cur .bstep-dot { border-color: var(--pb-accent); color: var(--pb-accent); box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .5); }
.bstep-cur .bstep-label { color: var(--pb-text); font-weight: 700; }
.bstep-done .bstep-dot { border-color: var(--pb-accent); background: var(--pb-accent); color: var(--pb-accent-ink); }
.bstep-done .bstep-label { color: var(--pb-text); }
/* Band — storefront, roomy */
.bstep--band { max-width: 560px; margin: 0 auto; }
.bstep--band .bstep-dot { width: 32px; height: 32px; font-size: 14px; }
.bstep--band .bstep-i + .bstep-i::before { top: 16px; }
.bstep--band .bstep-label { font-size: 13px; }
/* Desktop — ~2x so the numbers read clearly (Chris, 2026-07-09) */
@media (min-width: 768px) {
  .bstep--band { max-width: 760px; }
  .bstep--band .bstep-dot { width: 60px; height: 60px; font-size: 27px; border-width: 2.5px; }
  .bstep--band .bstep-i + .bstep-i::before { top: 30px; height: 3px; }
  .bstep--band .bstep-label { font-size: 18px; margin-top: .15rem; }
  /* Desktop order (Chris 2026-07-14): section-nav band first. The trust strip is dropped on desktop
     (waste of space) — it stays in the mobile DOM flow below the menu. The Next-openings calendar
     now sits below the gallery (Chris 2026-07-18), so it follows DOM order (no explicit order). */
  .menu-below { display: flex; flex-direction: column; }
  .menu-below > .m-trust { display: none; }
}

/* Context wrappers */
.m-book-steps { padding: 4px 0 6px; }
.bm-steps { padding: .85rem 1.1rem .2rem; }
.bk-topnav .bstep { flex: 1 1 auto; min-width: 0; margin-left: .6rem; }
.bk-topnav > .btn-link { flex: 0 0 auto; white-space: nowrap; }
/* "Start here" pulse on the Availability CTA */
.m-book-steps.pulse-once .bstep-cur .bstep-dot { animation: bstepPulse 1.7s ease-out 1; }
@keyframes bstepPulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--pb-accent-rgb), .55); }
  55% { box-shadow: 0 0 0 9px rgba(var(--pb-accent-rgb), 0); }
  100% { box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .5); }
}
@media (max-width: 380px) {
  .bstep-label { font-size: 10px; }
  .bstep--band .bstep-label { font-size: 11px; }
}

/* ── Shared-component accent polish (over the token remap) ── */
.btn-primary {
  box-shadow: 0 0 22px rgba(var(--pb-accent-rgb), .4), 0 10px 30px -12px rgba(var(--pb-accent-rgb), .6);
  letter-spacing: .01em;
}
.btn-primary:disabled { box-shadow: none; }
.btn-ghost, .btn-quiet { background: var(--c-surface); }
.btn-ghost:not(:disabled):active { border-color: var(--gold); color: var(--gold); }

.choice[aria-pressed="true"], .choice[aria-checked="true"] {
  box-shadow: inset 0 0 0 1px var(--gold), 0 0 18px rgba(var(--pb-accent-rgb), .18);
  background: linear-gradient(160deg, rgba(var(--pb-accent-rgb), .1), rgba(var(--pb-accent-rgb), .015));
}
.slot[aria-pressed="true"], .date-chip[aria-pressed="true"] { box-shadow: var(--glow); }
.slot:not([aria-pressed="true"]):active { border-color: var(--gold); color: var(--gold); }

.banner-warn { border-color: rgba(var(--pb-accent-rgb), .45); }
.banner-ok { border-color: rgba(var(--pb-accent-rgb), .45); }
.banner-danger { border-color: rgba(255, 122, 107, .5); }
.banner-ok strong { color: var(--gold); }

input::placeholder { color: var(--c-muted); opacity: .7; }

/* ── Booking chrome ── */
.bk-head { padding: 1.1rem 0 .4rem; }
.bk-shopname {
  font-family: var(--font-heading); font-size: 1.02rem; letter-spacing: .08em;
  color: var(--gold); text-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .18);  /* calmer (#52) */
}
/* Brand-kit logo — header slot: height-capped 28–32px, width auto, left of top bar. */
.bk-logo-header {
  display: block; height: 30px; width: auto; max-width: 160px;
  object-fit: contain; object-position: left center;
}
.bk-topnav {
  display: flex; justify-content: space-between; align-items: center;
  margin: .2rem 0 .4rem; min-height: var(--tap);
}
.bk-foot { padding: 2rem 0 1rem; text-align: center; }
/* Brand-kit logo — footer slot: centered, ~36px cap, grayscale-friendly. */
.bk-logo-footer-wrap { margin-bottom: .75rem; }
.bk-logo-footer {
  display: block; height: 36px; width: auto; max-width: 160px;
  margin: 0 auto; object-fit: contain; opacity: .75;
  filter: grayscale(20%);
}

.bk-avatar {
  flex: 0 0 auto; width: 3rem; height: 3rem; border-radius: 50%;
  object-fit: cover; background: #000; box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .4);
}
.bk-avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.2rem; color: var(--gold);
}

.bk-svc .bk-qty { margin: .4rem 0 .2rem .5rem; }
.bk-qty-n { font-weight: 700; min-width: 2.4rem; text-align: center; color: var(--gold); }
.bk-addon-h { margin-top: 1.2rem; }

/* Added-people cards (funnel review #8) — each is one back-to-back booking with its own service. */
.bk-people { margin-top: 1.2rem; }
.bk-person {
  border: 1px solid var(--c-line); border-radius: var(--radius-sm);
  padding: .7rem .8rem; margin-bottom: .6rem;
  background: color-mix(in srgb, var(--c-primary) 3%, var(--c-surface));
}
.bk-person-h { font-family: var(--font-heading); font-size: .82rem; letter-spacing: .02em; color: var(--gold); }
.bk-addperson { margin-top: .2rem; }

/* "Most popular" anchor badge (funnel review #58). */
.sfr-popular {
  display: inline-block; margin-left: .5rem; padding: .05rem .45rem; border-radius: 999px;
  font-family: var(--font-body); font-size: .62rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; vertical-align: middle;
  color: var(--pb-accent-ink); background: var(--gold);
}

.bk-sticky {
  position: sticky; bottom: 0; padding: .75rem 0 calc(.75rem + env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--c-bg) 72%, transparent);
}

.bk-review-when { font-family: var(--font-heading); font-size: 1.05rem; letter-spacing: .02em; }
.bk-review-time {
  font-size: 1.6rem; font-weight: 800; color: var(--gold);
  text-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .5);
}

.bk-success-mark {
  width: 3.4rem; height: 3.4rem; border-radius: 50%;
  background: var(--gold); color: var(--c-on-primary);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.8rem; font-weight: 700; margin-top: 1.2rem;
  box-shadow: 0 0 26px rgba(var(--pb-accent-rgb), .5);
}

/* ── Storefront (the shop's front door) ── */
.sf { padding-top: .5rem; }

.sf-hero {
  position: relative; border-radius: 18px; overflow: hidden;
  padding: 2.2rem 1.3rem; margin: .6rem 0 1.1rem;
  background:
    radial-gradient(140% 120% at 50% -10%, rgba(var(--pb-accent-rgb), .18), transparent 60%),
    linear-gradient(165deg, var(--pb-surface-2), var(--pb-surface));
  border: 1.5px solid rgba(var(--pb-accent-rgb), .55);
  box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .12), 0 18px 48px -16px rgba(var(--pb-accent-rgb), .45),
    inset 0 0 40px rgba(var(--pb-accent-rgb), .05);
  text-align: center;
}
.sf-eyebrow {
  font-family: var(--font-heading); font-size: .66rem; letter-spacing: .22em;
  text-transform: uppercase; color: var(--c-muted); margin-bottom: .55rem;
}
.sf-shopname {
  font-family: var(--font-heading); font-size: clamp(1.5rem, 7vw, 2.1rem); font-weight: 400;
  line-height: 1.12; margin: 0; color: var(--pb-text);
  text-shadow: 0 0 26px rgba(var(--pb-accent-rgb), .5);
}
.sf-tagline { margin: .6rem 0 0; color: var(--c-muted); font-size: .9rem; }

.sf-loc { display: flex; align-items: center; gap: .55rem; margin: 0 0 1.1rem; }
.sf-loc-main {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: .6rem;
  text-decoration: none; color: var(--c-ink);
  background: var(--c-surface); border: 1px solid var(--c-line); border-radius: 12px;
  padding: .55rem .65rem; min-height: var(--tap);
}
.sf-loc-main:active { border-color: rgba(var(--pb-accent-rgb), .55); }
.sf-pin {
  width: 28px; height: 28px; flex: none; border-radius: 50%;
  background: var(--gold); color: var(--pb-accent-ink);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .35);
}
.sf-addr {
  flex: 1; min-width: 0; font-size: .9rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sf-nav {
  flex: none; display: inline-flex; align-items: center; min-height: var(--tap);
  text-decoration: none; font-weight: 700; font-size: .82rem; color: var(--gold);
  border: 1px solid rgba(var(--pb-accent-rgb), .6); border-radius: 999px; padding: .5rem .85rem;
  box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .2), inset 0 0 8px rgba(var(--pb-accent-rgb), .08);
}

.sf-book {
  /* Calm panel — no gold border/haze/tint; the focal glow lives on the primary
     action (.sfr-acc-primary "Today") alone (funnel review #52 glow hierarchy). */
  border: 1px solid var(--c-line); border-radius: 18px; padding: 1.15rem 1rem;
  margin: 0 0 1.4rem;
  background: var(--c-surface);
  box-shadow: var(--pb-shadow);
}
.sf-book-h {
  /* Gold word, but no glow — panel stays calm so the action pops (#52). */
  font-family: var(--font-heading); font-size: 1.15rem; letter-spacing: .03em; color: var(--gold);
}
.sf-book-sub { color: var(--c-muted); font-size: .86rem; margin: .35rem 0 .95rem; }
.sf-book-btn { font-size: 1.05rem; }

.sf-team { margin: 0 0 1.2rem; }
.sf-team-h {
  font-family: var(--font-heading); font-size: .7rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--c-muted); margin: 0 0 .6rem;
}
.sf-prov {
  display: flex; align-items: center; gap: .8rem;
  background: var(--c-surface); border: 1px solid var(--c-line); border-radius: 14px;
  padding: .7rem .8rem;
}
.sf-prov-av {
  width: 3rem; height: 3rem; flex: none; border-radius: 50%; object-fit: cover;
  background: #000; box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .4);
}
.sf-prov-av-fb {
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.15rem; color: var(--gold);
}
.sf-prov-main { flex: 1; min-width: 0; }
.sf-prov-name { display: block; font-weight: 700; font-size: 1rem; }
.sf-prov-link {
  color: var(--gold); text-decoration: none;
  display: inline-flex; align-items: center; gap: .25rem;
}
.sf-prov-link:active { text-decoration: underline; }
.sf-prov-arrow { font-size: 1.2rem; line-height: 1; }
.sf-prov-bio { display: block; color: var(--c-muted); font-size: .85rem; margin-top: .1rem; }

.sf-links { text-align: center; margin-top: .4rem; }
.sf-ig {
  color: var(--gold); text-decoration: none; font-weight: 600; font-size: .88rem;
  display: inline-flex; min-height: var(--tap); align-items: center;
}
.sf-ig:active { text-decoration: underline; }

/* ── Rich storefront (config.storefront — the barber-benson design on the real engine).
   Ported 2026-07-06 from public/barber-benson/index.html (the approved static demo); colors ride
   the theme vars so any shop with storefront config gets its own palette. */

.sfr-head { display: flex; justify-content: space-between; align-items: center; gap: .8rem; padding: 1.2rem 0 1rem; }
.sfr-mark {
  /* A wordmark, not an action — no glow (funnel review #52 glow hierarchy). */
  font-family: var(--font-heading); font-size: 1.02rem; letter-spacing: .11em; line-height: 1.15;
}
.sfr-mark em { font-style: normal; color: var(--gold); }
.sfr-mark small {
  display: block; font-family: var(--font-body); font-size: .64rem; letter-spacing: .2em;
  text-transform: uppercase; color: var(--c-muted); margin-top: .35rem; text-shadow: none;
}
.sfr-call {
  flex: none; display: inline-flex; align-items: center; min-height: var(--tap);
  text-decoration: none; border: 1px solid rgba(var(--pb-accent-rgb), .7); color: var(--gold);
  border-radius: 10px; padding: .45rem .8rem; font-weight: 700; font-size: .84rem;
  box-shadow: inset 0 0 8px rgba(var(--pb-accent-rgb), .08);  /* secondary — no outer glow (#52) */
}

.sfr-hero {
  position: relative; height: 230px; border-radius: 16px; overflow: hidden; margin: .2rem 0 1.1rem;
  background: #000 center 20% / cover no-repeat;
  box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .35);  /* ring only — no outer haze (#52) */
}
.sfr-hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(6, 6, 8, .72), transparent 55%);
}
.sfr-hero b {
  position: absolute; left: .85rem; bottom: .75rem; z-index: 1;
  font-family: var(--font-heading); font-size: .82rem; letter-spacing: .1em;
  color: #fff; text-shadow: 0 1px 10px rgba(0, 0, 0, .9);
}

.sfr-book { padding-bottom: .6rem; margin-bottom: .7rem; }
.sfr-acc {
  display: block; width: 100%; border-radius: 12px; padding: .8rem .9rem; margin-bottom: .6rem;
  text-align: center; border: 1px solid var(--c-line); background: var(--c-surface);
  font: inherit; font-weight: 700; color: var(--c-ink); cursor: pointer; min-height: var(--tap);
}
.sfr-acc small { display: block; font-weight: 400; color: var(--c-muted); font-size: .78rem; margin-top: .1rem; }
.sfr-acc[aria-expanded="true"] { border-color: rgba(var(--pb-accent-rgb), .6); color: var(--gold); }
/* A visual open/closed cue — aria-expanded alone left the panel looking identical, so people
   re-tapped and collapsed it (funnel review #47). */
.sfr-acc { position: relative; }
.sfr-acc::after {
  content: '⌄'; position: absolute; right: 1rem; top: 50%; transform: translateY(-60%);
  font-size: 1.1rem; line-height: 1; transition: transform .15s ease; opacity: .7;
}
.sfr-acc[aria-expanded="true"]::after { transform: translateY(-40%) rotate(180deg); }
.sfr-acc-primary, .sfr-acc-primary[aria-expanded="true"] {
  background: var(--gold); color: var(--pb-accent-ink); border-color: var(--gold);
  box-shadow: 0 0 22px rgba(var(--pb-accent-rgb), .5);
}
/* .70 alpha clears WCAG 1.4.3 AA on the gold at this size (funnel review #48). */
.sfr-acc-primary small { color: rgba(0, 0, 0, .7); }
.sfr-reveal {
  border: 1px solid var(--c-line); border-radius: 12px; padding: .75rem;
  margin: -.2rem 0 .7rem; background: rgba(255, 255, 255, .015);
}
.sfr-reveal .date-strip { margin-bottom: .6rem; }

.sfr-cta2 {
  display: block; width: 100%; border-radius: 14px; padding: .85rem; text-align: center;
  font: inherit; font-weight: 700; font-size: .95rem; margin: 0 0 1.4rem; cursor: pointer;
  background: transparent; color: var(--gold); border: 1.5px solid rgba(var(--pb-accent-rgb), .55);
  box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .15); min-height: var(--tap);
}
.sfr-cta2:active { border-color: var(--gold); }

.sfr-h2 { font-family: var(--font-heading); font-size: 1.12rem; letter-spacing: .05em; line-height: 1.25; margin: .4rem 0 .3rem; }
.sfr-psub { font-size: .88rem; color: var(--c-muted); margin-bottom: .9rem; }
.sfr-egh {
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--c-muted); margin: .55rem 0 .35rem;
}
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
/* Day-part headers organize the slots — they must whisper, not outshine the times they label
   (funnel review #25). h2 semantics kept for AT navigation. */
.bk-part-h {
  font-family: var(--font-body); font-size: .72rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--c-muted); margin: .6rem 0 .1rem;
}

.sfr-bcard { border: 1px solid var(--c-line); border-radius: 14px; overflow: hidden; margin-bottom: 1.2rem; background: var(--c-surface); }
.sfr-bstrip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; height: 96px; }
.sfr-bstrip div { background: #000 center / cover no-repeat; }
.sfr-bmeta { display: flex; align-items: center; gap: .7rem; padding: .75rem .85rem; }
.sfr-bav {
  width: 44px; height: 44px; flex: none; border-radius: 50%;
  background: #000 center / cover no-repeat; box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .4);
  display: inline-flex; align-items: center; justify-content: center; color: var(--gold); font-weight: 700;
}
.sfr-bmeta b { display: block; font-size: .96rem; }
.sfr-bt { font-size: .78rem; color: var(--c-muted); }
.sfr-next { margin-left: auto; text-align: right; font-size: .76rem; font-weight: 700; color: var(--gold); white-space: nowrap; }
.sfr-next small { display: block; font-weight: 400; color: var(--c-muted); }

/* Services step: categories, thumbs, the package upsell */
.sfr-addh {
  /* Michroma detail collapses below ~13px — use the body face at label size so category
     headers stay legible (funnel review #51). */
  color: var(--c-muted); font-size: .8rem; letter-spacing: .14em; text-transform: uppercase;
  margin: 1rem 0 .55rem; font-family: var(--font-body); font-weight: 700;
}
.sfr-thumb {
  width: 52px; height: 52px; border-radius: 10px; flex: none;
  background: #000 center / cover no-repeat; box-shadow: 0 0 0 1px rgba(var(--pb-accent-rgb), .25);
}
/* "The Menu" note in the in-flow service picker (Chris 2026-07-14) — the complimentary-wash line
   under the title, mirroring the storefront menu's eyebrow copy. */
.sfr-menu-note { font-size: .86rem; line-height: 1.5; color: var(--c-muted); margin: 0 0 .4rem; }
.sfr-picked { font-size: .88rem; color: var(--gold); margin: 0; }
/* Keep the 44px tap floor — min-height:0 shrank this to ~21px (WCAG 2.5.8, funnel review #32). */
.sfr-picked .sfr-chg { color: var(--c-muted); font-size: .84rem; padding: .5rem .35rem; min-height: var(--tap); }

.sfr-pkgbox {
  border: 1px solid rgba(var(--pb-accent-rgb), .45); border-radius: 14px;
  padding: .85rem .85rem .55rem; margin: .1rem 0 .6rem;
  background: linear-gradient(140deg, rgba(var(--pb-accent-rgb), .08), transparent);
  box-shadow: inset 0 0 22px rgba(var(--pb-accent-rgb), .05);
}
.sfr-pkgh {
  font-family: var(--font-body); font-weight: 800; font-size: .82rem; letter-spacing: .06em; color: var(--gold);
  text-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .25);  /* calmer (#52) */
}
.sfr-pkgsub { font-size: .8rem; color: var(--c-muted); margin: .28rem 0 .7rem; }
.sfr-pkg {
  display: flex; gap: .6rem; width: 100%; align-items: center; text-align: left;
  background: var(--c-bg); border: 1.5px solid var(--c-line); border-radius: 12px;
  padding: .7rem .8rem; margin-bottom: .5rem; font: inherit; color: var(--c-ink); cursor: pointer;
  min-height: var(--tap);
}
.sfr-pkg[aria-pressed="true"] { border-color: var(--gold); box-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .2); }
.sfr-pkg b { display: block; }
.sfr-pkgd { color: var(--c-muted); font-size: .78rem; display: block; }
.sfr-pkgpr { margin-left: auto; color: var(--gold); font-weight: 800; white-space: nowrap; text-align: right; }
.sfr-pkgpr .sfr-save {
  display: block; font-size: .62rem; font-weight: 800; letter-spacing: .03em;
  color: var(--pb-accent-ink); background: var(--gold); border-radius: 999px;
  padding: .06rem .45rem; margin-top: .25rem;
}
.sfr-pkgjust {
  display: block; width: 100%; text-align: center; color: var(--c-muted); font-size: .82rem;
  font-weight: 600; padding: .5rem; border: 1px dashed var(--c-line); border-radius: 10px;
  margin-top: .1rem; background: none; font-family: inherit; cursor: pointer; min-height: var(--tap);
}
.sfr-pkgjust[aria-pressed="true"] { border-color: rgba(var(--pb-accent-rgb), .5); color: var(--gold); }

.sfr-footcall { color: var(--gold); text-decoration: none; }
.sfr-pb { opacity: .8; margin-top: .3rem; }
.sfr-callwide { text-decoration: none; }

/* ADR-0014 badge — "powered by PerfectBarber" on free-tier booking pages.
   Footer-weight, one line, tasteful: must not read as an ad or damage shop trust.
   Works on both light and dark themes via --pb-dim (muted text, readable at lower opacity). */
.pb-powered-by {
  display: inline-block;
  font-size: .72rem;
  color: var(--pb-dim, #9a948b);
  opacity: .65;
  text-decoration: none;
  letter-spacing: .02em;
}
.pb-powered-by:hover { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  #app > .wrap { animation: bk-in .18s ease-out; }
  @keyframes bk-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; } }
}

/* ══ DESKTOP full-bleed hero (approved 2026-07-08) ═══════════════════════════════
   Hidden on mobile — the mobile storefront is untouched. On desktop the .wrap breaks
   out to full width, the flipped photo hero is the first screen (Chelsea + chair right,
   wordmark + booking left), and the existing Book panel / services / barber card reflow
   into a centered column below. Buttons wire to the real engine (enterFlow / pickEntrySlot
   / the week accordion). Tokens are theme-driven, so it re-skins with any dark theme. */
.dhero, .mhero { display: none; }

/* Hero preview mode (?heroPreview=1): the dashboard Website editor iframes ONLY the hero as a
   WYSIWYG framing surface. Kill page scroll/chrome so the iframe is exactly one hero tall, and make
   it read as a display surface (the editor's overlay owns all interaction). See ADR-0020. */
body.is-hero-preview { margin: 0; overflow: hidden; }
.hero-preview { min-height: 100vh; }
.hero-preview a, .hero-preview button { cursor: default; }
.has-hero > .sfr-head { display: none; }             /* hero carries the wordmark + call (both breakpoints) */
.has-hero .sfr-body > .sfr-hero { display: none; }   /* small mobile photo redundant with the hero */

@media (min-width: 900px) {
  .wrap.sfr.has-hero { max-width: none; padding: 0; }
  .has-hero .sfr-body { max-width: 34rem; margin: 0 auto; padding: 1.6rem 1rem 4rem; }
  .wrap.sfr.has-hero > .bk-foot { max-width: 34rem; margin: 0 auto; }

  .dhero {
    display: block; position: relative; width: 100%; height: 100vh; min-height: 660px;
    overflow: hidden; background: var(--pb-bg);
  }
  .dh-photo { position: absolute; inset: 0; background: #000 50% 50% / cover no-repeat; }
  /* ADR-0023 tier-1 overlays: box-hugging effects live OUTSIDE the transformed photo layer.
     Opacity 0 by default; #hero-framing drives it from heroMedia.adjust. */
  .dh-vig { position: absolute; inset: 0; pointer-events: none; opacity: 0;
    background: radial-gradient(120% 100% at 50% 45%, transparent 52%, rgba(0,0,0,.62) 100%); }
  .dh-grain { position: absolute; inset: 0; pointer-events: none; opacity: 0; mix-blend-mode: overlay;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 240px 240px; }
  .dh-scrim {
    position: absolute; inset: 0;
    /* Scrim tint auto-derived from brand accent (brand-kit part 2).
       --pb-brand-scrim-rgb is set by applyBrandAccent() when an accent is configured;
       fallback 8,8,10 (near-black) when no accent is set. Geometry (stops/direction) is contract-locked. */
    background:
      linear-gradient(90deg, rgba(var(--pb-brand-scrim-rgb,8,8,10),.95) 26%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.68) 42%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.12) 60%, transparent 74%),
      linear-gradient(0deg, rgba(var(--pb-brand-scrim-rgb,8,8,10),.55), transparent 40%);
  }
  /* Group 1 — bottom-left desktop glow removed (2026-07-09: per SPEC.md Group 1) */
  .dh-haze { display: none; }

  .dh-top {
    /* Links left-anchor next to the address over the dark scrim (Chris 2026-07-14): flex-start
       keeps address + links grouped on the left; .dh-call is pushed to the right with margin-left:
       auto. space-between shoved the links into the bright center over the subject on a 27" monitor. */
    /* % (of the .dhero box), not vw — so the capped 2560 column places the bar the same as a 27"
       instead of pushing it inward on a 49" viewport (Chris 2026-07-14). Equals vw when full-bleed. */
    position: absolute; top: 2.4rem; left: 4.8%; right: 3%; z-index: 3;
    display: flex; justify-content: flex-start; align-items: flex-start; gap: 1rem;
  }
  .dh-brandleft { display: flex; flex-direction: column; gap: .6rem; align-items: flex-start; }
  .dh-addr {
    display: inline-flex; align-items: center; gap: .55rem; text-decoration: none; color: var(--pb-text);
    background: rgba(10,10,12,.5); border: 1px solid var(--pb-edge); border-radius: 999px;
    padding: .38rem .7rem .38rem .45rem; backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
  }
  .dh-addr:hover { border-color: rgba(var(--pb-accent-rgb), .55); }
  .dh-pin {
    width: 23px; height: 23px; flex: none; border-radius: 50%; background: var(--gold);
    color: var(--pb-accent-ink); display: inline-flex; align-items: center; justify-content: center;
    box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .4);
  }
  .dh-pin svg { width: 13px; height: 13px; }
  .dh-addrtxt { font-size: .83rem; font-weight: 600; letter-spacing: .02em; white-space: nowrap; }
  .dh-nav {
    font-size: .74rem; font-weight: 700; color: var(--gold);
    border-left: 1px solid var(--pb-edge); padding-left: .6rem; white-space: nowrap;
  }
  .dh-appt {
    font-family: var(--font-heading); font-size: .6rem; letter-spacing: .24em;
    text-transform: uppercase; color: var(--pb-dim); padding-left: .3rem;
  }
  /* Phone sits in the LEFT group beside the burger (Chris 2026-07-19) — it was pinned right with
     margin-left:auto and captioned "Call / Text". Number only now; tapping opens the chooser sheet.
     Height matches the 42px burger so the row reads as one control cluster. */
  .dh-call {
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    font-family: var(--font-body); font-weight: 800; font-size: 1rem; letter-spacing: .01em; color: var(--gold);
    background: rgba(8,8,10,.58); border: 1.5px solid rgba(var(--pb-accent-rgb), .4); border-radius: 999px;
    height: 42px; padding: 0 1.05rem; white-space: nowrap; flex: none;
    backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
    box-shadow: 0 8px 24px -8px rgba(0,0,0,.75), inset 0 0 16px rgba(var(--pb-accent-rgb), .05);
    transition: border-color .15s, color .15s;
  }
  .dh-call:hover { border-color: rgba(var(--pb-accent-rgb), .8); }
  /* Section jump-links sitting ON the hero, between the address and the call/text box
     (Chris 2026-07-14) — small type, no bar of their own. */
  .dh-navlinks { display: flex; align-items: center; gap: 2px; flex-wrap: nowrap; align-self: flex-start; margin-top: .28rem; }
  .dh-navlink {
    font-family: var(--font-heading); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
    font-weight: 600; color: var(--pb-text); background: none; border: 0; cursor: pointer;
    padding: 6px 11px; border-radius: 8px; white-space: nowrap; text-shadow: 0 1px 10px rgba(0,0,0,.75);
    transition: color .15s, background .15s;
  }
  .dh-navlink:hover { color: var(--gold); background: rgba(255,255,255,.07); }
  /* Hamburger row (Chris 2026-07-15): burger sits left of the address; its drawer carries the
     section jump-links that used to sit inline on the hero band. Reuses the mobile burger markup,
     re-styled here because the .mh-* rules live inside the mobile media query. */
  .dh-brandrow { display: flex; align-items: center; gap: .55rem; }
  .dh-brandleft .mh-menuwrap { position: relative; flex: none; }
  .dh-brandleft .mh-burger {
    display: inline-flex; flex-direction: column; justify-content: center; align-items: center; gap: 4px;
    width: 42px; height: 42px; cursor: pointer;
    background: rgba(10,10,12,.5); border: 1px solid var(--pb-edge); border-radius: 999px;
    backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
  }
  .dh-brandleft .mh-burger:hover { border-color: rgba(var(--pb-accent-rgb), .55); }
  .dh-brandleft .mh-burger-bar { display: block; height: 2px; width: 18px; border-radius: 2px; background: var(--pb-text); }
  .dh-brandleft .mh-menu {
    position: absolute; top: calc(100% + 8px); left: 0; z-index: 8; display: none;
    flex-direction: column; min-width: 210px; padding: 6px;
    background: rgba(12,12,14,.97); border: 1px solid var(--pb-edge); border-radius: 14px;
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 20px 44px -14px rgba(0,0,0,.85);
  }
  .dh-brandleft .mh-menuwrap.open .mh-menu { display: flex; }
  .dh-brandleft .mh-menu-link {
    text-align: left; font-family: var(--font-heading); font-weight: 400; font-size: .74rem; letter-spacing: .08em;
    text-transform: uppercase; color: var(--pb-text); background: none; border: 0; border-radius: 9px;
    padding: 11px 12px; cursor: pointer; white-space: nowrap;
  }
  .dh-brandleft .mh-menu-link:hover { background: rgba(var(--pb-accent-rgb), .14); color: var(--gold); }
  /* Credential line under the reviews proof (Chris 2026-07-15): barber-pole glyph + "Red Seal
     Barber · Since 2016", replacing the bio paragraph on the hero (the full bio stays in About). */
  .dh-cred {
    display: inline-flex; align-items: center; gap: .5rem;
    font-family: var(--font-heading); font-size: .78rem; letter-spacing: .04em; color: var(--pb-text);
    margin: 0 0 1.9rem; text-shadow: 0 1px 10px rgba(0,0,0,.7);
  }
  .dh-cred svg { flex: none; }
  /* Divider between the reviews proof and the credential on the shared hero line (Chris 2026-07-15):
     " | " — a pipe with breathing room on either side. Dim so the two proofs still lead. */
  .hero-credsep {
    display: inline-block; margin: 0 .55rem; color: var(--pb-dim);
    font-size: .8rem; vertical-align: baseline; text-shadow: 0 1px 10px rgba(0,0,0,.6);
  }

  .dh-copy { position: absolute; left: 4.8%; top: 50%; transform: translateY(-50%); z-index: 3; max-width: 46ch; }
  /* Brand-kit logo — hero slot (desktop): small logo above the wordmark block, ~48px height cap. */
  .dh-logo-hero {
    display: block; height: 48px; width: auto; max-width: 180px;
    object-fit: contain; object-position: left center; margin-bottom: 1rem;
  }
  .dh-mark {
    font-family: var(--font-heading); font-weight: 400; font-size: 4.5rem; line-height: .98; letter-spacing: .02em;
    color: var(--pb-text); text-shadow: 0 2px 34px rgba(0,0,0,.65);
  }
  /* Group 1 — gold glow halved (.42 → .21, per SPEC.md Group 1) */
  .dh-mark em { font-style: normal; color: var(--gold); text-shadow: 0 0 34px rgba(var(--pb-accent-rgb), .21); }
  .dh-rule {
    width: 70px; height: 2px; background: var(--gold); margin: 1.8rem 0 1.5rem;
    box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .6);
  }
  .dh-tag {
    font-family: var(--font-heading); font-size: 1.22rem; letter-spacing: .04em; color: var(--pb-text);
    margin: 0 0 .9rem; line-height: 1.25; text-shadow: 0 2px 14px rgba(0,0,0,.7);
  }
  .dh-tag em { font-style: normal; color: var(--gold); }
  .dh-bio {
    font-family: var(--font-body); font-size: .92rem; line-height: 1.55; color: var(--pb-dim);
    max-width: 44ch; margin: 0 0 1.9rem; text-shadow: 0 1px 10px rgba(0,0,0,.7);
  }

  /* Stacked-ladder CTA: next-opening eyebrow → full-width Book primary → even ghost row. */
  .dh-eyebrow {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem;
    font-size: .66rem; letter-spacing: .2em; text-transform: uppercase; color: var(--pb-dim);
    margin-bottom: 1.15rem;
  }
  .dh-eyeslot {
    font: inherit; letter-spacing: .14em; font-weight: 800; color: var(--gold); cursor: pointer;
    background: none; border: 0; padding: 0; text-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .4);
  }
  .dh-eyeslot:hover { text-decoration: underline; text-underline-offset: 3px; }
  .dh-qload { color: var(--pb-dim); }

  .dh-cta { display: block; max-width: 25rem; }
  /* Group 1 — dh-book glow halved (.4/.6 → .2/.3, per SPEC.md Group 1) */
  /* Gold-outline pill in the brand (Michroma) heading font (Chris 2026-07-15): matches the
     "Reserve your chair" reference shape — thin gold border, dark fill, spaced gold lettering —
     while wearing the same typeface as the "Barber Benson" wordmark. */
  /* Shine + bold (Chris 2026-07-15): a glossy top highlight over the pill + brighter gold glow so
     the primary CTA catches the eye; label bolded to 700. */
  .dh-book {
    display: block; width: 100%; text-align: center; margin-bottom: .8rem;
    font-family: var(--font-heading); font-weight: 700; font-size: .92rem; letter-spacing: .06em; color: var(--gold); cursor: pointer;
    background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,0) 44%), rgba(10,10,12,.45);
    border: 1.5px solid rgba(var(--pb-accent-rgb), .7); border-radius: 999px; padding: 1.05rem 2.2rem;
    box-shadow: 0 0 30px rgba(var(--pb-accent-rgb), .22), inset 0 1px 0 rgba(255,255,255,.22), inset 0 0 20px rgba(var(--pb-accent-rgb), .06);
    transition: box-shadow .2s ease, transform .15s ease, border-color .2s ease, background .2s ease;
  }
  .dh-book:hover {
    transform: translateY(-2px); border-color: var(--gold);
    background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,0) 44%), rgba(var(--pb-accent-rgb), .12);
    box-shadow: 0 0 44px rgba(var(--pb-accent-rgb), .36), inset 0 1px 0 rgba(255,255,255,.3), inset 0 0 24px rgba(var(--pb-accent-rgb), .1);
  }
  .dh-book:active { transform: translateY(0); }
  .dh-duo { display: grid; grid-template-columns: 1fr 1fr; gap: .8rem; }
  .dh-services {
    width: 100%; text-align: center;
    font-family: var(--font-body); font-weight: 700; font-size: .98rem; color: var(--gold); cursor: pointer;
    /* Full pill (Chris 2026-07-15): match the Book + Available pills' 999px shape — was a 14px chip. */
    background: transparent; border: 1.5px solid rgba(var(--pb-accent-rgb), .55); border-radius: 999px; padding: .95rem 1rem;
  }
  .dh-services:hover { border-color: var(--gold); }
}

/* Narrow desktops: keep the wordmark from crowding the photo. */
@media (min-width: 900px) and (max-width: 1180px) {
  .dh-mark { font-size: 3.6rem; }
  .dh-copy { max-width: 40ch; }
  /* Tighten the section links so address + links + call/text still fit one row when left-anchored. */
  .dh-navlink { font-size: .6rem; padding: 5px 8px; letter-spacing: .08em; }
}

/* C4 — Ultrawide type ramp (2026-07-13): at ≥2560px the text block stays small on a vast
   canvas. Scale headline, tagline, and CTAs conservatively — cap at ~1.6× of the 1920
   size. max-width on .dh-copy prevents the block hugging the far edge at 5120. The photo
   framing and bucket logic are untouched (v5 head-safe defaults stay). */
@media (min-width: 2560px) {
  .dh-mark  { font-size: 6rem; }
  .dh-tag   { font-size: 1.55rem; }
  .dh-bio   { font-size: 1.05rem; }
  .dh-book  { font-size: 1.2rem; }
  .dh-services { font-size: 1.1rem; }
  .dh-cta   { max-width: 30rem; }
  .dh-copy  { max-width: 52ch; }
  .dh-rule  { width: 90px; margin: 2.2rem 0 1.9rem; }
}
@media (min-width: 3440px) {
  .dh-mark  { font-size: 6.8rem; }
  .dh-tag   { font-size: 1.7rem; }
  .dh-bio   { font-size: 1.12rem; }
  .dh-book  { font-size: 1.3rem; }
  .dh-services { font-size: 1.18rem; }
  .dh-cta   { max-width: 33rem; }
  .dh-copy  { max-width: 58ch; left: 5.2vw; }
}
/* Hard cap: 5120 gets the same values as 3440 (no further scale — 1.6× is the ceiling) */
/* The capped storefront (.menu-sf, max 2560px) must NOT take the full-bleed ultrawide type ramp:
   at ≥2560px its box is still only 2560px wide, so the ramp over-sized the wordmark/copy on a 49"
   (Chris 2026-07-14). Revert to the base desktop proportions inside the capped column. Non-menu
   full-bleed heroes keep the ramp. */
@media (min-width: 2560px) {
  .menu-sf .dh-mark  { font-size: 4.5rem; }
  .menu-sf .dh-tag   { font-size: 1.22rem; }
  .menu-sf .dh-bio   { font-size: .92rem; }
  .menu-sf .dh-book  { font-size: 1.05rem; }
  .menu-sf .dh-services { font-size: .98rem; }
  .menu-sf .dh-cta   { max-width: 25rem; }
  .menu-sf .dh-copy  { max-width: 46ch; left: 4.8%; }
  .menu-sf .dh-rule  { width: 70px; margin: 1.8rem 0 1.5rem; }
}

/* ══ F3 — ultrawide hero full-bleed (Chris 2026-07-21) ═══════════════════════════
   .menu-sf caps the WHOLE storefront column (hero + below-hero "Menu" content) at 2560px so it
   letterboxes like YouTube on huge monitors (see .menu-sf / .wrap.sfr.has-hero.menu-sf above).
   That used to cap the hero PHOTO too — a 49"/5120px screen got the same crop as a 27". Now only
   the .dhero PHOTO box breaks back out to the real viewport width; the below-hero column keeps its
   2560 cap untouched (no seam — .dhero is the only element that reaches past its .menu-sf parent).
   Reuses the exact full-bleed technique already used by the mobile hero below (width:100vw +
   negative margin out of the wrap). Non-menu-sf shops are already width:100% of an uncapped
   .wrap.sfr.has-hero (line ~513), so this is a no-op for them — kept generic across the shared
   engine, not menu-sf-scoped. app.js (heroFramingStyle, HERO_CAP/ULTRA_ASPECT) mirrors this. */
@media (min-width: 2561px) {
  .dhero { width: 100vw; margin-left: calc(-50vw + 50%); }
}
/* F3 aspect-ratio escape hatch: past 3:1 (32:9 super-ultrawide, e.g. 5120×1440 ≈ 3.56:1) the box
   is so wide relative to its height that `cover` crops the subject's body no matter how the frame
   is tuned. Abandon full-bleed here — center the PHOTO layer at a capped ~3200px column (glow
   fills the letterboxed sides) while .dhero itself stays full-bleed so .dh-scrim/.dh-vig/.dh-grain
   (separate inset:0 layers) still cover the full width. Only .dh-photo's box is touched — its
   `transform`/`background-*` stay under app.js's control (the injected #hero-framing style wins
   the cascade for those props; we only set left/width/margin here, which it never sets). Must
   match ULTRA_ASPECT_CAP in app.js exactly so the delivered image size matches the rendered box. */
@media (min-width: 2561px) and (min-aspect-ratio: 3/1) {
  .dhero {
    background: radial-gradient(120% 100% at 50% 50%, rgba(var(--pb-accent-rgb, 255, 209, 102), .16), var(--pb-bg) 62%);
  }
  .dh-photo {
    left: 50%; right: auto; width: min(3200px, 100vw);
    margin-left: calc(min(3200px, 100vw) * -0.5);
  }
}

/* ══ MOBILE hero (M5 "poster", approved 2026-07-09) — shown < 900px ══════════════
   Full-bleed photo (breaks out of the .wrap padding), wordmark + tagline top-left above
   Chelsea, booking block just below her feet. Same real hooks as the desktop hero. */
@media (max-width: 899.98px) {
  .mhero {
    display: block; position: relative;
    width: 100vw; margin-left: calc(-50vw + 50%);      /* full-bleed out of the .wrap padding */
    /* svh, not vh: iOS Safari resolves 100vh to the LARGE viewport (toolbar collapsed), which hides
       the hero's bottom ~140px behind the toolbar at load (iPhone 17 Pro Max report, 2026-07-13).
       svh sizes to the visible area; the vh declaration stays as the fallback for engines without svh. */
    height: 100vh; height: 100svh;
    min-height: 620px; overflow: hidden; background: #000; margin-bottom: 1.2rem;
  }
  /* TOP-anchored cover (2026-07-10): center-anchored cover cropped the vertical overflow from
     BOTH edges on short/wide phones (360×640, 375×667…), slicing Chelsea's head off under the
     phone pill. The photo is framed with her head ~9% from the image top, so anchoring the crop
     to the top keeps her head at ~9% of the scaled height (~69–83px) — always below the ~50px
     top bar on every screen size; overflow now crops only the floor at the bottom (scrim-hidden).
     Also stops the photo re-centering jump when iOS Safari's URL bar collapses. */
  .mh-photo { position: absolute; inset: 0; background: #000 50% 0 / cover no-repeat; }
  /* ADR-0023 tier-1 overlays (see .dh-vig/.dh-grain) */
  .mh-vig { position: absolute; inset: 0; pointer-events: none; opacity: 0;
    background: radial-gradient(130% 100% at 50% 42%, transparent 50%, rgba(0,0,0,.62) 100%); }
  .mh-grain { position: absolute; inset: 0; pointer-events: none; opacity: 0; mix-blend-mode: overlay;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 240px 240px; }
  .mh-scrim { position: absolute; inset: 0;
    /* Scrim tint auto-derived from brand accent — same var as desktop, fallback near-black. Geometry locked. */
    background: linear-gradient(to bottom, rgba(var(--pb-brand-scrim-rgb,8,8,10),.7), transparent 22%, transparent 40%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.9) 78%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.99)); }
  .mh-haze { position: absolute; left: 0; right: 0; bottom: 0; height: 40%; pointer-events: none;
    background: radial-gradient(70% 90% at 50% 130%, rgba(var(--pb-accent-rgb), .16), transparent 70%); }
  .mh-top { position: absolute; top: 1rem; left: 1rem; right: 1rem; z-index: 4; display: flex; justify-content: space-between; align-items: flex-start; gap: .5rem; }
  .mh-addr { display: inline-flex; align-items: center; gap: .4rem; text-decoration: none; color: var(--pb-text);
    background: rgba(10,10,12,.5); border: 1px solid var(--pb-edge); border-radius: 999px; padding: .34rem .6rem .34rem .4rem; backdrop-filter: blur(5px);
    min-width: 0; flex: 0 1 auto;          /* shrinks + ellipsizes so it never crushes the phone box */
    position: relative; }
  .mh-addr::after { content: ""; position: absolute; inset: -5px 0; }  /* ~44px hit area (audit 2026-07-12) */
  .mh-pin { width: 20px; height: 20px; flex: none; border-radius: 50%; background: var(--gold); color: var(--pb-accent-ink); display: inline-flex; align-items: center; justify-content: center; }
  .mh-pin svg { width: 12px; height: 12px; }
  .mh-addrtxt { font-size: .72rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  .mh-nav { font-size: .66rem; font-weight: 700; color: var(--gold); border-left: 1px solid var(--pb-edge); padding-left: .45rem; white-space: nowrap; }
  /* Call/text box slightly smaller (Chris 2026-07-14) to make room for the hamburger + address. */
  /* Phone: number only (2026-07-19), back on the FAR RIGHT (Chris 2026-07-21) — the button that
     opens the Call-or-Text sheet. 44px-class tap target (38px min-height + hit padding). */
  .mh-call { display: inline-flex; align-items: center; justify-content: center; font-weight: 800;
    font-size: .92rem; color: var(--gold); cursor: pointer; min-height: 38px;
    background: rgba(8,8,10,.55); border: 1.5px solid rgba(var(--pb-accent-rgb), .4); border-radius: 11px;
    padding: .3rem .7rem; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    flex: none; white-space: nowrap; }        /* locked: the phone box never wraps or shrinks */
  /* Hamburger + section menu (Chris 2026-07-14). Single row again (Chris 2026-07-21): burger +
     address left, phone right. Three items fit at 360px ONLY because mh-toprow/mh-addr shrink
     and the address text ellipsizes — min-width:0 down the chain is what makes that work. */
  .mh-toprow { display: inline-flex; align-items: center; gap: .5rem; min-width: 0; flex: 0 1 auto; }
  .mh-menuwrap { position: relative; flex: none; }
  .mh-burger { display: inline-flex; flex-direction: column; justify-content: center; gap: 4px;
    width: 40px; height: 38px; padding: 0 11px; cursor: pointer;
    background: rgba(10,10,12,.5); border: 1px solid var(--pb-edge); border-radius: 11px;
    backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px); }
  .mh-burger-bar { display: block; height: 2px; width: 18px; border-radius: 2px; background: var(--pb-text); }
  .mh-menu { position: absolute; top: calc(100% + 8px); left: 0; z-index: 8; display: none;
    flex-direction: column; min-width: 200px; padding: 6px;
    background: rgba(12,12,14,.97); border: 1px solid var(--pb-edge); border-radius: 14px;
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 20px 44px -14px rgba(0,0,0,.85); }
  .mh-menuwrap.open .mh-menu { display: flex; }
  .mh-menu-link { text-align: left; font-family: var(--font-body); font-weight: 700; font-size: .92rem;
    color: var(--pb-text); background: none; border: 0; border-radius: 9px; padding: 11px 12px;
    cursor: pointer; min-height: 44px; }
  .mh-menu-link:active { background: rgba(var(--pb-accent-rgb), .14); color: var(--gold); }
  /* C6 density pass (2026-07-13): text block anchored top-left, bounded max-height so the
     tagline can't drift into the subject's face zone. Tighter vertical rhythm throughout.
     mh-head grows downward (overflow:hidden + max-height) — the photo subject always keeps
     her face above the text block. mh-stack raised from 61.5% to 64% for more air. */
  /* F1 fix (visual audit 2026-07-21): top bumped 4.2rem → 6.5rem. .mh-top (the burger+phone row
     plus, when an address is set, the stacked address-pill row added 2026-07-19) is absolutely
     positioned starting at top:1rem and reaches ~92px tall (38px row + .45rem gap + ~33px pill
     row) at every phone width — those two rows are fixed-px, not viewport-scaled. .mh-head used
     to start at 4.2rem (67px), landing its first line (.mh-appt, "By appointment only") in the
     SAME band as the address pill; the pill's higher z-index (4 vs 3) painted over the label on
     all 12 audited phone widths. 6.5rem clears the tallest possible .mh-top with margin to spare. */
  .mh-head { position: absolute; left: 1.3rem; right: 1.3rem; top: 6.5rem; z-index: 3; text-align: left;
    max-height: 52%; overflow: hidden; }
  /* Brand-kit logo — hero slot (mobile): small logo above the wordmark, ~48px height cap.
     max-height applied to parent (.mh-head) keeps it within the C6 density bounds. */
  .mh-logo-hero {
    display: block; height: 40px; width: auto; max-width: 140px;
    object-fit: contain; object-position: left center; margin-bottom: .55rem;
  }
  /* Stronger local scrim behind the text lines — gradient drops faster than before, leaving
     the mid-section (subject zone) clean. C6 density pass override — tint auto-derived from accent. */
  /* F4 fix (visual audit 2026-07-21): the dark-floor stop moved 78%→60% (opacity value unchanged)
     so the scrim is already near-opaque by .mh-stack's own top (64%), giving the CTA row (quick
     slot + Book/Services buttons) solid contrast against the photo instead of competing with it.
     The transparent 32%-42% "subject zone" band (keeps the face/torso clean) is untouched — this
     only accelerates darkening BELOW that band, where the CTAs already lived. */
  .mh-scrim { position: absolute; inset: 0;
    background: linear-gradient(to bottom, rgba(var(--pb-brand-scrim-rgb,8,8,10),.82) 0%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.55) 18%, transparent 32%, transparent 42%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.9) 60%, rgba(var(--pb-brand-scrim-rgb,8,8,10),.99) 100%); }
  /* Type ladder scales with viewport width (clamps cap at the approved 390px+ sizes, so wide
     phones are pixel-identical): fixed sizes let the eyebrow/wordmark/tagline swallow the photo
     on 320-360px screens (2026-07-10). */
  .mh-appt { font-family: var(--font-body); font-weight: 800; font-size: clamp(.56rem, 2.9vw, .66rem); letter-spacing: .2em; text-transform: uppercase; color: var(--gold); margin-bottom: .45rem; text-shadow: 0 1px 8px rgba(0,0,0,.8); }
  .mh-mark { font-family: var(--font-heading); font-size: clamp(2rem, 10.5vw, 2.5rem); line-height: .96; letter-spacing: .03em; color: var(--pb-text); text-shadow: 0 2px 22px rgba(0,0,0,.75); }
  /* Group 1 — mobile mark glow halved (.42 → .21, per SPEC.md Group 1) */
  .mh-mark .g { display: block; color: var(--gold); text-shadow: 0 0 28px rgba(var(--pb-accent-rgb), .21); margin-top: .08rem; }
  .mh-tag { font-family: var(--font-heading); font-size: clamp(.73rem, 3.6vw, .86rem); letter-spacing: .04em; color: var(--pb-text); margin: .42rem 0 0; text-shadow: 0 2px 12px rgba(0,0,0,.85); }
  .mh-tag em { font-style: normal; color: var(--gold); }
  .mh-stack { position: absolute; left: 1.3rem; right: 1.3rem; top: 64%; z-index: 3; text-align: center; }
  /* F4 fix (visual audit 2026-07-21): justify-content was `center`. .mh-l + .mh-slot(min-width
     5.5rem) + the "Available now?" pill are flex:none/min-width — on narrow phones (~360-393px)
     their combined width exceeds .mh-stack's inset box, and nowrap+center overflows SYMMETRICALLY
     on both sides, bleeding the "BOOK NEXT SLOT →" label left past the 1.3rem gutter to the raw
     viewport edge (0px). flex-start anchors the row to the gutter instead — on phones where the
     row fits, it now sits left-aligned rather than dead-center (consistent with the rest of the
     hero's left-aligned type), and on phones where it doesn't fit, only the right side overflows,
     never the left. See also the ≤400px tightening below (mh-l letter-spacing) which shrinks the
     row's intrinsic width so overflow is rarer in the first place. */
  .mh-quick { display: flex; flex-wrap: nowrap; justify-content: flex-start; align-items: center; gap: .55rem; margin-bottom: 1.2rem; }
  /* Mobile review 2026-07-13 P2: ~10px on a busy photo read as near-invisible — a touch larger
     plus a dark halo so it holds up over any hero crop. */
  .mh-l { font-family: var(--font-body); font-weight: 800; font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); flex: none;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .8); }
  /* nowrap + hidden + ellipsis: the time must NEVER stack ("11:00" / "AM" wrapped inside the chip
     on 360px phones — 2026-07-10). fitOneLine() in app.js steps the font down (floor 11px) until
     the text fits one row; the ellipsis only ever shows in the sub-330px + longest-label extreme. */
  .mh-slot { font-family: var(--font-body); font-weight: 800; font-size: .98rem; color: var(--pb-text); cursor: pointer;
    border: 1.5px solid var(--gold); border-radius: 10px; padding: .45rem 1rem; background: rgba(var(--pb-accent-rgb), .06);
    flex: 1; min-width: 5.5rem; box-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .16);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    min-height: 44px; }   /* 44px tap minimum (audit 2026-07-12) — was ~35px */
  .mh-load { font-size: .8rem; color: var(--pb-dim); }
  /* nowrap: "Availability ›" split onto two lines at 320px (same wrap bug as the time chip);
     one line fits at every width now that the chip's fitOneLine slims the row (2026-07-10). */
  .mh-cal { font-family: var(--font-body); font-weight: 700; font-size: .74rem; color: var(--gold); text-decoration: underline; background: none; border: 0; cursor: pointer; white-space: nowrap;
    position: relative; }
  /* invisible hit-area extension to ~44px without moving the locked one-row layout (audit 2026-07-12) */
  .mh-cal::after { content: ""; position: absolute; inset: -14px -6px; }
  /* Group 1 — mh-book glow halved (.45 → .225, per SPEC.md Group 1) */
  /* Gold-outline pill + brand heading font (Chris 2026-07-15) — mirrors the desktop .dh-book restyle. */
  /* Shine + bold (Chris 2026-07-15) — mirrors the desktop .dh-book restyle: glossy top highlight,
     brighter glow, label bolded to 700. */
  .mh-book { display: block; width: 100%; font-family: var(--font-heading); font-weight: 700; font-size: .9rem; letter-spacing: .07em; color: var(--gold); cursor: pointer;
    background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,0) 44%), rgba(10,10,12,.45); border: 1.5px solid rgba(var(--pb-accent-rgb), .7); border-radius: 999px; padding: 1.05rem 1rem; text-align: center; box-shadow: 0 0 26px rgba(var(--pb-accent-rgb), .22), inset 0 1px 0 rgba(255,255,255,.22), inset 0 0 18px rgba(var(--pb-accent-rgb), .06); margin-bottom: .6rem; }
  .mh-svc { display: block; width: 100%; font-family: var(--font-body); font-weight: 700; font-size: .96rem; color: var(--gold); cursor: pointer;
    background: transparent; border: 1.5px solid rgba(var(--pb-accent-rgb), .5); border-radius: 999px; padding: .85rem; text-align: center; }
  /* Owner bio under the Services button (mobile) — left-aligned to the button edge. */
  .mh-bio { font-family: var(--font-body); font-size: .76rem; line-height: 1.5; color: var(--pb-dim);
    margin: 1rem 0 0; text-align: left; text-shadow: 0 1px 8px rgba(0,0,0,.85); }
  /* Credential line (Chris 2026-07-15): barber-pole glyph + "Red Seal Barber · Since 2016". */
  .mh-cred { display: inline-flex; align-items: center; gap: .4rem; font-family: var(--font-heading);
    font-size: .72rem; letter-spacing: .03em; color: var(--pb-text); margin: 1rem 0 0;
    text-shadow: 0 1px 8px rgba(0,0,0,.85); }
  .mh-cred svg { flex: none; }
}

/* Standard & smaller phones: drop the redundant "Navigate ›" so the full address fits before it
   ellipsizes (the whole address pill still opens Maps). Kept on large phones (>400px). Phone box
   stays locked either way. The quick-slot chip also slims its side padding so the fall-forward
   label ("10:30 AM tomorrow") fits one row at the 11px font floor (2026-07-10). */
@media (max-width: 400px) {
  .mh-nav { display: none; }
  .mh-slot { padding: .45rem .6rem; }
  /* F4 fix (visual audit 2026-07-21): tighten the "BOOK NEXT SLOT →" label's letter-spacing at the
     narrowest phones so .mh-quick's nowrap row is less likely to overflow its 1.3rem gutter at all
     (belt-and-braces alongside the flex-start change above). */
  .mh-l { letter-spacing: .08em; }
}

/* ══ "The Menu" below-hero storefront (Barber Benson, approved 2026-07-09) ════════════════════
   Replaces the old redundant below-hero column (location bar + book panel + Services + tagline +
   barber card) with the approved "The Menu" section. Gated by config.storefront.layout==='menu'
   in app.js (viewStorefrontRich) — tenants without it are untouched. Ported from
   design/storefront-below-hero-2026-07-09/d2-menu.html. The mockup's local color names are remapped
   to the theme tokens so it rides the shop palette; the gold-glow rgba() literals are tuned to
   Barber Benson's accent (255,209,102) and stay literal. All classes are .menu-sf-scoped in the DOM
   so nothing here can touch other storefronts. */
.menu-sf {
  /* Cap the whole storefront COLUMN on ultrawide monitors so the below-hero "Menu" content doesn't
     stretch edge-to-edge — centered column with dark side borders, like YouTube (Chris 2026-07-14,
     49" 5120px). Below 2560px this is a no-op (content is narrower). F3 (2026-07-21): the hero
     PHOTO itself is exempted from this cap and goes full-bleed above 2560px — see the
     "F3 — ultrawide hero full-bleed" rule further down (.dhero breaks back out via negative margin,
     same trick as the mobile hero) — only the below-hero column stays capped here. */
  max-width: 2560px; margin-inline: auto; padding: 0;
  --bg: var(--pb-bg); --panel: var(--pb-surface); --edge: var(--pb-edge);
  --txt: var(--pb-text); --dim: var(--pb-dim); --gold: var(--pb-accent);
  --disp: var(--font-heading); --body: var(--font-body);
}
/* The has-hero storefront zeroes max-width via `.wrap.sfr.has-hero` (3-class, @900) — this 4-class
   selector re-asserts the ultrawide cap so the centered column + dark borders actually apply. */
.wrap.sfr.has-hero.menu-sf { max-width: 2560px; margin-inline: auto; }
.m-wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }

/* Trust bar */
/* ── Availability bar — proof-of-openings chips at the top of The Menu (Chris 2026-07-11) ── */
.m-avail { padding: 16px 0 4px; }
.m-avail-inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 16px;
  background: var(--panel); border: 1px solid rgba(var(--pb-accent-rgb), .35);
  border-radius: 16px; padding: 14px 18px;
}
.m-avail-label {
  font-family: var(--disp); font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 700; color: var(--gold);
}
.m-avail-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.m-avail-chip {
  font-family: var(--font-body); font-weight: 700; font-size: 14px; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .07); border: 1.5px solid rgba(var(--pb-accent-rgb), .55);
  border-radius: 999px; padding: 8px 18px; cursor: pointer;
  transition: background .15s, box-shadow .15s;
  /* 44px minimum tap height (audit 2026-07-12) — the chips ARE the conversion path */
  min-height: 44px; display: inline-flex; align-items: center;
}
.m-avail-chip:hover { background: rgba(var(--pb-accent-rgb), .16); box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .3); }
.m-avail-note { flex-basis: 100%; text-align: center; font-size: 12px; color: var(--dim); }
/* Hours beside the openings label (mobile review 2026-07-13 P1-3) — flows inline on wide,
   wraps to its own centered line on phones. */
.m-avail-hours { font-size: 12px; color: var(--dim); white-space: nowrap; }
.m-avail-load { font-size: 13px; color: var(--dim); }
/* "+N more times" chip — ghost variant so it reads as "there's more", not another bookable time. */
.m-avail-chip.m-avail-more { background: transparent; border-style: dashed; font-weight: 600; }
/* Expanded full-week reveal inside the bar (sfr-reveal supplies the frame). */
.m-avail-week { flex-basis: 100%; text-align: left; margin: 0; }
.m-avail-week .date-strip { margin-bottom: .6rem; }

/* Desktop 2-row layout (Chris 2026-07-14): heading top-left + time chips top-right on row 1, the
   open day/time hours line BOTTOM-LEFT + the "Tap a time" note BOTTOM-RIGHT on row 2. Placed AFTER
   the base .m-avail rules above so this grid wins the cascade at equal specificity (a media query
   adds no specificity). Width is left at the default .m-wrap size — no cap. Mobile (<768px) keeps
   the base flex layout via the @media(max-width:767px) block below. */
@media (min-width: 768px) {
  /* Compact content-hugging box (Chris 2026-07-15): the bar used to span the full 1120px column with
     a big 1fr slack track shoving the chips to the far right. Now the box shrinks to its content and
     centers — the label sits left, the time chips sit at the box's right edge, and the gap between
     "Next openings · Today" and the first time is a fixed 44px (well under 2× the "+N more times"
     bubble). Expanding "+N more times" grows the box to fit the week grid via width:max-content. */
  .m-avail-inner {
    display: grid; grid-template-columns: auto auto; align-items: center;
    column-gap: 44px; row-gap: 8px;
    width: max-content; max-width: 100%; margin: 0 auto; padding: 12px 22px;
  }
  .m-avail-label { grid-column: 1; grid-row: 1; justify-self: start; }
  .m-avail-hours { grid-column: 1; grid-row: 2; justify-self: start; }
  .m-avail-chips { grid-column: 2; grid-row: 1; justify-self: end; }
  .m-avail-note  { grid-column: 2; grid-row: 2; justify-self: end; flex-basis: auto; text-align: right; }
  .m-avail-week  { grid-column: 1 / -1; grid-row: 3; }
  /* Smaller time pills to match the tighter box — desktop only; mobile keeps the 44px tap target. */
  .m-avail-chip { font-size: 12px; padding: 6px 13px; min-height: 34px; }
}

/* Mobile (iPhone 17 Pro Max report, 2026-07-14): the Next-openings times + the expanded week grid
   bled past the rounded box. Keep the times on ONE swipeable row, and let the expanded week scroll
   INSIDE the box (min-width:0 lets the date-strip's own overflow engage). Also pin the
   Select-your-service tracker to the top once you scroll past it. */
@media (max-width: 767px) {
  .m-avail-inner { max-width: 100%; }
  .m-avail-chips {
    flex: 1 1 100%; min-width: 0; max-width: 100%;
    flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
    padding-bottom: 2px; scrollbar-width: thin; -webkit-overflow-scrolling: touch;
    /* Soft right-edge fade cues the horizontal scroll when the times run wider than the box;
       over empty space (few chips, left-packed) it's invisible, so it self-hides when not needed. */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  }
  .m-avail-chips > .m-avail-chip { flex: 0 0 auto; }
  .m-avail-week { min-width: 0; max-width: 100%; width: 100%; }
  .m-avail-week .slot-grid { max-width: 100%; }

  .m-book-steps {
    position: sticky; top: 0; z-index: 20;
    background: var(--pb-bg); box-shadow: 0 8px 18px -12px rgba(0, 0, 0, .9);
    padding-top: 8px; padding-bottom: 8px;
  }
}

/* Desktop sticky stepper (Chris 2026-07-19): the 3-step band ("Select your service · Pick the
   perfect time · You're in") used to pin only on mobile (the max-width:767px rule above), so on a
   desktop monitor it scrolled away and the wayfinder was gone for the whole menu run. Same
   treatment here, sized for the roomier band variant. The hero's own top bar is position:absolute
   inside .dhero (it scrolls away with the hero), so nothing else occupies top:0 to collide with. */
@media (min-width: 768px) {
  .m-book-steps {
    position: sticky; top: 0; z-index: 20;
    background: var(--pb-bg); box-shadow: 0 10px 22px -14px rgba(0, 0, 0, .9);
    padding-top: 10px; padding-bottom: 10px;
  }
}

/* ── Next-openings calendar — below-gallery 3-day view (Chris 2026-07-18) ──────────────────────
   Replaces the compact avail bar. today / tomorrow / day-after as side-by-side day cards, each with
   their real open times as tap-to-book pills, plus a "Pick another date" native date control. Uses
   the same .menu-sf alias tokens (--gold/--dim/--panel/--edge/--disp) as the rest of The Menu. */
.m-cal { padding: 28px 0 8px; }
.m-cal-head { text-align: center; margin-bottom: 18px; }
.m-cal-title {
  display: block; font-family: var(--disp); font-size: 13px; letter-spacing: .16em;
  text-transform: uppercase; font-weight: 700; color: var(--gold);
}
.m-cal-grid {
  display: grid; grid-template-columns: minmax(0, 520px); justify-content: center;
  gap: 14px; align-items: start; margin-top: 14px;
}
.m-cal-day {
  background: var(--panel); border: 1px solid rgba(var(--pb-accent-rgb), .28);
  border-radius: 16px; padding: 16px; min-height: 72px;
}
.m-cal-slots {
  display: flex; flex-wrap: wrap; gap: 8px;
  max-height: 360px; overflow-y: auto; scrollbar-width: thin;
}
.m-cal-slot {
  font-family: var(--font-body); font-weight: 700; font-size: 14px; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .07); border: 1.5px solid rgba(var(--pb-accent-rgb), .5);
  border-radius: 999px; padding: 8px 15px; cursor: pointer;
  transition: background .15s, box-shadow .15s;
  min-height: 40px; display: inline-flex; align-items: center;
}
.m-cal-slot:hover { background: rgba(var(--pb-accent-rgb), .16); box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .3); }
.m-cal-empty, .m-cal-status { font-size: 13px; color: var(--dim); margin: 4px 0 0; }
/* "Next opening →" nudge — shown only when the whole 3-day window is fully booked. Filled gold pill
   so it reads as the clear way forward (not another dim time chip). */
.m-cal-nudge {
  display: block; margin: 18px auto 0; text-align: center;
  font-family: var(--font-body); font-weight: 700; font-size: 14px; color: #111;
  background: var(--pb-accent, #E8C36A); border: 0; border-radius: 999px;
  padding: 11px 22px; min-height: 44px; cursor: pointer;
  box-shadow: 0 0 16px rgba(var(--pb-accent-rgb), .35);
}
.m-cal-nudge:hover { filter: brightness(1.05); }
/* Date navigation row: ‹ / › day steppers around the viewed date + a calendar-icon date picker. */
.m-cal-nav {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  max-width: 520px; margin: 0 auto;
}
.m-cal-arrow {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 999px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--disp); font-size: 22px; line-height: 1; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .07); border: 1.5px solid rgba(var(--pb-accent-rgb), .5);
  transition: background .15s, box-shadow .15s, opacity .15s;
}
.m-cal-arrow:hover:not(:disabled) { background: rgba(var(--pb-accent-rgb), .16); box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .3); }
.m-cal-arrow:disabled { opacity: .3; cursor: default; }
.m-cal-nav-date {
  flex: 1 1 auto; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 6px;
}
.m-cal-nav-day {
  font-family: var(--disp); font-size: 16px; font-weight: 700; color: var(--gold);
  letter-spacing: .02em; white-space: nowrap;
}
.m-cal-nav-sep { color: var(--dim); }
.m-cal-nav-full { font-size: 13px; color: var(--dim); letter-spacing: .04em; white-space: nowrap; }
/* The icon: transparent native date input laid over the glyph so any tap opens the OS picker. */
.m-cal-icon {
  position: relative; flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; width: 40px; height: 40px; border-radius: 12px; cursor: pointer;
  border: 1.5px solid rgba(var(--pb-accent-rgb), .5); background: rgba(var(--pb-accent-rgb), .07);
  transition: background .15s;
}
.m-cal-icon:hover { background: rgba(var(--pb-accent-rgb), .16); }
/* Real SVG (svgCalendar) inherits --gold via currentColor — no emoji-tinting filter needed. */
.m-cal-icon-glyph { display: inline-flex; color: var(--gold); }
.m-cal-icon-input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; color-scheme: dark; border: 0; padding: 0; background: transparent;
}
.m-cal-icon-input::-webkit-calendar-picker-indicator { width: 100%; height: 100%; cursor: pointer; }
/* A deliberately-closed day, styled as information rather than a refusal — the bare dim
   "Fully booked" it replaces read as rejection (Chris 2026-07-31). See closureCard() / closure(). */
.m-cal-closed { color: var(--pb-text, #fff); }
.m-cal-closed strong { color: var(--gold); font-weight: 700; }
.m-cal-closed span { color: var(--dim); }

/* ── Planned-closure notice (Chris 2026-07-31) ───────────────────────────────────────────────
   Sits directly below the hero for the length of a closure. Deliberately NOT styled as a warning
   banner (no amber/red): it is the page's primary call to action while she's away, so it carries
   the same gold-on-panel treatment as the booking surfaces, and the real next-available times
   inside it use the same pill language as .m-cal-slot so they read as tappable. */
.m-closed { padding: 22px 0 4px; }
.m-closed-card {
  max-width: 560px; margin: 0 auto; padding: 20px 20px 22px;
  background: var(--panel); border: 1px solid rgba(var(--pb-accent-rgb), .34);
  border-radius: 18px; box-shadow: 0 0 34px rgba(var(--pb-accent-rgb), .1);
}
.m-closed-head { display: flex; align-items: center; gap: 9px; }
.m-closed-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: var(--pb-accent, #E8C36A); box-shadow: 0 0 10px rgba(var(--pb-accent-rgb), .8);
}
.m-closed-title {
  margin: 0; font-family: var(--disp); font-size: 19px; font-weight: 700;
  letter-spacing: .01em; color: var(--pb-text, #fff);
}
.m-closed-msg { margin: 7px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--dim); }
.m-closed-status { margin: 14px 0 0; font-size: 13px; color: var(--dim); }

/* Real openings — the primary action. */
.m-closed-next { margin-top: 16px; }
.m-closed-next-h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.m-closed-next-lbl {
  font-family: var(--disp); font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  font-weight: 700; color: var(--gold);
}
.m-closed-next-day { font-size: 14px; font-weight: 700; color: var(--pb-text, #fff); }
.m-closed-slots { display: flex; flex-wrap: wrap; gap: 8px; }
.m-closed-slot {
  font-family: var(--font-body); font-weight: 700; font-size: 14px; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .07); border: 1.5px solid rgba(var(--pb-accent-rgb), .5);
  border-radius: 999px; padding: 8px 15px; cursor: pointer; text-decoration: none;
  transition: background .15s, box-shadow .15s;
  min-height: 40px; display: inline-flex; align-items: center;
}
.m-closed-slot:hover { background: rgba(var(--pb-accent-rgb), .16); box-shadow: 0 0 14px rgba(var(--pb-accent-rgb), .3); }
.m-closed-all {
  display: inline-block; margin-top: 11px; padding: 0; border: 0; background: none;
  font-family: var(--font-body); font-size: 13.5px; font-weight: 700; color: var(--gold);
  cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}
.m-closed-rule { height: 1px; margin: 20px 0 16px; background: var(--pb-edge, rgba(255, 255, 255, .12)); }

/* Secondary capture. Quieter than the slot pills on purpose — a booking is worth more than a lead,
   so this must never out-shout the times above it. */
.m-closed-notify { margin: 0; }
.m-closed-notify-h { font-size: 14.5px; font-weight: 700; color: var(--pb-text, #fff); }
.m-closed-notify-sub { margin: 5px 0 12px; font-size: 13.5px; line-height: 1.5; color: var(--dim); }
.m-closed-fields { display: flex; gap: 10px; flex-wrap: wrap; }
.m-closed-fields .field { flex: 1 1 140px; min-width: 0; margin: 0; }
.m-closed-fields .field > span {
  font-size: 10.5px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--dim); margin-bottom: 3px;
}
.m-closed-fields input {
  width: 100%; min-height: 42px; padding: .45rem .7rem; font-size: 1rem; border-radius: 10px;
  background: var(--pb-surface, #1c1c1c); color: var(--pb-text, #fff);
  border: 1px solid var(--pb-edge, rgba(255, 255, 255, .18));
}
.m-closed-fields input:focus { outline: none; border-color: rgba(var(--pb-accent-rgb), .6); }
.m-closed-fields input:disabled { opacity: .55; }
.m-closed-err { color: #f28b82; font-size: 13px; margin: 9px 0 0; }
.m-closed-notify-btn {
  margin-top: 12px; width: 100%; min-height: 44px; cursor: pointer;
  font-family: var(--font-body); font-weight: 700; font-size: 14.5px; color: #111;
  background: rgba(var(--pb-accent-rgb), .82); border: 0; border-radius: 999px;
  transition: filter .15s, opacity .15s;
}
.m-closed-notify-btn:hover:not(:disabled) { filter: brightness(1.06); }
.m-closed-notify-btn:disabled { opacity: .6; cursor: default; }
.m-closed-done {
  font-size: 14px; line-height: 1.55; color: var(--pb-text, #fff);
  background: rgba(var(--pb-accent-rgb), .1); border: 1px solid rgba(var(--pb-accent-rgb), .38);
  border-radius: 12px; padding: 13px 15px;
}
.m-closed-done strong { color: var(--gold); }
@media (max-width: 420px) {
  .m-closed-card { padding: 17px 15px 18px; border-radius: 15px; }
  .m-closed-title { font-size: 17.5px; }
  .m-closed-fields { gap: 8px; }
  .m-closed-fields .field { flex: 1 1 100%; }
}

/* Mobile: full-width day card; keep the times on a swipeable single row so a busy day never blows
   out the card height. The row is width-constrained (min-width:0 above) so it can't push the page. */
@media (max-width: 767px) {
  .m-cal { padding: 24px 0 4px; }
  .m-cal-grid { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .m-cal-nav { gap: 6px; }
  .m-cal-nav-date { gap: 6px; }
  .m-cal-slots {
    flex-wrap: nowrap; overflow-x: auto; max-height: none; padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  }
  .m-cal-slots > .m-cal-slot { flex: 0 0 auto; }
  /* No times to swipe — drop the fade so short/empty days don't look clipped. */
  .m-cal-slots:not(:has(.m-cal-slot)) { -webkit-mask-image: none; mask-image: none; }
}

/* ── "Available now?" concierge chat (2026-07-12) ──
   Mounted on <body>, OUTSIDE .menu-sf — so the .menu-sf alias tokens (--gold/--dim/--panel/
   --edge/--disp) do NOT resolve here. Everything below uses the root --pb-* tokens with
   literal fallbacks. (Chris's prod live-fire caught the symptom: typing dots painted with
   var(--dim) were transparent — the chat looked frozen.) */
.chat-fab {
  position: fixed; right: 16px; bottom: 16px; z-index: 150;
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-body, inherit); font-weight: 700; font-size: 14px; color: #111;
  background: var(--pb-accent, #E8C36A); border: 0; border-radius: 999px; padding: 12px 18px;
  min-height: var(--tap); cursor: pointer;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .45), 0 0 14px rgba(var(--pb-accent-rgb), .35);
}
.chat-fab:active { transform: scale(.97); }
/* Inline chat glyph (SVG, app.js) — desktop keeps the text pill as-is, so the icon stays hidden
   there; the mobile media query below flips it on and hides .chat-fab-text instead. */
.chat-fab-icon { display: none; }
/* Sticky Book bar active (body.msticky-on, set by app.js): lift the FAB clear of the bar — they
   shared the bottom-right thumb zone and overlapped by 53px (mobile review 2026-07-13). Desktop
   never shows .m-sticky (≥768px), so scope the lift to mobile. */
@media (max-width: 767px) {
  .chat-fab { transition: bottom .25s ease; }
  body.msticky-on .chat-fab { bottom: calc(84px + env(safe-area-inset-bottom)); }
  /* F11 fix (chat-fab-compact, 2026-07-21): the F5 shrink (smaller padding/font) still left a
     WIDE text pill that sat on top of the menu/services list — it covered the "$80" Facial price
     row, not just the reviews/footer. Collapsing to a small circular icon-only FAB (~50px, the
     standard Intercom/Messenger corner-bubble pattern) removes almost all footprint, so a tiny
     corner overlap of empty card padding is the worst case instead of covering price/body text.
     .chat-fab-icon is the inline SVG chat glyph (app.js); .chat-fab-text is the "Available now?"
     label, kept for desktop and hidden here. .m-footer keeps matching bottom clearance below. */
  .chat-fab {
    width: 50px; height: 50px; padding: 0; gap: 0; border-radius: 50%; justify-content: center;
  }
  .chat-fab-icon { display: flex; align-items: center; justify-content: center; color: #111; }
  .chat-fab-text { display: none; }
  .chat-fab-dot {
    position: absolute; top: 3px; right: 3px; width: 10px; height: 10px;
    border: 2px solid var(--pb-accent, #E8C36A); box-sizing: content-box;
  }
  /* F5 fix (visual audit 2026-07-21, cont'd): reserve clearance at the true page end so the FAB
     never sits over the footer's links/copy — it has no sticky bar below it there to lift off of. */
  .m-footer { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
}
.chat-fab-dot {
  width: 9px; height: 9px; border-radius: 50%; background: #1d9d55;
  box-shadow: 0 0 0 0 rgba(29, 157, 85, .6); animation: chat-pulse 2s infinite;
}
@keyframes chat-pulse {
  0% { box-shadow: 0 0 0 0 rgba(29, 157, 85, .6); }
  70% { box-shadow: 0 0 0 8px rgba(29, 157, 85, 0); }
  100% { box-shadow: 0 0 0 0 rgba(29, 157, 85, 0); }
}
/* Scroll hand-off (Chris 2026-07-15): while the hero is on screen its own inline "Available now?"
   bubble carries the chat entry point, so the floating FAB is hidden; once the hero scrolls away
   (body.hero-scrolled, set by wireStickyBar in app.js) the FAB fades in bottom-right — reads as the
   hero bubble sliding down to the corner. bottom stays in the transition so the msticky lift eases. */
.chat-fab { opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity .3s ease, transform .3s ease, bottom .25s ease; }
body.hero-scrolled .chat-fab { opacity: 1; transform: none; pointer-events: auto; }
/* F10 fix (mobile polish audit 2026-07-21, extended 2026-07-22): yield the FAB while a section
   flagged as needing clearance (.m-reviews, .m-footer-inner, or .m-menu-section — see
   wireStickyBar's fab-yield toggle in app.js) is on screen, so it can never sit on top of that
   section's cards/brand-line/links/service prices. Same fade as the hero hand-off; re-uses
   body.hero-scrolled's transition so it reads as one continuous behavior, not a glitch. */
body.fab-yield .chat-fab { opacity: 0; transform: translateY(10px); pointer-events: none; }

/* Inline hero "Available now?" bubble — the on-hero twin of the FAB, sitting where the
   "Availability" button used to. Same green pulse dot; pill shape. Overrides the base
   .dh-services / .mh-cal styling for the buttons that carry this class. */
.hero-availchat {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  font-family: var(--font-body); font-weight: 700; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .1);
  border: 1.5px solid rgba(var(--pb-accent-rgb), .6); border-radius: 999px;
  text-decoration: none; cursor: pointer;
}
.hero-availchat:hover { border-color: var(--gold); background: rgba(var(--pb-accent-rgb), .16); }
.hero-availchat .chat-fab-dot { width: 8px; height: 8px; flex: none; }
.dh-duo .hero-availchat { width: 100%; font-size: .96rem; padding: .95rem 1rem; letter-spacing: .02em; }
.mh-quick .hero-availchat { font-size: .72rem; padding: .42rem .72rem; white-space: nowrap; flex: none; }
.chat-backdrop { position: fixed; inset: 0; z-index: 220; background: rgba(0, 0, 0, .55); }
.chat-sheet {
  position: fixed; z-index: 221; display: flex; flex-direction: column;
  left: 0; right: 0; bottom: 0; max-height: 82vh;
  background: var(--pb-bg, #111); border: 1px solid rgba(var(--pb-accent-rgb), .35);
  border-bottom: 0; border-radius: 18px 18px 0 0;
}
@media (min-width: 768px) {
  .chat-sheet {
    left: auto; right: 24px; bottom: 24px; width: 380px; max-height: 70vh;
    border-bottom: 1px solid rgba(var(--pb-accent-rgb), .35); border-radius: 18px;
  }
}
.chat-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--pb-edge, rgba(255, 255, 255, .1));
}
.chat-title { font-family: var(--font-heading, inherit); font-size: 13px; letter-spacing: .1em; text-transform: uppercase; color: var(--pb-accent, #E8C36A); }
/* Header identity — shop name while connecting, then headshot + Ashley + role (GoRV pattern). */
.chat-id { display: flex; align-items: center; gap: 10px; min-width: 0; }
.chat-av {
  width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none;
  border: 1.5px solid rgba(var(--pb-accent-rgb), .5);
}
.chat-id-col { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.chat-sub { font-size: 11px; color: var(--pb-dim, #9a968e); }
.chat-x {
  background: none; border: 0; color: var(--pb-dim, #9a968e); font-size: 26px; line-height: 1;
  cursor: pointer; padding: 4px 8px; min-width: var(--tap); min-height: var(--tap);
}
.chat-log { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.cb { max-width: 85%; padding: 10px 14px; border-radius: 16px; font-size: 14.5px; line-height: 1.45; }
.cb-c { align-self: flex-end; background: rgba(var(--pb-accent-rgb), .18); border: 1px solid rgba(var(--pb-accent-rgb), .4); border-bottom-right-radius: 4px; }
.cb-a { align-self: flex-start; background: var(--pb-surface, #1c1c1c); border: 1px solid var(--pb-edge, rgba(255, 255, 255, .1)); border-bottom-left-radius: 4px; }
.cb-typing-wrap { align-self: flex-start; display: flex; flex-direction: column; gap: 5px; }
.cb-typing { display: flex; gap: 4px; padding: 14px; }
.cb-typing span {
  width: 7px; height: 7px; border-radius: 50%; background: var(--pb-dim, #9a968e);
  animation: cb-blink 1.2s infinite;
}
.cb-status { font-size: 12px; color: var(--pb-dim, #9a968e); padding-left: 6px; }
/* Sender name above assistant bubbles (script v3: "actually shows her name"). */
.cb-a-wrap { align-self: flex-start; display: flex; flex-direction: column; gap: 3px; max-width: 85%; }
.cb-a-wrap .cb { max-width: none; }
.cb-name { font-size: 11.5px; letter-spacing: .06em; color: var(--pb-dim, #9a968e); padding-left: 6px; }
.cb-typing span:nth-child(2) { animation-delay: .2s; }
.cb-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes cb-blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
.cb-chips { display: flex; flex-wrap: wrap; gap: 8px; align-self: flex-start; }
.cb-chip {
  font: inherit; font-weight: 700; color: var(--pb-accent, #E8C36A); cursor: pointer;
  background: rgba(var(--pb-accent-rgb), .07); border: 1.5px solid rgba(var(--pb-accent-rgb), .55);
  border-radius: 999px; padding: 8px 22px; min-height: var(--tap);
}
.cb-chip:active { background: rgba(var(--pb-accent-rgb), .2); }
/* Meta choices — ghosted so real times read as the primary action. */
.cb-chip-alt { background: transparent; border-style: dashed; font-weight: 600; color: var(--pb-dim, #9a968e); }

/* ── Mini calendar widget (v3d) — menu-flow booking inside the chat ── */
.chat-cal {
  align-self: stretch; display: flex; flex-direction: column; gap: 10px;
  background: var(--pb-surface, #1c1c1c); border: 1px solid var(--pb-edge, rgba(255, 255, 255, .12));
  border-radius: 14px; padding: 12px;
}
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cal-title {
  font-family: var(--font-heading, inherit); font-size: 12px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--pb-accent, #E8C36A); text-align: center; flex: 1;
}
.cal-nav, .cal-back {
  background: none; border: 1px solid var(--pb-edge, rgba(255, 255, 255, .16)); border-radius: 8px;
  color: var(--pb-text, #fff); cursor: pointer; font: inherit; font-size: 14px;
  padding: 4px 10px; min-height: 32px;
}
.cal-nav:disabled { opacity: .3; cursor: default; }
.cal-back { font-size: 13px; color: var(--pb-dim, #9a968e); }
.cal-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
.cal-day {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  background: transparent; border: 1px solid var(--pb-edge, rgba(255, 255, 255, .14));
  border-radius: 10px; padding: 7px 0 6px; cursor: pointer; min-width: 0;
}
.cal-day:not(:disabled):active { border-color: rgba(var(--pb-accent-rgb), .6); }
.cal-day-full { opacity: .38; cursor: default; }
.cal-dow { font-size: 9.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--pb-dim, #9a968e); white-space: nowrap; }
.cal-num { font-weight: 700; font-size: 15px; color: var(--pb-text, #fff); }
.cal-sub { font-size: 8.5px; color: var(--pb-accent, #E8C36A); white-space: nowrap; }
.cal-day-full .cal-sub { color: var(--pb-dim, #9a968e); }
.cal-times { display: flex; flex-wrap: wrap; gap: 7px; }
.cal-time { padding: 7px 14px; font-size: 13.5px; }
.cal-group { display: flex; flex-direction: column; gap: 5px; }
.cal-group-h { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--pb-dim, #9a968e); }
.cal-note { font-size: 13.5px; color: var(--pb-dim, #9a968e); margin: 0; }
/* Compact capture/booking form — clear but not overbearing (Chris 2026-07-12): small caps
   labels, slimmer inputs (font stays ≥16px so iOS doesn't zoom), narrower than the sheet. */
.cb-form { align-self: flex-start; width: 100%; max-width: 300px; display: flex; flex-direction: column; gap: 7px; padding: 2px; }
.cb-form .field { margin: 0; }
.cb-form .field > span {
  font-size: 10.5px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--pb-dim, #9a968e); margin-bottom: 3px;
}
.cb-form input {
  min-height: 40px; padding: .4rem .7rem; font-size: 1rem; border-radius: 10px;
  background: var(--pb-surface, #1c1c1c); color: var(--pb-text, #fff);
  border: 1px solid var(--pb-edge, rgba(255, 255, 255, .18));
}
.cb-form input:focus { border-color: rgba(var(--pb-accent-rgb), .6); outline: none; }
.cb-err { color: #f28b82; font-size: 13px; margin: 0; }
.cb-send { margin-top: 2px; min-height: 40px; padding: .45rem; font-size: .9rem; }
.cb-close-link { align-self: center; margin-top: 2px; }
.chat-input {
  display: flex; gap: 8px; align-items: center; padding: 10px 12px;
  border-top: 1px solid var(--pb-edge, rgba(255, 255, 255, .1));
}
.chat-input input {
  flex: 1; font: inherit; font-size: 14.5px; color: var(--pb-text, #fff);
  background: var(--pb-surface, #1c1c1c); border: 1px solid var(--pb-edge, rgba(255, 255, 255, .14));
  border-radius: 999px; padding: 10px 16px; min-height: var(--tap);
}
.chat-input input:focus { outline: none; border-color: rgba(var(--pb-accent-rgb), .6); }
.chat-send {
  flex: none; width: 42px; height: 42px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--pb-accent, #E8C36A); color: #111; font-size: 16px; line-height: 1;
}
.chat-send:active { transform: scale(.94); }

/* ── Sticky mobile Book bar (conversion audit 2026-07-12) — fixed bottom CTA, revealed by app.js
   once the hero's Book button scrolls out. Mobile-only; desktop keeps the in-hero CTA cluster. ── */
.m-sticky { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; gap: 10px; align-items: stretch;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: rgba(10, 10, 12, .93); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border-top: 1px solid rgba(var(--pb-accent-rgb), .35);
  transform: translateY(110%); transition: transform .25s ease; pointer-events: none; }
.m-sticky.on { transform: none; pointer-events: auto; }
.m-sticky-book { flex: 1; min-height: 48px; font-family: var(--font-body); font-weight: 800;
  font-size: 1rem; color: var(--pb-accent-ink); background: var(--gold); border: 0;
  border-radius: 12px; cursor: pointer; }
.m-sticky-slot { flex: none; min-height: 48px; padding: 0 14px; font-family: var(--font-body);
  font-weight: 800; font-size: .92rem; color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .08); border: 1.5px solid var(--gold);
  border-radius: 12px; cursor: pointer; white-space: nowrap; }
@media (min-width: 768px) { .m-sticky { display: none; } }

.m-trust { background: var(--panel); border-bottom: 1px solid var(--edge); }
.m-trust-inner { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; }
.m-trust-item { display: flex; align-items: center; gap: 10px; padding: 18px 32px; border-right: 1px solid var(--edge); flex: 1 1 200px; justify-content: center; }
.m-trust-item:last-child { border-right: none; }
.m-trust-icon { width: 20px; height: 20px; flex-shrink: 0; color: var(--gold); display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 15px; }
.m-trust-label { font-size: 13px; font-weight: 600; color: var(--txt); letter-spacing: .01em; white-space: nowrap; }

/* ── Reviews (growth review 2026-07-09) — hero proof line + quote strip, both GATED in app.js
   on ≥5 reviews at ≥4.5★ (a thin rating hurts more than none; they render nothing until then) ── */
.dh-proof {
  display: inline-block; margin: -0.35rem 0 1rem; font-weight: 700; font-size: .95rem;
  color: var(--gold); text-decoration: none; text-shadow: 0 1px 10px rgba(0,0,0,.6);
}
.mh-proof {
  display: block; margin: .5rem 0 0; font-weight: 700; font-size: .8rem;
  color: var(--gold); text-decoration: none; text-shadow: 0 1px 10px rgba(0,0,0,.8);
  /* review proof was a 19px-tall link — pad the hit area to ~44px in place (audit 2026-07-12) */
  position: relative; width: fit-content;
}
.mh-proof::after { content: ""; position: absolute; inset: -12px -8px; }
.m-reviews { background: var(--panel); border-top: 1px solid var(--edge); border-bottom: 1px solid var(--edge); padding: 34px 0 40px; margin-bottom: 72px; }
/* flex-wrap (360px audit 2026-07-22): title + the 18px nowrap stars link don't share one row on
   sub-380px phones — the stars (plus their -8px hit-area pseudo) poked 13px past the viewport and
   side-scrolled the whole page. Wrapping drops the stars to a second line only when needed. */
.m-reviews-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .4rem 1rem; margin-bottom: 18px; }
.m-reviews-title { font-family: var(--disp); font-size: 15px; letter-spacing: .08em; text-transform: uppercase; color: var(--txt); }
/* Bigger review proof (Chris 2026-07-15): the "5.0 · 19 Google reviews" rating is the strongest
   trust cue in the section — bumped from 13px so it reads at a glance. */
.m-reviews-stars { color: var(--gold); font-weight: 700; font-size: 18px; white-space: nowrap; text-decoration: none;
  position: relative; }
.m-reviews-stars::after { content: ""; position: absolute; inset: -14px -8px; }  /* 44px hit area (audit 2026-07-12) */
.m-reviews-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.m-review-card { margin: 0; background: rgba(0,0,0,.22); border: 1px solid var(--edge); border-radius: 14px; padding: 16px 18px; }
.m-review-card blockquote { margin: 0 0 10px; font-size: .92rem; line-height: 1.55; color: var(--txt); }
.m-review-card figcaption { font-size: .78rem; color: var(--dim); }
.m-review-card figcaption::after { content: " — Google review"; color: var(--gold); opacity: .8; }

/* Section header */
/* Top padding is the gap between the Select-your-service tracker and "The Menu"
   (Chris 2026-07-15: 2.5× the prior 36px). */
.m-section-header { text-align: center; padding: 90px 24px 24px; }
.m-eyebrow { font-family: var(--disp); font-size: 10px; letter-spacing: .22em; text-transform: uppercase; color: var(--gold); margin-bottom: 14px; }
.m-section-title { font-family: var(--disp); font-size: clamp(26px, 4vw, 40px); font-weight: 400; color: var(--txt); letter-spacing: .04em; line-height: 1.2; }
.m-section-sub { margin: 10px auto 0; font-size: 15px; color: var(--dim); max-width: 480px; }

/* Most-popular cards */
.m-packages-section { padding: 0 0 56px; }
/* Group 2 — "Most popular" promoted to bold sub-heading (SPEC.md Group 2) */
/* margin-bottom is the gap below "Most popular" before the cards (Chris 2026-07-15: tightened so the
   cards sit just under the heading). */
.m-packages-eyebrow { font-family: var(--disp); font-size: clamp(20px, 3vw, 26px); font-weight: 700; letter-spacing: .03em; text-transform: none; color: var(--gold); text-align: center; margin-bottom: 16px; }
/* haircut_note caption under "The Menu" — italic, and it WRAPS (Chris 2026-07-15): the old
   white-space:nowrap ran "head massage & style (optional)." off-screen on mobile. */
.m-pop-note { margin: -16px 0 65px; padding: 0 20px; text-align: center; font-size: clamp(11px, 2.9vw, 13px); font-style: italic; color: var(--dim); white-space: normal; line-height: 1.5; }
.m-packages-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.m-pkg-card { background: var(--panel); border: 1px solid var(--edge); border-radius: 16px; padding: 28px 22px 24px; position: relative; transition: border-color .2s, box-shadow .2s; display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: inherit; cursor: pointer; }
.m-pkg-card::before { content: ''; position: absolute; inset: 0; border-radius: 16px; background: linear-gradient(135deg, rgba(255,209,102,.05) 0%, transparent 60%); pointer-events: none; }
.m-pkg-card:hover { border-color: rgba(255,209,102,.4); box-shadow: 0 0 32px rgba(255,209,102,.08); }
/* Card hierarchy swapped (Chris, 2026-07-13): NAME leads (as large as the box allows, always
   ONE line — fitPkgNames() in app.js shrinks from this cap so "Haircut & Hot Shave" never
   wraps at any viewport), price demoted smaller, Book cue promoted larger. */
.m-pkg-name { font-size: 30px; font-weight: 700; color: var(--txt); line-height: 1.2; white-space: nowrap; }
.m-pkg-time { font-size: 12px; color: var(--dim); margin-top: 2px; }
.m-pkg-price { font-family: var(--disp); font-size: 18px; color: var(--gold); letter-spacing: .02em; margin-top: auto; padding-top: 18px; }
.m-pkg-cta { font-size: 15px; font-weight: 700; letter-spacing: .04em; color: var(--gold); margin-top: 12px; }
.m-pkg-card:hover .m-pkg-cta { text-decoration: underline; }
.m-pop-m { display: none; }

/* Two-column menu */
.m-menu-section { padding: 0 0 72px; }
.m-menu-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: start; }
/* Category headings ("Men's Barber Services" / "Other Services"). Centered in every layout;
   fitMenuTitles() (app.js) scales each title's text to 65% of its column width — the 13px here is
   just the pre-fit fallback if JS hasn't run yet (Chris, 2026-07-14). */
.m-menu-col-title { font-family: var(--disp); font-size: 13px; letter-spacing: .04em; text-transform: none; color: var(--gold); padding-bottom: 16px; margin-bottom: 4px; border-bottom: 1px solid var(--edge); text-align: center; line-height: 1.15; }
/* Group 2 — menu rows are now buttons (SPEC.md Group 2) */
.m-menu-row {
  display: flex; align-items: center; gap: 12px; padding: 14px 10px; width: 100%; text-align: left;
  border-bottom: 1px solid rgba(38,38,44,.6); border-top: none; border-left: none; border-right: none;
  background: none; font: inherit; color: inherit; cursor: pointer; border-radius: 8px;
  transition: background .12s;
}
.m-menu-row:last-child { border-bottom: none; }
.m-menu-row:hover { background: rgba(255,209,102,.05); }
.m-menu-row:active { background: rgba(255,209,102,.1); }
.m-menu-row-left { flex: 1; min-width: 0; }
.m-menu-name { font-size: 15px; font-weight: 600; color: var(--txt); line-height: 1.3; }
.m-menu-desc { font-size: 12px; color: var(--dim); margin-top: 3px; line-height: 1.5; }
.m-menu-row-right { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex-shrink: 0; }
.m-menu-price { font-size: 17px; font-weight: 700; color: var(--txt); white-space: nowrap; }
.m-menu-time { font-size: 11px; color: var(--dim); white-space: nowrap; }
/* "Book ›" affordance (Group 2) */
.m-menu-book-cue { font-size: 11px; font-weight: 700; color: var(--gold); white-space: nowrap; margin-left: 4px; opacity: 0; transition: opacity .15s; }
.m-menu-row:hover .m-menu-book-cue,
.m-menu-row:focus-visible .m-menu-book-cue { opacity: 1; }
/* Inquiry rows (config.storefront.inquiries) — no fixed price, Text/Call instead of Book */
.m-menu-inquire { cursor: default; }
.m-menu-inquire:hover, .m-menu-inquire:active { background: none; }
.m-menu-inq-price { font-size: 13px; font-weight: 700; font-style: italic; color: var(--dim); white-space: normal; text-align: right; }
.m-menu-inq-actions { display: flex; gap: 8px; margin-top: 6px; }
.m-menu-inq-btn { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--gold); border: 1px solid var(--gold); border-radius: 999px; padding: 3px 11px; text-decoration: none; white-space: nowrap; }
.m-menu-inq-btn:hover { background: rgba(255,209,102,.12); }
/* Wide desktop: stack the categories full-width (Men's Barber Services, then Packages &
   Combos, then Other Services), center each title, and lay that category's services out in
   2 columns (Chris, 2026-07-14). Below 900px this stays the single-column mobile menu. */
@media (min-width: 900px) {
  .m-menu-cols { grid-template-columns: 1fr; gap: 56px; }
  .m-menu-col { display: grid; grid-template-columns: 1fr 1fr; column-gap: 40px; align-items: start; }
  .m-menu-col-title { grid-column: 1 / -1; text-align: center; }
}

/* ══ Booking modal (Group 3, SPEC.md) ══════════════════════════════════════════
   In-page dialog: service → add-on ladder → time. Hands off to full-page details
   on time-pick. Focus-trapped, Esc-to-close, history-backed for Android hardware back. */
.bm-backdrop {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(8, 8, 10, .78); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  display: flex; align-items: flex-end; justify-content: center;
  padding: 0;
}
@media (min-width: 560px) {
  .bm-backdrop { align-items: center; padding: 1.5rem; }
}
.bm-dialog {
  background: var(--pb-bg); border: 1px solid var(--pb-edge);
  border-radius: 20px 20px 0 0; width: 100%; max-width: 560px;
  max-height: 90dvh; overflow-y: auto; overscroll-behavior: contain;
  box-shadow: 0 -8px 48px rgba(0,0,0,.6), 0 0 0 1px rgba(255,209,102,.08);
  position: relative;
}
@media (min-width: 560px) {
  .bm-dialog { border-radius: 20px; max-height: 82dvh; }
}
.bm-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.1rem 1.1rem .6rem; border-bottom: 1px solid var(--pb-edge);
  position: sticky; top: 0; background: var(--pb-bg); z-index: 2;
}
/* F9 fix (visual audit 2026-07-21): wraps .bm-title + the new "Change service" link so the link
   sits directly under the service name instead of competing with .bm-close for the header row's
   flex space. Title keeps its own single-line ellipsis; the wrap just stacks the two vertically. */
.bm-title-wrap { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-width: 0; }
.bm-title {
  font-family: var(--font-heading); font-size: 1rem; letter-spacing: .04em;
  color: var(--pb-text); margin: 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bm-title em { font-style: normal; color: var(--pb-accent); }
/* F9 fix (visual audit 2026-07-21): plain link-style button, deliberately quiet (no border/pill)
   so it reads as a correction affordance, not a competing CTA next to the time grid below it. */
.bm-change-svc {
  align-self: flex-start; background: none; border: none; padding: 0; margin: 0;
  font: inherit; font-size: .76rem; font-weight: 600; letter-spacing: .01em;
  color: var(--pb-accent); text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer;
}
.bm-change-svc:hover { color: var(--gold, var(--pb-accent)); }
.bm-close {
  width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--pb-edge);
  background: var(--pb-surface); color: var(--pb-dim); font-size: 1.2rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; font: inherit; flex: none; margin-left: .6rem;
}
.bm-close:hover { border-color: rgba(var(--pb-accent-rgb), .55); color: var(--pb-accent); }
.bm-body { padding: 1rem 1.1rem 1.4rem; }
.bm-svc-name {
  font-family: var(--font-heading); font-size: .92rem; letter-spacing: .03em;
  color: var(--pb-dim); margin: 0 0 .9rem;
}
/* Add-on ladder (Group 3) — single-select, reuses .sfr-pkg styles */
.bm-ladder-h {
  font-family: var(--font-heading); font-size: .7rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--pb-dim); margin: .2rem 0 .7rem;
}
.bm-upgrade {
  border: 1.5px solid rgba(var(--pb-accent-rgb), .45); border-radius: 14px;
  padding: .85rem; margin: .8rem 0; cursor: pointer; width: 100%; text-align: left;
  background: linear-gradient(140deg, rgba(var(--pb-accent-rgb), .08), transparent); font: inherit; color: inherit;
  display: flex; align-items: center; gap: .6rem;
  transition: border-color .15s, box-shadow .15s;
}
.bm-upgrade:hover { border-color: var(--pb-accent); box-shadow: 0 0 18px rgba(var(--pb-accent-rgb), .2); }
.bm-upgrade-text { flex: 1; }
.bm-upgrade-label { font-weight: 700; font-size: .95rem; color: var(--pb-text); display: block; }
.bm-upgrade-sub { font-size: .78rem; color: var(--pb-dim); display: block; margin-top: .2rem; }
.bm-upgrade-price { font-family: var(--font-heading); font-size: 1rem; color: var(--pb-accent); font-weight: 700; white-space: nowrap; }
.bm-upgrade-skip {
  display: block; width: 100%; text-align: center; font: inherit; font-size: .82rem; font-weight: 600;
  color: var(--pb-dim); background: none; border: 1px dashed var(--pb-edge); border-radius: 10px;
  padding: .55rem; cursor: pointer; min-height: var(--tap);
}
.bm-upgrade-skip:hover { border-color: rgba(var(--pb-accent-rgb), .4); color: var(--pb-text); }

/* Time grid inside modal — minimal padding, reuses slot-grid + slot classes */
.bm-time-h {
  font-family: var(--font-heading); font-size: .7rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--pb-dim); margin: .6rem 0 .4rem;
}
.bm-loading { display: flex; align-items: center; gap: .55rem; font-size: .88rem; color: var(--pb-dim); padding: .6rem 0; }
.bm-err { font-size: .85rem; color: var(--pb-dim); padding: .4rem 0; }
.bm-empty { font-size: .85rem; color: var(--pb-dim); padding: .4rem 0; }
/* Date strip inside modal — compact (same .date-chip + .date-strip classes) */
.bm-date-strip { margin-bottom: .7rem; }
/* F6 fix (visual audit 2026-07-21): the day strip (.date-strip, shared/tokens.css) is already
   horizontally scrollable, but nothing signalled it — "Sat 25" clipped mid-card at the modal's
   right edge with no cue, so it read as "only 5 days bookable." Same right-edge fade convention
   already used for the below-hero avail-bar's time chips (see .m-avail-chips a few hundred lines
   up) plus scroll-snap so cards settle cleanly instead of stopping mid-card. Scoped to
   .bm-date-strip only (the two booking-modal date strips) — the homepage-calendar and legacy
   .date-strip usages elsewhere are untouched. */
.bm-date-strip {
  scroll-snap-type: x mandatory;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.bm-date-strip .date-chip { scroll-snap-align: start; }

/* See-calendar taken-slot indicator — muted but still clickable (SPEC-2 §B / ADR-0018). */
.bm-slot-taken { opacity: .5; }
.bm-slot-taken .bm-taken-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--c-danger); margin-left: 4px; vertical-align: middle;
}

/* Add-a-person section inside the modal time step (SPEC-2 §D). */
/* Extra clearance from the slot grid — a time-tap landed on "+ Add another person" during the
   2026-07-13 mobile review (tap-bleed on re-render); the gap keeps the button out of that zone. */
.bm-people { border-top: 1px solid var(--pb-edge); margin-top: 1.75rem; padding-top: 1.1rem; }

/* Photo strip */
.m-photo-strip { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 12px; margin-bottom: 72px; border-radius: 16px; overflow: hidden; }
.m-photo-strip-item { position: relative; overflow: hidden; border-radius: 12px; }
.m-photo-strip-item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
.m-photo-strip-item:hover img { transform: scale(1.03); }
/* work-wash.jpg is a tall portrait — shift its crop up so Chelsea stays fully in frame
   in the home photo strip (the wide first slot otherwise center-crops off her head). */
.m-photo-strip-item img[src*="work-wash.jpg"] { object-position: center 25%; }
.m-photo-strip-item:first-child { aspect-ratio: 16/10; }
.m-photo-strip-item:not(:first-child) { aspect-ratio: 4/5; }
.m-photo-overlay { position: absolute; bottom: 0; left: 0; right: 0; padding: 20px 16px 14px; background: linear-gradient(to top, rgba(10,10,12,.82) 0%, transparent 100%); }
.m-photo-ig { font-size: 12px; font-weight: 600; color: var(--gold); letter-spacing: .05em; text-decoration: none; }

/* Before/after portfolio — drag-to-reveal sliders (Premium, auto-shown from consented photos) */
.m-ba { max-width: 1120px; margin: 0 auto 72px; padding: 0 24px; }
.m-ba-strip { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; padding-bottom: 6px; }
.ba-slider { flex: 0 0 auto; width: min(78vw, 300px); scroll-snap-align: center; margin: 0; }
.ba-pane { --rev: 50%; position: relative; aspect-ratio: 4/5; border-radius: 16px; overflow: hidden; background: var(--panel); touch-action: none; user-select: none; }
.ba-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.ba-before { clip-path: inset(0 calc(100% - var(--rev)) 0 0); }
.ba-handle { position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px; background: rgba(255,255,255,.9); box-shadow: 0 0 0 1px rgba(10,10,12,.35); pointer-events: none; }
.ba-handle::after { content: '⟷'; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 34px; height: 34px; border-radius: 50%; background: rgba(255,255,255,.92); color: #111; font-size: 15px; line-height: 34px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,.35); }
/* The native range is the actual control: invisible, fills the pane, gives pointer + keyboard. */
.ba-range { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; -webkit-appearance: none; appearance: none; background: transparent; }
.ba-range:focus-visible { outline: none; }
.ba-range:focus-visible ~ .ba-handle::after { box-shadow: 0 0 0 3px var(--gold), 0 2px 8px rgba(0,0,0,.35); }
.ba-range::-webkit-slider-thumb { -webkit-appearance: none; width: 44px; height: 100%; }
.ba-range::-moz-range-thumb { width: 44px; height: 100%; border: 0; background: transparent; }
.ba-cap { margin-top: 10px; font-size: 13px; color: var(--dim); letter-spacing: .04em; text-align: center; }

/* Credential bar */
.m-cred-bar { background: var(--panel); border-top: 1px solid var(--edge); border-bottom: 1px solid var(--edge); margin-bottom: 72px; }
.m-cred-inner { display: grid; grid-template-columns: auto 1fr; gap: 32px; align-items: center; padding: 40px 0; }
.m-cred-portrait { width: 100px; height: 100px; border-radius: 50%; overflow: hidden; border: 2px solid rgba(255,209,102,.3); flex-shrink: 0; box-shadow: 0 0 24px rgba(255,209,102,.1); }
.m-cred-portrait img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.m-cred-name { font-family: var(--disp); font-size: 18px; letter-spacing: .06em; color: var(--txt); margin-bottom: 6px; }
.m-cred-bio { font-size: 14px; color: var(--dim); line-height: 1.6; max-width: 640px; }
.m-cred-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.m-cred-tag { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--gold); background: rgba(255,209,102,.08); border: 1px solid rgba(255,209,102,.2); padding: 4px 12px; border-radius: 50px; }

/* Hours + location */
.m-info-section { margin-bottom: 72px; }
.m-info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.m-info-card { background: var(--panel); border: 1px solid var(--edge); border-radius: 16px; padding: 32px 28px; }
.m-info-card-label { font-family: var(--disp); font-size: 10px; letter-spacing: .20em; text-transform: uppercase; color: var(--gold); margin-bottom: 16px; }
.m-hours-row { display: flex; justify-content: space-between; align-items: center; padding: 11px 0; border-bottom: 1px solid rgba(38,38,44,.5); font-size: 14px; }
.m-hours-row:last-child { border-bottom: none; }
.m-hours-day { color: var(--dim); font-weight: 500; }
.m-hours-time { color: var(--txt); font-weight: 600; }
.m-hours-open { display: inline-flex; align-items: center; gap: 6px; }
.m-hours-dot { width: 7px; height: 7px; border-radius: 50%; background: #4ade80; box-shadow: 0 0 8px rgba(74,222,128,.6); flex-shrink: 0; }
.m-location-address { font-size: 15px; color: var(--txt); font-weight: 600; line-height: 1.5; margin-bottom: 6px; }
.m-location-sub { font-size: 13px; color: var(--dim); margin-bottom: 20px; }
.m-location-links { display: flex; flex-direction: column; gap: 10px; }
.m-loc-link { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--gold); text-decoration: none; }
.m-loc-link:hover { text-decoration: underline; }
/* Address doubles as the Get-directions link (Chris 2026-07-15). */
.m-location-addr-link { display: block; text-decoration: none; color: inherit; margin-bottom: 20px; }
.m-location-addr-link .m-location-sub { margin-bottom: 6px; }
.m-location-dir { font-size: 13px; font-weight: 700; color: var(--gold); }
.m-location-addr-link:hover .m-location-dir { text-decoration: underline; }
.m-loc-ig svg { flex: none; }

/* Final CTA */
.m-cta-section { padding: 80px 24px 96px; text-align: center; position: relative; }
.m-cta-glow { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 500px; height: 260px; background: radial-gradient(ellipse, rgba(255,209,102,.07) 0%, transparent 70%); pointer-events: none; }
.m-cta-headline { font-family: var(--disp); font-size: clamp(22px, 3.5vw, 36px); letter-spacing: .05em; color: var(--txt); margin-bottom: 10px; position: relative; }
.m-cta-sub { font-size: 15px; color: var(--dim); margin-bottom: 36px; position: relative; }
.m-cta-btn { display: inline-flex; align-items: center; gap: 10px; background: var(--gold); color: var(--bg); font-family: var(--disp); font-size: 13px; letter-spacing: .14em; text-transform: uppercase; font-weight: 700; text-decoration: none; padding: 18px 44px; border-radius: 50px; border: none; cursor: pointer; position: relative; box-shadow: 0 4px 32px rgba(255,209,102,.25); transition: box-shadow .2s, transform .15s; }
.m-cta-btn:hover { box-shadow: 0 6px 48px rgba(255,209,102,.38); transform: translateY(-1px); }
.m-cta-note { margin-top: 14px; font-size: 12px; color: var(--dim); position: relative; }

/* Footer */
.m-footer { border-top: 1px solid var(--edge); padding: 28px 24px; }
.m-footer-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.m-footer-brand { font-family: var(--disp); font-size: 12px; letter-spacing: .14em; color: var(--dim); text-transform: uppercase; }
.m-footer-links { display: flex; gap: 24px; flex-wrap: wrap; }
.m-footer-link { font-size: 12px; color: var(--dim); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 44px; }  /* 44px tap minimum (audit 2026-07-12) */
.m-footer-link:hover { color: var(--txt); }
.m-footer-copy { font-size: 11px; color: rgba(156,154,147,.5); }

/* Mobile (<900px) */
@media (max-width: 899px) {
  .m-trust-inner { flex-direction: column; align-items: stretch; }
  .m-trust-item { border-right: none; border-bottom: 1px solid var(--edge); padding: 14px 20px; flex: 1 1 auto; justify-content: flex-start; }
  .m-trust-item:last-child { border-bottom: none; }
  .m-section-header { padding: 26px 0 18px; }
  .m-packages-grid { grid-template-columns: 1fr 1fr; gap: 12px; }
  /* Mobile card: left-aligned larger white name leads; gold price sits in the bottom-right corner, smaller (2026-07-09). */
  .m-pkg-card { text-align: left; }
  /* Name keeps the global 30px cap — fitPkgNames() shrinks it to the 2-col card width. */
  .m-pkg-price { position: absolute; right: 18px; bottom: 18px; margin: 0; padding: 0; font-size: 14px; }
  .m-menu-cols { grid-template-columns: 1fr; gap: 48px; }
  .m-photo-strip { grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; }
  .m-photo-strip-item:first-child { grid-column: 1 / -1; aspect-ratio: 16/9; }
  .m-cred-inner { grid-template-columns: 1fr; text-align: center; gap: 20px; padding: 32px 0; }
  .m-cred-portrait { margin: 0 auto; }
  .m-cred-tags { justify-content: center; }
  .m-info-grid { grid-template-columns: 1fr; }
  .m-cta-section { padding: 64px 0 80px; }
  .m-cta-glow { width: 300px; height: 180px; }
  .m-footer-inner { flex-direction: column; align-items: flex-start; gap: 12px; }
  .m-footer-links { gap: 16px; }
}
@media (max-width: 520px) {
  .m-packages-grid { grid-template-columns: 1fr; }
  .m-pkg-card { padding: 22px 18px 20px; }
  .m-trust-item { flex: 1 1 100%; }
  .m-photo-strip { grid-template-columns: 1fr; }
  .m-photo-strip-item:first-child, .m-photo-strip-item:not(:first-child) { aspect-ratio: 4/3; }
}

/* ── benson-quickwins (2026-07-13) ──────────────────────────────────────────── */

/* A-1: optional gallery heading above the photo strip (sf.gallery_title, config-gated) */
.m-gallery-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 18px;
}
.m-gallery-title {
  font-family: var(--disp);
  font-size: 10px;
  letter-spacing: .20em;
  text-transform: uppercase;
  color: var(--gold);
}
/* Teaser link to the full /gallery page (media-hub lane, ADR-0024). Sits just under the 3-photo
   strip; the strip's own margin-bottom (72px) is pulled up so the link reads as part of the block. */
.m-gallery-more {
  display: inline-block;
  margin: -56px 0 72px;
  font-family: var(--disp);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gold);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 209, 102, .35);
  padding-bottom: 2px;
}
.m-gallery-more:hover { border-bottom-color: var(--gold); }

/* C-2: arrival note line in the location card (sf.arrival_note, config-gated) */
.m-arrival-note {
  font-size: 13px;
  color: var(--dim);
  margin: 6px 0 14px;
  line-height: 1.5;
}

/* C-3: arrival note inside the booking confirmed card */
.bk-arrival-note {
  margin-top: 4px;
  font-style: italic;
}

/* ── Modal selection summary (Chris 2026-07-19) ───────────────────────────────────────────────
   Sits above the day chips: the chosen service, any stacked extras, a running total, and the two
   ways to grow the booking (another service / another person). */
.bm-sel {
  margin: 0 0 1rem; padding: .85rem .9rem;
  background: rgba(255,255,255,.035); border: 1px solid var(--edge, rgba(255,255,255,.12));
  border-radius: 14px;
}
.bm-sel-h {
  font-family: var(--font-heading); font-size: .68rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--dim); margin-bottom: .55rem;
}
.bm-sel-row {
  display: flex; align-items: baseline; gap: .55rem; padding: .32rem 0;
  border-top: 1px solid rgba(255,255,255,.055);
}
.bm-sel-row:first-of-type { border-top: 0; }
.bm-sel-name { font-weight: 700; font-size: .95rem; flex: 1 1 auto; min-width: 0; }
.bm-sel-meta { font-size: .82rem; color: var(--dim); white-space: nowrap; flex: none; }
.bm-sel-x {
  flex: none; background: none; border: 0; cursor: pointer; padding: 2px 4px;
  font-size: .78rem; font-weight: 600; color: var(--dim); text-decoration: underline;
}
.bm-sel-x:hover { color: var(--gold); }
.bm-sel-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: .5rem;
  margin-top: .5rem; padding-top: .5rem; border-top: 1px solid rgba(255,255,255,.12);
  font-size: .88rem; color: var(--dim);
}
.bm-sel-total strong { color: var(--gold); font-size: .95rem; white-space: nowrap; }
.bm-sel { --bm-sel-gap: .6rem; }

/* Quick add-on grid (2026-07-19) — 2x2 toggles that replaced the "+ Add another service" dropdown.
   Row-major: row 1 = first two config ids, row 2 = third + the All Services / Clear all cell. */
.bm-quick-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: .5rem;
  margin-top: var(--bm-sel-gap);
}
.bm-quick {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px;
  min-height: 52px; padding: .5rem .7rem; cursor: pointer; text-align: left;
  font-family: var(--font-body); color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .06);
  border: 1.5px solid rgba(var(--pb-accent-rgb), .42); border-radius: 12px;
  transition: background .15s, border-color .15s, box-shadow .15s;
}
.bm-quick:hover { background: rgba(var(--pb-accent-rgb), .13); border-color: rgba(var(--pb-accent-rgb), .7); }
/* Selected: filled, so "on" is obvious at a glance across all four cells. */
.bm-quick-on {
  background: rgba(var(--pb-accent-rgb), .2); border-color: var(--pb-accent, #E8C36A);
  box-shadow: 0 0 12px rgba(var(--pb-accent-rgb), .22);
}
.bm-quick-name { font-weight: 700; font-size: .9rem; line-height: 1.15; }
.bm-quick-meta { font-size: .76rem; color: var(--dim); line-height: 1.15; }
.bm-quick-on .bm-quick-meta { color: rgba(var(--pb-accent-rgb), .85); }
/* "All Services" is a browse/reveal control, not an add-on — dashed until its menu is open. */
.bm-quick-all { border-style: dashed; }
.bm-quick-all.bm-quick-on { border-style: solid; }

/* Full menu revealed by "All Services": every bookable service as a tap-to-add row. */
.bm-allsvc {
  display: flex; flex-direction: column; gap: 6px; margin-top: var(--bm-sel-gap);
  padding: 10px; border-radius: 12px; border: 1px solid var(--edge);
  background: rgba(255,255,255,.02);
}
.bm-allsvc-row {
  display: flex; align-items: baseline; gap: 10px; width: 100%; cursor: pointer; text-align: left;
  padding: 10px 12px; min-height: 44px; border-radius: 10px;
  font-family: var(--font-body); color: var(--gold);
  background: rgba(var(--pb-accent-rgb), .05); border: 1.5px solid rgba(var(--pb-accent-rgb), .32);
  transition: background .15s, border-color .15s;
}
.bm-allsvc-row:hover { background: rgba(var(--pb-accent-rgb), .12); border-color: rgba(var(--pb-accent-rgb), .6); }
.bm-allsvc-on { background: rgba(var(--pb-accent-rgb), .18); border-color: var(--pb-accent, #E8C36A); }
.bm-allsvc-mark { flex: none; width: 1em; font-weight: 800; text-align: center; }
.bm-allsvc-name { flex: 1 1 auto; min-width: 0; font-weight: 700; font-size: .92rem; }
.bm-allsvc-meta { flex: none; font-size: .8rem; color: var(--dim); white-space: nowrap; }
.bm-allsvc-on .bm-allsvc-meta { color: rgba(var(--pb-accent-rgb), .85); }

.bm-sel-add { display: block; margin-top: var(--bm-sel-gap); }
.bm-sel-add select {
  width: 100%; min-height: 44px; padding: 0 .7rem; cursor: pointer;
  font-family: var(--font-body); font-size: .92rem; font-weight: 600; color: var(--gold);
  background: transparent; border: 1px dashed rgba(var(--pb-accent-rgb), .5); border-radius: 11px;
}
.bm-sel .bm-people { margin-top: var(--bm-sel-gap); }

/* ── Call-or-Text chooser (Chris 2026-07-19) ──────────────────────────────────────────────────
   Opened by the header phone button, which now shows the number alone. Bottom sheet on phones,
   centred dialog from 560px up — the same breakpoint and geometry the booking modal uses, so the
   two dialogs feel like one system. z-index clears the sticky stepper (20) and the nav drawer (8). */
.ph-backdrop {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0,0,0,.62); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
.ph-sheet {
  width: 100%; max-width: 460px; padding: 1.5rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom));
  background: var(--panel, #141416); border: 1px solid var(--edge, rgba(255,255,255,.12));
  border-bottom: 0; border-radius: 20px 20px 0 0; text-align: center;
  box-shadow: 0 -18px 48px -16px rgba(0,0,0,.9);
}
.ph-num {
  font-family: var(--font-body); font-weight: 800; font-size: 1.5rem; color: var(--gold);
  letter-spacing: .01em;
}
.ph-sub { margin: .4rem 0 1.15rem; font-size: .9rem; color: var(--dim); }
.ph-actions { display: flex; gap: .7rem; }
.ph-btn {
  flex: 1 1 0; display: inline-flex; align-items: center; justify-content: center; min-height: 52px;
  font-family: var(--font-body); font-weight: 800; font-size: 1rem; text-decoration: none;
  border-radius: 13px; border: 1.5px solid rgba(var(--pb-accent-rgb), .45); cursor: pointer;
}
.ph-btn-call { background: var(--gold); color: var(--pb-accent-ink, #101010); border-color: var(--gold); }
.ph-btn-text { background: transparent; color: var(--gold); }
.ph-btn-text:hover, .ph-btn-call:hover { filter: brightness(1.08); }
.ph-cancel {
  margin-top: .9rem; width: 100%; min-height: 44px; background: none; border: 0; cursor: pointer;
  font-family: var(--font-body); font-size: .92rem; font-weight: 600; color: var(--dim);
}
.ph-cancel:hover { color: var(--pb-text, #fff); }
@media (min-width: 560px) {
  .ph-backdrop { align-items: center; }
  .ph-sheet { border-radius: 20px; border-bottom: 1px solid var(--edge, rgba(255,255,255,.12)); }
}
