/*
 * Site styles. There is no CSS framework and no build step — this file is
 * served exactly as written, so everything the site needs is here or in the
 * site's own additions below.
 *
 * ---------------------------------------------------------------------------
 * FLUID TYPE & SPACE SCALE
 *
 * Every size below is derived from the six anchor numbers in --u-*. Change an
 * anchor and the whole scale moves with it, in proportion. That is the point:
 * retuning a site is editing six numbers, not auditing every value in the file.
 *
 * Each step is a clamp() between its value at the minimum viewport and its
 * value at the maximum, so text and spacing scale smoothly with the viewport
 * instead of jumping at breakpoints. No media queries are needed for sizing.
 *
 * TO RETUNE FOR THIS SITE (see refs/design/DESIGN.md):
 *   --u-min-ratio / --u-max-ratio   how dramatic the jump between sizes is.
 *                                   1.2 (minor third) reads calm and even;
 *                                   1.333 (perfect fourth) reads confident;
 *                                   above ~1.4 gets shouty for a practice site.
 *   --u-min-font / --u-max-font     base body size at each end, in px.
 *   --u-min-vw / --u-max-vw         the viewport range the scale spans.
 *
 * A larger max-ratio with the same min-ratio gives a site that is restrained on
 * a phone and expressive on a desktop, which usually suits a hero-led page.
 */
:root {
    /* --- Anchors: the dial for this site ------------------------------- */
    --u-min-vw: 320;
    --u-max-vw: 1240;
    --u-min-font: 16;
    --u-max-font: 18;
    --u-min-ratio: 1.2;
    --u-max-ratio: 1.25;
    /* Space unit (rem) at each end. Every --space-* step and pair is a fixed
     * multiple of it, so these two knobs move the whole spacing rhythm at once. */
    --u-space-min: 1;
    --u-space-max: 1.25;

    /* --- Derivation. Not usually edited by hand. ----------------------- */
    /* Slope and intercept of the line between the two anchor viewports,
     * expressed so each step can be written as clamp(min, calc(...), max). */
    --u-vw-range: calc(var(--u-max-vw) - var(--u-min-vw));

    /* Type steps, in rem at each anchor. Each step multiplies the previous
     * one by the ratio, so the relationship between sizes is fixed even as the
     * absolute values move. */
    --u-min-0: calc(var(--u-min-font) / 16);
    --u-max-0: calc(var(--u-max-font) / 16);

    --u-min--2: calc(var(--u-min-0) / var(--u-min-ratio) / var(--u-min-ratio));
    --u-max--2: calc(var(--u-max-0) / var(--u-max-ratio) / var(--u-max-ratio));
    --u-min--1: calc(var(--u-min-0) / var(--u-min-ratio));
    --u-max--1: calc(var(--u-max-0) / var(--u-max-ratio));
    --u-min-1: calc(var(--u-min-0) * var(--u-min-ratio));
    --u-max-1: calc(var(--u-max-0) * var(--u-max-ratio));
    --u-min-2: calc(var(--u-min-1) * var(--u-min-ratio));
    --u-max-2: calc(var(--u-max-1) * var(--u-max-ratio));
    --u-min-3: calc(var(--u-min-2) * var(--u-min-ratio));
    --u-max-3: calc(var(--u-max-2) * var(--u-max-ratio));
    --u-min-4: calc(var(--u-min-3) * var(--u-min-ratio));
    --u-max-4: calc(var(--u-max-3) * var(--u-max-ratio));
    --u-min-5: calc(var(--u-min-4) * var(--u-min-ratio));
    --u-max-5: calc(var(--u-max-4) * var(--u-max-ratio));
    /* Display extensions, still the same geometric chain: a site never needs
     * to invent a bigger heading step. */
    --u-min-6: calc(var(--u-min-5) * var(--u-min-ratio));
    --u-max-6: calc(var(--u-max-5) * var(--u-max-ratio));
    --u-min-7: calc(var(--u-min-6) * var(--u-min-ratio));
    --u-max-7: calc(var(--u-max-6) * var(--u-max-ratio));
    --u-min-8: calc(var(--u-min-7) * var(--u-min-ratio));
    --u-max-8: calc(var(--u-max-7) * var(--u-max-ratio));

    /* --- Type scale ---------------------------------------------------- */
    /* step--2 fine print · step-0 body · step-2/3 section headings ·
     * step-4/5 hero display. Use these, not raw px. */
    --step--2: clamp(calc(var(--u-min--2) * 1rem), calc(var(--u-min--2) * 1rem + (var(--u-max--2) - var(--u-min--2)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max--2) * 1rem));
    --step--1: clamp(calc(var(--u-min--1) * 1rem), calc(var(--u-min--1) * 1rem + (var(--u-max--1) - var(--u-min--1)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max--1) * 1rem));
    --step-0: clamp(calc(var(--u-min-0) * 1rem), calc(var(--u-min-0) * 1rem + (var(--u-max-0) - var(--u-min-0)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-0) * 1rem));
    --step-1: clamp(calc(var(--u-min-1) * 1rem), calc(var(--u-min-1) * 1rem + (var(--u-max-1) - var(--u-min-1)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-1) * 1rem));
    --step-2: clamp(calc(var(--u-min-2) * 1rem), calc(var(--u-min-2) * 1rem + (var(--u-max-2) - var(--u-min-2)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-2) * 1rem));
    --step-3: clamp(calc(var(--u-min-3) * 1rem), calc(var(--u-min-3) * 1rem + (var(--u-max-3) - var(--u-min-3)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-3) * 1rem));
    --step-4: clamp(calc(var(--u-min-4) * 1rem), calc(var(--u-min-4) * 1rem + (var(--u-max-4) - var(--u-min-4)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-4) * 1rem));
    --step-5: clamp(calc(var(--u-min-5) * 1rem), calc(var(--u-min-5) * 1rem + (var(--u-max-5) - var(--u-min-5)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-5) * 1rem));
    --step-6: clamp(calc(var(--u-min-6) * 1rem), calc(var(--u-min-6) * 1rem + (var(--u-max-6) - var(--u-min-6)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-6) * 1rem));
    --step-7: clamp(calc(var(--u-min-7) * 1rem), calc(var(--u-min-7) * 1rem + (var(--u-max-7) - var(--u-min-7)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-7) * 1rem));
    --step-8: clamp(calc(var(--u-min-8) * 1rem), calc(var(--u-min-8) * 1rem + (var(--u-max-8) - var(--u-min-8)) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-max-8) * 1rem));

    /* --- Weight -------------------------------------------------------- */
    /* Named by the CSS value, not by a word. "bold" is a claim about how a
     * typeface renders; 700 is what you actually asked for, and two faces
     * disagree about which of their cuts reads as bold.
     *
     * THREE WEIGHTS, DELIBERATELY. Body, emphasis, headline — that is the
     * whole system, and it is expressed by which tokens exist rather than by
     * a rule asking politely. Adding --weight-800 needs a reason: the face
     * has a visibly distinct heavy cut AND 700 alone is not creating enough
     * contrast. If 700 and 800 render identically on screen, that is not one.
     * A flat hierarchy is almost always a spacing or size problem, not a
     * weight problem. */
    --weight-400: 400;  /* body */
    --weight-600: 600;  /* nav, card emphasis, eyebrows */
    --weight-700: 700;  /* headlines, CTAs */

    /* --- Leading ------------------------------------------------------- */
    /* A ladder rather than a derived scale, so it is t-shirt sized like
     * --space-* rather than numbered like --step-*. Tightest to loosest.
     *
     * The relationship worth holding: line-height falls as type size rises.
     * Display type at body leading looks unset; body copy at display leading
     * is unreadable. Pair --leading-xs with --step-4/5 and --leading-l with
     * --step-0. */
    --leading-xs: 1.05;   /* display, very large headlines */
    --leading-s: 1.18;     /* headings */
    --leading-m: 1.3;    /* subheadings, ledes, card copy */
    --leading-l: 1.5;     /* body copy */
    --leading-xl: 1.6;   /* long-form and small print, which need more air */

    /* --- Tracking ------------------------------------------------------ */
    /* Same shape: a ladder, tightest to loosest, in em so it scales with
     * whatever size it is applied to.
     *
     * The relationship: tracking tightens as size grows, and ALL-CAPS always
     * needs opening up — uppercase at 0 tracking reads cramped at any size.
     * Pair --tracking-xs with --step-4/5, --tracking-m with body, and
     * --tracking-l or --tracking-xl with any text-transform: uppercase. */
    --tracking-xs: -0.02em;  /* large display */
    --tracking-s: -0.01em;   /* headings */
    --tracking-m: 0;         /* body — the default, stated so it can be reset to */
    --tracking-l: 0.04em;    /* small caps-ish, buttons */
    --tracking-xl: 0.08em;   /* eyebrows and other all-caps runs */

    /* --- Space scale --------------------------------------------------- */
    /* Multiples of the space unit (--u-space-min / --u-space-max) rather than
     * the type ratio, so spacing stays predictable while type can be as
     * dramatic as the site needs. DO NOT redeclare these per site: tune the
     * --u-* knobs above and every step and pair follows. */
    --space-3xs: clamp(calc(var(--u-space-min) * 0.25rem), calc(var(--u-space-min) * 0.25rem + (var(--u-space-max) * 0.3 - var(--u-space-min) * 0.25) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 0.3rem));
    --space-2xs: clamp(calc(var(--u-space-min) * 0.5rem), calc(var(--u-space-min) * 0.5rem + (var(--u-space-max) * 0.5 - var(--u-space-min) * 0.5) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 0.5rem));
    --space-xs: clamp(calc(var(--u-space-min) * 0.75rem), calc(var(--u-space-min) * 0.75rem + (var(--u-space-max) * 0.75 - var(--u-space-min) * 0.75) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 0.75rem));
    --space-s: clamp(calc(var(--u-space-min) * 1rem), calc(var(--u-space-min) * 1rem + (var(--u-space-max) * 1 - var(--u-space-min) * 1) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 1rem));
    --space-m: clamp(calc(var(--u-space-min) * 1.5rem), calc(var(--u-space-min) * 1.5rem + (var(--u-space-max) * 1.5 - var(--u-space-min) * 1.5) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 1.5rem));
    --space-l: clamp(calc(var(--u-space-min) * 2rem), calc(var(--u-space-min) * 2rem + (var(--u-space-max) * 2 - var(--u-space-min) * 2) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 2rem));
    --space-xl: clamp(calc(var(--u-space-min) * 3rem), calc(var(--u-space-min) * 3rem + (var(--u-space-max) * 3 - var(--u-space-min) * 3) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 3rem));
    --space-2xl: clamp(calc(var(--u-space-min) * 4rem), calc(var(--u-space-min) * 4rem + (var(--u-space-max) * 4 - var(--u-space-min) * 4) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 4rem));
    --space-3xl: clamp(calc(var(--u-space-min) * 6rem), calc(var(--u-space-min) * 6rem + (var(--u-space-max) * 6 - var(--u-space-min) * 6) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 6rem));
    --space-4xl: clamp(calc(var(--u-space-min) * 8rem), calc(var(--u-space-min) * 8rem + (var(--u-space-max) * 8 - var(--u-space-min) * 8) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 8rem));

    /* --- Space pairs --------------------------------------------------- */
    /* A pair moves from the SMALLER step on a phone to the LARGER one on a
     * desktop, so the gap changes step rather than merely scaling. This is what
     * replaces per-breakpoint section padding: --space-l-2xl is roughly the old
     * "40-48px mobile, 80-96px desktop" rule, expressed once. */
    --space-2xs-xs: clamp(calc(var(--u-space-min) * 0.5rem), calc(var(--u-space-min) * 0.5rem + (var(--u-space-max) * 0.75 - var(--u-space-min) * 0.5) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 0.75rem));
    --space-xs-s: clamp(calc(var(--u-space-min) * 0.75rem), calc(var(--u-space-min) * 0.75rem + (var(--u-space-max) * 1 - var(--u-space-min) * 0.75) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 1rem));
    --space-s-m: clamp(calc(var(--u-space-min) * 1rem), calc(var(--u-space-min) * 1rem + (var(--u-space-max) * 1.5 - var(--u-space-min) * 1) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 1.5rem));
    --space-m-l: clamp(calc(var(--u-space-min) * 1.5rem), calc(var(--u-space-min) * 1.5rem + (var(--u-space-max) * 2 - var(--u-space-min) * 1.5) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 2rem));
    --space-l-xl: clamp(calc(var(--u-space-min) * 2rem), calc(var(--u-space-min) * 2rem + (var(--u-space-max) * 3 - var(--u-space-min) * 2) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 3rem));
    --space-xl-2xl: clamp(calc(var(--u-space-min) * 3rem), calc(var(--u-space-min) * 3rem + (var(--u-space-max) * 4 - var(--u-space-min) * 3) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 4rem));
    --space-l-2xl: clamp(calc(var(--u-space-min) * 2rem), calc(var(--u-space-min) * 2rem + (var(--u-space-max) * 4 - var(--u-space-min) * 2) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 4rem));
    --space-s-l: clamp(calc(var(--u-space-min) * 1.125rem), calc(var(--u-space-min) * 1.125rem + (var(--u-space-max) * 2 - var(--u-space-min) * 1.125) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 2rem));  /* skip-a-step: grid gutter */
    --space-2xl-3xl: clamp(calc(var(--u-space-min) * 4rem), calc(var(--u-space-min) * 4rem + (var(--u-space-max) * 6 - var(--u-space-min) * 4) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 6rem));
    --space-3xl-4xl: clamp(calc(var(--u-space-min) * 6rem), calc(var(--u-space-min) * 6rem + (var(--u-space-max) * 8 - var(--u-space-min) * 6) * (100vw - var(--u-min-vw) * 1px) / var(--u-vw-range) * 16), calc(var(--u-space-max) * 8rem));

    /* --- Measure ------------------------------------------------------- */
    --measure: 65ch;        /* body copy */
    --measure-tight: 45ch;  /* card and caption copy */

    /* =====================================================================
     * COLOUR
     *
     * Three anchors drive the whole palette. Change them to match the
     * practice; everything else follows. See refs/design/DESIGN.md.
     *
     * That is the default path, and most sites never go past it. Underneath,
     * the palette is layered so a site can take more control WITHOUT hand-
     * writing hex values, which is what a migrated site needs:
     *
     *   1. Anchors        the three below. Tune these first.
     *   2. Per-role       --chroma-secondary, --l-tertiary and friends. A
     *                     brand's second colour is a designer's pick, not a
     *                     rotation of the first, so each role carries its own
     *                     hue, chroma and lightness, defaulting to the anchors.
     *   3. Neutrals       --hue-neutral, --chroma-ink, --chroma-ground. Greys
     *                     are their own decision -- see the block below.
     *   4. Polarity       --scheme. One number flips light/dark.
     *
     * Derive WITHIN a role, declare ACROSS roles. This is the same split
     * Bootstrap 5.3 makes (mix() generates each scale; the base of each theme
     * colour is declared) and the opposite of deriving everything from one
     * hue, which cannot express a real brand pair.
     *
     *   --palette-hue         the practice's brand hue, 0-360.
     *                         Roughly: 25 terracotta · 60 ochre · 145 green
     *                         · 195 teal · 240 blue · 275 violet · 340 rose
     *   --palette-chroma      how saturated the brand reads. OKLCH chroma is
     *                         NOT 0-1 — it runs about 0-0.37 in sRGB, and
     *                         above ~0.15 a surface colour starts to shout.
     *                         0.04 muted · 0.09 confident · 0.14 vivid
     *   --palette-secondary-shift
     *                         degrees from the primary to the secondary.
     *                         150-180 gives a complement; 30-60 an analogous
     *                         neighbour that reads calmer.
     * ===================================================================== */
    --palette-hue: 195;
    --palette-chroma: 0.09;
    --palette-secondary-shift: 150;

    --hue-primary: var(--palette-hue);
    --hue-secondary: calc(var(--palette-hue) + var(--palette-secondary-shift));

    /* Secondary and tertiary each carry their OWN chroma and lightness, not
     * the primary's. They default to it, so a site built from this template
     * still tunes with the three numbers above and renders identically.
     *
     * The override exists because a brand's second colour is often a designer's
     * choice rather than a systematic partner: on a migrated site the secondary
     * was measured at 3.6x the primary's chroma and 0.26 lighter in OKLCH
     * (deep forest green against warm terracotta). One shared chroma and one
     * shared lightness cannot express that pair, and forcing it produced a
     * washed-out grey-green beside a dusty mauve.
     *
     * This is the same concession the feedback colours below already make --
     * each of those carries its own chroma because "yellows need more to read
     * as yellow, reds less before they turn fluorescent". Brand colours want
     * the same latitude. */
    --chroma-secondary: var(--palette-chroma);
    --l-secondary: var(--l-solid);

    /* Tertiary: a third brand colour, typically doing button/CTA work, that is
     * neither a tint of the primary nor semantic. Practices routinely have one
     * ("Button Brown", "Morning Orange"). Defaults to an analogous neighbour of
     * the primary so it is harmless when unused. */
    --palette-tertiary-shift: 30;
    --hue-tertiary: calc(var(--palette-hue) + var(--palette-tertiary-shift));
    --chroma-tertiary: var(--palette-chroma);
    --l-tertiary: var(--l-solid);

    /* --- Neutrals: their own hue, not the brand's ---------------------
     *
     * --hue-neutral defaults to the brand hue, so a site that sets nothing
     * keeps the "greys feel of a piece with the accent" behaviour. But it is
     * a SEPARATE dial, because tying greys to the brand hue is not what any
     * mature system does and not what real practices choose:
     *
     *   - Tailwind ships five grey families (slate/gray/zinc/neutral/stone)
     *     precisely so the temperature of the greys is a decision.
     *   - Bootstrap keeps $gray independent of $theme-colors.
     *   - daisyUI declares base-100/200/300 per theme.
     *
     * And measured on our own migrated sites: both chose warm grounds at hue
     * 80-94 despite green brands at 145 and 166 -- roughly 80 degrees off the
     * brand. A green practice does not want green text, and at the default
     * hue 195 the old derivation gave --ink-strong an R-to-B spread of 17,
     * i.e. a visibly blue-black rather than a black.
     *
     * Set --hue-neutral to taste: the brand hue for a tinted-grey scheme, a
     * warm 70-90 for a settled off-black, or leave chroma at 0 for a true
     * neutral. --chroma-ink and --chroma-ground are separate because ink
     * carries tint better than a large ground does -- the same chroma that
     * reads as "warm grey" in a heading reads as "the wrong white" across a
     * full-bleed background. */
    /* +80 deg off the brand, which is what the previous code already did for
     * --ink-strong alone, and what both migrated practices independently
     * chose for their grounds (warm 80-94 against green brands at 145/166).
     * It defaults to the brand hue so that adding this dial changes nothing on
     * an existing site; the interesting values are elsewhere:
     *
     *   var(--palette-hue)              greys tinted toward the brand (default)
     *   calc(var(--palette-hue) + 80)   the offset real practices tend to pick
     *   70-90                           a warm, settled off-black
     *   with --chroma-ink: 0            a true neutral, no hue at all
     */
    --hue-neutral: var(--palette-hue);
    --chroma-ink: 0.012;    /* text. 0 = true grey; 0.03 = clearly tinted */
    --chroma-ground: calc(0.004 + 0.008 * (1 - var(--scheme)));  /* page background */
    --chroma-surface: calc(0.000 + 0.014 * (1 - var(--scheme))); /* raised surfaces */
    --chroma-border: calc(0.008 + 0.007 * (1 - var(--scheme)));  /* rules and outlines */
    /* Grounds carry MORE tint when dark and less when light: 0.014 across a
     * near-black reads as a warm dark, the same 0.014 across a near-white
     * reads as a colour cast. The old code expressed this by declaring the
     * light and dark neutrals separately; here it rides on --scheme. */

    /* Feedback hues are FIXED and do not follow the brand. A danger colour
     * that rotates with the practice's hue stops reading as danger — the
     * entire value of a semantic colour is that it means the same thing on
     * every site. Only the brand colours above derive from --palette-hue. */
    --hue-success: 145;
    --hue-warning: 75;
    --hue-danger: 27;
    --hue-info: 240;

    /* Lightness ramp. Dark mode overrides these below rather than declaring a
     * second palette — in OKLCH, dark mode is largely an inversion of these
     * four numbers. */
    --l-solid: 0.55;   /* solid fills: buttons, badges */
    --l-hover: 0.48;   /* one step darker for hover */
    --l-light: 0.66;   /* one step lighter: gradient partner for --primary */
    --l-muted: 0.92;   /* a touch stronger than pale, for wash gradients */
    --l-pale: 0.96;    /* tinted backgrounds */
    --l-on-solid: 0.99;/* text on a solid fill */

    /* --- Polarity -----------------------------------------------------
     *
     * --scheme is the one number that says which way round the site runs:
     * 1 = dark ink on a light ground (the norm), 0 = light ink on a dark
     * ground. Every neutral below is written as "light value, plus the
     * distance to its dark counterpart, times (1 - scheme)", so flipping the
     * one number inverts the whole set consistently.
     *
     * This is why the dark-mode block further down only sets --scheme and the
     * three brand-lightness values, instead of re-declaring eight neutrals
     * with a second set of hand-picked literals. Two hand-maintained sets
     * drift: the old block never declared --ink-strong at all, so headings
     * stayed at lightness 0.18 -- dark text on a dark ground.
     *
     * A site that should ALWAYS render dark sets --scheme: 0 here and deletes
     * the media query. A site that should never flip deletes the query alone. */
    --scheme: 1;
    color-scheme: light;

    /* Neutral lightness, light-mode value first, dark-mode value second.
     * Edit these to shift contrast; they are dials, not literals buried in
     * the colour definitions. */
    --l-ink-strong: calc(0.18 + 0.79 * (1 - var(--scheme)));
    --l-ink:        calc(0.25 + 0.70 * (1 - var(--scheme)));
    --l-ink-mid:    calc(0.45 + 0.35 * (1 - var(--scheme)));
    --l-ink-soft:   calc(0.54 + 0.12 * (1 - var(--scheme)));
    --l-bg:         calc(0.99 - 0.81 * (1 - var(--scheme)));
    --l-surface:    calc(1.00 - 0.78 * (1 - var(--scheme)));
    --l-border:     calc(0.90 - 0.58 * (1 - var(--scheme)));
    --l-border-strong: calc(0.82 - 0.40 * (1 - var(--scheme)));

    /* Brand */
    --primary: oklch(var(--l-primary, var(--l-solid)) var(--palette-chroma) var(--hue-primary));
    --primary-hover: oklch(var(--l-hover) var(--palette-chroma) var(--hue-primary));
    --primary-light: oklch(var(--l-light) var(--palette-chroma) var(--hue-primary));
    --primary-muted: oklch(var(--l-muted) calc(var(--palette-chroma) * 0.35) var(--hue-primary));
    /* Chroma falls as lightness rises — a pale tint at full chroma reads
     * muddy rather than tinted. */
    --primary-pale: oklch(var(--l-pale) calc(var(--palette-chroma) * 0.25) var(--hue-primary));
    --on-primary: oklch(var(--l-on-solid) 0 0);

    --secondary: oklch(var(--l-secondary) var(--chroma-secondary) var(--hue-secondary));
    --secondary-hover: oklch(calc(var(--l-secondary) - 0.07) var(--chroma-secondary) var(--hue-secondary));
    --secondary-light: oklch(calc(var(--l-secondary) + 0.11) var(--chroma-secondary) var(--hue-secondary));
    --secondary-pale: oklch(var(--l-pale) calc(var(--chroma-secondary) * 0.25) var(--hue-secondary));
    --on-secondary: oklch(var(--l-on-solid) 0 0);

    /* Tertiary, same shape as the two above. */
    --tertiary: oklch(var(--l-tertiary) var(--chroma-tertiary) var(--hue-tertiary));
    --tertiary-hover: oklch(calc(var(--l-tertiary) - 0.07) var(--chroma-tertiary) var(--hue-tertiary));
    --tertiary-pale: oklch(var(--l-pale) calc(var(--chroma-tertiary) * 0.25) var(--hue-tertiary));
    --on-tertiary: oklch(var(--l-on-solid) 0 0);

    /* Aliases for the older names in DESIGN.md, so existing markup and any
     * site copied from an earlier template keep working. */
    --accent: var(--primary);
    --accent-dark: var(--primary-hover);
    --accent-pale: var(--primary-pale);

    /* Feedback. Chroma is per-hue: yellows need more to read as yellow, reds
     * less before they turn fluorescent. */
    --success: oklch(calc(var(--l-solid) - 0.03) 0.13 var(--hue-success));
    --success-pale: oklch(var(--l-pale) 0.03 var(--hue-success));
    --warning: oklch(0.75 0.14 var(--hue-warning));
    --warning-pale: oklch(var(--l-pale) 0.04 var(--hue-warning));
    --danger: oklch(var(--l-solid) 0.17 var(--hue-danger));
    --danger-pale: oklch(var(--l-pale) 0.03 var(--hue-danger));
    --info: oklch(var(--l-solid) 0.11 var(--hue-info));
    --info-pale: oklch(var(--l-pale) 0.03 var(--hue-info));

    /* Neutrals. DESIGN.md asked in prose for "a teal practice and a navy
     * practice want different --ink warmth"; --hue-neutral is that, made a
     * dial instead of a fixed derivation from the brand.
     *
     * Hue and chroma come from the --hue-neutral / --chroma-*
     * dials above, lightness from the --l-* dials, so all three are tunable
     * without editing any of these lines. Ink chroma tapers as text gets
     * lighter, and grounds use the lower --chroma-ground throughout. */
    --ink-strong: oklch(var(--l-ink-strong) calc(var(--chroma-ink) * 2.5) calc(var(--hue-neutral) + 80));  /* headings, dark surfaces */
    --ink: oklch(var(--l-ink) calc(var(--chroma-ink) * 1.25) var(--hue-neutral));
    --ink-mid: oklch(var(--l-ink-mid) var(--chroma-ink) var(--hue-neutral));
    --ink-soft: oklch(var(--l-ink-soft) calc(var(--chroma-ink) * 0.833) var(--hue-neutral));
    --bg: oklch(var(--l-bg) var(--chroma-ground) var(--hue-ground, var(--hue-neutral)));
    --surface: oklch(var(--l-surface) var(--chroma-surface) var(--hue-neutral));
    --border: oklch(var(--l-border) var(--chroma-border) var(--hue-neutral));
    --border-strong: oklch(var(--l-border-strong) calc(var(--chroma-border) * 1.25) var(--hue-neutral));

    /* Paired foreground for each ground, the way daisyUI's -content and
     * Bootstrap's -emphasis work. Use --on-bg rather than reaching for --ink
     * directly when the ground itself might be flipped. */
    --on-bg: var(--ink);
    --on-surface: var(--ink);

    /* --- Grid ---------------------------------------------------------- */
    /* Deliberately minimal: the container and gutter are fluid, placement is
     * left to each layout. Use .u-container and .u-grid below. */
    --grid-max-width: 77.5rem;
    --grid-gutter: var(--space-s-l);
    --grid-columns: 12;

    /* --- Radius -------------------------------------------------------- */
    /* Named by intent rather than by number, so a change of scale does not
     * mean auditing every --radius-3 in the stylesheet. */
    --radius-xs: 0.25rem;   /* tags, inline chips */
    --radius-s: 0.5rem;     /* buttons, inputs */
    --radius-m: 0.75rem;    /* cards */
    --radius-l: 1.25rem;    /* panels, modals, hero media */
    --radius-round: 50%;    /* avatars */
    --radius-pill: 999px;   /* pills, badges */

    /* --- Border widths ------------------------------------------------- */
    --border-thin: 1px;
    --border-medium: 2px;
    --border-thick: 4px;    /* accent rules, active states */

    /* --- Touch targets ------------------------------------------------- */
    /* The smallest box a finger hits reliably: 44px (WCAG 2.5.5, Apple's
     * HIG). A fixed dimension rather than spacing, so it does not scale. */
    --target-min: 2.75rem;
    /* The gold nav bar's height, 79px measured on live. A fixed dimension. */
    --navbar-h: 4.9375rem;

    /* --- Shadows ------------------------------------------------------- */
    /* Two knobs drive every shadow. --shadow-color takes the brand hue so a
     * raised card reads as part of this practice rather than as generic grey;
     * --shadow-strength is what dark mode adjusts, because a shadow on a dark
     * background needs MORE opacity to be seen, not less. */
    --shadow-color: var(--hue-primary, 220) 20% 15%;
    --shadow-strength: 1%;

    --shadow-s:
        0 1px 2px -1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%));
    --shadow-m:
        0 3px 5px -2px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)),
        0 7px 14px -5px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%));
    --shadow-l:
        0 -1px 3px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 2%)),
        0 6px 12px -3px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 3%)),
        0 15px 30px -6px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 5%));

    --shadow-inner-s: inset 0 1px 2px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 6%));
    --shadow-inner-m: inset 0 2px 6px 0 hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%));

    /* --- Layers -------------------------------------------------------- */
    /* Six values, so z-index is never invented at the call site. */
    --layer-behind: -1;    /* decorative washes sitting behind content */
    --layer-base: 1;
    --layer-raised: 2;      /* hover cards, sticky rows */
    --layer-nav: 3;         /* sticky header */
    --layer-overlay: 4;     /* dropdowns, popovers */
    --layer-modal: 5;       /* dialogs and their backdrop */
    --layer-top: 2147483647;/* skip links, live-region alerts */

    /* --- Motion -------------------------------------------------------- */
    --duration-fast: 120ms;   /* hover, focus */
    --duration-base: 220ms;   /* most transitions */
    --duration-slow: 400ms;   /* entrances */
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --reveal-distance: 1.5rem;

    /* Typefaces. Set these per site; everything else references them. */
    --font-body: system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-heading: var(--font-body);   /* override for a display face */
}

