/**
 * Claire Abbas Site Builder — frontend styles.
 *
 * The approved Figma design is drawn at a 1728px viewport. Every clamp() below
 * is tuned so its vw term resolves to the exact signed-off desktop value at
 * 1728px, and caps there for wider screens.
 *
 *   1728 × 0.0578vw =  1px      →  Npx  ≈  (N / 17.28)vw
 *
 * Contents
 *   1  Fonts
 *   2  Tokens & reset
 *   3  Typography primitives
 *   4  Buttons
 *   5  Header & mobile drawer
 *   6  Hero
 *   7  Form panels
 *   8  Intro
 *   9  Services carousel
 *   10 Video component
 *   11 Price list
 *   12 Memberships
 *   13 Reviews
 *   14 Book appointment
 *   15 Social
 *   16 Footer
 *   17 Confirmation page
 *   18 Legal page
 *   19 Responsive
 *   20 Reduced motion
 */

/* ═══════════════════════════════════════════════════════════════════════
   1. Fonts — self-hosted, only the weights used in the design
   ═══════════════════════════════════════════════════════════════════════ */
@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('../fonts/bricolage-grotesque-300.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Instrument Sans';
  src: url('../fonts/instrument-sans-var.woff2') format('woff2-variations'),
       url('../fonts/instrument-sans-var.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter CA';
  src: url('../fonts/inter-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('../fonts/satoshi-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('../fonts/satoshi-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════
   2. Tokens & reset (tokens also emitted inline in wp_head)
   ═══════════════════════════════════════════════════════════════════════ */
.ca-site {
  --ca-green: #8B8D77;
  --ca-green-rgb: 139, 141, 119;
  --ca-green-deep: #385146;
  --ca-cream: #FFFBF5;
  --ca-cream-alt: #F5F1EA;
  --ca-beige: #E7E0D6;
  --ca-beige-2: #E6E1DA;
  --ca-off-white: #FAF9F7;
  --ca-dark: #4E4E4E;
  --ca-dark-2: #2C2A2A;
  --ca-white: #FFFFFF;

  --ca-radius-btn: 3px;
  --ca-radius-card: 5px;

  --ca-container: 1297px;
  --ca-gutter: clamp(20px, 12.5vw, 216px);

  --ca-font-display: 'Bricolage Grotesque', Georgia, serif;
  --ca-font-body: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  --ca-font-nav: 'Inter CA', system-ui, -apple-system, sans-serif;
  --ca-font-review: 'Satoshi', system-ui, -apple-system, sans-serif;

  --ca-ease: cubic-bezier(.16, 1, .3, 1);
  --ca-dur: .34s;
  --ca-dur-fast: .2s;

  font-family: var(--ca-font-body);
  color: var(--ca-dark);
  background: var(--ca-cream);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

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

.ca-site :where(img, svg, video, iframe) { display: block; max-width: 100%; }
.ca-site :where(img) { height: auto; }

/* Figma places some photographs larger than their frame with an explicit
   offset, which object-fit cannot express. --ca-crop-* carry those exact
   values; anything without them falls back to a centred cover. */
.ca-crop { position: relative; overflow: hidden; }
.ca-crop > img {
  position: absolute;
  max-width: none;
  width: var(--ca-crop-w, 100%);
  height: var(--ca-crop-h, 100%);
  left: var(--ca-crop-x, 0);
  top: var(--ca-crop-y, 0);
  object-fit: cover;
  object-position: var(--ca-crop-pos, 50% 50%);
}

.ca-site :where(p, h1, h2, h3, h4, h5, h6, ul, ol, figure, blockquote) {
  margin: 0;
  padding: 0;
}

.ca-site :where(ul, ol) { list-style: none; }

.ca-site :where(a) { color: inherit; text-decoration: none; }

.ca-site :where(button) { font: inherit; color: inherit; }

/* Focus — visible on every interactive element, never removed */
.ca-site a:focus-visible,
.ca-site button:focus-visible,
.ca-site input:focus-visible,
.ca-site select:focus-visible,
.ca-site textarea:focus-visible,
.ca-site [tabindex]:focus-visible {
  outline: 3px solid var(--ca-green-deep);
  outline-offset: 3px;
  border-radius: 2px;
}

.ca-site .ca-hero :focus-visible,
.ca-site .ca-videorow :focus-visible,
.ca-site .ca-members :focus-visible,
.ca-site .ca-conf :focus-visible { outline-color: var(--ca-white); }

/* Layout shells */
.ca-shell {
  width: 100%;
  max-width: calc(var(--ca-container) + var(--ca-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--ca-gutter);
}
.ca-shell--narrow { max-width: calc(820px + var(--ca-gutter) * 2); }

.ca-main { display: block; }

/* Screen-reader-only utility */
.ca-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ═══════════════════════════════════════════════════════════════════════
   3. Typography primitives
   ═══════════════════════════════════════════════════════════════════════ */

/* Display heading — Bricolage Grotesque Light 60px / 72.99 / -2.4px @1728 */
.ca-display {
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(34px, 3.472vw, 60px);
  line-height: 1;          /* Figma: leading-none on the display headings */
  letter-spacing: -0.04em;
  color: var(--ca-dark);
}

/* Eyebrow — Instrument Sans Medium 24px, sage */
.ca-eyebrow {
  font-family: var(--ca-font-body);
  font-weight: 500;
  font-size: clamp(15px, 1.389vw, 24px);
  line-height: 1.3;
  color: var(--ca-green);
  margin-bottom: clamp(4px, .463vw, 8px);
}

.ca-section-head { max-width: 900px; }
.ca-section-head--center { max-width: 760px; margin-inline: auto; text-align: center; }

.ca-section-head__intro {
  margin-top: clamp(12px, 1.16vw, 20px);
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.5;
  color: var(--ca-dark);
  opacity: .8;
}

/* ═══════════════════════════════════════════════════════════════════════
   4. Buttons — Instrument Sans Medium 18px, radius 3px
   ═══════════════════════════════════════════════════════════════════════ */
.ca-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 62px;
  padding: 0 clamp(24px, 2.2vw, 38px);
  font-family: var(--ca-font-body);
  font-weight: 500;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.2;
  text-align: center;
  border-radius: var(--ca-radius-btn);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color var(--ca-dur-fast) var(--ca-ease),
              color var(--ca-dur-fast) var(--ca-ease),
              border-color var(--ca-dur-fast) var(--ca-ease),
              transform var(--ca-dur-fast) var(--ca-ease);
}

.ca-btn--primary {
  background: var(--ca-green);
  color: var(--ca-white);
  box-shadow: var(--ca-shadow-btn, 0 2px 2px rgba(0, 0, 0, .05)),
              inset 0 -2px 2px rgba(0, 0, 0, .04);
}
.ca-btn--primary:hover { background: #7C7E69; }
.ca-btn--primary:active { transform: translateY(1px); }

.ca-btn--outline {
  background: transparent;
  color: var(--ca-white);
  border-color: var(--ca-beige);
}
.ca-btn--outline:hover { background: var(--ca-beige); color: var(--ca-dark); }
.ca-btn--outline:active { transform: translateY(1px); }

/* ═══════════════════════════════════════════════════════════════════════
   5. Header & mobile drawer
   Figma: logo x86, nav from x705, phone x1296, CTA 191×62 ending x1671
   ═══════════════════════════════════════════════════════════════════════ */
.ca-header {
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  padding-block: clamp(18px, 2.66vw, 46px);
  background: transparent;
  transition: background-color var(--ca-dur) var(--ca-ease),
              box-shadow var(--ca-dur) var(--ca-ease),
              padding var(--ca-dur) var(--ca-ease);
}

/* Scrolled state — white, pinned to the viewport.
   The header is out of flow in BOTH states (absolute over the hero, fixed once
   scrolled), so switching between them cannot move any content below it. Only
   the header's own padding animates. */
/* Frosted glass rather than a solid white bar: the page stays faintly visible
   through it, which reads far lighter at this header's height. Saturation is
   nudged up so the cream and sage beneath keep their warmth through the blur
   instead of going grey. */
.ca-header.is-scrolled {
  position: fixed;
  background: rgba(255, 255, 255, .72);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 1px 0 rgba(78, 78, 78, .07), 0 10px 30px rgba(0, 0, 0, .045);
  /* ~80px tall: 16 + 48 (the CTA, the tallest item) + 16 */
  padding-block: clamp(10px, .926vw, 16px);
}
/* The scrolled bar is driven by its tallest child, so the logo and the CTA
   both shrink with it. Everything stays vertically centred by the flex
   alignment already on .ca-header__inner. */
.ca-header.is-scrolled .ca-logo__img { width: clamp(150px, 15.336vw, 265px); }
.ca-header.is-scrolled .ca-header__cta { min-height: 48px; min-width: 165px; }
.ca-header.is-scrolled .ca-burger { width: 44px; height: 44px; }

/* Without backdrop-filter the translucency would leave text on a busy
   photograph, so fall back to near-solid white. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ca-header.is-scrolled { background: rgba(255, 255, 255, .95); }
}

.ca-header__inner {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.315vw, 40px);
  padding-left: clamp(20px, 4.98vw, 86px);
  padding-right: clamp(20px, 3.3vw, 57px);
}

/* Logo — both variants share one grid cell and cross-fade, so no reflow and
   no flash of a missing image on the first scroll. With no dark artwork
   uploaded the packaged SVG is simply recoloured through currentColor. */
.ca-logo {
  flex: none;
  display: inline-grid;
  color: var(--ca-white);
  transition: color var(--ca-dur) var(--ca-ease);
}
.ca-logo__variant {
  grid-area: 1 / 1;
  display: block;
  transition: opacity var(--ca-dur) var(--ca-ease);
}
.ca-logo__variant--dark { opacity: 0; }
.ca-header.is-scrolled .ca-logo { color: var(--ca-dark-2); }
.ca-header.is-scrolled .ca-logo.has-dark .ca-logo__variant--light { opacity: 0; }
.ca-header.is-scrolled .ca-logo.has-dark .ca-logo__variant--dark  { opacity: 1; }

.ca-logo__img {
  width: clamp(190px, 19.68vw, 340px);
  height: auto;
  color: currentColor;
  transition: width var(--ca-dur) var(--ca-ease);
}

.ca-nav { margin-left: auto; }
.ca-nav__list {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.3vw, 40px);
}
.ca-nav__link {
  font-family: var(--ca-font-nav);
  font-weight: 500;
  font-size: 16px;
  line-height: 1.22;
  color: var(--ca-white);
  position: relative;
}
.ca-nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -5px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--ca-dur-fast) var(--ca-ease);
}
.ca-nav__link:hover::after { transform: scaleX(1); }

/* ── Scrolled header: dark, legible content over white ──────────────────
   Colour only. Nothing here changes size or position, so the switch cannot
   nudge the layout. The CTA keeps its sage fill, which reads correctly on
   both the hero photograph and the white bar. */
.ca-header.is-scrolled .ca-nav__link,
.ca-header.is-scrolled .ca-header__phone { color: var(--ca-dark-2); }
.ca-header.is-scrolled .ca-nav__link:hover { color: var(--ca-green); }
.ca-header.is-scrolled .ca-header__phone:hover { color: var(--ca-green); }
.ca-header.is-scrolled .ca-burger span { background: var(--ca-dark-2); }

.ca-nav__link,
.ca-header__phone { transition: color var(--ca-dur) var(--ca-ease); }
.ca-burger span { transition: background-color var(--ca-dur) var(--ca-ease); }

/* Focus rings must stay visible against whichever background is showing. */
.ca-header :where(a, button):focus-visible {
  outline: 2px solid var(--ca-white);
  outline-offset: 3px;
  border-radius: 2px;
}
.ca-header.is-scrolled :where(a, button):focus-visible { outline-color: var(--ca-green); }

.ca-header__aside {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.488vw, 43px);
  flex: none;
}

.ca-header__phone {
  font-family: var(--ca-font-nav);
  font-weight: 500;
  font-size: 16px;
  line-height: 1.22;
  color: var(--ca-white);
  width: clamp(120px, 8.102vw, 140px);
  flex: none;
}
.ca-header__phone-label,
.ca-header__phone-number { display: block; }

.ca-header__cta {
  min-width: 191px;
  min-height: 62px;
  transition: min-height var(--ca-dur) var(--ca-ease),
              min-width var(--ca-dur) var(--ca-ease),
              background-color var(--ca-dur-fast) var(--ca-ease);
}

/* Burger — X state driven from aria-expanded, not a JS class */
.ca-burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 48px;
  height: 48px;
  padding: 12px;
  background: transparent;
  border: 0;
  cursor: pointer;
  border-radius: 6px;
}
.ca-burger span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--ca-white);
  border-radius: 2px;
  transition: transform var(--ca-dur-fast) var(--ca-ease),
              opacity var(--ca-dur-fast) var(--ca-ease);
}
.ca-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.ca-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.ca-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Drawer */
.ca-mobile {
  position: fixed;
  inset: 0;
  z-index: 200;
  visibility: hidden;      /* also removes panel links from the tab order */
  pointer-events: none;
}
.ca-mobile::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(44, 42, 42, .5);
  opacity: 0;
  transition: opacity var(--ca-dur) var(--ca-ease);
}
.ca-mobile.is-open { visibility: visible; pointer-events: auto; }
.ca-mobile.is-open::before { opacity: 1; }

