/* Generated by build.js — do not edit by hand.
   Edit the sources in css/ (variables.css, reset.css, style.css, responsive.css) and re-run the build.
   Concatenation order is the cascade: changing it changes the design. */

/* ---- variables.css ------------------------------------------------- */
/* ==========================================================================
   VARIABLES.CSS — Rikki Malherbe Physiotherapy
   Design tokens. Colours are sampled directly from the practice logo.
   ========================================================================== */

/* ---- Typeface ------------------------------------------------------------
   General Sans, self-hosted. No third-party font request anywhere on the
   site: Google Fonts is a render-blocking round trip to another origin, and
   this build is held to a Lighthouse score. One family, five weights,
   differentiated by weight, size and tracking rather than by mixing faces. */

@font-face {
  font-family: 'General Sans';
  src: url('/assets/fonts/general-sans/GeneralSans-Light.woff2') format('woff2'),
       url('/assets/fonts/general-sans/GeneralSans-Light.woff') format('woff');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'General Sans';
  src: url('/assets/fonts/general-sans/GeneralSans-Regular.woff2') format('woff2'),
       url('/assets/fonts/general-sans/GeneralSans-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'General Sans';
  src: url('/assets/fonts/general-sans/GeneralSans-Medium.woff2') format('woff2'),
       url('/assets/fonts/general-sans/GeneralSans-Medium.woff') format('woff');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'General Sans';
  src: url('/assets/fonts/general-sans/GeneralSans-Semibold.woff2') format('woff2'),
       url('/assets/fonts/general-sans/GeneralSans-Semibold.woff') format('woff');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'General Sans';
  src: url('/assets/fonts/general-sans/GeneralSans-Bold.woff2') format('woff2'),
       url('/assets/fonts/general-sans/GeneralSans-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {

  /* ---- Brand -------------------------------------------------------------
     Sampled from rikki-logo.jpeg: the teal of the vertebral dots, and the
     charcoal of the wordmark. Everything else is derived from these two. */
  --c-accent:        #1CABB1;
  --c-ink:           #191919;

  /* Teal scale */
  --c-accent-hover:  #189AA0;   /* booking button hover; 5.1:1 against ink */
  --c-accent-deep:   #15898E;   /* hover / pressed on ghost controls */
  --c-accent-dark:   #0E6165;   /* text on pale teal, meets AA on --c-wash */
  --c-accent-mid:    #8FD9DC;   /* rules, dividers on dark */
  --c-wash:          #EDF8F8;   /* palest tint, section grounds */

  /* Ink scale */
  --c-body:          #2B3132;   /* body copy — softer than pure logo charcoal */
  --c-muted:         #5E6768;   /* secondary copy; 5.6:1 on white */
  /* Captions, meta and hints. Kept as dark as it is because #8B9394 measured
     3.1:1 on white and failed AA everywhere it appeared, not only in the one
     caption Lighthouse happened to sample. This is 5.2:1 on white and 4.8:1
     on the teal wash. */
  --c-faint:         #666E6F;
  --c-line:          rgba(25, 25, 25, 0.11);
  --c-line-strong:   rgba(25, 25, 25, 0.2);

  /* Surfaces */
  --c-bg:            #FFFFFF;
  --c-bg-alt:        #F6F9F9;   /* faint teal-cast grey, never a flat neutral */
  --c-deep:          #14191A;   /* dark bands — charcoal with a teal undertone */
  --c-deep-teal:     #0B3A3D;   /* the CTA ground; unmistakably brand */

  /* On dark */
  --c-on-deep:       #F4F8F8;
  --c-on-deep-muted: rgba(244, 248, 248, 0.66);
  --c-line-on-deep:  rgba(244, 248, 248, 0.16);

  /* Semantic */
  --c-focus:         #1CABB1;

  /* ---- Type --------------------------------------------------------- */
  --font: 'General Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
          Helvetica, Arial, sans-serif;

  --fs-display: clamp(2.75rem, 6.2vw + 0.4rem, 5.75rem);
  --fs-h1:      clamp(2.35rem, 4.4vw + 0.6rem, 4rem);
  --fs-h2:      clamp(1.95rem, 2.6vw + 0.8rem, 3rem);
  --fs-h3:      clamp(1.35rem, 1vw + 0.95rem, 1.75rem);
  --fs-h4:      clamp(1.1rem, 0.4vw + 0.95rem, 1.25rem);
  --fs-lead:    clamp(1.08rem, 0.5vw + 0.95rem, 1.3rem);
  --fs-body:    1.0625rem;
  --fs-sm:      0.9375rem;
  --fs-xs:      0.8125rem;
  --fs-label:   0.75rem;

  --lh-tight:   1.04;
  --lh-snug:    1.18;
  --lh-body:    1.65;

  --tr-display: -0.032em;   /* the logo wordmark is tightly set; headings echo it */
  --tr-head:    -0.022em;
  --tr-label:    0.16em;

  /* ---- Space — 8px rhythm ------------------------------------------- */
  --s-1:  0.25rem;
  --s-2:  0.5rem;
  --s-3:  0.75rem;
  --s-4:  1rem;
  --s-5:  1.5rem;
  --s-6:  2rem;
  --s-7:  2.75rem;
  --s-8:  4rem;
  --s-9:  6rem;
  --s-10: 8.5rem;

  --section-y:  clamp(4rem, 8vw, 7.5rem);
  --section-y-lg: clamp(5.5rem, 11vw, 10rem);

  /* ---- Layout -------------------------------------------------------- */
  --wrap:        1280px;
  --wrap-wide:   1480px;
  --wrap-narrow: 720px;
  --gutter:      clamp(1.25rem, 4.5vw, 3.5rem);
  --header-h:    84px;
  --header-h-sm: 68px;
  --sticky-cta-h: 68px;      /* mobile booking bar; body gets matching padding */

  /* ---- Radii ---------------------------------------------------------
     Deliberately not uniform. Buttons stay tight and purposeful; media gets
     a generous curve so photography reads soft rather than punched-out. */
  --r-xs:  4px;
  --r-sm:  8px;
  --r-md:  16px;
  --r-lg:  28px;
  --r-xl:  40px;
  --r-pill: 999px;

  /* ---- Motion --------------------------------------------------------- */
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast:    200ms;
  --t-base:    420ms;
  --t-slow:    820ms;

  /* ---- Elevation ------------------------------------------------------
     Shadows are tinted with the brand teal rather than neutral black, so
     depth reads as part of the palette instead of grey haze. */
  --sh-sm: 0 1px 2px rgba(11, 58, 61, 0.06);
  --sh-md: 0 14px 34px -20px rgba(11, 58, 61, 0.28);
  --sh-lg: 0 34px 70px -32px rgba(11, 58, 61, 0.32);

  --z-header: 100;
  --z-mobile-nav: 105;
  --z-sticky-cta: 96;
}

/* ---- reset.css ----------------------------------------------------- */
/* ==========================================================================
   RESET.CSS
   Minimal modern reset. Typefaces and tokens are declared in variables.css,
   which loads first.
   ========================================================================== */

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

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  background: none;
  border: none;
}

a {
  color: inherit;
  text-decoration: none;
}

/* Component classes set display, which would otherwise beat the UA rule for
   [hidden] and leave hidden elements visible. */
[hidden] {
  display: none !important;
}

ul,
ol {
  list-style: none;
}

h1, h2, h3, h4, h5, h6 {
  font-weight: inherit;
  overflow-wrap: break-word;
}

p {
  overflow-wrap: break-word;
}

table {
  border-collapse: collapse;
}

:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 3px;
}