/*
 * Dark mode. In OKLCH this is mostly an inversion of the lightness ramp
 * rather than a second palette — the hues and chroma above are unchanged.
 *
 * Two things are not simple inversions and are set explicitly:
 *   - the accent gets LIGHTER (0.68, not 0.55), because a mid-lightness
 *     accent loses contrast against a dark background;
 *   - --shadow-strength rises, because a shadow on a dark surface needs more
 *     opacity to be visible at all.
 *
 * Delete this block for a site that should only ever render light.
 */
/* Ayr Medical Group renders light only, as live does: the dark-scheme block
 * that lived here is deleted (the template's own instruction for a light-only
 * site) and color-scheme is pinned above, so UA widgets match. */

/* ═══════════════════════════════════════════════════════════════════════
 * RESET
 *
 * Josh Comeau's Custom CSS Reset (joshwcomeau.com/css/custom-css-reset/),
 * lightly adapted. Normalises browser defaults so the base layer below is
 * building on the same ground in every browser. Leave this alone; make
 * design decisions in the base layer and the tokens above it.
 * ═══════════════════════════════════════════════════════════════════════ */

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

/* Skip link. craft.md requires one as the first element in <body>; without a
 * rule here it renders as a visible link above the header on every site. It is
 * off-screen until focused, then a real control with a visible focus ring. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: var(--layer-top, 2147483647);
    padding: var(--space-xs) var(--space-s);
    background: var(--accent);
    color: var(--on-primary);
    text-decoration: none;
    border-radius: 0 0 0.25rem 0;
}
.skip-link:focus, .skip-link:focus-visible {
    left: 0;
}

* { margin: 0; }

html {
    -webkit-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    -webkit-font-smoothing: antialiased;
    line-height: 1.5;
}

/* Media is block-level and never overflows its container. */
img, picture, video, canvas, svg {
    display: block;
    max-width: 100%;
}

/* Form controls inherit typography rather than using browser chrome. */
:where(input, button, textarea, select) { font: inherit; }   /* zero specificity: "Form controls" below must win */

/* Long words and URLs wrap instead of forcing a horizontal scrollbar. */
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }

/* A new stacking context on the root, so app-level layers cannot escape. */
#root, #__next { isolation: isolate; }

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

/* ═══════════════════════════════════════════════════════════════════════
 * ELEMENT BASE LAYER
 *
 * Bare elements are styled here so a page is correct with no classes at
 * all. Without this, an unclassed <h2> falls back to the browser default
 * and whoever writes the page patches it with an inline style — which is
 * how a site ends up with a different heading treatment per page.
 *
 * Every heading has a matching .h1-.h6 class. Use the ELEMENT for document
 * structure (SEO, screen readers, outline) and the CLASS for appearance,
 * so an <h1> can look like an eyebrow without lying about the hierarchy:
 *
 *     <h1 class="h4">Still the page's real heading, just smaller</h1>
 *
 * Sites override these; they are a floor, not a straitjacket.
 * ═══════════════════════════════════════════════════════════════════════ */

body {
    font-family: var(--font-body);
    font-size: var(--step-0);
    font-weight: var(--weight-400);
    line-height: var(--leading-l);
    color: var(--ink);
    background: var(--bg);
}

/* Headings ─────────────────────────────────────────────────────────────
 * Margins are top-heavy on purpose: a heading belongs to what follows it,
 * so the space above is larger than the space below. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    margin: var(--space-l) 0 var(--space-s);
    font-family: var(--font-heading);
    font-weight: var(--weight-700);
    line-height: var(--leading-s);
    letter-spacing: var(--tracking-xs);
    color: var(--ink-strong);
    text-wrap: balance;
}

:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) + * {
    margin-top: 0;
}

/* A heading opening its container needs no space above it. */
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6):first-child {
    margin-top: 0;
}

h1, .h1 { font-size: var(--step-5); }
h2, .h2 { font-size: var(--step-4); }
h3, .h3 { font-size: var(--step-3); }
h4, .h4 { font-size: var(--step-2); }
h5, .h5 { font-size: var(--step-1); line-height: var(--leading-m); }
h6, .h6 {
    font-size: var(--step-0);
    line-height: var(--leading-m);
    letter-spacing: var(--tracking-m);
    text-transform: uppercase;
}

/* A highlighted phrase inside a heading. One mechanism, not three. */
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) em {
    font-style: italic;
    color: var(--primary);
}

/* Text ─────────────────────────────────────────────────────────────── */
p, ul, ol, dl, blockquote, figure, table, pre {
    margin: 0 0 var(--space-m);
}

/*
 * Line length is a container's job, not every paragraph's — capping each <p>
 * leaves text hugging the left of any column already sized for reading.
 * Use .measure (or set a width on the container) where prose needs it.
 */
.measure { max-width: var(--measure); }
.measure-tight { max-width: var(--measure-tight); }

/* Opening paragraph: larger and looser than body copy. */
.lede {
    font-size: var(--step-1);
    line-height: var(--leading-m);
    color: var(--ink-mid);
}

/* Small label above a heading. */
.eyebrow {
    display: block;
    margin-bottom: var(--space-2xs);
    font-size: var(--step--1);
    font-weight: var(--weight-600);
    letter-spacing: var(--tracking-l);
    text-transform: uppercase;
    color: var(--primary);
}

small, .text-small { font-size: var(--step--1); }

strong, b { font-weight: var(--weight-700); }

a {
    color: var(--primary);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
    transition: color var(--duration-fast) var(--ease-out);
}
a:hover { color: var(--primary-hover); }

ul, ol { padding-left: var(--space-m); }

/*
 * List spacing applies to PROSE lists only. Navigation, button groups and
 * card grids are lists too, and flow margins on those knock flex/grid items
 * out of alignment (the site header) or balloon the spacing (the footer).
 *
 * Presence of a class is not the test — a footer nav is a nav whether or not
 * anyone put a class on it — so navigation context opts out explicitly.
 */
:where(ul, ol) > li { margin-bottom: var(--space-2xs); }
:where(ul, ol) > li:last-child { margin-bottom: 0; }

nav ul, nav ol,
header ul, header ol,
footer ul, footer ol,
menu {
    margin: 0;
    padding-left: 0;
    list-style: none;
}

nav li, header li, footer li, menu li {
    margin-bottom: 0;
}

/* A list explicitly used for layout carries no bullets, indent or margin. */
:where(ul, ol)[class] {
    margin: 0;
    padding-left: 0;
    list-style: none;
}

:where(ul, ol)[class] > li { margin-bottom: 0; }

blockquote {
    padding-left: var(--space-m);
    border-left: var(--border-thick) solid var(--primary-pale);
    color: var(--ink-mid);
    font-style: italic;
}

hr {
    height: 0;
    margin: var(--space-l) 0;
    border: 0;
    border-top: var(--border-thin) solid var(--border);
}

code, kbd, samp, pre {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.9em;
}

/* Media ────────────────────────────────────────────────────────────────
 * Images carry NO radius and NO background plate by default.
 *
 * They used to. `img { border-radius: var(--radius-m); background: var(--surface) }`
 * was added to fix one square photo on Wellbrook, and it cost far more than it
 * saved: every migration since has had to undo it, because a faithful clone of a
 * customer's live site decides its own corners, and the background plate fills
 * the transparent areas of every PNG and SVG — a logo on a dark footer renders
 * as a solid block. Ten of the thirteen sites on this box carried an override
 * for it before it was removed.
 *
 * A radius is a design decision belonging to the site's own stylesheet, next to
 * the cards it should match. Use .is-rounded (below) or a site-layer rule; do
 * not put it back here. */
img, picture, video, canvas, svg {
    height: auto;
}

/* Opt in where a photo should match the radius of the cards around it. */
img.is-rounded, .is-rounded img { border-radius: var(--radius-m); }

figure { margin-inline: 0; }

figcaption {
    margin-top: var(--space-2xs);
    font-size: var(--step--1);
    color: var(--ink-soft);
}

/* Tables ───────────────────────────────────────────────────────────── */
table {
    width: 100%;
    border-collapse: collapse;
    text-align: left;
}

th, td {
    padding: var(--space-2xs) var(--space-xs);
    border-bottom: var(--border-thin) solid var(--border);
    vertical-align: top;
}

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

tbody tr:last-child :where(th, td) { border-bottom: 0; }

/* ═══ Form controls & focus ═══ form-controls:begin ══════════════════════
 * A text field's look, and every focus ring on the site, are set ONCE,
 * here: by the --field-* and --focus-ring* tokens and a few base rules.
 * Every text-like control on the site (contact, search, careers, booking,
 * anything mediflare.js or Connect writes) inherits it, so they match by
 * construction.
 *
 * - This section is copied VERBATIM from _template and never edited in a
 *   site: check-system.sh fails the site if its copy differs by a character.
 *   A site differs only in TOKEN VALUES, set in the site layer's own :root,
 *   below this section (a later :root wins over the defaults here).
 * - Never restyle a control inside a component. A component rule may place
 *   a field (grid, margin, width) but never sets its border, radius,
 *   background or height -- check-system.sh fails the site if one does.
 * - Fields and buttons share ONE corner, --control-radius: set it in the
 *   site layer's :root and both follow. Never set --field-radius
 *   (check-system.sh fails it), except to 0 in underline mode below;
 *   pill buttons mean pill fields.
 * - The base rules are at zero specificity (:where), so any token change
 *   reaches every field and nothing here outranks a deliberate override.
 * - ONE focus ring per site, on links, buttons and fields alike: an outline
 *   in --focus-ring at --focus-ring-w. No other rule sets a focus outline,
 *   colour or box-shadow (check-system.sh fails one); outline-offset may be
 *   adjusted where a ring would be clipped.
 * - Underline-only fields: set --field-border-w: 0,
 *   --field-border-bottom: var(--border-thin) solid <colour> and
 *   --field-radius: 0 (an underline has no corners to share; a rounded one
 *   curves at its ends, and buttons keep --control-radius); optionally
 *   --field-focus-border-bottom: var(--focus-ring-w) solid var(--focus-ring)
 *   so the underline thickens with the ring. No extra rules. Underline
 *   mode is the only time a site sets --field-radius, and check-system.sh
 *   then requires the 0.
 * - Dark panels and bands: the container re-sets the tokens for its
 *   descendants, never the rules. Tokens defined here are resolved on :root,
 *   so re-set the leaf values, not the ones they derive from:
 *     .band--dark {
 *         --focus-ring: var(--surface);
 *         --field-bg: transparent;
 *         --field-ink: var(--on-primary);
 *         --field-border: var(--on-primary);
 *         --field-placeholder: color-mix(in oklab, var(--on-primary) 70%, transparent);
 *     }
 *   --focus-ring must reach >= 3:1 against every ground it is drawn on.
 * The guard finds this section by the begin/end markers; keep both.
 * ═══════════════════════════════════════════════════════════════════════ */

