/* ==========================================================================
   BlueWater Wellness & MedSpa — design system
   Direction: DTC e-commerce (Gruns / Bloom / IM8), not luxury med spa.
   Bold type, chunky shapes, price-forward, zero marble.

   Single-hue system built on the logo blue (#0f7fcd). Hierarchy comes from
   value and saturation rather than a second colour: near-black navy grounds,
   a text-safe CTA blue, one cyan accent, and pale blue tints. Nothing warm.
   ========================================================================== */

/* ---------- Typefaces ---------- */
/* Self-hosted so there's no render-blocking third-party request and no
   dependency on a CDN staying up. Latin subsets only — 81 KB for all three. */
/* The brand faces. Both are licensed fonts, so the files are not in the repo
   — see public/fonts/README.md for exactly what to drop in. Until they land,
   every stack below falls through to Fraunces and Plus Jakarta Sans, which
   are here and which the site was designed on. Nothing breaks in the gap; the
   type just changes the day the files appear. */
@font-face {
  font-family: 'Timesquare';
  src: url('/fonts/timesquare-bold.woff2') format('woff2');
  /* One weight, claimed across the range. A static face declared at a single
     weight gets synthetically emboldened when something asks for more — this
     maps every request onto the real Bold instead. */
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'TT Travels';
  src: url('/fonts/tt-travels-regular.woff2') format('woff2');
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'TT Travels';
  src: url('/fonts/tt-travels-demibold.woff2') format('woff2');
  /* DemiBold covers 700 too, so the uppercase labels set at --w-label get the
     real face rather than a synthetic bold of the 600. */
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}

/* Fallbacks, present in the repo. */
@font-face {
  font-family: 'Fraunces';
  src: url('/fonts/fraunces.woff2') format('woff2');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/fonts/plus-jakarta-sans.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  /* This is a brand site, not a document — it commits to one visual world in
     both OS themes. Declaring the scheme stops browsers force-darkening form
     controls, which would break the palette rather than adapt it. */
  color-scheme: light;

  /* One hue, top to bottom. Range comes from value and saturation rather than
     a second colour — there is nothing warm in this system. */
  --ink: #06253d;
  --ink-2: #0c4067;
  --deep: #0a5487;
  --brand: #0f7fcd; /* the logo blue */
  --brand-bright: #3d9ce4;
  --sky: #6fc7f2;
  --sky-soft: #d9edfb;

  /* CTA — a half step deeper than the logo blue so white button text clears
     4.5:1. Reads as the same colour, measurably more legible. */
  --cta: #0a6cba;
  --cta-dark: #085795;

  /* The dark chrome: mobile header, menu drawer head, footer, dark bands,
     trust strip, calculator head. The button blue rather than the near-black
     navy, so the frame of the site carries the brand instead of receding to
     almost-black. --ink stays the type colour — this is surfaces only.
     White on it is 5.4:1, so the soft white text on these grounds had to come
     up from 0.72 to 0.92 to stay above 4.5:1. */
  --chrome: var(--cta);

  /* Accent — a soft mid blue, sitting between the brand and the pale tints.
     It carries the drawer promo bar, every accent badge, the cart count and
     the hero starburst. Always paired with ink text (5.5:1), never white:
     white lands at 2.9:1 on it. */
  --accent: #709dc6;
  --accent-soft: #a5dcf7;

  /* Neutrals, biased toward the brand hue so nothing reads grey or beige. */
  --cream: #f7fbfe;
  --sand: #e9f2fa;
  --sand-2: #d8e8f4;
  --white: #ffffff;
  --line: #dbe7f2;
  --line-strong: #b9d2e6;
  --muted: #566b7d;
  --muted-2: #8093a4;

  --ok: #128669;

  /* Type — a transitional serif for display, a quiet humanist sans for UI.
     The serif echoes the logo wordmark, which is where the pairing comes from.
     Libre Baskerville runs large for its size and reads best at regular
     weight, so headings are 400 and sizes are set a notch smaller than a
     grotesk would need. */
  /* Three roles, not two:
       --font-display  main titles and big headlines
       --font-title    product and card titles, labels, buttons
       --font-body     body copy and UI
     Title and body are the same family at different weights, which is the
     point — the split is so a card title can never drift into the display
     serif as the site grows. */
  --font-display: 'Timesquare', 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --font-title: 'TT Travels', 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', sans-serif;
  --font-body: 'TT Travels', 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', sans-serif;

  /* Weight scale. Nothing goes above 700, and 700 is reserved for small
     uppercase labels that need the extra weight to hold at 12px. */
  --w-display: 600;
  --w-body: 400;
  --w-medium: 500;
  --w-semi: 600;
  --w-label: 700;

  /* Shape */
  --r-sm: 10px;
  --r: 14px;
  --r-lg: 20px;
  --r-xl: 26px;
  --r-pill: 999px;

  --shadow-sm: 0 2px 8px rgba(6, 37, 61, 0.06);
  --shadow: 0 8px 30px rgba(6, 37, 61, 0.1);
  --shadow-lg: 0 24px 60px rgba(6, 37, 61, 0.16);
  --shadow-pop: 0 4px 0 var(--ink);

  --wrap: 1200px;
  --gut: clamp(18px, 4vw, 40px);
  --header-h: 68px;
}

/* ---------- Reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 20px);
}
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: var(--w-body);
  line-height: 1.65;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img,
svg,
video {
  max-width: 100%;
  display: block;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
button {
  cursor: pointer;
  border: 0;
  background: none;
}
a {
  color: inherit;
  text-decoration: none;
}
h1,
h2,
h3,
h4 {
  /* A serif needs more leading and far less negative tracking than a grotesk.
     Tighten much past this and the letterforms collide at display sizes. */
  line-height: 1.18;
  letter-spacing: -0.012em;
  margin: 0 0 0.5em;
  text-wrap: balance;
}
h1,
h2 {
  font-family: var(--font-display);
  font-weight: var(--w-display);
}
/* h3 and h4 are card and section-block titles rather than headlines, so they
   sit with the buttons and labels in the title face. */
h3,
h4 {
  font-family: var(--font-title);
  font-weight: var(--w-semi);
}
/* Libre Baskerville has a large x-height and runs big for its point size, so
   every step is set a notch smaller than the previous grotesk needed. */
h1 {
  font-size: clamp(2.1rem, 4.2vw, 3.25rem);
  line-height: 1.14;
}
h2 {
  font-size: clamp(1.7rem, 3.3vw, 2.5rem);
  line-height: 1.16;
}
h3 {
  font-size: clamp(1.25rem, 1.9vw, 1.55rem);
}
h4 {
  font-size: 1.05rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
p {
  margin: 0 0 1em;
  text-wrap: pretty;
}
ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
:focus-visible {
  outline: 3px solid var(--brand-bright);
  outline-offset: 3px;
  border-radius: 4px;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Layout ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.wrap-narrow {
  max-width: 780px;
}
.section {
  padding-block: clamp(56px, 9vw, 110px);
}
.section-tight {
  padding-block: clamp(40px, 6vw, 72px);
}
.stack > * + * {
  margin-top: var(--s, 16px);
}
.grid {
  display: grid;
  gap: clamp(16px, 2.4vw, 28px);
}
.g-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.g-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.g-4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 900px) {
  .g-3,
  .g-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 560px) {
  .g-2,
  .g-3,
  .g-4 {
    grid-template-columns: 1fr;
  }
}

/* ---------- Type helpers ---------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.74rem;
  font-weight: var(--w-semi);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cta);
  margin-bottom: 14px;
  font-family: var(--font-title);
}
.eyebrow::before {
  content: '';
  width: 22px;
  height: 3px;
  border-radius: 2px;
  background: var(--cta);
}
.lead {
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  color: var(--muted);
  line-height: 1.55;
}
.tiny {
  font-size: 0.82rem;
  color: var(--muted-2);
}
.center {
  text-align: center;
}
.center .eyebrow {
  justify-content: center;
}
/* A band under the baseline rather than a block behind the word — a serif's
   descenders otherwise sit in the fill and the whole line looks smudged. */
.hl {
  background: linear-gradient(
    180deg,
    transparent 66%,
    var(--accent-soft) 66%,
    var(--accent-soft) 92%,
    transparent 92%
  );
  padding-inline: 2px;
}
.hl-aqua {
  background: linear-gradient(180deg, transparent 66%, var(--sky) 66%, var(--sky) 92%, transparent 92%);
}

/* ---------- Buttons ---------- */
.btn {
  --bg: var(--ink);
  --fg: var(--white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 15px 28px;
  background: var(--bg);
  color: var(--fg);
  border-radius: var(--r-pill);
  font-family: var(--font-title);
  font-weight: var(--w-semi);
  font-size: 1rem;
  letter-spacing: -0.01em;
  transition: transform 0.14s ease, box-shadow 0.14s ease, background 0.14s ease;
  text-align: center;
  white-space: nowrap;
}
.btn:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
.btn:active {
  transform: translateY(0);
}
.btn-primary {
  --bg: var(--cta);
  --fg: #fff;
}
.btn-primary:hover {
  --bg: var(--cta-dark);
}
.btn-ink {
  --bg: var(--ink);
}
.btn-brand {
  --bg: var(--brand);
}
.btn-white {
  --bg: #fff;
  --fg: var(--ink);
}
.btn-ghost {
  --bg: transparent;
  --fg: var(--ink);
  border: 1px solid var(--line-strong);
}
.btn-ghost:hover {
  --bg: var(--ink);
  --fg: #fff;
}
.btn-lg {
  padding: 19px 38px;
  font-size: 1.08rem;
}
.btn-sm {
  padding: 10px 18px;
  font-size: 0.88rem;
}
.btn-block {
  display: flex;
  width: 100%;
}
.btn[disabled] {
  opacity: 0.45;
  pointer-events: none;
}
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* ---------- Badges & pills ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  font-size: 0.72rem;
  font-weight: var(--w-semi);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--ink);
  color: #fff;
  white-space: nowrap;
  font-family: var(--font-title);
}
.badge-accent {
  background: var(--accent);
  color: var(--ink);
}
.badge-brand {
  background: var(--cta);
  color: #fff;
}
/* Sale flag. The one place on the site that uses the brand blue at full
   strength on a badge, so a discount never reads as just another label. */
.badge-sale {
  background: var(--cta);
  color: #fff;
}
.badge-sky {
  background: var(--accent-soft);
  color: var(--ink);
}
.badge-soft {
  background: var(--sand);
  color: var(--ink-2);
}
.badge-outline {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--line);
}

.pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ---------- Cards ---------- */
.card {
  background: var(--white);
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  overflow: hidden;
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.card-soft {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--white);
}
.card-lift:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 34px rgba(6, 37, 61, 0.13);
}
.card-pad {
  padding: clamp(20px, 3vw, 32px);
}

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(247, 251, 254, 0.94);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: 20px;
}
.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.logo-full {
  height: auto;
  width: 176px;
  max-width: 100%;
}
.logo-mark {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
}
.logo-footer .logo-full {
  width: 190px;
}
/* White lockup for the dark mobile header/drawer — hidden until that breakpoint kicks in below. */
.logo-full-mobile {
  display: none;
  width: 120px;
}
.mn-head .logo-full {
  width: 116px;
}

/* The three dark grounds. The real logo files are flat blue art on
   transparency, and an <img> can't be recoloured by an attribute the way the
   SVG fallback can — this knocks any ink to pure white while leaving the
   alpha edges intact. A no-op on the SVG fallback, which is already white
   in these three places. */