/* ---- style.css ----------------------------------------------------- */
/* ==========================================================================
   STYLE.CSS — Rikki Malherbe Physiotherapy

   Design notes for whoever maintains this:

   The practice logo is a run of graduated dots tracing a vertebral curve, set
   over an offset broken circle. That motif is the whole design language. It
   appears as the scroll rail (3), the eyebrow marker, the list bullet, the
   scroll cue, and the focal dot inside every service icon. Nothing here uses
   a stock icon set, a dingbat glyph or an emoji.

   The page is predominantly white. Deep teal is spent in exactly one place —
   the booking band — so it stays the loudest thing on any page.

   1.  Base + typography       10. Split / about
   2.  Layout                  11. Reviews
   3.  Spine rail (signature)  12. Areas served
   4.  Buttons + booking       13. CTA band
   5.  Header + navigation     14. Footer
   6.  Sticky mobile CTA       15. Forms
   7.  Hero                    16. FAQ
   8.  Sections                17. Utilities + motion
   9.  Service tiles
   ========================================================================== */

/* ---------- 1. Base + typography ----------------------------------------- */

html { scroll-behavior: smooth; }

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

body {
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
  color: var(--c-body);
  background-color: var(--c-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font);
  color: var(--c-ink);
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-head);
  font-weight: 600;
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
  font-weight: 700;
  letter-spacing: var(--tr-display);
  line-height: var(--lh-tight);
}

h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-h4); }

p { text-wrap: pretty; }

a { color: inherit; transition: color var(--t-fast) var(--ease); }

strong { font-weight: 600; color: var(--c-ink); }

::selection { background: var(--c-accent); color: #fff; }

:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--c-deep-teal);
  color: #fff;
  padding: var(--s-3) var(--s-5);
  border-radius: 0 0 var(--r-sm) 0;
  font-weight: 500;
}

.skip-link:focus { left: 0; }

/* Lede — light weight at scale. The tension between a 700 display and a 300
   lede is where this build gets its voice, using a single family. */
.lede {
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.5;
  color: var(--c-muted);
  max-width: 46ch;
}

/* Eyebrow — marked with a dot, never a dash. The dot is the logo. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-accent-dark);
  margin-bottom: var(--s-4);
}

.eyebrow::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-accent);
  flex-shrink: 0;
}

.on-deep .eyebrow { color: var(--c-accent-mid); }

/* ---------- 2. Layout ----------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap-wide { max-width: var(--wrap-wide); }
.wrap-narrow { max-width: var(--wrap-narrow); }

main { overflow-x: clip; }

/* ---------- 3. Spine rail — the signature -------------------------------- */
/* A vertical rail down the left edge carrying one dot per page section. The
   dot for the section in view fills teal and grows, the way the largest dot
   in the logo sits at the apex of the curve. It is the brand mark doing an
   actual job: telling you where you are, and jumping you there. */

.spine {
  position: fixed;
  left: max(1.25rem, calc((100vw - var(--wrap)) / 2 - 3rem));
  top: 50%;
  transform: translateY(-50%);
  z-index: 90;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-base) var(--ease), visibility var(--t-base);
}

.spine.is-ready { opacity: 1; visibility: visible; }

.spine::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(180deg, transparent, var(--c-line-strong) 12%, var(--c-line-strong) 88%, transparent);
}

.spine-dot {
  position: relative;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.spine-dot::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-line-strong);
  transition: width var(--t-base) var(--ease-out),
              height var(--t-base) var(--ease-out),
              background-color var(--t-base) var(--ease);
}

.spine-dot:hover::after { background: var(--c-accent-deep); }

.spine-dot.is-active::after {
  width: 13px;
  height: 13px;
  background: var(--c-accent);
}

.spine-label {
  position: absolute;
  left: calc(100% + 10px);
  white-space: nowrap;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--c-ink);
  background: var(--c-bg);
  border: 1px solid var(--c-line);
  border-radius: var(--r-pill);
  padding: 3px 11px;
  opacity: 0;
  transform: translateX(-4px);
  pointer-events: none;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
  box-shadow: var(--sh-sm);
}

.spine-dot:hover .spine-label,
.spine-dot:focus-visible .spine-label { opacity: 1; transform: none; }

.spine.on-dark::before {
  background: linear-gradient(180deg, transparent, var(--c-line-on-deep) 12%, var(--c-line-on-deep) 88%, transparent);
}

.spine.on-dark .spine-dot::after { background: rgba(244, 248, 248, 0.35); }
.spine.on-dark .spine-dot.is-active::after { background: var(--c-accent-mid); }

@media (min-width: 1200px) {
  .spine { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  .spine-dot::after, .spine-label { transition: none; }
}

/* ---------- 4. Buttons + booking ----------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1;
  padding: 1.05rem 1.7rem;
  border-radius: var(--r-sm);
  border: 1.5px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}

.btn .icon { width: 18px; height: 18px; flex-shrink: 0; }

.btn:active { transform: translateY(1px); }

/* The booking button. The most important control on the site, and the only
   one carrying weight and lift, so nothing competes with it.

   Charcoal on teal, not white on teal: white on #1CABB1 measures 2.8:1 and
   fails WCAG AA outright. Charcoal reaches 6.2:1, keeps the bright brand teal
   as the loudest thing on the page rather than darkening it into compliance,
   and pairs the two logo colours exactly as the logo does. */
.btn-book {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-ink);
  box-shadow: var(--sh-md);
}

.btn-book:hover {
  background: var(--c-accent-hover);
  border-color: var(--c-accent-hover);
  box-shadow: var(--sh-lg);
}

.btn-ghost {
  background: transparent;
  border-color: var(--c-line-strong);
  color: var(--c-ink);
}

.btn-ghost:hover { border-color: var(--c-ink); background: rgba(25, 25, 25, 0.03); }