:root {
    --field-h: var(--target-min);                 /* the single-line height: exact, never below the 44px target */
    --field-textarea-h: calc(var(--field-h) * 3); /* the textarea's minimum height */
    --field-pad-block: var(--space-2xs);          /* textarea only; a one-line field centres its text in --field-h */
    --field-pad-inline: var(--space-xs);
    --field-font-size: max(var(--step-0), 1rem);  /* never below 16px, or iOS zooms the page on focus */
    --field-leading: var(--leading-m);
    --field-weight: var(--weight-400);            /* one weight wherever the field sits */
    --field-radius: var(--control-radius);        /* = the .btn radius, by construction; never set it */
    --field-textarea-radius: min(var(--field-radius), var(--radius-l));   /* a pill textarea is a capsule; cap it */
    --field-bg: var(--surface);
    --field-ink: var(--ink);
    --field-border-w: var(--border-thin);
    --field-border: var(--border-strong);
    --field-border-hover: var(--ink-soft);
    --field-placeholder: var(--ink-soft);
    /* Unset by default, so they follow --field-border-w/--field-border:
     * --field-border-bottom          the resting bottom edge (underline mode)
     * --field-focus-border-bottom    the bottom edge while focused
     * --field-focus-outline          the field's ring; leave it to the default */
    --focus-ring: var(--primary);                 /* >= 3:1 against --bg, --field-bg and every ground it lands on */
    --focus-ring-w: var(--border-medium);         /* >= --field-border-w, so the ring covers the border */
}

/* THE focus ring: every interactive element, always. Fields refine the
 * offset and radius below; nothing else sets a focus outline. */
:focus-visible {
    outline: var(--focus-ring-w) solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius-xs);
}

label {
    display: block;
    margin-bottom: var(--space-3xs);
    font-size: var(--step--1);
    font-weight: var(--weight-600);
    color: var(--ink-strong);
}

/* THE base rule. Every text-like control: text, email, tel, search, number,
 * date, url, password, select and textarea -- not checkboxes, radios,
 * ranges, files or button-type inputs. */
:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=submit],[type=button],[type=reset],[type=image],[type=hidden]), select, textarea) {
    --_field-radius: var(--field-radius);
    appearance: none;
    box-sizing: border-box;
    width: 100%;
    height: var(--field-h);
    min-height: var(--field-h);
    padding: 0 var(--field-pad-inline);
    font: inherit;
    font-size: var(--field-font-size);
    font-weight: var(--field-weight);
    line-height: var(--field-leading);
    color: var(--field-ink);
    background-color: var(--field-bg);
    border: var(--field-border-w) solid var(--field-border);
    border-bottom: var(--field-border-bottom, var(--field-border-w) solid var(--field-border));
    border-radius: var(--_field-radius);
    box-shadow: none;
    transition: border-color var(--duration-fast) var(--ease-out);
}

:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=submit],[type=button],[type=reset],[type=image],[type=hidden]), select, textarea):hover {
    border-color: var(--field-border-hover);
}

/* One edge on focus. The offset pulls the ring in by the border's width, so
 * it is drawn ON the border (covering it) rather than outside it; the border
 * and shadow are held at rest so nothing draws a second edge. Specificity
 * 0,1,0 and later than the global :focus-visible, so it wins over that one
 * (whose offset and radius suit links, not fields). In underline mode the
 * bottom edge may take --field-focus-border-bottom as well. */
:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=submit],[type=button],[type=reset],[type=image],[type=hidden]), select, textarea):focus {
    border-color: var(--field-border);
    border-bottom: var(--field-border-bottom, var(--field-border-w) solid var(--field-border));
    box-shadow: none;
    outline: none;
}
:where(input:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=submit],[type=button],[type=reset],[type=image],[type=hidden]), select, textarea):focus-visible {
    outline: var(--field-focus-outline, var(--focus-ring-w) solid var(--focus-ring));
    outline-offset: calc(var(--field-border-w) * -1);
    border-bottom: var(--field-focus-border-bottom, var(--field-border-bottom, var(--field-border-w) solid var(--field-border)));
    border-radius: var(--_field-radius);
}

:where(textarea) {
    --_field-radius: var(--field-textarea-radius);
    height: auto;
    min-height: var(--field-textarea-h);
    padding-block: var(--field-pad-block);
    resize: vertical;
}

/* The chevron is one conic-gradient wedge in --field-ink: tokens only, no
 * image, so it recolours with the palette and the scheme. (Two half-square
 * linear gradients leave a seam where they meet.) */
:where(select) {
    padding-inline-end: calc(var(--field-pad-inline) * 2 + var(--space-xs));
    background-image: conic-gradient(from -45deg at 50% 100%, var(--field-ink) 90deg, transparent 0);
    background-position: calc(100% - var(--field-pad-inline)) 50%;
    background-size: calc(var(--space-3xs) * 2.5) calc(var(--space-3xs) * 1.25);
    background-repeat: no-repeat;
    cursor: pointer;
}
:where(select[multiple], select[size]) { height: auto; padding-block: var(--field-pad-block); padding-inline-end: var(--field-pad-inline); background-image: none; }

:where(input, textarea)::placeholder { color: var(--field-placeholder); opacity: 1; }

/* The browser's own clear (x) in a search box, redrawn as a mask so it takes
 * --field-ink instead of the browser's grey. */
:where(input[type=search])::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    inline-size: 1em;
    block-size: 1em;
    cursor: pointer;
    background-color: var(--field-ink);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

input[type="checkbox"], input[type="radio"] { accent-color: var(--primary); }

fieldset { margin: 0 0 var(--space-m); padding: 0; border: 0; }

/* ═══ form-controls:end (Form controls & focus) ═════════════════════════ */

/* Buttons size to their content, not to the form-control full width. */
input[type="submit"], input[type="button"] { width: auto; }

/*
 * A bare <button> is usually a UI affordance — a menu toggle, a dropdown
 * trigger — not a visual button, so it gets a reset rather than a look.
 * Add .btn when you want one that looks like a button.
 */
button {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

/* Buttons ──────────────────────────────────────────────────────────────
 * .btn is opt-in — put it on a <button> or an <a> that should look like a
 * button. Variants change colour, sizes change scale. A bare <button> is
 * reset above, not styled, because most of them are menu and dropdown
 * triggers rather than visual buttons. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: var(--target-min);   /* the 44px tap target, every size and variant */
    gap: var(--space-3xs);
    padding: var(--space-2xs) var(--space-s);
    font-family: inherit;
    font-size: var(--step--1);
    font-weight: var(--weight-600);
    line-height: var(--leading-s);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    border: var(--border-thin) solid transparent;
    border-radius: var(--control-radius);   /* shared with every field; set --control-radius, not this */
    transition: background var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
}

.btn--primary {
    background: var(--primary);
    color: var(--on-primary);
}
.btn--primary:hover { background: var(--primary-hover); color: var(--on-primary); }

.btn--secondary {
    background: transparent;
    border-color: var(--primary);
    color: var(--primary);
}
.btn--secondary:hover { background: var(--primary-pale); color: var(--primary-hover); }

.btn--ghost {
    background: transparent;
    color: var(--ink-mid);
}
.btn--ghost:hover { background: var(--primary-pale); color: var(--primary); }

.btn--sm { padding: var(--space-3xs) var(--space-xs); font-size: var(--step--2); }
.btn--lg { padding: var(--space-xs) var(--space-m); font-size: var(--step-0); }

/*
 * ON A DARK GROUND
 *
 * Variants above assume a light background. On a dark or brand-coloured
 * section they invert: the solid button goes white, the outline picks up a
 * translucent white edge. Put .on-dark on the button or any ancestor.
 */
.on-dark .btn--primary,
.btn--primary.on-dark {
    background: var(--surface);
    color: var(--primary);
}

.on-dark .btn--primary:hover,
.btn--primary.on-dark:hover {
    background: var(--surface);
    color: var(--primary-hover);
}

.on-dark .btn--secondary,
.btn--secondary.on-dark {
    color: var(--on-primary);
    border-color: color-mix(in oklab, var(--on-primary) 40%, transparent);
}

.on-dark .btn--secondary:hover,
.btn--secondary.on-dark:hover {
    background: color-mix(in oklab, var(--on-primary) 12%, transparent);
    color: var(--on-primary);
}

.btn[disabled], .btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Media frames ────────────────────────────────────────────────────────
 * A frame for an embed — map, video or photo — so the child fills a box of
 * known proportion instead of the element's natural size.
 *
 * The ratio, radius and any framing are DEFAULTS. Change them in this file
 * to suit the design; they are here so a frame is never unstyled, not to
 * fix how it should look. */
.media-frame {
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--radius-m);
    background: var(--surface);
}

.media-frame > :where(iframe, img, video) {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    object-fit: cover;
    border-radius: 0;
}

.media-frame--square { aspect-ratio: 1; }
.media-frame--wide { aspect-ratio: 16 / 9; }

/* Cards ────────────────────────────────────────────────────────────────
 * Deliberately minimal — a surface with a radius. Sites compose their own
 * card variants on top; modelling every one here would be guesswork. */
.card {
    padding: var(--space-m);
    background: var(--surface);
    border: var(--border-thin) solid var(--border);
    border-radius: var(--radius-m);
}

/* Utility ──────────────────────────────────────────────────────────── */
.visually-hidden, .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/*
 * Grid utilities. .u-container centres and pads; .u-grid lays out. Placement
 * within the grid is each layout's business — see refs/design/layouts.md.
 */
.u-container {
    max-width: var(--grid-max-width);
    margin-inline: auto;
    padding-inline: var(--grid-gutter);
}

.u-grid {
    display: grid;
    gap: var(--grid-gutter);
}

/*
 * Section rhythm. EVERY band on a page should be a .section — this is what
 * gives a page its vertical breathing room, and it is the single most
 * repeated review comment when it is missed ("this section is lacking top
 * and bottom padding", raised three separate times on one site).
 *
 * It is a class rather than a bare `section` selector because bands are not
 * always <section> elements, and because a band that deliberately runs flush
 * to its neighbour needs to say so out loud via --flush.
 *
 * Do not hand-roll the padding. --space-l-2xl is the site-wide "40px phone /
 * 80px desktop" step, already a clamp; a bespoke value breaks the rhythm.
 *
 * Verify with bandpad.mjs, which measures the real rendered ink gap between
 * adjacent bands and fails under 40px.
 */
.section { padding-block: var(--space-l-2xl); }
.section--tight { padding-block: var(--space-l); }
.section--flush { padding-block: 0; }

/* A centred intro (eyebrow + heading + standfirst) above a band's content. */
.section__head {
    max-width: 46rem;
    margin-inline: auto;
    text-align: center;
}

/*
 * Scroll entrance.
 *
 * Native scroll-driven animation — no library, no IntersectionObserver, no
 * JS. Add .reveal for a plain fade, or one of the directional modifiers.
 *
 * WHY THE WHOLE BLOCK IS INSIDE prefers-reduced-motion: a reveal implemented
 * as `opacity: 0` plus an animation leaves reduced-motion users staring at
 * invisible content when the animation never runs. Scoping the rule means
 * they simply get the content, with no trap to fall into.
 *
 * Safari and Firefox do not support animation-timeline yet, so content there
 * is simply visible. That is the correct failure for a practice site: no
 * entrance effect is always better than content that never arrives.
 */
@media (prefers-reduced-motion: no-preference) {
    .reveal {
        animation: reveal linear both;
        animation-timeline: view();
        animation-range: entry 0% cover 30%;
    }

    .reveal--up { --reveal-from: translateY(var(--reveal-distance)); }
    .reveal--down { --reveal-from: translateY(calc(var(--reveal-distance) * -1)); }
    .reveal--left { --reveal-from: translateX(var(--reveal-distance)); }
    .reveal--right { --reveal-from: translateX(calc(var(--reveal-distance) * -1)); }
}

@keyframes reveal {
    from {
        opacity: 0;
        transform: var(--reveal-from, none);
    }
}

/*
 * Doctor avatar fallback
 * Shows a gradient + person silhouette when no photo exists.
 * The <img> has onerror="this.style.display='none'" which hides
 * the broken image, revealing this CSS background underneath.
 *
 * Derived from the site's own --accent so a missing photo reads as part of
 * this practice rather than as a stray swatch. Define --accent in :root above.
 */
.doctor-avatar {
    position: relative;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    border-radius: 0.5rem;
    background: linear-gradient(135deg,
        color-mix(in oklab, var(--primary) 85%, black),
        var(--primary));
    display: flex;
    align-items: center;
    justify-content: center;
}

.doctor-avatar::after {
    content: "";
    position: absolute;
    width: 40%;
    height: 40%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='white' stroke-width='1.5'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
}

.doctor-avatar img {
    position: relative;
    z-index: var(--layer-base);
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/*
 * Mediflare footer logo — dark/light variants.
 * Default: inverted (white text) for dark footers.
 * Add .footer-light to <footer> for light backgrounds.
 */
.mf-logo-light { display: none; }
.mf-logo-dark { display: inline; }
.footer-light .mf-logo-light { display: inline; }
.footer-light .mf-logo-dark { display: none; }

/* Hours: prevent time strings from breaking between number and am/pm */
.hours-table td:last-child,
.footer__hours-row span {
    white-space: nowrap;
}
/* ── 404 ──────────────────────────────────────────────────────────────
 * Served for any unmatched path, so it stands alone: say what happened, then
 * offer the way back rather than leaving a dead end.
 *
 * Deliberately written against fallbacks rather than this site's own token
 * names - every site in the fleet has a different vocabulary, and a 404 that
 * silently loses its layout because one variable is spelt differently is
 * worse than one that is slightly plainer. */
.notfound {
    padding-block: var(--space-3xl) var(--space-2xl);
    text-align: center;
}
.notfound__inner { max-width: 46rem; margin-inline: auto; }
.notfound__code {
    font-size: var(--step-7);   /* the site's display step, as the hero headline */
    font-weight: var(--weight-700);
    line-height: var(--leading-xs);
    margin: 0 0 var(--space-2xs);
    opacity: 0.55;
}
.notfound h1 { margin-top: 0; }
.notfound__lede { font-size: var(--step-1); line-height: var(--leading-l); margin-inline: auto; max-width: 40rem; }
.notfound__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-s);
    justify-content: center;
    margin-top: var(--space-l);
}
.notfound__links {
    margin-top: var(--space-xl);
    padding-top: var(--space-l);
    border-top: var(--border-thin) solid currentColor;
    border-color: color-mix(in oklab, currentColor 22%, transparent);
}
.notfound__links-title {
    font-size: var(--step-0);
    text-transform: uppercase;
    letter-spacing: var(--tracking-xl);
    margin: 0 0 var(--space-s);
}
.notfound__links ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-l);
    justify-content: center;
}
.notfound__links a {
    display: inline-block;
    min-height: 24px;   /* WCAG 2.5.8 target size */
    line-height: var(--leading-l);
    font-weight: var(--weight-600);
}

/* ===== SITE LAYER: Ayr Medical Group ===== */

/* ===========================================================================
 * AYR MEDICAL GROUP — site layer
 *
 * Transcribed from https://www.ayrmedical.com.au (WordPress/Elementor kit 6)
 * on 2026-09-10. Every value below was MEASURED off the live DOM at 1440,
 * 1024, 390 and 1920 — none of it was chosen.
 *
 * THE SCALE IS THE TEMPLATE'S, TUNED BY ITS EIGHT KNOBS ONLY (owner
 * decision 2026-10-03). Every --step-* and --space-* is generated by the
 * template's block at the top of this file; this layer sets the --u-* knobs
 * and nothing else. No step is redeclared and none is invented.
 *
 * Live sets a fluid root, `calc(0.74981rem + 0.31266vw)`, and states every
 * size as a plain rem multiple of it (0.75 / 0.9 / 1.0 / 1.125 / 1.25 / 1.5 /
 * 2.5 / 3.0 / 3.5rem), plus a few fixed px sizes (13 / 14 / 14.4 / 15 / 32).
 * Our root stays at 100%: the steps carry the fluidity.
 *
 * The knobs are fitted at the two design widths, 390 and 1440. Body is exact
 * at both (16px phone floor, 16.5px desktop). A ratio of 1.2 at 1440 lands
 * live's three display sizes on step-5/6/7 within 2.4%; 1.16 at 390 does the
 * same for live's phone display sizes. Live sizes -> our step, at 390 / 1440:
 *
 *   0.75rem  12.0 / 12.4   step--2  11.9 / 11.9
 *   0.9rem   14.0 / 14.9   step--1  13.8 / 13.8   (and the 13/14/14.4/15px)
 *   (The two small steps hold constant: their 390 value exceeds their 1440
 *   one, and a clamp() whose min is above its max returns the min.)
 *   1.0rem   16.0 / 16.5   step-0   16.0 / 16.5   <- body, 67 uses
 *   1.125rem 18.0 / 18.6   step-1   18.6 / 19.8
 *   1.25rem  20.0 / 20.6   step-1   18.6 / 19.8   <- 27 uses
 *   1.5rem   24.0 / 24.8   step-2   21.5 / 23.8
 *   32px     32   / 32     step-4   29.0 / 34.2
 *   2.5rem   33.0 / 41.3   step-5   33.6 / 41.1
 *   3.0rem   39.7 / 49.5   step-6   39.0 / 49.3
 *   3.5rem   46.3 / 57.8   step-7   45.2 / 59.1
 *
 * (Live's text sizes are shown with the 16px-root readability floor this site
 * has held since 2026-09-30: live's own root reaches a 13.2px body at 390.)
 * Above 1440 the scale holds its 1440 values. Live keeps growing to 1920
 * (18px body) and then snaps back to a fixed 16px root from 1921 up, so the
 * cap is 8% under live at exactly 1920 and 3% over it on any wider screen.
 * ======================================================================== */
