/* Vitalife Core: supplementary styles for patterns and layout rhythm. */

.vc-section {
	padding-block: var(--wp--custom--section--padding-block);
}

/* Below the theme's contentSize (78rem), WP's "constrained" layout has
   nothing to auto-margin against, so content runs flush to the viewport
   edge - the header and footer wrappers have the same gap since they only
   ever set padding-block inline. .vc-story is excluded: it's alignfull by
   design (the photo band should bleed edge-to-edge) and already pads its
   own text layer via .vc-story__content. */
.vc-header,
.vc-section:not(.vc-story),
.vc-footer {
	padding-inline: clamp(1.25rem, 5vw, 2.5rem);
}

/* For a section that opens the page (sitting directly under the header,
   with no hero above it) - the standard section padding leaves too much
   air between the header and the content. Only the top is tightened; the
   bottom still needs to separate this section from whatever follows. */
.vc-section--flush-top {
	padding-top: clamp(2rem, 4vw, 4rem);
}

/* Full-width sections sit flush against each other.
 *
 * Core's root layout puts `:where(.wp-site-blocks) > * { margin-block: 24px 0 }`
 * on every top-level block. Between two sections of DIFFERENT colours that gap
 * is invisible, because one background simply starts where the other stops. The
 * page background shows through it only where two sections of the SAME colour
 * meet, as a 24px stripe in the wrong colour that looks like a rendering fault.
 *
 * That went unnoticed for as long as the sections happened to alternate. It is
 * fixed here rather than by re-ordering the backgrounds, because alternating
 * correctly is a thing somebody has to keep remembering and this is a thing the
 * stylesheet does. Every section carries 112px of its own vertical padding, so
 * removing 24px between them changes the rhythm by an amount nobody can see.
 *
 * Reported by Steven on 29 August 2026, between Lifestyle & Wellbeing Education
 * and Specialist Services, the first two same-coloured sections the site has
 * ever had next to each other. */
.wp-site-blocks > .vc-section {
	margin-block-start: 0;
}

/* Page headings shrink on narrow screens, because 3.5rem does not.
 *
 * The 'huge' preset in theme.json is a flat 3.5rem, so a 56px word has to fit
 * whatever width the phone has. Every h1 on the site got away with it until the
 * Pricing page took the heading 'Learning and guidance beyond your
 * appointments': at 390px, 'appointments' is wider than the column, and the
 * browser broke it mid-word rather than overflow, printing 'appointment' and
 * then a lone 's' on the next line.
 *
 * A clamp fixes it for every heading rather than for the one that exposed it,
 * and the upper bound is the existing 3.5rem, so nothing changes on a desktop.
 * Scoped to the class rather than changed in theme.json so the design system
 * keeps one definition of 'huge' and this stays a legible exception.
 *
 * Checked against the longest word on the site at the time: 'appointments'. If
 * a longer one arrives, measure it rather than assuming this still covers it. */
@media (max-width: 781.98px) {
	.has-huge-font-size {
		/* !important matches core's own on the preset class, which is emitted as
		   .has-huge-font-size{font-size:var(--...)!important}. Without it this
		   rule loses and computes to 56px, which is how the first attempt
		   silently did nothing. Measured, not assumed. */
		font-size: clamp(2.125rem, 8.5vw, 3.5rem) !important;
	}
}

/* Two adjacent sections that render the same colour are one visual band, so
 * they get one band's worth of padding at the seam rather than two.
 *
 * Every section carries 96px top and bottom. Where the colours alternate, the
 * 192px between two blocks of content is read as a deliberate boundary, because
 * the background changes in the middle of it. Where they do not alternate there
 * is nothing to see, and the same 192px reads as a hole in the page. Steven
 * pointed at one on the homepage, between the four ways to pay and "How we can
 * help": both beige, 192px of nothing between them.
 *
 * Zeroing the top of the second leaves the first section's own bottom padding
 * as the whole seam, which is a full deliberate amount of space, not a
 * calculated fraction that will need revisiting when the padding changes.
 *
 * "Same colour" is everything-that-is-not-surface versus surface, because a
 * section with no modifier is transparent and shows the beige page background
 * through, so it and .vc-section--muted are the same colour to a reader even
 * though they are different rules. */
.vc-section--surface + .vc-section--surface,
.vc-section:not(.vc-section--surface) + .vc-section:not(.vc-section--surface) {
	padding-top: 0;
}

.vc-section--surface {
	background-color: var(--wp--preset--color--surface);
}

.vc-section--muted {
	background-color: var(--wp--preset--color--background);
}

/* Cards (service cards, testimonial cards) */
.vc-card-row {
	align-items: stretch;
}

.vc-card-row > .wp-block-column {
	display: flex;
}

.vc-card {
	/* WordPress only sets border-box on real block elements (.wp-block-group
	   and friends), so a .vc-card written as raw HTML inside a wp:html block
	   would otherwise land on the browser default of content-box and add its
	   padding and border *outside* whatever width it was given - overflowing
	   its grid track or column by exactly 50px. Explicit here so both kinds of
	   card measure the same; a no-op for the block-based ones. */
	box-sizing: border-box;
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--custom--shadow--card);
	padding: var(--wp--preset--spacing--50, 2rem);
	transition: box-shadow 0.25s ease, transform 0.25s ease;
	display: flex;
	flex-direction: column;
	width: 100%;
}

.vc-card__link {
	margin-top: auto;
	padding-top: 0.5rem;
}

.vc-card__title a {
	color: inherit;
	text-decoration: none;
}

.vc-card__title a:hover {
	text-decoration: underline;
}

/* Pricing cards: same shrink-to-fit issue as .vc-card > .vc-form (see the
   note above that rule) - a raw wp:html child of a "constrained" .vc-card
   collapses to fit-content width instead of filling it, so it needs the
   same explicit override. */
.vc-card > .vc-price-list,
.vc-card > .vc-price-poa {
	width: 100% !important;
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.vc-price-list {
	margin: 1rem 0 0;
}

.vc-price-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	padding-block: 0.6rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.vc-price-row:last-child {
	border-bottom: none;
}

.vc-price-row dt {
	color: var(--wp--preset--color--text-muted);
}

.vc-price-row dd {
	margin: 0;
	font-weight: 600;
	color: var(--wp--preset--color--primary);
	white-space: nowrap;
}

.vc-price-poa {
	margin: 1rem 0 0;
	color: var(--wp--preset--color--text-muted);
}

.vc-card:hover {
	box-shadow: var(--wp--custom--shadow--cardHover);
	transform: translateY(-2px);
}

.vc-card__title {
	font-family: var(--wp--preset--font-family--heading);
	margin-bottom: 0.5rem;
}

.vc-card__title--centered {
	text-align: center;
}

.vc-card__badge {
	display: inline-block;
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.65rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	background: color-mix(in srgb, var(--wp--preset--color--accent) 14%, transparent);
	border-radius: 999px;
	padding: 0.2rem 0.6rem;
	margin-top: 0.35rem;
}

.vc-card__link {
	font-weight: 600;
	text-decoration: none;
}

/* Same size/weight/position as .vc-card__link above (shares that class) -
   only the color changes, to read as inactive text rather than a link,
   for a card whose service isn't bookable yet. */
.vc-card__link--disabled {
	color: var(--wp--preset--color--text-muted);
}

/* Footer: theme.json's global heading/link colors override inherited
   context, so force them back to the footer's light text color. */
.vc-footer :where(h1, h2, h3, h4, h5, h6) {
	color: var(--wp--preset--color--surface);
}

.vc-footer a {
	color: var(--wp--preset--color--surface);
}

.vc-footer .wp-block-button__link {
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--charcoal);
}

.vc-footer .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--accent-soft);
	color: var(--wp--preset--color--charcoal);
}

.vc-footer a:hover {
	color: var(--wp--preset--color--accent-soft);
}

/* The footer "Book a consultation" action opens the enquiry modal via
   [data-vc-enquiry-trigger] rather than navigating, so it's a <button>, not
   an <a> - reset the native button chrome and match .vc-footer a exactly so
   it reads as an inline text link (not the accent pill .wp-block-button
   gives). */
.vc-footer__linkbtn {
	appearance: none;
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	font: inherit;
	color: var(--wp--preset--color--surface);
	text-decoration: underline;
	cursor: pointer;
}

.vc-footer__linkbtn:hover {
	color: var(--wp--preset--color--accent-soft);
}

/* Brand statement: a single emphasised line of philosophy, given its own
   full section (rather than the thin bordered strip it used to be) so it
   reads as a deliberate statement instead of fine print. The decorative
   line-art illustration sits absolutely positioned behind the text as a
   faint watermark - overflow:hidden keeps its oversized bleed contained
   within the section, and the text gets its own stacking context so it
   stays legible on top. */
.vc-brand-statement {
	position: relative;
	overflow: hidden;
}

.vc-brand-statement p {
	position: relative;
	z-index: 1;
	line-height: 1.35;
}

.vc-brand-statement__decoration {
	position: absolute;
	bottom: -3rem;
	right: -3rem;
	width: 22rem;
	max-width: none;
	margin: 0;
	opacity: 0.35;
	pointer-events: none;
	z-index: 0;
	transform: scaleX(-1);
}

/* Parallax: .vc-parallax-ready is only added by parallax.js when the visitor
   hasn't requested reduced motion, so none of this - not even the resting
   scale/overflow used to hide the reveal edge - applies unless JS is actually
   going to animate it. --vc-parallax-y is written per-frame by that script;
   it defaults to 0px so these rules are inert until then. */
.vc-parallax-ready .vc-brand-statement__decoration {
	transform: scaleX(-1) translate3d(0, var(--vc-parallax-y, 0px), 0);
}

.vc-brand-statement__decoration img {
	width: 100%;
	height: auto;
}

/* Hero: less top/bottom air than a standard .vc-section - it's the first
   thing on the page, right below the header, so it doesn't need the same
   breathing room a section further down the page uses to separate itself
   from its neighbours. Top and bottom are split (rather than a single
   padding-block) because .wp-site-blocks already adds 120.5625px of its
   own padding-top to clear the fixed header - stacking the hero's own
   top padding on top of that made the gap above the hero noticeably
   bigger than the gap below it, so the top side gets a smaller value. */
.vc-hero {
	background-color: var(--wp--preset--color--background);
	padding-top: clamp(0.5rem, 1vw, 1rem);
	padding-bottom: clamp(1rem, 2vw, 2rem);
}