.logo-footer .logo-full,
.mn-head .logo-full,
.logo-full-mobile {
  filter: brightness(0) invert(1);
}
.nav {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}
.nav-item {
  position: relative;
}
.nav-link {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 9px 13px;
  border-radius: var(--r-pill);
  font-weight: var(--w-semi);
  font-size: 0.93rem;
  white-space: nowrap;
  transition: background 0.14s;
}
.nav-link:hover {
  background: var(--sand);
}
.nav-link.is-highlight {
  color: var(--cta);
}
.nav-caret {
  width: 10px;
  height: 10px;
  opacity: 0.5;
  transition: transform 0.16s;
}
.nav-item:hover .nav-caret {
  transform: rotate(180deg);
}
.nav-drop {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 250px;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  padding: 8px;
  box-shadow: 0 12px 30px rgba(6, 37, 61, 0.13);
  opacity: 0;
  visibility: hidden;
  transition: all 0.16s ease;
}
.nav-item:hover .nav-drop,
.nav-item:focus-within .nav-drop {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}
.nav-drop a {
  display: block;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  font-weight: var(--w-semi);
  font-size: 0.92rem;
}
.nav-drop a:hover {
  background: var(--sand);
}
.header-left {
  display: none;
  align-items: center;
  gap: 2px;
}
.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.icon-btn {
  position: relative;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  transition: background 0.14s;
}
.icon-btn:hover {
  background: var(--sand);
}
.cart-count {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--cta);
  color: #fff;
  font-size: 0.68rem;
  font-weight: var(--w-label);
  display: grid;
  place-items: center;
}
.cart-count[data-empty='true'] {
  display: none;
}
.burger {
  display: none;
}
.header-cta {
  display: inline-flex;
}

/* Below this width the header switches to the app-style pattern: dark bar,
   menu + search on the left, centered logo, cart on the right. No header CTA
   text — the drawer's bottom CTA and the tiles carry that job on phones. */
@media (max-width: 1080px) {
  .nav {
    display: none;
  }
  .burger {
    display: grid;
  }
  .site-header {
    background: var(--chrome);
    border-bottom: none;
  }
  /* Equal side columns, not `auto 1fr auto` — with auto sides the middle
     column absorbs the difference between them, and two icons on the left
     against one on the right shoved the logo 22px right of true centre. */
  .header-inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 4px;
    height: 60px;
  }
  .header-inner > * {
    min-width: 0;
  }
  .header-left {
    display: flex;
    justify-self: start;
  }
  .site-header .logo {
    justify-self: center;
  }
  .site-header .logo .logo-full:not(.logo-full-mobile) {
    display: none;
  }
  .logo-full-mobile {
    display: block;
  }
  .site-header .header-actions {
    justify-self: end;
  }
  .site-header .icon-btn.hide-mobile,
  .site-header .header-cta {
    display: none;
  }
  .site-header .icon-btn,
  .site-header .burger {
    color: #fff;
  }
  .site-header .icon-btn:hover,
  .site-header .burger:hover {
    background: rgba(255, 255, 255, 0.14);
  }
  .site-header .cart-count {
    background: var(--accent);
    color: var(--ink);
  }
}

/* On a 320px screen the full-width lockup runs into the menu and search
   buttons. Nothing else needs to move — the logo just comes down a size. */
@media (max-width: 359px) {
  .logo-full-mobile {
    width: 96px;
  }
}

/* Mobile nav — a dark head row (close/search/logo/cart), a bright promo bar,
   circular category tiles, two collapsed link sections, and a bottom CTA. */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--cream);
  transform: translateX(100%);
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
}
.mobile-nav.is-open {
  transform: translateX(0);
}
.mn-head {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  align-items: center;
  gap: 2px;
  background: var(--chrome);
  padding: 12px var(--gut);
}
.mn-head .logo {
  justify-self: center;
}
.mn-head .icon-btn {
  color: #fff;
}
.mn-head .icon-btn:hover {
  background: rgba(255, 255, 255, 0.14);
}
.mn-head .cart-count {
  background: var(--accent);
  color: var(--ink);
}
.mn-promo {
  display: block;
  background: var(--accent);
  color: var(--ink);
  text-align: center;
  font-weight: var(--w-semi);
  font-size: 0.86rem;
  padding: 10px var(--gut);
}
.mn-body {
  padding: 22px var(--gut) 50px;
}
.mn-tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 28px;
}
.mn-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
}
.mn-tile-ico {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--sky-soft);
  color: var(--cta);
  display: grid;
  place-items: center;
  transition: background 0.14s, color 0.14s;
}
.mn-tile:active .mn-tile-ico {
  background: var(--cta);
  color: #fff;
}
.mn-tile span:last-child {
  font-size: 0.72rem;
  font-weight: var(--w-semi);
  line-height: 1.2;
}
.mn-acc {
  margin-bottom: 26px;
}
/* The last item's rule and .mn-bottom's rule were drawing two lines 26px
   apart with nothing between them. Let .mn-bottom draw the divider. */
.mn-acc .acc-item:last-child {
  border-bottom: 0;
}
.mn-acc-group {
  padding-bottom: 6px;
}
.mn-acc-group h5 {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin: 14px 0 2px;
}
.mn-acc-group:first-child h5 {
  margin-top: 0;
}
.mn-acc .acc-panel a,
.mn-acc .acc-panel > div > a {
  display: block;
  padding: 9px 0;
  font-weight: var(--w-semi);
  font-size: 0.98rem;
}
.mn-bottom {
  border-top: 1px solid var(--line);
  padding-top: 22px;
}
/* Call and text, stacked. Both are real tel:/sms: links — the number is the
   same line either way, so the only thing that changes is which app opens. */
.mn-contact {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-top: 12px;
  padding: 13px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  font-weight: var(--w-semi);
  color: var(--ink);
  text-decoration: none;
}
.mn-contact svg {
  flex: none;
  color: var(--cta);
}
.mn-contact-alt {
  border-style: dashed;
  font-weight: var(--w-medium);
  color: var(--ink-2);
}
.mn-tagline {
  margin-top: 14px;
  text-align: center;
  font-size: 0.78rem;
  color: var(--muted-2);
}

/* Search panel — opened from the header or the drawer, on every page. */
.search-panel {
  position: fixed;
  inset: 0;
  z-index: 230;
  background: var(--cream);
  transform: translateY(-100%);
  transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
}
.search-panel.is-open {
  transform: translateY(0);
}
.search-panel-inner {
  padding-block: 18px 50px;
}
.search-panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.search-field {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border: 2px solid var(--line);
  border-radius: var(--r-pill);
  background: #fff;
  color: var(--muted-2);
}
.search-field input {
  flex: 1;
  border: 0;
  outline: none;
  background: transparent;
  font-size: 1rem;
  color: var(--ink);
  font-family: inherit;
}
.search-field input::placeholder {
  color: var(--muted-2);
}
.search-results {
  margin-top: 18px;
}
.search-hint {
  color: var(--muted-2);
  font-size: 0.92rem;
  padding: 14px 2px;
}
.search-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 2px;
  border-bottom: 1px solid var(--line);
}
.search-result strong {
  display: block;
  font-family: var(--font-title);
  font-weight: var(--w-semi);
  font-size: 1.05rem;
  letter-spacing: -0.008em;
}
.search-result .tiny {
  display: block;
  color: var(--muted);
  margin-top: 2px;
}
.search-result-arrow {
  flex-shrink: 0;
  color: var(--muted-2);
}

/* ---------- Quiz teaser (home) ---------- */
.quiz-teaser {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: clamp(24px, 4vw, 52px);
  align-items: center;
  padding: clamp(24px, 4vw, 46px);
  border-radius: var(--r-xl);
  background: linear-gradient(150deg, var(--sky-soft) 0%, #cfe8fa 55%, #bfe0f8 100%);
  border: 1px solid var(--brand);
  box-shadow: 0 18px 44px rgba(6, 37, 61, 0.14);
  position: relative;
  overflow: hidden;
}
/* Soft light bloom behind the tiles so the panel isn't one flat wash. */
.quiz-teaser::after {
  content: '';
  position: absolute;
  right: -140px;
  top: -160px;
  width: 460px;
  height: 460px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.75), transparent 70%);
  pointer-events: none;
}
.quiz-teaser-copy,
.quiz-teaser-pick {
  position: relative;
  z-index: 1;
  min-width: 0;
}
.quiz-teaser-copy h2 {
  margin: 14px 0 10px;
  font-size: clamp(1.9rem, 3.6vw, 2.9rem);
}
.quiz-teaser-copy p {
  color: var(--ink-2);
  font-size: 1.06rem;
}

/* The 5 answer steps, as a compact rail — shows how short the quiz is. */
.qt-steps {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  margin: 20px 0 24px;
}
.qt-step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.76rem;
  font-weight: var(--w-semi);
  color: var(--ink-2);
  white-space: nowrap;
}
.qt-step i {
  display: grid;
  place-items: center;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  font-style: normal;
  font-size: 0.66rem;
  font-weight: var(--w-label);
}
.qt-dash {
  width: 12px;
  height: 1px;
  background: var(--line-strong);
  flex-shrink: 0;
}

.qt-lead {
  font-size: 0.76rem;
  font-weight: var(--w-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--deep);
  margin-bottom: 12px;
}
.qt-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.qt-tile {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 15px 14px 16px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color 0.14s, transform 0.14s, box-shadow 0.14s;
}
.qt-tile:hover {
  border-color: var(--cta);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(6, 37, 61, 0.12);
}
.qt-ico {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--sky-soft);
  color: var(--cta);
  margin-bottom: 8px;
}
.qt-ico svg {
  width: 19px;
  height: 19px;
}
.qt-label {
  font-weight: var(--w-semi);
  font-size: 0.92rem;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.qt-sub {
  font-size: 0.76rem;
  color: var(--muted);
  line-height: 1.35;
}
.qt-all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  font-size: 0.88rem;
  font-weight: var(--w-semi);
  color: var(--cta);
}
.qt-all svg {
  width: 16px;
  height: 16px;
}
@media (max-width: 900px) {
  .quiz-teaser {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 560px) {
  .qt-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The split hero this replaced — headline beside a photo with floating price
   cards — is gone; the homepage hero is now the full-bleed carousel further
   down this file. Only the star row survived, and other pages still use it. */
.stars {
  display: inline-flex;
  gap: 2px;
  color: var(--brand);
}

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
  }
}

/* Trust strip */
.trust-strip {
  background: var(--chrome);
  color: #fff;
  padding: 16px 0;
  overflow: hidden;
}
.trust-track {
  display: flex;
  gap: 44px;
  align-items: center;
  white-space: nowrap;
  animation: scroll-x 34s linear infinite;
  width: max-content;
}
@keyframes scroll-x {
  to {
    transform: translateX(-50%);
  }
}
.trust-item {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-weight: var(--w-semi);
  font-size: 0.92rem;
  letter-spacing: -0.01em;
}
.trust-item svg {
  color: var(--sky);
  flex-shrink: 0;
}

/* A clip in the gallery strip. The thumb is a plain image — its poster —
   styled by the shared .gallery-thumb img rule, so it is indistinguishable
   from the photographs beside it. No play badge: the strip is small enough
   that a glyph in the middle covers the shot it is meant to preview. */
/* Fills the slot, same as a photo does. The clip is 9:16 and the stage is
   square, so cover crops top and bottom rather than letterboxing — Cole's
   call, and it is the right one for a strip where every other slot is a
   full-bleed photo. `object-position` favours the upper middle, which is
   where a face sits in a vertical clip. */
.gallery-stage video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
  background: var(--ink);
  display: block;
}

/* The honeypot on every lead form. Off-screen rather than display:none —
   some bots skip hidden inputs, and one that is technically visible but
   nowhere near the page gets filled in, which is the entire point. Screen
   readers skip it on aria-hidden and it is out of the tab order. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* ---------- Value props ----------
   Big soft-tinted circles with the label centred underneath, in the shape of
   a flavour picker rather than a stat row — the point is that each one reads
   as its own thing at a glance, not as four entries in a table.

   One tint across all four. The row is a set of equal facts, not a sequence,
   and a gradient across it implied an order that the icons and labels already
   carry on their own.

   Four columns is the usual case, but the count comes from the template so a
   service listing three keeps its circles evenly spread under the price
   instead of leaving a gap on the right. */
.vprops {
  display: grid;
  grid-template-columns: repeat(var(--vprop-cols, 4), minmax(0, 1fr));
  /* Circle, value, caption — three rows shared by all four columns, so a
     value that wraps to two lines pushes every caption down together
     instead of dropping its own out of line with the rest. "Free touch-up"
     wraps at phone widths and was hanging a row below its neighbours. */
  grid-template-rows: auto auto auto;
  column-gap: clamp(4px, 1.6vw, 16px);
  row-gap: 9px;
  margin: 20px 0 6px;
  padding: 0;
  list-style: none;
}
.vprop {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  justify-items: center;
  align-content: start;
  text-align: center;
  min-width: 0;
}
/* Subgrid is what does the aligning. Without it the columns are independent
   again, so the fallback keeps them readable rather than pretending. */