/* Scroll lock for the mobile drawer. Class-driven so that third-party
   scripts which save and restore the document's inline overflow cannot
   strand the page in a locked state — see the note in frontend.js. */
html.ca-scroll-locked,
html.ca-scroll-locked body { overflow: hidden; }
html.ca-scroll-locked body { padding-right: var(--ca-scrollbar, 0px); }

.ca-mobile__panel {
  position: absolute;
  inset-block: 0;
  right: 0;
  /* Full width on phones, 80% on tablets — see the responsive section */
  width: min(420px, 100%);
  display: flex;
  flex-direction: column;
  background: var(--ca-green);
  transform: translateX(100%);
  transition: transform var(--ca-dur) var(--ca-ease);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.ca-mobile.is-open .ca-mobile__panel { transform: translateX(0); }

.ca-mobile__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 24px;
  border-bottom: 1px solid rgba(255, 255, 255, .18);
}
.ca-mobile__logo { color: var(--ca-white); }
.ca-mobile__logo-img { width: 200px; height: auto; color: var(--ca-white); }

.ca-mobile__close {
  flex: none;
  width: 48px; height: 48px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 0;
  color: var(--ca-white);
  cursor: pointer;
  border-radius: 6px;
}
.ca-mobile__close-icon { width: 24px; height: 24px; }

.ca-mobile__nav { flex: 1; padding: 14px 20px; }
.ca-mobile__item { border-bottom: 1px solid rgba(255, 255, 255, .14); }
.ca-mobile__item a {
  display: block;
  padding: 18px 12px;
  min-height: 44px;
  font-family: var(--ca-font-body);
  font-weight: 500;
  font-size: 16px;
  color: var(--ca-white);
  border-radius: 6px;
  transition: background-color var(--ca-dur-fast) var(--ca-ease);
}
.ca-mobile__item a:hover { background: rgba(255, 255, 255, .1); }

.ca-mobile__foot {
  padding: 20px 24px calc(20px + env(safe-area-inset-bottom));
  border-top: 1px solid rgba(255, 255, 255, .18);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ca-mobile__cta { width: 100%; background: var(--ca-white); color: var(--ca-green-deep); }
.ca-mobile__cta:hover { background: var(--ca-beige); }
.ca-mobile__phone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 44px;
  color: var(--ca-white);
  font-size: 16px;
}
.ca-mobile__phone-icon { width: 18px; height: 18px; }

/* ═══════════════════════════════════════════════════════════════════════
   6. Hero — full-bleed 1728×971, heading 70px/-2.8px
   ═══════════════════════════════════════════════════════════════════════ */
.ca-hero {
  position: relative;
  isolation: isolate;
  min-height: clamp(620px, 56.2vw, 971px);
  display: flex;
  align-items: center;
  overflow: hidden;
}

.ca-hero__media { position: absolute; inset: 0; z-index: 0; }
.ca-hero__media { --ca-crop-w: 101.100%; --ca-crop-h: 101.236%; --ca-crop-x: -1.100%; --ca-crop-y: 0%; }

/* Figma layers five multiply gradients; these two reproduce the result. */
/* Figma 3:284 — the same four-gradient treatment as the confirmation hero
   (both are "Group 63"); two of them were missing here. */
.ca-hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(-50.009deg, rgba(0, 0, 0, 0) 56.52%, rgba(0, 0, 0, .34) 110.14%),
    linear-gradient(-55.784deg, rgba(0, 0, 0, .34) 0.683%, rgba(0, 0, 0, 0) 32.982%),
    linear-gradient(-1.310deg, rgba(0, 0, 0, 0) 75.966%, rgba(0, 0, 0, .6) 98.842%),
    linear-gradient(233.804deg, rgba(0, 0, 0, 0) 41.135%, rgba(0, 0, 0, .6) 105.53%);
}

/* Figma: content column x102–742, form panel x829–1670, both bottom-aligned
   at y889 within a 971px band. */
.ca-hero__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1728px;
  margin-inline: auto;
  padding-left: clamp(20px, 4.977vw, 86px);
  padding-right: clamp(20px, 3.356vw, 58px);
  padding-top: clamp(120px, 7.64vw, 132px);
  padding-bottom: clamp(48px, 4.745vw, 82px);
  display: grid;
  grid-template-columns: minmax(0, 640px) minmax(0, 841px);
  gap: clamp(24px, 5.961vw, 103px);
  align-items: end;
}

.ca-hero__content { position: relative; padding-left: clamp(14px, .93vw, 16px); }
/* The vertical rule at x86 in the design */
.ca-hero__content::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  width: 1px;
  height: clamp(96px, 8.1vw, 140px);
  background: var(--ca-white);
  opacity: .85;
}

.ca-hero__title {
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(38px, 4.051vw, 70px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ca-white);
  text-shadow: 0 2px 2px rgba(0, 0, 0, .1);
}

.ca-hero__text {
  margin-top: clamp(14px, 1.157vw, 20px);
  max-width: 517px;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.5;
  color: var(--ca-white);
}

.ca-hero__btn { margin-top: clamp(22px, 1.9vw, 33px); min-width: min(370px, 100%); }

/* ═══════════════════════════════════════════════════════════════════════
   7. Form panels — beige card, inputs at 80% white
   ═══════════════════════════════════════════════════════════════════════ */
/* Figma: hero panel 841×757 with 111px top padding and 96px side padding;
   book panel 743×757 with 111px top padding and 85px side padding. */
.ca-form-panel {
  background: var(--ca-beige);
  border-radius: var(--ca-radius-card);
  padding: clamp(24px, 4.630vw, 80px);   /* uniform on all four sides */
  min-height: clamp(0px, 43.8vw, 757px);
  display: flex;
  flex-direction: column;
}

.ca-form-panel__title {
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(26px, 2.315vw, 40px);
  line-height: .875;
  letter-spacing: -0.04em;
  color: var(--ca-dark);
}

.ca-form-panel__intro {
  margin-top: clamp(8px, .752vw, 13px);
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.3;
  color: var(--ca-green);
}

.ca-form { margin-top: clamp(18px, 1.562vw, 27px); }
/* WPForms wraps its markup in several containers; none may add height. */
.ca-form > *,
.ca-form .wpforms-container > *,
.ca-form .wpforms-form > * { margin-top: 0; margin-bottom: 0; }
.ca-form .wpforms-container::before,
.ca-form .wpforms-container::after { content: none; }

/* ── WPForms ──────────────────────────────────────────────────────────
   WPForms' own stylesheets are dequeued on builder pages (see
   includes/template.php) so the form matches the approved design exactly.
   Its JavaScript — validation and AJAX submission — is untouched.
   Figma: five 60px fields on a 75px pitch (15px gap), then the submit. */

.ca-form .wpforms-container,
.ca-form .wpforms-container-full { margin: 0; padding: 0; }
.ca-form .wpforms-form { margin: 0; }
.ca-form .wpforms-field-container { display: block; }

.ca-form .wpforms-form .wpforms-field {
  padding: 0 0 clamp(10px, .868vw, 15px);
  margin: 0;
  clear: both;
}