/* Service pages (patterns/service-hero.php) and the Coaching page: half
   of .vc-hero's own already-reduced padding, since these heroes carry
   less content than the homepage's, and the page's real content starts
   immediately below. */
.vc-hero--compact {
	padding-block: clamp(0.5rem, 1vw, 1rem);
}

/* Coaching page hero: the text column's length varies with content
   edits, but .vc-hero__image's shared aspect-ratio (4/5, tuned for the
   homepage's tall portrait) doesn't know that - it was dictating a
   fixed height regardless, leaving the image taller than the text next
   to it. Stretching the row and letting the image fill that height
   (same technique as .vc-media-row above, scoped here instead of
   switching this image's class, so it keeps .vc-hero__image's own
   parallax hook) makes the image match the text column instead.
   align-items:stretch on the row alone doesn't do it: the
   "vertically aligned center" columns option core uses here applies
   align-self:center to each column individually (see
   .is-vertically-aligned-center), which overrides whatever the row's
   own align-items says - the actual override has to happen there. */
.vc-hero--compact .wp-block-column {
	align-self: stretch;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.vc-hero--compact .vc-hero__image {
	height: 100%;
	margin: 0;
}

.vc-hero--compact .vc-hero__image img {
	/* aspect-ratio:auto (rather than a fixed ratio) seemed like the right
	   idea for "match the text column" but backfires: flexbox resolves a
	   percentage height against an indefinite container as auto, so the
	   image's own intrinsic (tall/portrait) ratio still wins the row's
	   height calculation, and the *text* ends up stretched to match the
	   *image* instead of the reverse. A deliberately short fixed ratio
	   (matching the service pages' compact hero image) keeps the image's
	   own hypothetical height low enough that the text column is reliably
	   the taller side, so this height:100% then correctly stretches the
	   image up to meet it instead. */
	height: 100%;
	aspect-ratio: 4 / 3;
	object-position: center top;
	min-height: 14rem;
}

/* Pinned main navigation. position:sticky can show sub-pixel jitter during
   momentum/trackpad scrolling in some browsers - it's still technically
   scroll-linked right up until it hits its threshold. position:fixed has
   no such drift (it's never part of scroll-driven layout at all), but it
   takes the header out of the document flow entirely, so the page content
   needs matching top padding to avoid sliding under it - see
   .wp-site-blocks below, kept in sync with the header's actual height at
   each breakpoint (120.5625px default, 86px under the 600px breakpoint
   where the header switches to its centered-logo grid layout). */
header.wp-block-template-part {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 100;
}

.wp-site-blocks {
	padding-top: 120.5625px;
}

@media (max-width: 600px) {
	.wp-site-blocks {
		padding-top: 86px;
	}
}

.vc-header {
	background-color: var(--wp--preset--color--primary-dark);
	box-shadow: 0 1px 0 rgba(36, 49, 43, 0.08);
}

/* The hamburger icon (fill:currentColor) needs light color against the
   header's dark green background... */
.vc-header .wp-block-navigation {
	color: var(--wp--preset--color--surface);
}

/* ...but the nav's own open/overlay panel (.is-menu-open) is styled
   separately below, not the dark header bar - so only the inline,
   closed-row nav links need this rule. */
.vc-header .wp-block-navigation__responsive-container:not(.is-menu-open) a {
	color: var(--wp--preset--color--surface);
	font-size: 1rem;
}

.vc-header .wp-block-navigation__responsive-container:not(.is-menu-open) a:hover {
	color: var(--wp--preset--color--accent-soft);
}

/* Current-page nav link: aria-current="page" is set server-side (see
   inc/nav-active-link.php) since these are plain custom-URL links, not
   "Page" reference blocks WP core would mark as current-menu-item on its
   own. A soft pill on the closed/inline row, gold text in the open
   overlay - matches the translucent-white chip language already used for
   the hamburger/close buttons on this dark background. */
.vc-header .wp-block-navigation__responsive-container:not(.is-menu-open) a[aria-current="page"] {
	background-color: rgba(255, 255, 255, 0.14);
	border-radius: 999px;
	padding-inline: 0.75rem;
	margin-inline: -0.75rem;
}

/* Open mobile/tablet overlay menu: core's default is a plain white
   fullscreen sheet with small sans-serif links crammed top-right - swap
   it for a full-bleed dark panel matching the header/CTA-banner palette,
   with large centered serif links (the same heading font as every H1/H2
   on the site) and generous rhythm between them, so opening the menu
   feels like a considered part of the brand rather than a generic
   WordPress default. */
/* !important is load-bearing here: core's navigation block sets this
   overlay's background via its own equal-or-higher-specificity rule
   (white, unstyled by this theme otherwise), which otherwise wins over a
   plain class selector regardless of stylesheet order. */
.vc-header .wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--primary-dark) !important;
}

/* Every rule below is scoped to .is-menu-open explicitly - core keeps this
   same dialog/close/content markup in the DOM even in the closed, inline
   desktop row (just visually suppressed by its own layout, not removed),
   so an unscoped version of any of these rules leaks into that closed
   state too. Confirmed the hard way: an earlier unscoped version of the
   content padding below pushed the closed inline nav links down by its
   4rem top padding, throwing them out of vertical alignment with the
   logo/CTA button next to them. */

/* Core wraps the dialog in an intermediate .responsive-close element with
   no explicit height, so height:100% on .responsive-dialog below it would
   otherwise resolve against an auto-height box instead of the full
   overlay - collapsing the centered content into the top half of the
   screen. Carrying height:100% through this wrapper too closes that gap. */
.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close {
	height: 100%;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
	position: absolute;
	top: 1.25rem;
	right: 1.25rem;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 1px solid rgba(255, 255, 255, 0.22);
	border-radius: 999px;
	background-color: rgba(255, 255, 255, 0.08);
	color: var(--wp--preset--color--surface);
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:hover {
	background-color: rgba(255, 255, 255, 0.16);
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	display: flex;
	flex: 1;
	align-items: center;
	justify-content: center;
	padding: 4rem 1.5rem 2rem;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.25rem;
	width: 100%;
	height: 100%;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	/* Core sets this li to flex-direction:column and inherits align-items
	   from the block's own "justifyContent: right" layout attribute (used
	   for the closed, inline row) - for a column-direction flex item,
	   align-items controls horizontal position, not justify-content, which
	   is why text-align:center alone doesn't recenter it. */
	align-items: center;
	width: 100%;
	max-width: 22rem;
	text-align: center;
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:last-child {
	border-bottom: none;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	display: block;
	width: 100%;
	padding: 1.1rem 0;
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(1.5rem, 5vw, 1.75rem);
	color: var(--wp--preset--color--surface);
	transition: color 0.15s ease;
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--accent-soft);
}

.vc-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content[aria-current="page"] {
	color: var(--wp--preset--color--accent-soft);
}

/* The default button style (green fill) would nearly disappear against the
   header's own green background, so give it the same gold-on-dark
   treatment already used for .vc-cta-banner's button. */
.vc-header .wp-block-buttons .wp-block-button__link {
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--charcoal);
	white-space: nowrap;
}

.vc-header .wp-block-buttons .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--accent-soft);
}

/* WP core's navigation block only collapses to its built-in hamburger
   overlay below a fixed 600px breakpoint; above that it always renders
   the full inline item list, regardless of whether it actually fits. At
   common laptop/tablet widths the 340px logo + 6 nav items + "Book a
   Consultation" button don't fit on one line, so the nav wraps to a
   second line instead of shrinking - confirmed broken up to 1240px (the
   button was touching the container edge) and clean from 1280px, so the
   cutoff below is set with a safety margin above that measured boundary.
   Rather than fighting to cram everything into a shrinking row, extend
   core's own hamburger breakpoint by overriding its exact selectors
   (matched for equal-or-higher specificity so this wins regardless of
   stylesheet order) - the same overlay menu already used on mobile just
   kicks in earlier. */
@media (min-width: 600px) and (max-width: 1279px) {
	.vc-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.vc-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* Below WP core's 600px breakpoint, redesign the header row entirely: a
   plain left-logo/right-hamburger flex row put all the visual weight on
   one side (the hamburger and CTA pinned hard against the right edge),
   and the bare hamburger icon read as an afterthought next to a 340px
   desktop logo. Switch to a 3-column grid so the logo sits dead-center
   regardless of how wide its two neighbours are - flexbox space-between
   can't center a middle item once its neighbours are unequal widths -
   and give the hamburger a real bordered, tappable button instead of a
   bare icon. */
@media (max-width: 600px) {
	.vc-header > .wp-block-group {
		display: grid;
		grid-template-columns: 1fr auto 1fr;
		align-items: center;
	}

	/* grid-row is pinned explicitly on all three items: auto-placement's
	   cursor only ever moves forward through columns in DOM order, and the
	   markup order here is logo, nav, buttons (column 2, then 1, then 3) -
	   without this, the logo claims column 2 first, and nav's column-1
	   request lands "behind" that cursor position and silently wraps to a
	   second implicit row instead of sharing row 1. */
	.vc-header .wp-block-navigation {
		grid-column: 1;
		grid-row: 1;
		justify-self: start;
	}

	.vc-header .wp-block-site-logo {
		grid-column: 2;
		grid-row: 1;
		justify-self: center;
	}

	.vc-header .wp-block-site-logo img {
		width: 220px;
	}

	.vc-header .wp-block-buttons {
		grid-column: 3;
		grid-row: 1;
		justify-self: end;
	}

	.vc-header .wp-block-navigation__responsive-container-open {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 2.75rem;
		height: 2.75rem;
		padding: 0;
		border: 1px solid rgba(255, 255, 255, 0.22);
		border-radius: 999px;
		background-color: rgba(255, 255, 255, 0.08);
	}

	.vc-header .wp-block-navigation__responsive-container-open:hover {
		background-color: rgba(255, 255, 255, 0.16);
	}

	.vc-header .wp-block-buttons .wp-block-button__link {
		white-space: nowrap;
		padding-inline: 1rem;
		font-size: var(--wp--preset--font-size--small);
	}

	/* Wrapped in header.html so the pill can show just "Book" on phones
	   while keeping the full "Book a Consultation" label for desktop and
	   for screen readers on desktop; still a real, readable button label
	   on mobile, not truncated text. */
	.vc-header__cta-more {
		display: none;
	}
}

.vc-hero__eyebrow {
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--secondary);
	font-weight: 600;
}