:root {
    /* --- The eight knobs ------------------------------------------------ */
    --u-min-vw: 390;
    --u-max-vw: 1440;
    --u-min-font: 16;
    --u-max-font: 16.5;
    --u-min-ratio: 1.16;
    --u-max-ratio: 1.2;
    /* Space: live's desktop rhythm is 10/15/20/30/40/60/80/120px, which is
     * exactly the template ladder on a 20px unit (2xs 10, xs 15, s 20, m 30,
     * l 40, xl 60, 2xl 80, 3xl 120). Live does not scale it; ours does, by the
     * template's 1 : 1.25, so a phone is 20% tighter (s 16, m 24, l 32). */
    --u-space-min: 1;
    --u-space-max: 1.25;

    /* --- Named compositions: sums of steps, never new values ------------ */
    /* Band rhythm: live steps 60 / 80 / 120px at 390 / 1024 / 1440. The pair
     * runs 64 / 98 / 120 — exact on desktop, a ramp where live steps. */
    --space-band: var(--space-2xl-3xl);
    /* Side gutter: live 20px below 768, 40px above. The template's own
     * gutter pair runs 18 / 31 / 40 at 390 / 1024 / 1440. */
    --space-gutter: var(--space-s-l);
    --space-block: calc(var(--space-xl) + var(--space-2xs));       /* 70 — band head -> content, wide column gaps */
    --space-inset-xl: calc(var(--space-2xl) + var(--space-2xs));   /* 90 — live's card inset */
    /* Live's guides column inset is PROPORTIONAL, not fixed: measured
     * 92.25/1025, 108/1200, 129.594/1440, 172.797/1920 — exactly 9vw at every
     * one. Transcribing the 1440 value as a fixed 129.594px starved the two
     * guide columns to 144px between 1040 and 1120 and clipped the "Missed
     * Appointments" heading. This is the px-inset trap in the playbook. It is
     * geometry, not a step, so it is not named into the --space-* family. */
    --guides-inset: 9vw;
    --space-card-gap: var(--space-m);   /* 30 — grid gap, fixed on live at every width */
    --space-icon-gap: var(--space-s);   /* 20 — Elementor icon-box wrapper gap */
    --space-inset-s: var(--space-m);    /* 30 — card padding */
    --space-inset-m: calc(var(--space-l) + var(--space-2xs));      /* 50 — fact-card padding */
    --space-inset-l: var(--space-2xl);                             /* 80 — about-card top; live's 80px row gaps */
    --space-lead: calc(var(--space-2xl) + var(--space-s));         /* 100 */
    --space-hero-lead: calc(var(--space-3xl) - var(--space-3xs));  /* 114; live 116 to the first hero ink */
    --space-panel-gap: calc(var(--space-m) + var(--space-3xs));    /* 36; live 35 — CTA panel and card body */
    --space-tick-gap: var(--space-3xs);   /* 6; live 3.75 glyph->text */
    --space-tick-pad: var(--space-3xs);   /* 6; live 5 text padding in its lists */
    --space-cta-inset: calc(var(--space-3xl) + var(--space-3xl) + var(--space-2xs));   /* 250 — live's closing band top inset */
    /* The policy hero's arch panel: the first ink sits 236px down on live.
     * Re-declared per breakpoint below because the arch's radius steps there
     * too (250 / 160px): the lead is clearance under that curve. */
    --space-arch-lead: calc(var(--space-3xl) + var(--space-2xl) + var(--space-s));   /* 220 */
    --tick-pale: oklch(0.8088 0.0432 239.55);  /* rgb(168,197,218), live's pale-blue list glyph */

    /* --- Shell ------------------------------------------------------------
     * 1290px, a REAL cap: measured 1290 at both 1440 and 1920 (17 uses).
     * Verified above the design width per "measure above the cap" — at 1920
     * it holds at 1290 rather than growing, so it is a max-width and not
     * viewport-minus-padding. The header/footer use a wider 1350 shell. */
    --shell: 80.625rem;        /* 1290 */
    --shell-wide: 84.375rem;   /* 1350 — header contact bar, nav, footer */
    --shell-tiles: 90.625rem;  /* 1450 — the appointment tiles strip. Live runs
                                  it full-bleed, which strands the gold dividers
                                  on a wide monitor; owner review 2026-09-28 */

    /* --- Colour, from the Elementor kit, expressed through the dials ------
     * Two hue families: brand blue ~257-262 and a warm gold/cream ~81-92.
     * Every value below is an exact OKLCH conversion of live's measured sRGB,
     * verified by painting each token to a canvas.
     *
     * The brand colours ARE the template's roles, set on its dials, so every
     * template component (focus rings, skip link, link hover, .btn--*, pale
     * and hover variants) paints in the brand rather than a near-miss blue:
     *   primary   = brand blue  rgb(61,107,193)   headings, links, hovers
     *   secondary = brand navy  rgb(0,33,78)      pills, footer, eyebrows
     *   tertiary  = brand gold  rgb(251,205,123)  nav bar, buttons, rules
     *   --bg = page cream rgb(255,250,235), --ink = rgb(43,44,41),
     *   --surface = white (search field, form fields), all on the neutral dials.
     * The ground is warm (hue 91.58) and the ink a near-neutral olive (121.80):
     * one --hue-neutral cannot carry both, so the ground takes --hue-ground. */
    --palette-hue: 261.66;
    --palette-chroma: 0.1438;
    --l-primary: 0.5397;
    --palette-secondary-shift: -4.54;   /* 257.12 */
    --chroma-secondary: 0.0916;
    --l-secondary: 0.2568;
    --palette-tertiary-shift: -180.80;  /* 80.86 */
    --chroma-tertiary: 0.1131;
    --l-tertiary: 0.8714;

    --hue-neutral: 121.80;
    --chroma-ink: 0.0044;               /* --ink = 1.25x = 0.0055 */
    --l-ink: 0.2910;                    /* rgb(43,44,41) */
    --hue-ground: 91.58;
    --chroma-ground: 0.0204;
    --l-bg: 0.9849;                     /* rgb(255,250,235) */
    --l-on-solid: 1;                    /* text on a fill is white on live */

    /* Extension colours: measured on live, derivable from no role. */
    --ground-deep:  oklch(0.9618 0.0512 91.37);  /* rgb(255,242,204) deeper bands, raised cards */
    --on-navy:      oklch(0.9932 0.0080 98.88);  /* rgb(254,253,247) text on navy */
    /* Not recorded as measured; kept at the build's values. */
    --ink-slate:    oklch(0.4602 0.0178 251.33); /* rgb(81,89,98)    the search field's glyph */
    --ink-grey:     oklch(0.5173 0 0);           /* rgb(104,104,104) the bare text button, program numbers */
    --notice-ink:   oklch(0.5521 0.0769 79.72);  /* rgb(138,109,59)  the contact form's notice box */
    --required:     oklch(0.5433 0.1740 29.70);  /* rgb(192,57,43)   the form's required-field mark */
    /* THE focus ring, on links, buttons and fields alike (owner, 2026-10-06:
     * one ring per site): the brand gold's own hue and chroma, darkened until
     * it clears 3:1 (WCAG 1.4.11) against every ground it is drawn on.
     * Painted to a canvas at 0.60 -> rgb(163,120,31): white 3.99, deep cream
     * 3.58, page cream 3.82, navy footer >= 3. 0.62 left only 3.30. The gold
     * nav and legal bars are the grounds it cannot clear: see .navbar below. */
    --l-focus-ring: 0.60;
    --focus-ring: oklch(var(--l-focus-ring) var(--chroma-tertiary) var(--hue-tertiary));
    --focus-ring-w: var(--border-thick);           /* 4px, the owner's ring */

    /* Buttons and fields share one corner: live's pill (.btn-pill, the
     * Book/CTA button), so every button and the contact form's borderless
     * deep-cream fields are pills. A textarea is a rectangle with the pill's
     * own corner: half the field height. Never restyle a control in a
     * component; change these. */
    --control-radius: var(--radius-pill);
    --field-h: var(--target-min);                  /* 44px; live's field was 41px, under the target */
    --field-pad-block: var(--space-2xs);
    --field-pad-inline: var(--space-s);
    --field-textarea-radius: calc(var(--field-h) / 2);
    --field-bg: var(--ground-deep);                /* on the page cream; see .topbar / overlay for deep-cream grounds */
    --field-ink: var(--ink);
    --field-border-w: 0px;                         /* borderless: the fill is the edge */
    --field-border: transparent;
    --field-border-hover: transparent;
    --field-placeholder: color-mix(in oklab, var(--ink) 80%, transparent);   /* live's near-ink placeholder */

    /* Leading: live's own steps. s is retuned 1.18 -> 1.2 (live's heading and
     * display leading, 10 uses); three in-between steps carry live's 1.25
     * article titles, 1.4 eyebrows and 1.45 contact values. */
    --leading-s: 1.2;
    --leading-m-tight: 1.25;
    --leading-m-loose: 1.4;
    --leading-l-tight: 1.45;
    --tracking-m-loose: 0.02em;   /* live's bare text button and form submit */
    /* Live uses two more weights than the template's three: Manrope 800 on the
     * contact labels and Work Sans 500 on fact and contact copy. Kept for
     * fidelity. */
    --weight-500: 500;
    --weight-800: 800;

    /* Live's own type faces. Three, against the two-family norm — kept for
     * fidelity: IBM Plex Sans headings/nav/buttons, Work Sans body, Manrope
     * only in the header contact bar and footer contact rows. */
    --font-head: "IBM Plex Sans", system-ui, sans-serif;
    --font-body: "Work Sans", system-ui, sans-serif;
    --font-meta: "Manrope", system-ui, sans-serif;
}

/* The root stays at 100%: the steps carry the fluidity, and a fluid root
 * under fluid steps would scale everything twice. */
html { font-size: 100%; }

/* Between 1025 and ~1104 four padded tiles cannot fit; live's own tile carries
   no padding and holds four 260px columns down to 1040. Tighten ours there
   rather than dropping a column, so the band still matches live. */
@media (min-width: 1025px) and (max-width: 1140px) {
    .tiles__inner[style*="--tiles-n: 4"] .tile { padding: var(--space-inset-m) var(--space-m); }
}

/* The arch panel's lead follows its radius, which steps here (live 128px at
 * <=1024, 80px at <=480). */
@media (max-width: 1024px) {
    :root { --space-arch-lead: calc(var(--space-3xl) + var(--space-xs)); }   /* 124 at 1024 */
}
@media (max-width: 480px) {
    :root { --space-arch-lead: calc(var(--space-2xl) + var(--space-s)); }    /* 80 at 390 */
}

body {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--step-0);
    line-height: var(--leading-l);
}

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    color: var(--primary);
    /* Live sets no tracking and no balance on headings; the template's
     * defaults would change every line count. Reset them, as Cavenagh had to. */
    letter-spacing: normal;
    text-wrap: wrap;
}
/* The template sets h1-h4 at step-5/4/3/2; live's are 3.0 / 2.5 / 1.5 /
 * 1.25rem, which on this site's knobs are step-6 / 5 / 2 / 1. */
h1, .h1 { font-size: var(--step-6); }
h2, .h2 { font-size: var(--step-5); }
h3, .h3 { font-size: var(--step-2); }
h4, .h4 { font-size: var(--step-1); }

a { color: var(--primary); }

/* ---------------------------------------------------------------------------
 * SHELL + BANDS
 * ------------------------------------------------------------------------ */
.shell {
    width: 100%;
    max-width: var(--shell);
    margin-inline: auto;
}
.shell--wide { max-width: var(--shell-wide); }

.band {
    padding-inline: var(--space-gutter);
    background: var(--bg);
}
.band__inner {
    /* flex column so a child's negative margin cannot drag the band up —
     * the Cavenagh trap */
    display: flex;
    flex-direction: column;
    padding-block: var(--space-band);
}

/* ---------------------------------------------------------------------------
 * HEADER — contact bar (deep cream, 142px @1440) + nav bar (gold, 79px)
 * ------------------------------------------------------------------------ */
.site-header { position: relative; z-index: var(--layer-nav); }

.topbar {
    background: var(--ground-deep);
    padding-inline: var(--space-gutter);
}
.topbar__inner {
    display: flex;
    align-items: center;
    gap: var(--space-m);
    padding-block: var(--space-2xs);
    min-height: 8.875rem;   /* 142px measured */
}
.site-logo { flex: 0 0 auto; display: inline-flex; padding: var(--space-2xs) 0; }
.site-logo img { width: 12.1875rem; height: auto; }   /* 195px measured */

.topbar__meta {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-m);
}
/* Phone and email sit side by side, as live lays them out (owner,
   2026-10-05: a stacked column was tried and reverted). They are grouped so
   the folded header can treat them as one column. Nothing in the bar shrinks
   or wraps; where it no longer fits, the header folds (see HEADER FOLD). */
.topbar__meta > * { flex: none; }
.topbar__contact { display: flex; align-items: center; gap: var(--space-m); }
.meta-item { display: flex; align-items: center; gap: var(--space-2xs); }   /* live 12px */
.meta-item svg { width: 1.5rem; height: 1.5rem; flex: none; fill: var(--tertiary); }
.meta-item__label {
    display: block;
    font-family: var(--font-meta);
    font-size: var(--step--1);      /* 14px, fixed on live — not a rem multiple */
    font-weight: var(--weight-800);
    color: var(--ink);
    line-height: var(--leading-m);
}
.meta-item__value {
    margin: 0;
    font-family: var(--font-meta);
    font-size: var(--step--1);     /* 13px, fixed on live */
    font-weight: var(--weight-600);
    color: var(--ink);
    line-height: var(--leading-l-tight);
    white-space: nowrap;
}
.meta-item a { color: inherit; text-decoration: none; }
.meta-item a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
 * SITE SEARCH — the platform component (mediflare.js), styled to live's box.
 * Two placements: the visible box with a dropdown in the contact bar, and the
 * phone overlay opened from .topbar__search-open. The component writes the
 * markup unstyled; every rule here is this site's. The overlay and the popup
 * are styled ONLY through :not([hidden]), or they never close.
 * ------------------------------------------------------------------------ */
.topbar__search {
    --search-field: 14rem;       /* 224px measured */
    --search-glyph: 1.3125rem;   /* 21px measured */
    position: relative;
}
.topbar__search .mf-search__form {
    position: relative;
    display: grid;
    grid-template-columns: var(--search-field) auto;
    gap: var(--space-3xs);       /* 6px measured */
    align-items: center;
}
/* Live's magnifier sits inside the field. An input takes no pseudo-element,
   so it is drawn on the form, over the field's leading padding. */
.topbar__search .mf-search__form::before {
    content: "";
    position: absolute;
    inset-inline-start: var(--space-s);
    inset-block-start: calc((var(--field-h) - var(--search-glyph)) / 2);
    width: var(--search-glyph);
    height: var(--search-glyph);
    background: var(--ink-slate);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z'/%3E%3C/svg%3E") center / contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z'/%3E%3C/svg%3E") center / contain no-repeat;
    pointer-events: none;
    z-index: var(--layer-base);
}
.topbar__search .mf-search__input {
    width: 100%;
    padding: 0 var(--space-2xs) 0 calc(var(--space-s) + var(--search-glyph) + var(--space-s));   /* clears the glyph */
}
/* The header and the phone overlay are deep cream, the contact fill: a field
 * there takes the white surface, or a borderless field would vanish. A token
 * per ground, not a restyle of the control. */