/* The design shows placeholders only — no visible labels */
.ca-form .wpforms-form .wpforms-field-label,
.ca-form .wpforms-form .wpforms-field-sublabel,
.ca-form .wpforms-form .wpforms-required-label,
.ca-form .wpforms-form .wpforms-field-description,
.ca-form .wpforms-error-noscript,
.ca-form .wpforms-form .wpforms-hidden-strict {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.ca-form .wpforms-form input[type="text"],
.ca-form .wpforms-form input[type="email"],
.ca-form .wpforms-form input[type="tel"],
.ca-form .wpforms-form input[type="url"],
.ca-form .wpforms-form input[type="number"],
.ca-form .wpforms-form input[type="date"],
.ca-form .wpforms-form select,
.ca-form .wpforms-form textarea {
  width: 100%;
  min-height: 60px;
  padding: 0 clamp(18px, 1.53vw, 26px);
  background: rgba(255, 255, 255, .8);
  border: 1px solid transparent;
  border-radius: 0;
  font-family: var(--ca-font-body);
  font-weight: 400;
  font-size: clamp(15px, .926vw, 16px);
  color: var(--ca-dark);
  box-shadow: none;
  transition: background-color var(--ca-dur-fast) var(--ca-ease),
              border-color var(--ca-dur-fast) var(--ca-ease);
}
.ca-form .wpforms-form textarea { min-height: 120px; padding-top: 18px; padding-bottom: 18px; }

/* Date / Time field.
   WPForms splits it into two blocks that stack once its own stylesheet is
   dequeued, making the field twice the height of every other row. The design
   has one row per question, so the date and time sit side by side. Their
   sublabels stay in the accessibility tree (hidden above with every other
   label) so each input is still announced as "Date" / "Time". */
.ca-form .wpforms-form .wpforms-field-date-time fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}
.ca-form .wpforms-form .wpforms-field-date-time .wpforms-field-row {
  display: flex;
  gap: clamp(10px, .868vw, 15px);
}
.ca-form .wpforms-form .wpforms-field-date-time .wpforms-field-row-block {
  flex: 1 1 0;
  min-width: 0;
}
.ca-form .wpforms-form .wpforms-datepicker-wrap { position: relative; display: block; }
/* Keep the clear-date control inside the field rather than floating loose */
.ca-form .wpforms-form .wpforms-datepicker-clear {
  position: absolute;
  right: clamp(10px, .87vw, 15px);
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  cursor: pointer;
}

.ca-form .wpforms-form select {
  -webkit-appearance: none;
  appearance: none;
  background-image: none;
  cursor: pointer;
}

.ca-form .wpforms-form input::placeholder,
.ca-form .wpforms-form textarea::placeholder { color: var(--ca-green); opacity: 1; }

.ca-form .wpforms-form input:focus,
.ca-form .wpforms-form select:focus,
.ca-form .wpforms-form textarea:focus {
  background: var(--ca-white);
  border-color: var(--ca-green);
  outline: 2px solid var(--ca-green-deep);
  outline-offset: 1px;
}

.ca-form .wpforms-submit-container { padding: 0; margin: 0; }

.ca-form .wpforms-form button[type="submit"] {
  width: 100%;
  min-height: 60px;
  margin: 0;
  padding: 0 24px;
  background: var(--ca-green);
  color: var(--ca-white);
  border: 0;
  border-radius: var(--ca-radius-btn);
  font-family: var(--ca-font-body);
  font-weight: 500;
  font-size: clamp(15px, .926vw, 16px);
  cursor: pointer;
  transition: background-color var(--ca-dur-fast) var(--ca-ease);
}
.ca-form .wpforms-form button[type="submit"]:hover { background: #7C7E69; }

.ca-form .wpforms-form .wpforms-error {
  color: #9B2C2C;
  font-size: 14px;
  margin-top: 6px;
}
.ca-form .wpforms-form input.wpforms-error,
.ca-form .wpforms-form select.wpforms-error,
.ca-form .wpforms-form textarea.wpforms-error { border-color: #9B2C2C; }

/* Admin-only notice when no shortcode has been chosen */
.ca-form-placeholder {
  margin-top: clamp(18px, 1.6vw, 28px);
  padding: 20px 22px;
  border: 1px dashed var(--ca-green);
  border-radius: var(--ca-radius-btn);
  background: rgba(255, 255, 255, .55);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ca-dark);
}
.ca-form-placeholder p + p { margin-top: 6px; }

/* ═══════════════════════════════════════════════════════════════════════
   8. Intro
   ═══════════════════════════════════════════════════════════════════════ */
.ca-intro {
  position: relative;
  isolation: isolate;
  /* The watermark starts above this band (Figma y886, band top y971) exactly
     as it does in the design, where the hero covers the overhang. Clipping
     reproduces that without letting it bleed over the hero. */
  overflow: clip;
  background: var(--ca-cream);
  padding-bottom: clamp(40px, 5.787vw, 100px);
}

/* The exported SVG already carries the design's own opacity="0.05" on its
   root group. Passing a translucent colour as well multiplied the two —
   0.05 x 0.07 = 0.0035 — which is why these marks were effectively invisible.
   currentColor is solid here so the asset renders at the 5% the design
   specifies, and nothing more. */
.ca-intro__watermark,
.ca-book__watermark {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  color: var(--ca-green);
}
/* Figma 3:282 — x-348.5 y886 (i.e. 86px above the band top), 1650 × 1013 */
.ca-intro__watermark { left: -20.171%; top: clamp(-86px, -4.9769vw, 0px); width: 95.494%; }
/* Figma 5:848 places this at x1123 y7074, where the photograph and the form
   card cover almost all of it — only a ~100px sliver of the right margin was
   ever visible. Anchored to the same right-hand side, but lifted and widened
   so it also reads in the cream above and below the card, which is how the
   equivalent mark behaves in the Intro band. */
.ca-book__watermark { left: 46%; top: -14%; width: 80%; }
.ca-watermark__svg { width: 100%; height: auto; }

/* Figma, measured from the visible top of the intro band (y971 — the cream
   rectangle starts at y854 but sits behind the hero, which covers it to y971):
     video  x0     y+155   1517 × 697   (87.789% wide, flush left)
     card   x1119  y+339    553 × 785   (32.030% wide, 3.213% from the right)
   The card is in the grid rather than absolutely positioned, so it — not the
   video — sets the block's height, exactly as it does in the design. */
.ca-intro__top {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 32.0297% 3.2131%;
  align-items: start;
  padding-top: clamp(40px, 8.9699vw, 155px);
}

/* Video is flush to the left edge and stops short of the right, per the design */
.ca-intro__video { grid-column: 1 / -1; grid-row: 1; width: 87.789%; }
.ca-intro__video .ca-video { aspect-ratio: 1517 / 697; border-radius: 0; }

/* Figma crops the portrait source (1467×2200) to a wide frame of Claire's
   face: the image is scaled to 1624.242 × 2436.065 and offset within the
   1517 × 697 window. Percentages are of that window. */
.ca-video--intro .ca-video__cover {
  --ca-crop-w: 100%; --ca-crop-h: 100%;
  --ca-crop-x: 0;  --ca-crop-y: 0;
}

/* The dark card overlaps the video's lower-right.
   Figma 3:373 — #4E4E4E flat, 4px radius, 70px side padding, 92px top. */
.ca-intro__card {
  grid-column: 2;
  grid-row: 1;
  z-index: 2;
  align-self: start;
  margin-top: clamp(40px, 10.6481vw, 184px);
  min-height: clamp(0px, 45.4282vw, 785px);
  background: #4E4E4E;
  color: var(--ca-white);
  border-radius: 4px;
  padding: clamp(24px, 5.3241vw, 92px) clamp(22px, 4.0509vw, 70px);
}

.ca-intro__card-eyebrow {
  font-weight: 600;
  font-size: clamp(14px, 1.1574vw, 20px);
  line-height: 1.22;
  color: var(--ca-green);
}
.ca-intro__card-title {
  margin-top: clamp(5px, .463vw, 8px);
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(26px, 2.3148vw, 40px);
  line-height: 1.07;
  letter-spacing: -0.04em;
}
.ca-intro__card-lead {
  margin-top: clamp(13px, 1.157vw, 20px);
  font-weight: 600;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.22;
  color: rgba(255, 255, 255, .7);
}
.ca-intro__card-body {
  margin-top: clamp(14px, 1.273vw, 22px);
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.22;
  color: rgba(255, 255, 255, .5);
}
.ca-intro__card-body p + p { margin-top: 1em; }

/* Figma: heading x216 y+1091, body x216 y+1241 (845 wide),
   CTA x1119 y+1294 — the CTA aligns to the card's left edge, not the gutter.
   Within the 1296 shell that splits 903 / 393. */
.ca-intro__bottom {
  display: grid;
  grid-template-columns: minmax(0, 903fr) minmax(0, 393fr);
  /* No gap: the 903/393 split already carries the design's spacing (the copy
     is 845 wide inside its 903 column). A gap here would be subtracted from
     both tracks and push the CTA off the card's left edge. */
  gap: 0;
  align-items: start;
  padding-top: clamp(40px, 7.1vw, 122px);
}

/* On desktop the heading sits beside the lower half of the overlapping card
   rather than below it, so the block is pulled up by the 150px the design
   shows. The two never collide horizontally (heading x216, card x1119).
   Below 1100px the card stacks under the video and this no longer applies. */
@media (min-width: 1101px) {
  .ca-intro__bottom {
    margin-top: clamp(-150px, -8.6806vw, 0px);
    padding-top: 0;
  }
}
.ca-intro__copy { max-width: 845px; }
.ca-intro__body {
  margin-top: clamp(18px, 1.736vw, 30px);
  max-width: 845px;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.42;
  color: var(--ca-dark);
  opacity: .85;
}
.ca-intro__body p + p { margin-top: 1em; }
/* CTA sits 203px below the heading's top edge, 234 × 62 (Figma 3:330) */
.ca-intro__action { margin-top: clamp(24px, 11.7476vw, 203px); }
.ca-intro__action .ca-btn { min-width: clamp(150px, 13.5417vw, 234px); min-height: 62px; }
@media (max-width: 1100px) {
  .ca-intro__action { margin-top: clamp(20px, 3vw, 32px); }
}

/* ═══════════════════════════════════════════════════════════════════════
   9. Services carousel — cards 612×677, chip 342×101
   ═══════════════════════════════════════════════════════════════════════ */
.ca-services {
  background: var(--ca-cream);
  padding-block: clamp(40px, 5.787vw, 100px);
  border-top: 1px solid rgba(var(--ca-green-rgb), .25);
}

/* Figma: heading block ends y2628, cards begin y2672 */
.ca-services__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: clamp(28px, 3.0093vw, 52px);
}
.ca-services__head .ca-section-head { flex: 1 1 auto; min-width: 0; }