/* A quieter alternative to a second hero photo: the same leaf line-art used
   as .vc-brand-statement__decoration, tucked behind the text column as a
   faint watermark rather than a competing image. Opted-out of parallax
   (see .vc-no-parallax note above .vc-brand-statement__decoration) - it's
   meant to recede, not draw the eye. */
.vc-hero--decorated {
	position: relative;
	overflow: hidden;
}

.vc-hero--decorated .wp-block-columns {
	position: relative;
	z-index: 1;
}

.vc-hero__decoration {
	position: absolute;
	top: 50%;
	left: -3rem;
	transform: translateY(-50%);
	width: 18rem;
	max-width: none;
	margin: 0;
	opacity: 0.2;
	pointer-events: none;
	z-index: 0;
}

.vc-hero__decoration img {
	width: 100%;
	height: auto;
}

/* CTA banner */
.vc-cta-banner {
	background-color: var(--wp--preset--color--primary-dark);
	border-radius: var(--wp--custom--radius--large);
	color: var(--wp--preset--color--surface);
}

.vc-cta-banner .wp-block-button__link {
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--charcoal);
}

.vc-cta-banner .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--accent-soft);
}

/* Secondary / outline buttons (e.g. "Explore Services") */
.is-style-vc-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--wp--preset--color--primary);
	box-shadow: inset 0 0 0 1.5px var(--wp--preset--color--primary);
}

.is-style-vc-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

/* Forms (newsletter, contact, enquiry modal). .vc-card uses the "constrained"
   group layout, which renders as a flex column and gives every direct child
   `margin-left/right: auto !important` (core's own rule, for centering
   prose-width content). Auto margins on a flex item's cross axis override
   stretch alignment per spec, so without this the form collapsed to its
   shrink-to-fit content width instead of filling the card - the !important
   here is only to match core's own, not a general pattern. */
.vc-card > .vc-form {
	width: 100% !important;
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.vc-form input[type="text"],
.vc-form input[type="email"],
.vc-form input[type="tel"],
.vc-form input[type="number"],
.vc-form select,
.vc-form textarea {
	box-sizing: border-box;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--small);
	padding: 0.75rem 1rem;
	background-color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--body);
	/* No explicit size here previously left these at the browser's small
	   UA default for form controls - iOS Safari auto-zooms the page on
	   focus for any field under 16px, forcing the visitor to manually
	   zoom back out just to see the rest of the modal. 16px is the
	   documented iOS threshold; anything at or above it suppresses the
	   zoom entirely. */
	font-size: 16px;
	width: 100%;
}

.vc-form input:focus,
.vc-form select:focus,
.vc-form textarea:focus {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 1px;
}

.vc-form label {
	display: block;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
	margin-block: 1rem 0.35rem;
}

/* Wraps the self-hosted ALTCHA widget (assets/js/altcha.min.js) - it
   renders its own compact UI (a checkbox-like state indicator), so this
   just gives it consistent spacing against the rest of the form. */
.vc-captcha {
	margin-block: 1rem 0.35rem;
}

.vc-captcha altcha-widget {
	--altcha-max-width: 100%;
	--altcha-border-radius: var(--wp--custom--radius--small);
	--altcha-color-border: var(--wp--preset--color--border);
}

.vc-form label:first-of-type {
	margin-top: 0;
}

.vc-form__status {
	min-height: 1.5em;
	margin-block: 0.75rem;
	font-size: var(--wp--preset--font-size--small);
}

.vc-form__status.is-success {
	color: var(--wp--preset--color--primary);
}

.vc-form__status.is-error {
	color: #b3261e;
}

/* Submit buttons previously reused core's .wp-block-button__link.wp-element-button
   classes, the same ones the Buttons block generates. That pulls in WP
   core's own block-library button CSS on top of this theme's, and the two
   rendered inconsistently between browsers (fine in Chromium, but Firefox
   rendered the button pill many hundreds of px tall - almost certainly the
   two rulesets fighting over box-sizing/height in a way only Gecko exposed).
   Rather than chase which core rule was responsible, .vc-form__submit is
   fully self-contained: every property it needs is declared here, with no
   dependency on core's button CSS at all. */
.vc-form__submit {
	display: inline-block;
	box-sizing: border-box;
	appearance: none;
	-webkit-appearance: none;
	font-family: var(--wp--preset--font-family--body);
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.3;
	padding: 0.75rem 2.25rem;
	border: 0;
	border-radius: 999px;
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
	cursor: pointer;
}

.vc-form__submit:hover {
	background-color: var(--wp--preset--color--primary-dark);
}

/* Enquiry modal */
.vc-modal {
	position: fixed;
	inset: 0;
	z-index: 1000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
}

.vc-modal[hidden] {
	display: none;
}

.vc-modal__backdrop {
	position: absolute;
	inset: 0;
	background-color: rgba(36, 49, 43, 0.55);
}

/* .vc-modal__panel itself no longer scrolls or holds padding - it's just
   the fixed-size frame. Scrolling and padding live on .vc-modal__body
   instead, so the close button (a sibling, not a descendant of body) stays
   anchored to the panel and visible the whole time, instead of scrolling
   away with the form fields on a small phone viewport where the full form
   + captcha doesn't fit in one screen. */
.vc-modal__panel {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 32rem;
	max-height: calc(100vh - 3rem);
	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--large, 1.25rem);
	box-shadow: var(--wp--custom--shadow--cardHover);
	display: flex;
	flex-direction: column;
}

.vc-modal__body {
	/* min-height:0 overrides flex's default min-height:auto, which would
	   otherwise let this child grow taller than its flex parent's
	   max-height instead of triggering its own overflow-y:auto. */
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	padding: 2rem;
	padding-top: 0.5rem;
}

/* Honeypot field: kept to a 1px box rather than pushed thousands of
   pixels off-screen, since a huge offset inside .vc-modal__body's
   overflow-y:auto would inflate its scrollable area and produce a
   spurious scrollbar even when the visible content easily fits. */
.vc-honeypot {
	/* Same recipe as WordPress core's own .screen-reader-text: clip-path
	   plus a negative margin keeps the box fully self-contained at 1x1px,
	   unlike a large negative offset (the previous approach here), which
	   inflates .vc-modal__body's overflow:auto scrollable area and was
	   producing a spurious scrollbar. */
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.vc-modal__close {
	position: absolute;
	top: 1rem;
	right: 1rem;
	z-index: 2;
	width: 2.75rem;
	height: 2.75rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border: none;
	border-radius: 999px;
	background-color: var(--wp--preset--color--primary);
	box-shadow: 0 1px 4px rgba(36, 49, 43, 0.2);
	font-size: 1.5rem;
	line-height: 1;
	color: var(--wp--preset--color--surface);
	cursor: pointer;
}

.vc-modal__close:hover {
	background-color: var(--wp--preset--color--primary-dark);
}

/* The third instance of the shrink-to-fit trap already written up twice above,
   at .vc-card > .vc-form and .vc-card > .vc-price-list: .vc-card is a
   "constrained" group, so core gives every direct child
   margin-left/right: auto !important, auto margins beat stretch alignment on a
   flex item, and the child collapses to its content width. Here the child is
   the image figure, so every card image rendered at the source's own pixel
   width (300px, or 200px for a portrait) inside a card two or three times
   wider, centred, with the ragged white margins that produced. Measured in the
   browser rather than guessed: figure widths came back 300, 200, 300, 300...
   against cards of a uniform width.

   Pre-existing and live on production's services grid before this work. The
   !important matches core's own, as the note on .vc-card > .vc-form says. */
.vc-card > .vc-card__image {
	width: 100% !important;
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* And the last link in the same chain. Core renders a linked image's anchor as
   display:inline-block, which makes the anchor a containing block at
   shrink-to-fit width. The image's own width:100% then resolves against the
   anchor rather than against the figure, so widening the figure above achieved
   nothing on its own: measured in the browser, figure=350 while
   anchor=300 and img=300.

   Three separate rules were needed to make a card image fill its card, and all
   three were invisible in the markup. Anything added to .vc-card in future is
   worth measuring rather than eyeballing. */
.vc-card__image > a {
	display: block;
	width: 100%;
}

/* Images */
.vc-card__image img {
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--medium, 0.75rem);
	width: 100%;
	/* height:auto for the same reason .vc-included__media img needs it, and it
	   was missing here: WordPress injects width and height attributes into raw
	   img markup on the way out, that height is a presentational hint, and it
	   beats aspect-ratio (which only applies when height is auto). So every
	   card cropped to its own source ratio and a row of cards came out ragged,
	   with the headings on different lines. Visible on production's six-card
	   services grid before this repositioning touched anything: the served
	   heights were 225, 300, 300, 200, 200, 200 against one declared ratio. */
	height: auto;
}

/* wp:post-featured-image has no intrinsic height cap, so a tall source
   photo (portrait or near-square) renders at its full natural height once
   stretched to a wide page-width column - shared across every template
   that uses this core block (page/archive/single/service-detail) rather
   than scoped to one, so the treatment stays consistent everywhere a
   featured image appears. */
.wp-block-post-featured-image img {
	aspect-ratio: 16 / 9;
	object-fit: cover;
	width: 100%;
}

/* Service page hero (patterns/service-hero.php): the featured image sits
   in a side column next to the title rather than spanning the page as a
   full-width band, so it needs its own, more contained ratio instead of
   the wide 16:9 above - source photos here are a mix of square and
   landscape, and 4:3 crops either reasonably without the aggressive
   top/bottom loss a taller ratio would cause on the square ones. */
.vc-hero .wp-block-post-featured-image.vc-service-hero__image img {
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--large, 1.25rem);
	width: 100%;
}

/* Equal-height media rows: unlike .vc-hero__image/.vc-approach__image's
   fixed aspect-ratio (fine when both columns are similar length), text
   length varies a lot on the coaching page, and a fixed-ratio image next
   to a much taller or shorter text column left visible dead space in one
   side. This stretches both columns to match and lets the image fill
   whatever height that turns out to be. */
.vc-media-row {
	align-items: stretch;
}

.vc-media-row > .wp-block-column {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.vc-media-row .vc-media-row__image {
	height: 100%;
	margin: 0;
}

.vc-media-row .vc-media-row__image img {
	width: 100%;
	height: 100%;
	min-height: 20rem;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--large, 1.25rem);
}

.vc-hero__image img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: center top;
	border-radius: var(--wp--custom--radius--large, 1.25rem);
	width: 100%;
}

