/* Vista Clinic — home template tokens.
 * Derived from a computed-style profile of the Wix Studio comp
 * (giho22.wixstudio.com/my-site) taken 2026-07-26 at 1440x900 and 390x844.
 * Every value below was READ from that page, not invented. Where a value is a
 * judgement call it is marked TUNE.
 *
 * SCOPE: this sheet only ever loads on the page-home.php template, so it cannot
 * regress the 33 Elementor-built pages. It styles a Gutenberg page, so it is NOT
 * fighting Elementor's per-widget selectors here — no !important needed inside
 * .vc-home. (Additional CSS post 13817 still prints after this sheet; its
 * `font-family: 'Poppins' !important` on body/h1-h6/a/li/span/button DOES reach
 * into this template. The font-family declarations below are therefore marked
 * !important — that is the one place we must match the legacy arms race.)
 */

/* ---------------------------------------------------------------------------
 * 0. FONTS — SELF-HOSTED, NOT hotlinked from fonts.googleapis.com.
 *
 * CONFIRMED 2026-07-26: both families return HTTP 200 from the Google Fonts
 * API with real woff2 sources, i.e. they are genuine Google Fonts and therefore
 * OFL — free to self-host and redistribute.
 *
 * WHY SELF-HOSTED: the audience is Ireland/EU and the site runs a consent
 * banner. Requesting fonts from fonts.googleapis.com transmits every visitor's
 * IP to Google before consent — the exact practice fined in the Munich
 * regional court ruling (3 O 17493/20, Jan 2022). Self-hosting removes the
 * third-party request entirely, so there is nothing to gate behind consent.
 * DO NOT "simplify" this back to an @import of fonts.googleapis.com.
 *
 * Both files are variable fonts (wght 400..700), so one file covers every
 * weight — no separate Regular/Medium downloads. latin + latin-ext subsets
 * only; vietnamese/cyrillic/greek were deliberately dropped. 88 KB total.
 * ------------------------------------------------------------------------ */