.btn-ghost-light {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.34);
  color: #fff;
}

.btn-ghost-light:hover { border-color: #fff; background: rgba(255, 255, 255, 0.1); }

.btn-solid-light {
  background: #fff;
  border-color: #fff;
  color: var(--c-deep-teal);
}

.btn-solid-light:hover { background: var(--c-wash); border-color: var(--c-wash); }

.btn-sm { padding: 0.7rem 1.15rem; font-size: var(--fs-xs); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--c-accent-dark);
}

.link-arrow .icon { width: 17px; height: 17px; transition: transform var(--t-fast) var(--ease); }
.link-arrow:hover .icon { transform: translateX(4px); }

.btn-group { display: flex; flex-wrap: wrap; gap: var(--s-3); }

/* ---------- 5. Header + navigation --------------------------------------- */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--t-base) var(--ease),
              border-color var(--t-base) var(--ease),
              height var(--t-base) var(--ease);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  max-width: var(--wrap-wide);
}

.site-header.is-solid,
.site-header.is-scrolled {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--c-line);
  height: var(--header-h-sm);
}

.brand { display: flex; align-items: center; flex-shrink: 0; }

.brand svg { height: 44px; width: auto; display: block; transition: height var(--t-base) var(--ease); }

.site-header.is-scrolled .brand svg,
.site-header.is-solid .brand svg { height: 38px; }

/* Over the hero video the mark is knocked out to white. */
.brand .mark-ring { stroke: var(--c-ink); }
.brand .mark-arc { stroke: var(--c-accent); }
.brand .mark-dot { fill: var(--c-accent); }
.brand .mark-word { fill: var(--c-ink); }
.brand .mark-rule { stroke: var(--c-ink); }

.site-header:not(.is-solid):not(.is-scrolled) .brand .mark-ring,
.site-header:not(.is-solid):not(.is-scrolled) .brand .mark-rule { stroke: rgba(255, 255, 255, 0.85); }

.site-header:not(.is-solid):not(.is-scrolled) .brand .mark-word { fill: #fff; }

.main-nav { display: flex; align-items: center; gap: clamp(1rem, 2vw, 2rem); }

.nav-list { display: flex; align-items: center; gap: clamp(0.85rem, 1.4vw, 1.55rem); }

.nav-list > li { position: relative; }

.nav-list a,
.nav-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: #fff;
  background: none;
  border: 0;
  padding: 6px 0;
  cursor: pointer;
  font-family: var(--font);
}

.nav-trigger .icon { width: 15px; height: 15px; transition: transform var(--t-fast) var(--ease); }
.nav-list li:hover .nav-trigger .icon { transform: rotate(180deg); }

.site-header.is-solid .nav-list a,
.site-header.is-scrolled .nav-list a,
.site-header.is-solid .nav-trigger,
.site-header.is-scrolled .nav-trigger { color: var(--c-body); }

.nav-list a:hover,
.nav-trigger:hover { color: var(--c-accent); }

/* Current page marked with the logo dot, not an underline. */
.nav-list > li > a[aria-current="page"] { color: var(--c-accent); font-weight: 600; }

.nav-list > li > a[aria-current="page"]::after {
  content: "";
  position: absolute;
  bottom: -3px;
  left: 50%;
  transform: translateX(-50%);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--c-accent);
}

.nav-menu {
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 296px;
  background: var(--c-bg);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  box-shadow: var(--sh-lg);
  padding: var(--s-2);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease), visibility var(--t-fast);
}

.nav-list li:hover .nav-menu,
.nav-list li:focus-within .nav-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.nav-menu a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: 0.62rem 0.7rem;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--c-body);
}

.nav-menu a:hover { background: var(--c-wash); color: var(--c-accent-dark); }
.nav-menu a[aria-current="page"] { color: var(--c-accent-dark); background: var(--c-wash); }
.nav-menu .icon { width: 22px; height: 22px; color: var(--c-ink); flex-shrink: 0; }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  background: none;
  border: 0;
  cursor: pointer;
  color: #fff;
  z-index: 110;
}

.site-header.is-solid .nav-toggle,
.site-header.is-scrolled .nav-toggle { color: var(--c-ink); }

.nav-toggle .icon { width: 26px; height: 26px; }
.nav-toggle .icon-close { display: none; }
.nav-toggle[aria-expanded="true"] { color: var(--c-ink); }
.nav-toggle[aria-expanded="true"] .icon-open { display: none; }
.nav-toggle[aria-expanded="true"] .icon-close { display: block; }

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: var(--z-mobile-nav);
  background: var(--c-bg);
  padding: calc(var(--header-h-sm) + var(--s-5)) var(--gutter) var(--s-8);
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity var(--t-base) var(--ease), transform var(--t-base) var(--ease), visibility var(--t-base);
}

.mobile-nav.is-open { opacity: 1; visibility: visible; transform: none; }

.mobile-nav-list { display: flex; flex-direction: column; }

.mobile-nav-list > li + li { border-top: 1px solid var(--c-line); }

.mobile-nav-list > li > a {
  display: block;
  padding: var(--s-4) 0;
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: var(--tr-head);
  color: var(--c-ink);
}

.mobile-nav-list > li > a[aria-current="page"] { color: var(--c-accent); }

.mobile-sub {
  display: flex;
  flex-direction: column;
  padding: 0 0 var(--s-4) var(--s-4);
  border-left: 1px solid var(--c-line);
  margin-left: 3px;
}

.mobile-sub a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--c-muted);
  padding: var(--s-2) 0;
}

.mobile-sub a:hover { color: var(--c-accent-dark); }
.mobile-sub a[aria-current="page"] { color: var(--c-accent-dark); font-weight: 500; }
.mobile-sub .icon { width: 21px; height: 21px; color: var(--c-ink); flex-shrink: 0; }

.mobile-nav-foot {
  margin-top: var(--s-6);
  padding-top: var(--s-6);
  border-top: 1px solid var(--c-line);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.contact-line {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--c-muted);
}

.contact-line .icon { width: 19px; height: 19px; color: var(--c-accent); flex-shrink: 0; }

/* ---------- 6. Sticky mobile CTA ----------------------------------------- */
/* Promised in the proposal: the next step is never more than one tap away.
   It slides in once the hero's own booking button has scrolled away, so the
   two are never stacked one above the other on first paint. */

.sticky-cta {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-sticky-cta);
  display: none;
  gap: var(--s-2);
  padding: 0.6rem var(--s-4) calc(0.6rem + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--c-line);
  transform: translateY(100%);
  transition: transform var(--t-base) var(--ease-out);
}

.sticky-cta.is-ready { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .sticky-cta { transition: none; }
}