.vc-approach__image img {
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--large, 1.25rem);
	width: 100%;
}

/* Parallax reveal: the wrapping figure clips to its rounded corners while
   the image underneath is scaled up slightly and nudged by parallax.js, so
   the vertical drift never exposes an empty edge inside the frame. See the
   .vc-parallax-ready note above .vc-brand-statement__decoration.
   .vc-no-parallax opts an instance out entirely - used on the Two-Column
   Feature section's image, a line-art decorative graphic rather than a
   photo, which looked wrong zoomed/drifting the same way a photo does. */
.vc-parallax-ready .vc-hero__image:not(.vc-no-parallax),
.vc-parallax-ready .vc-approach__image:not(.vc-no-parallax) {
	overflow: hidden;
}

.vc-parallax-ready .vc-hero__image:not(.vc-no-parallax) img,
.vc-parallax-ready .vc-approach__image:not(.vc-no-parallax) img {
	transform: scale(1.2) translate3d(0, var(--vc-parallax-y, 0px), 0);
}

.vc-testimonial__avatar img {
	width: 72px;
	height: 72px;
	border-radius: 9999px;
	object-fit: cover;
}

.vc-step__icon img {
	width: 100%;
	aspect-ratio: 1 / 1;
	border-radius: var(--wp--custom--radius--medium, 0.75rem);
	object-fit: cover;
	margin-bottom: 0.5rem;
}

.vc-step__number {
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	font-weight: 600;
	margin-bottom: 0.25rem;
}

/* Whole-person dimensions grid: lighter-weight than .vc-card since there
   are eight of these in view at once. */
.vc-dimension {
	border-top: 2px solid var(--wp--preset--color--accent);
	padding-top: 0.75rem;
	height: 100%;
}

.vc-dimension__title {
	font-family: var(--wp--preset--font-family--heading);
	letter-spacing: 0.02em;
	margin-bottom: 0.35rem;
}

/* Evidence-led philosophy: trio of circular photos */
.vc-evidence-photos {
	gap: 1.5rem;
}

.vc-evidence-photos__item {
	width: 9.5rem;
	margin: 0;
}

.vc-evidence-photos__item img {
	width: 100%;
	aspect-ratio: 1 / 1;
	border-radius: 9999px;
	object-fit: cover;
	border: 4px solid var(--wp--preset--color--surface);
	box-shadow: var(--wp--custom--shadow--card);
}

.vc-evidence-photos__item {
	transform: translateY(var(--vc-photo-offset, 0px));
}

.vc-evidence-photos__item:nth-child(2) {
	--vc-photo-offset: 1.5rem;
}

.vc-parallax-ready .vc-evidence-photos__item {
	transform: translateY(var(--vc-photo-offset, 0px)) translate3d(0, var(--vc-parallax-y, 0px), 0);
}

/* Testimonial */
.vc-testimonial blockquote {
	border-left: 3px solid var(--wp--preset--color--accent);
	padding-left: 1.5rem;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
}

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

/* Story band: a full-bleed photo with a deliberately pronounced parallax
   drift (unlike the restrained accents on .vc-hero__image etc elsewhere) -
   this is the one section built specifically to make the effect
   unmistakable. Falls back to a plain static photo band when
   .vc-parallax-ready isn't present (JS didn't run, or reduced motion). */
/* The media layer is the absolutely-positioned one (filling whatever height
   .vc-story ends up being), and the text sits in normal flow with its own
   padding - the section's height comes from the text content (plus a
   min-height floor), not the other way around. An earlier version pinned
   the text to position:absolute;inset:0 against a fixed-height band; on
   narrow viewports the heading wraps to 4 lines and the text overflowed
   that fixed box, spilling white-on-light-background text into the next
   section, unreadable. Content driving the height, rather than being
   force-fit into it, avoids that regardless of how much it wraps. */
.vc-story {
	position: relative;
	overflow: hidden;
	min-height: 30rem;
	padding-block: 4rem 3rem;
	display: flex;
	align-items: center;
	justify-content: center;
}

.vc-story__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.vc-story__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(36, 49, 43, 0.25) 0%, rgba(36, 49, 43, 0.7) 100%);
}

.vc-story__image {
	margin: 0;
	height: 100%;
}

.vc-story__image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 20%;
}

.vc-parallax-ready .vc-story__image img {
	transform: scale(1.45) translate3d(0, var(--vc-parallax-y, 0px), 0);
}

.vc-story__content {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding-inline: 1.5rem;
}

.vc-story__content .vc-hero__eyebrow {
	color: var(--wp--preset--color--accent);
}

.vc-story__content h2,
.vc-story__content p {
	color: var(--wp--preset--color--surface);
}

.vc-story__content p {
	max-width: 36rem;
}

@media (max-width: 600px) {
	.vc-story {
		min-height: 24rem;
	}
}

/* About / Team page
   ------------------------------------------------------------------------- */

/* Team grid: reuses .vc-card, but the row shouldn't stretch a single founder
   card to full width while the practice is small. Capping the column width
   keeps one card looking intentional, and the grid still reflows neatly as
   more coaches are added to $vc_team. */
.vc-team-grid {
	justify-content: center;
	flex-wrap: wrap;
	gap: 1.5rem;
}

.vc-team-grid > .wp-block-column {
	flex-basis: 22rem;
	flex-grow: 0;
	max-width: 22rem;
}

.vc-team-card {
	text-align: center;
	align-items: center;
}

.vc-team-card__photo {
	margin: 0 0 1rem;
}

.vc-team-card__photo img {
	width: 8.5rem;
	height: 8.5rem;
	border-radius: 9999px;
	object-fit: cover;
	border: 4px solid var(--wp--preset--color--surface);
	box-shadow: var(--wp--custom--shadow--card);
}

.vc-team-card__role {
	color: var(--wp--preset--color--accent);
	font-weight: 600;
	letter-spacing: 0.02em;
	margin: 0 0 0.75rem;
}

/* Credentials strip: evenly-spaced text trust marks. Each mark keeps the
   heading font so it reads as a mark rather than body copy; swap the inner
   paragraph for an <img> logo where a real one exists. */
.vc-credentials {
	gap: 2.5rem 3rem;
}

.vc-credential {
	max-width: 12rem;
	text-align: center;
}

.vc-credential__mark {
	font-family: var(--wp--preset--font-family--heading);
	color: var(--wp--preset--color--primary);
	font-weight: 600;
	margin: 0 0 0.35rem;
}

/* Resources (blog) -------------------------------------------------------- */

/* Tighten the gap between the Resources title/intro and the card grid: drop
   the hero's bottom padding and trim the top padding of the grid below it. */
.vc-resources-hero {
	padding-top: clamp(1rem, 2.5vw, 1.75rem);
	padding-bottom: 0;
}

.vc-resources-hero + .vc-section {
	padding-top: clamp(1rem, 2.5vw, 1.75rem);
}

/* Post cards reuse .vc-card; these rules add the image, meta row and excerpt
   spacing specific to a blog card. */
.vc-post-card {
	padding: 0;
	overflow: hidden;
}

/* Use padding-inline, not margin: WP's constrained-layout rule forces
   margin-left/right:auto !important on group children, which would wipe out
   any margin-based inset. The featured image is excluded so it stays full
   bleed to the card edges. */
.vc-post-card > :not(.vc-post-card__image) {
	padding-inline: 1.5rem;
}

.vc-post-card > .vc-post-meta {
	padding-top: 0.25rem;
}

.vc-post-card__image {
	margin: 0 0 1.25rem;
}

.vc-post-card__image img {
	width: 100%;
	object-fit: cover;
	border-radius: 0;
}

.vc-post-card > :last-child {
	padding-bottom: 1.75rem;
}

.vc-post-meta {
	gap: 0.5rem 0.9rem;
	align-items: center;
	margin-bottom: 0.35rem;
}

.vc-post-meta a,
.vc-post-meta .wp-block-post-terms {
	color: var(--wp--preset--color--secondary);
	font-weight: 600;
	text-decoration: none;
	letter-spacing: 0.02em;
}

.vc-post-meta .wp-block-post-date {
	color: var(--wp--preset--color--text-muted);
}

.vc-post-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-top: 0.5rem;
	font-weight: 600;
	color: var(--wp--preset--color--secondary);
	text-decoration: none;
}

.vc-post-card .wp-block-post-excerpt__more-link:hover {
	color: var(--wp--preset--color--accent);
}

/* Pagination */
.vc-pagination {
	gap: 0.5rem;
	align-items: center;
}

.vc-pagination .wp-block-query-pagination-numbers,
.vc-pagination a {
	color: var(--wp--preset--color--secondary);
	text-decoration: none;
	font-weight: 600;
}

.vc-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.25rem;
	height: 2.25rem;
	padding: 0 0.6rem;
	border-radius: var(--wp--custom--radius--small);
	border: 1px solid var(--wp--preset--color--border);
}

.vc-pagination .page-numbers.current {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
	border-color: var(--wp--preset--color--primary);
}

.vc-pagination .page-numbers:hover:not(.current) {
	border-color: var(--wp--preset--color--primary);
}

/* Single post */
/* Single post: keep the title, image and body as one tight article flow
   rather than three separate sections each carrying full section padding. */
.vc-post-header {
	padding-top: clamp(1rem, 2.5vw, 1.75rem);
	padding-bottom: 0;
}

.vc-post-back {
	margin-bottom: 1.25rem;
}

.vc-post-back a {
	color: var(--wp--preset--color--text-muted);
	text-decoration: none;
	font-weight: 600;
}

.vc-post-back a:hover {
	color: var(--wp--preset--color--secondary);
}

.vc-post-header .wp-block-post-terms {
	display: block;
	margin-bottom: 0.5rem;
}

.vc-post-meta--center {
	margin-top: 0.75rem;
}

.vc-post-media {
	padding-block: clamp(0.75rem, 2vw, 1.25rem);
}

.vc-post-hero-image img {
	width: 100%;
	object-fit: cover;
}

.vc-post-body {
	padding-top: clamp(1rem, 2.5vw, 1.5rem);
	padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
	line-height: 1.75;
}

/* In-content images (illustrations placed mid-article): floated so the article
   text flows around them, never full width. They un-float and stack on narrow
   screens. */
.vc-post-body figure.wp-block-image img {
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--large);
}

.vc-post-body figure.wp-block-image.alignleft,
.vc-post-body figure.wp-block-image.alignright {
	width: min(20rem, 42%);
	margin-block: 0.5rem;
}