@supports not (grid-template-rows: subgrid) {
  .vprop {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
  }
}
.vprop-ring {
  display: grid;
  place-items: center;
  width: clamp(52px, 15vw, 74px);
  height: clamp(52px, 15vw, 74px);
  border-radius: 50%;
  background: var(--sky-soft);
  color: var(--deep);
  flex: none;
}
.vprop-ring svg {
  width: clamp(21px, 5.6vw, 29px);
  height: clamp(21px, 5.6vw, 29px);
  stroke-width: 1.7;
}
.vprop-value {
  font-family: var(--font-title);
  font-size: clamp(0.78rem, 2.4vw, 0.98rem);
  font-weight: var(--w-semi);
  line-height: 1.22;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}
/* The proof under the promise. Deliberately quiet — the reference this is
   modelled on carries one label per circle, and a second line at the same
   weight would turn a picker back into a table. */
.vprop-label {
  margin-top: -3px;
  font-size: clamp(0.66rem, 2vw, 0.74rem);
  line-height: 1.35;
  color: var(--muted-2);
  text-wrap: balance;
}

/* ---------- Payment option card ---------- */
.pay-grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  align-items: start;
}
.pay-grid-2 {
  max-width: 860px;
  margin-inline: auto;
}
.pay {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: clamp(20px, 2.4vw, 26px);
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
}
.pay-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}
.pay-name {
  font-family: var(--font-title);
  font-size: 1.28rem;
  font-weight: var(--w-semi);
  letter-spacing: -0.012em;
  line-height: 1.14;
  margin: 0;
}
.pay-by {
  font-size: 0.74rem;
  font-weight: var(--w-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
  font-family: var(--font-title);
}
/* "Covers · Botox Cosmetic and Juvéderm" — the one fact that decides whether
   a programme is worth joining, so it sits above the prose rather than in it. */
.pay-covers {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
  margin: 0;
  padding: 9px 12px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--r);
  font-size: 0.85rem;
  font-weight: var(--w-semi);
  color: var(--ink);
}
.pay-covers span {
  font-family: var(--font-title);
  font-size: 0.7rem;
  font-weight: var(--w-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.pay-text {
  margin: 0;
  color: var(--muted);
  font-size: 0.93rem;
  line-height: 1.6;
}
.pay-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: auto;
  padding-top: 6px;
  font-family: var(--font-title);
  font-size: 0.83rem;
  font-weight: var(--w-label);
  color: var(--brand);
  text-decoration: none;
}
.pay-link:hover {
  text-decoration: underline;
}
.pay-link svg {
  width: 14px;
  height: 14px;
}

/* ---------- Provider card ----------
   A row per provider rather than a grid of thumbnails: a bio is the point of
   this page, and a bio does not fit under a square photo in a three-across
   grid. Stacks to photo-over-text on a phone. */
.prov-grid {
  display: grid;
  gap: clamp(20px, 3vw, 32px);
}
.prov {
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: clamp(18px, 3vw, 34px);
  align-items: start;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.prov-photo {
  aspect-ratio: 1;
  background: var(--sand);
  /* The placeholder art carries a filename label that is wider than a 190px
     column, and without this it printed across the bio beside it. */
  overflow: hidden;
}
.prov-photo img,
.prov-photo svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.prov-body {
  padding: clamp(18px, 2.4vw, 28px) clamp(18px, 2.4vw, 28px) clamp(20px, 2.6vw, 30px) 0;
}
.prov-name {
  font-family: var(--font-title);
  font-size: clamp(1.3rem, 2.4vw, 1.65rem);
  font-weight: var(--w-semi);
  letter-spacing: -0.014em;
  line-height: 1.12;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.prov-cred {
  font-family: var(--font-title);
  font-size: 0.82rem;
  font-weight: var(--w-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--brand);
}
.prov-role {
  margin: 5px 0 0;
  font-size: 0.86rem;
  font-weight: var(--w-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  font-family: var(--font-title);
}
.prov-bio {
  margin: 12px 0 0;
  color: var(--ink-2);
  line-height: 1.62;
}
.prov-treats {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin-top: 16px;
}
.prov-treats-k {
  font-size: 0.72rem;
  font-weight: var(--w-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-right: 2px;
  font-family: var(--font-title);
}
.prov-chip {
  display: inline-flex;
  padding: 5px 11px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.79rem;
  font-weight: 600;
  color: var(--ink-2);
  text-decoration: none;
  background: var(--cream);
}
.prov-chip:hover {
  border-color: var(--brand);
  color: var(--brand);
}
/* Front of house: a face and a job, no bio to make room for. */
.prov-mini-grid {
  display: grid;
  gap: clamp(14px, 2vw, 22px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}
.prov-mini {
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  padding-bottom: 18px;
  text-align: center;
}
.prov-mini-photo {
  aspect-ratio: 1;
  background: var(--sand);
  overflow: hidden;
  margin-bottom: 14px;
}
.prov-mini-photo img,
.prov-mini-photo svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.prov-mini-name {
  font-family: var(--font-title);
  font-size: 1.1rem;
  font-weight: var(--w-semi);
  line-height: 1.15;
  padding-inline: 14px;
}
.prov-mini-role {
  margin: 4px 0 0;
  padding-inline: 14px;
  font-size: 0.78rem;
  font-weight: var(--w-label);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  font-family: var(--font-title);
}
/* Two across once there is room, so nine clinical cards are not nine full
   screens of scrolling. Below this the row card stacks instead. */
@media (min-width: 1080px) {
  .prov-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .prov {
    grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
    gap: 20px;
  }
}
@media (max-width: 720px) {
  .prov {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }
  .prov-photo {
    aspect-ratio: 3 / 2;
  }
  .prov-body {
    padding: 20px 20px 24px;
  }
}

/* ---------- Promotion card ----------
   Wider than a product card and laid out side-by-side on desktop, because a
   promotion has to carry its conditions. A treatment card sells the treatment
   in a glance; this one has to survive being read. */
.promo-grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  align-items: start;
}
.promo {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  height: 100%;
}
.promo-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--sand);
  overflow: hidden;
}
.promo-media img,
.promo-media svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.promo-flag {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
}
.promo-body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}
.promo-title {
  font-family: var(--font-title);
  font-size: 1.32rem;
  font-weight: var(--w-semi);
  letter-spacing: -0.014em;
  line-height: 1.14;
}
.promo-hook {
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.55;
}
/* The figure block. A price cut and a freebie land in the same spot so two
   cards side by side stay comparable, even though one has no price at all. */
.promo-figure {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  padding: 12px 14px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.promo-now,
.promo-free {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: var(--w-display);
  line-height: 1;
  color: var(--cta);
}
.promo-now small {
  font-size: 0.9rem;
  font-weight: 600;
}
.promo-fig-sub {
  flex-basis: 100%;
  font-size: 0.78rem;
  color: var(--muted);
}
.promo-qualify {
  font-size: 0.85rem;
  font-weight: var(--w-label);
  color: var(--ink-2);
}
.promo-terms {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 6px;
  font-size: 0.8rem;
  color: var(--muted);
}
.promo-terms li {
  padding-left: 15px;
  position: relative;
  line-height: 1.5;
}
.promo-terms li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--line-strong);
}
.promo-foot {
  margin-top: auto;
  padding-top: 6px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
}
.promo-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.83rem;
  font-weight: var(--w-label);
  color: var(--brand);
  text-decoration: none;
}
.promo-link:hover {
  text-decoration: underline;
}
.promo-link svg {
  width: 14px;
  height: 14px;
}
/* Two offers should not stretch to half a 1400px page each. */
.promo-grid-home {
  max-width: 900px;
  margin-inline: auto;
}

/* ---------- Product card ---------- */
.p-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform 0.16s ease, box-shadow 0.16s ease;
  height: 100%;
}
.p-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 14px 34px rgba(6, 37, 61, 0.13);
}
.p-media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--sand);
  overflow: hidden;
}
.p-media img,
.p-media svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.p-badges {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}
.p-body {
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 8px;
}
.p-name {
  font-family: var(--font-title);
  font-size: 1.22rem;
  font-weight: var(--w-semi);
  letter-spacing: -0.012em;
  line-height: 1.1;
}
.p-tag {
  font-size: 0.9rem;
  color: var(--muted);
  line-height: 1.45;
  flex: 1;
}
.p-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 600;
}
.p-foot {
  display: flex;
  /* Wraps rather than clipping. A price like "$499/syringe" is a single
     unbreakable token, so when it and the button do not fit on one line the
     button has to move down — without this it simply rendered past the card's
     edge, and `.p-card` has `overflow: hidden`, so it was cut in half. */
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px 12px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.p-foot > div {
  min-width: 0;
}
.p-foot .btn {
  flex-shrink: 0;
  /* Keeps the button right-aligned on the rare width where it still wraps
     onto its own line — space-between would otherwise park it at the left. */
  margin-left: auto;
}
.p-price {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: var(--w-display);
  letter-spacing: -0.012em;
  line-height: 1;
}
.p-price small {
  font-size: 0.7rem;
  font-weight: var(--w-semi);
  color: var(--muted-2);
  letter-spacing: 0;
}
.p-price-from {
  display: block;
  font-family: var(--font-title);
  font-size: 0.68rem;
  font-weight: var(--w-semi);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-bottom: 3px;
}

/* Placeholder art */
.ph {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  position: relative;
}
.ph-label {
  position: absolute;
  bottom: 10px;
  left: 10px;
  right: 10px;
  font-size: 0.66rem;
  font-weight: var(--w-semi);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  /* Scaffolding, but it is real text on a live page until the photos land,
     so it carries its weight against AA on the lightest placeholder tint. */
  color: rgba(6, 37, 61, 0.7);
  text-align: center;
}

/* ---------- PDP (product detail page) ---------- */
.pdp {
  padding-block: clamp(24px, 4vw, 44px) clamp(50px, 7vw, 80px);
}
.breadcrumbs {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 0.82rem;
  color: var(--muted-2);
  font-weight: 600;
  margin-bottom: 22px;
  flex-wrap: wrap;
}
.breadcrumbs a:hover {
  color: var(--cta);
}
.pdp-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
@media (max-width: 940px) {
  .pdp-grid {
    grid-template-columns: 1fr;
  }
}
.pdp-gallery {
  position: sticky;
  top: calc(var(--header-h) + 20px);
}
@media (max-width: 940px) {
  .pdp-gallery {
    position: static;
  }
}
.gallery-main {
  aspect-ratio: 1;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  overflow: hidden;
  background: var(--sand);
  position: relative;
}
/* Every other art container carries this pair; the gallery never did, because
   until a real photo landed both slots held a .ph, which sizes itself. A real
   <img> falls back to its width/height attributes instead — so the first
   photo dropped in rendered at 900px inside a 354px box, cropped to its own
   top-left corner. */
.gallery-main img,
.gallery-main .ph,
.gallery-stage,
.gallery-thumb img,
.gallery-thumb .ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Arrows on the image itself. Desktop only — on a phone the thumb strip sits
   directly under the photo and the image takes a swipe, so a pair of tap
   targets sitting over the picture would be in the way rather than useful. */
.gallery-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  cursor: pointer;
  opacity: 0;
  box-shadow: 0 2px 10px rgba(6, 37, 61, 0.18);
  transition: opacity 0.16s ease, background 0.16s ease;
}
.gallery-main:hover .gallery-nav,
.gallery-nav:focus-visible {
  opacity: 1;
}
.gallery-nav:hover {
  background: #fff;
}
.gallery-prev {
  left: 12px;
}
.gallery-next {
  right: 12px;
}
@media (max-width: 940px) {
  .gallery-nav {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .gallery-nav {
    transition: none;
  }
}
/* auto-fit, so four photos sit four across exactly as before and six sit six
   across — the count comes from what's on disk, not from a fixed grid. */
.gallery-thumbs {
  display: grid;
  /* One track per tile, so the strip is always a single row — auto-fit wrapped
     the fifth tile onto a line of its own as soon as five at full size did not
     fit. Each track is capped at 104px, which is what five came to when they
     stretched to fill the row, and shrinks below that only when the row is too
     narrow to hold them all. Fewer tiles therefore stay tile-sized rather than
     growing to half the stage. */
  grid-template-columns: repeat(var(--thumbs, 4), minmax(0, 104px));
  justify-content: start;
  gap: 10px;
  margin-top: 10px;
}
/* Always 2 columns, phone included — unlike .g-2, which drops to a single
   column under 560px and turns these four short badges into a tall stack. */
.pdp-trust-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 16px;
}
.gallery-thumb {
  aspect-ratio: 1;
  border-radius: var(--r-sm);
  border: 2px solid var(--line);
  overflow: hidden;
  background: var(--sand);
  transition: border-color 0.14s;
}
.gallery-thumb[aria-selected='true'] {
  border-color: var(--cta);
  box-shadow: inset 0 0 0 1px var(--cta);
}