.sticky-cta .btn-book { flex: 1; box-shadow: none; }

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  flex-shrink: 0;
  border-radius: var(--r-sm);
  border: 1.5px solid var(--c-line-strong);
  color: var(--c-ink);
  background: transparent;
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}

.btn-icon:hover { border-color: var(--c-accent); color: var(--c-accent); }
.btn-icon .icon { width: 22px; height: 22px; }

@media (max-width: 860px) {
  .sticky-cta { display: flex; }
  body { padding-bottom: var(--sticky-cta-h); }
}

/* ---------- 7. Hero ------------------------------------------------------- */

.hero {
  position: relative;
  min-height: min(94svh, 900px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: var(--c-on-deep);
  background: var(--c-deep-teal);
}

.hero-media { position: absolute; inset: 0; z-index: 0; }

.hero-media video,
.hero-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
}

.hero-media video::-webkit-media-controls-start-playback-button {
  display: none !important;
  -webkit-appearance: none;
}

/* Scrim, weighted to the bottom-left where the copy sits and tinted with the
   brand teal rather than neutral black, so the footage reads as part of the
   palette instead of a stock clip behind a grey wash. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(7, 30, 32, 0.93) 0%, rgba(7, 30, 32, 0.6) 40%, rgba(7, 30, 32, 0.24) 72%, rgba(7, 30, 32, 0.45) 100%),
    linear-gradient(to right, rgba(7, 30, 32, 0.62) 0%, rgba(7, 30, 32, 0) 62%);
}

.hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--wrap-wide);
  padding-top: calc(var(--header-h) + var(--s-8));
  padding-bottom: clamp(3.5rem, 7vw, 6rem);
}

.hero .eyebrow { color: var(--c-accent-mid); }

.hero h1 {
  font-size: var(--fs-display);
  color: #fff;
  max-width: 13ch;
  margin-bottom: var(--s-5);
}

.hero .lede {
  color: rgba(255, 255, 255, 0.84);
  max-width: 54ch;
  margin-bottom: var(--s-6);
}

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }

/* Scroll cue — a falling dot-spine, straight from the logo. */
.hero-cue {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(3.5rem, 7vw, 6rem);
  z-index: 1;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 7px;
}

.hero-cue span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--c-accent-mid);
  opacity: 0.3;
  animation: cue 1.9s var(--ease) infinite;
}

.hero-cue span:nth-child(2) { animation-delay: 0.14s; width: 7px; height: 7px; }
.hero-cue span:nth-child(3) { animation-delay: 0.28s; width: 9px; height: 9px; }
.hero-cue span:nth-child(4) { animation-delay: 0.42s; width: 6px; height: 6px; }

@keyframes cue {
  0%, 100% { opacity: 0.22; transform: translateY(0); }
  50%      { opacity: 1;    transform: translateY(3px); }
}

@media (min-width: 900px) { .hero-cue { display: flex; } }

@media (prefers-reduced-motion: reduce) {
  .hero-cue span { animation: none; opacity: 0.6; }
}

/* Sub-page hero. The logo's offset double circle, blown up and cropped by the
   section edge — replaces the radial-gradient glow the template shipped with. */
.page-hero {
  position: relative;
  background: var(--c-wash);
  padding: calc(var(--header-h-sm) + var(--s-8)) 0 var(--s-8);
  overflow: hidden;
}

.page-hero::before,
.page-hero::after {
  content: "";
  position: absolute;
  width: 520px;
  height: 520px;
  border-radius: 50%;
  pointer-events: none;
}

.page-hero::before {
  right: -130px;
  top: -180px;
  border: 1px solid rgba(28, 171, 177, 0.4);
}

.page-hero::after {
  right: -76px;
  top: -138px;
  border: 1px solid rgba(25, 25, 25, 0.09);
}

.page-hero .wrap { position: relative; z-index: 1; }
.page-hero h1 { max-width: 19ch; }
.page-hero .lede { margin-top: var(--s-5); max-width: 58ch; }
.page-hero .btn-group { margin-top: var(--s-6); }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  color: var(--c-muted);
  margin-bottom: var(--s-5);
}

.breadcrumb a:hover { color: var(--c-accent-dark); }
.breadcrumb .sep { color: var(--c-faint); }
.breadcrumb [aria-current] { color: var(--c-ink); font-weight: 500; }

/* ---------- 8. Sections --------------------------------------------------- */
/* One padding rule; modifiers only change the ground. Keeps the cascade
   predictable, with no section class silently cancelling another. */

.section { padding-block: var(--section-y); }
.section-lg { padding-block: var(--section-y-lg); }
.section-tight { padding-block: clamp(2.5rem, 5vw, 4rem); }

.ground-wash { background: var(--c-wash); }
.ground-alt  { background: var(--c-bg-alt); }

.on-deep { background: var(--c-deep-teal); color: var(--c-on-deep); }
.on-deep h1, .on-deep h2, .on-deep h3, .on-deep h4 { color: #fff; }
.on-deep .lede { color: var(--c-on-deep-muted); }

.section-head { max-width: 660px; margin-bottom: var(--s-7); }
.section-head .lede { margin-top: var(--s-4); }
.section-head.centred { margin-inline: auto; text-align: center; }
.section-head.centred .eyebrow { justify-content: center; }
.section-head.centred .lede { margin-inline: auto; }

.section-foot { margin-top: var(--s-7); display: flex; justify-content: center; }

/* Dot-spine list — replaces the tick-in-a-circle. Dots are graduated, the way
   they are in the logo, rather than a repeated identical marker. */
.dot-list { display: flex; flex-direction: column; gap: var(--s-4); }

.dot-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  color: var(--c-body);
}

.dot-list li::before {
  content: "";
  flex-shrink: 0;
  width: 9px;
  height: 9px;
  margin-top: 0.6em;
  border-radius: 50%;
  background: var(--c-accent);
}

.dot-list li:nth-child(2)::before { width: 11px; height: 11px; margin-top: 0.55em; }
.dot-list li:nth-child(3)::before { width: 8px;  height: 8px;  margin-top: 0.62em; }
.dot-list li:nth-child(n+4)::before { width: 6px; height: 6px; margin-top: 0.66em; opacity: 0.7; }

.on-deep .dot-list li { color: var(--c-on-deep-muted); }
.on-deep .dot-list li::before { background: var(--c-accent-mid); }

/* Credential strip — verifiable facts only, no invented statistics. */
.creds {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--c-line);
  border-block: 1px solid var(--c-line);
}