.vc-post-body figure.wp-block-image.alignleft {
	float: left;
	margin-right: 1.75rem;
}

.vc-post-body figure.wp-block-image.alignright {
	float: right;
	margin-left: 1.75rem;
}

/* Contain the floats within the article so they never spill into later blocks. */
.vc-post-body .wp-block-post-content::after {
	content: "";
	display: block;
	clear: both;
}

@media (max-width: 640px) {
	.vc-post-body figure.wp-block-image.alignleft,
	.vc-post-body figure.wp-block-image.alignright {
		float: none;
		width: 100%;
		margin-inline: 0;
	}
}

.vc-post-body > * {
	margin-block: 1.1rem;
}

/* Trust stats band: a contained, rounded sage proof bar high on the homepage
   - the same rounded-panel treatment as .vc-cta-banner, so it sits inside the
   content column rather than bleeding full-width against the narrower sections
   above it. Gold figures on sage, ivory labels. Four tiles that wrap to a 2x2
   grid on smaller screens. */
/* Tight vertical rhythm: the panel supplies its own padding, so the section
   around it only needs a small gap to its neighbours rather than the full
   section padding-block (which stacked up and wasted height). */
.vc-stats-section {
	padding-block: clamp(1rem, 3vw, 2rem);
}

/* The section straight after the stats band (the services grid on the
   homepage) doesn't need its full top padding on top of the band's gap -
   tighten it so "Our Services" sits closer to the proof band above it. */
.vc-stats-section + .vc-section {
	padding-top: clamp(0.75rem, 2vw, 1.5rem);
}

.vc-stats-band {
	background-color: var(--wp--preset--color--primary);
	border-radius: var(--wp--custom--radius--large);
	color: var(--wp--preset--color--surface);
	box-shadow: var(--wp--custom--shadow--card);
}

.vc-stats {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 1.25rem 1rem;
}

.vc-stat {
	flex: 1 1 12rem;
	max-width: 16rem;
	text-align: center;
	padding-inline: 0.5rem;
}

.vc-stat__figure {
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(1.75rem, 3.5vw, 2.5rem);
	font-weight: 600;
	line-height: 1.1;
	color: var(--wp--preset--color--accent-soft);
	margin: 0 0 0.4rem;
}

.vc-stat__label {
	font-size: 0.95rem;
	line-height: 1.4;
	color: var(--wp--preset--color--surface);
	opacity: 0.9;
	margin: 0;
}

/* Divider between tiles on wide screens, for a bit of rhythm. */
@media (min-width: 782px) {
	.vc-stat:not(:last-child) {
		border-right: 1px solid rgba(255, 255, 255, 0.18);
	}
}

/* FAQ accordion: native <details>/<summary>, so it works with no JavaScript
   and stays keyboard-accessible. The +/- marker is a CSS pseudo-element that
   flips when the item is open. The default disclosure triangle is removed. */
.vc-faq {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.vc-faq__item {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	padding: 0 1.25rem;
}

.vc-faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.1rem 0;
	cursor: pointer;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 600;
	color: var(--wp--preset--color--charcoal);
	list-style: none;
}

/* Remove the native disclosure triangle (WebKit + the standards property). */
.vc-faq__q::-webkit-details-marker {
	display: none;
}

.vc-faq__icon {
	position: relative;
	flex: 0 0 auto;
	width: 1rem;
	height: 1rem;
}

.vc-faq__icon::before,
.vc-faq__icon::after {
	content: "";
	position: absolute;
	background-color: var(--wp--preset--color--accent);
	transition: transform 0.2s ease, opacity 0.2s ease;
}

/* horizontal bar of the + */
.vc-faq__icon::before {
	top: 50%;
	left: 0;
	width: 100%;
	height: 2px;
	transform: translateY(-50%);
}

/* vertical bar of the + - hidden when open, leaving a - */
.vc-faq__icon::after {
	top: 0;
	left: 50%;
	width: 2px;
	height: 100%;
	transform: translateX(-50%);
}

.vc-faq__item[open] .vc-faq__icon::after {
	transform: translateX(-50%) scaleY(0);
	opacity: 0;
}

.vc-faq__a {
	padding: 0 0 1.2rem;
	color: var(--wp--preset--color--text-muted);
}

.vc-faq__a p {
	margin: 0;
}

@media (prefers-reduced-motion: reduce) {
	.vc-faq__icon::before,
	.vc-faq__icon::after {
		transition: none;
	}
}

/* Free guide: full-width layout (its own template) rather than the narrow
   44rem page column. The title sits centred above the body, which runs to the
   site's full content width. */
.vc-guide__body {
	margin-top: 2.5rem;
}

/* Wellness wheel (free guide): the inline-SVG diagram scales to its container
   and keeps its own breathing room. Pills are white with a sage outline, which
   reads cleanly on the page's ivory background without needing a panel. */
.vc-wellness-wheel {
	margin-block: 2.5rem;
}

.vc-wellness-wheel svg {
	display: block;
	width: 100%;
	height: auto;
}

/* Newsletter lead-magnet card: a two-column card with the image bled to one
   edge. Overrides .vc-card's padding (the image should reach the card edge)
   and its hover lift (this is a form, not a clickable card). */
.vc-newsletter-card {
	padding: 0;
	overflow: hidden;
}

.vc-newsletter-card:hover {
	transform: none;
	box-shadow: var(--wp--custom--shadow--card);
}

/* Kill the inter-column gap so the photo meets the text panel flush; the
   text panel supplies its own breathing room via padding. */
.vc-newsletter-card__inner {
	gap: 0;
	margin-block: 0;
}

.vc-newsletter-card__inner > .wp-block-column {
	margin: 0;
}

.vc-newsletter-card__media {
	margin: 0;
	height: 100%;
}

.vc-newsletter-card__media img {
	width: 100%;
	height: 100%;
	min-height: 20rem;
	object-fit: cover;
}

.vc-newsletter-card__body {
	padding: clamp(1.75rem, 3vw, 2.75rem);
}

/* Inline form variant (newsletter card): name + email + button sit on one
   row and wrap gracefully, with the status line and reveal link each taking
   their own full-width row beneath. */
.vc-form--inline {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	align-items: center;
	margin-top: 1.25rem;
}

.vc-form--inline input {
	flex: 1 1 10rem;
	min-width: 0;
}

.vc-form--inline button[type="submit"] {
	flex: 0 0 auto;
}

.vc-form--inline .vc-form__status {
	flex-basis: 100%;
	margin: 0;
}

@media (max-width: 781px) {
	.vc-newsletter-card__media img {
		min-height: 14rem;
	}
}

/* Newsletter lead-magnet: the "Read your guide" link revealed on successful
   signup. It borrows the button classes for styling, so it needs [hidden] to
   actually hide (button display would otherwise override it), and its own row
   in the flex form. */
.vc-form__resource[hidden] {
	display: none;
}

.vc-form__resource {
	flex-basis: 100%;
	text-align: center;
	text-decoration: none;
	margin-top: 0.25rem;
}

/* Membership page rhythm. The site-wide section padding (clamp(3.5rem, 6vw,
   7rem) top and bottom) plus the 24px block gap between siblings puts about
   178px of empty space between every section at desktop width. That pacing
   earns its keep on the long-form service pages, where each section is a
   separate idea worth pausing on - but this page is one short decision, and
   the gaps read as the page having ended rather than as breathing room.
   Scoped to this template's body class rather than changing the global token,
   so every other page keeps the rhythm it was designed with. The token is
   defined on :root, so setting it here wins for the body subtree by normal
   inheritance without needing !important. */
.page-template-template-pricing {
	--wp--custom--section--padding-block: clamp(1.75rem, 2.5vw, 2.75rem);
}

/* Membership page: "what's included" grid. A plain CSS grid rather than
   wp:columns, for the same reason .vc-stats uses one - four equal cards that
   need to reflow to two-up and then one-up without the column block's
   percentage widths fighting it. */
.vc-included {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 1.5rem;
	text-align: left;
}

/* The image is bled to the card's top and side edges rather than sitting
   inside its padding, so the four cards read as a row of pictures with
   captions - which is the point of this section - instead of framed boxes. */
.vc-included__item {
	padding-top: 0;
	overflow: hidden;
}

.vc-included__media {
	margin: 0 calc(-1 * var(--wp--preset--spacing--50, 2rem)) 1.25rem;
}

/* .vc-card__image's own rule already sets the 4/3 crop and object-fit, but
   these images come from wp_get_attachment_image(), which emits width and
   height attributes. That height is a presentational hint, so it wins over
   aspect-ratio (which only applies when height is auto) and the crop silently
   reverts to the source's own portrait shape - height:auto hands control back.
   The radius is dropped because the figure now meets the card's own rounded
   corners, and a second radius inside them reads as a mistake. */
.vc-included__media img {
	display: block;
	height: auto;
	border-radius: 0;
}

/* These cards aren't links, so they shouldn't lift on hover the way the
   clickable service cards do. */
.vc-included__item:hover {
	transform: none;
	box-shadow: var(--wp--custom--shadow--card);
}

.vc-included__title {
	font-size: var(--wp--preset--font-size--medium);
}

.vc-included__text {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

/* Membership tiers. A fixed column count rather than auto-fit, and centred
   with a max width, so the plans read as one comparison rather than as
   unrelated panels stretched across the full content width. The count is
   fixed at 3 for free/Essentials/Guided; if a plan is ever added or dropped,
   this number and the max-width move with it. */
.vc-tiers {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.5rem;
	/* Each card is as tall as its own contents, NOT stretched to match the
	   tallest. Stretching plus a bottom-pinned button gave the shortest card
	   four hundred pixels of nothing, and the free plan, which is the one a
	   nervous visitor is looking at, was the emptiest thing on the page. Three
	   cards of honestly different heights read as three different amounts of
	   thing; one full card beside two hollow ones reads as a mistake. */
	align-items: start;
	max-width: 72rem;
	margin-inline: auto;
	text-align: left;
}

/* Straight from three to one. Two-up would leave the third plan orphaned on
   a row of its own, which reads as a mistake rather than a layout. */
@media (max-width: 960px) {
	.vc-tiers {
		grid-template-columns: minmax(0, 1fr);
		max-width: 32rem;
	}
}

.vc-tier:hover {
	transform: none;
	box-shadow: var(--wp--custom--shadow--card);
}

/* The featured plan is marked with a border rather than a lift or a scale, so
   the two cards stay the same size and the comparison stays honest. */
.vc-tier--featured {
	border-color: var(--wp--preset--color--accent);
	box-shadow: var(--wp--custom--shadow--cardHover);
}

.vc-tier .vc-card__badge {
	align-self: flex-start;
	margin-top: 0;
	margin-bottom: 0.75rem;
}

/* Reserves the exact height of the featured card's badge on the plan that
   doesn't carry one, so both plan names sit on the same line. Rendered and
   hidden rather than substituted with a margin, because any equivalent margin
   is a guess that drifts the moment the badge's type or padding changes. */
.vc-card__badge--placeholder {
	visibility: hidden;
}

@media (max-width: 960px) {
	/* Stacked one above the other there's nothing to line up with, so the
	   reserved space would just read as a gap at the top of the card. Tracks
	   the .vc-tiers stacking breakpoint above. */
	.vc-card__badge--placeholder {
		display: none;
	}
}

.vc-tier__name {
	font-size: var(--wp--preset--font-size--large);
	margin-bottom: 0.25rem;
}

.vc-tier__price {
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
	margin: 0 0 0.75rem;
}

.vc-tier__amount {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--preset--color--primary);
}