.pdp-title {
  font-size: clamp(1.85rem, 3.4vw, 2.6rem);
  margin-bottom: 10px;
}
.pdp-tagline {
  font-size: 1.12rem;
  color: var(--ink-2);
  font-weight: 600;
  margin-bottom: 16px;
}
.pdp-rating {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.9rem;
  font-weight: var(--w-semi);
  margin-bottom: 20px;
}
.pdp-rating a {
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.price-block {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.price-now {
  font-family: var(--font-display);
  font-size: 2.15rem;
  font-weight: var(--w-display);
  letter-spacing: -0.015em;
  line-height: 1;
}
.price-unit {
  font-size: 1rem;
  font-weight: var(--w-semi);
  color: var(--muted);
}

/* ---------- Sale pricing ----------
   `.price-was` collapses to nothing when it's empty, so every price on the
   site can carry one unconditionally and it only appears during a sale. */
.price-was {
  color: var(--muted-2);
  font-weight: 400;
  text-decoration-thickness: 1px;
  margin-right: 8px;
}
.price-was:empty {
  display: none;
  margin: 0;
}
.price-block .price-was {
  font-family: var(--font-display);
  font-size: 1.35rem;
  order: -1;
}
.p-price .price-was,
.opt-price .price-was,
.compare .price-was {
  font-size: 0.82em;
  margin-right: 6px;
}
.opt-price .price-was,
.compare .price-was {
  display: block;
  margin-right: 0;
}
.price-now.is-sale,
.p-price.is-sale,
.compare strong.is-sale {
  color: var(--cta);
}
.price-member {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: var(--r-pill);
  background: var(--sky-soft);
  color: var(--deep);
  font-size: 0.83rem;
  font-weight: var(--w-semi);
}
.price-note {
  font-size: 0.88rem;
  color: var(--muted);
  margin-bottom: 22px;
}

/* A note under the option list — where the choice itself needs explaining,
   rather than the price above it. Indented to the rows it belongs to. */
.opt-note {
  margin: 10px 2px 0;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--muted);
}

/* Variant selector */
.opt-group {
  margin-bottom: 24px;
}
.opt-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.76rem;
  font-weight: var(--w-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 11px;
  font-family: var(--font-title);
}
.opt-list {
  display: grid;
  gap: 10px;
}
.opt {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  gap: 13px;
  align-items: center;
  width: 100%;
  padding: 15px 17px;
  border: 2px solid var(--line);
  border-radius: var(--r);
  background: #fff;
  text-align: left;
  transition: border-color 0.14s, background 0.14s;
}
.opt:hover {
  border-color: var(--muted-2);
}
.opt[aria-pressed='true'] {
  border-color: var(--cta);
  background: var(--sky-soft);
  box-shadow: inset 0 0 0 1px var(--cta);
}
.opt-radio {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--line);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.opt[aria-pressed='true'] .opt-radio {
  border-color: var(--cta);
}
.opt[aria-pressed='true'] .opt-radio::after {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--cta);
}
.opt-name {
  font-weight: var(--w-semi);
  font-size: 1rem;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.opt-sub {
  display: block;
  font-size: 0.84rem;
  color: var(--muted);
  margin-top: 2px;
}
.opt-price {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: 1.05rem;
  letter-spacing: -0.008em;
  text-align: right;
  white-space: nowrap;
}
.opt-price small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.7rem;
  color: var(--cta);
  font-weight: var(--w-semi);
}

/* Comparison table inside PDP */
.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.compare th,
.compare td {
  padding: 13px 14px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.compare th {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted-2);
  font-weight: var(--w-label);
}
.compare tbody tr:hover {
  background: var(--cream);
}
.compare-wrap {
  overflow-x: auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: #fff;
}
.compare-wrap table {
  min-width: 620px;
}

/* Add-ons */
.addon {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 13px 15px;
  border: 2px solid var(--line);
  border-radius: var(--r);
  background: #fff;
  width: 100%;
  text-align: left;
  transition: border-color 0.14s;
}
.addon[aria-pressed='true'] {
  border-color: var(--cta);
  background: var(--sky-soft);
}
.addon-check {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  border: 2px solid var(--line);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: transparent;
}
.addon[aria-pressed='true'] .addon-check {
  background: var(--ink);
  border-color: var(--line-strong);
  color: #fff;
}
.calc-area[aria-pressed='true'] .addon-check {
  background: var(--cta);
  border-color: var(--cta);
  color: #fff;
}
.addon-body {
  flex: 1;
  min-width: 0;
}
.addon-name {
  display: block;
  font-weight: var(--w-semi);
  font-size: 0.94rem;
}
.addon-desc {
  display: block;
  font-size: 0.82rem;
  color: var(--muted);
}
/* Why a line says "Free". The price is conditional and the condition is the
   offer, so it sits with the line rather than in fine print at the bottom —
   somebody reading "Free" should find out why in the same glance. */
.addon-note {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--sky-soft);
  color: var(--deep);
  font-family: var(--font-title);
  font-size: 0.71rem;
  font-weight: var(--w-label);
  line-height: 1.3;
}

.addon-price {
  font-weight: var(--w-semi);
  font-size: 0.94rem;
  white-space: nowrap;
  font-family: var(--font-title);
}
/* The unit on a rate-priced line — "from $7.99 per unit". Quieter than the
   figure, and it needs the gap the markup can't carry. */
.addon-price small {
  margin-left: 4px;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--muted);
}

.atc-note {
  margin-top: 11px;
  color: var(--muted);
  max-width: 40ch;
  margin-inline: auto;
}

/* ---------- Same-visit bundle (PDP) ---------- */
.bundle {
  margin-top: 28px;
  padding: clamp(18px, 3vw, 26px);
  border: 1px solid var(--brand);
  border-radius: var(--r-lg);
  background: linear-gradient(170deg, var(--sky-soft) 0%, var(--cream) 62%);
}
.bundle-head {
  margin-bottom: 18px;
}
.bundle-title {
  font-family: var(--font-title);
  font-weight: var(--w-semi);
  font-size: clamp(1.28rem, 2.6vw, 1.58rem);
  letter-spacing: -0.014em;
  line-height: 1.15;
  margin-bottom: 6px;
}
.bundle-sub {
  margin: 0;
  font-size: 0.9rem;
  color: var(--muted);
  max-width: 46ch;
}
.bundle-strip {
  display: flex;
  /* Captions run to one or two lines, so tiles line up by their photos
     rather than by their middles. */
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin-bottom: 20px;
}
.bundle-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  position: relative;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}
.bundle-thumb img,
.bundle-thumb .ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.bundle-plus {
  flex-shrink: 0;
  font-size: 1.05rem;
  font-weight: var(--w-label);
  color: var(--cta);
}
/* A tile and the "+" in front of it wrap as one unit — split across a line
   break, the plus dangles at the end of the row above it.

   Two grid rows: the photo, and its name underneath. The plus is placed in
   the photo's row so it stays centred on the photo however many lines the
   name below runs to. Photos are named from the last column line, so the
   base tile — which has no plus and so no first column — places them with
   the same two rules. */
.bundle-item {
  display: grid;
  grid-template-columns: auto 74px;
  align-items: center;
  justify-items: center;
  column-gap: 8px;
  row-gap: 6px;
  min-width: 0;
}
.bundle-item.is-base {
  grid-template-columns: 74px;
}
.bundle-thumb,
.bundle-name {
  grid-column: -2 / -1;
}
.bundle-thumb {
  grid-row: 1;
}
.bundle-name {
  grid-row: 2;
  font-size: 0.68rem;
  font-weight: var(--w-label);
  line-height: 1.25;
  text-align: center;
  color: var(--muted);
  text-wrap: balance;
}
.bundle-plus {
  grid-column: 1;
  grid-row: 1;
}
/* An add-on's tile only joins the strip once it's checked. */
.bundle-strip .is-addon-tile {
  display: none;
}
.bundle-strip .is-addon-tile.is-on {
  display: grid;
  animation: tile-in 0.22s ease both;
}
@keyframes tile-in {
  from {
    opacity: 0;
    transform: scale(0.88);
  }
}
@media (prefers-reduced-motion: reduce) {
  .bundle-strip .is-addon-tile.is-on {
    animation: none;
  }
}
.bundle-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding-bottom: 14px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.bundle-total-k {
  font-size: 0.76rem;
  font-weight: var(--w-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.bundle-total-v {
  display: flex;
  align-items: baseline;
  gap: 9px;
}
.bundle-total-v s {
  color: var(--muted-2);
  font-size: 1.02rem;
}
.bundle-total-v b {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: clamp(1.5rem, 3.4vw, 1.85rem);
  letter-spacing: -0.018em;
  color: var(--cta);
}
.bundle-addons {
  margin-top: 18px;
}
.bundle-addons .opt-list {
  gap: 9px;
}
.bundle-note {
  margin-top: 14px;
  margin-bottom: 0;
  color: var(--muted-2);
}

/* Sticky buy bar (mobile) */
.buy-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 70;
  background: #fff;
  border-top: 1px solid var(--line-strong);
  padding: 11px var(--gut) calc(11px + env(safe-area-inset-bottom));
  display: none;
  align-items: center;
  gap: 12px;
  transform: translateY(110%);
  transition: transform 0.24s ease;
}
.buy-bar.is-visible {
  transform: translateY(0);
}
@media (max-width: 940px) {
  .buy-bar {
    display: flex;
  }
  body.has-buybar {
    padding-bottom: 78px;
  }
}
.buy-bar-info {
  flex: 1;
  min-width: 0;
}
.buy-bar-name {
  font-weight: var(--w-semi);
  font-size: 0.86rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.buy-bar-price {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: var(--w-display);
  letter-spacing: -0.008em;
}

/* Spec grid */
.specs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  margin-bottom: 24px;
}
.spec {
  background: #fff;
  padding: 15px 14px;
}
.spec-k {
  font-size: 0.68rem;
  font-weight: var(--w-label);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: 5px;
}
.spec-v {
  font-weight: var(--w-display);
  font-size: 0.96rem;
  letter-spacing: -0.01em;
}

/* Meter */
.meter {
  display: flex;
  gap: 3px;
  margin-top: 5px;
}
.meter i {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  background: var(--sand-2);
}
.meter i.on {
  background: var(--cta);
}

/* ---------- Accordion / FAQ ---------- */
.acc {
  border-top: 1px solid var(--line);
}
.acc-item {
  border-bottom: 1px solid var(--line);
}
.acc-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  width: 100%;
  padding: 20px 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: clamp(1.02rem, 1.7vw, 1.2rem);
  letter-spacing: -0.008em;
  line-height: 1.25;
}
.acc-icon {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  transition: transform 0.2s, background 0.2s, color 0.2s;
}
.acc-btn[aria-expanded='true'] .acc-icon {
  transform: rotate(45deg);
  background: var(--ink);
  color: #fff;
}
.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.26s ease;
}
.acc-panel[data-open='true'] {
  grid-template-rows: 1fr;
}
.acc-panel > div {
  overflow: hidden;
}
.acc-panel p {
  color: var(--muted);
  padding-bottom: 20px;
  max-width: 68ch;
  margin: 0;
}

/* ---------- Timeline ---------- */
.timeline {
  position: relative;
  padding-left: 34px;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 9px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--line);
}
.tl-item {
  position: relative;
  padding-bottom: 26px;
}
.tl-item:last-child {
  padding-bottom: 0;
}
.tl-item::before {
  content: '';
  position: absolute;
  left: -30px;
  top: 6px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--cta);
  border: 3px solid var(--cream);
  box-shadow: 0 0 0 2px var(--cta);
}
.tl-when {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: 1rem;
  letter-spacing: -0.008em;
  margin-bottom: 3px;
}
.tl-what {
  color: var(--muted);
  font-size: 0.94rem;
}