.ca-carousel__controls { display: flex; gap: 4px; flex: none; }
.ca-carousel__btn {
  width: clamp(48px, 3.646vw, 63px);
  height: clamp(48px, 3.646vw, 63px);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--ca-radius-btn);
  cursor: pointer;
  transition: background-color var(--ca-dur-fast) var(--ca-ease),
              opacity var(--ca-dur-fast) var(--ca-ease);
}
.ca-carousel__btn--prev { background: var(--ca-beige); color: var(--ca-dark); }
.ca-carousel__btn--next { background: var(--ca-green); color: var(--ca-white); }
.ca-carousel__btn:hover:not(:disabled) { filter: brightness(.94); }
.ca-carousel__btn:disabled { opacity: .4; cursor: default; }
.ca-carousel__icon { width: 20px; height: 20px; }

.ca-services__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(260px, 35.4vw, 612px);
  align-items: start;
  gap: clamp(20px, 4.2vw, 73px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-inline: var(--ca-gutter);
  scroll-padding-left: var(--ca-gutter);
  padding-bottom: 8px;
}
.ca-services__track::-webkit-scrollbar { display: none; }
.ca-services__track.is-dragging { scroll-snap-type: none; scroll-behavior: auto; cursor: grabbing; }
.ca-services__track > * { scroll-snap-align: start; }

/* Figma places the intro paragraph above the second card, not in its own
   slot — card 2 is pushed down by exactly the paragraph's block. */
.ca-service { display: flex; flex-direction: column; }

/* The design alternates every card and staggers the flipped ones downward:
     even cards  tile  → copy   (Figma: media y2672, copy y3405)
     odd cards   copy  → tile   (Figma: copy y2721, media y2816)
   `order` does the flip so the DOM stays tile-then-copy for every card, which
   keeps the reading order consistent and makes the pattern continue correctly
   however many services are added. */
.ca-service.is-offset { margin-top: clamp(0px, 2.836vw, 49px); }
.ca-service.is-offset .ca-service__desc {
  order: -1;
  margin-top: 0;
  margin-bottom: clamp(16px, 2.7778vw, 48px);
}

.ca-service__link { display: block; }

.ca-service__media {
  position: relative;
  aspect-ratio: 612 / 677;
  border-radius: var(--ca-radius-card);
  overflow: hidden;
  background: var(--ca-beige);
}
/* No explicit crop here, unlike the other bands. Figma's 166% "crop" on these
   cards is just object-fit: cover — a 1500 × 1000 photograph filling a
   612 × 677 portrait window — and the small per-card horizontal nudges are the
   designer framing three specific stock photos. These images come from a
   repeater the client edits, so a hardcoded offset would mis-frame whatever
   they upload next. Centred cover is both correct for the design and correct
   for every future image. */
.ca-service__img--empty { display: block; width: 100%; height: 100%; }

.ca-service__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 44%, rgba(0, 0, 0, .7) 100%);
  pointer-events: none;
}

.ca-service__label {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 1;
  width: clamp(200px, 19.8vw, 342px);
  min-height: clamp(64px, 5.845vw, 101px);
  display: grid;
  place-items: center;
  padding: 12px 20px;
  background: rgba(var(--ca-green-rgb), .9);
  color: var(--ca-white);
  border-radius: var(--ca-radius-btn);
  font-weight: 500;
  font-size: clamp(16px, 1.273vw, 22px);
  text-align: center;
  transition: background-color var(--ca-dur-fast) var(--ca-ease);
}
.ca-service__link:hover .ca-service__label { background: rgba(var(--ca-green-rgb), 1); }
.ca-service__link:hover .ca-service__img { transform: scale(1.02); }
.ca-service__img { transition: transform var(--ca-dur) var(--ca-ease); }

.ca-service__desc {
  /* Figma: card media ends y3349, description begins y3405 */
  margin-top: clamp(16px, 3.2407vw, 56px);
  max-width: 530px;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.4;
  color: var(--ca-dark);
  opacity: .8;
}

/* ═══════════════════════════════════════════════════════════════════════
   10. Video component — shared by Intro and Video Row
   ═══════════════════════════════════════════════════════════════════════ */
.ca-video {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--ca-dark-2);
  /* Safety net: every usage sets its own ratio, but the component must never
     collapse if a new one forgets. */
  aspect-ratio: 16 / 9;
}

/* The player must behave like `background-size: cover`.
   A <video> gets that from object-fit. An <iframe> cannot — object-fit has no
   effect on it, so a 16:9 film in a 1728×697 band letterboxes with black bars
   top and bottom. The fix is to size the frame itself so its 16:9 content
   always overflows the container on one axis, then centre it and clip.
   Container query units make that a pure-CSS calculation against the band
   rather than the viewport, so it holds for the Intro (87.8% wide) and the
   full-bleed Video Row alike. */
.ca-video__player { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.ca-video__player iframe,
.ca-video__player video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}

@supports (width: 1cqw) {
  .ca-video__player { container-type: size; }
  .ca-video__player iframe {
    inset: auto;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* cover: whichever axis is short, grow to fill it and let the other spill */
    width:  max(100cqw, 100cqh * 16 / 9);
    height: max(100cqh, 100cqw * 9 / 16);
    max-width: none;
  }
}

.ca-video__cover {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 1;
  transition: opacity .55s var(--ca-ease);
}
.ca-video__cover-img { width: 100%; height: 100%; object-fit: cover; }
.ca-video.is-playing .ca-video__cover { opacity: 0; pointer-events: none; }

/* With no video source the cover is simply the image — it still fills the
   frame, which the component's aspect-ratio establishes. */

/* Play control.
   Figma 54:17 — a 135px circle filled #838572 at 20% with a 1.6px white
   stroke, containing the word "Play" (22px, semi-bold, white). Not a glyph:
   implemented exactly as designed. Hidden entirely when no video is set,
   because ca_render_video() only emits the button when a source exists. */
.ca-video__toggle {
  position: absolute;
  z-index: 4;
  width: clamp(76px, 7.8125vw, 135px);
  height: clamp(76px, 7.8125vw, 135px);
  display: grid;
  place-items: center;
  padding: 0;
  background: rgba(131, 133, 114, .2);
  border: 1.6px solid rgba(255, 255, 255, .95);
  border-radius: 50%;
  color: var(--ca-white);
  cursor: pointer;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  transition: background-color var(--ca-dur-fast) var(--ca-ease),
              border-color var(--ca-dur-fast) var(--ca-ease),
              transform var(--ca-dur-fast) var(--ca-ease);
}
.ca-video__toggle-label {
  font-family: var(--ca-font-nav);
  font-weight: 600;
  font-size: clamp(15px, 1.2731vw, 22px);
  line-height: 1.22;
  text-align: center;
}
.ca-video__toggle:hover {
  background: rgba(131, 133, 114, .45);
  border-color: var(--ca-white);
  transform: scale(1.04);
}
.ca-video__toggle:active { transform: scale(.97); }
.ca-video__toggle:focus-visible {
  outline: 2px solid var(--ca-white);
  outline-offset: 4px;
}

/* Intro: Figma places the control at x46, y518 within the 1517×697 frame */
.ca-video--intro .ca-video__toggle { left: clamp(16px, 2.6620vw, 46px); top: 74.32%; }
/* Video row: dead centre (Figma 54:16) */
.ca-video--row .ca-video__toggle { left: 50%; top: 50%; transform: translate(-50%, -50%); }
.ca-video--row .ca-video__toggle:hover  { transform: translate(-50%, -50%) scale(1.04); }
.ca-video--row .ca-video__toggle:active { transform: translate(-50%, -50%) scale(.97); }

@media (prefers-reduced-motion: reduce) {
  .ca-video__toggle:hover,
  .ca-video__toggle:active,
  .ca-video--row .ca-video__toggle:hover,
  .ca-video--row .ca-video__toggle:active { transform: none; }
  .ca-video--row .ca-video__toggle { transform: translate(-50%, -50%); }
}

/* ── Playback state ──────────────────────────────────────────────────
   frontend.js flags the section while its video is playing, from the
   player's own events. The Intro card and the Video Row logo both sit over
   the film, so both step aside — visibility keeps the card out of the tab
   order while it is invisible, and both return on pause, on end, and if
   playback fails. */
.ca-intro__card,
.ca-videorow__logo {
  transition: opacity .5s var(--ca-ease), visibility .5s var(--ca-ease);
}
.ca-intro.is-video-playing .ca-intro__card {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.ca-videorow.is-video-playing .ca-videorow__logo { opacity: 0; }

.ca-videorow {
  position: relative;
  isolation: isolate;
}
.ca-videorow .ca-video { aspect-ratio: 1728 / 697; }
.ca-video--row .ca-video__cover {
  --ca-crop-w: 100%; --ca-crop-h: 100%;
  --ca-crop-x: 0; --ca-crop-y: 0;
}
/* Figma 3:396 — a dark corner wash that keeps the logo legible over the
   photograph. Sits above the cover (z-2) and below the Play control (z-4),
   so it stays put whether or not the video is playing. */
.ca-video--row::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(135.841deg, rgba(0, 0, 0, 0) 61.326%, rgba(0, 0, 0, .6) 110.82%);
}

/* Figma 54:21 — 275 × 34 at 72.9 from the right, 54 from the bottom */
.ca-videorow__logo {
  position: absolute;
  right: clamp(16px, 4.2188vw, 73px);
  bottom: clamp(16px, 3.125vw, 54px);
  z-index: 4;
  width: clamp(150px, 15.9144vw, 275px);
  color: var(--ca-white);
  pointer-events: none;
}
.ca-videorow__logo-img { width: 100%; height: auto; color: var(--ca-white); }

/* ═══════════════════════════════════════════════════════════════════════
   11. Price list — rows 104px apart, divider at x593
   ═══════════════════════════════════════════════════════════════════════ */
.ca-pricing {
  background: var(--ca-white);
  padding-block: clamp(48px, 9.317vw, 161px) clamp(48px, 11.516vw, 199px);
}
.ca-pricing__list { margin-top: clamp(20px, 1.794vw, 31px); }

.ca-pricing__row {
  display: grid;
  grid-template-columns: minmax(0, 374px) minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(16px, 1.7vw, 30px);
  min-height: clamp(76px, 6.02vw, 104px);
  border-bottom: 1px solid rgba(var(--ca-green-rgb), .3);
}
.ca-pricing__row:first-child { border-top: 1px solid rgba(var(--ca-green-rgb), .3); }

.ca-pricing__name {
  font-weight: 500;
  font-size: clamp(16px, 1.273vw, 22px);
  line-height: 1.3;
  color: var(--ca-green);
}