.vc-tier__period {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

.vc-tier__tagline {
	margin: 0 0 1.25rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

.vc-tier__inherits {
	margin: 0 0 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

/* Tick markers are drawn rather than typed: a literal check character in the
   content would be read out by screen readers on every single bullet. */
.vc-tier__features {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.vc-tier__features li {
	position: relative;
	padding-left: 1.75rem;
	font-size: var(--wp--preset--font-size--small);
}

.vc-tier__features li::before {
	content: "";
	position: absolute;
	left: 0.25rem;
	top: 0.4em;
	width: 0.5rem;
	height: 0.85rem;
	border: solid var(--wp--preset--color--primary);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.vc-tier__note {
	margin: 1.25rem 0 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

/* margin-top:auto pins the button to the card's bottom edge, so both cards'
   buttons line up regardless of how many features each plan lists. */
.vc-tier__cta {
	margin-top: 1.25rem;
	padding-top: 1.5rem;
}

.vc-tier__cta .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: center;
}

.vc-tiers__pending {
	max-width: 34rem;
	margin: 1.75rem auto 0;
	text-align: center;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

/* One-to-one card: same shrink-to-fit override the other raw-HTML children
   of a constrained .vc-card need (see the .vc-price-list note above). */
.vc-card > .vc-rates,
.vc-card > .vc-one-to-one__note,
.vc-card > .vc-member-nudge,
.vc-card > .vc-one-to-one__cta {
	width: 100% !important;
	max-width: none;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* Standard-vs-member rate table. Three columns rather than the single-price
   .vc-price-list, because the whole point here is the comparison. */
.vc-rates {
	display: grid;
	grid-template-columns: 1fr auto auto;
	align-items: center;
	column-gap: clamp(1rem, 4vw, 2.5rem);
}

.vc-rates__row {
	display: grid;
	grid-template-columns: subgrid;
	grid-column: 1 / -1;
	align-items: baseline;
	padding-block: 0.75rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.vc-rates__row:last-child {
	border-bottom: none;
}

/* The header row labels the two price columns, so it reads as column headings
   rather than another priced line. */
.vc-rates__row--head {
	padding-block: 0 0.5rem;
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.vc-rates__col {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--text-muted);
	text-align: right;
}

.vc-rates__col--member {
	color: var(--wp--preset--color--primary);
}

.vc-rates__label {
	color: var(--wp--preset--color--text-muted);
}

.vc-rates__price {
	font-weight: 600;
	text-align: right;
	white-space: nowrap;
	color: var(--wp--preset--color--text-muted);
}

/* The member column is the one being sold, so it carries the weight and the
   brand colour while the standard rate stays deliberately quiet - no
   strikethrough, since it's a real price someone actually pays. */
.vc-rates__price--member {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.15rem;
	font-size: 1.25rem;
	color: var(--wp--preset--color--primary);
}

.vc-rates__save {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	background: color-mix(in srgb, var(--wp--preset--color--accent) 14%, transparent);
	border-radius: 999px;
	padding: 0.15rem 0.5rem;
	white-space: nowrap;
}

/* The "join and the block pays for itself" line - the actual argument for
   membership on this section, so it gets a panel rather than running on as
   another muted footnote. */
.vc-member-nudge {
	/* Raw HTML inside a wp:html block, so it doesn't inherit WordPress's
	   border-box the way a real block element does. Without this, the
	   width:100% forced by the .vc-card override above has its padding and
	   border added outside it, and the panel bleeds ~37px past the card. */
	box-sizing: border-box;
	margin: 1.25rem 0 0;
	padding: 0.9rem 1.1rem;
	border-radius: var(--wp--custom--radius--medium);
	background: color-mix(in srgb, var(--wp--preset--color--primary) 7%, transparent);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--primary) 18%, transparent);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text);
}

@media (max-width: 600px) {
	/* Tighten the gutters only. The row must keep grid-template-columns:
	   subgrid - restating explicit tracks here overrides it, and each row then
	   sizes its own columns independently, so the prices stop lining up
	   underneath their Standard/Member headings. */
	.vc-rates {
		column-gap: 0.75rem;
	}

	.vc-rates__price--member {
		font-size: 1.1rem;
	}
}

.vc-one-to-one:hover {
	transform: none;
	box-shadow: var(--wp--custom--shadow--card);
}

.vc-one-to-one__note {
	margin: 1.25rem 0 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
}

.vc-one-to-one__cta {
	margin-top: 1.5rem;
	text-align: center;
}

/* Join-our-team CTA: a calm bordered panel rather than the dark cta-banner,
   so the recruitment ask reads as an aside, not a second primary conversion. */
.vc-join {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--large);
	box-shadow: var(--wp--custom--shadow--card);
}

/* Article diagrams (Resources posts) -------------------------------------
   Ported verbatim from the Portal's `resources/css/app.css`, where the Blade
   views that emit this markup live. The Portal pushes a Resources article here
   with its diagrams already rendered, inside a `wp:html` block, so the only
   thing this side needs is the styling for them.

   Keep the two in step. If a card gains a class in the Portal, it gains one
   here; a diagram whose CSS is missing does not degrade politely, it renders
   as a stack of unstyled words in the middle of the article.

   The block below is unchanged apart from this bridge, which maps the Portal's
   variable names onto the theme's presets. The two palettes are the same
   colours under different names, and the fonts are identical (Fraunces and
   Inter in both), so nothing here is an approximation except `--tint`, which
   the theme has no equivalent of. */
.magazine-figure {
	--primary: var(--wp--preset--color--primary);
	--accent: var(--wp--preset--color--accent);
	--surface: var(--wp--preset--color--surface);
	--charcoal: var(--wp--preset--color--charcoal);
	--text-muted: var(--wp--preset--color--text-muted);
	--border: var(--wp--preset--color--border);
	--font-sans: var(--wp--preset--font-family--body);
	--font-serif: var(--wp--preset--font-family--heading);

	/* No theme preset: the Portal's palest forest, used as the figure's ground. */
	--tint: #eef2ec;

	/* The Portal's darker gold, one step down from --accent for small text. */
	--color-gold-600: #a9823a;
}

/*  ── Figures ───────────────────────────────────────────────────────────
    The Foundry's video cards, rendered live rather than screenshotted.

    Three differences from `video/cards/_style.blade.php`, and only three:

    1. `vw` becomes `cqw` against the figure's own container, because here a
       figure is a box on a page rather than the whole 1920x1080 frame. The
       type roles are also retuned down: a video card is legible at three
       metres by design, and a page is read at fifty centimetres.
    2. `--t` is gone. It exists so a screenshot can be taken at a chosen
       moment; a browser has a clock of its own. Animations start when the
       figure is scrolled to, which is what `.is-seen` does.
    3. Reduced motion is honoured. The video set has no such branch and should
       not: a video has no reader preference to consult. A web page does. */
.magazine-figure {
    container-type: inline-size;
    background: var(--tint);
    border: 1px solid var(--border);
    border-radius: 1.1rem;
    padding: clamp(1.25rem, 3.4cqw, 2.6rem);
    margin: 2.6rem 0;
    font-family: var(--font-serif);
    color: var(--charcoal);

    --fig-eyebrow: clamp(0.7rem, 1.2cqw, 0.85rem);
    --fig-item: clamp(1rem, 2.1cqw, 1.45rem);
    --fig-lead: clamp(1.15rem, 2.6cqw, 1.8rem);
}
.magazine-figure .fig-kicker {
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--primary);
    margin-bottom: clamp(1rem, 2.4cqw, 1.8rem);
}
.magazine-figure .fig-caption {
    font-family: var(--font-sans);
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--text-muted);
    margin-top: clamp(1.1rem, 2.6cqw, 1.9rem);
    padding-top: 0.9rem;
    border-top: 1px solid var(--border);
}
.magazine-figure .fig-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 0.8rem;
    padding: clamp(0.9rem, 2.2cqw, 1.7rem);
    font-weight: 600;
    font-size: var(--fig-item);
    line-height: 1.25;
}
.magazine-figure .fig-note {
    font-family: var(--font-sans);
    font-size: 0.86rem;
    line-height: 1.6;
    color: var(--text-muted);
    margin-top: 1.1rem;
}

/*  The motion vocabulary, lifted whole. Every animated element is paused until
    its figure has been seen; `--in` is its own start offset in seconds and
    `--dur` its length, exactly as on a card. CardEntranceTest on the Foundry
    holds `--in + --dur` to 1.6s across the whole set, so nothing here can take
    longer than that to arrive. */
.magazine-figure .m {
    animation-duration: calc(var(--dur, 0.5) * 1s);
    animation-delay: calc(var(--in, 0) * 1s);
    animation-timing-function: cubic-bezier(0.22, 0.72, 0.24, 1);
    animation-fill-mode: both;
    animation-iteration-count: 1;
    animation-play-state: paused;
}
.magazine-figure.is-seen .m { animation-play-state: running; }

@keyframes mRise   { from { opacity: 0; transform: translate3d(0, 1.6rem, 0); } to { opacity: 1; transform: none; } }
@keyframes mDrop   { from { opacity: 0; transform: translate3d(0, -1.1rem, 0); } to { opacity: 1; transform: none; } }
@keyframes mLead   { from { opacity: 0; transform: translate3d(-1.6rem, 0, 0); } to { opacity: 1; transform: none; } }
@keyframes mIn     { from { opacity: 0; } to { opacity: 1; } }
@keyframes mPop    { from { opacity: 0; transform: scale(0.84); } to { opacity: 1; transform: none; } }
@keyframes mGrow   { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes mTall   { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes mDraw   { from { stroke-dashoffset: 1; } to { stroke-dashoffset: var(--to-off, 0); } }

.magazine-figure .m-rise  { animation-name: mRise; }
.magazine-figure .m-drop  { animation-name: mDrop; }
.magazine-figure .m-lead  { animation-name: mLead; }
.magazine-figure .m-in    { animation-name: mIn; }
.magazine-figure .m-pop   { animation-name: mPop; }
.magazine-figure .m-grow  { animation-name: mGrow; transform-origin: left center; }
.magazine-figure .m-tall  { animation-name: mTall; transform-origin: bottom center; }
.magazine-figure .m-draw  { animation-name: mDraw; stroke-dasharray: 1; stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
    .magazine-figure .m {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
        stroke-dashoffset: 0 !important;
    }
}

/*  ── The shapes each figure kind is drawn with ─────────────────────────── */

/* cycle / flow: panels in a row with the link between them */
.fig-chain { display: flex; align-items: stretch; gap: clamp(0.6rem, 2cqw, 1.6rem); }
.fig-chain > .fig-panel { flex: 1; }
.fig-chain .fig-link {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    color: var(--accent);
    font-size: calc(var(--fig-item) * 1.3);
    line-height: 1;
    text-align: center;
}
.fig-chain .fig-link small {
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.fig-leg { position: relative; margin: clamp(0.5rem, 1cqw, 1rem) 0 clamp(2rem, 4cqw, 3rem); }
.fig-leg .fig-leg-line {
    height: clamp(1.2rem, 3cqw, 2.2rem);
    border: 2px solid var(--accent);
    border-top: 0;
    border-radius: 0 0 1rem 1rem;
    opacity: 0.55;
    transform-origin: right center;
}
.fig-leg .fig-leg-label {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    top: calc(clamp(1.2rem, 3cqw, 2.2rem) + 0.55rem);
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
    white-space: nowrap;
}

/* ripple: one cause, several consequences */
.fig-ripple { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(0.8rem, 2.4cqw, 2rem); }
.fig-ripple .fig-centre {
    background: var(--primary);
    color: #fff;
    border-radius: 999px;
    padding: clamp(0.8rem, 2cqw, 1.5rem) clamp(1.1rem, 2.6cqw, 2rem);
    font-weight: 600;
    font-size: var(--fig-item);
    line-height: 1.2;
    text-align: center;
}
.fig-ripple .fig-outs { display: flex; flex-direction: column; gap: 0.7rem; flex: 1; min-width: 12rem; }

/* steps / stack: a numbered or summed column */
.fig-column { display: flex; flex-direction: column; gap: 0.75rem; }
.fig-column .fig-panel { display: flex; align-items: baseline; gap: 0.9rem; }
.fig-column .fig-index {
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.12em;
    color: var(--accent);
    flex: none;
}
.fig-total {
    margin-top: 0.9rem;
    padding-top: 0.9rem;
    border-top: 2px solid var(--accent);
    font-size: var(--fig-lead);
    font-weight: 600;
    color: var(--primary);
}

/* timeline */
.fig-timeline { position: relative; }
.fig-timeline .fig-track {
    position: absolute;
    left: 0;
    right: 0;
    top: clamp(1.6rem, 2.9cqw, 2.4rem);
    height: 2px;
    background: var(--border);
    transform-origin: left center;
}
.fig-timeline .fig-points { display: flex; position: relative; }
.fig-timeline .fig-point { flex: 1; text-align: center; padding: 0 0.6rem; }
.fig-timeline .fig-when {
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
}
.fig-timeline .fig-dot {
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 999px;
    background: var(--primary);
    margin: clamp(0.7rem, 1.6cqw, 1.2rem) auto clamp(0.7rem, 1.6cqw, 1.2rem);
    box-shadow: 0 0 0 0.4rem var(--tint);
}
.fig-timeline .fig-what { font-weight: 600; font-size: var(--fig-item); line-height: 1.25; }

/* contrast: from / to */
.fig-swap { display: flex; align-items: stretch; gap: clamp(0.7rem, 2.2cqw, 1.8rem); }
.fig-swap .fig-side { flex: 1; }
.fig-swap .fig-from {
    color: var(--text-muted);
    background: transparent;
    border-style: dashed;
}
.fig-swap .fig-to { border-color: var(--primary); }
.fig-swap .fig-side-label {
    font-family: var(--font-sans);
    font-size: var(--fig-eyebrow);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 0.5rem;
    display: block;
}
.fig-swap .fig-to .fig-side-label { color: var(--primary); }

/* balance: two things held against each other */
.fig-balance { text-align: center; }
.fig-beam {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    border-bottom: 3px solid var(--primary);
    padding-bottom: 0.9rem;
    transform-origin: center center;
}
.fig-beam > div { font-weight: 600; font-size: var(--fig-item); }
.fig-fulcrum {
    width: 0;
    height: 0;
    margin: 0 auto;
    border-left: 0.8rem solid transparent;
    border-right: 0.8rem solid transparent;
    border-top: 1rem solid var(--accent);
}

/* myth: the belief, struck through as the correction lands */
.fig-myth-belief {
    position: relative;
    display: inline-block;
    font-weight: 600;
    font-size: var(--fig-lead);
    line-height: 1.3;
    color: var(--text-muted);
}
.fig-myth-belief .fig-strike {
    position: absolute;
    left: -0.1em;
    right: -0.1em;
    top: 52%;
    height: 2px;
    background: var(--color-gold-600);
    transform-origin: left center;
}
.fig-myth-truth {
    font-weight: 600;
    font-size: var(--fig-lead);
    line-height: 1.28;
    color: var(--primary);
    margin-top: clamp(0.9rem, 2.4cqw, 1.8rem);
}

/* definition */
.fig-term {
    font-weight: 600;
    font-size: calc(var(--fig-lead) * 1.15);
    line-height: 1.2;
    color: var(--primary);
}
.fig-meaning { font-size: var(--fig-item); line-height: 1.45; margin-top: 0.8rem; }

/* proportion: figures counted, never a pie */
.fig-people { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(0.5rem, 2.2cqw, 1.8rem); }
.fig-people .fig-person { position: relative; width: clamp(2.2rem, 7cqw, 4.4rem); }
.fig-people svg { width: 100%; display: block; }
.fig-people .fig-person-on { position: absolute; inset: 0; }
.fig-count {
    text-align: center;
    margin-top: clamp(1.2rem, 3cqw, 2.4rem);
    font-size: var(--fig-lead);
    line-height: 1.25;
    font-weight: 600;
}
.fig-count b { color: var(--primary); font-weight: 600; }

/* the wheel */
/*  One centred ring. It was a two-column grid, ring beside a note explaining
    that nothing on the wheel is a score; the note said something about the
    card's design rather than about the subject and has gone, so the second
    column would now be empty air with the ring pinned to the left of it. */
.fig-wheel {
    display: grid;
    justify-content: center;
}
.fig-wheel svg {
    width: 100%;
    max-width: 26rem;
    margin-inline: auto;
    display: block;
    overflow: visible;
}
.fig-wheel text {
    font-family: var(--font-sans);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.03em;
    fill: var(--text-muted);
}
.fig-wheel .fig-hub {
    font-family: var(--font-serif);
    font-size: 26px;
    font-weight: 600;
    fill: var(--primary);
    letter-spacing: -0.01em;
}
@container (max-width: 620px) {
    .fig-chain, .fig-swap { flex-direction: column; }
    .fig-chain .fig-link { transform: rotate(90deg); }
    .fig-leg { display: none; }
    .fig-timeline .fig-points { flex-direction: column; gap: 1.2rem; }
    .fig-timeline .fig-track { display: none; }
    .fig-timeline .fig-point { text-align: left; padding: 0; }
    .fig-timeline .fig-dot { margin-left: 0; }
}

/* The research behind an article ------------------------------------------
   The collapsed evidence panel at the foot of a Resources post. The Portal
   builds the markup at publish time (resources/views/wordpress/article-sources
   .blade.php there) because `details` and `summary` cannot be stored in the
   article body; this is its styling.

   Matches the Portal's own panel: a pale sage card, collapsed, opened on
   purpose. Collapsed rather than absent because a citation nobody can open is
   one taken on trust, and collapsed rather than listed because it should not be
   in the reader's face. */
.vc-article-sources {
	margin-block: 2rem;
	padding: 1.1rem 1.5rem;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--large, 1rem);
	background: color-mix(in srgb, var(--wp--preset--color--primary) 7%, transparent);
}

.vc-article-sources > summary {
	cursor: pointer;
	font-weight: 600;
	font-size: 0.95rem;
	color: var(--wp--preset--color--charcoal);
	list-style-position: outside;
}

.vc-article-sources > summary::marker {
	color: var(--wp--preset--color--text-muted);
}

.vc-article-sources > p {
	margin-top: 0.85rem;
	margin-bottom: 0;
	font-size: 0.95rem;
	line-height: 1.65;
	color: var(--wp--preset--color--text-muted);
}

.vc-article-sources ul {
	margin: 0.85rem 0 0;
	padding-left: 1.1rem;
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	font-size: 0.95rem;
}

.vc-article-sources a {
	color: var(--wp--preset--color--secondary);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.vc-article-sources a:hover {
	color: var(--wp--preset--color--accent);
}

.vc-article-sources__meta {
	color: var(--wp--preset--color--text-muted);
	font-size: 0.85em;
}

/* Three ways to work with us
   ---------------------------------------------------------------------------
   Same three-up grid and stacking behaviour as .vc-tiers, and for the same
   reason: two-up orphans the third card on a row of its own and reads as a
   layout mistake. Kept as its own class rather than reusing .vc-tiers because
   these cards carry prose rather than a price list, and sharing the class would
   mean every future tweak to one silently moved the other. */
.vc-ways {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1.5rem;
	align-items: stretch;
	max-width: 72rem;
	margin-inline: auto;
	text-align: left;
}

@media (max-width: 960px) {
	.vc-ways {
		grid-template-columns: minmax(0, 1fr);
		max-width: 32rem;
	}
}

/* The card is a flex column so the price and button sit on a common baseline
   across all three, however much prose the middle of the card carries. */
.vc-way {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.vc-way:hover {
	transform: none;
	box-shadow: var(--wp--custom--shadow--card);
}

/* Marked with a border rather than a lift, matching .vc-tier--featured, so the
   three cards stay the same size and the comparison stays honest. */
.vc-way--featured {
	border-color: var(--wp--preset--color--primary);
	border-width: 2px;
}

.vc-way__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--large);
}

.vc-way__lead {
	margin: 0;
	color: var(--wp--preset--color--text-muted);
}

.vc-way__for {
	margin: 0;
}

/* The cards carry no money at all, so the button is what sits at the bottom and
   margin-top:auto is what pins it there however long the prose above runs. See
   the two-axes note in three-ways.php for why the figures moved out. */
.vc-way__cta {
	margin: auto 0 0;
	padding-top: 0.75rem;
}

.vc-way__cta .wp-element-button {
	width: 100%;
	text-align: center;
}

/* Service pages: what to expect
   ---------------------------------------------------------------------------
   The facts strip answers format, length and price in the place a visitor asks
   them. Auto-fit rather than a fixed column count because the blood testing
   page carries four longer values and the coaching pages four short ones, and
   a fixed grid would strand one of them. */
.vc-expect-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 1.5rem;
	max-width: 72rem;
	/* The top margin has to be explicit. These three children come out of a
	   wp:html block, so they are direct children of the constrained group and
	   would normally be spaced by the theme's blockGap - but a `margin: 0 auto`
	   shorthand silently overrides the margin-block-start blockGap sets, and the
	   heading above then sits straight on top of the 2px rules. It reads as a
	   collision rather than as tight spacing, because the rules look like they
	   are underlining the heading. */
	margin: 2.5rem auto 3rem;
	padding: 0;
}

.vc-expect-facts__item {
	border-top: 2px solid var(--wp--preset--color--primary);
	padding-top: 0.75rem;
}

.vc-expect-facts dt {
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	margin-bottom: 0.35rem;
}

.vc-expect-facts dd {
	margin: 0;
}

/* Two-up, and it stacks early: "this is for you if" against "worth knowing
   first" only works as a pair when they are read together, so a narrow viewport
   should put them one under the other rather than squeeze both. */
.vc-expect-fit {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1.5rem;
	/* Top-aligned rather than stretched: the caveat card is deliberately
	   shorter than the fit list, and stretching it just added a pool of empty
	   card under three lines of text. */
	align-items: start;
	max-width: 72rem;
	margin: 0 auto 3rem;
}

@media (max-width: 782px) {
	.vc-expect-fit {
		grid-template-columns: minmax(0, 1fr);
	}
}

.vc-expect-fit ul {
	margin: 0;
	padding-left: 1.1rem;
}

.vc-expect-fit li {
	margin-bottom: 0.4rem;
}

.vc-expect-fit li:last-child {
	margin-bottom: 0;
}

/* The caveat card is deliberately quieter than the fit card. It is there to be
   honest, not to argue the visitor out of the service. */
.vc-expect-fit__no {
	background-color: transparent;
	color: var(--wp--preset--color--text-muted);
}

.vc-expect-fit__no .vc-card__title {
	color: var(--wp--preset--color--text);
}

.vc-expect-start {
	max-width: 44rem;
	margin-inline: auto;
	text-align: center;
}

.vc-expect-start .wp-block-button {
	margin-top: 1.25rem;
}

/* How things are paid for
   ---------------------------------------------------------------------------
   The second axis. Separated from the cards above by a rule rather than by
   distance, because it answers a different question about the same three
   things and needs to read as a companion rather than as a fifth option.
   Four across on a wide screen, two on a narrow one: these are short labels
   rather than cards, so they take a tighter grid than .vc-ways. */
.vc-pay {
	max-width: 72rem;
	margin: 2.5rem auto 0;
	padding-top: 1.75rem;
	border-top: 1px solid var(--wp--preset--color--border);
}

.vc-pay__heading {
	text-align: center;
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	font-weight: 600;
	margin: 0 0 1.25rem;
}

.vc-pay__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 0.75rem;
}

@media (max-width: 960px) {
	.vc-pay__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 480px) {
	.vc-pay__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

.vc-pay__item {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	padding: 0.9rem 1rem;
}

.vc-pay__title {
	display: block;
	font-weight: 600;
	margin-bottom: 0.15rem;
}

.vc-pay__text {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--text-muted);
	line-height: 1.45;
}

/* Plan cards: the visual half
   ---------------------------------------------------------------------------
   The plans are where somebody decides whether to pay, and the cards were a
   price and a wall of ticks. These three additions carry the difference between
   the plans before anybody reads a bullet: a glyph that says what the plan is,
   a single headline saying why you would pick it, and a featured card that
   actually looks chosen rather than merely outlined.

   Restraint is deliberate. This is a clinic, and a plans page that shouts reads
   as a sales funnel. One accent, one glyph, no gradients. */
.vc-tier__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 50%;
	background-color: var(--wp--preset--color--background);
	color: var(--wp--preset--color--primary);
	margin-bottom: 0.85rem;
}