.cred {
  background: var(--c-wash);
  padding: var(--s-6) var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.cred-figure {
  font-size: clamp(1.35rem, 1.7vw, 1.75rem);
  font-weight: 600;
  letter-spacing: var(--tr-head);
  color: var(--c-ink);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  line-height: 1.2;
}

.cred-figure .icon { width: 22px; height: 22px; color: var(--c-accent); flex-shrink: 0; }
.cred-label { font-size: var(--fs-sm); color: var(--c-muted); }

/* ---------- 9. Service tiles ---------------------------------------------- */
/* Deliberately not a uniform lattice. Seven services laid out 2 / 3 / 2 across
   a 12-column grid, photo-led, no borders — whitespace and image edges do the
   separating instead of hairlines. */

.tiles {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--s-5);
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-bg-alt);
  min-height: 300px;
  isolation: isolate;
}

.tile-span-6 { grid-column: span 6; min-height: 430px; }
.tile-span-4 { grid-column: span 4; min-height: 360px; }
.tile-span-7 { grid-column: span 7; min-height: 320px; }
.tile-span-5 { grid-column: span 5; min-height: 320px; }

.tile-media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }

.tile-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out);
}

.tile:hover .tile-media img { transform: scale(1.045); }

.tile-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(7, 30, 32, 0.94) 0%, rgba(7, 30, 32, 0.72) 34%, rgba(7, 30, 32, 0.3) 68%, rgba(7, 30, 32, 0.08) 100%);
}

.tile-body {
  position: relative;
  z-index: 1;
  margin-top: auto;
  padding: var(--s-6);
  color: #fff;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.tile-body .icon { width: 30px; height: 30px; color: #fff; margin-bottom: var(--s-2); }

/* The heading level varies by page — h2 where the tile is a top-level section,
   h3 where a section heading already introduces the group — so style both. */
.tile h2,
.tile h3 { color: #fff; font-size: var(--fs-h3); }

.tile p {
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--fs-sm);
  max-width: 40ch;
}

.tile .link-arrow { color: #fff; margin-top: var(--s-2); }

/* The whole tile is the target; the visible link keeps the affordance. */
.tile-link::after { content: ""; position: absolute; inset: 0; z-index: 2; }

.tile:hover .link-arrow .icon { transform: translateX(4px); }

/* Compact variant for the services list on interior pages. */
.tile-quiet { background: var(--c-wash); min-height: 0; border-radius: var(--r-md); }
.tile-quiet .tile-body { color: var(--c-body); padding: var(--s-5); margin-top: 0; }
.tile-quiet h2,
.tile-quiet h3 { color: var(--c-ink); font-size: var(--fs-h4); }
.tile-quiet p { color: var(--c-muted); }
.tile-quiet .tile-body .icon { color: var(--c-ink); }
.tile-quiet .link-arrow { color: var(--c-accent-dark); }

/* ---------- 10. Split / about --------------------------------------------- */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 5.5rem);
  align-items: center;
}

/* Alternates the image side down a page so consecutive splits do not stack
   into a column of identical left-hand images. */
.split-reverse .split-media { order: 2; }

.split-media { position: relative; }

.split-media img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--r-lg);
  display: block;
}

/* The logo's arc, bracketing the portrait so the rectangle is broken. */
.split-media::before {
  content: "";
  position: absolute;
  inset: auto -22px -22px auto;
  width: 62%;
  aspect-ratio: 1;
  border: 1.5px solid var(--c-accent);
  border-radius: 50%;
  clip-path: polygon(50% 50%, 100% 0, 100% 100%, 0 100%, 0 62%);
  z-index: -1;
  pointer-events: none;
}

.split-body > * + * { margin-top: var(--s-4); }
.split-body h2 + .lede { margin-top: var(--s-4); }
.split-body .btn-group { margin-top: var(--s-6); }

/* Pull quote — her own words. No quote glyph; a dot-run instead. */
.pullquote {
  position: relative;
  padding-top: var(--s-5);
  margin-top: var(--s-6);
  border-top: 1px solid var(--c-line);
  font-size: clamp(1.15rem, 1.2vw + 0.9rem, 1.55rem);
  font-weight: 300;
  line-height: 1.42;
  letter-spacing: -0.012em;
  color: var(--c-ink);
}

.pullquote cite {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
  font-size: var(--fs-xs);
  font-style: normal;
  font-weight: 500;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-muted);
}

.pullquote cite::before {
  content: "";
  width: 26px;
  height: 1.5px;
  background: var(--c-accent);
  flex-shrink: 0;
}

.on-deep .pullquote { color: #fff; border-top-color: var(--c-line-on-deep); }
.on-deep .pullquote cite { color: var(--c-on-deep-muted); }

/* The quote as the whole point of a section rather than an aside. Centred,
   larger, and marked with the dot-run instead of a rule. */
.pullquote-lead {
  text-align: center;
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
  font-size: clamp(1.5rem, 2.2vw + 1rem, 2.4rem);
  line-height: 1.28;
  letter-spacing: -0.022em;
  max-width: 20ch;
  margin-inline: auto;
}

.pullquote-lead::before {
  content: "";
  display: block;
  width: 46px;
  height: 10px;
  margin: 0 auto var(--s-5);
  background:
    radial-gradient(circle 5px at 5px 5px, var(--c-accent) 100%, transparent 0) 0 0/17px 10px no-repeat,
    radial-gradient(circle 4px at 4px 5px, var(--c-accent) 100%, transparent 0) 17px 0/15px 10px no-repeat,
    radial-gradient(circle 3px at 3px 5px, var(--c-accent) 100%, transparent 0) 32px 0/14px 10px no-repeat;
}

.pullquote-lead cite { justify-content: center; }

/* ---------- 11. Reviews ---------------------------------------------------- */
/* Real, attributed Google reviews. No invented avatars, no glyph star rows
   standing in for a rating the practice has actually earned. */

.rating-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--c-bg);
  border: 1px solid var(--c-line);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-sm);
}

.rating-badge .icon { width: 20px; height: 20px; flex-shrink: 0; }
.rating-badge .stars { display: flex; gap: 2px; color: #F5A623; }
.rating-badge .stars .icon { width: 15px; height: 15px; }

.rating-badge .score { font-weight: 600; color: var(--c-ink); }
.rating-badge .count { font-size: var(--fs-sm); color: var(--c-muted); }

.reviews {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-5);
}

.review {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-6);
  background: var(--c-bg);
  border-radius: var(--r-md);
  box-shadow: var(--sh-md);
}

/* Dot-run in place of a quote mark. */
.review::before {
  content: "";
  width: 34px;
  height: 7px;
  border-radius: var(--r-pill);
  background:
    radial-gradient(circle 3.5px at 3.5px 3.5px, var(--c-accent) 100%, transparent 0) 0 0/13px 7px no-repeat,
    radial-gradient(circle 3px at 3px 3.5px, var(--c-accent) 100%, transparent 0) 13px 0/11px 7px no-repeat,
    radial-gradient(circle 2.5px at 2.5px 3.5px, var(--c-accent) 100%, transparent 0) 24px 0/10px 7px no-repeat;
  opacity: 0.9;
}