.ca-pricing__value {
  position: relative;
  padding-left: clamp(16px, 3.24vw, 56px);
}
/* The vertical rule between name and price */
.ca-pricing__value::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: clamp(40px, 3.5vw, 60px);
  background: rgba(var(--ca-green-rgb), .3);
}
.ca-pricing__price {
  font-size: clamp(16px, 1.389vw, 24px);
  line-height: 1.3;
  color: var(--ca-dark);
}
.ca-pricing__note {
  margin-top: 4px;
  font-size: clamp(13px, .81vw, 14px);
  color: var(--ca-dark);
  opacity: .65;
}

.ca-pricing__action { flex: none; }
.ca-pricing__btn { min-width: clamp(140px, 13.54vw, 234px); min-height: clamp(48px, 3.59vw, 62px); }

/* ═══════════════════════════════════════════════════════════════════════
   12. Memberships — dark card 821.9×548.9 over a full-bleed photo
   ═══════════════════════════════════════════════════════════════════════ */
.ca-members {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(520px, 45.8vw, 792px);
  padding-block: clamp(48px, 4vw, 70px);
  overflow: hidden;
}
.ca-members__media { position: absolute; inset: 0; z-index: 0; }
/* Figma: 1754×1169 at (-26, -164) inside 1728×792, flipped horizontally. */
.ca-members__media { --ca-crop-w: 101.505%; --ca-crop-h: 147.601%; --ca-crop-x: -1.505%; --ca-crop-y: -20.707%; }
.ca-members__media > img { transform: scaleX(-1); }

.ca-members .ca-shell {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: flex-end;
  --ca-container: 1500px;
  --ca-gutter: clamp(20px, 6.597vw, 114px);
}

.ca-members__card {
  width: min(100%, 822px);
  min-height: clamp(0px, 31.771vw, 549px);
  background: linear-gradient(167.32deg, #4E4E4E 2.38%, #2C2A2A 106.19%);
  border-radius: var(--ca-radius-card);
  color: var(--ca-white);
  padding: clamp(28px, 5.845vw, 101px) clamp(24px, 5.903vw, 102px) clamp(32px, 5.208vw, 90px);
}
.ca-members__title { color: var(--ca-white); line-height: 1.2166; } /* Figma: 72.99px on 60px */
.ca-members__body {
  margin-top: clamp(14px, 1.27vw, 22px);
  max-width: 581px;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.22;
  color: var(--ca-beige);
}

.ca-members__price {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.45vw, 25px);
  margin-top: clamp(22px, 2.66vw, 46px);
}
.ca-members__price-value {
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(30px, 2.604vw, 45px);
  line-height: 1.05;
  letter-spacing: -0.04em;
}
.ca-members__price-suffix {
  position: relative;
  padding-left: clamp(14px, 1.45vw, 25px);
  font-weight: 500;
  font-size: clamp(14px, .926vw, 16px);
  line-height: 1.2;
}
.ca-members__price-suffix::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: clamp(34px, 2.9vw, 50px);
  background: rgba(255, 255, 255, .5);
}

.ca-members__actions {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(12px, .92vw, 16px);
  margin-top: clamp(24px, 2.55vw, 44px);
}
.ca-members__actions .ca-btn { min-width: clamp(160px, 15.45vw, 267px); }

/* ═══════════════════════════════════════════════════════════════════════
   13. Reviews — cards 413.3×301, gap 24.7, section bg #F5F1EA
   ═══════════════════════════════════════════════════════════════════════ */
.ca-reviews {
  background: var(--ca-cream-alt);
  padding-block: clamp(48px, 7.75vw, 134px) clamp(48px, 10.127vw, 175px);
}

/* The enquiry confirmation page draws the same band with the palette inverted
   — white section, cream cards — per the approved design (Figma 54:139). */
.ca-reviews--alt { background: var(--ca-white); }
.ca-reviews--alt .ca-review { background: var(--ca-cream-alt); }

.ca-reviews__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 1.43vw, 25px);
  margin-top: clamp(28px, 3.3vw, 57px);
}

/* Live reviews widget. Outer positioning only: the provider builds its own
   carousel markup after load, with generated class names that change between
   releases, so nothing here targets its internals. Colours, fonts and slide
   counts belong to the provider's dashboard — the two custom properties below
   are the site tokens, which providers that read inherited values pick up. */
.ca-reviews__feed {
  margin-top: clamp(28px, 3.3vw, 57px);
  color: var(--ca-green-deep);
  font-family: var(--ca-font-review);
  --ca-widget-accent: var(--ca-green-deep);
  --ca-widget-surface: var(--ca-white);
}
.ca-reviews--alt .ca-reviews__feed { --ca-widget-surface: var(--ca-cream-alt); }

.ca-review {
  background: var(--ca-white);
  border-radius: var(--ca-radius-card);
  padding: clamp(20px, 1.56vw, 27px) clamp(18px, 1.85vw, 32px) clamp(22px, 2.43vw, 42px);
  display: flex;
  flex-direction: column;
  min-height: clamp(240px, 17.4vw, 301px);
}

.ca-review__head {
  display: flex;
  align-items: center;
  gap: clamp(10px, .8vw, 14px);
}

.ca-review__avatar {
  flex: none;
  width: clamp(52px, 4.109vw, 71px);
  height: clamp(52px, 4.109vw, 71px);
  border-radius: 50%;
  overflow: hidden;
  background: var(--ca-beige);
  display: grid;
  place-items: center;
}
.ca-review__avatar-img { width: 100%; height: 100%; object-fit: cover; }
.ca-review__initial {
  font-family: var(--ca-font-review);
  font-weight: 700;
  font-size: 22px;
  color: var(--ca-green-deep);
}

.ca-review__meta { flex: 1; min-width: 0; }
.ca-review__name {
  font-family: var(--ca-font-review);
  font-weight: 700;
  font-size: clamp(17px, 1.273vw, 22px);
  line-height: 1.3;
  color: var(--ca-green-deep);
}
.ca-review__date {
  margin-top: 2px;
  font-family: var(--ca-font-review);
  font-weight: 500;
  font-size: clamp(13px, .868vw, 15px);
  color: rgba(0, 0, 0, .5);
}

.ca-review__source { flex: none; width: 32px; height: 32px; }
.ca-review__source-custom { flex: none; width: 32px; height: 32px; }
.ca-review__source-img { width: 100%; height: 100%; object-fit: contain; }

.ca-review__stars {
  display: flex;
  gap: 3px;
  margin-top: clamp(14px, 1.4vw, 24px);
}
.ca-star { display: block; width: 22px; height: 22px; color: #E3DDCF; }
.ca-star svg { width: 100%; height: 100%; fill: currentColor; }
.ca-star.is-on { color: #FBBC05; }

.ca-review__text {
  margin-top: clamp(12px, 1.1vw, 19px);
  font-family: var(--ca-font-review);
  font-weight: 500;
  font-size: 16px;
  line-height: 22px;
  color: rgba(56, 81, 70, .6);
}

.ca-reviews__actions {
  display: flex;
  justify-content: center;
  margin-top: clamp(28px, 2.9vw, 50px);
}
.ca-reviews__actions .ca-btn { min-width: clamp(200px, 15.38vw, 266px); min-height: 55px; }

/* ═══════════════════════════════════════════════════════════════════════
   14. Book appointment
   ═══════════════════════════════════════════════════════════════════════ */
.ca-book {
  position: relative;
  isolation: isolate;
  overflow: clip;      /* the decorative icon overhangs the right edge */
  background: var(--ca-white);
  padding-block: clamp(40px, 4.340vw, 75px) clamp(40px, 3.993vw, 69px);
  /* Figma overlaps the booking panel 99px into the reviews band. */
  margin-top: clamp(-99px, -5.729vw, 0px);
}
.ca-book .ca-shell { --ca-container: 1510px; --ca-gutter: clamp(20px, 6.308vw, 109px); }
.ca-book__grid {
  display: grid;
  grid-template-columns: minmax(0, 743fr) minmax(0, 777fr);
  align-items: stretch;
}
.ca-book__panel { border-radius: var(--ca-radius-card) 0 0 var(--ca-radius-card); }
.ca-book__media { border-radius: 0 var(--ca-radius-card) var(--ca-radius-card) 0; }
/* Figma 5:851/5:853 — the 1138 × 758 photograph is offset -327 within its
   777 × 757 window, so the frame sits right of the image's centre. */
.ca-book__media {
  --ca-crop-w: 146.4608%; --ca-crop-h: 100.1321%;
  --ca-crop-x: -42.0849%; --ca-crop-y: -0.1321%;
}

/* ═══════════════════════════════════════════════════════════════════════
   15. Social — tiles 312×312, gap 20
   ═══════════════════════════════════════════════════════════════════════ */
.ca-social {
  background: var(--ca-white);
  padding-block: clamp(32px, 2.951vw, 51px) 0;
}
/* Figma: heading block ends y8135, tiles begin y8176 */
.ca-social__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: clamp(24px, 2.8935vw, 50px);
}

/* Figma 4:644 — four 41.89px circles filled #E7E0D6 with #8B8D77 glyphs,
   spaced 53.115px on centre (11.22px gap), sitting bottom-right of the
   section head. Each brand glyph keeps its own Font Awesome viewBox, so the
   optical sizes are tuned individually rather than forced onto one box. */
.ca-social__links {
  display: flex;
  align-items: center;
  gap: clamp(8px, .6493vw, 11.22px);
  flex: none;
}
.ca-social__link {
  width: clamp(36px, 2.4241vw, 41.89px);
  height: clamp(36px, 2.4241vw, 41.89px);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ca-beige);
  color: var(--ca-green);
  transition: background-color var(--ca-dur-fast) var(--ca-ease),
              color var(--ca-dur-fast) var(--ca-ease),
              transform var(--ca-dur-fast) var(--ca-ease);
}
.ca-social__link:hover {
  background: var(--ca-green);
  color: var(--ca-white);
  transform: translateY(-2px);
}
.ca-social__link:focus-visible {
  outline: 2px solid var(--ca-green);
  outline-offset: 3px;
}
.ca-social__icon { height: clamp(16px, 1.1574vw, 20px); width: auto; }
/* Optical balance — the wordless marks read heavier at the same cap height */
.ca-social__icon--facebook { height: clamp(15px, 1.0995vw, 19px); }
.ca-social__icon--x        { height: clamp(14px, 1.0417vw, 18px); }

@media (prefers-reduced-motion: reduce) {
  .ca-social__link:hover { transform: none; }
}