.topbar, .mf-search-overlay { --field-bg: var(--surface); }
.mf-search__label { margin: 0; }
.topbar__search .mf-search__label,
.mf-search--overlay .mf-search__label {   /* read out, not shown: the glyph and placeholder say it */
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* The Search button: live's gold pill, uppercase Plex. Every button on the
   site hovers brand blue (owner, round 8). */
.mf-search__submit {
    min-height: var(--field-h);   /* level with the field beside it */
    padding: 0 var(--space-m);
    background: var(--tertiary);
    color: var(--ink);
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    font-size: var(--step--1);
    letter-spacing: var(--tracking-l);
    text-transform: uppercase;
    border-radius: var(--control-radius);
    transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.mf-search__submit:hover, .mf-search__submit:focus-visible { background: var(--primary); color: var(--bg); }

/* The floating results, beneath the box and aligned to its right edge. */
.topbar__search .mf-search__popup:not([hidden]) {
    position: absolute;
    inset-block-start: calc(100% + var(--space-2xs));
    inset-inline-end: 0;
    z-index: var(--layer-overlay);
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    inline-size: max(100%, min(var(--measure-tight), calc(100vw - 2 * var(--space-gutter))));
    padding: var(--space-xs);
    background: var(--surface);
    border: var(--border-thin) solid var(--tertiary);
    border-radius: var(--radius-m);
    box-shadow: var(--shadow-l);
}
.topbar__search .mf-search__results:not([hidden]) {
    max-block-size: 60dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Status and results, wherever the box sits. */
.mf-search__status {
    margin: 0;
    padding-inline: var(--space-xs);
    font-size: var(--step--1);
    line-height: var(--leading-m);
    color: var(--ink);
}
.mf-search__status:empty { display: none; }
.mf-search__results { margin: 0; padding: 0; list-style: none; }
.mf-search__results:not([hidden]) { display: flex; flex-direction: column; gap: var(--space-3xs); }
.mf-search__link {
    display: block;
    padding: var(--space-2xs) var(--space-xs);
    border-radius: var(--radius-s);
    color: var(--ink);
    text-decoration: none;
    overflow-wrap: anywhere;
    transition: background var(--duration-fast) var(--ease-out);
}
.mf-search__link:hover, .mf-search__link:focus-visible { color: var(--ink); background: var(--ground-deep); text-decoration: none; }
.mf-search__link:focus-visible { outline-offset: calc(var(--focus-ring-w) * -1); }   /* inset: a scrolling list clips an outset ring */
.mf-search__title {
    display: block;
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    line-height: var(--leading-s);
    color: var(--primary);
}
.mf-search__excerpt {
    display: block;
    margin-top: var(--space-3xs);
    font-size: var(--step--1);
    line-height: var(--leading-m);
    color: var(--ink);
}
.mf-search__excerpt mark {
    color: var(--ink);
    background: color-mix(in srgb, var(--tertiary) 70%, transparent);
    border-radius: var(--radius-xs);
}

/* The phone trigger: live's white field, shrunk to its magnifier. Shown only
   where the contact bar (and so the box) is hidden — see HEADER FOLD. */
.topbar__search-open {
    display: none;
    align-items: center;
    justify-content: center;
    inline-size: var(--target-min);
    block-size: var(--target-min);
    color: var(--ink-slate);
    background: var(--surface);
    border-radius: var(--radius-pill);
    transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.topbar__search-open svg { width: var(--step-1); height: var(--step-1); fill: currentColor; }
.topbar__search-open:hover,
.topbar__search-open:focus-visible,
.topbar__search-open[aria-expanded="true"] { color: var(--bg); background: var(--primary); }

/* The phone overlay: the contact bar's deep cream, live's white field and
   gold Search pill, Close leading so focus order matches what is seen. One
   row holds Close, the field and Search; the results scroll below it.
   Subgrid puts the box's own children on the overlay's grid. */
.mf-search-overlay:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: var(--layer-modal);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto minmax(0, 1fr);
    gap: var(--space-xs) var(--space-2xs);
    padding-block-start: max(var(--space-s), env(safe-area-inset-top));
    padding-inline: max(var(--space-gutter), env(safe-area-inset-left)) max(var(--space-gutter), env(safe-area-inset-right));
    background: var(--ground-deep);
}
.mf-search-overlay__header { display: contents; }
.mf-search-overlay__close {
    grid-column: 1;
    grid-row: 1;
    align-self: stretch;
    position: relative;
    z-index: var(--layer-base);   /* above the box, which spans this cell too */
    min-inline-size: var(--target-min);
    min-block-size: var(--target-min);
    padding-inline: var(--space-s);
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    color: var(--ink);
    background: var(--surface);
    border-radius: var(--radius-pill);
    transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.mf-search-overlay__close:hover, .mf-search-overlay__close:focus-visible { color: var(--bg); background: var(--primary); }
.mf-search--overlay,
.mf-search--overlay .mf-search__form {
    grid-column: 1 / -1;
    grid-row: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    align-items: stretch;   /* Close, the field and Search share one height */
}
.mf-search--overlay .mf-search__input { grid-column: 2; grid-row: 1; }
/* Tighter than the desktop pill, so "Type to search" is not clipped at 390. */
.mf-search--overlay .mf-search__submit { grid-column: 3; grid-row: 1; min-height: var(--target-min); padding-inline: var(--space-s); }
.mf-search--overlay .mf-search__status { grid-column: 1 / -1; grid-row: 2; }
.mf-search--overlay .mf-search__results {
    grid-column: 1 / -1;
    grid-row: 3;
    align-self: stretch;
    min-block-size: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-block-end: max(var(--space-s), env(safe-area-inset-bottom));
}
.mf-search--overlay .mf-search__link:hover,
.mf-search--overlay .mf-search__link:focus-visible { background: var(--surface); }   /* the ground is already deep cream */
.nav-menu-btn:hover, .nav-menu-btn:focus-visible { background: var(--primary); color: var(--bg); }
.navbar { background: var(--tertiary); padding-inline: var(--space-gutter); }
/* The amber ring is only ~2.7:1 on the gold nav bar (and its dropdowns) and
 * the gold legal bar; the brand navy reaches 10.6:1 there. A token on the
 * container, not a focus rule. */
.navbar, .legalbar { --focus-ring: var(--secondary); }
.navbar__inner {
    display: flex; align-items: center; gap: var(--space-m);
    padding-block: var(--space-xs);   /* 15px measured */
    min-height: var(--navbar-h);      /* 79px measured */
}
.nav { display: flex; }
.nav > ul {
    display: flex; align-items: center; gap: var(--space-l);
    list-style: none; margin: 0; padding: 0;
}
.nav > ul > li { position: relative; margin: 0; }
.nav a,
.nav__toggle {
    display: inline-flex; align-items: center; gap: var(--space-3xs);
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    font-size: var(--step-0);
    color: var(--ink);
    text-decoration: none;
    padding-block: var(--space-2xs);
}
.nav a:hover { text-decoration: none; }
.nav a:focus-visible { text-decoration: underline; }
/* Live marks the current page with a 3px bar in the light cream (measured
   rgb(255,242,204), --ground-deep, 3px, full link width, bottom 0), not an underline. */
.nav > ul > li > a { position: relative; }
.nav > ul > li > a[aria-current="page"]::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
    background: var(--ground-deep);
}
.nav__caret { width: 1rem; height: 1rem; fill: currentColor; flex: none; }

/* The toggle is a <button> so the submenu is keyboard-operable, but it must
   read as one of the nav links — it shares their rule above and only adds
   the button reset here. It previously kept `font: inherit` and picked up
   the body face and weight, so it rendered lighter than its siblings. */
.nav__toggle {
    background: none; border: 0; cursor: pointer;
}
.nav__sub {
    list-style: none; margin: 0; padding: var(--space-2xs) 0;
    position: absolute; top: 100%; left: 0; min-width: 16rem;
    background: var(--tertiary);
    border-radius: 0 0 var(--radius-s) var(--radius-s);
    box-shadow: var(--shadow-m);
    display: none; z-index: var(--layer-overlay);
}
.nav__sub li { margin: 0; }
.nav__sub a { display: block; padding: var(--space-2xs) var(--space-s); }
.nav__sub a:hover, .nav__sub a:focus-visible { background: var(--ground-deep); text-decoration: none; }
.nav__item--has-sub:hover .nav__sub,
.nav__item--has-sub:focus-within .nav__sub,
.nav__sub[data-open="true"] { display: block; }

.nav-cta { margin-left: auto; }
.nav-menu-btn {
    display: none;
    margin-left: auto;
    align-items: center; gap: var(--space-2xs);
    background: none; border: 0; padding: var(--space-2xs);
    font-family: var(--font-head); font-weight: var(--weight-700);
    font-size: var(--step-0); color: var(--ink); cursor: pointer;
}
.nav-menu-btn svg { width: 1.5rem; height: 1.5rem; fill: currentColor; }


/* Buttons. Live's pill: gold fill, ink text, 100px radius, uppercase
 * IBM Plex Sans 700. The header CTA is the pale cream fill instead. */
.btn-pill {
    display: inline-flex; align-items: center; justify-content: center;
    min-block-size: var(--target-min);   /* the 44px tap target, every size */
    background: var(--tertiary); color: var(--ink);
    font-family: var(--font-head); font-weight: var(--weight-700);
    font-size: var(--step-0);
    letter-spacing: var(--tracking-l);
    text-transform: uppercase; text-decoration: none;
    border: 0; cursor: pointer;
    border-radius: var(--control-radius);
    padding: var(--space-s) var(--space-xl);
    /* live keeps every CTA on one line; the 267px app column is narrow enough
       that the default would wrap it. But nowrap on a LONG label overflows a
       phone -- the CDM "MEDICARE CHRONIC DISEASE MANAGEMENT DETAILS" button
       measured 482px in a 400px viewport -- so allow a wrap once it cannot fit. */
    white-space: nowrap;
    max-width: 100%;
}
@media (max-width: 560px) {
    .btn-pill { white-space: normal; text-align: center; }
}
/* Owner 2026-09-30: every button hovers to brand blue with cream text. */
.btn-pill:hover, .btn-pill:focus-visible { background: var(--primary); color: var(--bg); }
.btn-pill--pale { background: var(--ground-deep); font-size: var(--step--1); padding: var(--space-2xs) var(--space-l); }
/* Live's header CTA hovers to brand blue with cream text. It used to hover to
   the same gold as the nav bar, which made the button disappear (owner review
   2026-09-29). */
.btn-pill--pale:hover, .btn-pill--pale:focus-visible { background: var(--primary); color: var(--bg); }

/* ---------------------------------------------------------------------------
 * BAND 0 — hero. 550x550 arched photo, radius 100% 100% 0 0.
 * ------------------------------------------------------------------------ */
/* Live's hero band has NO band padding of its own: the 670px height is
 * 120px of media-column top padding plus the photo's own 550px. Measured,
 * not chosen — an inherited --space-band here made the band 178px too tall. */
.hero .band__inner { padding-block: 0; }
.hero__inner {
    display: grid;
    grid-template-columns: 1fr 1fr;      /* live: 550px 550px in a 1150 shell */
    gap: var(--space-xl) var(--space-inset-m);   /* 50px column gap: 550+50+550 = 1150 */
    align-items: start;
    max-width: 71.875rem;                /* 1150px measured */
    margin-inline: auto;
}
.hero__copy { display: flex; flex-direction: column; gap: var(--space-l); padding-top: var(--space-hero-lead); }  /* 116px to live's first ink */
/* .eyebrow sits on h1..h4 as well as p (live marks these up as headings), and a
   heading's own font-size beats a class at equal specificity by source order --
   which rendered the /health-articles/ h2 eyebrow at 41px against live's 20.6.
   Pin every property the tag could otherwise supply. */
h1.eyebrow, h2.eyebrow, h3.eyebrow, h4.eyebrow,
.eyebrow {
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    font-size: var(--step-1);
    color: var(--secondary);
    letter-spacing: normal;
    text-transform: none;
    margin: 0;
}
.hero__title {
    font-size: var(--step-7);            /* 3.5rem = 57.75px @1440 */
    line-height: var(--leading-s);                    /* live: 69.2967 / 57.7473 */
    margin: 0;
}
.hero__copy p { margin: 0 0 var(--space-s); max-width: 31rem; }
.hero__copy p:last-child { margin-bottom: 0; }
/* Desktop rhythm inside the copy column, measured on live at 1440: eyebrow ->
 * title 14px, title -> lead 28px, lead -> button 57px, and the button then
 * ends 117px above the tiles divider. The uniform 40px flex gap PLUS the
 * eyebrow's 20px paragraph margin stacked to 60px at the top and pushed the
 * whole column down until the button sat 36px off the divider. Owner
 * review 2026-09-28: "top align the text content". */
@media (min-width: 1025px) {
    .hero__copy { gap: 0; }
    .hero__copy .eyebrow { margin-bottom: var(--space-xs); }     /* live 14px */
    .hero__title { margin-bottom: var(--space-m); }              /* live 28px */
    .hero__copy > div + p { margin-top: var(--space-panel-gap); }      /* live 33px: the button p adds its own line-box leading, so 33 renders as live's 57 */
}
.hero__media { padding-top: var(--space-band); }    /* 120px measured; zeroed at <=1024 below */
.hero__media img {
    display: block; width: 100%; height: auto;
    border-radius: 100% 100% 0 0;        /* the one percentage arch on the page */
}

/* ---------------------------------------------------------------------------
 * BAND 1 — three appointment tiles, full bleed on the deeper cream.
 * ------------------------------------------------------------------------ */
.tiles { background: var(--ground-deep); }   /* full-bleed band; the tiles inside are capped at --shell-tiles */
/* Live runs THREE tiles on the homepage/about and FOUR on the contact and
   service pages, always in ONE row (measured: 4 x 360px, band 401px tall).
   Hard-coding three wrapped the four-tile variant onto two rows, +208px. */
.tiles__inner {
    display: grid; grid-template-columns: repeat(var(--tiles-n, 3), minmax(0, 1fr));
    max-width: var(--shell-tiles);
    margin-inline: auto;
}
/* Once the strip is narrower than the viewport its trailing rule is no longer
 * clipped by the band edge, so drop it on the last tile there. Below 1451 the
 * strip IS the viewport and the per-breakpoint rules above still hold. */
/* Owner review 2026-09-30: once the strip is narrower than the band, mark
 * its beginning and end with the same gold rule the columns use. Below 1451
 * the strip IS the viewport, so the edges are clipped as on live. */
@media (min-width: 1451px) {
    .tile:first-child { border-left: var(--border-thin) solid var(--tertiary); }
}
.tile {
    padding: var(--space-xl);            /* 60px measured, flat */
    text-align: center;
    /* Live divides the three tiles with a 1px solid gold rule, and WHICH edges
     * carry it changes per breakpoint (measured at 390/768/1024/1440):
     *   >1024   border-right          vertical rules between the columns
     *   768-1024 right + bottom       the grid is 2-col there, so both
     *   <=767   bottom only           stacked, so horizontal only
     * The trailing rule lands on the band edge and is clipped, which is why
     * live puts it on every tile rather than excluding the last. */
    border-right: var(--border-thin) solid var(--tertiary);
}
.tile svg { width: 2.8125rem; height: 2.8125rem; fill: var(--tertiary); display: block; margin-inline: auto; }  /* 45px */
.tile h2 {
    font-size: var(--step-2);            /* 1.5rem = 24.75px @1440 */
    color: var(--ink);
    /* live's icon-box: 20px wrapper gap, then 8.25px/16px on the title */
    margin: var(--space-icon-gap) 0 var(--space-xs);   /* live 16px */
}
.tile p { margin: 0; }

/* ---------------------------------------------------------------------------
 * BAND 2 — services. 3-col grid of 410px cards; the navy label pill rides the
 * photo's bottom edge on a NEGATIVE MARGIN, in flow (never absolute).
 * ------------------------------------------------------------------------ */
/* live: head block 213px total with a 70px bottom pad; the eyebrow's own
 * Elementor margin collapses most of the gap to the title. */
.section__head { text-align: center; padding-bottom: var(--space-block); }   /* 70px measured */
.section__head .eyebrow { margin-bottom: var(--space-3xs); line-height: var(--leading-l); }
.section-title {
    font-size: var(--step-6);            /* 3rem = 49.5px @1440 */
    line-height: var(--leading-s);                    /* live: 59.3972 / 49.4977 */
    margin: 0;
}

.svc-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-card-gap);
    margin-bottom: var(--space-inset-l);   /* 80px measured */
}
.svc { display: flex; flex-direction: column; }
/* Live's card photo is the asset's natural 4:3 (410x308 at 1440) with a 20px
 * radius; its widget carries margin-bottom: -31px, which is what makes the
 * navy label pill ride the photo's bottom edge. That is an IN-FLOW negative
 * margin, never absolute positioning — measured 31 of the pill's 69px above
 * the photo's ink edge (share 0.45; ours 0.48, both inside the owner's
 * 0.4-0.6 straddle rule). */
.svc__media {
    position: relative; z-index: var(--layer-base);
    margin-bottom: calc(-1 * var(--space-m));   /* live -31px */
}
.svc__media img {
    display: block; width: 100%; height: auto;
    /* live never scales the asset past its natural 800px: measured 410 wide at
     * 1440, 688 at 768, and 800 (not the 944 column) at 1024. */
    max-width: 800px;
    margin-inline: auto;
    border-radius: var(--radius-l);                 /* live's own, measured */
}
.svc__label {
    position: relative; z-index: var(--layer-raised);
    margin: 0 var(--space-xl);           /* 60px inset — measured */
    background: var(--secondary);
    color: var(--on-navy);
    border-radius: var(--radius-pill);
    padding: var(--space-s) var(--space-m);  /* 20px vertical — live's own */
    min-height: 4.3125rem;               /* 69px measured */
    text-align: center;
}
.svc__label h3 {
    margin: 0; color: inherit;
    font-size: var(--step-1);            /* 1.25rem = 20.62px @1440 */
    line-height: var(--leading-s);
}
.svc__body { padding: var(--space-m) var(--space-m) 0; margin-bottom: calc(-1 * var(--space-s)); text-align: center; }  /* 35/30 measured */
.svc__body p { margin: 0; }

/* the wide seventh card: 420px photo + an 840px copy panel on the deeper cream */
.svc-wide {
    display: grid;
    grid-template-columns: 420fr 840fr;   /* live's own ratio, in fr so both shrink */
    gap: var(--space-card-gap);
    align-items: stretch;                 /* the photo card runs the panel's full height (owner, 2026-09-30) */
}
.svc-wide .svc__media { flex: 1; display: flex; }
.svc-wide .svc__media img { flex: 1; height: 100%; object-fit: cover; object-position: 50% 25%; }
.svc-wide__panel {
    background: var(--ground-deep);
    border-radius: var(--radius-s);
    padding: var(--space-l);
    display: flex; flex-direction: column; gap: var(--space-s);
}
.svc-wide__panel > p:first-child {
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    font-size: var(--step-1);            /* 1.1rem = 18.15px @1440 */
    color: var(--primary);
    margin: 0;
}
.svc-wide__panel p { margin: 0; }

/* ---------------------------------------------------------------------------
 * BAND 3 — why choose us. 455px arched photo + a 2x2 card grid.
 * The arch is border-radius on a background-image div, exactly as live: the
 * radius is FIXED px against a box that is not, so the shape legitimately
 * changes character with the viewport. Do not normalise it.
 * ------------------------------------------------------------------------ */
.why__inner { display: grid; grid-template-columns: 455fr 795fr; gap: var(--space-l); }
.why__media {
    background-image: var(--why-photo);
    background-size: cover;
    background-position: center;
    border-radius: 300px 300px 15px 15px;
    height: 39.25rem;                    /* 628px measured — fixed, live's own */
    align-self: start;
}
.why__body { display: flex; flex-direction: column; gap: var(--space-m); }  /* 30px measured */
/* Live's heading block is 65px total: Elementor collapses the eyebrow with
   margin:-2px 0 -20px and the title with -11px/-4px. Those widget margins are
   structural here, not decoration — reproducing the gaps without them made the
   band 65px too tall. */
.why__head { display: flex; flex-direction: column; }
.why__head .eyebrow { line-height: var(--leading-m-loose); margin: 0 0 calc(-1 * var(--space-3xs)); }   /* live -5px */
.why__head .section-title { margin: 0; }
.why__cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-l) var(--space-m); }  /* 40/30 measured */
.why-card {
    background: var(--ground-deep);
    border-radius: var(--radius-s);
    padding: var(--space-inset-s);       /* 30px measured */
    min-height: 15.375rem;               /* 246px measured */
}
.why-card svg { width: 2.8125rem; height: 2.8125rem; fill: var(--tertiary); }
.why-card h3 {
    font-size: var(--step-1);
    /* live's icon-box wrapper gaps 20px, then the title's own 8.25/16 */
    margin: var(--space-icon-gap) 0 var(--space-xs);   /* live 16px */
}
.why-card p { margin: 0; }

/* ---------------------------------------------------------------------------
 * BAND 4 — full-bleed photo with a quote card on the right.
 * ------------------------------------------------------------------------ */
.quote {
    background-image: var(--quote-photo);
    background-size: cover;
    background-position: center;
}
.quote__inner {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--space-xl);
    max-width: 71.25rem;                 /* 1140px measured */
    margin-inline: auto;
    padding-block: var(--space-l);       /* 40px measured */
    /* Below the 1140 cap there is no gutter, so the card overflowed between
       1025 and 1140 on every page carrying this band (a phase-1 defect the
       homepage-only sweep never reached). */
    padding-inline: var(--space-gutter);
    box-sizing: border-box;
    min-height: 31.375rem;               /* 502px @1440 — overridden per breakpoint below */
    align-items: center;
}
/* live: outer column 50/50/40, inner card a further 40 all round */
.quote__card { padding: var(--space-inset-xl) var(--space-inset-xl) var(--space-l); }
.quote__card em {
    display: block;
    font-style: italic; font-weight: var(--weight-700);
    font-size: var(--step-1);
    color: var(--secondary);
    margin-bottom: var(--space-s);
}
.quote__card p { color: var(--secondary); margin: 0 0 var(--space-l); }

/* ---------------------------------------------------------------------------
 * BAND 5 — about. A cream arch-topped copy card with a 1px gold rule, beside
 * a stacked photo + two info cards.
 * ------------------------------------------------------------------------ */
/* live's about band pads 120 top and only 40 bottom */
.about .band__inner { padding-block: var(--space-band) var(--space-l); }
.about__inner { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-card-gap); }
.about__card {
    background: var(--bg);
    border: 1px solid var(--tertiary);
    border-radius: 350px 350px 15px 15px;
    min-height: 42.4375rem;              /* 679px measured */
    padding: var(--space-inset-l) var(--space-inset-xl) var(--space-l);  /* live: 80/90/40 */
    display: flex; flex-direction: column; gap: var(--space-m);
    justify-content: center;
    text-align: center;
}
.about__card p { margin: 0; }
.about__side { display: grid; gap: var(--space-card-gap); align-content: start; }
.about__photo {
    background-image: var(--about-photo);
    background-size: cover;
    background-position: center;
    border-radius: 100px 100px 15px 15px;
    min-height: 20.3125rem;              /* 325px measured */
}
.about__facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-card-gap); }
.fact {
    background: var(--ground-deep);
    border-radius: var(--radius-s);
    padding: var(--space-inset-m);       /* 50px measured */
    min-height: 20.3125rem;              /* 325px measured */
}
.fact svg { width: 2.8125rem; height: 2.8125rem; fill: var(--tertiary); }
.fact h3 { font-size: var(--step-1); color: var(--ink); margin: var(--space-s) 0 var(--space-s); }
.fact p { margin: 0; font-weight: var(--weight-500); }

/* ---------------------------------------------------------------------------
 * BAND 6 — patient guidelines. A left-bleeding photo arched on its RIGHT
 * side (radius 0 400px 400px 0) beside a 2x2 icon-box grid.
 * ------------------------------------------------------------------------ */
.guides { display: flex; background: var(--bg); }
.guides__media {
    flex: 0 0 44.6%;                     /* 642 of 1440 measured */
    background-image: var(--guides-photo);
    background-size: cover;
    background-position: center;
    border-radius: 0 400px 400px 0;
    margin-block: var(--space-lead);     /* 100px measured */
    height: 37.25rem;                    /* 596px measured */
    align-self: start;
}
.guides__body {
    flex: 1 1 auto;
    display: flex; flex-direction: column; gap: var(--space-s);   /* 20px measured */
    padding: var(--guides-inset);  /* 9vw — live is proportional here */
    justify-content: center;
}
.guides__body > p { margin: 0; }
.guides__body .eyebrow { line-height: var(--leading-m-loose); margin: 0 0 calc(-1 * var(--space-2xs)); }
.guides__grid {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--space-inset-m);           /* 50px measured */
    align-items: start;
}
/* The 539px once capped here was the column's natural width at 1440
 * (798 body - 2 x 9vw), not a max-width: live's grid fills the column at
 * every width (2 x 420px at 2380). Capping it crammed the four guides into
 * two 245px columns on wide screens, made the band 256px taller than live
 * and left blank cream under the photo, before the closing CTA. */