.review blockquote {
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--c-body);
  flex: 1;
}

.review figcaption {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--c-line);
  font-size: var(--fs-sm);
}

.review .reviewer { font-weight: 600; color: var(--c-ink); }
.review .source { display: flex; align-items: center; gap: 5px; margin-left: auto; color: var(--c-faint); font-size: var(--fs-xs); }
.review .source .icon { width: 15px; height: 15px; }

/* Treatment steps.
   The only numbered sequence on the site, because a course of treatment
   genuinely is one. Rendered as a horizontal run of dots that grow from the
   first step to the last — the logo motif carrying real information, here the
   patient's progress toward being discharged. */

.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5);
}

.step {
  position: relative;
  padding-top: var(--s-6);
}

/* The rail, carrying on through the gap to the next step. */
.step::before {
  content: "";
  position: absolute;
  top: 9px;
  left: 0;
  right: calc(-1 * var(--s-5));
  height: 1px;
  background: var(--c-line-strong);
}

.step:last-child::before { right: 0; }

/* The dot, graduating as the sequence advances. */
.step::after {
  content: "";
  position: absolute;
  top: 5px;
  left: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--c-accent);
}

.step:nth-child(2)::after { width: 11px; height: 11px; top: 4px; }
.step:nth-child(3)::after { width: 13px; height: 13px; top: 3px; }
.step:nth-child(4)::after { width: 16px; height: 16px; top: 2px; }

.step-index {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--c-faint);
  margin-bottom: var(--s-2);
}

.step h3 { font-size: var(--fs-h4); margin-bottom: var(--s-2); }
.step p { font-size: var(--fs-sm); color: var(--c-muted); }

/* ---------- 12. Areas served ---------------------------------------------- */

.areas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}

.area-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0.55rem 1.1rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-line);
  background: var(--c-bg);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--c-body);
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}

.area-chip::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-accent);
  flex-shrink: 0;
}

a.area-chip:hover { border-color: var(--c-accent); color: var(--c-accent-dark); background: var(--c-wash); }

.on-deep .area-chip { background: rgba(255, 255, 255, 0.06); border-color: var(--c-line-on-deep); color: var(--c-on-deep); }
.on-deep a.area-chip:hover { border-color: var(--c-accent-mid); background: rgba(255, 255, 255, 0.12); color: #fff; }

.area-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }

.area-entry {
  padding: var(--s-5) 0;
  border-top: 1px solid var(--c-line);
}

/* A photograph occupying one cell of the suburb grid. It stretches to the row
   height so it sits flush with the text entries beside it. */
.area-photo {
  margin: var(--s-5) 0 0;
  border-radius: var(--r-md);
  overflow: hidden;
  min-height: 210px;
  background: var(--c-bg-alt);
}

.area-photo img {
  width: 100%;
  height: 100%;
  min-height: 210px;
  object-fit: cover;
  display: block;
}

.area-entry h3 { font-size: var(--fs-h4); margin-bottom: var(--s-2); }
.area-entry p { font-size: var(--fs-sm); color: var(--c-muted); }
.area-entry .meta { display: block; margin-top: var(--s-3); font-size: var(--fs-xs); color: var(--c-faint); }

/* ---------- 13. CTA band --------------------------------------------------- */
/* The one place deep teal is spent. */

.cta-band {
  position: relative;
  background: var(--c-deep-teal);
  color: var(--c-on-deep);
  padding-block: var(--section-y);
  overflow: hidden;
}

/* Logo geometry: the offset broken circle, cropped by the band. */
.cta-band::before,
.cta-band::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.cta-band::before {
  width: 640px;
  height: 640px;
  left: -190px;
  bottom: -330px;
  border: 1px solid rgba(143, 217, 220, 0.28);
}

.cta-band::after {
  width: 640px;
  height: 640px;
  left: -140px;
  bottom: -300px;
  border: 1px solid rgba(255, 255, 255, 0.09);
}

.cta-band .wrap { position: relative; z-index: 1; }

.cta-inner {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.cta-band h2 { color: #fff; max-width: 17ch; }
.cta-band .lede { color: rgba(255, 255, 255, 0.75); margin-top: var(--s-4); max-width: 44ch; }

.cta-actions { display: flex; flex-direction: column; gap: var(--s-3); }
.cta-actions .btn { width: 100%; }

.cta-aside {
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.62);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.cta-aside a:hover { color: #fff; }

/* ---------- 14. Footer ------------------------------------------------------ */

.site-footer {
  background: var(--c-deep);
  color: var(--c-on-deep-muted);
  padding: var(--s-9) 0 var(--s-6);
  font-size: var(--fs-sm);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.2fr;
  gap: var(--s-7);
  padding-bottom: var(--s-7);
  border-bottom: 1px solid var(--c-line-on-deep);
}

.footer-brand svg { height: 46px; width: auto; margin-bottom: var(--s-4); }
.footer-brand .mark-ring, .footer-brand .mark-rule { stroke: rgba(244, 248, 248, 0.7); }
.footer-brand .mark-word { fill: #fff; }
.footer-brand p { max-width: 34ch; }

.footer-heading {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: #fff;
  margin-bottom: var(--s-4);
}

.footer-links { display: flex; flex-direction: column; gap: var(--s-3); }
.footer-links a:hover { color: var(--c-accent-mid); }

.footer-contact { display: flex; flex-direction: column; gap: var(--s-3); }
.footer-contact .contact-line { color: var(--c-on-deep-muted); align-items: flex-start; }
.footer-contact .contact-line .icon { color: var(--c-accent-mid); margin-top: 2px; }
.footer-contact a:hover { color: #fff; }

.footer-hours { margin-top: var(--s-4); display: grid; grid-template-columns: auto 1fr; gap: 4px var(--s-4); font-size: var(--fs-xs); }
.footer-hours dt { color: var(--c-on-deep-muted); }
.footer-hours dd { color: #fff; text-align: right; }

.footer-bottom {
  padding-top: var(--s-5);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-3);
  font-size: var(--fs-xs);
  color: rgba(244, 248, 248, 0.62);   /* 0.45 measured 4.2:1 on this ground */
}

.footer-bottom a:hover { color: var(--c-accent-mid); }

/* ---------- 15. Forms -------------------------------------------------------- */

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4);
}

.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field.full { grid-column: 1 / -1; }

.field label { font-size: var(--fs-sm); font-weight: 600; color: var(--c-ink); }

.field input,
.field select,
.field textarea {
  font-family: var(--font);
  font-size: var(--fs-body);
  color: var(--c-body);
  background: var(--c-bg);
  border: 1.5px solid var(--c-line);
  border-radius: var(--r-sm);
  padding: 0.85rem 1rem;
  width: 100%;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}

.field textarea { resize: vertical; min-height: 140px; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--c-accent);
  box-shadow: 0 0 0 3px rgba(28, 171, 177, 0.16);
}

.field .hint { font-size: var(--fs-xs); color: var(--c-faint); }

.form-note { font-size: var(--fs-xs); color: var(--c-muted); margin-top: var(--s-3); }

.contact-panel {
  background: var(--c-wash);
  border-radius: var(--r-lg);
  padding: clamp(1.75rem, 3vw, 2.75rem);
}

.hours-table { width: 100%; font-size: var(--fs-sm); border-collapse: collapse; }
.hours-table th { text-align: left; font-weight: 400; color: var(--c-muted); padding: 0.55rem 0; }
.hours-table td { text-align: right; color: var(--c-ink); font-weight: 500; padding: 0.55rem 0; font-variant-numeric: tabular-nums; }
.hours-table tr + tr th, .hours-table tr + tr td { border-top: 1px solid var(--c-line); }
.hours-table .closed { color: var(--c-faint); font-weight: 400; }
.hours-table tr.is-today th, .hours-table tr.is-today td { color: var(--c-accent-dark); font-weight: 600; }

/* Map.
   The embed sits over a fallback that names the address and links out. If
   Google is blocked, slow, or the patient has declined third-party content,
   they still get the address and a way to navigate to it rather than a white
   rectangle where the directions should be. */

.map-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-bg-alt);
  border: 1px solid var(--c-line);
}