/* ── Third-party embeds ──────────────────────────────────────────────────
   One container for every embed field. Pasted markup arrives with its
   presentation attributes stripped (see includes/embeds.php), so sizing is
   entirely ours: the iframe fills the box, and --ca-embed-ratio sets the box
   where a fixed proportion is wanted. This is what keeps a pasted Google
   Maps "600 × 450" from imposing itself on the footer column. */
.ca-embed { position: relative; width: 100%; }

/* Sizing is applied ONLY when the caller asks for a fixed ratio (the footer
   map). A widget embed gets a plain block container and nothing else — no
   widths, no heights, no rules touching provider-generated classes — so it
   lays itself out exactly as configured in its own dashboard. */
.ca-embed[style*="--ca-embed-ratio"] { aspect-ratio: var(--ca-embed-ratio); }
.ca-embed[style*="--ca-embed-ratio"] iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* The Instagram widget takes the place of the tile grid.
   Its height is pinned to the 312px tile band from the design rather than
   left to the widget, because a feed's natural height depends on how many
   rows the provider is configured to show — and letting that drive the page
   would break both this band's proportions and its overlap onto the footer.
   Configure the feed as a single row of four in the provider's dashboard so
   it fills this box exactly. */
/* Outer positioning only. The widget's internal layout — columns, tile
   proportions, gaps — belongs to the provider's dashboard, so nothing here
   constrains its height or targets its generated markup. The negative bottom
   margin is the design's overlap onto the footer band. */
.ca-social__feed {
  max-width: 1728px;
  margin-inline: auto;
  padding-inline: clamp(20px, 12.153vw, 210px);
  position: relative;
  z-index: 2;
  margin-bottom: clamp(-149px, -8.623vw, -40px);
}

.ca-social__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.157vw, 20px);
  max-width: 1728px;
  margin-inline: auto;
  padding-inline: clamp(20px, 12.153vw, 210px);
  /* Tiles overlap the footer band, exactly as in the design */
  position: relative;
  z-index: 2;
  margin-bottom: clamp(-149px, -8.623vw, -40px);
}
.ca-social__tile {
  aspect-ratio: 1;
  border-radius: var(--ca-radius-card);
  overflow: hidden;
  background: var(--ca-beige);
}
.ca-social__tile a { display: block; height: 100%; }
.ca-social__img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--ca-dur) var(--ca-ease); }
.ca-social__tile a:hover .ca-social__img { transform: scale(1.04); }

/* ═══════════════════════════════════════════════════════════════════════
   16. Footer — sage band, gutter 110
   ═══════════════════════════════════════════════════════════════════════ */
.ca-footer {
  background: var(--ca-green);
  color: var(--ca-white);
  padding-top: clamp(96px, 14.410vw, 249px);
  padding-bottom: clamp(24px, 2.488vw, 43px);
}
.ca-footer .ca-shell {
  --ca-container: 1508px;
  --ca-gutter: clamp(20px, 6.366vw, 110px);
}

/* Figma: brand 110–568, divider x568, opening times x638.94, map x949–1619.
   Expressed as fr so the proportions hold as the shell narrows. */
.ca-footer__main {
  display: grid;
  grid-template-columns: minmax(0, 458fr) minmax(0, 239fr) minmax(0, 670fr);
  gap: clamp(24px, 4.1053vw, 71px);
  padding-bottom: clamp(32px, 3.2vw, 56px);
}

.ca-footer__logo { display: block; color: var(--ca-beige); }
.ca-footer__logo-img { width: clamp(180px, 17.78vw, 307px); height: auto; color: var(--ca-beige); }

.ca-footer__contact { margin-top: clamp(28px, 3.9vw, 68px); }
.ca-footer__label {
  font-weight: 600;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.33;
  letter-spacing: -0.01em;
  color: var(--ca-beige);
}
.ca-footer__label--spaced { margin-top: clamp(24px, 2.2vw, 38px); }
.ca-footer__sublabel {
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.33;
  letter-spacing: -0.02em;
  color: var(--ca-white);
}
.ca-footer__phone {
  margin-top: 4px;
  font-weight: 500;
  font-size: clamp(19px, 1.273vw, 22px);
  color: var(--ca-beige-2);
}
.ca-footer__phone a:hover,
.ca-footer__email a:hover { text-decoration: underline; }
.ca-footer__email { margin-top: 10px; font-size: clamp(15px, .926vw, 16px); color: var(--ca-white); }

.ca-footer__col { position: relative; }
/* The vertical rule at x568 in the design */
/* Figma Line 15 sits at x568 — the far side of the gap, not just inside it.
   NOTE the argument order: clamp(MIN, val, MAX) silently returns MIN when
   MIN > MAX, which is how the previous -24/-42 pair had this divider sitting
   46px out of place with no visible error. */
/* Height is max(design, content): the clamp reproduces Figma's rule, which sits
   slightly PAST the content, while 100% takes over once the column outgrows it.
   Without the 100% the rule stopped short as soon as the client added a fourth
   or fifth footer link — at 1280px, six links made the column 334px against a
   293px rule. The clamp alone cannot know how many links there are. */
.ca-footer__col:not(:last-child)::before {
  content: "";
  position: absolute;
  left: clamp(-71px, -4.1053vw, -24px);
  top: 0;
  width: 1px;
  height: max(clamp(240px, 22.9vw, 396px), 100%);
  background: rgba(255, 255, 255, .35);
}

.ca-footer__hours,
.ca-footer__links { margin-top: clamp(10px, .87vw, 15px); }
.ca-footer__hours li,
.ca-footer__links li {
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.333;
  letter-spacing: -0.02em;
  color: var(--ca-white);
}
.ca-footer__links li a { display: inline-block; min-height: 24px; }
.ca-footer__links li a:hover { text-decoration: underline; }

/* Figma: label ends y8607, map begins y8625 */
.ca-footer__map { margin-top: clamp(10px, .8102vw, 14px); }
.ca-footer__map-img {
  width: 100%;
  aspect-ratio: 670 / 341;
  object-fit: cover;
  border-radius: var(--ca-radius-card);
}
/* The live map embed occupies exactly the frame the screenshot did */
.ca-footer__map .ca-embed--map {
  border-radius: var(--ca-radius-card);
  overflow: hidden;
}
.ca-footer__address {
  margin-top: clamp(10px, .87vw, 15px);
  font-style: normal;
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.4;
  color: var(--ca-white);
}

.ca-footer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: clamp(20px, 2.315vw, 40px);
  border-top: 1px solid rgba(255, 255, 255, .35);
}
.ca-footer__copyright,
.ca-to-top {
  font-weight: 500;
  font-size: clamp(13px, .868vw, 15px);
  color: var(--ca-beige);
}
/* Keeps a 44px touch target without letting it set the row height — in the
   design "Return to Top" sits on the copyright's own baseline. The negative
   block margin cancels the padding's contribution to layout while the hit
   area stays full size. */
.ca-to-top {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 4px;
  margin-block: -12px;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.ca-to-top:hover { text-decoration: underline; }
.ca-to-top__icon { width: 14px; height: 14px; }

/* ═══════════════════════════════════════════════════════════════════════
   17. Confirmation page
   ═══════════════════════════════════════════════════════════════════════ */
.ca-conf {
  position: relative;
  isolation: isolate;
  min-height: clamp(560px, 56.2vw, 971px);
  display: grid;
  place-items: center;
  text-align: center;
  overflow: hidden;
  padding: clamp(120px, 9vw, 155px) var(--ca-gutter) clamp(48px, 4vw, 70px);
}
/* Figma 54:156 — same crop as the homepage hero, then four corner gradients.
   Figma composites those with multiply inside the image group; here they are
   ordinary alpha layers over the photograph, which is equivalent for black and
   avoids multiply blending a second time with whatever sits beneath. */
.ca-conf__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  --ca-crop-w: 101.099%; --ca-crop-h: 101.236%;
  --ca-crop-x: -1.100%;  --ca-crop-y: 0%;
}
.ca-conf__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(-50.009deg, rgba(0, 0, 0, 0) 56.52%, rgba(0, 0, 0, .34) 110.14%),
    linear-gradient(-55.784deg, rgba(0, 0, 0, .34) 0.683%, rgba(0, 0, 0, 0) 32.982%),
    linear-gradient(-1.310deg, rgba(0, 0, 0, 0) 75.966%, rgba(0, 0, 0, .6) 98.842%),
    linear-gradient(233.804deg, rgba(0, 0, 0, 0) 41.135%, rgba(0, 0, 0, .6) 105.53%);
}
.ca-conf__inner { position: relative; z-index: 1; max-width: 700px; }
.ca-conf__eyebrow {
  font-weight: 500;
  font-size: clamp(16px, 1.389vw, 24px);
  color: var(--ca-white);
  opacity: .9;
}
.ca-conf__title {
  margin-top: clamp(8px, .8vw, 14px);
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(34px, 4.051vw, 70px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ca-white);
  text-shadow: 0 2px 2px rgba(0, 0, 0, .1);
}
.ca-conf__text {
  margin-top: clamp(16px, 1.4vw, 24px);
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.5;
  color: var(--ca-white);
}
.ca-conf__btn { margin-top: clamp(22px, 1.9vw, 33px); min-width: min(370px, 100%); }

/* ═══════════════════════════════════════════════════════════════════════
   18. Legal page
   ═══════════════════════════════════════════════════════════════════════ */
.ca-legal {
  background: var(--ca-white);
  padding-block: clamp(140px, 14vw, 170px) clamp(56px, 6vw, 104px);
}
.ca-legal__head { padding-bottom: clamp(24px, 2.4vw, 42px); border-bottom: 1px solid rgba(var(--ca-green-rgb), .3); }
.ca-legal__title {
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(32px, 3.472vw, 60px);
  line-height: 1.1;
  letter-spacing: -0.04em;
  color: var(--ca-dark);
}
.ca-legal__intro {
  margin-top: clamp(12px, 1.16vw, 20px);
  font-size: clamp(15px, .926vw, 16px);
  line-height: 1.5;
  color: var(--ca-green);
}
.ca-legal__updated {
  margin-top: clamp(10px, .87vw, 15px);
  font-size: 15px;
  color: var(--ca-dark);
  opacity: .65;
}