/* Live renders the emoji INLINE in the heading text, so the heading wraps
 * normally in a narrow column. A flex row here cannot wrap and clipped
 * "Missed Appointments" between 1040 and 1120 — live's own column is the same
 * 177px there and simply wraps. */
.guide h3 {
    font-size: var(--step-1);
    margin: 0 0 var(--space-xs);         /* live 14px heading -> copy */
}
.guide h3 img {
    display: inline-block;                 /* the global img rule is block, which
                                              stacked the emoji above its heading */
    width: 1.3125rem; height: 1.3125rem;   /* 21px emoji */
    vertical-align: -0.2em;
    margin-right: 0;                       /* live separates them with the space alone */
}
.guide p { margin: 0; }

/* ---------------------------------------------------------------------------
 * BAND 7 — closing CTA. A deep-cream panel arched at its bottom-right, with
 * the photo column riding 300px ABOVE it on a negative margin (live's own
 * mechanism, in flow).
 * ------------------------------------------------------------------------ */
.cta__inner { padding-block: var(--space-cta-inset) calc(2 * var(--space-lead)); }   /* 250 / 200 measured */
.cta__row { display: flex; }
.cta__panel {
    flex: 1 1 50%;
    background: var(--ground-deep);
    border-radius: 15px 0 300px 300px;
    padding: var(--space-inset-xl) var(--space-inset-xl) calc(2 * var(--space-lead));  /* live: 90/90/200 */
    display: flex; flex-direction: column; gap: var(--space-panel-gap);   /* 35px — live's CTA panel, not on the ladder */
    align-self: start;
    min-height: 56.6875rem;              /* 907px measured */
}
.cta__panel h2 { font-size: var(--step-5); line-height: var(--leading-s); margin: 0; }   /* 41.248px, 2 lines on live */
.cta__panel .eyebrow { font-size: var(--step-1); line-height: var(--leading-m); }
.cta__panel p { margin: 0; }
.cta__app { display: grid; grid-template-columns: 267fr 178fr; gap: var(--space-s); align-items: start; }  /* live 267/178, 20px */
.cta__app svg { width: 2.5rem; height: 2.5rem; fill: var(--secondary); }
.cta__app h3 { font-size: var(--step-1); margin: var(--space-icon-gap) 0 var(--space-xs); }
.cta__qr {
    background: var(--bg); padding: var(--space-s);
    border-radius: 10px;
    display: grid; gap: var(--space-s);
    width: 11.125rem;                    /* 178px measured — a fixed panel on live */
    justify-self: end;
}
.cta__qr img { display: block; width: 8.625rem; height: 8.625rem; max-width: none; }   /* 138x138 measured */

/* iPhone / Android toggle. Live stacks both QR codes at once, which makes it
   hard to tell which is which; one at a time is clearer and keeps the panel at
   live's measured 178px width with a single 138px code showing. */
.qr-panel { margin: 0; }                 /* figure's default 1em block margins added 64px */
.qr-panel figcaption { font-size: var(--step--2); text-align: center; margin-top: var(--space-3xs); color: var(--ink); }
.cta__media {
    flex: 1 1 50%;
    margin-top: calc(-5 * var(--space-xl));   /* -300px measured */
    align-self: start;
}
.cta__media img {
    display: block; width: 100%; height: auto;
    border-radius: 300px 300px 15px 0;
}

/* ---------------------------------------------------------------------------
 * FOOTER — navy block (4-col) + a gold legal bar.
 * ------------------------------------------------------------------------ */
.site-footer { background: var(--secondary); color: var(--on-navy); }
.site-footer a { color: var(--on-navy); text-decoration: none; }
.site-footer a:hover, .site-footer a:focus-visible { color: var(--tertiary); text-decoration: none; }
.site-footer__main { padding-inline: var(--space-gutter); }
.site-footer__grid {
    display: grid;
    grid-template-columns: 420fr 224fr 336fr 280fr;   /* live's own ratio */
    gap: var(--space-card-gap);
    padding-block: var(--space-inset-xl);
}
.site-footer h2 {
    font-family: var(--font-head); font-weight: var(--weight-700);
    font-size: var(--step-1);
    color: var(--on-navy);
    margin: 0 0 var(--space-m);
}
.site-footer__brand { display: flex; flex-direction: column; gap: var(--space-l); }
.site-footer__brand img.footer-logo { width: 8.75rem; height: auto; }   /* 140px */
.site-footer__brand p { margin: 0; color: var(--on-secondary); }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2xs); }
.site-footer li { margin: 0; }
.footer-contact { display: grid; gap: var(--space-m); }
.footer-contact__row { display: flex; gap: var(--space-s); align-items: start; }
.footer-contact__row svg { width: 1.625rem; height: 1.625rem; fill: var(--tertiary); flex: none; }
.footer-contact__label {
    display: block;
    font-family: var(--font-head); font-weight: var(--weight-700);
    font-size: var(--step-0);
}
.footer-contact__value {
    margin: 0;
    font-family: var(--font-meta); font-size: var(--step--1); font-weight: var(--weight-500);  /* 15px fixed on live */
    line-height: var(--leading-l);
}
.powered-by { display: flex; align-items: center; gap: var(--space-2xs); }
.powered-by span { font-size: var(--step--2); color: var(--bg); }
.powered-by img { width: 5rem; height: auto; }

.legalbar { background: var(--tertiary); padding-inline: var(--space-gutter); }
.legalbar__inner {
    display: flex; flex-wrap: wrap; gap: var(--space-s) var(--space-l);
    align-items: center; justify-content: space-between;
    padding-block: var(--space-2xs);
}
.legalbar { font-size: var(--step--1); }   /* live is --step-0; stepped down at the owner's request */
.legalbar p { margin: 0; color: var(--ink); }
.legalbar nav { display: flex; gap: var(--space-l); }
.legalbar a { color: var(--secondary); text-decoration: none; }
.legalbar a:hover, .legalbar a:focus-visible { color: var(--primary); text-decoration: none; }

/* ---------------------------------------------------------------------------
 * ENTRANCE REVEALS — one-way, IntersectionObserver, short directional travel.
 * NOT the template's scroll-linked .reveal, which plays backwards on scroll-up.
 * ------------------------------------------------------------------------ */
[data-reveal] {
    opacity: 0;
    transition: opacity 760ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 760ms cubic-bezier(0.22, 1, 0.36, 1);
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}
[data-reveal="up"]    { transform: translateY(26px); }
[data-reveal="down"]  { transform: translateY(-26px); }
[data-reveal="left"]  { transform: translateX(-18px); }
[data-reveal="right"] { transform: translateX(18px); }
[data-reveal="fade"]  { transform: none; }
[data-reveal][data-revealed] { opacity: 1; transform: none; }

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

/* ---------------------------------------------------------------------------
 * RESPONSIVE. Live switches to a distinct tablet layout at 1024 and a phone
 * layout at 767 — reproduced from measurements at those widths, not scaled.
 * ------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------
 * RESPONSIVE. Live switches layout at Elementor's own breakpoints (1024 and
 * 767) and gives each arch a DIFFERENT measured height at each — the boxes
 * shrink while the px radii stay put, which is exactly why the arches change
 * character. Every height below was measured on live at that width.
 *
 *   arch                    1440      1024       390
 *   hero photo           550x550   800x800   350x350
 *   why photo            455x628   984x613   350x432
 *   about card           630x679   944x413   350x476
 *   about photo          630x325   944x314   350x631  <- radius 100 -> 500
 *   guides photo         642x596   984x400   390x250
 *   cta photo            645x756   784x919   350x410
 *   cta panel            645x907   864x1039  350x1296
 * ------------------------------------------------------------------------ */
@media (max-width: 1024px) {
    /* Live collapses the nav to a burger at <=1024, not at the phone
     * breakpoint — measured: nav hidden and burger shown at 768/860/900/
     * 1000/1024, nav shown at 1025. Collapsing at 767 instead left the
     * header CTA running up to 172px off-page across 768-985. */
    .navbar__inner { flex-wrap: wrap; }
    .nav { display: none; width: 100%; }
    .nav[data-open="true"] { display: block; }
    .nav > ul { flex-direction: column; gap: 0; }
    .nav__sub { position: static; display: none; box-shadow: none; min-width: 0; }
    .nav__sub[data-open="true"] { display: block; }
    .nav-menu-btn {
        display: inline-flex; order: 1; margin-left: 0;
        background: var(--ground-deep); border-radius: var(--radius-pill);
        padding: var(--space-2xs) var(--space-s);
    }
    .nav-cta { order: 2; }
    /* The open menu wraps to its own full-width row BELOW the button and CTA.
       Before this the button carried the auto margin and the CTA sat beside
       it; opening the menu pushed the CTA to a third row and the button slid
       to the right edge. */
    .nav { order: 3; }

    .hero__inner { grid-template-columns: 1fr; }
    .hero__media { padding-top: 0; }
    .hero__copy { padding-top: var(--space-inset-xl); }   /* tablet lead-in */
    .svc-grid { grid-template-columns: 1fr; }
    .svc-wide { grid-template-columns: 1fr; }
    .site-footer__grid { grid-template-columns: 1fr 1fr; }
    .tiles__inner { grid-template-columns: 1fr 1fr; }

    .why__inner, .about__inner { grid-template-columns: 1fr; }
    /* live at 1024: the why media drops BELOW its cards (order swap) */
    .why__media { height: 38.3125rem; order: 2; }   /* 613px measured @1024 */
    .why .band__inner { padding-block: var(--space-inset-l) var(--space-l); }   /* live: 80/40 */
    .about .band__inner { padding-block: var(--space-l) var(--space-inset-l); } /* live: 40/80 */
    .about__card { min-height: 25.8125rem; padding: var(--space-lead) 0 var(--space-xl); text-align: center; }  /* live 100/0/60 */
    .about__photo { min-height: 19.625rem; }   /* 314px */
    .tile { padding: var(--space-inset-m); border-bottom: var(--border-thin) solid var(--tertiary); }   /* 50px, and live adds the horizontal rule in the 2-col grid */

    .guides__media {
        flex: none; width: 96.09%; height: 25rem;  /* 984x400 measured @1024 */
        margin-block: var(--space-lead);
    }
    .guides__body > p, .guides__grid { max-width: none; }

    /* live at 1024 keeps the CTA photo BELOW the panel and pulls it up 150px
     * (not the desktop 300) — measured. */
    .cta__row { flex-direction: column; }
    .cta__media { margin-top: calc(-2.5 * var(--space-xl)); }      /* -150px measured @1024 */
    .cta__panel {
        min-height: 64.9375rem;                /* 1039px measured @1024 */
        padding: var(--space-inset-xl) var(--space-inset-xl) calc(2 * var(--space-lead));
    }
    .cta__inner { padding-block: var(--space-l) var(--space-inset-l); }   /* live: 40/80 */

    .quote__inner { min-height: 25.6875rem; }   /* 411px measured @1024 */

    /* live at 1024 puts the guides photo BELOW its copy — measured (photo
     * y=11560 against copy y=10950). */
    .guides { flex-direction: column-reverse; }
    .guides__body { padding: 0 var(--space-l) var(--space-inset-l) var(--space-inset-xl); gap: var(--space-l); }  /* live 0/40/80/90 */
}

@media (max-width: 900px) {
    .quote__inner { grid-template-columns: 1fr; min-height: 0; }
    .quote__card { padding: var(--space-l); }
}

/* ---------------------------------------------------------------------------
 * HEADER FOLD — three header layouts and the two widths that switch them,
 * both measured (2026-10-05) from the bar's intrinsic widths: logo 195,
 * contact (phone and email side by side) 371, hours 197, search 345, gaps
 * --space-m (~28).
 *
 *   wide    >= 1280   logo | phone, email | hours | search, one row. Needs
 *                     ~1199px of shell and first fits at 1272; 1280 leaves a
 *                     few px for font rendering. (The old flex-wrap bar
 *                     dropped its search to a second row below 1280 too.)
 *   folded  1025-1279 logo centred on its own row; beneath it contact,
 *                     hours and search, space-around and centred as a group.
 *                     The row holds a full --space-m between columns down to
 *                     1059; from 1058 to 1025 it still fits, the space-around
 *                     share shrinking to ~17px between columns at 1025. It
 *                     would only overflow below ~975, inside the phone range.
 *   phone   <= 1024   logo + search trigger; Menu and Book Appointment.
 *                     1024 is where the nav already collapses to Menu (live
 *                     did the same), and the header's desktop and phone
 *                     layouts — menu, booking and search — swap at ONE width.
 *
 * The desktop box and the phone trigger therefore swap at 1024/1025: no width
 * shows both, none shows neither.
 * ------------------------------------------------------------------------ */
@media (min-width: 1025px) and (max-width: 1279px) {
    .topbar__inner { flex-direction: column; justify-content: center; gap: var(--space-xs); min-height: 0; padding-block: var(--space-s); }
    .topbar__meta { margin-left: 0; width: 100%; justify-content: space-around; }
}
/* The nav row cramps at the narrow end of the fold: at --space-l it wrapped
   "Patient Information" and "Health Info" to two lines from 1094 down
   (measured). --space-s-m holds every label on one line at 1025. */
@media (min-width: 1025px) and (max-width: 1099px) {
    .nav > ul { gap: var(--space-s-m); }
}
@media (max-width: 1024px) {
    /* Owner, 2026-09-30: on a phone the header is the logo, the Menu button
       and Book Appointment, centred — now from the menu's own breakpoint, so
       the whole header swaps at one width. The contact rows are hidden; the
       footer carries the same phone, email and hours. Search is the overlay,
       opened from the magnifier on the logo row — never inside the menu, and
       not beside Menu either: a 44px button there wraps Book Appointment to
       a second row at 390. */
    .topbar__inner {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        align-items: center;
        gap: var(--space-xs);
        min-height: 0;
        padding-block: var(--space-s);
    }
    .site-logo { grid-column: 2; padding: 0; }
    .topbar__search-open { display: inline-flex; grid-column: 3; justify-self: end; }
    .topbar__meta { display: none; }
    .navbar__inner { justify-content: center; gap: var(--space-s); }
    .nav-cta { margin-left: 0; }
    /* The buttons must not move when the menu opens (owner, 2026-10-05).
       With a min-height and align-items: center, the closed bar's one flex
       line filled the 79px and centred the 44px buttons; the open menu wraps
       to a second line, the bar outgrows its min-height, the first line
       shrinks to 44 and the buttons rose 5.5px (390) / 3.7px (1024). Padding
       the bar to the same 79px instead puts them at one place in both states. */
    .navbar__inner { min-height: 0; padding-block: calc((var(--navbar-h) - var(--target-min)) / 2); }
    /* Menu and Book Appointment share one box: the touch-target height, the
       same padding, no border. Menu's 24px glyph made it 40 tall against
       Book's 37 (measured at 390). */
    .nav-menu-btn, .nav-cta {
        box-sizing: border-box;
        min-height: var(--target-min);
        padding: 0 var(--space-s);
        border: 0;
        align-items: center;
    }
    .nav > ul { align-items: center; text-align: center; }
    .nav__sub { padding-left: 0; }
    .nav__sub a, .nav a, .nav__toggle { justify-content: center; }
}

@media (max-width: 767px) {
    .tiles__inner { grid-template-columns: 1fr; }
    .tile { padding: var(--space-inset-m) var(--space-m); border-right-width: 0; }   /* live 50/30 @390; stacked, so only the horizontal rule remains */
    .why__cards, .about__facts, .guides__grid { grid-template-columns: 1fr; }
    .site-footer__grid { grid-template-columns: 1fr; }
    .legalbar__inner { justify-content: flex-start; }

    .hero__title { font-size: var(--step-6); }   /* live drops 3.5rem -> 3rem here */
    /* live pads the hero 60px top only at 390, not the desktop 116px lead-in */
    .hero__copy { padding-top: 0; gap: var(--space-m); }   /* live gaps 30px @390 */
    .hero .band__inner { padding-block: var(--space-xl) 0; }
    .hero__inner { gap: var(--space-inset-m) 0; }   /* 50px measured @390 */
    .hero__copy p { margin-bottom: var(--space-2xs); }
    /* live gaps these 50px minus Elementor's negative widget margins; the
       rendered step is ~20px, so state that rather than the arithmetic */

    /* live keeps the guides photo BELOW the copy at 390 as well */
    .guides { flex-direction: column-reverse; }
    .why__media { height: 27rem; }               /* 432px measured @390 */
    .about__card { min-height: 29.75rem; padding: var(--space-inset-l) var(--space-s) var(--space-l); gap: var(--space-m); }  /* live 80/20/40 @390 */

    /* THE ONE GENUINE BREAKPOINT OVERRIDE ON THIS SITE. Live changes the about
     * photo's radius from 100px to 500px at the phone breakpoint — verified at
     * 390 (350x631, radius 500px 500px 15px 15px). It is a real override, not a
     * reflow; copying the desktop value here would be wrong. */
    .about__photo { border-radius: 500px 500px 15px 15px; min-height: 39.4375rem; }  /* 631px */

    .guides__media { width: 100%; height: 15.625rem; margin-block: 0; }   /* 390x250 measured @390 */
    /* live pads 60/20 and gaps its head blocks 50px MINUS Elementor's negative
       widget margins (-2/-30, -7, -20); the rendered step is ~20px, so state
       that rather than reproducing the arithmetic */
    .guides__body { padding: var(--space-xl) var(--space-s); gap: var(--space-s); }
    .guides__grid { gap: var(--space-inset-m); padding-top: var(--space-2xs); }
    .quote__inner { min-height: 21.3125rem; padding-block: var(--space-l); }   /* 341px measured @390; live pads 40/0 but the plated card needs a foot */
    /* Live sets the quote copy straight onto the photo at phone widths, where
       the column is the whole viewport and the text lands on the faces. Ours
       plates it — a deliberate legibility improvement on live, 2026-09-30. */
    .quote__card {
        background: color-mix(in srgb, var(--bg) 92%, transparent);
        border-radius: 15px;
        padding: var(--space-m) var(--space-s);
    }
    .cta__panel { min-height: 0; padding: var(--space-xl) var(--space-s) var(--space-lead); }  /* live 60/20/100 @390; live's 1296 min-height left a blank arch under the codes */
    .cta__app { grid-template-columns: 1fr; }
    /* both codes side by side, centred, instead of a 178px card hugging the right edge */
    .cta__qr { width: auto; justify-self: stretch; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); justify-items: center; }
    .qr-panel img { max-width: 100%; height: auto; }   /* 128px codes held the panel at 336 on a 320 phone */
    .cta__qr img { width: 8rem; height: 8rem; }
    /* the photo rode 150px up into a panel that no longer carries live's blank
       arch, covering the QR captions; it now rides only into the panel's padding */
    .cta__media { margin-top: calc(-1 * var(--space-xl)); }
}



/* ===========================================================================
 * PHASE 2 — the fourteen inner pages
 *
 * The same measured design language as the homepage. Components here recur
 * across several pages, so each is defined once: the two-column hero, the
 * eyebrow/title/lede band head, the bordered card grid, the prose list and
 * the contact panel. Every value measured off live at 1440/1024/390.
 * ======================================================================== */

/* --- Inner-page hero: copy beside an arched photo -------------------------
 * Live's column split varies by page and is transcribed per page as a ratio
 * (not a px track — a px track cannot shrink, which is what breaks these
 * layouts between roughly 1000 and 1300). The 100px gap is constant. */
.phero__inner {
    display: grid;
    grid-template-columns: var(--phero-cols, 1fr 1fr);
    gap: var(--space-lead);              /* 100px measured on every page */
    align-items: center;
}
.phero__copy { display: flex; flex-direction: column; gap: var(--space-panel-gap); }
.phero__copy p { margin: 0; }
.phero__title {
    font-family: var(--font-head);
    font-weight: var(--weight-700);
    color: var(--primary);            /* rgb(61,107,193) measured on live */
    font-size: var(--step-7);
    line-height: var(--leading-s);
    margin: 0;
}
.phero__title--sm { font-size: var(--step-5); }
.phero__media img,
.phero__media {
    display: block; width: 100%; height: auto;
    border-radius: var(--phero-radius, 350px 350px 15px 15px);
}