.map-fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--s-3);
  text-align: center;
  padding: var(--s-5);
}

.map-fallback .icon { width: 30px; height: 30px; color: var(--c-accent); }
.map-fallback address { font-style: normal; color: var(--c-body); }

.map-embed {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ---------- 15b. Booking page --------------------------------------------- */

.booking-layout {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}

.chosen-service {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-5);
  background: var(--c-wash);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  color: var(--c-body);
}

.chosen-service .icon { width: 17px; height: 17px; color: var(--c-accent); flex-shrink: 0; }
.chosen-service a { margin-left: auto; font-weight: 600; color: var(--c-accent-dark); }
.chosen-service a:hover { color: var(--c-accent); }

.booking-widget {
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--c-bg);
}

/* Live Bookem widget.
   The min-height reserves roughly what the widget renders at rest — its list
   of consultation types — so the page does not jump when the third-party
   script finally paints. It grows on its own from there, when the patient
   picks a type and the calendar opens, which is a shift they asked for. */
.booking-frame-wrap { position: relative; }

.booking-frame {
  display: block;
  width: 100%;
  min-height: 260px;
  border: 0;
}

.booking-frame bookem-widget {
  display: block;
  width: 100%;
}

/* Overlays the (still rendering) frame above rather than replacing it, so the
   host stays visible and normally laid out the whole time — some third-party
   widgets decide what to render based on their own visibility or size. */
.booking-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  margin: 0;
  background: var(--c-bg);
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.booking-loading .spinner {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--c-line);
  border-top-color: var(--c-accent);
  animation: spin 0.8s linear infinite;
  flex-shrink: 0;
}

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .booking-loading .spinner { animation: none; }
}

/* Bookem sets its own type; only the width is ours to insist on. */
.booking-frame iframe {
  width: 100%;
  border: 0;
  display: block;
}

/* Shown until the Bookem embed URL is configured. */
.booking-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-4);
  padding: clamp(2.5rem, 6vw, 4.5rem) var(--s-5);
}

.booking-fallback .icon { width: 40px; height: 40px; color: var(--c-accent); }
.booking-fallback h2 { font-size: var(--fs-h3); }
.booking-fallback p { color: var(--c-muted); max-width: 42ch; }
.booking-fallback .btn { margin-top: var(--s-2); }

.booking-alt { font-size: var(--fs-sm); }
.booking-alt a { color: var(--c-accent-dark); font-weight: 600; }
.booking-alt a:hover { color: var(--c-accent); }

/* On the booking page itself, a header button and a sticky bar that both
   point at the current page are noise. */
.page-book .site-header .btn-book,
.page-book .mobile-nav-foot .btn-book,
.page-book .sticky-cta { display: none; }

/* ---------- 16. FAQ ---------------------------------------------------------- */

.faq { border-top: 1px solid var(--c-line); }
.faq-item { border-bottom: 1px solid var(--c-line); }

/* The question heading is h2 on /faq/ and h3 elsewhere; the button inside
   sets its own type either way. */
.faq-item h2,
.faq-item h3 { font-size: inherit; }

.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  padding: var(--s-5) 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font);
  font-size: var(--fs-h4);
  font-weight: 600;
  letter-spacing: var(--tr-head);
  color: var(--c-ink);
  transition: color var(--t-fast) var(--ease);
}

.faq-q:hover { color: var(--c-accent-dark); }

/* Marker grows from a dot to a ring when open — the logo again. */
.faq-marker {
  position: relative;
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
}

.faq-marker::before {
  content: "";
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--c-accent);
  transition: width var(--t-base) var(--ease-out), height var(--t-base) var(--ease-out),
              background-color var(--t-base) var(--ease), border-width var(--t-base) var(--ease);
  border: 0 solid var(--c-accent);
}

.faq-item[data-open="true"] .faq-marker::before {
  width: 22px;
  height: 22px;
  background: transparent;
  border-width: 2px;
}

.faq-a { height: 0; overflow: hidden; transition: height var(--t-base) var(--ease); }
.faq-a-inner { padding-bottom: var(--s-5); color: var(--c-muted); max-width: 68ch; }
.faq-a-inner > * + * { margin-top: var(--s-3); }

@media (prefers-reduced-motion: reduce) {
  .faq-a { transition: none; }
  .faq-marker::before { transition: none; }
}

/* ---------- 17. Utilities + motion -------------------------------------------- */

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

.measure { max-width: 62ch; }
.measure-tight { max-width: 46ch; }
.text-centre { text-align: center; }

.prose > * + * { margin-top: var(--s-4); }
.prose h2 { margin-top: var(--s-7); }
.prose h3 { margin-top: var(--s-6); }
.prose p, .prose li { color: var(--c-body); }
.prose a { color: var(--c-accent-dark); text-decoration: underline; text-underline-offset: 3px; }
.prose .btn, .prose .link-arrow { text-decoration: none; }
.prose .btn-book { color: var(--c-ink); }
.prose a:hover { color: var(--c-accent); }