/* ---------- Steps ---------- */
.steps {
  counter-reset: step;
  display: grid;
  gap: 18px;
}
.step {
  display: grid;
  grid-template-columns: 46px 1fr;
  gap: 16px;
  align-items: start;
}
.step-n {
  counter-increment: step;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: 1.15rem;
}
.step-n::before {
  content: counter(step);
}
.step h4 {
  margin-bottom: 3px;
}
.step p {
  color: var(--muted);
  font-size: 0.95rem;
  margin: 0;
}

/* ---------- Member Facial steps ----------------------------------------
   Five cards, one per step of the facial. Auto-fit rather than a fixed
   column count: the row reflows if a step is added or dropped in
   membership.facial.steps, which is where the copy actually lives.        */
.fsteps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: 16px;
  margin: clamp(26px, 4vw, 38px) 0 0;
  padding: 0;
}
.fstep {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 24px 22px;
  box-shadow: 0 10px 26px rgba(6, 37, 61, 0.06);
}
.fstep-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  background: var(--sky-soft);
  color: var(--cta);
  margin-bottom: 14px;
}
.fstep-n {
  display: block;
  font-size: 0.7rem;
  font-weight: var(--w-semi);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}
.fstep h4 {
  margin-bottom: 6px;
}
.fstep p {
  margin: 0;
  font-size: 0.92rem;
  color: var(--ink-2);
}

/* ---------- Vitamin shot menu ----------------------------------------
   Auto-fit rather than a fixed column count — the list is eleven today and
   is whatever membership.shotMenu holds tomorrow.                        */
.shot-menu {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
  gap: 12px;
  margin: clamp(24px, 4vw, 34px) 0 0;
  padding: 0;
}
.shot-item {
  display: grid;
  grid-template-columns: 42px 1fr;
  gap: 14px;
  align-items: start;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 16px 20px;
}
.shot-ico {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: var(--r-pill);
  background: var(--sky-soft);
  color: var(--cta);
}
.shot-body {
  min-width: 0;
}
.shot-name {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: 1.05rem;
  letter-spacing: -0.008em;
}
.shot-price {
  flex: none;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: var(--w-semi);
  letter-spacing: 0;
  color: var(--cta);
}
.shot-item .tiny {
  display: block;
  color: var(--muted);
  margin-top: 3px;
}

/* ---------- Good for / not for ---------- */
.gf-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
@media (max-width: 700px) {
  .gf-grid {
    grid-template-columns: 1fr;
  }
}
.gf {
  padding: 22px 24px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
}
.gf-yes {
  background: var(--sky-soft);
}
.gf-no {
  background: var(--sand);
}
.gf h4 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}
.gf li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 6px 0;
  font-size: 0.94rem;
  line-height: 1.45;
}
.gf li svg {
  flex-shrink: 0;
  margin-top: 4px;
}

/* ---------- Reviews ---------- */
.review {
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  padding: 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
}
.review-text {
  font-size: 1rem;
  line-height: 1.55;
  flex: 1;
  margin: 0;
}
.review-who {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--sky);
  color: var(--deep);
  display: grid;
  place-items: center;
  font-weight: var(--w-semi);
  font-size: 0.9rem;
  flex-shrink: 0;
}
.review-name {
  font-weight: var(--w-semi);
  font-size: 0.92rem;
  line-height: 1.2;
  font-family: var(--font-title);
}
.review-loc {
  font-size: 0.78rem;
  color: var(--muted-2);
}
.verified {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.72rem;
  font-weight: var(--w-semi);
  color: var(--ok);
}

/* ---------- Before & after slider ---------- */
.ba {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #fff;
}
.ba-stage {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  cursor: ew-resize;
  user-select: none;
  touch-action: none;
  background: var(--sand);
}
/* One result on its own would otherwise stretch to the full content width,
   which on a portrait photograph is a card about as tall as the screen. */
.ba-grid.g-1 {
  max-width: 460px;
  margin-inline: auto;
}
/* A result that came in as one already-labelled image. Nothing to drag, so
   it loses the grab cursor, and it is contained rather than cropped: these
   arrive stacked at whatever ratio the phone shot them in, and cropping to
   4:5 would cut off one half of the comparison. */
.ba-stage.is-static {
  cursor: default;
  touch-action: auto;
  display: grid;
  place-items: center;
}
.ba-stage.is-static img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.ba-layer {
  position: absolute;
  inset: 0;
}
.ba-layer img,
.ba-layer svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ba-after {
  clip-path: inset(0 0 0 50%);
}
.ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(6, 37, 61, 0.3);
  pointer-events: none;
}
.ba-knob {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
  box-shadow: var(--shadow);
}
.ba-tag {
  position: absolute;
  bottom: 12px;
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: rgba(6, 37, 61, 0.82);
  color: #fff;
  font-size: 0.7rem;
  font-weight: var(--w-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  pointer-events: none;
}
.ba-tag-b {
  left: 12px;
}
.ba-tag-a {
  right: 12px;
}
.ba-info {
  padding: 16px 18px;
  border-top: 1px solid var(--line-strong);
}
.ba-info h4 {
  margin-bottom: 4px;
}
.ba-info p {
  margin: 0;
  font-size: 0.88rem;
  color: var(--muted);
}

/* ---------- Quiz ---------- */
.quiz-shell {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
}
.quiz-progress {
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--sand-2);
  overflow: hidden;
  margin-bottom: 8px;
}
.quiz-progress i {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--brand), var(--sky));
  transition: width 0.34s cubic-bezier(0.4, 0, 0.2, 1);
}
.quiz-step {
  display: none;
  animation: fade-up 0.34s ease;
}
.quiz-step.is-active {
  display: block;
}
@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.quiz-q {
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  margin-bottom: 8px;
}
.quiz-help {
  color: var(--muted);
  margin-bottom: 26px;
}
.quiz-opts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
}
.quiz-opt {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 17px 19px;
  border: 2px solid var(--line);
  border-radius: var(--r);
  background: #fff;
  text-align: left;
  transition: all 0.14s;
}
.quiz-opt:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
}
.quiz-opt[aria-pressed='true'] {
  border-color: var(--cta);
  background: var(--sky-soft);
  box-shadow: inset 0 0 0 1px var(--cta), 0 8px 20px rgba(10, 108, 186, 0.14);
}
.quiz-opt-icon {
  width: 44px;
  height: 44px;
  border-radius: 13px;
  background: var(--sand);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--deep);
}
.quiz-opt[aria-pressed='true'] .quiz-opt-icon {
  background: #fff;
}
.quiz-opt-label {
  display: block;
  font-weight: var(--w-semi);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.quiz-opt-sub {
  display: block;
  font-size: 0.82rem;
  color: var(--muted);
  margin-top: 2px;
}
.quiz-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 30px;
}
.quiz-loading {
  display: none;
  text-align: center;
  padding: 60px 0;
}
.quiz-loading.is-active {
  display: block;
}
.spinner {
  width: 54px;
  height: 54px;
  border: 5px solid var(--sand-2);
  border-top-color: var(--brand);
  border-radius: 50%;
  margin: 0 auto 22px;
  animation: spin 0.85s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
.quiz-result {
  display: none;
}
.quiz-result.is-active {
  display: block;
  animation: fade-up 0.4s ease;
}
.match-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  background: var(--ok);
  color: #fff;
  font-size: 0.74rem;
  font-weight: var(--w-label);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ---------- Unit calculator ---------- */
.calc {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: #fff;
  overflow: hidden;
}
.calc-head {
  padding: clamp(22px, 3vw, 32px);
  background: var(--chrome);
  color: #fff;
}
.calc-head h3 {
  margin-bottom: 6px;
  color: #fff;
}
.calc-head p {
  margin: 0;
  color: rgba(255, 255, 255, 0.92);
  font-size: 0.94rem;
}
/* ---------- Stepped calculator ------------------------------------------
   One question at a time — areas, age, line depth, estimate — rather than
   the whole form at once. Steps are stacked and toggled rather than
   re-rendered, so the face map keeps its selection state throughout.      */
.calc-flow {
  padding: clamp(20px, 3vw, 30px);
}
.calc-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 6px;
  margin-bottom: clamp(20px, 3vw, 28px);
}
.calc-tick {
  font-size: 0.68rem;
  font-weight: var(--w-semi);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
  padding-top: 9px;
  border-top: 3px solid var(--line);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.calc-tick.is-on {
  color: var(--cta);
  border-top-color: var(--cta);
}
.calc-tick.is-current {
  color: var(--ink);
}
.calc-step {
  display: none;
}
.calc-step.is-active {
  display: block;
}
.calc-q {
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  margin-bottom: 4px;
}
.calc-help {
  color: var(--muted);
  font-size: 0.94rem;
  margin-bottom: 20px;
}
.calc-split {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(16px, 3vw, 28px);
  align-items: start;
}
@media (max-width: 860px) {
  .calc-split {
    grid-template-columns: 1fr;
  }
}
.calc-nav {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: clamp(20px, 3vw, 28px);
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
/* Keeps Continue hard right when Back is hidden on the first step. */
.calc-nav #calc-next {
  margin-left: auto;
}
.calc-nav .btn[disabled] {
  opacity: 0.45;
  pointer-events: none;
}
/* Roomier hit targets — these two steps are the whole screen now. */
.seg-tall button {
  padding-block: 15px;
}

@media (prefers-reduced-motion: reduce) {
  .calc-tick {
    transition: none;
  }
}
.calc-face {
  /* Grid items default to min-width:auto, which refuses to shrink below the
     content's own minimum — without this, a wide child forces this column
     wider than the viewport and .calc's overflow:hidden silently clips
     everything past the edge instead of wrapping it. */
  min-width: 0;
  padding: clamp(14px, 2vw, 22px);
  background: linear-gradient(170deg, var(--sky-soft), var(--cream));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
@media (max-width: 860px) {
  .calc-face {
    border-right: 0;
    border-bottom: 1px solid var(--line-strong);
  }
}
.face-svg {
  width: 100%;
  max-width: 340px;
  height: auto;
}
/* The illustrated face map: picture underneath, tappable zones over it. The
   overlay's viewBox has to match the image's aspect ratio or every hotspot
   drifts off its feature. */
.face-map {
  position: relative;
  width: 100%;
  max-width: 340px;
  line-height: 0;
}
.face-map img {
  width: 100%;
  height: auto;
  border-radius: var(--r);
  display: block;
}
.face-map .face-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
}
/* The zones sit on a photographed face, so a thin blue line at low opacity
   disappears into skin, hair and eyebrow alike — which made the map look
   decorative rather than tappable. A white halo lifts the ring off whatever
   is behind it, and the fill carries enough blue to read as a region. */
.face-zone {
  fill: rgba(15, 127, 205, 0.16);
  stroke: #0f7fcd;
  stroke-width: 2.2;
  stroke-dasharray: 6 4;
  cursor: pointer;
  filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.95));
  transition: fill 0.16s, stroke-width 0.16s;
}
.face-zone:hover {
  fill: rgba(15, 127, 205, 0.3);
}
.face-zone.is-on {
  fill: rgba(15, 127, 205, 0.42);
  stroke: var(--cta);
  stroke-dasharray: none;
  stroke-width: 3.4;
}
/* The zones carry tabindex so they're reachable by keyboard, which also gives
   them the UA focus ring — a black rectangle drawn around the ellipse's box,
   on every mouse click. Keyboard users keep a ring; it's just this one. */
.face-zone:focus {
  outline: none;
}
.face-zone:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}
/* Until the first zone is picked, the ring breathes. It's the only cue that
   the picture is an input rather than an illustration. */