/* --- Band head: eyebrow + title + optional lede --------------------------
 * Live's eyebrow carries Elementor's -2px/-25px collapse, so the rendered
 * step to the title is far tighter than the nominal 35px gap. */
.bandhead { display: flex; flex-direction: column; padding-bottom: var(--space-block); }
.bandhead .eyebrow { margin: 0 0 var(--space-3xs); line-height: var(--leading-l); }
.bandhead h2:not(.eyebrow) { font-size: var(--step-5); line-height: var(--leading-s); margin: 0; }
.bandhead p { margin: var(--space-s) 0 0; max-width: 48rem; }
.bandhead--center { text-align: center; align-items: center; }
.bandhead--center p { margin-inline: auto; }

/* --- Bordered card grid (About's doctors, the policy cards, careers) -----
 * 376px cards at 1440 in a 1290 shell with an 80px gap; 40px padding, 15px
 * radius, 1px border. Stated as fr so both tracks shrink together. */
.cardgrid {
    display: grid;
    grid-template-columns: repeat(var(--cardgrid-cols, 3), minmax(0, 1fr));
    gap: var(--space-inset-l) var(--space-card-gap);     /* 80px row gap measured */
}
.pcard {
    border: var(--border-thin) solid var(--tertiary);
    border-radius: var(--radius-s);
    padding: var(--space-l);
    display: flex; flex-direction: column; gap: var(--space-2xs);
}
.pcard h3 { font-size: var(--step-1); margin: 0 0 var(--space-2xs); }
.pcard p { margin: 0; }
.pcard--filled { background: var(--ground-deep); border-color: transparent; }
.pcard svg { width: 2.8125rem; height: 2.8125rem; fill: var(--tertiary); }

/* --- Split band: copy one side, arched photo the other ------------------- */
.split { display: grid; grid-template-columns: var(--split-cols, 1fr 1fr); gap: var(--space-inset-xl); align-items: center; }
/* Grid children default to min-width:auto and refuse to shrink below their
   content, which pushed a column 5px past a 360px viewport. */
.split > * { min-width: 0; }
.phero__inner > * { min-width: 0; }
.cardgrid > * { min-width: 0; }
.split__media {
    background-size: cover; background-position: center;
    border-radius: var(--split-radius, 350px 350px 15px 15px);
}
/* Only a CSS-background split needs a height floor -- one wrapping an <img>
   takes the photo's own aspect, which is what live draws. A blanket
   min-height forced every arch to at least 480px. */
.split__media:not(:has(img)) { min-height: var(--split-h, 30rem); }
.split__media img { display: block; width: 100%; height: auto; border-radius: inherit; }

/* --- Prose list: live's tick/label rows in the policy and fees pages ----- */
.prose h2 { font-size: var(--step-2); margin: var(--space-xl) 0 var(--space-s); }
.prose h3 { font-size: var(--step-1); margin: var(--space-l) 0 var(--space-2xs); }
.prose p, .prose li { margin: 0 0 var(--space-s); }
.prose ul, .prose ol { margin: 0 0 var(--space-m); padding-left: var(--space-m); }
.prose > :first-child { margin-top: 0; }

/* --- Forms --------------------------------------------------------------- */
.form-grid { display: grid; gap: var(--space-s); }
.form-row { display: grid; gap: var(--space-3xs); }
.form-row label { font-family: var(--font-head); font-weight: var(--weight-700); font-size: var(--step--1); }
.form-row input, .form-row textarea, .form-row select { width: 100%; }

@media (max-width: 1024px) {
    .phero__inner { grid-template-columns: 1fr; gap: var(--space-inset-xl); }
    .split { grid-template-columns: 1fr; }
    .cardgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-inset-xl) var(--space-card-gap); }
}
@media (max-width: 767px) {
    .phero__inner { gap: var(--space-xl); }
    .cardgrid { grid-template-columns: 1fr; }
    .bandhead { padding-bottom: var(--space-xl); }
}

/* ---------- Phase 2: inner-page components ---------- */

/* Band rhythm variants. Live steps its band padding per page; --tight is the
   half-band that follows a hero, --deep the deeper cream ground. */
.band--deep  { background: var(--ground-deep); }

/* Ticked lists. Measured on /home-medicine-review/: 15px gold glyph,
   3.75px + 5px between glyph and text, 4px between rows, body at --step-0. */
.tick-list {
    list-style: none;
    margin: 0;                 /* live gives the list no top margin */
    padding: 0;
}
.tick-list li {
    display: flex;
    align-items: flex-start;
    padding-bottom: var(--space-3xs);   /* 4px, measured on live */
    line-height: var(--leading-l);
}
.tick-list li svg {
    flex: 0 0 auto;
    width: 0.9375rem;
    height: 0.9375rem;
    margin-right: var(--space-tick-gap);
    margin-top: var(--space-3xs);   /* live 0.28em: centres the glyph on the first line */
    fill: var(--tertiary);
}
.tick-list li > span { padding-left: var(--space-tick-pad); }
.tick-list__title {
    margin-top: var(--space-l);
    margin-bottom: var(--space-2xs);
    font-size: var(--step-1);
}

/* Practice hours. Live uses Elementor's price-list header: flex, space-between,
   --step-1, label 700 / value 600. The rows are Rails' {{opening_hours_html}}
   table (one <tr> per day group), set as flex rows rather than a table. */
.hours { margin: var(--space-m) 0; }
.hours .hours-table, .hours .hours-table tbody { display: block; margin: 0; }
.hours tr {
    display: flex;
    justify-content: space-between;
    gap: var(--space-m);
    font-size: var(--step-1);
    padding-block: var(--space-3xs);
}
.hours td { padding: 0; border: 0; }
.hours td:first-child { font-weight: var(--weight-700); }
.hours td:last-child { font-weight: var(--weight-600); }

/* The same table as plain "Day: time" lines — header bar, footer and the
   homepage's hours card, where live sets the hours as lines of text. */
.hours-lines .hours-table { width: auto; margin: 0; }
.hours-lines .hours-table tr { display: block; }
.hours-lines .hours-table td { display: inline; padding: 0; border: 0; }
.hours-lines .hours-table td:first-child::after { content: ": "; }
.fact .hours-lines { font-weight: var(--weight-500); }

/* Practitioner cards on /about/ render from Rails, where a line break inside
   qualifications or bio is stored as a newline. */
.doctor-card p { white-space: pre-line; }

/* The "what to bring" row on /appointment/ — four 45px glyphs in a row. */
.bring {
    list-style: none;
    margin: var(--space-l) 0 var(--space-inset-xl);
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-l);
    text-align: center;
}
.bring li {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2xs);
    font-size: var(--step-1);
    font-weight: var(--weight-500);
}
.bring li svg { width: 2.8125rem; height: 2.8125rem; fill: var(--primary); }

/* A row of buttons (the /appointment/ hero runs two side by side). */
.btn-row { display: flex; flex-wrap: wrap; align-items: center; }
.btn-pill--ghost {
    background: transparent;
    color: var(--secondary);
    box-shadow: inset 0 0 0 var(--border-thin) var(--secondary);
}
.btn-pill--ghost:hover, .btn-pill--ghost:focus-visible {
    background: var(--primary);
    color: var(--on-navy);
}
/* Outlined in gold, fills gold on hover — the one button that does not hover
   blue, by the owner's request for the appointment hero's Fees and Billing
   button (2026-09-30). */
.btn-pill--outline { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 2px var(--tertiary); }
.btn-pill--outline:hover, .btn-pill--outline:focus-visible { background: var(--tertiary); color: var(--ink); }

/* /health-info/ leads with copy only — no hero photo beside it; its photo
   row (.phero__photos) sits below the copy. */
.phero--plain .band__inner { max-width: var(--shell); }
.phero--plain .bandhead { max-width: 46rem; }

@media (max-width: 1024px) {
    .bring { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 767px) {
    .bring { grid-template-columns: 1fr; gap: var(--space-m); text-align: left; }
    .bring li { flex-direction: row; align-items: center; gap: var(--space-s); }
    .hours tr { font-size: var(--step-0); }
}

/* Bands carrying an arched photo run on live's WIDER row (1350, not 1290).
   Measured: /health-assessment/ hero col 543 inside a 1350 row; /careers/ 595
   inside 1290. Without this every arch came out ~4.4% short. */
.phero .band__inner,
.band__inner:has(> .split) { max-width: var(--shell-wide); }

/* Groups that sit INSIDE a copy column beside a photo. Live draws these as
   bare text blocks -- no padding, no radius, no plate (measured 218px tall
   against our 351px card). See /health-assessment/ bands 2 and 3. */
.pcard--plain {
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    gap: var(--space-2xs);
}
/* Live's group heading carries no bottom margin -- the gap does that work. */
.pcard--plain > h2, .pcard--plain > h3, .pcard--plain > h4 { margin-bottom: 0; }
/* ...and the grid holding them uses live's own 20px row gap, not the 80px
   the between-band card rows use. */
.cardgrid:has(> .pcard--plain) { gap: var(--space-icon-gap); }

/* A centred hero with a glyph and no photo -- live uses this on
   /practice-policy/ (measured: 760px column, 45px icon, band 1038px). */
.centre-hero {
    max-width: 47.5rem;          /* 760px measured */
    margin-inline: auto;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-m);
}
.centre-hero > svg { width: 2.8125rem; height: 2.8125rem; fill: var(--tertiary); }
.centre-hero p { margin: 0; }

/* The narrow 258px "WHAT TO BRING" column on /appointment/ -- live stacks its
   four glyph rows vertically rather than spreading them across the band. */
.bring--stack { grid-template-columns: 1fr; gap: var(--space-l); }

/* Live flows some card sets down each column independently rather than in a
   uniform grid -- measured on /appointment/ band 3: a 630/630 pair with two
   cards in the left column and three in the right, 30px apart. A uniform grid
   makes every row as tall as its tallest card and ran that band 378px long. */
/* ---------- /about/ — owner review round 2 (2026-09-28) ----------
 * Measured on live at 2223: the hero copy is a 2x2 paragraph grid (371/371,
 * 50px gap, 35px above, 14px between paragraphs); the "why" band is four
 * 308px page-cream cards 20px apart, centred; the doctors grid uses an 80px
 * column gap with centred cards; the safety band is three equal 403px
 * columns on the 1350 row, 70px apart, with a hairline-divided list. */
.phero__grid {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--space-inset-m);           /* 50px */
    padding-top: var(--space-panel-gap); /* 35px */
}
.phero__grid p + p { margin-top: var(--space-xs); }   /* live 14px */
.cardgrid--tight { gap: var(--space-s); }      /* 20px */
.cardgrid--wide  { column-gap: var(--space-inset-l); }          /* 80px */
.pcard--light { background: var(--bg); border-color: transparent; padding: var(--space-inset-m); }
.pcard--centre { text-align: center; align-items: center; gap: var(--space-s); }
.pcard--centre h3 { margin-bottom: 0; }
.trio {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-block);             /* 70px */
    align-items: start;
}
.trio__copy .bandhead { padding-bottom: var(--space-panel-gap); }
.trio__copy > p { margin: 0; }
.trio__media img {
    display: block; width: 100%; height: auto;
    aspect-ratio: 403 / 605; object-fit: cover; object-position: 50% 0;   /* heads sit at the top of these portraits */
    border-radius: 200px 200px 20px 20px;
}
.rule-list { padding-top: var(--space-l); }
.rule-list h3 { font-size: var(--step-1); margin: 0 0 var(--space-2xs); }
.rule-list p { margin: 0; }
.rule-list > div + div {
    margin-top: var(--space-panel-gap); padding-top: var(--space-panel-gap);
    border-top: var(--border-thin) solid var(--tertiary);
}
@media (max-width: 1024px) {
    .trio { grid-template-columns: 1fr; }
    .trio__media img { aspect-ratio: auto; border-radius: 200px 200px 15px 15px; }
    .cardgrid--wide { column-gap: var(--space-card-gap); }
}
@media (max-width: 767px) {
    .phero__grid { grid-template-columns: 1fr; gap: var(--space-xs); }
}

/* ---------- /appointment/ — owner review round 2 (2026-09-28) ----------
 * Measured on live at 2223. */
.btn-row { gap: var(--space-m); }
.band--after-hero { padding-top: 0; }        /* live's row sits 80px under the hero photo */
.pcard h2 { font-size: var(--step-1); margin: 0 0 var(--space-2xs); }
.pcard--roomy { padding: var(--space-inset-m); gap: var(--space-s); }
.split--hours { gap: var(--space-m); align-items: stretch; }
.split--hours .split__media img { height: 100%; object-fit: cover; object-position: 50% 30%; }
.hours-card {
    background: var(--ground-deep); border-radius: 10px;
    padding: var(--space-inset-m);
    display: flex; flex-direction: column; gap: var(--space-panel-gap);
}
.hours-card h2 { font-size: var(--step-4); margin: 0; }       /* 32px measured */
.hours-card p { margin: 0; }
.hours-card .hours { margin: 0; }
.hours-card .hours tr { align-items: center; gap: var(--space-2xs); }
.hours-card .hours tr::after {                    /* live's price-list leader line */
    content: ""; flex: 1; order: 1;
    border-bottom: var(--border-thin) solid var(--primary);
}
.hours-card .hours td:last-child { order: 2; }
.dot-list { list-style: disc; margin: 0; padding-left: var(--space-s); }
.dot-list li { padding-bottom: var(--space-3xs); padding-left: var(--space-tick-pad); }
.dot-list li::marker { color: var(--tertiary); }
/* Live's chronic-conditions list: 9px rows (10px here, on the ladder) with a hairline between each */
.dot-list--rows li { padding-block: var(--space-2xs); border-bottom: var(--border-thin) solid var(--tertiary); }
.dot-list--rows li:last-child { border-bottom: 0; }
/* Two of live's lists use a pale blue glyph (rgb 168,197,218) rather than gold */
.tick-list--pale li svg { fill: var(--tick-pale); }
.dot-list--pale li::marker { color: var(--tick-pale); }
/* Live's plain browser discs (the HMR questions and "No cost" list) */
.disc-list { list-style: disc; margin: 0; padding-left: var(--space-s); }
.disc-list li { padding-bottom: var(--space-3xs); padding-left: var(--space-tick-pad); }
/* A button that follows a list or paragraph: live leaves ~57px above it */
.btn-row--lead { margin-top: var(--space-panel-gap); }
.colpair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-card-gap); align-items: start; }
.colpair__col { display: flex; flex-direction: column; gap: var(--space-card-gap); }
.newpat {
    display: grid; grid-template-columns: 2fr 2fr 1fr;   /* 516 / 516 / 258 */
    gap: var(--space-m);
}
.newpat__card {
    background: var(--bg); border-radius: var(--radius-s);
    padding: var(--space-block);                         /* 70px measured */
    display: flex; flex-direction: column; gap: var(--space-panel-gap);
}
.newpat__card h2 { font-size: var(--step-6); margin: 0; }
.newpat__card h3 { font-size: var(--step-1); margin: 0; }
.newpat__card p { margin: 0; }
.newpat__media img {
    display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0;
    border-radius: 350px 350px 15px 15px;
}
.bring-panel {
    border: 2px solid var(--tertiary); border-radius: 150px 150px 10px 10px;
    padding: var(--space-block) var(--space-s) var(--space-panel-gap);   /* live 75 / 20 / 35 */
    text-align: center;
}
.bring-panel h2 { font-size: var(--step-1); color: var(--secondary); margin: 0 0 var(--space-panel-gap); }
.bring-panel .bring { margin: 0; gap: 0; }
.bring-panel .bring li { gap: var(--space-xs); padding-block: var(--space-s); font-size: var(--step-1); }
.bring-panel .bring li + li { border-top: var(--border-thin) solid var(--tertiary); }
.bring-panel .bring li svg { fill: var(--tertiary); }
@media (max-width: 1024px) {
    .colpair, .newpat { grid-template-columns: 1fr; }
    .newpat__media img { height: auto; }
    .newpat__card { padding: var(--space-inset-m); }
}

/* ---------- /sample-page/ (Contact) — owner review round 2 (2026-09-28) ----------
 * Measured on live at 2223: deep-cream borderless fields (40px, radius 3,
 * 15px type), a full-width 47px gold rectangular submit, a 15px-inset notice
 * box in the brown rgb(138,109,59); the clinic band is 645/645 with the map
 * in the right column. */
.form-grid--live .form-row label { font-size: var(--step-0); color: var(--ink); }
.form-grid--live .req { color: var(--required); }
.form-grid--live p { margin: 0; }

/* Text controls: one shape for every field (header search, the phone
 * overlay's box, the contact form) now lives in Form controls, set by the
 * --field-* tokens in :root. Focus there is ONE ring in --focus-ring, a dark
 * amber off the brand gold (owner, 2026-10-05: no ink edge; brand gold itself
 * is only ~1.3-1.5:1 on the creams). */
.form-notice {
    background: var(--ground-deep); color: var(--notice-ink);
    padding: var(--space-xs); border-radius: 3px;
}
.form-notice strong { display: block; margin-bottom: var(--space-3xs); }
.form-notice p { font-size: var(--step--1); line-height: var(--leading-xl); margin: 0; }
.clinic { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
.clinic__copy { padding-right: var(--space-lead); display: flex; flex-direction: column; gap: var(--space-inset-m); }
.clinic__copy .bandhead { padding-bottom: 0; }
.clinic__cards {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-s);
    padding-top: var(--space-inset-m);
    border-top: var(--border-thin) solid var(--tertiary);
}
.clinic__card { background: var(--ground-deep); border-radius: 3px; padding: var(--space-s); }
.clinic__card h3 { font-size: var(--step-1); color: var(--secondary); margin: 0 0 var(--space-2xs); }
.clinic__card p { margin: 0; font-size: var(--step--1); }
.clinic__card a { color: var(--ink); text-decoration: none; }
.clinic__card a:hover { text-decoration: underline; }
.clinic__copy .contact-note { margin: 0; }
.clinic__map { border-radius: 10px 10px 300px 300px; overflow: hidden; min-height: 30rem; }   /* live: an inverted arch, measured */
.clinic__map iframe { display: block; width: 100%; height: 100%; min-height: 30rem; border: 0; }
@media (max-width: 1024px) {
    .clinic { grid-template-columns: 1fr; gap: var(--space-xl); }
    .clinic__copy { padding-right: 0; }
    .clinic__map { border-radius: 10px 10px 150px 150px; }
}
@media (max-width: 480px) {
    .clinic__cards { grid-template-columns: 1fr; }
}

/* ---------- /fees-and-billing/ — owner review round 2 (2026-09-28) ----------
 * Measured on live at 2223. */