.figure-band img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  border-radius: var(--r-lg);
  display: block;
}

.figure-band figcaption {
  margin-top: var(--s-3);
  font-size: var(--fs-xs);
  color: var(--c-faint);
}

[data-animate] {
  opacity: 0;
  transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out);
}

[data-animate="up"]    { transform: translateY(22px); }
[data-animate="left"]  { transform: translateX(-24px); }
[data-animate="right"] { transform: translateX(24px); }
[data-animate="in"]    { transform: scale(0.985); }

[data-animate].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-animate] { opacity: 1; transform: none; transition: none; }
  .tile-media img { transition: none; }
}

/* ---- responsive.css ------------------------------------------------ */
/* ==========================================================================
   RESPONSIVE.CSS — Rikki Malherbe Physiotherapy

   Most patients arrive on a phone, in pain, late at night. Mobile is the
   primary case, not the fallback, so the breakpoints below are about keeping
   the booking button and the practitioner's face in view — not about making
   a desktop layout survive a narrow viewport.

   Breakpoints: 1180 (spine rail, declared in style.css) · 1024 · 860 · 620
   ========================================================================== */

/* ---------- ≤ 1180px ------------------------------------------------------ */

@media (max-width: 1180px) {
  .cta-inner { grid-template-columns: 1fr; }
  .cta-band h2 { max-width: 22ch; }
  .cta-actions { flex-direction: row; flex-wrap: wrap; }
  .cta-actions .btn { width: auto; flex: 1 1 240px; }
}

/* ---------- ≤ 1024px ------------------------------------------------------ */

@media (max-width: 1024px) {

  /* Service tiles fall from 2/3/2 to a plain pair. The asymmetry is a
     desktop luxury; on a tablet it just makes the tiles too short to read. */
  .tile-span-6,
  .tile-span-4,
  .tile-span-7,
  .tile-span-5 { grid-column: span 6; }

  .split { grid-template-columns: 1fr; gap: var(--s-7); }
  .split-media { max-width: 460px; }
  .split-media img { aspect-ratio: 4 / 3; }
  .split-reverse .split-media { order: -1; }

  .reviews { grid-template-columns: 1fr 1fr; }
  .review:last-child { grid-column: 1 / -1; }

  .area-list { grid-template-columns: 1fr 1fr; }
  .steps { grid-template-columns: 1fr 1fr; row-gap: var(--s-6); }

  .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--s-6); }
  .footer-brand { grid-column: 1 / -1; }
}

/* ---------- ≤ 860px — navigation and the sticky booking bar --------------- */

@media (max-width: 860px) {

  .main-nav { display: none; }
  .nav-toggle { display: inline-flex; }

  /* The header booking button is redundant once the sticky bar appears, and
     two competing Book buttons on a small screen is one too many. */
  .site-header .btn-book { display: none; }

  .hero { min-height: min(88svh, 720px); }
  .hero h1 { max-width: 100%; }
  .hero .lede { max-width: 100%; }
  .hero-actions { width: 100%; }
  .hero-actions .btn { flex: 1 1 auto; }

  .page-hero { padding-top: calc(var(--header-h-sm) + var(--s-6)); }
  .page-hero::before,
  .page-hero::after { width: 320px; height: 320px; right: -110px; top: -120px; }
  .page-hero::after { right: -80px; top: -96px; }

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

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

  .split-media::before { inset: auto -12px -12px auto; width: 52%; }
}

/* ---------- ≤ 620px ------------------------------------------------------- */

@media (max-width: 620px) {

  .tile-span-6,
  .tile-span-4,
  .tile-span-7,
  .tile-span-5 { grid-column: 1 / -1; }

  .tile { min-height: 250px; border-radius: var(--r-md); }
  .tile-body { padding: var(--s-5); }

  .reviews { grid-template-columns: 1fr; }
  .review:last-child { grid-column: auto; }

  .area-list { grid-template-columns: 1fr; }
  .area-entry { padding: var(--s-4) 0; }

  /* Stacked, the run of dots turns vertical — still a spine, still a sequence. */
  .steps { grid-template-columns: 1fr; gap: 0; }
  .step { padding: var(--s-4) 0 var(--s-4) var(--s-6); }
  .step::before { top: 0; bottom: 0; left: 7px; right: auto; width: 1px; height: auto; }
  .step:first-child::before { top: var(--s-4); }
  .step:last-child::before { bottom: auto; height: var(--s-4); }
  .step::after { top: calc(var(--s-4) + 4px); left: 3px; }
  .step:nth-child(2)::after { left: 2px; }
  .step:nth-child(3)::after { left: 1px; }
  .step:nth-child(4)::after { left: 0; }

  .creds { grid-template-columns: 1fr; }
  .cred { padding: var(--s-5) var(--s-4); }

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

  .cta-actions { flex-direction: column; }
  .cta-actions .btn { width: 100%; }

  .btn { width: 100%; }
  .btn-group { flex-direction: column; align-items: stretch; }
  .sticky-cta .btn-book { width: auto; }
  .btn-icon { width: 52px; }

  .split-media { max-width: none; }
  .split-media img { aspect-ratio: 3 / 4; }

  .figure-band img { aspect-ratio: 4 / 3; }

  .faq-q { font-size: var(--fs-body); gap: var(--s-4); }
}

/* ---------- Print ---------------------------------------------------------
   Patients do print directions and opening hours. Strip the furniture. */

@media print {
  .site-header,
  .mobile-nav,
  .sticky-cta,
  .spine,
  .hero-media,
  .hero-cue,
  .cta-band,
  .section-foot { display: none !important; }

  body { padding-bottom: 0; color: #000; background: #fff; font-size: 11pt; }
  .hero { min-height: 0; background: none; color: #000; }
  .hero h1, .hero .lede { color: #000; }
  .tile, .review, .contact-panel { box-shadow: none; border: 1px solid #ccc; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
}

/* ---------- Booking page --------------------------------------------------- */

@media (max-width: 1024px) {
  .booking-layout { grid-template-columns: 1fr; }
  .booking-frame { min-height: 300px; }
}

@media (max-width: 620px) {
  .booking-frame { min-height: 380px; }  /* the type cards stack */
  .chosen-service { flex-wrap: wrap; }
  .chosen-service a { margin-left: 0; }

  /* The sticky bar is hidden here, so the body padding it reserves is not
     needed either. */
  .page-book { padding-bottom: 0; }
}

@media (max-width: 860px) {
  .page-book { padding-bottom: 0; }

  /* One photograph per grid row reads better than a full-width band when the
     suburb entries stack. */
  .area-photo { min-height: 0; }
  .area-photo img { min-height: 0; aspect-ratio: 3 / 2; height: auto; }
}