.ca-legal__body { margin-top: clamp(28px, 2.9vw, 50px); font-size: clamp(15px, .926vw, 16px); line-height: 1.7; }
.ca-legal__body h2 {
  margin-top: clamp(28px, 2.9vw, 50px);
  margin-bottom: clamp(8px, .8vw, 14px);
  font-family: var(--ca-font-display);
  font-weight: 300;
  font-size: clamp(24px, 1.968vw, 34px);
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--ca-dark);
}
.ca-legal__body h3 {
  margin-top: clamp(20px, 1.9vw, 33px);
  margin-bottom: clamp(6px, .58vw, 10px);
  font-weight: 600;
  font-size: clamp(17px, 1.273vw, 22px);
  color: var(--ca-green-deep);
}
.ca-legal__body p { margin-bottom: 1em; color: var(--ca-dark); opacity: .88; }
.ca-legal__body ul,
.ca-legal__body ol { margin: 0 0 1.2em 1.4em; }
.ca-legal__body ul li { list-style: disc; margin-bottom: .5em; opacity: .88; }
.ca-legal__body ol li { list-style: decimal; margin-bottom: .5em; opacity: .88; }
.ca-legal__body a { color: var(--ca-green-deep); text-decoration: underline; }
.ca-legal__body em { font-style: italic; }
.ca-legal__body strong { font-weight: 600; }

/* Legal pages have no hero, so the header needs a solid backdrop */
/* The confirmation page keeps the transparent header over its hero photograph.
   Legal pages are deliberately NOT listed here any more: they ship locked in
   the scrolled state, and this rule out-specifies `.ca-header.is-scrolled`
   (both are two classes, so the later one won), which would have pinned them
   back to absolute and lost the sticky behaviour. */
.ca-site--confirmation .ca-header { position: absolute; }
/* Legal pages previously painted a solid green bar behind the transparent
   header, because they have no hero photograph for it to sit over. They now
   ship in the scrolled state instead (see ca_render_partial_header), so the
   frosted panel is the header on these pages and the green fill is gone. */

/* ═══════════════════════════════════════════════════════════════════════
   19. Responsive
   Breakpoints sit where the design genuinely needs to change.
   ═══════════════════════════════════════════════════════════════════════ */

/* Large desktop — cap the container, keep gutters proportional */
@media (min-width: 1729px) {
  .ca-site { --ca-gutter: calc((100vw - var(--ca-container)) / 2); }
  .ca-hero__inner { padding-left: calc((100vw - 1728px) / 2 + 102px); }
}