.face-svg:not(.has-pick) .face-zone {
  animation: zone-breathe 2.8s ease-in-out infinite;
}
@keyframes zone-breathe {
  0%,
  100% {
    fill: rgba(15, 127, 205, 0.12);
  }
  50% {
    fill: rgba(15, 127, 205, 0.32);
  }
}
@media (prefers-reduced-motion: reduce) {
  .face-svg:not(.has-pick) .face-zone {
    animation: none;
  }
}
.calc-areas {
  min-width: 0;
  display: grid;
  gap: 8px;
  align-content: start;
}
.calc-area {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border: 2px solid var(--line);
  border-radius: var(--r-sm);
  background: #fff;
  text-align: left;
  width: 100%;
  transition: all 0.14s;
}
.calc-area[aria-pressed='true'] {
  border-color: var(--cta);
  background: #eef6fd;
}
.calc-area-name {
  display: block;
  font-weight: var(--w-semi);
  font-size: 0.92rem;
  line-height: 1.2;
}
.calc-area-sub {
  display: block;
  font-size: 0.78rem;
  color: var(--muted);
}
.calc-area-units {
  margin-left: auto;
  font-size: 0.78rem;
  font-weight: var(--w-semi);
  color: var(--muted-2);
  white-space: nowrap;
}
.seg {
  display: grid;
  grid-auto-flow: column;
  /* Auto-placed columns default to sizing themselves by content (max-content),
     which combined with nowrap button text is exactly what pushed this off
     the right edge of the screen. minmax(0, 1fr) makes every column share
     space equally and actually allowed to shrink below its content. */
  grid-auto-columns: minmax(0, 1fr);
  gap: 6px;
  padding: 5px;
  background: var(--sand);
  border-radius: var(--r-pill);
  margin-bottom: 18px;
}
.seg button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px; /* touch target minimum — iOS HIG / WCAG 2.5.5 */
  padding: 9px 6px;
  border-radius: var(--r-pill);
  font-weight: var(--w-semi);
  font-size: 0.86rem;
  line-height: 1.2;
  transition: all 0.14s;
  /* Wrap rather than overflow — "Deep & always there" needs it on phones. */
  white-space: normal;
  text-align: center;
}
.seg button[aria-pressed='true'] {
  background: var(--ink);
  color: #fff;
}
.calc-out {
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  overflow: hidden;
}
.calc-out-top {
  padding: 20px;
  background: var(--accent-soft);
  text-align: center;
}
.calc-units {
  font-family: var(--font-display);
  font-size: 2.7rem;
  font-weight: var(--w-display);
  letter-spacing: -0.015em;
  line-height: 1;
}
.calc-units-label {
  font-size: 0.76rem;
  font-weight: var(--w-label);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  opacity: 0.7;
}
.calc-out-rows {
  padding: 6px 18px 14px;
}
/* Only appears for Dysport and Daxxify — see initCalculator. */
.calc-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.93rem;
}
.calc-row:last-child {
  border-bottom: 0;
}
.calc-row b {
  font-family: var(--font-display);
  font-size: 1.15rem;
  letter-spacing: -0.008em;
}
.calc-save {
  color: var(--ok);
  font-weight: var(--w-semi);
}

/* ---------- Cart drawer ---------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(6, 37, 61, 0.5);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: all 0.24s;
}
.scrim.is-open {
  opacity: 1;
  visibility: visible;
}
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 200;
  width: min(440px, 100%);
  background: var(--cream);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: var(--shadow-lg);
}
.drawer.is-open {
  transform: translateX(0);
}
.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--line-strong);
}
.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 18px 20px;
}
.drawer-foot {
  border-top: 1px solid var(--line-strong);
  padding: 18px 20px calc(18px + env(safe-area-inset-bottom));
  background: #fff;
}
.cart-line {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  gap: 13px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.cart-thumb {
  width: 62px;
  height: 62px;
  border-radius: var(--r-sm);
  background: var(--sand);
  border: 1px solid var(--line);
  overflow: hidden;
}
.cart-name {
  font-weight: var(--w-semi);
  font-size: 0.94rem;
  line-height: 1.25;
}
.cart-variant {
  font-size: 0.8rem;
  color: var(--muted);
}
.cart-remove {
  font-size: 0.78rem;
  color: var(--muted-2);
  text-decoration: underline;
  margin-top: 4px;
}
.cart-remove:hover {
  color: var(--cta);
}
.cart-price {
  font-weight: var(--w-display);
  white-space: nowrap;
}
.cart-empty {
  text-align: center;
  padding: 50px 20px;
  color: var(--muted);
}
.cart-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
}
.cart-total b {
  font-family: var(--font-display);
  font-size: 1.7rem;
  letter-spacing: -0.012em;
}
.cart-upsell {
  border: 2px dashed var(--brand);
  background: var(--sky-soft);
  border-radius: var(--r);
  padding: 14px 15px;
  margin-top: 18px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.cart-note {
  margin: 14px 0 0;
  color: var(--muted-2);
}
/* The other way to book, under the booking button rather than beside it —
   it is the fallback, not the equal. */
.cart-text {
  margin-top: 10px;
  gap: 8px;
  font-size: 0.92rem;
}
.cart-text svg {
  flex: none;
}
.cart-foot-note {
  margin: 9px 0 0;
  color: var(--muted-2);
}
/* Per-unit lines, named under the total rather than summed into it. */
.cart-rate-note {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-left: 3px solid var(--cta);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--sky-soft);
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.cart-rate-note span {
  color: var(--muted);
}

/* ---------- Modal / lead popup ---------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.modal.is-open {
  display: flex;
}
/* The shared .scrim carries a high z-index for the cart drawer. Inside a modal
   it is a sibling of the card, so it has to drop below it — otherwise the
   backdrop blur paints over the dialog itself. */
.modal .scrim {
  z-index: 1;
}
.modal-card {
  position: relative;
  z-index: 2;
  width: min(880px, 100%);
  max-height: 92vh;
  overflow-y: auto;
  background: var(--cream);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-xl);
  box-shadow: 0 26px 60px rgba(6, 37, 61, 0.2);
  animation: pop 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
}
@keyframes pop {
  from {
    opacity: 0;
    transform: scale(0.94) translateY(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.modal-grid {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
}
@media (max-width: 720px) {
  .modal-grid {
    grid-template-columns: 1fr;
  }
  .modal-art {
    display: none;
  }
}
.modal-art {
  background: linear-gradient(165deg, var(--brand), var(--deep));
  color: #fff;
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
}
.modal-art h3 {
  color: #fff;
  font-size: 1.9rem;
}
.modal-art li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 5px 0;
  font-size: 0.94rem;
  font-weight: 600;
}
.modal-body {
  padding: clamp(24px, 4vw, 38px);
}
.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 3;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--cream);
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
}
.modal-close:hover {
  background: var(--ink);
  color: #fff;
}

/* ---------- Forms ---------- */
.field {
  margin-bottom: 14px;
}
.field label {
  display: block;
  font-size: 0.78rem;
  font-weight: var(--w-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.input {
  width: 100%;
  padding: 14px 16px;
  border: 2px solid var(--line);
  border-radius: var(--r);
  background: #fff;
  font-size: 1rem;
  transition: border-color 0.14s;
}
.input:focus {
  outline: none;
  border-color: var(--line-strong);
}
.input::placeholder {
  color: var(--muted-2);
}
/* A <select> borrows .input, and without this it keeps the platform's own
   chrome — a different height and corner radius from the fields around it. */
select.input {
  appearance: none;
  padding-right: 42px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23566b7d' stroke-width='2.5' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
}
select.input:invalid {
  color: var(--muted-2);
}
.form-note {
  font-size: 0.76rem;
  color: var(--muted-2);
  margin-top: 10px;
  line-height: 1.5;
}
.form-ok {
  text-align: center;
  padding: 26px 0;
}

/* ---------- Membership ---------- */
.mem-card {
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: #fff;
  overflow: hidden;
  box-shadow: 0 18px 44px rgba(6, 37, 61, 0.14);
}
.mem-head {
  background: linear-gradient(150deg, var(--ink), var(--deep));
  color: #fff;
  padding: clamp(26px, 4vw, 40px);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.mem-head::after {
  content: '';
  position: absolute;
  top: -60px;
  right: -60px;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(111, 199, 242, 0.32), transparent 68%);
}
.mem-head h3 {
  color: #fff;
  position: relative;
}
.mem-price {
  font-family: var(--font-display);
  font-size: clamp(2.8rem, 6vw, 4rem);
  font-weight: var(--w-display);
  letter-spacing: -0.015em;
  line-height: 1;
  position: relative;
}
.mem-price span {
  font-size: 1.1rem;
  letter-spacing: -0.01em;
  opacity: 0.75;
}
.perk {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.perk:last-child {
  border-bottom: 0;
}
.perk-icon {
  width: 42px;
  height: 42px;
  border-radius: 13px;
  background: var(--sky-soft);
  color: var(--deep);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.perk h4 {
  margin-bottom: 3px;
}
.perk p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--muted);
}
.perk-value {
  margin-left: auto;
  font-size: 0.78rem;
  font-weight: var(--w-semi);
  color: var(--ok);
  white-space: nowrap;
}
.value-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 18px 22px;
  background: var(--accent-soft);
  border-top: 1px solid var(--line-strong);
  flex-wrap: wrap;
}

/* ---------- Local / map ---------- */
.local-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 3vw, 44px);
  align-items: center;
}
@media (max-width: 860px) {
  .local-grid {
    grid-template-columns: 1fr;
  }
}
.drive {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.95rem;
}
.drive b {
  white-space: nowrap;
}
.hours-row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.94rem;
}
.map-embed {
  width: 100%;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--sand);
}
.map-embed iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* ---------- Category sections ---------- */
.cat-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 26px;
  flex-wrap: wrap;
}
.cat-head h2 {
  margin: 0;
}
.cat-blurb {
  color: var(--muted);
  margin: 6px 0 0;
}

/* ---------- Banners ---------- */
/* Two sections use this: the homepage "difference" cards and the membership
   perk list. Both were a flat blue slab carrying translucent cards, which
   gave white type on blue for the full height of the section and cards that
   barely separated from the ground they sat on. Light tint, solid white
   cards — the blue moved into the icon tiles, where it has somewhere to
   read against. */
.band {
  background: linear-gradient(172deg, var(--sky-soft) 0%, var(--cream) 72%);
}
.band-accent {
  background: var(--accent-soft);
}
.band-sand {
  background: var(--sand);
}
.band-accent .lead,
.band-sand .lead {
  color: var(--ink-2);
}
/* --muted-2 is calibrated for white and drops to 3.05:1 on a tinted band. */
.band .tiny {
  color: var(--muted);
}
/* The calculator head is still a dark ground, and --cta on --cta is nothing. */
.calc-head .eyebrow {
  color: #fff;
}

/* Cards on a .band. */
.slab-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 26px 24px;
  box-shadow: 0 10px 26px rgba(6, 37, 61, 0.06);
}
.slab-icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background: var(--sky-soft);
  color: var(--cta);
  margin-bottom: 16px;
}
.slab-card h4 {
  margin-bottom: 8px;
}
.slab-card p {
  margin: 0;
  font-size: 0.94rem;
  color: var(--ink-2);
}
/* Beats `.slab-card p`, which this line is also matched by. */
.slab-card p.slab-value {
  margin: 10px 0 0;
  color: var(--cta);
  font-weight: var(--w-label);
  font-size: 0.86rem;
}

/* The closing CTA. It used to be a blue gradient block, which put a third
   blue slab in a row at the foot of the homepage and left the sub-copy
   sitting at --ink-2 on blue — near-invisible. It is a light card now, and
   the anchor at the bottom of the page is the blue footer right below it. */