.lead-navy { font-family: var(--font-head); font-weight: var(--weight-700); font-size: var(--step-1); color: var(--secondary); margin: 0; }
.phero__prose { display: flex; flex-direction: column; gap: var(--space-s); }
.band--flush { padding-inline: 0; }
.paysplit {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-inset-m);
    align-items: stretch;
}
.paysplit__panel {
    background: var(--ground-deep); border-radius: 0 15px 15px 0;
    padding: var(--space-lead) var(--space-lead) var(--space-lead) max(var(--space-lead), calc((100vw - var(--shell-wide)) / 2 + var(--space-inset-m)));
    display: flex; flex-direction: column; gap: var(--space-panel-gap);
}
.paysplit__panel .bandhead { padding-bottom: 0; }
.paysplit__panel > p { margin: 0; }
.paysplit__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-inset-m); }
.paysplit__media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 25%; border-radius: 15px 0 0 15px; }
.payopt { display: flex; flex-direction: column; align-items: center; }
.payopt__photo { width: 100%; }
.payopt__photo img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 1; object-fit: cover; border-radius: 10px; }
.payopt__card {
    width: min(100%, 59.0625rem);        /* 945px */
    margin-top: calc(-1 * var(--space-inset-l));   /* 80px overlap, measured */
    background: var(--ground-deep); border-radius: var(--radius-s);
    padding: var(--space-l); text-align: center;
    display: flex; flex-direction: column; gap: var(--space-s);
}
.payopt__card .eyebrow { font-size: var(--step-0); }
.payopt__card h3 { font-size: var(--step-4); margin: 0; }
.payopt__card p { margin: 0; }
.payopt__cols {
    width: 100%; margin-top: var(--space-block);   /* 70px */
    display: grid; grid-template-columns: 1fr 1fr; gap: 0;
}
.payopt__col {
    padding-block: var(--space-s) var(--space-l);
    display: flex; flex-direction: column; gap: var(--space-s);
}
/* one gold rule between the pair — the centre divider only, no foot rule (owner, 2026-09-30) */
.payopt__col:first-child { padding-right: var(--space-inset-m); border-right: var(--border-thin) solid var(--tertiary); }
.payopt__col:last-child { padding-left: var(--space-inset-m); }
.payopt__col .eyebrow { font-size: var(--step-0); }
.payopt__col h3 { font-size: var(--step-4); margin: 0; }
.payopt__col h4 { font-size: var(--step-1); margin: var(--space-2xs) 0 0; }
.payopt__col p { margin: 0; }
.afterhours { display: flex; flex-direction: column; gap: var(--space-panel-gap); }
.afterhours h2 { font-size: var(--step-4); margin: 0; }
.afterhours .dot-list { padding-left: var(--space-l); }
.mym { display: grid; grid-template-columns: 850fr 425fr; gap: var(--space-block); align-items: start; }   /* live 850 / 75 / 425 */
.mym__title { font-size: var(--step-7) !important; }
.mym__grid { display: grid; grid-template-columns: 355fr 444fr; gap: var(--space-inset-m); }
.mym__media img { display: block; width: 100%; height: auto; border-radius: 350px 350px 15px 15px; }
.mym__row {
    display: grid; grid-template-columns: 327fr 436fr 436fr; gap: var(--space-block);   /* live 75 */
    margin-top: var(--space-block); align-items: start;
}
.mym__thumb img { display: block; width: 100%; height: auto; border-radius: 10px; }
.chev-list { list-style: none; margin: 0; padding: 0; }
.chev-list li { position: relative; padding-left: var(--space-s); padding-bottom: var(--space-3xs); }
.chev-list li::before { content: "\203A"; position: absolute; left: 0; top: -0.1em; color: var(--tertiary); font-weight: var(--weight-700); font-size: 1.25em; }
@media (max-width: 1024px) {
    .paysplit { grid-template-columns: 1fr; }
    .paysplit__panel { border-radius: 0; padding: var(--space-inset-xl) var(--space-gutter); }
    .paysplit__media img { border-radius: 0; }
    .payopt__cols { grid-template-columns: 1fr; }
    .payopt__col:first-child { padding-right: 0; border-right: 0; }
    .payopt__col:last-child { padding-left: 0; border-top: var(--border-thin) solid var(--tertiary); }   /* the divider turns horizontal when the pair stacks */
    .mym, .mym__row { grid-template-columns: 1fr; }
    .mym__media img { border-radius: 200px 200px 15px 15px; }
}
@media (max-width: 767px) {
    .paysplit__pair, .mym__grid { grid-template-columns: 1fr; }
    .payopt__card { margin-top: var(--space-m); }
}

/* ---------- /privacy-policy/ and /terms-and-conditions/ — owner reference 2026-09-30 ----------
 * Measured on live at 1440 / 1024 / 390: a full-bleed photo 900 tall, then a
 * deep-cream band whose page-cream panel (1290 wide, radius 15, z-index 2)
 * rides 270px up over the photo with a 75px inset each side — it floats
 * between the two bands, never on the edge. Padding 100 / 70 / 50x30.
 * Title 3rem brand blue; section headings 2.5rem, navy at the owner's
 * request (live has them in rgb(51,51,51)). */
.lhero { height: 56.25rem; background-image: var(--lhero-photo); background-size: cover; background-position: center; }
.lband { background: var(--ground-deep); padding: 0 var(--space-gutter) var(--space-band); display: flow-root; }
/* flow-root matters: without it the panel's negative top margin collapsed
   THROUGH the band, so the deep-cream band itself rode up over the photo and
   the panel's top edge landed exactly on the band's — it sat on the seam
   instead of floating across it. Measured: bandTop 851 = panelTop 851. */
.lpanel {
    position: relative; z-index: var(--layer-raised);
    max-width: var(--shell); margin: calc(-3 * var(--space-inset-xl)) auto 0;   /* -270px */
    background: var(--bg); border-radius: 15px;
    padding: var(--space-lead); box-sizing: border-box;    /* 100px */
}
.lpanel h1 { font-size: var(--step-6); line-height: var(--leading-s); color: var(--secondary); margin: 0 0 var(--space-2xs); }   /* owner: title navy, section headings blue */
.prose--legal h2 { font-size: var(--step-5); line-height: var(--leading-s); color: var(--primary); margin: var(--space-2xs) 0 var(--space-xs); }   /* live 8/16 */
.prose--legal h3 { color: var(--primary); }
.prose--legal p, .prose--legal li { margin: 0 0 var(--space-xs); line-height: var(--leading-l); }   /* live 0.9rem of its fluid root = 14.85px @1440 */
.prose--legal .lede { font-size: var(--step-1); color: var(--ink); }   /* the template's mid-grey lede read washed-out on the cream panel (owner) */
@media (max-width: 1024px) {
    .lhero { height: 30.5rem; }                                   /* 488 measured */
    .lpanel { margin-top: calc(-1 * var(--space-lead)); padding: var(--space-block); }          /* -100 / 70 */
}
@media (max-width: 767px) {
    .lhero { height: 24rem; }
    .lpanel { padding: var(--space-inset-m) var(--space-m); }      /* 50 / 30 */
}

/* ---------- Text before picture when sections stack (owner, 2026-09-30) ----------
 * Below 1024 every two-column band is a single column. Where live puts the
 * photo on the LEFT the photo came first in the stack; the owner wants the
 * copy first everywhere on a phone. `order` on the media child only, so the
 * bands where the copy already leads are unchanged. */
@media (max-width: 1024px) {
    .phero__inner > .phero__media { order: 2; }
    .split > .split__media { order: 2; }
    .trio > .trio__media { order: 3; }
    .twoup__col > img { order: 2; }
    .about__side > .about__photo { order: 2; }
    .mym__row > .mym__thumb { order: 3; }
    .payopt > .payopt__card { order: 1; margin-top: 0; }
    .payopt > .payopt__photo { order: 2; margin-top: var(--space-m); }
    .payopt > .payopt__cols { order: 3; }
}

/* ---------- /careers/ — owner review round 2 (2026-09-28) ----------
 * Measured on live at 2223. The badge glyphs reuse the site's own icons where
 * live draws FontAwesome equivalents. */
.badge {
    display: inline-flex; align-items: center; justify-content: center;
    width: 3.125rem; height: 3.125rem; border-radius: var(--radius-round);
    background: var(--tertiary); flex: none;
}
.badge svg { width: 1.375rem; height: 1.375rem; fill: var(--on-tertiary); }
.badge-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-s); padding-top: var(--space-s); }
.badge-item { display: flex; flex-direction: column; gap: var(--space-s); }
.badge-item__label { font-family: var(--font-head); font-weight: var(--weight-700); color: var(--primary); }
.pcard--ink h3 { color: var(--secondary); }
.pcard--light.pcard--ink { padding: var(--space-l); align-items: stretch; text-align: left; }
.split--why { align-items: start; }
.why-copy { display: flex; flex-direction: column; gap: var(--space-panel-gap); }
.why-copy .bandhead { padding-bottom: 0; }
.why-copy > p { margin: 0; }
.split__media--end img { width: 84%; margin-left: auto; }        /* 500 of 595 */
.twoup { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-inset-m); margin-top: var(--space-inset-l); }
.twoup__col { display: flex; flex-direction: column; gap: var(--space-inset-m); }
.twoup__col--offset { padding-top: var(--space-inset-m); }
.twoup img { display: block; width: 100%; height: auto; aspect-ratio: 620 / 426; object-fit: cover; border-radius: var(--radius-s); }
.trio--about { grid-template-columns: 1.07fr 1fr 1fr; gap: var(--space-inset-m) var(--space-xl); }   /* live 64px column gap */
.trio--about .badge { margin-bottom: var(--space-2xs); }
.guides--join .guides__media { flex-basis: 50%; height: 51.875rem; }   /* 1112 x 830 measured */
.join__title { font-size: var(--step-7); }
.dot-list--divided { padding-left: var(--space-s); }
.dot-list--divided li { padding: var(--space-xs) 0;   /* live 12.5px */ border-bottom: var(--border-thin) solid var(--tertiary); }
@media (max-width: 1024px) {
    .twoup, .trio--about { grid-template-columns: 1fr; }
    .twoup__col--offset { padding-top: 0; }
    .split__media--end img { width: 100%; }
    .guides--join .guides__media { height: 25rem; }
}
@media (max-width: 767px) {
    .badge-row { grid-template-columns: 1fr; }
}

/* ---------- Service & policy pages — owner review round 4 (2026-09-28) ----------
 * Shared pieces measured on live at 2223: a 48px section title (--step-6 here, 3rem
 * on live); navy 20px group headings (the .eyebrow rule, on h3); blue 20px
 * sub-heads (.sub); 384/384 grids of bare groups 50px apart beside a photo
 * (.cardgrid--pair); two 675px columns divided by a gold hairline
 * (.ruled-pair); and the homepage's left-bleed .guides band reused for the
 * "Service Limits" / "Reminders" / "Step-by-Step" / "Practice Environment"
 * bands, whose copy column sits at exactly the same 9vw inset on live. */
.title-xl { font-size: var(--step-6); line-height: var(--leading-s); margin: 0; }
.title-l  { font-size: var(--step-5); line-height: var(--leading-s); margin: 0; }
.title-navy { color: var(--secondary); }
.sub { font-family: var(--font-head); font-weight: var(--weight-700); font-size: var(--step-1); color: var(--primary); margin: 0; }
.pcard--plain > h3.eyebrow, .guide > h3.eyebrow { margin-bottom: 0; }
.split--start { align-items: start; }
.split--copy { gap: var(--space-inset-m); align-items: start; margin-top: var(--space-s); }
.split--copy > div > p:first-of-type { margin-top: var(--space-2xs); }   /* live 12px */
.split--copy h2 { font-size: var(--step-2); color: var(--secondary); margin: 0 0 var(--space-2xs); line-height: var(--leading-l); }
.cardgrid.cardgrid--pair { grid-template-columns: 1fr 1fr; gap: var(--space-inset-m); margin-top: var(--space-panel-gap); }
.cardgrid--pair > .pcard--plain > p { margin: 0; }
.ruled-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0; align-items: start; }
.ruled-pair > :first-child { padding-right: var(--space-inset-m); border-right: var(--border-thin) solid var(--tertiary); }
.ruled-pair > :last-child { padding-left: var(--space-inset-m); }
.ruled-pair .pcard--plain > h3:not(.eyebrow):not(.title-l) { font-size: var(--step-1); margin: var(--space-2xs) 0 0; }
.pcard--cream { background: var(--bg); border-color: transparent; padding: var(--space-l); margin-top: var(--space-s); }
.pcard--cream .sub { margin-bottom: var(--space-2xs); }
.num-list { list-style: decimal; margin: 0; padding-left: var(--space-l); }   /* live: decimal, 40px indent */
.num-list li { padding-bottom: var(--space-3xs); }
.wide-photo { margin-top: var(--space-block); }
.wide-photo img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 1; object-fit: cover; border-radius: var(--radius-s); }
.split__media--short img { aspect-ratio: 425 / 398; object-fit: cover; object-position: 50% 30%; }
.guides__body > .guide + .guide { margin-top: var(--space-s); }   /* stacked guides only, never the grid */
/* Stacked guides (/practice-policy/ "Practice Environment") take live's own
   rhythm: 20px between eyebrow, sub-heading, copy and list, 40px between
   groups, list indented 40px — measured at 1440. The grid guides keep the
   homepage's tight eyebrow because that is what live does there. */
.guides__grid .guide > .eyebrow { margin: 0 0 var(--space-2xs); }   /* live: 10-14px to the list or copy, ours had 0 */
.guides__body > .guide { display: flex; flex-direction: column; gap: var(--space-s); }
.guides__body > .guide .eyebrow { margin: 0; }
.guides__body > .guide .dot-list { padding-left: var(--space-l); }
/* The copy column is a flex item and defaults to min-width: auto, so a long
 * ghost-button label or list line would not shrink and pushed the band past
 * the viewport on /chronic-disease-management/. */
.guides__body { min-width: 0; }
.guides__body .btn-pill { white-space: normal; text-align: center; }
.guides__body .guides__grid { max-width: none; }
.guides__body .num-list, .guides__body .dot-list { margin: 0; }
.guide .dot-list { padding-left: var(--space-s); }

/* /services/: centred hero over a 1920px-wide photo arched 110px at the top,
 * a three-part head row, six bordered service cards with gold badges, and a
 * hairline-ruled program list beside a washed-out photo. */
.services-hero { padding-bottom: 0; }
.services-hero .band__inner { padding-bottom: var(--space-inset-xl); }
.services-hero .bandhead p:not(.eyebrow) { max-width: 36rem; }
.services-hero .bandhead .phero__title { font-size: var(--step-7); }
.services-hero__media { max-width: 120rem; margin-inline: auto; padding-inline: var(--space-gutter); }
.services-hero__media img { display: block; width: 100%; height: auto; aspect-ratio: 1920 / 700; object-fit: cover; border-radius: 110px 110px 0 0; }
.svc-head { display: grid; grid-template-columns: 544fr 513fr auto; gap: var(--space-inset-m); align-items: center; margin-bottom: var(--space-xl); }
.svc-head .eyebrow { margin-bottom: var(--space-3xs); }
.svc-head h2 { font-size: var(--step-7); line-height: var(--leading-s); margin: 0; }
.svc-head > p { margin: 0; }
.pcard--svc { border-radius: 10px; padding: var(--space-inset-m); gap: var(--space-s); }
.pcard--svc h3 { font-size: var(--step-2); margin: 0; }
.pcard--svc .badge { margin-bottom: var(--space-2xs); }
.services-programs .bandhead h2 { font-size: var(--step-7); }
.progs-row { display: grid; grid-template-columns: 320fr 960fr; gap: var(--space-block); align-items: stretch; }
.progs-photo img { display: block; width: 100%; height: 100%; object-fit: cover; opacity: 0.18; border-radius: var(--radius-s); }
.progs { border-top: var(--border-thin) solid var(--tertiary); }
.prog {
    display: grid; grid-template-columns: 47fr 379fr 284fr 189fr; gap: var(--space-s);
    align-items: center; padding-block: var(--space-m);
    border-bottom: var(--border-thin) solid var(--tertiary);
}
.prog__n { font-size: var(--step--1); color: var(--ink-grey); }
.prog h3 { font-size: var(--step-2); margin: 0; }
.prog p { margin: 0; }
.btn-pill--sm { padding-block: var(--space-2xs); justify-self: end; }   /* live 12px */
.cta__app--noqr { grid-template-columns: 1fr; }

/* /practice-policy/: the hero is a cream arch panel over a full-bleed photo. */
.phero--policy { background: url('/assets/images/policy-hero.077478e8bd.webp') center / cover no-repeat; }
.phero--policy .band__inner { padding-block: var(--space-band); }
.arch-panel {
    background: var(--bg);
    border-radius: 450px 450px 15px 15px;
    padding: var(--space-arch-lead) var(--space-inset-l) var(--space-inset-l);   /* 220 / 80 / 80 */
}
.arch-panel .phero__title { font-size: var(--step-7); }
.arch-panel > p { max-width: 36rem; }
@media (max-width: 1024px) {
    .cardgrid.cardgrid--pair, .ruled-pair, .progs-row, .svc-head { grid-template-columns: 1fr; }
    .ruled-pair > :first-child { padding-right: 0; border-right: 0; }
    .ruled-pair > :last-child { padding-left: 0; padding-top: var(--space-l); }
    .progs-photo { display: none; }
    .prog { grid-template-columns: auto 1fr; }
    .prog p { grid-column: 2; }
    .btn-pill--sm { grid-column: 2; justify-self: start; }
    .arch-panel { padding: var(--space-arch-lead) var(--space-l) var(--space-xl); border-radius: 250px 250px 15px 15px; }
}
@media (max-width: 480px) {
    .arch-panel { padding: var(--space-arch-lead) var(--space-s) var(--space-l); border-radius: 160px 160px 15px 15px; width: 100%; box-sizing: border-box; }
    .phero--policy .band__inner { padding-inline: 0; }
    .services-hero__media { padding-inline: 0; }
    .services-hero__media img { border-radius: 0; }
}

/* ---------- /health-info/ (live's /health-articles/, renamed) ---------- */

/* Live's hero carries four 300x500 photos at border-radius 200px, and it
   STAGGERS them: photos 1 and 3 sit high, 2 and 4 drop by exactly 80px.
   Measured identical at 1440 and 1024 (tops 611/691 and 812/892). */
.phero__photos {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-card-gap);
    margin-top: var(--space-inset-xl);
    /* the drop is inside the row, so reserve it rather than letting the band grow */
    padding-bottom: var(--space-inset-l);   /* 80px measured */
    justify-items: center;
    align-items: start;
}
.phero__photos img:nth-child(even) { margin-top: var(--space-inset-l); }   /* 80px measured */
.phero__photos img {
    display: block;
    width: 100%;
    max-width: 18.75rem;                 /* 300px measured */
    height: auto;
    aspect-ratio: 300 / 500;
    object-fit: cover;
    border-radius: 200px;                /* measured on live */
}

/* Six trusted resources, static: Ayr is not a Your Health subscriber, so the
   page carries no hub and no copies of Your Health articles (2026-10-04).
   Cards are the site's filled .pcard; the heading IS the link. The grid is
   .cardgrid at three columns, folding to 2x3 at 1024 and one column at 767,
   so six cards never leave an orphan row. */
.resources { --cardgrid-cols: 3; gap: var(--space-card-gap); }
.resources h3 a { color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }
.resources h3 a:hover, .resources h3 a:focus-visible { color: var(--primary); }
.band--deep .centre-hero .btn-row { justify-content: center; }
/* The hero and the resources band share one ground, and the hero's photo row
   already reserves its 80px stagger below the last photo; without this the
   two bands stacked 120 + 80 + 120px of empty cream between them. */
.phero--plain + .band > .band__inner { padding-top: 0; }
/* `.phero .band__inner` (the wide arch row) sits later in the file at equal
   specificity and overrode the plain hero's shell width, so this hero ran
   30px wider each side than the band below it. */
.phero.phero--plain .band__inner { max-width: var(--shell); }

@media (max-width: 1024px) {
    /* live keeps all four in one row at 1024, at 213x356 with the same 80px
       stagger -- the images scale, the rhythm does not change */
    .phero__photos img { max-width: 13.3125rem; }   /* 213px measured @1024 */
}
@media (max-width: 767px) {
    /* At 390 live shows ONLY the first photo and sets display:none on the other
       three columns. Reproduced: a four-across stagger has nowhere to go on a
       phone, and live already decided this. */
    .phero__photos { grid-template-columns: 1fr; padding-bottom: 0; }
    .phero__photos img:nth-child(n + 2) { display: none; }
    .phero__photos img:nth-child(even) { margin-top: 0; }
    .phero__photos img { max-width: 18.75rem; }     /* back to 300px @390 */
}