.vc-tier__icon svg {
	width: 1.5rem;
	height: 1.5rem;
	display: block;
}

/* The featured plan's glyph is filled rather than outlined, so the eye lands
   on it first without the card needing to be a different size. */
.vc-tier--featured .vc-tier__icon {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

/* The one line a skimmer should take away. Sits between the price and the
   tagline because that is where the eye already is after reading the number. */
.vc-tier__headline {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 0.35rem;
}

.vc-tier--featured .vc-tier__headline {
	color: var(--wp--preset--color--primary-dark);
}

/* A tinted well behind the features, so the list reads as "what is in the box"
   rather than as more paragraph. Pulled to the card's edges. */
.vc-tier__features {
	background-color: var(--wp--preset--color--background);
	border-radius: var(--wp--custom--radius--medium);
	padding: 1rem 1.1rem;
	margin-block: 0.35rem;
}

.vc-tier--featured .vc-tier__features {
	background-color: color-mix(in srgb, var(--wp--preset--color--primary) 7%, transparent);
}

/* The tick was a small square. A real tick reads as a tick at a glance, and at
   this size the difference is most of why the list felt like filler. */
.vc-tier__features li::before {
	content: "";
	position: absolute;
	left: 0.15rem;
	top: 0.28em;
	width: 0.45rem;
	height: 0.8rem;
	border: solid var(--wp--preset--color--primary);
	border-width: 0 2px 2px 0;
	transform: rotate(42deg);
	border-radius: 1px;
	background: none;
}

/* An inherited feature is shown, but quietly: it is context for the one line
   that is actually new on this plan, not a claim competing with it. */
.vc-tier__features--inherited {
	color: var(--wp--preset--color--text-muted);
}

.vc-tier__features--inherited::before {
	opacity: 0.45;
}

/* What a tier inherits, as chips rather than a second tick list.
   Compact on purpose: the detail lives on the card these came from, which is
   directly alongside, and repeating it in full made the fullest plan tower over
   the free one. */
.vc-tier__inherited-chips {
	list-style: none;
	margin: 0 0 0.6rem;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
}

.vc-tier__inherited-chips li {
	font-size: 0.78rem;
	line-height: 1.3;
	padding: 0.28rem 0.6rem;
	border-radius: 999px;
	background-color: var(--wp--preset--color--background);
	color: var(--wp--preset--color--text-muted);
}

/* The top of a plan card had 154px above the plan's name and only 44 of them
   were the glyph. Two causes, both invisible in the markup:

   The name is an h3 and carried a 36px heading margin-top, which makes sense
   between paragraphs and makes none directly under an icon.

   And the "Most support" badge was kept in flow, with an empty placeholder on
   the other two cards so all three lined up. That reserved 36px of nothing on
   two cards out of three to keep one badge aligned. Taking the badge out of
   flow lets every card start at its glyph and costs nothing. */
.vc-tier {
	position: relative;
}

.vc-tier__name {
	margin-top: 0;
}

.vc-tier .vc-card__badge {
	position: absolute;
	top: 1.1rem;
	right: 1.1rem;
	margin: 0;
}

.vc-tier .vc-card__badge--placeholder {
	display: none;
}

/* The glyph now sits at the top of the card, so it needs room from the padding
   rather than from the element that used to be above it. */
.vc-tier__icon {
	margin-top: 0.15rem;
}

/* Equal-height cards WITHOUT the dead space
   ---------------------------------------------------------------------------
   Two earlier attempts and both were wrong in opposite directions. Stretching
   the cards pooled every spare pixel into a void above the shortest card's
   button. Letting them size themselves removed that but left a ragged column
   bottom, which read as broken rather than as deliberate.

   The answer is to stretch, and give the spare height to the tinted features
   panel rather than to blank card. Space inside a surface reads as a panel;
   the same space below one reads as a gap. The list centres inside it, so a
   three-item plan looks composed in its box rather than top-packed with a hole
   underneath.

   Everything from the button up keeps its natural spacing, so the CTAs line up
   across all three without anything being pushed. */
.vc-tiers {
	align-items: stretch;
}

.vc-tier {
	display: flex;
	flex-direction: column;
}

.vc-tier__features {
	flex: 1 1 auto;
	justify-content: center;
}

/* The note sits with the button rather than floating after the panel. */
.vc-tier__note {
	margin-top: 1.25rem;
}

/* ---------------------------------------------------------------------------
   Repositioning, 29 August 2026: three additions, and no changes to anything
   that already existed. Everything above this comment renders exactly as it
   did on 0.32.0.
   --------------------------------------------------------------------------- */

/* The "what we cover" lists in the primary service sections. Two columns where
   there is room, because six short items in one column pushes the button below
   the fold on a laptop. */
.vc-topic-list {
	margin-bottom: 1.5rem;
	padding-left: 1.1rem;
}

.vc-topic-list li {
	margin-bottom: 0.35rem;
}

@media (min-width: 600px) {
	.vc-topic-list {
		columns: 2;
		column-gap: 2rem;
	}

	.vc-topic-list li {
		break-inside: avoid;
	}
}

/* The one-line scope note at the foot of the services index. Tighter than a
   normal section: it is a footnote, not a block of content. */
.vc-scope-note {
	padding-top: 2rem;
	padding-bottom: 2rem;
}

.vc-scope-note p {
	margin: 0 auto;
	max-width: 46rem;
}