.cta-band {
  background: linear-gradient(150deg, var(--sky-soft) 0%, #eef7ff 58%, var(--sand) 100%);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  padding: clamp(32px, 5vw, 62px);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.cta-band::after {
  content: '';
  position: absolute;
  bottom: -160px;
  left: 50%;
  transform: translateX(-50%);
  width: 680px;
  height: 340px;
  background: radial-gradient(ellipse, rgba(112, 157, 198, 0.3), transparent 70%);
  pointer-events: none;
}
.cta-band > * {
  position: relative;
  z-index: 1;
}
.cta-band .lead {
  color: var(--ink-2);
}
/* --muted-2 only reaches 3.05:1 on this tint. */
.cta-band .tiny {
  color: var(--muted);
}
/* The phone and text numbers are the low-tech way to book, and on the old
   blue ground they were underlined white. They have to stay obviously
   tappable now that the line sits in muted grey. */
.cta-band .tiny a {
  color: var(--cta);
  font-weight: var(--w-semi);
  text-decoration: underline;
}

/* ---------- Footer ---------- */
.site-footer {
  background: var(--chrome);
  color: rgba(255, 255, 255, 0.92);
  padding-block: clamp(46px, 6vw, 76px) 30px;
}
.site-footer h4 {
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.74rem;
  font-weight: var(--w-display);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.site-footer a:hover {
  color: var(--sky);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr repeat(3, 1fr);
  gap: clamp(24px, 3vw, 44px);
}
@media (max-width: 900px) {
  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 560px) {
  .footer-grid {
    grid-template-columns: 1fr;
  }
}
.footer-grid li {
  padding: 5px 0;
  font-size: 0.94rem;
}
.footer-bottom {
  margin-top: 40px;
  padding-top: 22px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 0.82rem;
}
.socials {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}
.social {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.22);
  display: grid;
  place-items: center;
  transition: all 0.14s;
}
.social:hover {
  background: #fff;
  color: var(--ink);
}

/* ---------- Short-form content reel ---------- */
/* The track is inset so the first card lines up with the page gutter, and the
   snapport is inset to match — otherwise scroll-snap immediately scrolls past
   that leading padding and the row starts flush against the viewport edge. */
.reel-scroller {
  --reel-inset: max(var(--gut), calc((100vw - var(--wrap)) / 2 + var(--gut)));
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: var(--reel-inset);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  padding-block: 4px 18px;
}
.reel-track {
  display: flex;
  gap: 16px;
  width: max-content;
  padding-inline: var(--reel-inset);
}
.reel-card {
  flex: 0 0 auto;
  width: 236px;
  scroll-snap-align: start;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Only the Instagram card at the end of the rail is still a link. */
.reel-card-end {
  cursor: pointer;
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.reel-card-end:hover,
.reel-card-end:focus-visible {
  transform: translateY(-5px);
  box-shadow: 0 14px 34px rgba(6, 37, 61, 0.13);
}
.reel-media {
  position: relative;
  aspect-ratio: 9 / 16;
  background: var(--sand);
  overflow: hidden;
}
.reel-media img,
.reel-media .ph,
.reel-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* The clip is the card, so it gets the card's own background rather than the
   black a <video> paints while it buffers. */
.reel-video {
  background: var(--sand);
}
/* Placeholder filenames sit high on the card so they clear the duration
   chip. They disappear as soon as real footage lands. */
.reel-media .ph-label {
  bottom: auto;
  top: 46px;
  font-size: 0.58rem;
  line-height: 1.4;
}
.reel-tag {
  position: absolute;
  top: 10px;
  left: 10px;
  font-size: 0.62rem;
  padding: 5px 9px;
}
.reel-time {
  position: absolute;
  bottom: 10px;
  right: 10px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  background: rgba(6, 37, 61, 0.82);
  color: #fff;
  font-size: 0.68rem;
  font-weight: var(--w-label);
  font-variant-numeric: tabular-nums;
}
.reel-body {
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1;
}
.reel-title {
  font-size: 1rem;
  line-height: 1.2;
  margin: 0;
  font-family: var(--font-title);
}
.reel-caption {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.4;
}
.reel-card-end {
  border-style: dashed;
  background: var(--sky-soft);
}
.reel-end {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
  color: var(--deep);
}
.reel-end strong {
  font-family: var(--font-title);
  font-size: 1.05rem;
  letter-spacing: -0.008em;
}
.reel-end span {
  font-size: 0.82rem;
  color: var(--muted);
}

/* ---------- Toast ---------- */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translate(-50%, 130%);
  z-index: 220;
  background: var(--ink);
  color: #fff;
  padding: 14px 22px;
  border-radius: var(--r-pill);
  font-weight: var(--w-semi);
  font-size: 0.92rem;
  box-shadow: var(--shadow-lg);
  transition: transform 0.28s cubic-bezier(0.34, 1.4, 0.64, 1);
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: calc(100% - 32px);
}
.toast.is-visible {
  transform: translate(-50%, 0);
}
@media (max-width: 940px) {
  .toast.is-visible {
    transform: translate(-50%, -70px);
  }
}

/* ---------- Utility ---------- */
/* Hides below 700px and does nothing above it.
   This used to set `display: initial` at desktop, which is not a no-op — it
   clobbers whatever display the element already had. On the header's phone
   link that beat `.icon-btn { display: grid }` (same specificity, later in the
   file), so `place-items: center` stopped applying and the icon sat 9px high
   inside its own button. A utility that hides something should only hide it. */
@media (max-width: 700px) {
  .hide-mobile {
    display: none;
  }
}
.mt-0 {
  margin-top: 0;
}
.mb-0 {
  margin-bottom: 0;
}
.flex {
  display: flex;
}
.items-center {
  align-items: center;
}
.gap-sm {
  gap: 8px;
}
.gap {
  gap: 16px;
}
.wrap-flex {
  flex-wrap: wrap;
}
.justify-between {
  justify-content: space-between;
}
.full {
  width: 100%;
}
[hidden] {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   HOMEPAGE — Bloom-style layout
   Full-bleed alternating bands, oversized centred display type, pill buttons,
   tinted card panels and circular icon grids. Bloom's greens map to our blues:
   their dark green → --cta, their pale green band → --sky-soft, their cream
   label bars → --cream.
   ═════════════════════════════════════════════════════════════════════════ */

.b-band {
  padding-block: clamp(48px, 7vw, 92px);
}
.b-band-soft {
  background: linear-gradient(180deg, var(--sky-soft), #cfe8fa);
}
.b-band-deep {
  background: var(--cta);
  color: #fff;
}
.b-band-cream {
  background: var(--cream);
}

/* Oversized centred heading, the single loudest Bloom signal. */
.b-h {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.1rem, 6.4vw, 3.9rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-align: center;
  max-width: 15ch;
  margin: 0 auto;
  color: var(--cta);
}
.b-band-deep .b-h {
  color: #fff;
}
/* The sale heading carries two emoji, which cost it about 60px of line. The
   default 15ch cap breaks it across two lines on a phone and leaves the
   trailing emoji stranded on a short second line, so this one gets room to
   run and slightly smaller emoji. No space sits between the emoji and the
   words, so there is no break opportunity there — if a very narrow screen
   does force a wrap, it happens between words and never orphans an emoji. */
.b-h-sale {
  max-width: 22ch;
  /* A slightly lower floor than the other band headings buys the ~20px this
     one needs to hold a single line on every phone from 344px up. Above
     ~430px the vw term takes over and it matches the others exactly. */
  font-size: clamp(1.85rem, 6.4vw, 3.9rem);
  text-wrap: balance;
}
.b-h-emoji {
  font-size: 0.78em;
  /* Keeps the optical gap the removed spaces used to provide. */
  margin-inline: 0.16em;
  vertical-align: 0.04em;
}
.b-sub {
  text-align: center;
  max-width: 46ch;
  margin: 16px auto 0;
  font-size: 1.06rem;
  color: var(--ink-2);
}
.b-band-deep .b-sub {
  color: #fff;
}
.b-cta-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-top: 28px;
}
/* The longest of these labels runs a few pixels past a 360px phone. Let the
   button shrink and wrap its text rather than push the page wider. */
.b-cta-wrap .btn {
  max-width: 100%;
}

/* ---------- Hero carousel ----------------------------------------------
   One full-bleed image per slide with the copy laid over it. Slides are
   stacked and cross-faded rather than translated on a track: the number of
   slides is whatever site.mjs holds, and a fade needs no width arithmetic
   to stay correct when that count changes.                                */
.hero-car {
  position: relative;
  height: clamp(520px, 78vh, 780px);
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;
}
.hero-track {
  position: absolute;
  inset: 0;
}
.hero-slide {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.55s ease, visibility 0s linear 0.55s;
}
.hero-slide.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.55s ease, visibility 0s;
}
.hero-slide-bg {
  position: absolute;
  inset: 0;
}
.hero-slide-bg img,
.hero-slide-bg .ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The scrim. Photos we have no control over sit under white type, so the
   contrast has to come from the overlay, not from the picture: heaviest
   through the middle band where the headline and sub live. At 0.68 the
   worst case — a blown-out white photo — still composites to 5.5:1 against
   white text, so any image dropped into a slot clears AA. */
.hero-slide-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to bottom,
      rgba(6, 37, 61, 0.52) 0%,
      rgba(6, 37, 61, 0.68) 38%,
      rgba(6, 37, 61, 0.72) 62%,
      rgba(6, 37, 61, 0.6) 100%
    );
}
.hero-slide-copy {
  position: relative;
  z-index: 2;
  text-align: center;
  padding-bottom: 24px;
}
/* Placeholder art spells out which file belongs in the slot. Over the scrim
   the default ink-on-white label vanishes, and it sits where the dots go. */
.hero-slide-bg .ph-label {
  top: 12px;
  bottom: auto;
  text-align: left;
  color: rgba(255, 255, 255, 0.5);
}
.hero-slide-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.5rem, 8.4vw, 5.4rem);
  line-height: 0.96;
  letter-spacing: -0.03em;
  color: #fff;
  margin: 16px auto 0;
  max-width: 15ch;
  text-wrap: balance;
}
.hero-slide-sub {
  max-width: 48ch;
  margin: 18px auto 0;
  font-size: clamp(1rem, 2.4vw, 1.15rem);
  color: rgba(255, 255, 255, 0.93);
}
.hero-slide-copy .btn-row {
  margin-top: clamp(22px, 3.5vw, 32px);
}
/* The outline button needs to read as an outline against a photograph. */
.hero-slide-copy .btn-ghost {
  --fg: #fff;
  border-color: rgba(255, 255, 255, 0.62);
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(3px);
}
.hero-slide-copy .btn-ghost:hover {
  --bg: #fff;
  --fg: var(--ink);
  border-color: #fff;
}

.hero-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}
.hero-arrow:hover {
  background: #fff;
  transform: translateY(-50%) scale(1.06);
}
.hero-prev {
  left: clamp(8px, 2vw, 26px);
}
.hero-next {
  right: clamp(8px, 2vw, 26px);
}

.hero-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  z-index: 4;
  display: flex;
  justify-content: center;
  gap: 9px;
}
.hero-dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.5);
  cursor: pointer;
  transition: width 0.25s ease, background 0.25s ease;
}
.hero-dot.is-on {
  width: 26px;
  background: #fff;
}

/* Star rating, lifted out of the hero so it never competes with the photo. */
.hero-proof-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 4px 10px;
  padding: 16px var(--gut);
  font-size: 0.92rem;
}