/* Laptop — the intro card stops overlapping so far */
@media (max-width: 1280px) {
  .ca-intro__top { grid-template-columns: minmax(0, 1fr) minmax(0, 46vw); }
  .ca-intro__card { margin-top: 22vw; }
  .ca-book__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* Tablet landscape — hero form drops below the copy */
@media (max-width: 1100px) {
  .ca-hero {
    min-height: 0;
    padding-top: clamp(110px, 16vw, 150px);
    padding-bottom: 48px;
  }
  .ca-hero__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
    padding-top: 0;
    padding-inline: var(--ca-gutter);
  }
  .ca-hero__panel { max-width: 620px; }

  /* Intro card stacks under the video instead of overlapping it */
  .ca-intro__top { display: block; }
  .ca-intro__video { width: 100%; }
  .ca-intro__card {
    margin: -40px var(--ca-gutter) 0;
    margin-inline: var(--ca-gutter);
  }
  .ca-intro__bottom { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .ca-intro__action { padding-bottom: 0; }

  .ca-members .ca-shell { justify-content: center; }
  .ca-members__card { width: 100%; }
}

/* Tablet portrait — 2-up reviews, footer reflow */
@media (max-width: 1024px) {
  .ca-reviews__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-footer__main { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ca-footer__col--map { grid-column: 1 / -1; }
  .ca-footer__col:not(:last-child)::before { display: none; }
  .ca-social__grid { margin-bottom: clamp(-60px, -4vw, -32px); }
}

/* Mobile navigation threshold. The desktop header needs ~1585px for the logo,
   five nav items, the phone block and the CTA; below 1100px it no longer fits,
   so the drawer takes over there rather than at a nominal 900px. */
@media (max-width: 1100px) {
  .ca-nav,
  .ca-header__phone,
  .ca-header__cta { display: none; }
  .ca-burger { display: flex; }
  .ca-header__inner { justify-content: space-between; }
  .ca-header__aside { margin-left: auto; }

  .ca-book .ca-shell { --ca-gutter: 2.367vw; max-width: none; }       /* x20 */
  /* The desktop placement pushes the icon off the right edge; centring it
     keeps it readable as a decorative mark at this width. */
  .ca-book__watermark {
    left: 50%;
    translate: -50% 0;
    top: 26%;
    width: 132%;
  }
  .ca-book__grid { grid-template-columns: minmax(0, 1fr); }
  .ca-book__panel { border-radius: var(--ca-radius-card) var(--ca-radius-card) 0 0; }
  .ca-book__media { border-radius: 0 0 var(--ca-radius-card) var(--ca-radius-card); aspect-ratio: 16 / 10; }

  .ca-pricing__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name action" "value action";
    align-items: center;
    gap: 6px 16px;
    padding-block: 18px;
  }
  .ca-pricing__name { grid-area: name; }
  .ca-pricing__value { grid-area: value; padding-left: 0; }
  .ca-pricing__value::before { display: none; }
  .ca-pricing__action { grid-area: action; }
}

/* Tablet / large mobile */
@media (max-width: 820px) {
  .ca-services__head,
  .ca-social__head { flex-direction: column; align-items: flex-start; gap: 20px; }
  .ca-service.is-offset { margin-top: 0; }
  .ca-social__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Mobile */
@media (max-width: 640px) {
  .ca-reviews__grid { grid-template-columns: minmax(0, 1fr); }

  /* ── Footer, centred ──────────────────────────────────────────────
     Centred as a layout, not merely by inheriting text-align: the
     columns become centred flex stacks, list markers and their padding
     are removed, and each row's own items are centred too. */
  .ca-footer__main {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
    gap: 40px;
  }
  .ca-footer__brand,
  .ca-footer__col {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
  }
  .ca-footer__logo { display: flex; justify-content: center; }
  .ca-footer__hours,
  .ca-footer__links {
    list-style: none;
    padding-left: 0;
    margin-left: 0;
    width: 100%;
  }
  .ca-footer__hours li,
  .ca-footer__links li {
    display: flex;
    justify-content: center;
    gap: 6px;
  }
  .ca-footer__address { font-style: normal; }
  /* The map keeps the container's padding but fills the width it is given */
  .ca-footer__col--map { width: 100%; }
  .ca-footer__map { width: 100%; }
  .ca-footer__bar {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 12px;
  }
  .ca-to-top { justify-content: center; }

  /* Name across the top, then price and button side by side beneath it.
     A long service name wraps in its own row, so it can never collide with
     the price or the button. */
  .ca-pricing__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "name  name"
      "value action";
    align-items: center;
    gap: 10px 16px;
    padding-block: 18px;
  }
  .ca-pricing__name   { grid-area: name; text-align: left; }
  .ca-pricing__value  { grid-area: value; text-align: left; padding-left: 0; }
  .ca-pricing__action { grid-area: action; justify-self: end; }
  .ca-pricing__btn    { width: auto; }

  .ca-members__actions { flex-direction: column; }
  .ca-members__actions .ca-btn { width: 100%; }

  .ca-hero__btn,
  .ca-conf__btn { width: 100%; }

  .ca-intro__card { margin-inline: var(--ca-gutter); }
}

/* ═══════════════════════════════════════════════════════════════════════
   19b. Mobile layout — from the approved "Home-Mobile" Figma frame (56:7)
   ═══════════════════════════════════════════════════════════════════════
   The mobile frame is 845 wide, so every dimension below is expressed as
   Npx / 8.45 = Nvw and resolves to the exact Figma value at 845px. Body copy
   is the exception: it stays at the 15–16px reading size set in §3 rather
   than scaling, because the frame keeps desktop type sizes on a narrower
   canvas and scaling them proportionally would leave paragraphs at ~8px on a
   390px phone.

   Section order and stacking follow the frame, which differs from desktop in
   three ways: the hero's booking form becomes its own band, the Book
   Appointment photograph moves above its form, and the services cards stop
   alternating.

   The frame does not include a header, the Instagram band or the footer —
   those keep the responsive treatment derived from the desktop design. */
@media (max-width: 900px) {

  /* Display type keeps the frame's sizes (60px headings, 24px eyebrows) —
     only body copy is held at its reading size. */
  .ca-display { font-size: clamp(28px, 7.101vw, 60px); }
  .ca-eyebrow { font-size: clamp(15px, 2.840vw, 24px); }

  /* ── Image crops, taken from the mobile frame ──────────────────────
     The frame re-crops every photograph for the narrower canvas, so these
     override the desktop values rather than inheriting them. */
  .ca-hero__media {
    --ca-crop-w: 237.988%; --ca-crop-h: 128.636%;
    --ca-crop-x: -18.935%; --ca-crop-y: -16.591%;
  }
  .ca-video--intro .ca-video__cover {
    --ca-crop-w: 116.828%; --ca-crop-h: 349.528%;
    --ca-crop-x:  -6.130%; --ca-crop-y: -126.770%;
  }
  .ca-video--row .ca-video__cover {
    --ca-crop-w: 172.142%; --ca-crop-h: 199.158%;
    --ca-crop-x: -48.402%; --ca-crop-y: -20.082%;
  }
  .ca-book__media {
    --ca-crop-w: 157.400%; --ca-crop-h: 241.086%;
    --ca-crop-x: -53.147%; --ca-crop-y: -21.314%;
  }
  /* The frame uses a different (though near-identical) photograph here, so
     its pixel crop does not transfer — applying it misframes the approved
     image. Plain centred cover matches the frame's composition most closely
     and stays correct if the client swaps the photograph. */
  .ca-members__media {
    --ca-crop-w: 100%; --ca-crop-h: 100%;
    --ca-crop-x: 0%;   --ca-crop-y: 0%;
  }

  /* ── Hero: photograph band only; the form is a separate band below ─── */
  .ca-hero {
    background: var(--ca-cream);
    min-height: 0;
    padding: 0;
  }
  .ca-hero__media {
    position: absolute;
    inset: 0 0 auto 0;
    height: 104.142vw;             /* 880 */
  }
  .ca-hero__inner {
    display: block;
    padding: 0;
    gap: 0;
  }
  .ca-hero__content {
    box-sizing: border-box;
    min-height: 104.142vw;         /* the photograph band */
    padding-top: 55.976vw;         /* heading at y473 */
    padding-inline: 11.834vw;      /* x100 */
  }
  .ca-hero__title { font-size: clamp(30px, 7.101vw, 60px); }        /* 60 */
  .ca-hero__text  { margin-top: 5.444vw; max-width: 61.183vw; }     /* y639, w517 */
  .ca-hero__btn {
    margin-top: 5.089vw;                                            /* y727 */
    width: min(100%, 43.787vw);                                     /* 370 */
    min-height: 7.337vw;                                            /* 62 */
  }

  /* ── Booking form: its own full-bleed band (Figma y880–1571) ───────── */
  .ca-hero__panel {
    max-width: none;
    margin: 0;
    border-radius: 0;
    padding: 8.284vw;                    /* uniform, as on desktop (70 at the 845 frame) */
  }
  .ca-form-panel__title { font-size: clamp(26px, 4.734vw, 40px); }

  /* ── Intro ─────────────────────────────────────────────────────────── */
  .ca-intro { padding-bottom: 9.704vw; }                     /* band ends y3197 */
  .ca-intro__top { display: block; padding-top: 0; }
  .ca-intro__video { width: 100%; }
  .ca-intro__video .ca-video { aspect-ratio: 845 / 424; }            /* y1571–1995 */
  /* Centred on mobile, unlike the desktop's lower-left placement */
  .ca-video--intro .ca-video__toggle {
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
  .ca-video--intro .ca-video__toggle:hover  { transform: translate(-50%, -50%) scale(1.04); }
  .ca-video--intro .ca-video__toggle:active { transform: translate(-50%, -50%) scale(.97); }

  .ca-intro__card {
    margin: 2.367vw 1.657vw 0;      /* card x14, 20px below the video */
    min-height: 0;
    padding: 5.917vw 8.284vw 5.917vw;
  }
  .ca-intro__card-title {
    font-size: clamp(30px, 8.740vw, 74px);                           /* 73.85 */
    margin-top: 2.367vw;                                             /* y2109 */
  }
  .ca-intro__card-lead { margin-top: 1.775vw; }                      /* y2203 */
  .ca-intro__card-body { margin-top: 6.036vw; }                      /* y2291 */
  .ca-intro__card-eyebrow { font-size: clamp(15px, 2.367vw, 20px); }

  /* Figma puts "Book Today" inside the dark card (y2554, card ends y2666).
     The DOM order is card → copy → action, so the action is reordered ahead of
     the copy and pulled up onto reserved space at the foot of the card. */
  .ca-intro__card { padding-bottom: 24.852vw; }              /* card ends y2666 */
  .ca-intro__bottom {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    padding-top: 0;
    margin-top: 0;
  }
  .ca-intro__copy { max-width: none; padding-top: 7.337vw; }         /* heading y2728 */
  /* The stored heading carries a hard break that reads correctly on desktop
     but leaves a stranded fourth line here. The frame wraps it naturally, so
     the break is ignored at this width. */
  .ca-intro__copy .ca-display br { display: none; }
  .ca-intro__action {
    order: -1;
    margin-top: -13.254vw;                                           /* onto the card, y2554 */
    margin-inline: -2.556vw;                                         /* button x84 */
    padding-right: 1.775vw;                                          /* button w661.8 */
  }
  .ca-intro__action .ca-btn { width: 100%; min-height: 7.337vw; }

  /* ── Services: two cards across, no alternation on mobile ──────────── */
  .ca-services { padding-block: 6.982vw 8.284vw; --ca-gutter: 7.692vw; }   /* x65; bottom reduced with the desktop rule */
  /* The frame keeps the arrows beside the heading, with the heading itself
     capped at 343 so it breaks over three lines (Figma 56:80 / 56:82). */
  .ca-services__head {
    flex-direction: row;
    align-items: flex-end;
    gap: 2.367vw;
    margin-bottom: 4.379vw;          /* heading block → cards y3524 */
  }
  .ca-services__head .ca-display { max-width: 40.592vw; }   /* 343 */
  .ca-services .ca-carousel__controls { margin-bottom: 2.604vw; }
  .ca-service__label { min-width: 73.2%; }                  /* 311.7 of 425.8 */
  .ca-services__track { grid-auto-columns: 50.391vw; }               /* 425.8 */
  .ca-service.is-offset { margin-top: 0; }
  .ca-service.is-offset .ca-service__desc {
    order: 0;
    margin-top: clamp(12px, 2.367vw, 20px);
    margin-bottom: 0;
  }
  .ca-service__desc { margin-top: clamp(12px, 2.367vw, 20px); }
  .ca-service__label { font-size: clamp(15px, 2.604vw, 22px); }

  /* ── Video row ─────────────────────────────────────────────────────── */
  .ca-videorow .ca-video { aspect-ratio: 845 / 487; }
  .ca-videorow__logo { width: 32vw; right: 4.7vw; bottom: 4.7vw; }

  /* ── Price list ────────────────────────────────────────────────────── */
  .ca-pricing { padding-block: 11.361vw 10.651vw; --ca-gutter: 7.692vw; }  /* x65 */
  .ca-pricing .ca-section-head { margin-bottom: 7.456vw; }                 /* heading → first row y4935 */
  .ca-pricing__list { display: flex; flex-direction: column; gap: 4.379vw; }  /* 158 pitch */
  .ca-pricing__row { padding-block: 0; min-height: 14.320vw; }               /* 121 */

  /* ── Memberships: photograph above, card below, both full-bleed ────── */
  .ca-members { display: block; padding: 0; }
  .ca-members__media {
    position: relative;
    inset: auto;
    width: 100%;
    height: 59.645vw;               /* 504 */
  }
  .ca-members .ca-shell { padding: 0; max-width: none; }
  .ca-members__card {
    width: 100%;
    max-width: none;
    border-radius: 0;
    padding: 9.467vw 8.284vw 17.751vw;   /* card band 549 tall */
  }
  .ca-members__actions .ca-btn { min-width: 25.207vw; }   /* 213 */

  /* ── Reviews: a peeking carousel rather than a grid ─────────────────── */
  .ca-reviews__grid {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 48.911vw;    /* 413.3 */
    grid-template-columns: none;
    gap: 2.959vw;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-inline: var(--ca-gutter);
    margin-inline: calc(var(--ca-gutter) * -1);
  }
  .ca-reviews__grid::-webkit-scrollbar { display: none; }
  .ca-reviews__grid > * { scroll-snap-align: center; }
  .ca-review { min-height: 35.621vw; }        /* 301 */
  /* Figma band 6642–7527: eyebrow +96, heading +135, cards +240, CTA +594 */
  .ca-reviews { padding-block: 11.361vw 12.899vw; }
  .ca-reviews .ca-section-head { margin-bottom: 5.325vw; }
  .ca-reviews__actions { margin-top: 6.272vw; }

  /* ── Book appointment: photograph above the form ───────────────────── */
  .ca-book__grid { grid-template-columns: minmax(0, 1fr); }
  .ca-book__media {
    order: -1;
    aspect-ratio: auto;             /* the ≤1100 rule's 16/10 would fight the height */
    height: 41.420vw;               /* 350 */
    border-radius: var(--ca-radius-card) var(--ca-radius-card) 0 0;
  }
  .ca-book__panel {
    border-radius: 0 0 var(--ca-radius-card) var(--ca-radius-card);
    padding: 5.917vw;                    /* uniform */
  }
}

/* Small mobile */
/* Drawer: 80% on tablet, full width on phones */
@media (max-width: 1100px) { .ca-mobile__panel { width: 80%; } }
@media (max-width: 640px)  { .ca-mobile__panel { width: 100%; } }

@media (max-width: 480px) {
  .ca-services__track { grid-auto-columns: 78vw; }
  .ca-social__grid { gap: 8px; }
  .ca-video__toggle { width: 84px; height: 84px; }
}

@media (max-width: 380px) {
  .ca-logo__img { width: 170px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   20. Reduced motion
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .ca-site *,
  .ca-site *::before,
  .ca-site *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .ca-services__track { scroll-behavior: auto; }
  /* The video still works — it simply stays paused until the visitor acts. */
  .ca-video__cover { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Document shell — builder pages are served by the plugin's own template,
   so these are the only global rules the page needs.
   ═══════════════════════════════════════════════════════════════════════ */
body.ca-body {
  margin: 0;
  padding: 0;
  background: var(--ca-cream, #FFFBF5);
  overflow-x: hidden;
}

.ca-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  padding: 12px 20px;
  background: #385146;
  color: #fff;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: 15px;
  border-radius: 0 0 4px 0;
}
.ca-skip:focus { left: 0; }

/* WordPress admin bar offset for logged-in editors */
body.ca-body.admin-bar .ca-header { top: 32px; }
@media (max-width: 782px) {
  body.ca-body.admin-bar .ca-header { top: 46px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   21. Entrance animations
   ═══════════════════════════════════════════════════════════════════════
   A very small fade-and-lift as elements enter the viewport, once each.

   The hidden state is scoped to `html.ca-anim`, a class set by a tiny inline
   script in the document head (see ca_render_head). That ordering matters:
   the rule is live before the elements paint, so nothing flashes in and then
   hides. With JavaScript disabled the class never appears and every element
   renders normally; if frontend.js fails to load, a timeout in that same
   inline script removes the class so the content still appears.

   The selector list below is mirrored in frontend.js — keep them in step.
   The Intro card and the Video Row logo are deliberately absent: both carry
   their own opacity transition tied to video playback. */
html.ca-anim :is(
  .ca-service,
  .ca-review,
  .ca-pricing__row,
  .ca-social__tile,
  .ca-section-head,
  .ca-hero__content,
  .ca-hero__panel,
  .ca-intro__copy,
  .ca-intro__action,
  .ca-members__card,
  .ca-book__panel,
  .ca-book__media,
  .ca-footer__brand,
  .ca-footer__col,
  .ca-conf__inner
) {
  opacity: 0;
  transform: translateY(10px);
  will-change: opacity, transform;
}

html.ca-anim .is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity .55s var(--ca-ease), transform .55s var(--ca-ease);
  transition-delay: var(--ca-reveal-delay, 0ms);
  will-change: auto;
}

/* Reduced motion: everything is simply present. */
@media (prefers-reduced-motion: reduce) {
  html.ca-anim :is(
    .ca-service, .ca-review, .ca-pricing__row, .ca-social__tile,
    .ca-section-head, .ca-hero__content, .ca-hero__panel, .ca-intro__copy,
    .ca-intro__action, .ca-members__card, .ca-book__panel, .ca-book__media,
    .ca-footer__brand, .ca-footer__col, .ca-conf__inner
  ),
  html.ca-anim .is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }
}