@font-face {
	font-family: 'Afacad';
	font-style: normal;
	font-weight: 400 700;                      /* variable range */
	font-display: swap;                        /* never block render on webfont */
	src: url('fonts/afacad-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122,
		U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Afacad';
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url('fonts/afacad-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
		U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Cinzel';
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url('fonts/cinzel-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122,
		U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Cinzel';
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url('fonts/cinzel-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
		U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------------
 * 1. TOKENS
 * ------------------------------------------------------------------------ */
.vc-home {
	/* Palette — hex values read from the comp's :root custom properties. */
	--vc-bg:            #ffffff;  /* page / alternating light band          */
	--vc-bg-alt:        #f2f1ee;  /* cream alternating band + text-on-dark  */
	--vc-ink:           #2e2e2e;  /* body copy, h2/h4 on light sections     */
	--vc-ink-soft:      #52504e;  /* subtitles                              */
	--vc-olive:         #282e20;  /* dark full-bleed break + ghost btn      */
	--vc-teal:          #4A7874;  /* PRIMARY CTA fill — matches the header bar     */
	--vc-teal-light:    #6c9f9a;  /* contact band background (decorative only)     */
	--vc-teal-hover:    #3B615E;  /* CTA hover — one step darker than the header   */
	--vc-teal-deep:     #397578;  /* topbar address text                    */
	--vc-cream-warm:    #fef7f2;  /* hero subhead                           */
	--vc-border-soft:   #c8d8d5;  /* header button border                   */

	/* Type. Afacad carries ~95% of the comp; Cinzel is a single accent.
	 * Both are (INFERRED) SIL OFL / Google Fonts — VERIFY BEFORE SELF-HOSTING.
	 * Fallback chain degrades to the site's existing Poppins, then system. */
	--vc-font: "Afacad", "Poppins", -apple-system, "Segoe UI", sans-serif;
	--vc-font-accent: "Cinzel", Georgia, serif;

	/* Fluid scale. The comp uses Wix's spx engine — calc(N * 100vw / 1280),
	 * scaling linearly off a 1280px design base with no stops until 1920px.
	 * clamp() approximates it: the vw term equals N/1280, the max equals the
	 * 1920px value, the min is the comp's measured <=750px breakpoint value. */
	--vc-h1:  clamp(35px, 3.906vw, 50px);      /* fixed per breakpoint in comp */
	--vc-h2:  clamp(25px, 3.047vw, 58.5px);    /* 39 * vw/1280 -> 43.875@1440  */
	--vc-h3:  clamp(24px, 2.109vw, 40.5px);    /* 27 * vw/1280 -> 30.375@1440  */
	--vc-h4:  clamp(24px, 2.109vw, 40.5px);
	--vc-body: 16px;
	--vc-lede: clamp(16px, 1.389vw, 26.6px);   /* hero subhead 20px@1440       */

	/* Rhythm. The comp has no 8px system (Wix free-placement); these are the
	 * measured section paddings rounded to a usable scale. TUNE. */
	--vc-section-y: clamp(64px, 9vw, 130px);
	--vc-gutter:    clamp(16px, 3.47vw, 50px); /* 50px @1440, 24px @390        */
	--vc-maxw:      1340px;                    /* inner box @1440 viewport     */

	/* Shape. Census over the comp: radius 0 on virtually everything, and
	 * `--shd: none` on buttons. The hard-edged, shadowless treatment is the
	 * single biggest driver of the "clinical / expensive" read. */
	--vc-radius: 0;
	--vc-radius-pill: 999px;                   /* secondary "Explore" only     */
	--vc-shadow: none;
}

/* ---------------------------------------------------------------------------
 * 2. BASE
 * ------------------------------------------------------------------------ */
.vc-home {
	background: var(--vc-bg);
	color: var(--vc-ink);
	font-size: var(--vc-body);
	line-height: 1.6;                          /* comp body 16/25.6 = 1.60     */
}

/* font-family carries !important solely to beat Additional CSS post 13817.
 * See the header note. Nothing else in this file needs it. */
.vc-home,
.vc-home p,
.vc-home li,
.vc-home a,
.vc-home span,
.vc-home button,
.vc-home h1, .vc-home h2, .vc-home h3, .vc-home h4, .vc-home h5, .vc-home h6 {
	font-family: var(--vc-font) !important;
	letter-spacing: normal;                    /* comp: normal everywhere      */
	text-transform: none;                      /* comp: all-caps is literal copy */
}

.vc-home h1, .vc-home h2, .vc-home h3, .vc-home h4 {
	font-weight: 400;                          /* comp: 400 at every level     */
	color: var(--vc-ink);
	margin: 0 0 0.4em;
}
.vc-home h1 { font-size: var(--vc-h1); line-height: 1.00; }  /* 50/50 in comp */
.vc-home h2 { font-size: var(--vc-h2); line-height: 1.30; }
.vc-home h3 { font-size: var(--vc-h3); line-height: 1.30; }
.vc-home h4 { font-size: var(--vc-h4); line-height: 1.30; }
/* Body copy is 16/1.6 in the comp (= --vc-body), but the parent theme's own
 * paragraph rule computes 17px/27.2 and BEATS the inherited font-size set on
 * .vc-home above — inheritance loses to any direct rule on <p>. Declaring the
 * size on the element itself here restores the comp value at class specificity
 * (0,1,1); no !important needed. If a future theme rule outranks this, escalate
 * specificity (e.g. .vc-home .vc-section p) rather than reaching for !important. */
.vc-home p  { margin: 0 0 1em; font-size: var(--vc-body); line-height: 1.6; }

/* Images are hard-edged and un-shadowed, like the comp. */
.vc-home img { max-width: 100%; height: auto; border-radius: var(--vc-radius); box-shadow: var(--vc-shadow); }

/* ---------------------------------------------------------------------------
 * 3. LAYOUT
 * ------------------------------------------------------------------------ */
.vc-home .vc-wrap {
	max-width: var(--vc-maxw);
	margin-inline: auto;
	padding-inline: var(--vc-gutter);
}
.vc-home .vc-section { padding-block: var(--vc-section-y); }

/* Alternating bands + the two full-bleed dark breaks from the comp. */
.vc-home .vc-section--alt   { background: var(--vc-bg-alt); }
.vc-home .vc-section--olive { background: var(--vc-olive); color: var(--vc-bg-alt); }
.vc-home .vc-section--teal  { background: var(--vc-teal-light); color: var(--vc-bg-alt); }
.vc-home .vc-section--olive :is(h1,h2,h3,h4),
.vc-home .vc-section--teal  :is(h1,h2,h3,h4) { color: var(--vc-bg-alt); }

/* Content is left-biased inside the container, not centred — in the comp the
 * treatments text column stops at ~67% of the container width. */
.vc-home .vc-measure { max-width: 67%; }
@media (max-width: 900px) { .vc-home .vc-measure { max-width: 100%; } }

/* ---------------------------------------------------------------------------
 * 4. HERO
 * ------------------------------------------------------------------------ */
.vc-home .vc-hero {
	position: relative;
	/* Comp uses a flat 900px. Ours reads oversized at that height because our
	 * hero carries only an h1 + one lede line, where the comp's is a taller
	 * composition. Scaled to the viewport with a floor and ceiling instead, so
	 * it stays generous on a laptop without dominating a large desktop. */
	height: clamp(520px, 68vh, 720px);
	min-height: clamp(520px, 68vh, 720px);
	display: flex;
	align-items: flex-end;                     /* H1 sits lower-middle         */
	overflow: hidden;
	background: #000;                          /* scrim base                   */
}
.vc-home .vc-hero__media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 50%;
	/* Comp measured 0.51 over solid black (~49% flat scrim). We deliberately run
	 * DARKER: the comp's hero photo is low-key, ours (VISTA-CLINIC1.png) is a
	 * high-key shot with bright skin tones, and white text over it at 0.51
	 * failed legibility — verified in .playwright-mcp/h26-hero.jpeg at 1440x900.
	 * 0.42 restores contrast without flattening the image. TUNE: raise toward
	 * 0.51 if a darker hero photo replaces this one. */
	opacity: 0.42;
}
.vc-home .vc-hero__inner {
	/* Uses .vc-wrap, so the copy sits on the SAME left edge and max-width as
	 * every section below — it was reading as "offset" because the 22%
	 * bottom padding was tuned for the old 900px hero and pushed the block low
	 * and away from the optical centre once the hero shrank to ~612px. */
	position: relative;                        /* above the scrim              */
	width: 100%;
	padding-bottom: clamp(24px, 6%, 72px);
	text-align: left;
}
.vc-home .vc-hero h1 { color: #fff; max-width: 938px; }  /* comp wrap width   */
.vc-home .vc-hero__lede {
	color: var(--vc-cream-warm);
	font-size: var(--vc-lede);
	line-height: 1.6;
	margin-top: 1.6em;                         /* subhead sits +122px below h1 */
	max-width: 60ch;
}

/* --- The signature move: hero pins, next section scrolls over it. -----------
 * Comp measured: hero rect.top 159px @scroll0 -> 30px @scroll900, then holds.
 * The following section has a TRANSPARENT background so its card floats over
 * the still-pinned hero photo.
 *
 * FRAGILE. `position: sticky` dies if ANY ancestor has overflow:hidden/auto or
 * a transform. That is exactly why this is done on a Gutenberg template we
 * control rather than inside an Elementor Section. If the pin does not engage,
 * inspect ancestors of .vc-hero first — do not add z-index and hope.
 * Disabled under prefers-reduced-motion and on small screens.        */
@media (min-width: 901px) and (prefers-reduced-motion: no-preference) {
	.vc-home .vc-hero { position: sticky; top: 30px; }
	.vc-home .vc-section--overlaps { position: relative; z-index: 1; background: transparent; }
}

@media (max-width: 900px) {
	/* Comp uses a full 100vh hero at 390px. We use 88svh instead, for two
	 * reasons verified on an iPhone 17 (402x874) capture:
	 *   1. The consent banner is fixed to the bottom and covers ~300px, so at
	 *      100vh with bottom-anchored text the H1 and subhead were COMPLETELY
	 *      hidden on first paint — the page appeared to have no headline.
	 *   2. svh (small viewport height) avoids the iOS Safari 100vh bug where
	 *      the dynamic URL bar makes the hero taller than the visible area.
	 * Text is vertically centred rather than bottom-anchored so it clears the
	 * banner, and the 12svh remainder lets the next section peek to cue scroll. */
	/* 88svh left only ~22px of the next section visible on a phone, so the hero
	 * read as a full-screen wall with no cue to scroll. 62svh keeps the H1 and
	 * subhead comfortable while showing a clear slice of what follows.
	 * Measured at 402x874: 769px -> ~542px, next-section peek 25px -> ~250px. */
	.vc-home .vc-hero        { height: 62svh; min-height: 420px; align-items: center; }
	.vc-home .vc-hero__inner { text-align: center; padding-bottom: 0; }
	.vc-home .vc-hero h1     { margin-inline: auto; }
	.vc-home .vc-hero__lede  { margin-inline: auto; font-size: 16px; line-height: 1.35; }
	/* The subject's face sits right-of-centre in a 16:9 source; a 50% centre
	 * crop into a tall portrait viewport cut it out entirely and left only
	 * neck/shoulder. Bias the crop toward the face. */
	.vc-home .vc-hero__media { object-position: 68% 42%; }
}

/* Browsers without svh support fall back to vh — same intent, minor iOS drift. */
@supports not (height: 88svh) {
	@media (max-width: 900px) {
		.vc-home .vc-hero { height: 62vh; min-height: 420px; }
	}
}

/* ---------------------------------------------------------------------------
 * 5. BUTTONS
 * ------------------------------------------------------------------------ */
.vc-home .vc-btn {
	display: inline-block;
	padding: 8px 15px;                         /* comp exact                   */
	border: 0;
	border-radius: var(--vc-radius);           /* square — comp exact          */
	box-shadow: var(--vc-shadow);
	background: var(--vc-teal);
	color: #fff;
	font-size: 15px;
	line-height: 24px;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .4s ease, border-color .4s ease;  /* comp exact */
}
.vc-home .vc-btn:hover,
.vc-home .vc-btn:focus-visible { background: var(--vc-teal-hover); color: #fff; }

/* Secondary / ghost — the one pill in the comp. */
.vc-home .vc-btn--ghost {
	background: transparent;
	border: 1px solid var(--vc-olive);
	border-radius: var(--vc-radius-pill);
	color: var(--vc-olive);
	font-size: 14px;
}
.vc-home .vc-btn--ghost:hover,
.vc-home .vc-btn--ghost:focus-visible { background: var(--vc-olive); color: var(--vc-bg-alt); }

/* Large CTA ("BOOK YOUR FREE CONSULTATION" = 24.75/39.6 in the comp). */


/* WhatsApp keeps its channel identity (brand green) rather than the teal fill —
 * consistent with vc-blocks.css and the project's WhatsApp-primary CTA policy. */



/* --- Buttons on the dark full-bleed bands ------------------------------------
 * The default .vc-btn fill IS --vc-teal, and the contact band background is
 * ALSO --vc-teal, so an unmodified button renders teal-on-teal and disappears.
 * Same trap on the olive band, where .vc-btn--ghost's olive border/label vanish.
 * Caught in .playwright-mcp/h26-full3.jpeg. Invert both to the band's light ink.
 * WhatsApp is excluded — its brand green must stay recognisable everywhere. */
/* :not(.vc-btn--ghost) is load-bearing. Without it this rule (specificity
 * 0,4,0) beat the ghost rule (0,3,0) and painted "Results & testimonials"
 * solid cream — identical to the Solid button beside it, two different
 * actions rendered the same. */
.vc-home .vc-section--teal .vc-btn:not(.vc-btn--ghost),
.vc-home .vc-section--olive .vc-btn:not(.vc-btn--ghost) {
	background: var(--vc-bg-alt);
	color: var(--vc-olive);
}
.vc-home .vc-section--teal .vc-btn:hover,
.vc-home .vc-section--teal .vc-btn:focus-visible,
.vc-home .vc-section--olive .vc-btn:hover,
.vc-home .vc-section--olive .vc-btn:focus-visible {
	background: #fff;
	color: var(--vc-olive);
}
.vc-home .vc-section--teal .vc-btn--ghost,
.vc-home .vc-section--olive .vc-btn--ghost {
	background: transparent;
	border-color: var(--vc-bg-alt);
	color: var(--vc-bg-alt);
}
.vc-home .vc-section--teal .vc-btn--ghost:hover,
.vc-home .vc-section--teal .vc-btn--ghost:focus-visible,
.vc-home .vc-section--olive .vc-btn--ghost:hover,
.vc-home .vc-section--olive .vc-btn--ghost:focus-visible {
	background: var(--vc-bg-alt);
	color: var(--vc-olive);
}

/* Focus ring must stay visible on the dark bands too. */
.vc-home .vc-section--teal a:focus-visible,
.vc-home .vc-section--olive a:focus-visible { outline-color: var(--vc-bg-alt); }

/* Visible focus ring — the comp has none, which is an a11y defect we do not copy. */
.vc-home a:focus-visible,
.vc-home .vc-btn:focus-visible { outline: 2px solid var(--vc-teal-deep); outline-offset: 3px; }

/* ---------------------------------------------------------------------------
 * 6. TREATMENT CARDS
 * ------------------------------------------------------------------------ */
.vc-home .vc-cards {
	/* Overrides core's .wp-block-columns flex layout. auto-fit means the SAME
	 * markup gives 4 columns at 1440, 2 at 820 (iPad Air 11) and 1 at 402
	 * (iPhone 17) with no orphan rows — the hard-coded rows-of-3 it replaced
	 * left a lone card and a large gap at tablet width. */
	display: grid !important;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: clamp(20px, 2.5vw, 40px);
}
.vc-home .vc-card img {
	width: 100%;
	aspect-ratio: 332 / 380;                   /* comp desktop 0.87 portrait   */
	object-fit: cover;
}
@media (max-width: 900px) {
	.vc-home .vc-card img { aspect-ratio: 349 / 338; }  /* comp mobile ~1.03   */
}
.vc-home .vc-card h4 { margin-top: 0.8em; }

/* ---------------------------------------------------------------------------
 * 7. SCROLL REVEAL
 * Comp uses fade + 0.95->1 scale on enter. Progressive enhancement: elements
 * are only hidden once JS adds .vc-reveal-ready, so a JS failure leaves the
 * page fully readable rather than blank.
 * ------------------------------------------------------------------------ */
/* PREFERRED PATH — native CSS scroll-driven animations (Chrome/Edge 115+,
 * Safari 26+). No JS, so content can NEVER be left permanently hidden the way
 * the earlier IntersectionObserver implementation could be. Only `opacity` and
 * `scale` animate — both compositor-friendly.
 *
 * The @supports test MUST include `(animation-range: entry)`: some browsers
 * ship partial support for animation-timeline and would otherwise match.
 * `animation-timeline` is declared AFTER the `animation` shorthand, or the
 * shorthand resets it. Decorative only, so Firefox simply gets no animation. */
@media (prefers-reduced-motion: no-preference) {
	@supports ((animation-timeline: view()) and (animation-range: entry)) {
		@keyframes vc-enter {
			from { opacity: 0; scale: 0.95; }
			to   { opacity: 1; scale: 1; }
		}
		.vc-home .vc-reveal {
			animation: vc-enter auto linear both;
			animation-timeline: view();
			animation-range: entry 0% entry 55%;
		}
	}
}

/* FALLBACK — only for browsers without scroll-driven animation support
 * (currently Firefox). The `vc-reveal-ready` class is added by JS ONLY after it
 * has confirmed the lack of support AND attached an observer, and a failsafe
 * timer reveals everything regardless. See page-home.php. */
.vc-home.vc-reveal-ready .vc-reveal {
	opacity: 0;
	transform: scale(0.95);
	transition: opacity .6s ease, transform .6s ease;
}
.vc-home.vc-reveal-ready .vc-reveal.is-visible { opacity: 1; transform: scale(1); }

@media (prefers-reduced-motion: reduce) {
	.vc-home.vc-reveal-ready .vc-reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------------------------------------------------------------------------
 * 8. ACCENT + WEIGHT (closing the gap to the comp)
 * ------------------------------------------------------------------------ */
/* The comp's single Cinzel moment — the offer-card heading. */
.vc-home .vc-accent {
	font-family: var(--vc-font-accent) !important;
	/* Comp renders this at 67.5px, but in the comp it is a full-width display
	 * heading; ours sits inside a 453px card, where 67.5px breaks "CONSULTATION"
	 * mid-word. Sized to the container, not to the comp. Verified h26-p2.jpeg. */
	font-size: clamp(26px, 2.4vw, 44px);
	overflow-wrap: break-word;
	line-height: 1.2;
	color: var(--vc-olive);
}

/* Comp primary CTA is 399x50 — ours were visibly undersized at 8px/15px. */
.vc-home .vc-btn { min-width: 220px; padding: 13px 28px; font-size: 16px; }
.vc-home .vc-btn--ghost { min-width: 0; padding: 10px 22px; }

/* Comp section rhythm is far looser than a normal WP page; the emptiness read
 * came from cards sitting too close together, not from too little copy. */
.vc-home .vc-cards { gap: clamp(24px, 2.6vw, 40px); margin-block: clamp(20px, 2vw, 32px); align-items: start; }
.vc-home .vc-section h2 { margin-bottom: 0.8em; }
.vc-home .vc-section h3 { margin-top: 1.6em; }

/* Card images — comp uses 0.87 portrait desktop, ~square mobile, radius 0. */
.vc-home .vc-card-img img,
.vc-home .wp-block-column > figure.wp-block-image img {
	width: 100%;
	aspect-ratio: 332 / 380;
	object-fit: cover;
	margin-bottom: 0.9em;
}
@media (max-width: 900px) {
	.vc-home .vc-card-img img,
	.vc-home .wp-block-column > figure.wp-block-image img { aspect-ratio: 349 / 338; }
}
.vc-home .wp-block-column > figure.wp-block-image { margin: 0; }
.vc-home .vc-cards > .wp-block-column { flex-basis: auto !important; margin: 0 !important; }

/* Card headings: link colour should read as text, not default blue. */
.vc-home .vc-cards h4 a { color: inherit; text-decoration: none; }
.vc-home .vc-cards h4 a:hover { color: var(--vc-teal-deep); text-decoration: underline; }
.vc-home .vc-section--olive .vc-cards h4 a:hover,
.vc-home .vc-section--teal .vc-cards h4 a:hover { color: #fff; }

/* ---------------------------------------------------------------------------
 * 9. COMP PARITY — media rows, nurses, testimonials, CTA band
 * Added after a full top-to-bottom read of the comp (2026-07-26). The comp's
 * treatments block is NOT a card grid: it is 3 stacked image-left/text-right
 * rows, one per CATEGORY, each with its own CTA. Ours was a 25-item directory,
 * which is why it read thin despite having more content.
 * ------------------------------------------------------------------------ */
.vc-home .vc-eyebrow {
	font-size: 14px;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--vc-ink-soft);
	margin-bottom: .6em;
}
.vc-home .vc-section--olive .vc-eyebrow,
.vc-home .vc-section--teal .vc-eyebrow { color: var(--vc-bg-alt); opacity: .85; }

/* --- Classic-theme group wrapper (ROOT CAUSE, confirmed by DOM inspection
 * 2026-07-26) ----------------------------------------------------------------
 * A core group block rendered by a CLASSIC theme (medcity is one) emits an extra
 * layout wrapper:
 *     <div class="wp-block-group vc-media-row">
 *       <div class="wp-block-group__inner-container"> figure + text group </div>
 *     </div>
 * so `display: grid` on .vc-media-row saw exactly ONE child. Everything stacked
 * inside column 1 (measured 493px) and the right-hand 690px rendered empty. The
 * same collapse hit .vc-quotes.
 *
 * `display: contents` erases the wrapper's own box so its children become real
 * grid items of the row. Apply it ONLY to these layout-only wrappers: any
 * element that needs a box of its own (background, border, padding — e.g. the
 * text cell below, or the .vc-quotes cards) must NEVER get display: contents. */
.vc-home .vc-media-row > .wp-block-group__inner-container,
.vc-home .vc-quotes > .wp-block-group__inner-container { display: contents; }

/* Image-left / text-right rows. The comp does NOT alternate — all three rows
 * are image-left — so there is deliberately no --flip rule here (see note at
 * the end of this block). Always image-first on mobile too. */
.vc-home .vc-media-row {
	display: grid;
	/* Comp geometry @1440: image column is a FIXED 332px, gutter 135px, text
	 * takes the remainder. A fixed track (rather than the old 5fr/7fr) is what
	 * makes the portrait crop land at exactly 332x380 with the aspect-ratio
	 * below — a fractional track drifted with viewport width. */
	grid-template-columns: 332px 1fr;
	column-gap: 135px;
	/* stretch, not center: the text cell must be as tall as the image so its
	 * border-block hairlines align with the image's top and bottom edges. */
	align-items: stretch;
	/* Comp border-to-border gap between rows is 56px; ours measured 144px. */
	margin-block: 0 56px;
}
/* Descendant, not child: after display:contents above the figure is a grandchild
 * of .vc-media-row in the DOM even though it is a grid item in the box tree, so
 * `>` no longer matches it. */
.vc-home .vc-media-row figure,
.vc-home .vc-media-row .wp-block-image { margin: 0; }
.vc-home .vc-media-row img {
	width: 100%;
	aspect-ratio: 332 / 380;      /* comp portrait crop -> 332x380 exactly */
	object-fit: cover;
}

/* The text cell is the row's second grid item: a bare inner group block. Match
 * it by .wp-block-group, which can never hit the figure (figures carry
 * .wp-block-image or .vc-ba, never .wp-block-group). */
.vc-home .vc-media-row .wp-block-group {
	/* The comp draws a 1px dark hairline ABOVE and BELOW each row, running from
	 * the text's left edge to the container's right edge. That is a border on
	 * the TEXT CELL, not on the row — a row border would also run under the
	 * image. With align-items: stretch the two rules sit level with the image
	 * top/bottom. */
	/* border-TOP only. border-block drew both edges, so row N's bottom rule sat
	 * directly above row N+1's top rule and rendered as a DOUBLE hairline. The
	 * final row gets its closing rule added back explicitly below. */
	border-top: 1px solid #2e2e2e;
	padding-top: 29px;            /* comp rule-to-title distance */
}
/* :last-of-type is unreliable here (the rows are not the only element type
 * among their siblings), so close the section on the last row explicitly. */
.vc-home .vc-media-row:nth-last-of-type(1) .wp-block-group,
.vc-home .vc-media-row:last-child .wp-block-group {
	border-bottom: 1px solid #2e2e2e;
	padding-bottom: 29px;
}
/* Comp measures paragraphs at 434px and titles at 444px, so the copy is capped
 * at 450px while the CELL stays full-width — otherwise the hairline would stop
 * short of the container edge. Two selectors cover both render shapes: the
 * classic-theme inner container when it exists, and the block children directly
 * if a future theme drops the wrapper. */
.vc-home .vc-media-row .wp-block-group > .wp-block-group__inner-container,
.vc-home .vc-media-row .wp-block-group > :is(h3, p) { max-width: 450px; }
/* §8 sets `.vc-home .vc-section h3 { margin-top: 1.6em }` = 48.6px at the
 * 30.375px h3, which fights the comp's 29px rule-to-title spacing above. Same
 * specificity (0,2,1), declared later, so it wins without !important. */
.vc-home .vc-media-row h3 { margin-top: 0; }

@media (max-width: 900px) {
	.vc-home .vc-media-row { grid-template-columns: 1fr; gap: 20px; }
	.vc-home .vc-media-row img { aspect-ratio: 349 / 338; }
}
/* ⚠️ .vc-media-row--flip IS DELETED ON PURPOSE. The comp does not alternate;
 * every row is image-left. The old flip rule was inert only because the grid
 * was collapsed — the moment display:contents above promotes the real grid
 * items, `order: 2` would have ACTIVATED for the first time and flipped row 2
 * away from the comp. Do not reinstate it; the --flip class may still sit in
 * the markup (build_home.py) and is now purely a no-op hook. */

/* Comp CTA under each category is a full-width teal bar, label 15px/24
 * (§8's global .vc-btn 16px is one notch too large here). */
.vc-home .vc-media-row .vc-btn { display: block; width: 100%; margin-top: 1.4em; font-size: 15px; }
@media (min-width: 901px) { .vc-home .vc-media-row .vc-btn { max-width: 400px; } }
@media (max-width: 900px) {
	/* On mobile the comp CTA is content-width (~215x40) and left-aligned, NOT a
	 * full-width bar. Same specificity as the rule above but declared later, so
	 * it overrides cleanly; min-width: 0 is needed to defeat §8's 220px floor. */
	.vc-home .vc-media-row .vc-btn {
		display: inline-block;
		width: auto;
		min-width: 0;
		padding: 8px 18px;
		font-size: 15px;
	}
}

/* Treatments H2 sits 46px above the first row's hairline in the comp (§8's
 * generic 0.8em is ~35px). Scoped with :has() to the wrap that actually
 * contains the media rows so no other section's H2 moves. Specificity 0,3,1
 * beats §8's `.vc-home .vc-section h2` (0,2,1). Browsers without :has()
 * (none current) simply keep the 0.8em — a graceful, non-breaking fallback. */
.vc-home .vc-wrap:has(> .vc-media-row) > h2 { margin-bottom: 46px; }

/* Inline treatment links keep the 25 destinations without the directory look. */
.vc-home .vc-inline-links { font-size: 15px; color: var(--vc-ink-soft); }
.vc-home .vc-inline-links a { color: var(--vc-teal-deep); text-decoration: none; }
.vc-home .vc-inline-links a:hover { text-decoration: underline; }

/* MEET OUR NURSES */
.vc-home .vc-quote {
	border: 0;
	margin: 0 0 1.2em;
	padding: 0;
	font-size: clamp(20px, 1.9vw, 34px);
	line-height: 1.45;
}
.vc-home .vc-byline { font-size: 15px; letter-spacing: .06em; text-transform: uppercase; }

/* Testimonials */
.vc-home .vc-quotes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: clamp(24px, 2.6vw, 40px);
	align-items: start;
}
/* The card styling must land on the real grid items. Since the classic-theme
 * .wp-block-group__inner-container above is display:contents (no box, so a
 * background/padding on it would simply be dropped), match the items either way:
 * direct children when there is no wrapper, grandchildren when there is. */
.vc-home .vc-quotes > *:not(.wp-block-group__inner-container),
.vc-home .vc-quotes > .wp-block-group__inner-container > * {
	background: var(--vc-bg);
	padding: clamp(24px, 2.2vw, 36px);
	border-radius: var(--vc-radius);
}
.vc-home .vc-section--alt .vc-quotes > *:not(.wp-block-group__inner-container),
.vc-home .vc-section--alt .vc-quotes > .wp-block-group__inner-container > * { background: #fff; }
.vc-home .vc-stars { color: #d9a441; letter-spacing: .16em; font-size: 18px; }
.vc-home .vc-quotes cite { display: block; font-style: normal; font-weight: 600; margin-top: .8em; }

/* Full-bleed CTA band with a background photo. */
.vc-home .vc-cta-band {
	position: relative;
	min-height: 420px;
	display: grid;
	place-items: center;
	text-align: center;
	overflow: hidden;
	background: var(--vc-olive);
}
/* The img is nested TWICE: .wp-block-group__inner-container > figure > img.
 * The old `> img` child selector matched nothing, so the photo stayed in flow
 * and the band grew to 995px with the caption BELOW the picture instead of over
 * it. Un-box both wrappers so the img can be positioned against the band. */
.vc-home .vc-cta-band > .wp-block-group__inner-container,
.vc-home .vc-cta-band figure.wp-block-image { display: contents; }
.vc-home .vc-cta-band img {
	position: absolute; inset: 0; width: 100%; height: 100%;
	object-fit: cover; opacity: .55;
}
.vc-home .vc-cta-band .vc-wrap { position: relative; }
.vc-home .vc-cta-band p { color: #fff; font-size: clamp(22px, 2.4vw, 44px); line-height: 1.3; }

/* --- Before/after pair with conditional credit -----------------------------
 * Used for the Profhilo row. The credit is a CONDITION OF USE on these
 * third-party clinical images, so it is never removed — only visually de-
 * emphasised where a pointer exists to reveal it. It is always present in the
 * DOM (screen readers), always burnt into the pixels (the crop preserves it),
 * and always visible on touch devices where hover does not exist. */
/* Crossfade, not a stack. Stacking gave each image its own 332x380 slot and
 * made this row ~760px of media against the sibling rows' 380px — the client
 * reported it dominated the section. One slot, the two states alternating on a
 * timer, restores the row to sibling height AND keeps both states visible.
 *
 * 8s cycle = 4s per state (long enough to read the change, short enough that a
 * visitor sees both without waiting). Only `opacity` animates, so the work
 * stays on the compositor.
 *
 * The burnt-in "Courtesy of..." line has been CROPPED OUT of these files — the
 * credit is now carried solely by the .vc-credit figcaption below, which is
 * real text and legible at any scale. Do not re-introduce a crop that relies on
 * the pixels for attribution.
 *
 * prefers-reduced-motion: no animation. Both images are shown side by side
 * instead, because showing only the "after" state would misrepresent a result. */
.vc-home .vc-ba {
	position: relative;
	display: grid;
	grid-template-columns: 1fr;
	margin: 0;
	/* IDENTICAL BOX to the other two rows: 332x380. The attribution is removed
	 * by OVERFLOW, not by the box aspect — the img below is sized to 107% height
	 * and top-anchored, so its bottom 6.5% (the 48px burnt-in credit band on a
	 * 738px-tall source) falls outside this box and is clipped. That keeps all
	 * three media boxes the same size while still hiding the credit.
	 * Cropping in the FILE is not an option: `sips` only crops from the centre,
	 * which ate the left edge of the "Before" label. */
	aspect-ratio: 332 / 380;
	overflow: hidden;
}
.vc-home .vc-ba img {
	grid-area: 1 / 1;                  /* both images occupy the same cell */
	align-self: start;                 /* pin to the top so the overflow is at the bottom */
	width: 100%;
	height: 107%;                      /* 738/690 — pushes the credit band out of the box */
	object-fit: cover;
	object-position: left top;         /* left: never clip the "Before"/"After" label */
}
@media (prefers-reduced-motion: no-preference) {
	@keyframes vc-ba-fade {
		0%, 44%   { opacity: 1; }
		50%, 94%  { opacity: 0; }
		100%      { opacity: 1; }
	}
	.vc-home .vc-ba img:first-of-type { animation: vc-ba-fade 8s ease-in-out infinite; }
	.vc-home .vc-ba img:last-of-type  { opacity: 1; }   /* sits underneath */
	.vc-home .vc-ba img:first-of-type { position: relative; z-index: 1; }
}
@media (prefers-reduced-motion: reduce) {
	.vc-home .vc-ba { grid-template-columns: 1fr 1fr; gap: 6px; aspect-ratio: auto; }
	.vc-home .vc-ba img { grid-area: auto; }
}

.vc-home .vc-credit {
	position: static;
	margin: 0;
	padding: 6px 0 0;
	background: none;
	color: var(--vc-ink-soft);
	font-size: 13px;
	line-height: 1.4;
	text-align: left;
	opacity: 1;
}

/* ---------------------------------------------------------------------------
 * 10. BUTTON SYSTEM — one shape, one size, three fills.
 *
 * Audit 2026-07-26 found four inconsistent treatments in play: teal fill,
 * cream fill (dark-band inversion), a 999px PILL on .vc-btn--ghost, and
 * WhatsApp green. Shape and size are now invariant across every button on the
 * page; ONLY the fill varies, and only for a reason:
 *   primary   = teal fill        (default action)
 *   secondary = transparent + 1px border of the current ink
 *   whatsapp  = brand green      (channel affordance, deliberately kept)
 * On the dark olive/teal bands the primary inverts to cream-on-olive purely
 * for contrast — same box, same radius, same metrics.
 * Radius is 0 everywhere: the comp's census showed radius 0 on effectively
 * every element, and the lone pill was the outlier we had over-generalised.
 * ------------------------------------------------------------------------ */
.vc-home .vc-btn,
.vc-home .vc-btn--ghost,
.vc-home .vc-btn--whatsapp,
.vc-home .vc-btn--lg {
	border-radius: 0;                 /* kills the 999px pill — no exceptions */
	min-width: 220px;
	padding: 13px 28px;
	font-size: 15px;
	line-height: 24px;
	border-width: 1px;
	border-style: solid;
	box-sizing: border-box;
	vertical-align: middle;
}
/* Primary keeps a border so its box matches the outlined secondary exactly. */
.vc-home .vc-btn { border-color: var(--vc-teal); }
.vc-home .vc-btn:hover,
.vc-home .vc-btn:focus-visible { border-color: var(--vc-teal-hover); }

.vc-home .vc-btn--ghost { border-color: var(--vc-olive); min-width: 220px; }



/* Dark bands: inverted fill, identical box. */
.vc-home .vc-section--teal .vc-btn:not(.vc-btn--ghost),
.vc-home .vc-section--olive .vc-btn:not(.vc-btn--ghost) { border-color: var(--vc-bg-alt); }
.vc-home .vc-section--teal .vc-btn--ghost,
.vc-home .vc-section--olive .vc-btn--ghost { border-color: var(--vc-bg-alt); }

/* The large booking CTA is the ONE size exception — it is the page's primary
 * conversion action and the comp renders it markedly larger (24.75/39.6). */
/* --lg folded into Solid: TWO button styles only. The booking CTA keeps its
 * emphasis from placement (sole button in a full-bleed band), not from size.
 * Class kept in markup as an inert hook. */
.vc-home .vc-btn--lg { font-size: 15px; padding: 13px 28px; min-width: 220px; }

/* Buttons sitting next to each other should not touch. */
.vc-home .vc-btn + .vc-btn { margin-left: 10px; }
@media (max-width: 600px) {
	.vc-home .vc-btn { display: block; width: 100%; min-width: 0; }
	.vc-home .vc-btn + .vc-btn { margin-left: 0; margin-top: 10px; }
}

/* ---------------------------------------------------------------------------
 * 11. REVIEW CARDS — equal height.
 * `align-items: start` sized every card to its own copy, so three reviews of
 * different lengths produced three different box heights (one near-square, two
 * rectangles). Stretch makes the row uniform; the flex column pins the citation
 * to the bottom so the star rows and names align across cards.
 * ------------------------------------------------------------------------ */
.vc-home .vc-quotes { align-items: stretch; }
.vc-home .vc-quotes > *:not(.wp-block-group__inner-container),
.vc-home .vc-quotes > .wp-block-group__inner-container > * {
	display: flex;
	flex-direction: column;
	height: 100%;
}
.vc-home .vc-quotes cite { margin-top: auto; padding-top: .8em; }
.vc-home .vc-stars { margin-bottom: .4em; }

/* ---------------------------------------------------------------------------
 * 12. PARALLAX on the booking band (native scroll-driven animation).
 * Per modern-web-guidance/parallax-scroll-effects: wrapper carries the
 * view-timeline and clips overflow; the layer animates transform only, so the
 * work stays on the compositor. Feature-detected with the mandatory
 * `(animation-range: entry)` term, and gated on prefers-reduced-motion.
 * Firefox simply gets a static background — the effect is decorative, so per
 * the guidance we add NO polyfill and NO JS fallback.
 * The image is oversized to 130% and offset so the translate never exposes an
 * edge at either end of the range.
 * ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
	@supports ((animation-timeline: view()) and (animation-range: entry)) {
		@keyframes vc-parallax {
			from { transform: translateY(-11%); }
			to   { transform: translateY(11%); }
		}
		.vc-home .vc-cta-band {
			overflow: clip;
			view-timeline: --vc-band;
		}
		.vc-home .vc-cta-band img {
			height: 130%;
			top: -15%;
			animation: vc-parallax linear both;
			animation-timeline: --vc-band;   /* AFTER the shorthand, or it resets */
			animation-range: cover 0% cover 100%;
			will-change: transform;
		}
	}
}

/* ---------------------------------------------------------------------------
 * 13. PARALLAX on ALL large banners (hero + booking band).
 *
 * Same native scroll-driven pattern as §12. TWO corrections vs the first
 * attempt, both found by measuring `animationName` on the live page:
 *   1. The selector MUST be a descendant, not a child. WordPress classic-theme
 *      group blocks wrap children in .wp-block-group__inner-container, so
 *      `.vc-cta-band > img` matched nothing and the animation silently never
 *      applied (computed animationName was "none"). Same wrapper that
 *      collapsed the treatments grid.
 *   2. The hero keeps its sticky pin; the parallax runs on the IMAGE inside it,
 *      so the two effects compose instead of fighting (sticky moves the box,
 *      the animation moves the picture within it).
 * Images are oversized 130% and offset -15% so the translate never exposes an
 * edge. Decorative, so Firefox gets a static image and we add no polyfill.
 * ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
	@supports ((animation-timeline: view()) and (animation-range: entry)) {
		.vc-home .vc-hero { view-timeline: --vc-hero; }
		.vc-home .vc-hero__media {
			height: 130%;
			top: -15%;
			animation: vc-parallax linear both;
			animation-timeline: --vc-hero;
			animation-range: cover 0% cover 100%;
			will-change: transform;
		}
	}
}

/* The reviews CTA sat flush against the last card. Centre it and give it room —
 * it is a section-closing action, not part of the card grid. */
.vc-home .vc-quotes + p,
.vc-home .vc-section--alt .vc-quotes ~ p {
	margin-top: clamp(28px, 3vw, 48px);
	text-align: center;
}

/* ---------------------------------------------------------------------------
 * 14. Offer card density.
 * The card sat in a full section's vertical padding AND carried 48px of its own
 * — roughly 260px of dead space around ~120px of content. Halve the section
 * padding here and let the card's own padding do the work.
 * ------------------------------------------------------------------------ */
.vc-home .vc-section--overlaps { padding-block: clamp(32px, 4vw, 64px); }
.vc-home .vc-offer-card { padding: clamp(28px, 2.6vw, 40px) !important; }
.vc-home .vc-offer-card .vc-eyebrow { margin-bottom: .35em; }
.vc-home .vc-offer-card h2 { margin-bottom: .35em; }
.vc-home .vc-offer-card p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------------------
 * 15. Distinct band per section — no two adjacent sections share a background.
 *   hero      photograph
 *   treatments  #ffffff  white
 *   about+nurses #282e20 olive (dark)
 *   reviews     #f2f1ee  cream
 *   contact     #6c9f9a  light teal (dark-on-light text inverted)
 * The primary button fill (#315450) is deliberately NOT used as a section
 * background, so buttons never sit on their own colour.
 * ------------------------------------------------------------------------ */
.vc-home .vc-hero + .vc-section { background: #ffffff; }

/* The hero CTA (folded-in intro offer) sits on the photograph. */
.vc-home .vc-hero .vc-btn { margin-top: 1.6em; }

/* Contact section now carries the interior photo the retired band used. Same
 * classic-theme wrapper un-boxing as .vc-cta-band, or the img renders in flow
 * and pushes the content down (the 995px bug). */
.vc-home .vc-section--photo { position: relative; overflow: clip; }
.vc-home .vc-section--photo > .wp-block-group__inner-container,
.vc-home .vc-section--photo figure.wp-block-image { display: contents; }
.vc-home .vc-section--photo img {
	position: absolute; inset: 0; width: 100%; height: 130%; top: -15%;
	object-fit: cover; opacity: .22;
}
.vc-home .vc-section--photo > .vc-wrap,
.vc-home .vc-section--photo .vc-wrap { position: relative; z-index: 1; }
@media (prefers-reduced-motion: no-preference) {
	@supports ((animation-timeline: view()) and (animation-range: entry)) {
		.vc-home .vc-section--photo { view-timeline: --vc-contact; }
		.vc-home .vc-section--photo img {
			animation: vc-parallax linear both;
			animation-timeline: --vc-contact;
			animation-range: cover 0% cover 100%;
		}
	}
}

/* Row 3's figure measured 383px against the other two at 380px: the <img> is
 * inline by default, so the line-box descender added ~3px under it. display:block
 * removes that gap and makes all three media boxes byte-identical. */
.vc-home .vc-media-row figure img,
.vc-home .vc-ba img { display: block; }
.vc-home .vc-media-row figure { line-height: 0; }

/* Force ALL three media boxes to identical geometry. Row 3 measured 383px vs
 * 380px even after display:block, so rather than chase the extra 3px, pin the
 * figure itself to the same aspect box .vc-ba already uses. Any source ratio
 * now resolves to exactly 332x380 with the overflow cropped. */
.vc-home .vc-media-row figure {
	aspect-ratio: 332 / 380;
	overflow: hidden;
	display: block;
}
.vc-home .vc-media-row figure > img { width: 100%; height: 100%; object-fit: cover; }

/* Row 3's <img> resolved to 334.609px and dragged its figure to 335x383 while
 * the other two sat at 332x380 — width:100% was resolving against something
 * fractionally wider than the grid track. Cap the figure to the track width
 * outright so no source can push the box out of alignment. */
@media (min-width: 901px) {
	.vc-home .vc-media-row figure,
	.vc-home .vc-media-row .vc-ba {
		width: 332px;
		max-width: 332px;
		height: 380px;
		justify-self: start;
	}
	.vc-home .vc-media-row figure > img { max-width: 100%; }
}

/* ---------------------------------------------------------------------------
 * 16. Regressions found on the live page (2026-07-26, late pass)
 * ------------------------------------------------------------------------ */

/* (a) The before/after credit crop was lost. `.vc-media-row figure > img`
 * (0,2,2) added later beat `.vc-ba img` (0,2,1) and reset height to 100%, so
 * the burnt-in "Courtesy of..." band came back into view. Restore the 107%
 * top-anchored overflow with a selector that outranks it. */
.vc-home .vc-media-row .vc-ba > img,
.vc-home .vc-media-row figure.vc-ba > img {
	height: 107%;
	object-position: left top;
	align-self: start;
}

/* (b) Hero copy vertically centred, not bottom-anchored. */
.vc-home .vc-hero { align-items: center; }
.vc-home .vc-hero__inner { padding-bottom: 0; }

/* (c) Parallax was applied to the hero image but invisible: the hero is
 * position:sticky, so it stays pinned in the viewport and the image has no
 * relative travel to show. Drop the pin — the comp's pinned-hero trick is a
 * different effect from parallax, and we cannot have both on one element.
 * Parallax is the one that was asked for. */
@media (min-width: 901px) {
	.vc-home .vc-hero { position: relative; top: auto; }
}

/* Supporting line under a section heading — smaller, softer, tight to the h2. */
.vc-home .vc-subhead {
	font-size: clamp(17px, 1.35vw, 26px);
	line-height: 1.5;
	color: var(--vc-ink-soft);
	max-width: 46ch;
	margin-top: -0.4em;
}
.vc-home .vc-section--olive .vc-subhead,
.vc-home .vc-section--teal .vc-subhead { color: var(--vc-bg-alt); opacity: .9; }

/* Hero parallax range. `cover` is wrong for an element that starts at the TOP
 * of the document: at load the hero is already fully on screen, so the cover
 * timeline is ~60% elapsed before the user scrolls a pixel and only the tail is
 * usable — which reads as "no parallax". `exit` runs the whole animation across
 * the hero scrolling out of view, giving the full 612px of travel. Also widen
 * the translate so the movement is actually perceptible. */
@media (prefers-reduced-motion: no-preference) {
	@supports ((animation-timeline: view()) and (animation-range: entry)) {
		@keyframes vc-parallax-hero {
			from { transform: translateY(0); }
			to   { transform: translateY(-18%); }
		}
		.vc-home .vc-hero__media {
			animation: vc-parallax-hero linear both;
			animation-timeline: --vc-hero;
			animation-range: exit 0% exit 100%;
		}
	}
}

/* The supporting line was being pushed away from its heading: the treatments
 * H2 carries margin-bottom:46px (comp value) meant for a heading followed by
 * ROWS, not by a subtitle. Collapse the gap when a .vc-subhead follows. */
.vc-home h2:has(+ .vc-subhead) { margin-bottom: .15em !important; }
.vc-home .vc-subhead { margin-top: 0; margin-bottom: clamp(28px, 3vw, 52px); }

/* ---------------------------------------------------------------------------
 * 17. CROSSFADE FIX — .vc-ba must stay a GRID.
 * `.vc-home .vc-media-row figure { display:block }` (0,2,1), added for the
 * media-box sizing fix, outranked `.vc-home .vc-ba { display:grid }` (0,2,0).
 * With block flow the two images stopped sharing a cell and stacked vertically:
 * the second fell below the 380px overflow cut, so when the first faded out the
 * box went WHITE. Restore the grid at higher specificity and re-pin both images
 * to the same cell. DO NOT set display on .vc-media-row figure without
 * excluding .vc-ba.
 * ------------------------------------------------------------------------ */
.vc-home .vc-media-row figure.vc-ba {
	display: grid !important;
	grid-template-columns: 1fr;
	grid-template-rows: 1fr;
}
.vc-home .vc-media-row figure.vc-ba > img {
	grid-area: 1 / 1;
	align-self: start;
}
/* Keep the caption out of the image cell so it cannot be overlapped. */
.vc-home .vc-media-row figure.vc-ba > figcaption { grid-area: 2 / 1; }


/* ---------------------------------------------------------------------------
 * 19. WhatsApp gets NO special treatment.
 * Client decision 2026-07-26: one button system, no channel-specific colour.
 * `.vc-btn--whatsapp` is now an inert hook kept only so the markup does not
 * need rewriting — it inherits Solid exactly, including the cream inversion on
 * the olive/teal bands.
 *
 * This also retires the accessibility problem the test suite caught: brand
 * green #25D366 with white text was 1.98:1 (a WCAG AA failure, and the worst
 * contrast on the page). The primary fill #4A7874 is 4.96:1.
 *
 * Net effect: exactly TWO button styles on the page — Solid and Outline.
 * ------------------------------------------------------------------------ */
.vc-home .vc-btn--whatsapp {
	background: var(--vc-teal);
	border-color: var(--vc-teal);
	color: #fff;
}
.vc-home .vc-btn--whatsapp:hover,
.vc-home .vc-btn--whatsapp:focus-visible {
	background: var(--vc-teal-hover);
	border-color: var(--vc-teal-hover);
	color: #fff;
}
/* On the dark bands it inverts with everything else. */
.vc-home .vc-section--teal .vc-btn--whatsapp,
.vc-home .vc-section--olive .vc-btn--whatsapp {
	background: var(--vc-bg-alt);
	border-color: var(--vc-bg-alt);
	color: var(--vc-olive);
}

/* ---------------------------------------------------------------------------
 * 20. SUPPORT LINES — the h4 TIER, rendered by an <h3> element.
 *
 * ⚠️⚠️ THE ELEMENT IS AN <h3> AND MUST STAY ONE. DO NOT "CORRECT" IT TO <h4>.
 *
 * Both places .vc-support-line is used in pages/home-2026.html sit DIRECTLY
 * under that section's <h2>:
 *     h2 "About us"            + h3 "A medical clinic, not a beauty salon"
 *     h2 "What our clients say" + h3 "Rated 4.9 out of 5 ..."
 * An <h4> in either position would skip a heading level and fail the
 * "heading levels never skip" test in tests/home.spec.js. The smaller, lighter
 * LOOK comes entirely from this rule — change the size HERE, never the tag in
 * the markup.
 *
 * WHY THIS SHAPE: it mirrors the pattern the client already approved in the
 * footer contact band — h2 "Contact us" + h3.vc-support "Find a quiet moment to
 * care for yourself." The spec below is copied from .vc-support in
 * vc-footer.css deliberately (clamp/weight/line-height identical) so the two
 * read as one system; that file carries the same do-not-correct warning.
 *
 * SPECIFICITY: `.vc-home h3.vc-support-line` is (0,2,1) — equal to §8's
 * `.vc-home .vc-section h3 { margin-top: 1.6em }` and to §15's
 * `.vc-home .vc-section--olive :is(h1,h2,h3,h4) { color: ... }`. It is declared
 * last in the file, so it beats both on source order without !important.
 * ------------------------------------------------------------------------ */
.vc-home h3.vc-support-line {
	font-size: clamp(18px, 1.56vw, 24px);
	font-weight: 400;
	line-height: 1.4;
	color: var(--vc-ink-soft);
	margin: 0 0 1em;
}
/* On the dark bands --vc-ink-soft (#52504e) over olive (#282e20) measures
 * ~1.6:1 — unreadable. Invert to the band ink exactly as .vc-subhead does. */
.vc-home .vc-section--olive h3.vc-support-line,
.vc-home .vc-section--teal h3.vc-support-line {
	color: var(--vc-bg-alt);
	opacity: .9;
}

/* ---------------------------------------------------------------------------
 * 21. Treatment-row photos on phones/small tablets (<=900px): VISIBLE, but
 *     capped at one third of the viewport height.
 *
 * ⚠️ HISTORY, so this is not "simplified" back: an earlier pass HID these
 * photos outright (`display: none`) at <=900. The client reversed that — the
 * images stay, they just must not dominate the screen. Do not reinstate the
 * hide.
 *
 * At <=900 the row collapses to a single 1fr column, so each photo becomes a
 * full-width block between the heading and the copy. Uncapped, the 332/380
 * portrait ratio made each one ~430px tall on a 402px-wide phone — half the
 * viewport per photo. 33svh caps them at a third.
 *
 * THREE THINGS THIS RULE HAS TO GET RIGHT:
 *
 * 1. `aspect-ratio: auto` is LOAD-BEARING. §15 sets `aspect-ratio: 332/380` on
 *    these figures and §9 sets it again at <=900 (349/338). An aspect-ratio box
 *    derives its height from its width, which simply overrides max-height — the
 *    cap is silently ignored while the CSS looks correct. Clearing the ratio is
 *    what lets max-height actually bind.
 *
 * 2. `svh`, NOT `vh`. On iOS Safari `vh` is measured against the viewport with
 *    the URL bar RETRACTED, so 33vh is taller than a third of what the user can
 *    actually see. The hero (§4) already uses svh for the same reason; the
 *    @supports block below is the identical fallback for browsers without it.
 *
 * 3. `.vc-ba` (the Profhilo before/after crossfade) is one of these figures and
 *    is the fragile one. Its burnt-in "Courtesy of..." credit band is removed by
 *    OVERFLOW, not by cropping the file: the images run at height:107%,
 *    top-anchored, so the bottom 6.5% falls outside the box and is clipped.
 *    Shortening the box only ever clips MORE from the bottom, so the credit
 *    cannot come back — but `overflow: hidden` below is what guarantees it, and
 *    the img rules must not reset align-self. §16(a) and §17 pin
 *    `align-self: start` on `.vc-ba > img` at (0,3,2)/(0,3,1), both later than
 *    and/or more specific than the img rule here, so the top anchor survives.
 *    Verified at 402px: credit still cropped.
 *
 * CLASS SELECTORS ONLY — no `>` combinator. WordPress injects a
 * `.wp-block-group__inner-container` between .vc-media-row and its children, so
 * a child combinator matches nothing and the "fix" silently no-ops. That trap
 * has cost six bugs on this project; see the note above §9.
 *
 * WHY AT THE END OF THE FILE: §9's own `@media (max-width: 900px)` block sets
 * `aspect-ratio: 349/338` on these images and §15/§17 pin the figure geometry
 * later still, so anything declared earlier loses on source order. Declared
 * last, this wins without !important.
 * ------------------------------------------------------------------------ */
@media (max-width: 900px) {
	.vc-home .vc-media-row figure,
	.vc-home .vc-media-row figure.vc-ba,
	.vc-home .vc-media-row .wp-block-image {
		max-height: 33svh;
		aspect-ratio: auto;
		overflow: hidden;
	}
	/* Fill the shortened box and crop, rather than letter-boxing. height:100%
	   resolves against the max-height-constrained figure. */
	.vc-home .vc-media-row figure img,
	.vc-home .vc-media-row .wp-block-image img {
		height: 100%;
		width: 100%;
		object-fit: cover;
		object-position: center;
	}
	/* The before/after pair keeps its top anchor and its 107% overscan — that is
	   what clips the burnt-in credit. Never give these `object-position: center`
	   or `height: 100%`: either one re-exposes the attribution band. */
	.vc-home .vc-media-row figure.vc-ba > img {
		height: 107%;
		object-position: left top;
		align-self: start;
	}
}

/* Browsers without svh fall back to vh — same intent, minor iOS drift, exactly
   as the hero does in §4. */
@supports not (height: 33svh) {
	@media (max-width: 900px) {
		.vc-home .vc-media-row figure,
		.vc-home .vc-media-row figure.vc-ba,
		.vc-home .vc-media-row .wp-block-image {
			max-height: 33vh;
		}
	}
}

/* ---------------------------------------------------------------------------
 * 22. ATTRIBUTION FIX — the credit was invisible at every width.
 *
 * `.vc-ba` carried `overflow:hidden` for ONE job: cropping the burnt-in
 * "Courtesy of..." band out of the bottom of the source images. But that clip
 * also ate the `.vc-credit` figcaption sitting in grid row 2 — measured 24px
 * clipped at 1440 and 94px at 402, i.e. `capVisible: false` at both. So the
 * pixels were cropped AND the text replacement was hidden: no visible credit
 * anywhere, on images whose licence requires one.
 *
 * Decouple the two jobs. The IMAGES clip themselves via clip-path (6.63% off
 * the bottom = the same band the overflow used to remove), so the FIGURE no
 * longer needs to clip anything and the caption below it is free to render.
 * clip-path is a percentage so it holds at every viewport, including the 33svh
 * mobile cap.
 *
 * DO NOT re-add `overflow:hidden` to .vc-ba — that is what broke it.
 * ------------------------------------------------------------------------ */
.vc-home .vc-media-row figure.vc-ba {
	overflow: visible;
	aspect-ratio: auto;
	grid-template-rows: auto auto;
	height: auto;
}
.vc-home .vc-media-row figure.vc-ba > img {
	grid-area: 1 / 1;
	aspect-ratio: 332 / 380;
	height: auto;
	clip-path: inset(0 0 6.63% 0);   /* the burnt-in credit band */
	object-position: left top;
}
.vc-home .vc-media-row figure.vc-ba > .vc-credit {
	grid-area: 2 / 1;
	position: static;
	opacity: 1;
}
@media (min-width: 901px) {
	/* the generic figure height pin must not re-clamp this one */
	.vc-home .vc-media-row figure.vc-ba { height: auto; max-height: none; }
}

/* §22 follow-up: with `overflow:hidden` gone, the ≤900px cap had nothing to
 * clip against and the image grew to 48% of the viewport. Cap the IMAGE itself
 * instead of the figure — the figure then sizes to image + caption, so the
 * one-third rule holds AND the credit stays on screen. */
@media (max-width: 900px) {
	.vc-home .vc-media-row figure.vc-ba { height: auto; max-height: none; }
	/* `width: auto` (the first attempt) shrank this image to ~73% of the column
	 * while the sibling treatment photos filled 100% — visibly mismatched. Fill
	 * the width and let object-fit do the cropping instead.
	 * clip-path is switched OFF here on purpose: with `cover` + a top anchor the
	 * bottom of the source is already cropped well past the burnt-in credit
	 * band, so the extra inset would eat visible image for no reason. */
	.vc-home .vc-media-row figure.vc-ba > img {
		width: 100%;
		height: 33svh;
		max-height: 33svh;
		object-fit: cover;
		object-position: left top;
		clip-path: none;
	}
}
@supports not (height: 33svh) {
	@media (max-width: 900px) {
		.vc-home .vc-media-row figure.vc-ba > img { height: 33vh; max-height: 33vh; }
	}
}

/* ---------------------------------------------------------------------------
 * 23. MOBILE TREATMENT IMAGES — one uniform spec (client, 2026-07-27).
 * All three identical: 16:10 crop, 90% width, never more than half the screen.
 * Supersedes the 33svh cap and the per-image width rules in §21/§22 above.
 *
 * The aspect box goes on the IMAGE, not the figure: .vc-ba's figure also holds
 * the .vc-credit caption, so an aspect-ratio there would size image+caption
 * together and shrink the picture. object-position is top-left for two reasons
 * — it keeps the "Before"/"After" labels (top-left of the source) in frame, and
 * it crops from the bottom, which is where the burnt-in attribution band sits.
 * At 402px this computes to 362x226 (26% of viewport), so the 50svh ceiling is
 * a guard rail rather than the active constraint.
 * ------------------------------------------------------------------------ */
@media (max-width: 900px) {
	.vc-home .vc-media-row figure,
	.vc-home .vc-media-row .wp-block-image,
	.vc-home .vc-media-row figure.vc-ba {
		width: auto;
		max-width: none;
		height: auto;
		max-height: none;
		aspect-ratio: auto;
		overflow: visible;
	}
	.vc-home .vc-media-row img,
	.vc-home .vc-media-row figure.vc-ba > img {
		width: 90%;
		max-width: 90%;
		height: auto;
		aspect-ratio: 16 / 10;
		max-height: 50svh;
		object-fit: cover;
		object-position: left top;
		clip-path: none;          /* the 16:10 crop already removes the credit band */
		display: block;
	}
}
@supports not (height: 50svh) {
	@media (max-width: 900px) {
		.vc-home .vc-media-row img { max-height: 50vh; }
	}
}