@media (max-width: 640px) {
  .hero-car {
    height: clamp(490px, 78vh, 640px);
  }
  /* Centred arrows land on top of the sub-copy at this width — drop them to
     the bottom corners, either side of the dots. */
  .hero-arrow {
    width: 38px;
    height: 38px;
    top: auto;
    bottom: 12px;
    transform: none;
  }
  .hero-arrow:hover {
    transform: none;
  }
  .hero-dots {
    bottom: 26px;
  }
  .hero-slide-copy .btn-row {
    flex-direction: column;
    align-items: stretch;
  }
  .hero-slide-copy .btn {
    justify-content: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-slide,
  .hero-slide.is-active {
    transition: none;
  }
}

/* The "first visit on us" starburst, rotated into the corner of a slide.
   Slides that leave `sticker` unset simply don't render one. */
.starburst {
  position: absolute;
  top: clamp(10px, 2.5vw, 26px);
  right: clamp(10px, 2.5vw, 30px);
  z-index: 3;
  width: clamp(104px, 17vw, 148px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  text-align: center;
  transform: rotate(-14deg);
  color: #fff;
  background: var(--accent);
  clip-path: polygon(
    50% 0%, 61% 12%, 76% 6%, 79% 22%, 94% 22%, 89% 38%, 100% 50%, 89% 62%,
    94% 78%, 79% 78%, 76% 94%, 61% 88%, 50% 100%, 39% 88%, 24% 94%, 21% 78%,
    6% 78%, 11% 62%, 0% 50%, 11% 38%, 6% 22%, 21% 22%, 24% 6%, 39% 12%
  );
}
/* Gold for the sale sticker. The only warm colour on a single-hue blue site,
   which is the point — it is the one thing on the page that is not the brand
   speaking, and it reads as a sticker slapped on rather than part of the
   design. Ink text on it, never white: gold is too light to carry white. */
.starburst.is-sale {
  background: linear-gradient(150deg, #f7d774, #e0aa2e 62%, #c98f18);
  filter: drop-shadow(0 3px 10px rgba(140, 96, 12, 0.35));
}
.starburst.is-sale span {
  color: #3d2905;
}

.starburst span {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(0.7rem, 1.7vw, 0.92rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ink);
  padding: 0 12px;
}

/* ---------- Horizontal rail (best sellers) ---------- */
.b-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(248px, 1fr);
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 4px var(--gut) 8px;
  margin-inline: calc(var(--gut) * -1);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.b-rail::-webkit-scrollbar {
  display: none;
}
.b-rail > * {
  scroll-snap-align: start;
}
/* On desktop the rail stops scrolling and wraps instead. Auto-flow stays on
   rows so a rail of eight lays out as two rows of four rather than eight
   slivers — the card count is whatever the page passes in.

   1150px, not 900px. Four across at 900 left about 180px of card content: the
   rating line wrapped onto two rows and the footer could not hold a price and
   the View button side by side. Below this the rail keeps scrolling
   horizontally at a readable card width, which it already did well. */
@media (min-width: 1150px) {
  .b-rail {
    grid-auto-flow: row;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-columns: auto;
    gap: 20px;
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
  }
}

/* ---------- Circular perk grid (membership) ---------- */
.b-perks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(22px, 4vw, 40px) 18px;
  max-width: 620px;
  margin: clamp(28px, 4vw, 42px) auto 0;
}
@media (min-width: 760px) {
  .b-perks {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    max-width: 900px;
  }
}
.b-perk {
  text-align: center;
}
.b-perk-ring {
  width: clamp(64px, 12vw, 84px);
  aspect-ratio: 1;
  margin: 0 auto 12px;
  border-radius: 50%;
  border: 2px solid currentColor;
  display: grid;
  place-items: center;
  color: var(--cta);
}
.b-band-deep .b-perk-ring {
  color: #fff;
}
.b-perk-ring svg {
  width: 30px;
  height: 30px;
}
.b-perk-label {
  font-weight: var(--w-semi);
  font-size: 0.98rem;
  line-height: 1.3;
  color: var(--cta);
  max-width: 16ch;
  margin-inline: auto;
}
.b-band-deep .b-perk-label {
  color: #fff;
}

/* ---------- Category tiles ---------- */
.b-tiles {
  display: grid;
  /* Fits however many categories there are rather than assuming four: with
     chiropractic gone there are three, and a fixed four-column grid left an
     empty cell on the right. */
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: clamp(12px, 2vw, 20px);
  margin-top: clamp(26px, 4vw, 40px);
}
.b-tile {
  display: block;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--cream);
  border: 1px solid var(--line);
  transition: transform 0.16s, box-shadow 0.16s;
}
.b-tile:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px rgba(6, 37, 61, 0.14);
}
.b-tile-media {
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
}
.b-tile-media img,
.b-tile-media .ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.b-tile-label {
  display: block;
  text-align: center;
  padding: 16px 12px;
  font-family: var(--font-title);
  font-weight: 700;
  font-size: clamp(1rem, 2vw, 1.2rem);
  letter-spacing: -0.012em;
  color: var(--cta);
}

/* ---------- Email capture ---------- */
.b-email {
  max-width: 520px;
  margin: 26px auto 0;
  display: grid;
  gap: 12px;
}
.b-email .input {
  border-radius: var(--r-pill);
  border-color: transparent;
  padding: 17px 24px;
  font-size: 1rem;
}
.b-email .btn {
  border-radius: var(--r-pill);
}

/* Cart: more than one service means more than one Podium appointment. */
.cart-split-note {
  margin: 0 0 10px;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--muted);
  text-align: center;
}
.cart-split-btn + .cart-split-btn {
  margin-top: 8px;
}

/* ── Two-step unit estimator (tox page buy box) ───────────────────────── */
.est {
  margin: 20px 0 18px;
  display: grid;
  gap: 14px;
}
.est-field {
  display: block;
}
.est-label {
  display: block;
  font-size: 0.72rem;
  font-weight: var(--w-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 7px;
  font-family: var(--font-title);
}
/* The "what even is Xeomin" panel, under step one of the estimator. Tinted
   rather than boxed so it reads as part of the choice above it, not as a
   second thing to fill in. */
.est-why {
  margin-top: 10px;
  padding: 13px 15px 12px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.est-why-lead {
  margin: 0 0 10px;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--muted);
}
.est-why-copy {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ink);
}
.est-why-copy b {
  font-weight: var(--w-label);
}
.est-why-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
}
.est-why-facts li {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 10px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.74rem;
}
.est-why-facts span {
  color: var(--muted);
}
.est-why-facts b {
  font-weight: var(--w-label);
  color: var(--ink);
}
.est-why-more {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 11px;
  font-size: 0.79rem;
  font-weight: var(--w-label);
  color: var(--brand);
  text-decoration: none;
}
.est-why-more:hover {
  text-decoration: underline;
}
.est-why-more svg {
  width: 14px;
  height: 14px;
}

.est-select,
.est-summary {
  width: 100%;
  min-height: 52px;
  padding: 13px 15px;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}
.est-select:focus-visible,
.est-summary:focus-visible {
  outline: 3px solid var(--accent-soft);
  outline-offset: 2px;
}
.est-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  list-style: none;
}
.est-summary::-webkit-details-marker {
  display: none;
}
.est-drop[open] .est-summary {
  border-radius: var(--r) var(--r) 0 0;
  border-bottom-color: transparent;
}
.est-drop[open] .est-caret {
  transform: rotate(180deg);
}
.est-caret {
  flex-shrink: 0;
  color: var(--cta);
  transition: transform 0.18s ease;
}
.est-panel {
  border: 1px solid var(--line-strong);
  border-top: 0;
  border-radius: 0 0 var(--r) var(--r);
  background: #fff;
  max-height: 296px;
  overflow-y: auto;
}
.est-area {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 15px;
  cursor: pointer;
  border-top: 1px solid var(--line);
}
.est-area:first-child {
  border-top: 0;
}
.est-area:hover {
  background: var(--sand);
}
.est-area input {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  accent-color: var(--cta);
  cursor: pointer;
}
.est-area-body {
  flex: 1;
  min-width: 0;
}
.est-area-name {
  display: block;
  font-weight: 600;
  font-size: 0.92rem;
}
.est-area-sub {
  display: block;
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.35;
}
.est-area-units {
  flex-shrink: 0;
  font-size: 0.78rem;
  font-weight: var(--w-label);
  color: var(--cta);
}
.est-area-units small {
  display: block;
  font-size: 0.68rem;
  font-weight: 400;
  color: var(--muted-2);
  margin-top: 1px;
}
/* The "two syringes per area" caveat under the area picker. Sits with the
   step it qualifies rather than down in the estimate, because it changes how
   somebody reads the boxes they are ticking. */
.est-note {
  margin-top: 9px;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--muted);
}
.est-out {
  padding: 15px 17px;
  background: var(--sand);
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}
.est-out-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.est-out-row + .est-out-row {
  margin-top: 7px;
}
.est-out-k {
  font-size: 0.85rem;
  color: var(--ink-2);
}
.est-out-row b {
  font-size: 1.02rem;
}
.est-out-row.is-total b {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--cta);
  letter-spacing: -0.015em;
}
.est-hint {
  margin: 10px 0 0;
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--muted);
}

/* Product toggle on the calculator's estimate step. A segmented control, the
   same one the age and line-depth steps use, rather than a native select —
   four short names fit on one row and every rate stays one tap away. */
.calc-swap {
  margin: 0 0 16px;
}
.calc-swap-k {
  display: block;
  margin-bottom: 8px;
  font-size: 0.72rem;
  font-weight: var(--w-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.calc-swap .seg button {
  /* The base .seg button is a flex row, so a block child lands beside the
     label rather than under it — "Xeomin" and "sale" overlapped. */
  flex-direction: column;
  gap: 1px;
  line-height: 1.15;
}
.calc-swap .seg button i {
  font-style: normal;
  font-size: 0.62rem;
  font-weight: var(--w-label);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.75;
}

/* Homepage location band. */
.loc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px;
  margin: 26px 0 6px;
  text-align: left;
}
.loc-card {
  padding: 18px 20px;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg, var(--r));
}
.loc-k {
  font-size: 0.7rem;
  font-weight: var(--w-label);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 10px;
  font-family: var(--font-title);
}
.loc-addr {
  margin: 0 0 10px;
  font-weight: 600;
  line-height: 1.5;
}
.loc-link {
  font-weight: 600;
  color: var(--cta);
}
.loc-hours {
  list-style: none;
  margin: 0;
  padding: 0;
}
.loc-hours li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 0;
  font-size: 0.88rem;
  border-top: 1px solid var(--line);
}
.loc-hours li:first-child {
  border-top: 0;
}
.loc-hours span {
  color: var(--ink-2);
  min-width: 0;
}
.loc-hours b {
  flex-shrink: 0;
}

/* Names what is on sale, above the treatment page price. */
.sale-say {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  width: 100%;
  margin: 0 0 14px;
  padding: 9px 12px;
  text-align: left;
  background: var(--accent-wash, var(--sand));
  border: 1px solid var(--accent-soft);
  border-radius: var(--r-pill);
  font-size: 0.88rem;
}
.sale-say.is-pick {
  cursor: pointer;
  transition: border-color 0.14s, background 0.14s;
}
.sale-say.is-pick:hover {
  background: var(--sky-soft, var(--sand));
  border-color: var(--cta);
}
/* The gift version is a link to the promotions page, where the conditions
   live. A price cut needs no such page — the number is the whole offer.

   A rectangle rather than a pill: the pill radius is only right for a single
   line, and a gift offer needs a sentence. On two lines the curve ate the
   corners and the flag looked like it had fallen out of the box. */
.sale-say.is-gift {
  align-items: flex-start;
  border-radius: var(--r-lg);
  padding: 11px 14px;
  text-decoration: none;
  cursor: pointer;
}
.sale-say.is-gift .sale-say-flag {
  margin-top: 1px;
}
.sale-say.is-gift .sale-say-item {
  min-width: 0;
}
/* What the gift is worth. Styled like the struck price beside a sale rate,
   without the strike — that figure is cancelled, this one is the point. */
.sale-say.is-gift i {
  margin-left: 6px;
  font-style: normal;
  color: var(--muted);
  font-weight: 400;
  white-space: nowrap;
}
.sale-say.is-gift:hover {
  border-color: var(--cta);
}
/* A flat sale rate links to the conditions for the same reason the gift does,
   but it is one line and one price, so it keeps the pill rather than taking
   the gift's rectangle. */
.sale-say.is-rate {
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.14s, background 0.14s;
}
.sale-say.is-rate:hover {
  background: var(--sky-soft, var(--sand));
  border-color: var(--cta);
}
.sale-say-flag {
  flex-shrink: 0;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--cta);
  color: #fff;
  font-size: 0.68rem;
  font-weight: var(--w-label);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.sale-say-body {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  min-width: 0;
  color: var(--ink);
}
.sale-say-item b {
  font-weight: var(--w-label);
}
.sale-say-item s {
  margin-left: 6px;
  color: var(--muted-2);
  font-weight: 400;
}
/* The qualifier on a tiered rate — "first 10, then $10/unit". Quiet, and on
   its own line at phone widths, because it is a condition on the figure
   before it rather than a second figure. */
.sale-say-item i {
  margin-left: 6px;
  font-style: normal;
  font-weight: 400;
  color: var(--muted-2);
  white-space: nowrap;
}

/* Product step of the tox estimator — the standard option list, tightened up
   because four of them stack above the areas picker and the estimate. */
.est-opts {
  gap: 8px;
}
.est-opts .opt {
  padding: 12px 14px;
}
.est-opts .opt-sub {
  font-size: 0.8rem;
}
.est-opts .opt-price {
  font-size: 1.02rem;
  text-align: right;
  line-height: 1.25;
}
.est-opts .opt-price small {
  display: block;
  font-size: 0.68rem;
  font-weight: var(--w-semi);
  color: var(--muted-2);
}
.est-opts .opt-price .is-sale {
  color: var(--cta);
}
.est-opts .price-was {
  display: block;
  font-size: 0.78rem;
}
@media (max-width: 460px) {
  /* The badge is what pushes a name onto two lines on a small phone. */
  .est-opts .opt {
    grid-template-columns: 20px 1fr auto;
    gap: 10px;
    padding: 11px 12px;
  }
  .est-opts .opt-name {
    font-size: 0.95rem;
  }
  .est-opts .opt-name .badge {
    font-size: 0.6rem;
    padding: 2px 7px;
  }
}
